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