OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/isolate.h" | 5 #include "src/isolate.h" |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 | 8 |
9 #include <fstream> // NOLINT(readability/streams) | 9 #include <fstream> // NOLINT(readability/streams) |
10 #include <sstream> | 10 #include <sstream> |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 break; | 349 break; |
350 case SKIP_UNTIL_SEEN: | 350 case SKIP_UNTIL_SEEN: |
351 DCHECK(caller_->IsJSFunction()); | 351 DCHECK(caller_->IsJSFunction()); |
352 skip_next_frame_ = true; | 352 skip_next_frame_ = true; |
353 break; | 353 break; |
354 case SKIP_NONE: | 354 case SKIP_NONE: |
355 skip_next_frame_ = false; | 355 skip_next_frame_ = false; |
356 break; | 356 break; |
357 } | 357 } |
358 encountered_strict_function_ = false; | 358 encountered_strict_function_ = false; |
359 sloppy_frames_ = 0; | |
360 } | 359 } |
361 | 360 |
362 // The stack trace API should not expose receivers and function | 361 // The stack trace API should not expose receivers and function |
363 // objects on frames deeper than the top-most one with a strict mode | 362 // objects on frames deeper than the top-most one with a strict mode |
364 // function. The number of sloppy frames is stored as first element in | 363 // function. |
365 // the result array. | 364 bool IsStrictFrame(JSFunction* fun) { |
366 void CountSloppyFrames(JSFunction* fun) { | |
367 if (!encountered_strict_function_) { | 365 if (!encountered_strict_function_) { |
368 if (is_strict(fun->shared()->language_mode())) { | 366 encountered_strict_function_ = is_strict(fun->shared()->language_mode()); |
369 encountered_strict_function_ = true; | |
370 } else { | |
371 sloppy_frames_++; | |
372 } | |
373 } | 367 } |
| 368 return encountered_strict_function_; |
374 } | 369 } |
375 | 370 |
376 // Determines whether the given stack frame should be displayed in a stack | 371 // Determines whether the given stack frame should be displayed in a stack |
377 // trace. | 372 // trace. |
378 bool IsVisibleInStackTrace(JSFunction* fun) { | 373 bool IsVisibleInStackTrace(JSFunction* fun) { |
379 return ShouldIncludeFrame(fun) && IsNotInNativeScript(fun) && | 374 return ShouldIncludeFrame(fun) && IsNotInNativeScript(fun) && |
380 IsInSameSecurityContext(fun); | 375 IsInSameSecurityContext(fun); |
381 } | 376 } |
382 | 377 |
383 int sloppy_frames() const { return sloppy_frames_; } | |
384 | |
385 private: | 378 private: |
386 // This mechanism excludes a number of uninteresting frames from the stack | 379 // This mechanism excludes a number of uninteresting frames from the stack |
387 // trace. This can be be the first frame (which will be a builtin-exit frame | 380 // trace. This can be be the first frame (which will be a builtin-exit frame |
388 // for the error constructor builtin) or every frame until encountering a | 381 // for the error constructor builtin) or every frame until encountering a |
389 // user-specified function. | 382 // user-specified function. |
390 bool ShouldIncludeFrame(JSFunction* fun) { | 383 bool ShouldIncludeFrame(JSFunction* fun) { |
391 switch (mode_) { | 384 switch (mode_) { |
392 case SKIP_NONE: | 385 case SKIP_NONE: |
393 return true; | 386 return true; |
394 case SKIP_FIRST: | 387 case SKIP_FIRST: |
(...skipping 25 matching lines...) Expand all Loading... |
420 bool IsInSameSecurityContext(JSFunction* fun) { | 413 bool IsInSameSecurityContext(JSFunction* fun) { |
421 return isolate_->context()->HasSameSecurityTokenAs(fun->context()); | 414 return isolate_->context()->HasSameSecurityTokenAs(fun->context()); |
422 } | 415 } |
423 | 416 |
424 Isolate* isolate_; | 417 Isolate* isolate_; |
425 | 418 |
426 const FrameSkipMode mode_; | 419 const FrameSkipMode mode_; |
427 const Handle<Object> caller_; | 420 const Handle<Object> caller_; |
428 bool skip_next_frame_; | 421 bool skip_next_frame_; |
429 | 422 |
430 int sloppy_frames_; | |
431 bool encountered_strict_function_; | 423 bool encountered_strict_function_; |
432 }; | 424 }; |
433 | 425 |
434 namespace { | 426 namespace { |
435 | 427 |
436 // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the | 428 // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the |
437 // receiver in RegExp constructor frames. | 429 // receiver in RegExp constructor frames. |
438 Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) { | 430 Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) { |
439 return (in->IsTheHole(isolate)) | 431 return (in->IsTheHole(isolate)) |
440 ? Handle<Object>::cast(isolate->factory()->undefined_value()) | 432 ? Handle<Object>::cast(isolate->factory()->undefined_value()) |
441 : in; | 433 : in; |
442 } | 434 } |
| 435 |
| 436 bool GetStackTraceLimit(Isolate* isolate, int* result) { |
| 437 Handle<JSObject> error = isolate->error_function(); |
| 438 Handle<String> stackTraceLimit = |
| 439 isolate->factory()->InternalizeUtf8String("stackTraceLimit"); |
| 440 DCHECK(!stackTraceLimit.is_null()); |
| 441 |
| 442 Handle<Object> stack_trace_limit = |
| 443 JSReceiver::GetDataProperty(error, stackTraceLimit); |
| 444 if (!stack_trace_limit->IsNumber()) return false; |
| 445 |
| 446 // Ensure that limit is not negative. |
| 447 *result = Max(FastD2IChecked(stack_trace_limit->Number()), 0); |
| 448 return true; |
443 } | 449 } |
444 | 450 |
| 451 } // namespace |
| 452 |
445 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, | 453 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, |
446 FrameSkipMode mode, | 454 FrameSkipMode mode, |
447 Handle<Object> caller) { | 455 Handle<Object> caller) { |
448 DisallowJavascriptExecution no_js(this); | 456 DisallowJavascriptExecution no_js(this); |
449 | 457 |
450 // Get stack trace limit. | 458 int limit; |
451 Handle<JSObject> error = error_function(); | 459 if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value(); |
452 Handle<String> stackTraceLimit = | |
453 factory()->InternalizeUtf8String("stackTraceLimit"); | |
454 DCHECK(!stackTraceLimit.is_null()); | |
455 Handle<Object> stack_trace_limit = | |
456 JSReceiver::GetDataProperty(error, stackTraceLimit); | |
457 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value(); | |
458 int limit = FastD2IChecked(stack_trace_limit->Number()); | |
459 limit = Max(limit, 0); // Ensure that limit is not negative. | |
460 | 460 |
461 int initial_size = Min(limit, 10); | 461 using ESTF = EncodedStackTraceFrame; |
462 Handle<FixedArray> elements = | 462 int initial_size = Min(limit, 10) * ESTF::kElementsPerFrame; |
463 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); | 463 Handle<FixedArray> elements = factory()->NewFixedArrayWithHoles(initial_size); |
464 | 464 |
| 465 int cursor = 0; |
| 466 int frames_seen = 0; |
465 StackTraceHelper helper(this, mode, caller); | 467 StackTraceHelper helper(this, mode, caller); |
466 | 468 |
467 // First element is reserved to store the number of sloppy frames. | |
468 int cursor = 1; | |
469 int frames_seen = 0; | |
470 for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit; | 469 for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit; |
471 iter.Advance()) { | 470 iter.Advance()) { |
472 StackFrame* frame = iter.frame(); | 471 StackFrame* frame = iter.frame(); |
473 | 472 |
474 switch (frame->type()) { | 473 switch (frame->type()) { |
475 case StackFrame::JAVA_SCRIPT: | 474 case StackFrame::JAVA_SCRIPT: |
476 case StackFrame::OPTIMIZED: | 475 case StackFrame::OPTIMIZED: |
477 case StackFrame::INTERPRETED: | 476 case StackFrame::INTERPRETED: |
478 case StackFrame::BUILTIN: { | 477 case StackFrame::BUILTIN: { |
479 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); | 478 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); |
480 // Set initial size to the maximum inlining level + 1 for the outermost | 479 // Set initial size to the maximum inlining level + 1 for the outermost |
481 // function. | 480 // function. |
482 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 481 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
483 js_frame->Summarize(&frames); | 482 js_frame->Summarize(&frames); |
484 for (int i = frames.length() - 1; i >= 0; i--) { | 483 for (int i = frames.length() - 1; i >= 0; i--) { |
485 Handle<JSFunction> fun = frames[i].function(); | 484 Handle<JSFunction> fun = frames[i].function(); |
486 | 485 |
487 // Filter out internal frames that we do not want to show. | 486 // Filter out internal frames that we do not want to show. |
488 if (!helper.IsVisibleInStackTrace(*fun)) continue; | 487 if (!helper.IsVisibleInStackTrace(*fun)) continue; |
489 helper.CountSloppyFrames(*fun); | |
490 | 488 |
491 Handle<Object> recv = frames[i].receiver(); | 489 Handle<Object> recv = frames[i].receiver(); |
492 Handle<AbstractCode> abstract_code = frames[i].abstract_code(); | 490 Handle<AbstractCode> abstract_code = frames[i].abstract_code(); |
| 491 const int offset = frames[i].code_offset(); |
| 492 |
| 493 bool force_constructor = false; |
493 if (frame->type() == StackFrame::BUILTIN) { | 494 if (frame->type() == StackFrame::BUILTIN) { |
494 // Help CallSite::IsConstructor correctly detect hand-written | 495 // Help CallSite::IsConstructor correctly detect hand-written |
495 // construct stubs. | 496 // construct stubs. |
496 Code* code = Code::cast(*abstract_code); | 497 if (Code::cast(*abstract_code)->is_construct_stub()) { |
497 if (code->is_construct_stub()) { | 498 force_constructor = true; |
498 recv = handle(heap()->call_site_constructor_symbol(), this); | |
499 } | 499 } |
500 } | 500 } |
501 Handle<Smi> offset(Smi::FromInt(frames[i].code_offset()), this); | |
502 | 501 |
503 elements = MaybeGrow(this, elements, cursor, cursor + 4); | 502 int flags = 0; |
| 503 if (helper.IsStrictFrame(*fun)) flags |= StackTraceFrame::kIsStrict; |
| 504 if (force_constructor) flags |= StackTraceFrame::kForceConstructor; |
| 505 |
| 506 elements = MaybeGrow(this, elements, cursor, |
| 507 cursor + ESTF::kElementsPerFrame); |
504 elements->set(cursor++, *TheHoleToUndefined(this, recv)); | 508 elements->set(cursor++, *TheHoleToUndefined(this, recv)); |
505 elements->set(cursor++, *fun); | 509 elements->set(cursor++, *fun); |
506 elements->set(cursor++, *abstract_code); | 510 elements->set(cursor++, *abstract_code); |
507 elements->set(cursor++, *offset); | 511 elements->set(cursor++, Smi::FromInt(offset)); |
| 512 elements->set(cursor++, Smi::FromInt(flags)); |
508 frames_seen++; | 513 frames_seen++; |
509 } | 514 } |
510 } break; | 515 } break; |
511 | 516 |
512 case StackFrame::BUILTIN_EXIT: { | 517 case StackFrame::BUILTIN_EXIT: { |
513 BuiltinExitFrame* exit_frame = BuiltinExitFrame::cast(frame); | 518 BuiltinExitFrame* exit_frame = BuiltinExitFrame::cast(frame); |
514 Handle<JSFunction> fun = handle(exit_frame->function(), this); | 519 Handle<JSFunction> fun = handle(exit_frame->function(), this); |
515 | 520 |
516 // Filter out internal frames that we do not want to show. | 521 // Filter out internal frames that we do not want to show. |
517 if (!helper.IsVisibleInStackTrace(*fun)) continue; | 522 if (!helper.IsVisibleInStackTrace(*fun)) continue; |
518 helper.CountSloppyFrames(*fun); | |
519 | 523 |
| 524 Handle<Object> recv = handle(exit_frame->receiver(), this); |
520 Handle<Code> code = handle(exit_frame->LookupCode(), this); | 525 Handle<Code> code = handle(exit_frame->LookupCode(), this); |
521 int offset = | 526 const int offset = |
522 static_cast<int>(exit_frame->pc() - code->instruction_start()); | 527 static_cast<int>(exit_frame->pc() - code->instruction_start()); |
523 | 528 |
524 // In order to help CallSite::IsConstructor detect builtin constructors, | 529 int flags = 0; |
525 // we reuse the receiver field to pass along a special symbol. | 530 if (helper.IsStrictFrame(*fun)) flags |= StackTraceFrame::kIsStrict; |
526 Handle<Object> recv; | 531 if (exit_frame->IsConstructor()) |
527 if (exit_frame->IsConstructor()) { | 532 flags |= StackTraceFrame::kForceConstructor; |
528 recv = factory()->call_site_constructor_symbol(); | |
529 } else { | |
530 recv = handle(exit_frame->receiver(), this); | |
531 } | |
532 | 533 |
533 elements = MaybeGrow(this, elements, cursor, cursor + 4); | 534 elements = |
| 535 MaybeGrow(this, elements, cursor, cursor + ESTF::kElementsPerFrame); |
534 elements->set(cursor++, *recv); | 536 elements->set(cursor++, *recv); |
535 elements->set(cursor++, *fun); | 537 elements->set(cursor++, *fun); |
536 elements->set(cursor++, *code); | 538 elements->set(cursor++, *code); |
537 elements->set(cursor++, Smi::FromInt(offset)); | 539 elements->set(cursor++, Smi::FromInt(offset)); |
| 540 elements->set(cursor++, Smi::FromInt(flags)); |
538 frames_seen++; | 541 frames_seen++; |
539 } break; | 542 } break; |
540 | 543 |
541 case StackFrame::WASM: { | 544 case StackFrame::WASM: { |
542 WasmFrame* wasm_frame = WasmFrame::cast(frame); | 545 WasmFrame* wasm_frame = WasmFrame::cast(frame); |
543 Code* code = wasm_frame->unchecked_code(); | 546 Code* code = wasm_frame->unchecked_code(); |
544 Handle<AbstractCode> abstract_code = | 547 Handle<AbstractCode> abstract_code = |
545 Handle<AbstractCode>(AbstractCode::cast(code), this); | 548 Handle<AbstractCode>(AbstractCode::cast(code), this); |
546 int offset = | 549 const int offset = |
547 static_cast<int>(wasm_frame->pc() - code->instruction_start()); | 550 static_cast<int>(wasm_frame->pc() - code->instruction_start()); |
548 elements = MaybeGrow(this, elements, cursor, cursor + 4); | 551 |
| 552 // TODO(wasm): The wasm object returned by the WasmFrame should always |
| 553 // be a wasm object. |
| 554 DCHECK(wasm::IsWasmObject(wasm_frame->wasm_obj()) || |
| 555 wasm_frame->wasm_obj()->IsUndefined(this)); |
| 556 |
| 557 elements = |
| 558 MaybeGrow(this, elements, cursor, cursor + ESTF::kElementsPerFrame); |
549 elements->set(cursor++, wasm_frame->wasm_obj()); | 559 elements->set(cursor++, wasm_frame->wasm_obj()); |
550 elements->set(cursor++, Smi::FromInt(wasm_frame->function_index())); | 560 elements->set(cursor++, Smi::FromInt(wasm_frame->function_index())); |
551 elements->set(cursor++, *abstract_code); | 561 elements->set(cursor++, *abstract_code); |
552 elements->set(cursor++, Smi::FromInt(offset)); | 562 elements->set(cursor++, Smi::FromInt(offset)); |
| 563 elements->set(cursor++, Smi::FromInt(StackTraceFrame::kIsWasmFrame)); |
553 frames_seen++; | 564 frames_seen++; |
554 } break; | 565 } break; |
555 | 566 |
556 default: | 567 default: |
557 break; | 568 break; |
558 } | 569 } |
559 } | 570 } |
560 elements->set(0, Smi::FromInt(helper.sloppy_frames())); | 571 |
| 572 DCHECK_EQ(0, cursor % ESTF::kElementsPerFrame); |
561 elements->Shrink(cursor); | 573 elements->Shrink(cursor); |
562 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); | 574 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); |
563 result->set_length(Smi::FromInt(cursor)); | 575 result->set_length(Smi::FromInt(cursor)); |
| 576 |
564 // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. | 577 // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. |
565 return result; | 578 return result; |
566 } | 579 } |
567 | 580 |
568 MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace( | 581 MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace( |
569 Handle<JSReceiver> error_object) { | 582 Handle<JSReceiver> error_object) { |
570 if (capture_stack_trace_for_uncaught_exceptions_) { | 583 if (capture_stack_trace_for_uncaught_exceptions_) { |
571 // Capture stack trace for a detailed exception message. | 584 // Capture stack trace for a detailed exception message. |
572 Handle<Name> key = factory()->detailed_stack_trace_symbol(); | 585 Handle<Name> key = factory()->detailed_stack_trace_symbol(); |
573 Handle<JSArray> stack_trace = CaptureCurrentStackTrace( | 586 Handle<JSArray> stack_trace = CaptureCurrentStackTrace( |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
762 Handle<String> column_key_; | 775 Handle<String> column_key_; |
763 Handle<String> line_key_; | 776 Handle<String> line_key_; |
764 Handle<String> script_id_key_; | 777 Handle<String> script_id_key_; |
765 Handle<String> script_name_key_; | 778 Handle<String> script_name_key_; |
766 Handle<String> script_name_or_source_url_key_; | 779 Handle<String> script_name_or_source_url_key_; |
767 Handle<String> function_key_; | 780 Handle<String> function_key_; |
768 Handle<String> eval_key_; | 781 Handle<String> eval_key_; |
769 Handle<String> constructor_key_; | 782 Handle<String> constructor_key_; |
770 }; | 783 }; |
771 | 784 |
772 | |
773 int PositionFromStackTrace(Handle<FixedArray> elements, int index) { | |
774 DisallowHeapAllocation no_gc; | |
775 Object* maybe_code = elements->get(index + 2); | |
776 if (maybe_code->IsSmi()) { | |
777 return Smi::cast(maybe_code)->value(); | |
778 } else { | |
779 AbstractCode* abstract_code = AbstractCode::cast(maybe_code); | |
780 int code_offset = Smi::cast(elements->get(index + 3))->value(); | |
781 return abstract_code->SourcePosition(code_offset); | |
782 } | |
783 } | |
784 | |
785 Handle<JSArray> Isolate::CaptureCurrentStackTrace( | 785 Handle<JSArray> Isolate::CaptureCurrentStackTrace( |
786 int frame_limit, StackTrace::StackTraceOptions options) { | 786 int frame_limit, StackTrace::StackTraceOptions options) { |
787 DisallowJavascriptExecution no_js(this); | 787 DisallowJavascriptExecution no_js(this); |
788 CaptureStackTraceHelper helper(this, options); | 788 CaptureStackTraceHelper helper(this, options); |
789 | 789 |
790 // Ensure no negative values. | 790 // Ensure no negative values. |
791 int limit = Max(frame_limit, 0); | 791 int limit = Max(frame_limit, 0); |
792 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit); | 792 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit); |
793 Handle<FixedArray> stack_trace_elems( | 793 Handle<FixedArray> stack_trace_elems( |
794 FixedArray::cast(stack_trace->elements()), this); | 794 FixedArray::cast(stack_trace->elements()), this); |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1419 | 1419 |
1420 Object* Isolate::PromoteScheduledException() { | 1420 Object* Isolate::PromoteScheduledException() { |
1421 Object* thrown = scheduled_exception(); | 1421 Object* thrown = scheduled_exception(); |
1422 clear_scheduled_exception(); | 1422 clear_scheduled_exception(); |
1423 // Re-throw the exception to avoid getting repeated error reporting. | 1423 // Re-throw the exception to avoid getting repeated error reporting. |
1424 return ReThrow(thrown); | 1424 return ReThrow(thrown); |
1425 } | 1425 } |
1426 | 1426 |
1427 | 1427 |
1428 void Isolate::PrintCurrentStackTrace(FILE* out) { | 1428 void Isolate::PrintCurrentStackTrace(FILE* out) { |
1429 StackTraceFrameIterator it(this); | 1429 for (StackTraceFrameIterator it(this); !it.done(); it.Advance()) { |
1430 while (!it.done()) { | 1430 if (!it.is_javascript()) continue; |
| 1431 |
1431 HandleScope scope(this); | 1432 HandleScope scope(this); |
| 1433 JavaScriptFrame* frame = it.javascript_frame(); |
| 1434 |
1432 // Find code position if recorded in relocation info. | 1435 // Find code position if recorded in relocation info. |
1433 StandardFrame* frame = it.frame(); | 1436 AbstractCode* abstract_code = AbstractCode::cast(frame->LookupCode()); |
1434 AbstractCode* abstract_code; | 1437 const int code_offset = |
1435 int code_offset; | 1438 static_cast<int>(frame->pc() - abstract_code->instruction_start()); |
1436 if (frame->is_interpreted()) { | 1439 |
1437 InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame); | 1440 Handle<StackTraceFrame> st_frame = factory()->NewStackTraceFrame(); |
1438 abstract_code = AbstractCode::cast(iframe->GetBytecodeArray()); | 1441 |
1439 code_offset = iframe->GetBytecodeOffset(); | 1442 st_frame->set_receiver(frame->receiver()); |
1440 } else { | 1443 st_frame->set_function(frame->function()); |
1441 DCHECK(frame->is_java_script() || frame->is_wasm()); | 1444 st_frame->set_abstract_code(abstract_code); |
1442 Code* code = frame->LookupCode(); | 1445 st_frame->set_offset(code_offset); |
1443 abstract_code = AbstractCode::cast(code); | 1446 |
1444 code_offset = static_cast<int>(frame->pc() - code->instruction_start()); | |
1445 } | |
1446 int pos = abstract_code->SourcePosition(code_offset); | |
1447 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); | |
1448 Handle<Object> pos_obj(Smi::FromInt(pos), this); | |
1449 // Fetch function and receiver. | |
1450 Handle<JSFunction> fun(js_frame->function(), this); | |
1451 Handle<Object> recv(js_frame->receiver(), this); | |
1452 // Advance to the next JavaScript frame and determine if the | |
1453 // current frame is the top-level frame. | |
1454 it.Advance(); | |
1455 Handle<Object> is_top_level = factory()->ToBoolean(it.done()); | |
1456 // Generate and print stack trace line. | 1447 // Generate and print stack trace line. |
1457 Handle<String> line = | 1448 Handle<String> line = st_frame->ToString(); |
1458 Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level); | |
1459 if (line->length() > 0) { | 1449 if (line->length() > 0) { |
1460 line->PrintOn(out); | 1450 line->PrintOn(out); |
1461 PrintF(out, "\n"); | 1451 PrintF(out, "\n"); |
1462 } | 1452 } |
1463 } | 1453 } |
1464 } | 1454 } |
1465 | 1455 |
1466 bool Isolate::ComputeLocation(MessageLocation* target) { | 1456 bool Isolate::ComputeLocation(MessageLocation* target) { |
1467 StackTraceFrameIterator it(this); | 1457 StackTraceFrameIterator it(this); |
1468 if (it.done()) return false; | 1458 if (it.done()) return false; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1506 Handle<Name> script_symbol = factory()->error_script_symbol(); | 1496 Handle<Name> script_symbol = factory()->error_script_symbol(); |
1507 Handle<Object> script = JSReceiver::GetDataProperty( | 1497 Handle<Object> script = JSReceiver::GetDataProperty( |
1508 Handle<JSObject>::cast(exception), script_symbol); | 1498 Handle<JSObject>::cast(exception), script_symbol); |
1509 if (!script->IsScript()) return false; | 1499 if (!script->IsScript()) return false; |
1510 | 1500 |
1511 Handle<Script> cast_script(Script::cast(*script)); | 1501 Handle<Script> cast_script(Script::cast(*script)); |
1512 *target = MessageLocation(cast_script, start_pos_value, end_pos_value); | 1502 *target = MessageLocation(cast_script, start_pos_value, end_pos_value); |
1513 return true; | 1503 return true; |
1514 } | 1504 } |
1515 | 1505 |
| 1506 namespace { |
| 1507 |
| 1508 int PositionFromStackTrace(Handle<FixedArray> elements, int index) { |
| 1509 DisallowHeapAllocation no_gc; |
| 1510 using ESTF = EncodedStackTraceFrame; |
| 1511 Object* maybe_code = elements->get(index + ESTF::kCodeOffset); |
| 1512 if (maybe_code->IsSmi()) { |
| 1513 return Smi::cast(maybe_code)->value(); |
| 1514 } else { |
| 1515 AbstractCode* abstract_code = AbstractCode::cast(maybe_code); |
| 1516 int code_offset = |
| 1517 Smi::cast(elements->get(index + ESTF::kOffsetOffset))->value(); |
| 1518 return abstract_code->SourcePosition(code_offset); |
| 1519 } |
| 1520 } |
| 1521 |
| 1522 } // namespace |
1516 | 1523 |
1517 bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target, | 1524 bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target, |
1518 Handle<Object> exception) { | 1525 Handle<Object> exception) { |
1519 if (!exception->IsJSObject()) return false; | 1526 if (!exception->IsJSObject()) return false; |
1520 Handle<Name> key = factory()->stack_trace_symbol(); | 1527 Handle<Name> key = factory()->stack_trace_symbol(); |
1521 Handle<Object> property = | 1528 Handle<Object> property = |
1522 JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key); | 1529 JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key); |
1523 if (!property->IsJSArray()) return false; | 1530 if (!property->IsJSArray()) return false; |
1524 Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property); | 1531 Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property); |
1525 | 1532 |
1526 Handle<FixedArray> elements(FixedArray::cast(simple_stack_trace->elements())); | 1533 Handle<FixedArray> elements(FixedArray::cast(simple_stack_trace->elements())); |
1527 int elements_limit = Smi::cast(simple_stack_trace->length())->value(); | 1534 int elements_limit = Smi::cast(simple_stack_trace->length())->value(); |
1528 | 1535 |
1529 for (int i = 1; i < elements_limit; i += 4) { | 1536 using ESTF = EncodedStackTraceFrame; |
1530 Handle<Object> fun_obj = handle(elements->get(i + 1), this); | 1537 for (int i = 0; i < elements_limit; i += ESTF::kElementsPerFrame) { |
| 1538 Handle<Object> fun_obj = |
| 1539 handle(elements->get(i + ESTF::kFunctionOffset), this); |
1531 if (fun_obj->IsSmi()) { | 1540 if (fun_obj->IsSmi()) { |
1532 // TODO(clemensh): handle wasm frames | 1541 // TODO(clemensh): handle wasm frames |
1533 return false; | 1542 return false; |
1534 } | 1543 } |
1535 Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj); | 1544 Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj); |
1536 if (!fun->shared()->IsSubjectToDebugging()) continue; | 1545 if (!fun->shared()->IsSubjectToDebugging()) continue; |
1537 | 1546 |
1538 Object* script = fun->shared()->script(); | 1547 Object* script = fun->shared()->script(); |
1539 if (script->IsScript() && | 1548 if (script->IsScript() && |
1540 !(Script::cast(script)->source()->IsUndefined(this))) { | 1549 !(Script::cast(script)->source()->IsUndefined(this))) { |
(...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3203 // Then check whether this scope intercepts. | 3212 // Then check whether this scope intercepts. |
3204 if ((flag & intercept_mask_)) { | 3213 if ((flag & intercept_mask_)) { |
3205 intercepted_flags_ |= flag; | 3214 intercepted_flags_ |= flag; |
3206 return true; | 3215 return true; |
3207 } | 3216 } |
3208 return false; | 3217 return false; |
3209 } | 3218 } |
3210 | 3219 |
3211 } // namespace internal | 3220 } // namespace internal |
3212 } // namespace v8 | 3221 } // namespace v8 |
OLD | NEW |