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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 int sloppy_frames = 0; | 380 int sloppy_frames = 0; |
381 bool encountered_strict_function = false; | 381 bool encountered_strict_function = false; |
382 for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit; | 382 for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit; |
383 iter.Advance()) { | 383 iter.Advance()) { |
384 StackFrame* frame = iter.frame(); | 384 StackFrame* frame = iter.frame(); |
385 | 385 |
386 switch (frame->type()) { | 386 switch (frame->type()) { |
387 case StackFrame::JAVA_SCRIPT: | 387 case StackFrame::JAVA_SCRIPT: |
388 case StackFrame::OPTIMIZED: | 388 case StackFrame::OPTIMIZED: |
389 case StackFrame::INTERPRETED: | 389 case StackFrame::INTERPRETED: |
390 case StackFrame::BUILTIN: { | 390 case StackFrame::BUILTIN: |
391 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); | 391 case StackFrame::WASM_COMPILED: |
| 392 case StackFrame::WASM_INTERPRETED: { |
392 // Set initial size to the maximum inlining level + 1 for the outermost | 393 // Set initial size to the maximum inlining level + 1 for the outermost |
393 // function. | 394 // function. |
394 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 395 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
395 js_frame->Summarize(&frames); | 396 StandardFrame::cast(frame)->Summarize(&frames); |
396 for (int i = frames.length() - 1; i >= 0; i--) { | 397 for (int i = frames.length() - 1; i >= 0; i--) { |
397 Handle<JSFunction> fun = frames[i].function(); | 398 if (frames[i].is_javascript()) { |
398 Handle<Object> recv = frames[i].receiver(); | 399 Handle<JSFunction> fun = frames[i].function(); |
399 // Filter out internal frames that we do not want to show. | 400 Handle<Object> recv = frames[i].receiver(); |
400 if (!IsVisibleInStackTrace(*fun, *caller, &seen_caller)) continue; | 401 // Filter out internal frames that we do not want to show. |
401 // Filter out frames from other security contexts. | 402 if (!IsVisibleInStackTrace(*fun, *caller, &seen_caller)) continue; |
402 if (!this->context()->HasSameSecurityTokenAs(fun->context())) { | 403 // Filter out frames from other security contexts. |
403 continue; | 404 if (!this->context()->HasSameSecurityTokenAs(fun->context())) { |
| 405 continue; |
| 406 } |
| 407 elements = MaybeGrow(this, elements, cursor, cursor + 4); |
| 408 |
| 409 Handle<AbstractCode> abstract_code = frames[i].abstract_code(); |
| 410 |
| 411 Handle<Smi> offset(Smi::FromInt(frames[i].code_offset()), this); |
| 412 // The stack trace API should not expose receivers and function |
| 413 // objects on frames deeper than the top-most one with a strict mode |
| 414 // function. The number of sloppy frames is stored as first element |
| 415 // in |
| 416 // the result array. |
| 417 if (!encountered_strict_function) { |
| 418 if (is_strict(fun->shared()->language_mode())) { |
| 419 encountered_strict_function = true; |
| 420 } else { |
| 421 sloppy_frames++; |
| 422 } |
| 423 } |
| 424 elements->set(cursor++, *recv); |
| 425 elements->set(cursor++, *fun); |
| 426 elements->set(cursor++, *abstract_code); |
| 427 elements->set(cursor++, *offset); |
| 428 frames_seen++; |
| 429 } else { |
| 430 DCHECK(frames[i].is_wasm()); |
| 431 elements = MaybeGrow(this, elements, cursor, cursor + 4); |
| 432 elements->set(cursor++, *frames[i].wasm_object()); |
| 433 elements->set(cursor++, |
| 434 Smi::FromInt(frames[i].wasm_function_index())); |
| 435 elements->set(cursor++, *frames[i].abstract_code()); |
| 436 elements->set(cursor++, Smi::FromInt(frames[i].code_offset())); |
| 437 frames_seen++; |
404 } | 438 } |
405 elements = MaybeGrow(this, elements, cursor, cursor + 4); | |
406 | |
407 Handle<AbstractCode> abstract_code = frames[i].abstract_code(); | |
408 | |
409 Handle<Smi> offset(Smi::FromInt(frames[i].code_offset()), this); | |
410 // The stack trace API should not expose receivers and function | |
411 // objects on frames deeper than the top-most one with a strict mode | |
412 // function. The number of sloppy frames is stored as first element in | |
413 // the result array. | |
414 if (!encountered_strict_function) { | |
415 if (is_strict(fun->shared()->language_mode())) { | |
416 encountered_strict_function = true; | |
417 } else { | |
418 sloppy_frames++; | |
419 } | |
420 } | |
421 elements->set(cursor++, *recv); | |
422 elements->set(cursor++, *fun); | |
423 elements->set(cursor++, *abstract_code); | |
424 elements->set(cursor++, *offset); | |
425 frames_seen++; | |
426 } | 439 } |
427 } break; | 440 } break; |
428 | 441 |
429 case StackFrame::WASM: { | |
430 WasmFrame* wasm_frame = WasmFrame::cast(frame); | |
431 Code* code = wasm_frame->unchecked_code(); | |
432 Handle<AbstractCode> abstract_code = | |
433 Handle<AbstractCode>(AbstractCode::cast(code)); | |
434 int offset = | |
435 static_cast<int>(wasm_frame->pc() - code->instruction_start()); | |
436 elements = MaybeGrow(this, elements, cursor, cursor + 4); | |
437 elements->set(cursor++, wasm_frame->wasm_obj()); | |
438 elements->set(cursor++, Smi::FromInt(wasm_frame->function_index())); | |
439 elements->set(cursor++, *abstract_code); | |
440 elements->set(cursor++, Smi::FromInt(offset)); | |
441 frames_seen++; | |
442 } break; | |
443 | |
444 default: | 442 default: |
445 break; | 443 break; |
446 } | 444 } |
447 } | 445 } |
448 elements->set(0, Smi::FromInt(sloppy_frames)); | 446 elements->set(0, Smi::FromInt(sloppy_frames)); |
449 elements->Shrink(cursor); | 447 elements->Shrink(cursor); |
450 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); | 448 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); |
451 result->set_length(Smi::FromInt(cursor)); | 449 result->set_length(Smi::FromInt(cursor)); |
452 // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. | 450 // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. |
453 return result; | 451 return result; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 eval_key_ = | 531 eval_key_ = |
534 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isEval")); | 532 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isEval")); |
535 } | 533 } |
536 if (options & StackTrace::kIsConstructor) { | 534 if (options & StackTrace::kIsConstructor) { |
537 constructor_key_ = factory()->InternalizeOneByteString( | 535 constructor_key_ = factory()->InternalizeOneByteString( |
538 STATIC_CHAR_VECTOR("isConstructor")); | 536 STATIC_CHAR_VECTOR("isConstructor")); |
539 } | 537 } |
540 } | 538 } |
541 | 539 |
542 Handle<JSObject> NewStackFrameObject(FrameSummary& summ) { | 540 Handle<JSObject> NewStackFrameObject(FrameSummary& summ) { |
543 int position = summ.abstract_code()->SourcePosition(summ.code_offset()); | 541 if (summ.is_javascript()) { |
544 return NewStackFrameObject(summ.function(), position, | 542 int position = summ.abstract_code()->SourcePosition(summ.code_offset()); |
545 summ.is_constructor()); | 543 return NewStackFrameObject(summ.function(), position, |
| 544 summ.is_constructor()); |
| 545 } |
| 546 |
| 547 DCHECK(summ.is_wasm()); |
| 548 Handle<JSObject> stack_frame = |
| 549 factory()->NewJSObject(isolate_->object_function()); |
| 550 |
| 551 if (!function_key_.is_null()) { |
| 552 Handle<String> name = wasm::GetWasmFunctionName( |
| 553 isolate_, summ.wasm_object(), summ.wasm_function_index()); |
| 554 JSObject::AddProperty(stack_frame, function_key_, name, NONE); |
| 555 } |
| 556 // Encode the function index as line number. |
| 557 if (!line_key_.is_null()) { |
| 558 JSObject::AddProperty( |
| 559 stack_frame, line_key_, |
| 560 handle(Smi::FromInt(summ.wasm_function_index()), isolate_), NONE); |
| 561 } |
| 562 // Encode the byte offset as column. |
| 563 if (!column_key_.is_null()) { |
| 564 int position = |
| 565 summ.abstract_code()->GetCode()->SourcePosition(summ.code_offset()); |
| 566 // Make position 1-based. |
| 567 if (position >= 0) ++position; |
| 568 JSObject::AddProperty(stack_frame, column_key_, |
| 569 isolate_->factory()->NewNumberFromInt(position), |
| 570 NONE); |
| 571 } |
| 572 if (!script_id_key_.is_null()) { |
| 573 Script* script = summ.script(); |
| 574 // Null pointer can only happen during testing. |
| 575 int script_id = script ? script->id() : -1; |
| 576 JSObject::AddProperty(stack_frame, script_id_key_, |
| 577 handle(Smi::FromInt(script_id), isolate_), NONE); |
| 578 } |
| 579 |
| 580 return stack_frame; |
546 } | 581 } |
547 | 582 |
548 Handle<JSObject> NewStackFrameObject(Handle<JSFunction> fun, int position, | 583 Handle<JSObject> NewStackFrameObject(Handle<JSFunction> fun, int position, |
549 bool is_constructor) { | 584 bool is_constructor) { |
550 Handle<JSObject> stack_frame = | 585 Handle<JSObject> stack_frame = |
551 factory()->NewJSObject(isolate_->object_function()); | 586 factory()->NewJSObject(isolate_->object_function()); |
552 Handle<Script> script(Script::cast(fun->shared()->script())); | 587 Handle<Script> script(Script::cast(fun->shared()->script())); |
553 | 588 |
554 if (!line_key_.is_null()) { | 589 if (!line_key_.is_null()) { |
555 Script::PositionInfo info; | 590 Script::PositionInfo info; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 } | 629 } |
595 | 630 |
596 if (!constructor_key_.is_null()) { | 631 if (!constructor_key_.is_null()) { |
597 Handle<Object> is_constructor_obj = factory()->ToBoolean(is_constructor); | 632 Handle<Object> is_constructor_obj = factory()->ToBoolean(is_constructor); |
598 JSObject::AddProperty(stack_frame, constructor_key_, is_constructor_obj, | 633 JSObject::AddProperty(stack_frame, constructor_key_, is_constructor_obj, |
599 NONE); | 634 NONE); |
600 } | 635 } |
601 return stack_frame; | 636 return stack_frame; |
602 } | 637 } |
603 | 638 |
604 Handle<JSObject> NewStackFrameObject(WasmFrame* frame) { | |
605 Handle<JSObject> stack_frame = | |
606 factory()->NewJSObject(isolate_->object_function()); | |
607 | |
608 if (!function_key_.is_null()) { | |
609 Handle<String> name = wasm::GetWasmFunctionName( | |
610 isolate_, handle(frame->wasm_obj(), isolate_), | |
611 frame->function_index()); | |
612 JSObject::AddProperty(stack_frame, function_key_, name, NONE); | |
613 } | |
614 // Encode the function index as line number. | |
615 if (!line_key_.is_null()) { | |
616 JSObject::AddProperty( | |
617 stack_frame, line_key_, | |
618 isolate_->factory()->NewNumberFromInt(frame->function_index()), NONE); | |
619 } | |
620 // Encode the byte offset as column. | |
621 if (!column_key_.is_null()) { | |
622 Code* code = frame->LookupCode(); | |
623 int offset = static_cast<int>(frame->pc() - code->instruction_start()); | |
624 int position = code->SourcePosition(offset); | |
625 // Make position 1-based. | |
626 if (position >= 0) ++position; | |
627 JSObject::AddProperty(stack_frame, column_key_, | |
628 isolate_->factory()->NewNumberFromInt(position), | |
629 NONE); | |
630 } | |
631 if (!script_id_key_.is_null()) { | |
632 int script_id = frame->script()->id(); | |
633 JSObject::AddProperty(stack_frame, script_id_key_, | |
634 handle(Smi::FromInt(script_id), isolate_), NONE); | |
635 } | |
636 | |
637 return stack_frame; | |
638 } | |
639 | |
640 private: | 639 private: |
641 inline Factory* factory() { return isolate_->factory(); } | 640 inline Factory* factory() { return isolate_->factory(); } |
642 | 641 |
643 Isolate* isolate_; | 642 Isolate* isolate_; |
644 Handle<String> column_key_; | 643 Handle<String> column_key_; |
645 Handle<String> line_key_; | 644 Handle<String> line_key_; |
646 Handle<String> script_id_key_; | 645 Handle<String> script_id_key_; |
647 Handle<String> script_name_key_; | 646 Handle<String> script_name_key_; |
648 Handle<String> script_name_or_source_url_key_; | 647 Handle<String> script_name_or_source_url_key_; |
649 Handle<String> function_key_; | 648 Handle<String> function_key_; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 | 709 |
711 // Ensure no negative values. | 710 // Ensure no negative values. |
712 int limit = Max(frame_limit, 0); | 711 int limit = Max(frame_limit, 0); |
713 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit); | 712 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit); |
714 Handle<FixedArray> stack_trace_elems( | 713 Handle<FixedArray> stack_trace_elems( |
715 FixedArray::cast(stack_trace->elements()), this); | 714 FixedArray::cast(stack_trace->elements()), this); |
716 | 715 |
717 int frames_seen = 0; | 716 int frames_seen = 0; |
718 for (StackTraceFrameIterator it(this); !it.done() && (frames_seen < limit); | 717 for (StackTraceFrameIterator it(this); !it.done() && (frames_seen < limit); |
719 it.Advance()) { | 718 it.Advance()) { |
720 StandardFrame* frame = it.frame(); | 719 // Set initial size to the maximum inlining level + 1 for the outermost |
721 if (frame->is_java_script()) { | 720 // function. |
722 // Set initial size to the maximum inlining level + 1 for the outermost | 721 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
723 // function. | 722 it.frame()->Summarize(&frames); |
724 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 723 for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) { |
725 JavaScriptFrame::cast(frame)->Summarize(&frames); | 724 // Filter frames from other security contexts. |
726 for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) { | 725 if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) && |
727 Handle<JSFunction> fun = frames[i].function(); | 726 frames[i].is_javascript() && |
728 // Filter frames from other security contexts. | 727 !this->context()->HasSameSecurityTokenAs( |
729 if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) && | 728 frames[i].function()->context())) |
730 !this->context()->HasSameSecurityTokenAs(fun->context())) | 729 continue; |
731 continue; | 730 Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(frames[i]); |
732 Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(frames[i]); | |
733 stack_trace_elems->set(frames_seen, *new_frame_obj); | |
734 frames_seen++; | |
735 } | |
736 } else { | |
737 WasmFrame* wasm_frame = WasmFrame::cast(frame); | |
738 Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(wasm_frame); | |
739 stack_trace_elems->set(frames_seen, *new_frame_obj); | 731 stack_trace_elems->set(frames_seen, *new_frame_obj); |
740 frames_seen++; | 732 frames_seen++; |
741 } | 733 } |
742 } | 734 } |
743 | 735 |
744 stack_trace->set_length(Smi::FromInt(frames_seen)); | 736 stack_trace->set_length(Smi::FromInt(frames_seen)); |
745 return stack_trace; | 737 return stack_trace; |
746 } | 738 } |
747 | 739 |
748 | 740 |
(...skipping 2313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3062 // Then check whether this scope intercepts. | 3054 // Then check whether this scope intercepts. |
3063 if ((flag & intercept_mask_)) { | 3055 if ((flag & intercept_mask_)) { |
3064 intercepted_flags_ |= flag; | 3056 intercepted_flags_ |= flag; |
3065 return true; | 3057 return true; |
3066 } | 3058 } |
3067 return false; | 3059 return false; |
3068 } | 3060 } |
3069 | 3061 |
3070 } // namespace internal | 3062 } // namespace internal |
3071 } // namespace v8 | 3063 } // namespace v8 |
OLD | NEW |