| 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 |