OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | |
8 #include "src/arguments.h" | 7 #include "src/arguments.h" |
9 #include "src/compiler.h" | |
10 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
11 #include "src/deoptimizer.h" | 9 #include "src/debug/debug-evaluate.h" |
12 #include "src/parser.h" | 10 #include "src/debug/debug-frames.h" |
| 11 #include "src/debug/debug-scopes.h" |
13 #include "src/runtime/runtime.h" | 12 #include "src/runtime/runtime.h" |
14 #include "src/runtime/runtime-utils.h" | 13 #include "src/runtime/runtime-utils.h" |
15 | 14 |
16 namespace v8 { | 15 namespace v8 { |
17 namespace internal { | 16 namespace internal { |
18 | 17 |
19 RUNTIME_FUNCTION(Runtime_DebugBreak) { | 18 RUNTIME_FUNCTION(Runtime_DebugBreak) { |
20 SealHandleScope shs(isolate); | 19 SealHandleScope shs(isolate); |
21 DCHECK(args.length() == 0); | 20 DCHECK(args.length() == 0); |
22 // Get the top-most JavaScript frame. | 21 // Get the top-most JavaScript frame. |
23 JavaScriptFrameIterator it(isolate); | 22 JavaScriptFrameIterator it(isolate); |
24 isolate->debug()->Break(args, it.frame()); | 23 isolate->debug()->Break(args, it.frame()); |
25 isolate->debug()->SetAfterBreakTarget(it.frame()); | 24 isolate->debug()->SetAfterBreakTarget(it.frame()); |
26 return isolate->heap()->undefined_value(); | 25 return isolate->heap()->undefined_value(); |
27 } | 26 } |
28 | 27 |
29 | 28 |
30 RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) { | 29 RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) { |
31 SealHandleScope shs(isolate); | 30 SealHandleScope shs(isolate); |
32 DCHECK(args.length() == 0); | 31 DCHECK(args.length() == 0); |
33 isolate->debug()->HandleDebugBreak(); | 32 isolate->debug()->HandleDebugBreak(); |
34 return isolate->heap()->undefined_value(); | 33 return isolate->heap()->undefined_value(); |
35 } | 34 } |
36 | 35 |
37 | 36 |
38 // Helper functions for wrapping and unwrapping stack frame ids. | |
39 static Smi* WrapFrameId(StackFrame::Id id) { | |
40 DCHECK(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4))); | |
41 return Smi::FromInt(id >> 2); | |
42 } | |
43 | |
44 | |
45 static StackFrame::Id UnwrapFrameId(int wrapped) { | |
46 return static_cast<StackFrame::Id>(wrapped << 2); | |
47 } | |
48 | |
49 | |
50 // Adds a JavaScript function as a debug event listener. | 37 // Adds a JavaScript function as a debug event listener. |
51 // args[0]: debug event listener function to set or null or undefined for | 38 // args[0]: debug event listener function to set or null or undefined for |
52 // clearing the event listener function | 39 // clearing the event listener function |
53 // args[1]: object supplied during callback | 40 // args[1]: object supplied during callback |
54 RUNTIME_FUNCTION(Runtime_SetDebugEventListener) { | 41 RUNTIME_FUNCTION(Runtime_SetDebugEventListener) { |
55 SealHandleScope shs(isolate); | 42 SealHandleScope shs(isolate); |
56 DCHECK(args.length() == 2); | 43 DCHECK(args.length() == 2); |
57 RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() || | 44 RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() || |
58 args[0]->IsNull()); | 45 args[0]->IsNull()); |
59 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0); | 46 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0); |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 it.frame()->Summarize(&frames); | 455 it.frame()->Summarize(&frames); |
469 for (int i = frames.length() - 1; i >= 0; i--) { | 456 for (int i = frames.length() - 1; i >= 0; i--) { |
470 // Omit functions from native and extension scripts. | 457 // Omit functions from native and extension scripts. |
471 if (frames[i].function()->IsSubjectToDebugging()) n++; | 458 if (frames[i].function()->IsSubjectToDebugging()) n++; |
472 } | 459 } |
473 } | 460 } |
474 return Smi::FromInt(n); | 461 return Smi::FromInt(n); |
475 } | 462 } |
476 | 463 |
477 | 464 |
478 class FrameInspector { | |
479 public: | |
480 FrameInspector(JavaScriptFrame* frame, int inlined_jsframe_index, | |
481 Isolate* isolate) | |
482 : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) { | |
483 has_adapted_arguments_ = frame_->has_adapted_arguments(); | |
484 is_bottommost_ = inlined_jsframe_index == 0; | |
485 is_optimized_ = frame_->is_optimized(); | |
486 // Calculate the deoptimized frame. | |
487 if (frame->is_optimized()) { | |
488 // TODO(turbofan): Revisit once we support deoptimization. | |
489 if (frame->LookupCode()->is_turbofanned() && | |
490 frame->function()->shared()->asm_function() && | |
491 !FLAG_turbo_asm_deoptimization) { | |
492 is_optimized_ = false; | |
493 return; | |
494 } | |
495 | |
496 deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame( | |
497 frame, inlined_jsframe_index, isolate); | |
498 } | |
499 } | |
500 | |
501 ~FrameInspector() { | |
502 // Get rid of the calculated deoptimized frame if any. | |
503 if (deoptimized_frame_ != NULL) { | |
504 Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_, isolate_); | |
505 } | |
506 } | |
507 | |
508 int GetParametersCount() { | |
509 return is_optimized_ ? deoptimized_frame_->parameters_count() | |
510 : frame_->ComputeParametersCount(); | |
511 } | |
512 int expression_count() { return deoptimized_frame_->expression_count(); } | |
513 Object* GetFunction() { | |
514 return is_optimized_ ? deoptimized_frame_->GetFunction() | |
515 : frame_->function(); | |
516 } | |
517 Object* GetParameter(int index) { | |
518 return is_optimized_ ? deoptimized_frame_->GetParameter(index) | |
519 : frame_->GetParameter(index); | |
520 } | |
521 Object* GetExpression(int index) { | |
522 // TODO(turbofan): Revisit once we support deoptimization. | |
523 if (frame_->LookupCode()->is_turbofanned() && | |
524 frame_->function()->shared()->asm_function() && | |
525 !FLAG_turbo_asm_deoptimization) { | |
526 return isolate_->heap()->undefined_value(); | |
527 } | |
528 return is_optimized_ ? deoptimized_frame_->GetExpression(index) | |
529 : frame_->GetExpression(index); | |
530 } | |
531 int GetSourcePosition() { | |
532 return is_optimized_ ? deoptimized_frame_->GetSourcePosition() | |
533 : frame_->LookupCode()->SourcePosition(frame_->pc()); | |
534 } | |
535 bool IsConstructor() { | |
536 return is_optimized_ && !is_bottommost_ | |
537 ? deoptimized_frame_->HasConstructStub() | |
538 : frame_->IsConstructor(); | |
539 } | |
540 Object* GetContext() { | |
541 return is_optimized_ ? deoptimized_frame_->GetContext() : frame_->context(); | |
542 } | |
543 JavaScriptFrame* GetArgumentsFrame() { return frame_; } | |
544 | |
545 // To inspect all the provided arguments the frame might need to be | |
546 // replaced with the arguments frame. | |
547 void SetArgumentsFrame(JavaScriptFrame* frame) { | |
548 DCHECK(has_adapted_arguments_); | |
549 frame_ = frame; | |
550 is_optimized_ = frame_->is_optimized(); | |
551 DCHECK(!is_optimized_); | |
552 } | |
553 | |
554 private: | |
555 JavaScriptFrame* frame_; | |
556 DeoptimizedFrameInfo* deoptimized_frame_; | |
557 Isolate* isolate_; | |
558 bool is_optimized_; | |
559 bool is_bottommost_; | |
560 bool has_adapted_arguments_; | |
561 | |
562 DISALLOW_COPY_AND_ASSIGN(FrameInspector); | |
563 }; | |
564 | |
565 | |
566 static const int kFrameDetailsFrameIdIndex = 0; | 465 static const int kFrameDetailsFrameIdIndex = 0; |
567 static const int kFrameDetailsReceiverIndex = 1; | 466 static const int kFrameDetailsReceiverIndex = 1; |
568 static const int kFrameDetailsFunctionIndex = 2; | 467 static const int kFrameDetailsFunctionIndex = 2; |
569 static const int kFrameDetailsArgumentCountIndex = 3; | 468 static const int kFrameDetailsArgumentCountIndex = 3; |
570 static const int kFrameDetailsLocalCountIndex = 4; | 469 static const int kFrameDetailsLocalCountIndex = 4; |
571 static const int kFrameDetailsSourcePositionIndex = 5; | 470 static const int kFrameDetailsSourcePositionIndex = 5; |
572 static const int kFrameDetailsConstructCallIndex = 6; | 471 static const int kFrameDetailsConstructCallIndex = 6; |
573 static const int kFrameDetailsAtReturnIndex = 7; | 472 static const int kFrameDetailsAtReturnIndex = 7; |
574 static const int kFrameDetailsFlagsIndex = 8; | 473 static const int kFrameDetailsFlagsIndex = 8; |
575 static const int kFrameDetailsFirstDynamicIndex = 9; | 474 static const int kFrameDetailsFirstDynamicIndex = 9; |
576 | 475 |
577 | 476 |
578 static SaveContext* FindSavedContextForFrame(Isolate* isolate, | |
579 JavaScriptFrame* frame) { | |
580 SaveContext* save = isolate->save_context(); | |
581 while (save != NULL && !save->IsBelowFrame(frame)) { | |
582 save = save->prev(); | |
583 } | |
584 DCHECK(save != NULL); | |
585 return save; | |
586 } | |
587 | |
588 | |
589 // Advances the iterator to the frame that matches the index and returns the | |
590 // inlined frame index, or -1 if not found. Skips native JS functions. | |
591 int Runtime::FindIndexedNonNativeFrame(JavaScriptFrameIterator* it, int index) { | |
592 int count = -1; | |
593 for (; !it->done(); it->Advance()) { | |
594 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | |
595 it->frame()->Summarize(&frames); | |
596 for (int i = frames.length() - 1; i >= 0; i--) { | |
597 // Omit functions from native and extension scripts. | |
598 if (!frames[i].function()->IsSubjectToDebugging()) continue; | |
599 if (++count == index) return i; | |
600 } | |
601 } | |
602 return -1; | |
603 } | |
604 | |
605 | |
606 // Return an array with frame details | 477 // Return an array with frame details |
607 // args[0]: number: break id | 478 // args[0]: number: break id |
608 // args[1]: number: frame index | 479 // args[1]: number: frame index |
609 // | 480 // |
610 // The array returned contains the following information: | 481 // The array returned contains the following information: |
611 // 0: Frame id | 482 // 0: Frame id |
612 // 1: Receiver | 483 // 1: Receiver |
613 // 2: Function | 484 // 2: Function |
614 // 3: Argument count | 485 // 3: Argument count |
615 // 4: Local count | 486 // 4: Local count |
(...skipping 15 matching lines...) Expand all Loading... |
631 | 502 |
632 // Find the relevant frame with the requested index. | 503 // Find the relevant frame with the requested index. |
633 StackFrame::Id id = isolate->debug()->break_frame_id(); | 504 StackFrame::Id id = isolate->debug()->break_frame_id(); |
634 if (id == StackFrame::NO_ID) { | 505 if (id == StackFrame::NO_ID) { |
635 // If there are no JavaScript stack frames return undefined. | 506 // If there are no JavaScript stack frames return undefined. |
636 return heap->undefined_value(); | 507 return heap->undefined_value(); |
637 } | 508 } |
638 | 509 |
639 JavaScriptFrameIterator it(isolate, id); | 510 JavaScriptFrameIterator it(isolate, id); |
640 // Inlined frame index in optimized frame, starting from outer function. | 511 // Inlined frame index in optimized frame, starting from outer function. |
641 int inlined_jsframe_index = Runtime::FindIndexedNonNativeFrame(&it, index); | 512 int inlined_jsframe_index = |
| 513 DebugFrameHelper::FindIndexedNonNativeFrame(&it, index); |
642 if (inlined_jsframe_index == -1) return heap->undefined_value(); | 514 if (inlined_jsframe_index == -1) return heap->undefined_value(); |
643 | 515 |
644 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate); | 516 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate); |
645 bool is_optimized = it.frame()->is_optimized(); | 517 bool is_optimized = it.frame()->is_optimized(); |
646 | 518 |
647 // Traverse the saved contexts chain to find the active context for the | 519 // Traverse the saved contexts chain to find the active context for the |
648 // selected frame. | 520 // selected frame. |
649 SaveContext* save = FindSavedContextForFrame(isolate, it.frame()); | 521 SaveContext* save = |
| 522 DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame()); |
650 | 523 |
651 // Get the frame id. | 524 // Get the frame id. |
652 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); | 525 Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()), |
| 526 isolate); |
653 | 527 |
654 // Find source position in unoptimized code. | 528 // Find source position in unoptimized code. |
655 int position = frame_inspector.GetSourcePosition(); | 529 int position = frame_inspector.GetSourcePosition(); |
656 | 530 |
657 // Check for constructor frame. | 531 // Check for constructor frame. |
658 bool constructor = frame_inspector.IsConstructor(); | 532 bool constructor = frame_inspector.IsConstructor(); |
659 | 533 |
660 // Get scope info and read from it for local variable information. | 534 // Get scope info and read from it for local variable information. |
661 Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction())); | 535 Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction())); |
662 Handle<SharedFunctionInfo> shared(function->shared()); | 536 Handle<SharedFunctionInfo> shared(function->shared()); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 } | 733 } |
860 } | 734 } |
861 } | 735 } |
862 details->set(kFrameDetailsReceiverIndex, *receiver); | 736 details->set(kFrameDetailsReceiverIndex, *receiver); |
863 | 737 |
864 DCHECK_EQ(details_size, details_index); | 738 DCHECK_EQ(details_size, details_index); |
865 return *isolate->factory()->NewJSArrayWithElements(details); | 739 return *isolate->factory()->NewJSArrayWithElements(details); |
866 } | 740 } |
867 | 741 |
868 | 742 |
869 static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info, | |
870 Handle<String> parameter_name) { | |
871 VariableMode mode; | |
872 VariableLocation location; | |
873 InitializationFlag init_flag; | |
874 MaybeAssignedFlag maybe_assigned_flag; | |
875 return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &location, | |
876 &init_flag, &maybe_assigned_flag) != -1; | |
877 } | |
878 | |
879 | |
880 static Handle<Context> MaterializeReceiver(Isolate* isolate, | |
881 Handle<Context> target, | |
882 Handle<JSFunction> function, | |
883 JavaScriptFrame* frame) { | |
884 Handle<SharedFunctionInfo> shared(function->shared()); | |
885 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
886 Handle<Object> receiver; | |
887 switch (scope_info->scope_type()) { | |
888 case FUNCTION_SCOPE: { | |
889 VariableMode mode; | |
890 VariableLocation location; | |
891 InitializationFlag init_flag; | |
892 MaybeAssignedFlag maybe_assigned_flag; | |
893 | |
894 // Don't bother creating a fake context node if "this" is in the context | |
895 // already. | |
896 if (ScopeInfo::ContextSlotIndex( | |
897 scope_info, isolate->factory()->this_string(), &mode, &location, | |
898 &init_flag, &maybe_assigned_flag) >= 0) { | |
899 return target; | |
900 } | |
901 receiver = handle(frame->receiver(), isolate); | |
902 break; | |
903 } | |
904 case MODULE_SCOPE: | |
905 receiver = isolate->factory()->undefined_value(); | |
906 break; | |
907 case SCRIPT_SCOPE: | |
908 receiver = handle(function->global_proxy(), isolate); | |
909 break; | |
910 default: | |
911 // For eval code, arrow functions, and the like, there's no "this" binding | |
912 // to materialize. | |
913 return target; | |
914 } | |
915 | |
916 return isolate->factory()->NewCatchContext( | |
917 function, target, isolate->factory()->this_string(), receiver); | |
918 } | |
919 | |
920 | |
921 // Create a plain JSObject which materializes the local scope for the specified | |
922 // frame. | |
923 static void MaterializeStackLocalsWithFrameInspector( | |
924 Isolate* isolate, Handle<JSObject> target, Handle<ScopeInfo> scope_info, | |
925 FrameInspector* frame_inspector) { | |
926 // First fill all parameters. | |
927 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | |
928 // Do not materialize the parameter if it is shadowed by a context local. | |
929 Handle<String> name(scope_info->ParameterName(i)); | |
930 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; | |
931 | |
932 DCHECK_NOT_NULL(frame_inspector); | |
933 | |
934 HandleScope scope(isolate); | |
935 Handle<Object> value(i < frame_inspector->GetParametersCount() | |
936 ? frame_inspector->GetParameter(i) | |
937 : isolate->heap()->undefined_value(), | |
938 isolate); | |
939 DCHECK(!value->IsTheHole()); | |
940 | |
941 JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check(); | |
942 } | |
943 | |
944 // Second fill all stack locals. | |
945 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | |
946 if (scope_info->LocalIsSynthetic(i)) continue; | |
947 Handle<String> name(scope_info->StackLocalName(i)); | |
948 Handle<Object> value( | |
949 frame_inspector->GetExpression(scope_info->StackLocalIndex(i)), | |
950 isolate); | |
951 if (value->IsTheHole()) { | |
952 value = isolate->factory()->undefined_value(); | |
953 } | |
954 | |
955 JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check(); | |
956 } | |
957 } | |
958 | |
959 static void MaterializeStackLocalsWithFrameInspector( | |
960 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, | |
961 FrameInspector* frame_inspector) { | |
962 Handle<SharedFunctionInfo> shared(function->shared()); | |
963 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
964 | |
965 MaterializeStackLocalsWithFrameInspector(isolate, target, scope_info, | |
966 frame_inspector); | |
967 } | |
968 | |
969 | |
970 static void UpdateStackLocalsFromMaterializedObject( | |
971 Isolate* isolate, Handle<JSObject> target, Handle<ScopeInfo> scope_info, | |
972 JavaScriptFrame* frame, int inlined_jsframe_index) { | |
973 if (inlined_jsframe_index != 0 || frame->is_optimized()) { | |
974 // Optimized frames are not supported. Simply give up. | |
975 return; | |
976 } | |
977 | |
978 // Parameters. | |
979 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | |
980 // Shadowed parameters were not materialized. | |
981 Handle<String> name(scope_info->ParameterName(i)); | |
982 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; | |
983 | |
984 DCHECK(!frame->GetParameter(i)->IsTheHole()); | |
985 HandleScope scope(isolate); | |
986 Handle<Object> value = | |
987 Object::GetPropertyOrElement(target, name).ToHandleChecked(); | |
988 frame->SetParameterValue(i, *value); | |
989 } | |
990 | |
991 // Stack locals. | |
992 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | |
993 if (scope_info->LocalIsSynthetic(i)) continue; | |
994 int index = scope_info->StackLocalIndex(i); | |
995 if (frame->GetExpression(index)->IsTheHole()) continue; | |
996 HandleScope scope(isolate); | |
997 Handle<Object> value = Object::GetPropertyOrElement( | |
998 target, handle(scope_info->StackLocalName(i), | |
999 isolate)).ToHandleChecked(); | |
1000 frame->SetExpression(index, *value); | |
1001 } | |
1002 } | |
1003 | |
1004 | |
1005 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext( | |
1006 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, | |
1007 Handle<Context> frame_context) { | |
1008 HandleScope scope(isolate); | |
1009 Handle<SharedFunctionInfo> shared(function->shared()); | |
1010 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
1011 | |
1012 if (!scope_info->HasContext()) return target; | |
1013 | |
1014 // Third fill all context locals. | |
1015 Handle<Context> function_context(frame_context->declaration_context()); | |
1016 ScopeInfo::CopyContextLocalsToScopeObject(scope_info, function_context, | |
1017 target); | |
1018 | |
1019 // Finally copy any properties from the function context extension. | |
1020 // These will be variables introduced by eval. | |
1021 if (function_context->closure() == *function) { | |
1022 if (function_context->has_extension() && | |
1023 !function_context->IsNativeContext()) { | |
1024 Handle<JSObject> ext(JSObject::cast(function_context->extension())); | |
1025 Handle<FixedArray> keys; | |
1026 ASSIGN_RETURN_ON_EXCEPTION( | |
1027 isolate, keys, JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS), | |
1028 JSObject); | |
1029 | |
1030 for (int i = 0; i < keys->length(); i++) { | |
1031 // Names of variables introduced by eval are strings. | |
1032 DCHECK(keys->get(i)->IsString()); | |
1033 Handle<String> key(String::cast(keys->get(i))); | |
1034 Handle<Object> value; | |
1035 ASSIGN_RETURN_ON_EXCEPTION( | |
1036 isolate, value, Object::GetPropertyOrElement(ext, key), JSObject); | |
1037 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty( | |
1038 isolate, target, key, value, SLOPPY), | |
1039 JSObject); | |
1040 } | |
1041 } | |
1042 } | |
1043 | |
1044 return target; | |
1045 } | |
1046 | |
1047 | |
1048 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScriptScope( | |
1049 Handle<GlobalObject> global) { | |
1050 Isolate* isolate = global->GetIsolate(); | |
1051 Handle<ScriptContextTable> script_contexts( | |
1052 global->native_context()->script_context_table()); | |
1053 | |
1054 Handle<JSObject> script_scope = | |
1055 isolate->factory()->NewJSObject(isolate->object_function()); | |
1056 | |
1057 for (int context_index = 0; context_index < script_contexts->used(); | |
1058 context_index++) { | |
1059 Handle<Context> context = | |
1060 ScriptContextTable::GetContext(script_contexts, context_index); | |
1061 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); | |
1062 ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, | |
1063 script_scope); | |
1064 } | |
1065 return script_scope; | |
1066 } | |
1067 | |
1068 | |
1069 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalScope( | |
1070 Isolate* isolate, FrameInspector* frame_inspector) { | |
1071 Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction())); | |
1072 | |
1073 Handle<JSObject> local_scope = | |
1074 isolate->factory()->NewJSObject(isolate->object_function()); | |
1075 MaterializeStackLocalsWithFrameInspector(isolate, local_scope, function, | |
1076 frame_inspector); | |
1077 | |
1078 Handle<Context> frame_context(Context::cast(frame_inspector->GetContext())); | |
1079 | |
1080 return MaterializeLocalContext(isolate, local_scope, function, frame_context); | |
1081 } | |
1082 | |
1083 | |
1084 // Set the context local variable value. | |
1085 static bool SetContextLocalValue(Isolate* isolate, Handle<ScopeInfo> scope_info, | |
1086 Handle<Context> context, | |
1087 Handle<String> variable_name, | |
1088 Handle<Object> new_value) { | |
1089 for (int i = 0; i < scope_info->ContextLocalCount(); i++) { | |
1090 Handle<String> next_name(scope_info->ContextLocalName(i)); | |
1091 if (String::Equals(variable_name, next_name)) { | |
1092 VariableMode mode; | |
1093 VariableLocation location; | |
1094 InitializationFlag init_flag; | |
1095 MaybeAssignedFlag maybe_assigned_flag; | |
1096 int context_index = | |
1097 ScopeInfo::ContextSlotIndex(scope_info, next_name, &mode, &location, | |
1098 &init_flag, &maybe_assigned_flag); | |
1099 context->set(context_index, *new_value); | |
1100 return true; | |
1101 } | |
1102 } | |
1103 | |
1104 return false; | |
1105 } | |
1106 | |
1107 | |
1108 static bool SetLocalVariableValue(Isolate* isolate, JavaScriptFrame* frame, | |
1109 Handle<String> variable_name, | |
1110 Handle<Object> new_value) { | |
1111 // Optimized frames are not supported. | |
1112 if (frame->is_optimized()) return false; | |
1113 | |
1114 Handle<JSFunction> function(frame->function()); | |
1115 Handle<SharedFunctionInfo> shared(function->shared()); | |
1116 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
1117 | |
1118 bool default_result = false; | |
1119 | |
1120 // Parameters. | |
1121 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | |
1122 HandleScope scope(isolate); | |
1123 if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) { | |
1124 frame->SetParameterValue(i, *new_value); | |
1125 // Argument might be shadowed in heap context, don't stop here. | |
1126 default_result = true; | |
1127 } | |
1128 } | |
1129 | |
1130 // Stack locals. | |
1131 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | |
1132 HandleScope scope(isolate); | |
1133 if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) { | |
1134 frame->SetExpression(scope_info->StackLocalIndex(i), *new_value); | |
1135 return true; | |
1136 } | |
1137 } | |
1138 | |
1139 if (scope_info->HasContext()) { | |
1140 // Context locals. | |
1141 Handle<Context> frame_context(Context::cast(frame->context())); | |
1142 Handle<Context> function_context(frame_context->declaration_context()); | |
1143 if (SetContextLocalValue(isolate, scope_info, function_context, | |
1144 variable_name, new_value)) { | |
1145 return true; | |
1146 } | |
1147 | |
1148 // Function context extension. These are variables introduced by eval. | |
1149 if (function_context->closure() == *function) { | |
1150 if (function_context->has_extension() && | |
1151 !function_context->IsNativeContext()) { | |
1152 Handle<JSObject> ext(JSObject::cast(function_context->extension())); | |
1153 | |
1154 Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name); | |
1155 DCHECK(maybe.IsJust()); | |
1156 if (maybe.FromJust()) { | |
1157 // We don't expect this to do anything except replacing | |
1158 // property value. | |
1159 Runtime::SetObjectProperty(isolate, ext, variable_name, new_value, | |
1160 SLOPPY).Assert(); | |
1161 return true; | |
1162 } | |
1163 } | |
1164 } | |
1165 } | |
1166 | |
1167 return default_result; | |
1168 } | |
1169 | |
1170 | |
1171 static bool SetBlockVariableValue(Isolate* isolate, | |
1172 Handle<Context> block_context, | |
1173 Handle<ScopeInfo> scope_info, | |
1174 JavaScriptFrame* frame, | |
1175 Handle<String> variable_name, | |
1176 Handle<Object> new_value) { | |
1177 if (frame != nullptr) { | |
1178 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | |
1179 HandleScope scope(isolate); | |
1180 if (String::Equals(handle(scope_info->StackLocalName(i)), | |
1181 variable_name)) { | |
1182 frame->SetExpression(scope_info->StackLocalIndex(i), *new_value); | |
1183 return true; | |
1184 } | |
1185 } | |
1186 } | |
1187 if (!block_context.is_null()) { | |
1188 return SetContextLocalValue(block_context->GetIsolate(), scope_info, | |
1189 block_context, variable_name, new_value); | |
1190 } | |
1191 return false; | |
1192 } | |
1193 | |
1194 | |
1195 // Create a plain JSObject which materializes the closure content for the | |
1196 // context. | |
1197 static Handle<JSObject> MaterializeClosure(Isolate* isolate, | |
1198 Handle<Context> context) { | |
1199 DCHECK(context->IsFunctionContext()); | |
1200 | |
1201 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | |
1202 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
1203 | |
1204 // Allocate and initialize a JSObject with all the content of this function | |
1205 // closure. | |
1206 Handle<JSObject> closure_scope = | |
1207 isolate->factory()->NewJSObject(isolate->object_function()); | |
1208 | |
1209 // Fill all context locals to the context extension. | |
1210 ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, closure_scope); | |
1211 | |
1212 // Finally copy any properties from the function context extension. This will | |
1213 // be variables introduced by eval. | |
1214 if (context->has_extension()) { | |
1215 Handle<JSObject> ext(JSObject::cast(context->extension())); | |
1216 DCHECK(ext->IsJSContextExtensionObject()); | |
1217 Handle<FixedArray> keys = | |
1218 JSReceiver::GetKeys(ext, JSReceiver::OWN_ONLY).ToHandleChecked(); | |
1219 | |
1220 for (int i = 0; i < keys->length(); i++) { | |
1221 HandleScope scope(isolate); | |
1222 // Names of variables introduced by eval are strings. | |
1223 DCHECK(keys->get(i)->IsString()); | |
1224 Handle<String> key(String::cast(keys->get(i))); | |
1225 Handle<Object> value = Object::GetProperty(ext, key).ToHandleChecked(); | |
1226 JSObject::SetOwnPropertyIgnoreAttributes(closure_scope, key, value, NONE) | |
1227 .Check(); | |
1228 } | |
1229 } | |
1230 | |
1231 return closure_scope; | |
1232 } | |
1233 | |
1234 | |
1235 // This method copies structure of MaterializeClosure method above. | |
1236 static bool SetClosureVariableValue(Isolate* isolate, Handle<Context> context, | |
1237 Handle<String> variable_name, | |
1238 Handle<Object> new_value) { | |
1239 DCHECK(context->IsFunctionContext()); | |
1240 | |
1241 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | |
1242 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
1243 | |
1244 // Context locals to the context extension. | |
1245 if (SetContextLocalValue(isolate, scope_info, context, variable_name, | |
1246 new_value)) { | |
1247 return true; | |
1248 } | |
1249 | |
1250 // Properties from the function context extension. This will | |
1251 // be variables introduced by eval. | |
1252 if (context->has_extension()) { | |
1253 Handle<JSObject> ext(JSObject::cast(context->extension())); | |
1254 DCHECK(ext->IsJSContextExtensionObject()); | |
1255 Maybe<bool> maybe = JSReceiver::HasOwnProperty(ext, variable_name); | |
1256 DCHECK(maybe.IsJust()); | |
1257 if (maybe.FromJust()) { | |
1258 // We don't expect this to do anything except replacing property value. | |
1259 JSObject::SetOwnPropertyIgnoreAttributes(ext, variable_name, new_value, | |
1260 NONE).Check(); | |
1261 return true; | |
1262 } | |
1263 } | |
1264 | |
1265 return false; | |
1266 } | |
1267 | |
1268 | |
1269 static bool SetScriptVariableValue(Handle<Context> context, | |
1270 Handle<String> variable_name, | |
1271 Handle<Object> new_value) { | |
1272 Handle<ScriptContextTable> script_contexts( | |
1273 context->global_object()->native_context()->script_context_table()); | |
1274 ScriptContextTable::LookupResult lookup_result; | |
1275 if (ScriptContextTable::Lookup(script_contexts, variable_name, | |
1276 &lookup_result)) { | |
1277 Handle<Context> script_context = ScriptContextTable::GetContext( | |
1278 script_contexts, lookup_result.context_index); | |
1279 script_context->set(lookup_result.slot_index, *new_value); | |
1280 return true; | |
1281 } | |
1282 | |
1283 return false; | |
1284 } | |
1285 | |
1286 | |
1287 // Create a plain JSObject which materializes the scope for the specified | |
1288 // catch context. | |
1289 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate, | |
1290 Handle<Context> context) { | |
1291 DCHECK(context->IsCatchContext()); | |
1292 Handle<String> name(String::cast(context->extension())); | |
1293 Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX), | |
1294 isolate); | |
1295 Handle<JSObject> catch_scope = | |
1296 isolate->factory()->NewJSObject(isolate->object_function()); | |
1297 JSObject::SetOwnPropertyIgnoreAttributes(catch_scope, name, thrown_object, | |
1298 NONE).Check(); | |
1299 return catch_scope; | |
1300 } | |
1301 | |
1302 | |
1303 static bool SetCatchVariableValue(Isolate* isolate, Handle<Context> context, | |
1304 Handle<String> variable_name, | |
1305 Handle<Object> new_value) { | |
1306 DCHECK(context->IsCatchContext()); | |
1307 Handle<String> name(String::cast(context->extension())); | |
1308 if (!String::Equals(name, variable_name)) { | |
1309 return false; | |
1310 } | |
1311 context->set(Context::THROWN_OBJECT_INDEX, *new_value); | |
1312 return true; | |
1313 } | |
1314 | |
1315 | |
1316 // Create a plain JSObject which materializes the block scope for the specified | |
1317 // block context. | |
1318 static Handle<JSObject> MaterializeBlockScope(Isolate* isolate, | |
1319 Handle<ScopeInfo> scope_info, | |
1320 Handle<Context> context, | |
1321 FrameInspector* frame_inspector) { | |
1322 Handle<JSObject> block_scope = | |
1323 isolate->factory()->NewJSObject(isolate->object_function()); | |
1324 | |
1325 if (frame_inspector != nullptr) { | |
1326 MaterializeStackLocalsWithFrameInspector(isolate, block_scope, scope_info, | |
1327 frame_inspector); | |
1328 } | |
1329 | |
1330 if (!context.is_null()) { | |
1331 Handle<ScopeInfo> scope_info_from_context( | |
1332 ScopeInfo::cast(context->extension())); | |
1333 // Fill all context locals. | |
1334 ScopeInfo::CopyContextLocalsToScopeObject(scope_info_from_context, context, | |
1335 block_scope); | |
1336 } | |
1337 | |
1338 return block_scope; | |
1339 } | |
1340 | |
1341 | |
1342 // Create a plain JSObject which materializes the module scope for the specified | |
1343 // module context. | |
1344 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope( | |
1345 Isolate* isolate, Handle<Context> context) { | |
1346 DCHECK(context->IsModuleContext()); | |
1347 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); | |
1348 | |
1349 // Allocate and initialize a JSObject with all the members of the debugged | |
1350 // module. | |
1351 Handle<JSObject> module_scope = | |
1352 isolate->factory()->NewJSObject(isolate->object_function()); | |
1353 | |
1354 // Fill all context locals. | |
1355 ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, module_scope); | |
1356 | |
1357 return module_scope; | |
1358 } | |
1359 | |
1360 | |
1361 // Iterate over the actual scopes visible from a stack frame or from a closure. | |
1362 // The iteration proceeds from the innermost visible nested scope outwards. | |
1363 // All scopes are backed by an actual context except the local scope, | |
1364 // which is inserted "artificially" in the context chain. | |
1365 class ScopeIterator { | |
1366 public: | |
1367 enum ScopeType { | |
1368 ScopeTypeGlobal = 0, | |
1369 ScopeTypeLocal, | |
1370 ScopeTypeWith, | |
1371 ScopeTypeClosure, | |
1372 ScopeTypeCatch, | |
1373 ScopeTypeBlock, | |
1374 ScopeTypeScript, | |
1375 ScopeTypeModule | |
1376 }; | |
1377 | |
1378 ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector, | |
1379 bool ignore_nested_scopes = false) | |
1380 : isolate_(isolate), | |
1381 frame_inspector_(frame_inspector), | |
1382 nested_scope_chain_(4), | |
1383 seen_script_scope_(false), | |
1384 failed_(false) { | |
1385 if (!frame_inspector->GetContext()->IsContext() || | |
1386 !frame_inspector->GetFunction()->IsJSFunction()) { | |
1387 // Optimized frame, context or function cannot be materialized. Give up. | |
1388 return; | |
1389 } | |
1390 | |
1391 context_ = Handle<Context>(Context::cast(frame_inspector->GetContext())); | |
1392 | |
1393 // Catch the case when the debugger stops in an internal function. | |
1394 Handle<SharedFunctionInfo> shared_info(function()->shared()); | |
1395 Handle<ScopeInfo> scope_info(shared_info->scope_info()); | |
1396 if (shared_info->script() == isolate->heap()->undefined_value()) { | |
1397 while (context_->closure() == function()) { | |
1398 context_ = Handle<Context>(context_->previous(), isolate_); | |
1399 } | |
1400 return; | |
1401 } | |
1402 | |
1403 // Currently it takes too much time to find nested scopes due to script | |
1404 // parsing. Sometimes we want to run the ScopeIterator as fast as possible | |
1405 // (for example, while collecting async call stacks on every | |
1406 // addEventListener call), even if we drop some nested scopes. | |
1407 // Later we may optimize getting the nested scopes (cache the result?) | |
1408 // and include nested scopes into the "fast" iteration case as well. | |
1409 | |
1410 if (!ignore_nested_scopes && shared_info->HasDebugInfo()) { | |
1411 // The source position at return is always the end of the function, | |
1412 // which is not consistent with the current scope chain. Therefore all | |
1413 // nested with, catch and block contexts are skipped, and we can only | |
1414 // inspect the function scope. | |
1415 // This can only happen if we set a break point inside right before the | |
1416 // return, which requires a debug info to be available. | |
1417 Handle<DebugInfo> debug_info(shared_info->GetDebugInfo()); | |
1418 | |
1419 // PC points to the instruction after the current one, possibly a break | |
1420 // location as well. So the "- 1" to exclude it from the search. | |
1421 Address call_pc = frame()->pc() - 1; | |
1422 | |
1423 // Find the break point where execution has stopped. | |
1424 BreakLocation location = | |
1425 BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); | |
1426 | |
1427 ignore_nested_scopes = location.IsReturn(); | |
1428 } | |
1429 | |
1430 if (ignore_nested_scopes) { | |
1431 if (scope_info->HasContext()) { | |
1432 context_ = Handle<Context>(context_->declaration_context(), isolate_); | |
1433 } else { | |
1434 while (context_->closure() == function()) { | |
1435 context_ = Handle<Context>(context_->previous(), isolate_); | |
1436 } | |
1437 } | |
1438 if (scope_info->scope_type() == FUNCTION_SCOPE || | |
1439 scope_info->scope_type() == ARROW_SCOPE) { | |
1440 nested_scope_chain_.Add(scope_info); | |
1441 } | |
1442 } else { | |
1443 // Reparse the code and analyze the scopes. | |
1444 Handle<Script> script(Script::cast(shared_info->script())); | |
1445 Scope* scope = NULL; | |
1446 | |
1447 // Check whether we are in global, eval or function code. | |
1448 Handle<ScopeInfo> scope_info(shared_info->scope_info()); | |
1449 Zone zone; | |
1450 if (scope_info->scope_type() != FUNCTION_SCOPE && | |
1451 scope_info->scope_type() != ARROW_SCOPE) { | |
1452 // Global or eval code. | |
1453 ParseInfo info(&zone, script); | |
1454 if (scope_info->scope_type() == SCRIPT_SCOPE) { | |
1455 info.set_global(); | |
1456 } else { | |
1457 DCHECK(scope_info->scope_type() == EVAL_SCOPE); | |
1458 info.set_eval(); | |
1459 info.set_context(Handle<Context>(function()->context())); | |
1460 } | |
1461 if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) { | |
1462 scope = info.function()->scope(); | |
1463 } | |
1464 RetrieveScopeChain(scope, shared_info); | |
1465 } else { | |
1466 // Function code | |
1467 ParseInfo info(&zone, Handle<JSFunction>(function())); | |
1468 if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) { | |
1469 scope = info.function()->scope(); | |
1470 } | |
1471 RetrieveScopeChain(scope, shared_info); | |
1472 } | |
1473 } | |
1474 } | |
1475 | |
1476 ScopeIterator(Isolate* isolate, Handle<JSFunction> function) | |
1477 : isolate_(isolate), | |
1478 frame_inspector_(NULL), | |
1479 context_(function->context()), | |
1480 seen_script_scope_(false), | |
1481 failed_(false) { | |
1482 if (function->IsBuiltin()) context_ = Handle<Context>(); | |
1483 } | |
1484 | |
1485 // More scopes? | |
1486 bool Done() { | |
1487 DCHECK(!failed_); | |
1488 return context_.is_null(); | |
1489 } | |
1490 | |
1491 bool Failed() { return failed_; } | |
1492 | |
1493 // Move to the next scope. | |
1494 void Next() { | |
1495 DCHECK(!failed_); | |
1496 ScopeType scope_type = Type(); | |
1497 if (scope_type == ScopeTypeGlobal) { | |
1498 // The global scope is always the last in the chain. | |
1499 DCHECK(context_->IsNativeContext()); | |
1500 context_ = Handle<Context>(); | |
1501 return; | |
1502 } | |
1503 if (scope_type == ScopeTypeScript) { | |
1504 seen_script_scope_ = true; | |
1505 if (context_->IsScriptContext()) { | |
1506 context_ = Handle<Context>(context_->previous(), isolate_); | |
1507 } | |
1508 if (!nested_scope_chain_.is_empty()) { | |
1509 DCHECK_EQ(nested_scope_chain_.last()->scope_type(), SCRIPT_SCOPE); | |
1510 nested_scope_chain_.RemoveLast(); | |
1511 DCHECK(nested_scope_chain_.is_empty()); | |
1512 } | |
1513 CHECK(context_->IsNativeContext()); | |
1514 return; | |
1515 } | |
1516 if (nested_scope_chain_.is_empty()) { | |
1517 context_ = Handle<Context>(context_->previous(), isolate_); | |
1518 } else { | |
1519 if (nested_scope_chain_.last()->HasContext()) { | |
1520 DCHECK(context_->previous() != NULL); | |
1521 context_ = Handle<Context>(context_->previous(), isolate_); | |
1522 } | |
1523 nested_scope_chain_.RemoveLast(); | |
1524 } | |
1525 } | |
1526 | |
1527 // Return the type of the current scope. | |
1528 ScopeType Type() { | |
1529 DCHECK(!failed_); | |
1530 if (!nested_scope_chain_.is_empty()) { | |
1531 Handle<ScopeInfo> scope_info = nested_scope_chain_.last(); | |
1532 switch (scope_info->scope_type()) { | |
1533 case FUNCTION_SCOPE: | |
1534 case ARROW_SCOPE: | |
1535 DCHECK(context_->IsFunctionContext() || !scope_info->HasContext()); | |
1536 return ScopeTypeLocal; | |
1537 case MODULE_SCOPE: | |
1538 DCHECK(context_->IsModuleContext()); | |
1539 return ScopeTypeModule; | |
1540 case SCRIPT_SCOPE: | |
1541 DCHECK(context_->IsScriptContext() || context_->IsNativeContext()); | |
1542 return ScopeTypeScript; | |
1543 case WITH_SCOPE: | |
1544 DCHECK(context_->IsWithContext()); | |
1545 return ScopeTypeWith; | |
1546 case CATCH_SCOPE: | |
1547 DCHECK(context_->IsCatchContext()); | |
1548 return ScopeTypeCatch; | |
1549 case BLOCK_SCOPE: | |
1550 DCHECK(!scope_info->HasContext() || context_->IsBlockContext()); | |
1551 return ScopeTypeBlock; | |
1552 case EVAL_SCOPE: | |
1553 UNREACHABLE(); | |
1554 } | |
1555 } | |
1556 if (context_->IsNativeContext()) { | |
1557 DCHECK(context_->global_object()->IsGlobalObject()); | |
1558 // If we are at the native context and have not yet seen script scope, | |
1559 // fake it. | |
1560 return seen_script_scope_ ? ScopeTypeGlobal : ScopeTypeScript; | |
1561 } | |
1562 if (context_->IsFunctionContext()) { | |
1563 return ScopeTypeClosure; | |
1564 } | |
1565 if (context_->IsCatchContext()) { | |
1566 return ScopeTypeCatch; | |
1567 } | |
1568 if (context_->IsBlockContext()) { | |
1569 return ScopeTypeBlock; | |
1570 } | |
1571 if (context_->IsModuleContext()) { | |
1572 return ScopeTypeModule; | |
1573 } | |
1574 if (context_->IsScriptContext()) { | |
1575 return ScopeTypeScript; | |
1576 } | |
1577 DCHECK(context_->IsWithContext()); | |
1578 return ScopeTypeWith; | |
1579 } | |
1580 | |
1581 // Return the JavaScript object with the content of the current scope. | |
1582 MaybeHandle<JSObject> ScopeObject() { | |
1583 DCHECK(!failed_); | |
1584 switch (Type()) { | |
1585 case ScopeIterator::ScopeTypeGlobal: | |
1586 return Handle<JSObject>(CurrentContext()->global_object()); | |
1587 case ScopeIterator::ScopeTypeScript: | |
1588 return MaterializeScriptScope( | |
1589 Handle<GlobalObject>(CurrentContext()->global_object())); | |
1590 case ScopeIterator::ScopeTypeLocal: | |
1591 // Materialize the content of the local scope into a JSObject. | |
1592 DCHECK(nested_scope_chain_.length() == 1); | |
1593 return MaterializeLocalScope(isolate_, frame_inspector_); | |
1594 case ScopeIterator::ScopeTypeWith: | |
1595 // Return the with object. | |
1596 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); | |
1597 case ScopeIterator::ScopeTypeCatch: | |
1598 return MaterializeCatchScope(isolate_, CurrentContext()); | |
1599 case ScopeIterator::ScopeTypeClosure: | |
1600 // Materialize the content of the closure scope into a JSObject. | |
1601 return MaterializeClosure(isolate_, CurrentContext()); | |
1602 case ScopeIterator::ScopeTypeBlock: { | |
1603 if (!nested_scope_chain_.is_empty()) { | |
1604 // this is a block scope on the stack. | |
1605 Handle<ScopeInfo> scope_info = nested_scope_chain_.last(); | |
1606 Handle<Context> context = scope_info->HasContext() | |
1607 ? CurrentContext() | |
1608 : Handle<Context>::null(); | |
1609 return MaterializeBlockScope(isolate_, scope_info, context, | |
1610 frame_inspector_); | |
1611 } else { | |
1612 return MaterializeBlockScope(isolate_, Handle<ScopeInfo>::null(), | |
1613 CurrentContext(), nullptr); | |
1614 } | |
1615 } | |
1616 case ScopeIterator::ScopeTypeModule: | |
1617 return MaterializeModuleScope(isolate_, CurrentContext()); | |
1618 } | |
1619 UNREACHABLE(); | |
1620 return Handle<JSObject>(); | |
1621 } | |
1622 | |
1623 bool HasContext() { | |
1624 ScopeType type = Type(); | |
1625 if (type == ScopeTypeBlock || type == ScopeTypeLocal) { | |
1626 if (!nested_scope_chain_.is_empty()) { | |
1627 return nested_scope_chain_.last()->HasContext(); | |
1628 } | |
1629 } | |
1630 return true; | |
1631 } | |
1632 | |
1633 bool SetVariableValue(Handle<String> variable_name, | |
1634 Handle<Object> new_value) { | |
1635 DCHECK(!failed_); | |
1636 switch (Type()) { | |
1637 case ScopeIterator::ScopeTypeGlobal: | |
1638 break; | |
1639 case ScopeIterator::ScopeTypeLocal: | |
1640 return SetLocalVariableValue(isolate_, frame(), variable_name, | |
1641 new_value); | |
1642 case ScopeIterator::ScopeTypeWith: | |
1643 break; | |
1644 case ScopeIterator::ScopeTypeCatch: | |
1645 return SetCatchVariableValue(isolate_, CurrentContext(), variable_name, | |
1646 new_value); | |
1647 case ScopeIterator::ScopeTypeClosure: | |
1648 return SetClosureVariableValue(isolate_, CurrentContext(), | |
1649 variable_name, new_value); | |
1650 case ScopeIterator::ScopeTypeScript: | |
1651 return SetScriptVariableValue(CurrentContext(), variable_name, | |
1652 new_value); | |
1653 case ScopeIterator::ScopeTypeBlock: | |
1654 return SetBlockVariableValue( | |
1655 isolate_, HasContext() ? CurrentContext() : Handle<Context>::null(), | |
1656 CurrentScopeInfo(), frame(), variable_name, new_value); | |
1657 case ScopeIterator::ScopeTypeModule: | |
1658 // TODO(2399): should we implement it? | |
1659 break; | |
1660 } | |
1661 return false; | |
1662 } | |
1663 | |
1664 Handle<ScopeInfo> CurrentScopeInfo() { | |
1665 DCHECK(!failed_); | |
1666 if (!nested_scope_chain_.is_empty()) { | |
1667 return nested_scope_chain_.last(); | |
1668 } else if (context_->IsBlockContext()) { | |
1669 return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension())); | |
1670 } else if (context_->IsFunctionContext()) { | |
1671 return Handle<ScopeInfo>(context_->closure()->shared()->scope_info()); | |
1672 } | |
1673 return Handle<ScopeInfo>::null(); | |
1674 } | |
1675 | |
1676 // Return the context for this scope. For the local context there might not | |
1677 // be an actual context. | |
1678 Handle<Context> CurrentContext() { | |
1679 DCHECK(!failed_); | |
1680 if (Type() == ScopeTypeGlobal || Type() == ScopeTypeScript || | |
1681 nested_scope_chain_.is_empty()) { | |
1682 return context_; | |
1683 } else if (nested_scope_chain_.last()->HasContext()) { | |
1684 return context_; | |
1685 } else { | |
1686 return Handle<Context>(); | |
1687 } | |
1688 } | |
1689 | |
1690 #ifdef DEBUG | |
1691 // Debug print of the content of the current scope. | |
1692 void DebugPrint() { | |
1693 OFStream os(stdout); | |
1694 DCHECK(!failed_); | |
1695 switch (Type()) { | |
1696 case ScopeIterator::ScopeTypeGlobal: | |
1697 os << "Global:\n"; | |
1698 CurrentContext()->Print(os); | |
1699 break; | |
1700 | |
1701 case ScopeIterator::ScopeTypeLocal: { | |
1702 os << "Local:\n"; | |
1703 function()->shared()->scope_info()->Print(); | |
1704 if (!CurrentContext().is_null()) { | |
1705 CurrentContext()->Print(os); | |
1706 if (CurrentContext()->has_extension()) { | |
1707 Handle<Object> extension(CurrentContext()->extension(), isolate_); | |
1708 if (extension->IsJSContextExtensionObject()) { | |
1709 extension->Print(os); | |
1710 } | |
1711 } | |
1712 } | |
1713 break; | |
1714 } | |
1715 | |
1716 case ScopeIterator::ScopeTypeWith: | |
1717 os << "With:\n"; | |
1718 CurrentContext()->extension()->Print(os); | |
1719 break; | |
1720 | |
1721 case ScopeIterator::ScopeTypeCatch: | |
1722 os << "Catch:\n"; | |
1723 CurrentContext()->extension()->Print(os); | |
1724 CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print(os); | |
1725 break; | |
1726 | |
1727 case ScopeIterator::ScopeTypeClosure: | |
1728 os << "Closure:\n"; | |
1729 CurrentContext()->Print(os); | |
1730 if (CurrentContext()->has_extension()) { | |
1731 Handle<Object> extension(CurrentContext()->extension(), isolate_); | |
1732 if (extension->IsJSContextExtensionObject()) { | |
1733 extension->Print(os); | |
1734 } | |
1735 } | |
1736 break; | |
1737 | |
1738 case ScopeIterator::ScopeTypeScript: | |
1739 os << "Script:\n"; | |
1740 CurrentContext() | |
1741 ->global_object() | |
1742 ->native_context() | |
1743 ->script_context_table() | |
1744 ->Print(os); | |
1745 break; | |
1746 | |
1747 default: | |
1748 UNREACHABLE(); | |
1749 } | |
1750 PrintF("\n"); | |
1751 } | |
1752 #endif | |
1753 | |
1754 private: | |
1755 Isolate* isolate_; | |
1756 FrameInspector* const frame_inspector_; | |
1757 Handle<Context> context_; | |
1758 List<Handle<ScopeInfo> > nested_scope_chain_; | |
1759 bool seen_script_scope_; | |
1760 bool failed_; | |
1761 | |
1762 inline JavaScriptFrame* frame() { | |
1763 return frame_inspector_->GetArgumentsFrame(); | |
1764 } | |
1765 | |
1766 inline JSFunction* function() { | |
1767 return JSFunction::cast(frame_inspector_->GetFunction()); | |
1768 } | |
1769 | |
1770 void RetrieveScopeChain(Scope* scope, | |
1771 Handle<SharedFunctionInfo> shared_info) { | |
1772 if (scope != NULL) { | |
1773 int source_position = frame_inspector_->GetSourcePosition(); | |
1774 scope->GetNestedScopeChain(isolate_, &nested_scope_chain_, | |
1775 source_position); | |
1776 } else { | |
1777 // A failed reparse indicates that the preparser has diverged from the | |
1778 // parser or that the preparse data given to the initial parse has been | |
1779 // faulty. We fail in debug mode but in release mode we only provide the | |
1780 // information we get from the context chain but nothing about | |
1781 // completely stack allocated scopes or stack allocated locals. | |
1782 // Or it could be due to stack overflow. | |
1783 DCHECK(isolate_->has_pending_exception()); | |
1784 failed_ = true; | |
1785 } | |
1786 } | |
1787 | |
1788 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); | |
1789 }; | |
1790 | |
1791 | |
1792 RUNTIME_FUNCTION(Runtime_GetScopeCount) { | 743 RUNTIME_FUNCTION(Runtime_GetScopeCount) { |
1793 HandleScope scope(isolate); | 744 HandleScope scope(isolate); |
1794 DCHECK(args.length() == 2); | 745 DCHECK(args.length() == 2); |
1795 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | 746 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); |
1796 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); | 747 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); |
1797 | 748 |
1798 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | 749 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); |
1799 | 750 |
1800 // Get the frame where the debugging is performed. | 751 // Get the frame where the debugging is performed. |
1801 StackFrame::Id id = UnwrapFrameId(wrapped_id); | 752 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); |
1802 JavaScriptFrameIterator it(isolate, id); | 753 JavaScriptFrameIterator it(isolate, id); |
1803 JavaScriptFrame* frame = it.frame(); | 754 JavaScriptFrame* frame = it.frame(); |
1804 FrameInspector frame_inspector(frame, 0, isolate); | 755 FrameInspector frame_inspector(frame, 0, isolate); |
1805 | 756 |
1806 // Count the visible scopes. | 757 // Count the visible scopes. |
1807 int n = 0; | 758 int n = 0; |
1808 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) { | 759 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) { |
1809 n++; | 760 n++; |
1810 } | 761 } |
1811 | 762 |
1812 return Smi::FromInt(n); | 763 return Smi::FromInt(n); |
1813 } | 764 } |
1814 | 765 |
1815 | 766 |
1816 // Returns the list of step-in positions (text offset) in a function of the | 767 // Returns the list of step-in positions (text offset) in a function of the |
1817 // stack frame in a range from the current debug break position to the end | 768 // stack frame in a range from the current debug break position to the end |
1818 // of the corresponding statement. | 769 // of the corresponding statement. |
1819 RUNTIME_FUNCTION(Runtime_GetStepInPositions) { | 770 RUNTIME_FUNCTION(Runtime_GetStepInPositions) { |
1820 HandleScope scope(isolate); | 771 HandleScope scope(isolate); |
1821 DCHECK(args.length() == 2); | 772 DCHECK(args.length() == 2); |
1822 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | 773 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); |
1823 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); | 774 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); |
1824 | 775 |
1825 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | 776 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); |
1826 | 777 |
1827 // Get the frame where the debugging is performed. | 778 // Get the frame where the debugging is performed. |
1828 StackFrame::Id id = UnwrapFrameId(wrapped_id); | 779 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); |
1829 JavaScriptFrameIterator frame_it(isolate, id); | 780 JavaScriptFrameIterator frame_it(isolate, id); |
1830 RUNTIME_ASSERT(!frame_it.done()); | 781 RUNTIME_ASSERT(!frame_it.done()); |
1831 | 782 |
1832 List<int> positions; | 783 List<int> positions; |
1833 isolate->debug()->GetStepinPositions(frame_it.frame(), id, &positions); | 784 isolate->debug()->GetStepinPositions(frame_it.frame(), id, &positions); |
1834 Factory* factory = isolate->factory(); | 785 Factory* factory = isolate->factory(); |
1835 Handle<FixedArray> array = factory->NewFixedArray(positions.length()); | 786 Handle<FixedArray> array = factory->NewFixedArray(positions.length()); |
1836 for (int i = 0; i < positions.length(); ++i) { | 787 for (int i = 0; i < positions.length(); ++i) { |
1837 array->set(i, Smi::FromInt(positions[i])); | 788 array->set(i, Smi::FromInt(positions[i])); |
1838 } | 789 } |
1839 return *factory->NewJSArrayWithElements(array, FAST_SMI_ELEMENTS); | 790 return *factory->NewJSArrayWithElements(array, FAST_SMI_ELEMENTS); |
1840 } | 791 } |
1841 | 792 |
1842 | 793 |
1843 static const int kScopeDetailsTypeIndex = 0; | |
1844 static const int kScopeDetailsObjectIndex = 1; | |
1845 static const int kScopeDetailsSize = 2; | |
1846 | |
1847 | |
1848 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScopeDetails( | |
1849 Isolate* isolate, ScopeIterator* it) { | |
1850 // Calculate the size of the result. | |
1851 int details_size = kScopeDetailsSize; | |
1852 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); | |
1853 | |
1854 // Fill in scope details. | |
1855 details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type())); | |
1856 Handle<JSObject> scope_object; | |
1857 ASSIGN_RETURN_ON_EXCEPTION(isolate, scope_object, it->ScopeObject(), | |
1858 JSObject); | |
1859 details->set(kScopeDetailsObjectIndex, *scope_object); | |
1860 | |
1861 return isolate->factory()->NewJSArrayWithElements(details); | |
1862 } | |
1863 | |
1864 | |
1865 // Return an array with scope details | 794 // Return an array with scope details |
1866 // args[0]: number: break id | 795 // args[0]: number: break id |
1867 // args[1]: number: frame index | 796 // args[1]: number: frame index |
1868 // args[2]: number: inlined frame index | 797 // args[2]: number: inlined frame index |
1869 // args[3]: number: scope index | 798 // args[3]: number: scope index |
1870 // | 799 // |
1871 // The array returned contains the following information: | 800 // The array returned contains the following information: |
1872 // 0: Scope type | 801 // 0: Scope type |
1873 // 1: Scope object | 802 // 1: Scope object |
1874 RUNTIME_FUNCTION(Runtime_GetScopeDetails) { | 803 RUNTIME_FUNCTION(Runtime_GetScopeDetails) { |
1875 HandleScope scope(isolate); | 804 HandleScope scope(isolate); |
1876 DCHECK(args.length() == 4); | 805 DCHECK(args.length() == 4); |
1877 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | 806 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); |
1878 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); | 807 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); |
1879 | 808 |
1880 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | 809 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); |
1881 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); | 810 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); |
1882 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]); | 811 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]); |
1883 | 812 |
1884 // Get the frame where the debugging is performed. | 813 // Get the frame where the debugging is performed. |
1885 StackFrame::Id id = UnwrapFrameId(wrapped_id); | 814 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); |
1886 JavaScriptFrameIterator frame_it(isolate, id); | 815 JavaScriptFrameIterator frame_it(isolate, id); |
1887 JavaScriptFrame* frame = frame_it.frame(); | 816 JavaScriptFrame* frame = frame_it.frame(); |
1888 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); | 817 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); |
1889 | 818 |
1890 // Find the requested scope. | 819 // Find the requested scope. |
1891 int n = 0; | 820 int n = 0; |
1892 ScopeIterator it(isolate, &frame_inspector); | 821 ScopeIterator it(isolate, &frame_inspector); |
1893 for (; !it.Done() && n < index; it.Next()) { | 822 for (; !it.Done() && n < index; it.Next()) { |
1894 n++; | 823 n++; |
1895 } | 824 } |
1896 if (it.Done()) { | 825 if (it.Done()) { |
1897 return isolate->heap()->undefined_value(); | 826 return isolate->heap()->undefined_value(); |
1898 } | 827 } |
1899 Handle<JSObject> details; | 828 Handle<JSObject> details; |
1900 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, | 829 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, |
1901 MaterializeScopeDetails(isolate, &it)); | 830 it.MaterializeScopeDetails()); |
1902 return *details; | 831 return *details; |
1903 } | 832 } |
1904 | 833 |
1905 | 834 |
1906 // Return an array of scope details | 835 // Return an array of scope details |
1907 // args[0]: number: break id | 836 // args[0]: number: break id |
1908 // args[1]: number: frame index | 837 // args[1]: number: frame index |
1909 // args[2]: number: inlined frame index | 838 // args[2]: number: inlined frame index |
1910 // args[3]: boolean: ignore nested scopes | 839 // args[3]: boolean: ignore nested scopes |
1911 // | 840 // |
1912 // The array returned contains arrays with the following information: | 841 // The array returned contains arrays with the following information: |
1913 // 0: Scope type | 842 // 0: Scope type |
1914 // 1: Scope object | 843 // 1: Scope object |
1915 RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) { | 844 RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) { |
1916 HandleScope scope(isolate); | 845 HandleScope scope(isolate); |
1917 DCHECK(args.length() == 3 || args.length() == 4); | 846 DCHECK(args.length() == 3 || args.length() == 4); |
1918 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | 847 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); |
1919 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); | 848 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); |
1920 | 849 |
1921 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | 850 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); |
1922 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); | 851 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); |
1923 | 852 |
1924 bool ignore_nested_scopes = false; | 853 bool ignore_nested_scopes = false; |
1925 if (args.length() == 4) { | 854 if (args.length() == 4) { |
1926 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3); | 855 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3); |
1927 ignore_nested_scopes = flag; | 856 ignore_nested_scopes = flag; |
1928 } | 857 } |
1929 | 858 |
1930 // Get the frame where the debugging is performed. | 859 // Get the frame where the debugging is performed. |
1931 StackFrame::Id id = UnwrapFrameId(wrapped_id); | 860 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); |
1932 JavaScriptFrameIterator frame_it(isolate, id); | 861 JavaScriptFrameIterator frame_it(isolate, id); |
1933 JavaScriptFrame* frame = frame_it.frame(); | 862 JavaScriptFrame* frame = frame_it.frame(); |
1934 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); | 863 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); |
1935 | 864 |
1936 List<Handle<JSObject> > result(4); | 865 List<Handle<JSObject> > result(4); |
1937 ScopeIterator it(isolate, &frame_inspector, ignore_nested_scopes); | 866 ScopeIterator it(isolate, &frame_inspector, ignore_nested_scopes); |
1938 for (; !it.Done(); it.Next()) { | 867 for (; !it.Done(); it.Next()) { |
1939 Handle<JSObject> details; | 868 Handle<JSObject> details; |
1940 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, | 869 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, |
1941 MaterializeScopeDetails(isolate, &it)); | 870 it.MaterializeScopeDetails()); |
1942 result.Add(details); | 871 result.Add(details); |
1943 } | 872 } |
1944 | 873 |
1945 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length()); | 874 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length()); |
1946 for (int i = 0; i < result.length(); ++i) { | 875 for (int i = 0; i < result.length(); ++i) { |
1947 array->set(i, *result[i]); | 876 array->set(i, *result[i]); |
1948 } | 877 } |
1949 return *isolate->factory()->NewJSArrayWithElements(array); | 878 return *isolate->factory()->NewJSArrayWithElements(array); |
1950 } | 879 } |
1951 | 880 |
(...skipping 28 matching lines...) Expand all Loading... |
1980 ScopeIterator it(isolate, fun); | 909 ScopeIterator it(isolate, fun); |
1981 for (; !it.Done() && n < index; it.Next()) { | 910 for (; !it.Done() && n < index; it.Next()) { |
1982 n++; | 911 n++; |
1983 } | 912 } |
1984 if (it.Done()) { | 913 if (it.Done()) { |
1985 return isolate->heap()->undefined_value(); | 914 return isolate->heap()->undefined_value(); |
1986 } | 915 } |
1987 | 916 |
1988 Handle<JSObject> details; | 917 Handle<JSObject> details; |
1989 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, | 918 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details, |
1990 MaterializeScopeDetails(isolate, &it)); | 919 it.MaterializeScopeDetails()); |
1991 return *details; | 920 return *details; |
1992 } | 921 } |
1993 | 922 |
1994 | 923 |
1995 static bool SetScopeVariableValue(ScopeIterator* it, int index, | 924 static bool SetScopeVariableValue(ScopeIterator* it, int index, |
1996 Handle<String> variable_name, | 925 Handle<String> variable_name, |
1997 Handle<Object> new_value) { | 926 Handle<Object> new_value) { |
1998 for (int n = 0; !it->Done() && n < index; it->Next()) { | 927 for (int n = 0; !it->Done() && n < index; it->Next()) { |
1999 n++; | 928 n++; |
2000 } | 929 } |
(...skipping 24 matching lines...) Expand all Loading... |
2025 | 954 |
2026 bool res; | 955 bool res; |
2027 if (args[0]->IsNumber()) { | 956 if (args[0]->IsNumber()) { |
2028 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | 957 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); |
2029 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); | 958 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); |
2030 | 959 |
2031 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | 960 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); |
2032 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); | 961 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); |
2033 | 962 |
2034 // Get the frame where the debugging is performed. | 963 // Get the frame where the debugging is performed. |
2035 StackFrame::Id id = UnwrapFrameId(wrapped_id); | 964 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); |
2036 JavaScriptFrameIterator frame_it(isolate, id); | 965 JavaScriptFrameIterator frame_it(isolate, id); |
2037 JavaScriptFrame* frame = frame_it.frame(); | 966 JavaScriptFrame* frame = frame_it.frame(); |
2038 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); | 967 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); |
2039 | 968 |
2040 ScopeIterator it(isolate, &frame_inspector); | 969 ScopeIterator it(isolate, &frame_inspector); |
2041 res = SetScopeVariableValue(&it, index, variable_name, new_value); | 970 res = SetScopeVariableValue(&it, index, variable_name, new_value); |
2042 } else { | 971 } else { |
2043 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); | 972 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); |
2044 ScopeIterator it(isolate, fun); | 973 ScopeIterator it(isolate, fun); |
2045 res = SetScopeVariableValue(&it, index, variable_name, new_value); | 974 res = SetScopeVariableValue(&it, index, variable_name, new_value); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2298 if (!args[1]->IsNumber() || !args[2]->IsNumber()) { | 1227 if (!args[1]->IsNumber() || !args[2]->IsNumber()) { |
2299 return isolate->Throw(isolate->heap()->illegal_argument_string()); | 1228 return isolate->Throw(isolate->heap()->illegal_argument_string()); |
2300 } | 1229 } |
2301 | 1230 |
2302 CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]); | 1231 CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]); |
2303 | 1232 |
2304 StackFrame::Id frame_id; | 1233 StackFrame::Id frame_id; |
2305 if (wrapped_frame_id == 0) { | 1234 if (wrapped_frame_id == 0) { |
2306 frame_id = StackFrame::NO_ID; | 1235 frame_id = StackFrame::NO_ID; |
2307 } else { | 1236 } else { |
2308 frame_id = UnwrapFrameId(wrapped_frame_id); | 1237 frame_id = DebugFrameHelper::UnwrapFrameId(wrapped_frame_id); |
2309 } | 1238 } |
2310 | 1239 |
2311 // Get the step action and check validity. | 1240 // Get the step action and check validity. |
2312 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1])); | 1241 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1])); |
2313 if (step_action != StepIn && step_action != StepNext && | 1242 if (step_action != StepIn && step_action != StepNext && |
2314 step_action != StepOut && step_action != StepInMin && | 1243 step_action != StepOut && step_action != StepInMin && |
2315 step_action != StepMin && step_action != StepFrame) { | 1244 step_action != StepMin && step_action != StepFrame) { |
2316 return isolate->Throw(isolate->heap()->illegal_argument_string()); | 1245 return isolate->Throw(isolate->heap()->illegal_argument_string()); |
2317 } | 1246 } |
2318 | 1247 |
(...skipping 21 matching lines...) Expand all Loading... |
2340 // Clear all stepping set by PrepareStep. | 1269 // Clear all stepping set by PrepareStep. |
2341 RUNTIME_FUNCTION(Runtime_ClearStepping) { | 1270 RUNTIME_FUNCTION(Runtime_ClearStepping) { |
2342 HandleScope scope(isolate); | 1271 HandleScope scope(isolate); |
2343 DCHECK(args.length() == 0); | 1272 DCHECK(args.length() == 0); |
2344 RUNTIME_ASSERT(isolate->debug()->is_active()); | 1273 RUNTIME_ASSERT(isolate->debug()->is_active()); |
2345 isolate->debug()->ClearStepping(); | 1274 isolate->debug()->ClearStepping(); |
2346 return isolate->heap()->undefined_value(); | 1275 return isolate->heap()->undefined_value(); |
2347 } | 1276 } |
2348 | 1277 |
2349 | 1278 |
2350 // Helper function to find or create the arguments object for | |
2351 // Runtime_DebugEvaluate. | |
2352 static void MaterializeArgumentsObject(Isolate* isolate, | |
2353 Handle<JSObject> target, | |
2354 Handle<JSFunction> function) { | |
2355 // Do not materialize the arguments object for eval or top-level code. | |
2356 // Skip if "arguments" is already taken. | |
2357 if (!function->shared()->is_function()) return; | |
2358 Maybe<bool> maybe = JSReceiver::HasOwnProperty( | |
2359 target, isolate->factory()->arguments_string()); | |
2360 DCHECK(maybe.IsJust()); | |
2361 if (maybe.FromJust()) return; | |
2362 | |
2363 // FunctionGetArguments can't throw an exception. | |
2364 Handle<JSObject> arguments = | |
2365 Handle<JSObject>::cast(Accessors::FunctionGetArguments(function)); | |
2366 Handle<String> arguments_str = isolate->factory()->arguments_string(); | |
2367 JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments, | |
2368 NONE).Check(); | |
2369 } | |
2370 | |
2371 | |
2372 // Compile and evaluate source for the given context. | |
2373 static MaybeHandle<Object> DebugEvaluate(Isolate* isolate, | |
2374 Handle<SharedFunctionInfo> outer_info, | |
2375 Handle<Context> context, | |
2376 Handle<Object> context_extension, | |
2377 Handle<Object> receiver, | |
2378 Handle<String> source) { | |
2379 if (context_extension->IsJSObject()) { | |
2380 Handle<JSObject> extension = Handle<JSObject>::cast(context_extension); | |
2381 Handle<JSFunction> closure(context->closure(), isolate); | |
2382 context = isolate->factory()->NewWithContext(closure, context, extension); | |
2383 } | |
2384 | |
2385 Handle<JSFunction> eval_fun; | |
2386 ASSIGN_RETURN_ON_EXCEPTION(isolate, eval_fun, | |
2387 Compiler::GetFunctionFromEval( | |
2388 source, outer_info, context, SLOPPY, | |
2389 NO_PARSE_RESTRICTION, RelocInfo::kNoPosition), | |
2390 Object); | |
2391 | |
2392 Handle<Object> result; | |
2393 ASSIGN_RETURN_ON_EXCEPTION( | |
2394 isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL), | |
2395 Object); | |
2396 | |
2397 // Skip the global proxy as it has no properties and always delegates to the | |
2398 // real global object. | |
2399 if (result->IsJSGlobalProxy()) { | |
2400 PrototypeIterator iter(isolate, result); | |
2401 // TODO(verwaest): This will crash when the global proxy is detached. | |
2402 result = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
2403 } | |
2404 | |
2405 return result; | |
2406 } | |
2407 | |
2408 | |
2409 static Handle<JSObject> NewJSObjectWithNullProto(Isolate* isolate) { | |
2410 Handle<JSObject> result = | |
2411 isolate->factory()->NewJSObject(isolate->object_function()); | |
2412 Handle<Map> new_map = | |
2413 Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto"); | |
2414 Map::SetPrototype(new_map, isolate->factory()->null_value()); | |
2415 JSObject::MigrateToMap(result, new_map); | |
2416 return result; | |
2417 } | |
2418 | |
2419 | |
2420 namespace { | |
2421 | |
2422 // This class builds a context chain for evaluation of expressions | |
2423 // in debugger. | |
2424 // The scope chain leading up to a breakpoint where evaluation occurs | |
2425 // looks like: | |
2426 // - [a mix of with, catch and block scopes] | |
2427 // - [function stack + context] | |
2428 // - [outer context] | |
2429 // The builder materializes all stack variables into properties of objects; | |
2430 // the expression is then evaluated as if it is inside a series of 'with' | |
2431 // statements using those objects. To this end, the builder builds a new | |
2432 // context chain, based on a scope chain: | |
2433 // - every With and Catch scope begets a cloned context | |
2434 // - Block scope begets one or two contexts: | |
2435 // - if a block has context-allocated varaibles, its context is cloned | |
2436 // - stack locals are materizalized as a With context | |
2437 // - Local scope begets a With context for materizalized locals, chained to | |
2438 // original function context. Original function context is the end of | |
2439 // the chain. | |
2440 class EvaluationContextBuilder { | |
2441 public: | |
2442 EvaluationContextBuilder(Isolate* isolate, JavaScriptFrame* frame, | |
2443 int inlined_jsframe_index) | |
2444 : isolate_(isolate), | |
2445 frame_(frame), | |
2446 inlined_jsframe_index_(inlined_jsframe_index) { | |
2447 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); | |
2448 Handle<JSFunction> function = | |
2449 handle(JSFunction::cast(frame_inspector.GetFunction())); | |
2450 Handle<Context> outer_context = handle(function->context(), isolate); | |
2451 outer_info_ = handle(function->shared()); | |
2452 Handle<Context> inner_context; | |
2453 | |
2454 bool stop = false; | |
2455 for (ScopeIterator it(isolate, &frame_inspector); | |
2456 !it.Failed() && !it.Done() && !stop; it.Next()) { | |
2457 ScopeIterator::ScopeType scope_type = it.Type(); | |
2458 | |
2459 if (scope_type == ScopeIterator::ScopeTypeLocal) { | |
2460 Handle<Context> parent_context = | |
2461 it.HasContext() ? it.CurrentContext() : outer_context; | |
2462 | |
2463 // The "this" binding, if any, can't be bound via "with". If we need | |
2464 // to, add another node onto the outer context to bind "this". | |
2465 parent_context = | |
2466 MaterializeReceiver(isolate, parent_context, function, frame); | |
2467 | |
2468 Handle<JSObject> materialized_function = | |
2469 NewJSObjectWithNullProto(isolate); | |
2470 | |
2471 MaterializeStackLocalsWithFrameInspector(isolate, materialized_function, | |
2472 function, &frame_inspector); | |
2473 | |
2474 MaterializeArgumentsObject(isolate, materialized_function, function); | |
2475 | |
2476 Handle<Context> with_context = isolate->factory()->NewWithContext( | |
2477 function, parent_context, materialized_function); | |
2478 | |
2479 ContextChainElement context_chain_element; | |
2480 context_chain_element.original_context = it.CurrentContext(); | |
2481 context_chain_element.materialized_object = materialized_function; | |
2482 context_chain_element.scope_info = it.CurrentScopeInfo(); | |
2483 context_chain_.Add(context_chain_element); | |
2484 | |
2485 stop = true; | |
2486 RecordContextsInChain(&inner_context, with_context, with_context); | |
2487 } else if (scope_type == ScopeIterator::ScopeTypeCatch || | |
2488 scope_type == ScopeIterator::ScopeTypeWith) { | |
2489 Handle<Context> cloned_context = | |
2490 Handle<Context>::cast(FixedArray::CopySize( | |
2491 it.CurrentContext(), it.CurrentContext()->length())); | |
2492 | |
2493 ContextChainElement context_chain_element; | |
2494 context_chain_element.original_context = it.CurrentContext(); | |
2495 context_chain_element.cloned_context = cloned_context; | |
2496 context_chain_.Add(context_chain_element); | |
2497 | |
2498 RecordContextsInChain(&inner_context, cloned_context, cloned_context); | |
2499 } else if (scope_type == ScopeIterator::ScopeTypeBlock) { | |
2500 Handle<JSObject> materialized_object = | |
2501 NewJSObjectWithNullProto(isolate); | |
2502 MaterializeStackLocalsWithFrameInspector(isolate, materialized_object, | |
2503 it.CurrentScopeInfo(), | |
2504 &frame_inspector); | |
2505 if (it.HasContext()) { | |
2506 Handle<Context> cloned_context = | |
2507 Handle<Context>::cast(FixedArray::CopySize( | |
2508 it.CurrentContext(), it.CurrentContext()->length())); | |
2509 Handle<Context> with_context = isolate->factory()->NewWithContext( | |
2510 function, cloned_context, materialized_object); | |
2511 | |
2512 ContextChainElement context_chain_element; | |
2513 context_chain_element.original_context = it.CurrentContext(); | |
2514 context_chain_element.cloned_context = cloned_context; | |
2515 context_chain_element.materialized_object = materialized_object; | |
2516 context_chain_element.scope_info = it.CurrentScopeInfo(); | |
2517 context_chain_.Add(context_chain_element); | |
2518 | |
2519 RecordContextsInChain(&inner_context, cloned_context, with_context); | |
2520 } else { | |
2521 Handle<Context> with_context = isolate->factory()->NewWithContext( | |
2522 function, outer_context, materialized_object); | |
2523 | |
2524 ContextChainElement context_chain_element; | |
2525 context_chain_element.materialized_object = materialized_object; | |
2526 context_chain_element.scope_info = it.CurrentScopeInfo(); | |
2527 context_chain_.Add(context_chain_element); | |
2528 | |
2529 RecordContextsInChain(&inner_context, with_context, with_context); | |
2530 } | |
2531 } else { | |
2532 stop = true; | |
2533 } | |
2534 } | |
2535 if (innermost_context_.is_null()) { | |
2536 innermost_context_ = outer_context; | |
2537 } | |
2538 DCHECK(!innermost_context_.is_null()); | |
2539 } | |
2540 | |
2541 void UpdateVariables() { | |
2542 for (int i = 0; i < context_chain_.length(); i++) { | |
2543 ContextChainElement element = context_chain_[i]; | |
2544 if (!element.original_context.is_null() && | |
2545 !element.cloned_context.is_null()) { | |
2546 Handle<Context> cloned_context = element.cloned_context; | |
2547 cloned_context->CopyTo( | |
2548 Context::MIN_CONTEXT_SLOTS, *element.original_context, | |
2549 Context::MIN_CONTEXT_SLOTS, | |
2550 cloned_context->length() - Context::MIN_CONTEXT_SLOTS); | |
2551 } | |
2552 if (!element.materialized_object.is_null()) { | |
2553 // Write back potential changes to materialized stack locals to the | |
2554 // stack. | |
2555 UpdateStackLocalsFromMaterializedObject( | |
2556 isolate_, element.materialized_object, element.scope_info, frame_, | |
2557 inlined_jsframe_index_); | |
2558 } | |
2559 } | |
2560 } | |
2561 | |
2562 Handle<Context> innermost_context() const { return innermost_context_; } | |
2563 Handle<SharedFunctionInfo> outer_info() const { return outer_info_; } | |
2564 | |
2565 private: | |
2566 struct ContextChainElement { | |
2567 Handle<Context> original_context; | |
2568 Handle<Context> cloned_context; | |
2569 Handle<JSObject> materialized_object; | |
2570 Handle<ScopeInfo> scope_info; | |
2571 }; | |
2572 | |
2573 void RecordContextsInChain(Handle<Context>* inner_context, | |
2574 Handle<Context> first, Handle<Context> last) { | |
2575 if (!inner_context->is_null()) { | |
2576 (*inner_context)->set_previous(*last); | |
2577 } else { | |
2578 innermost_context_ = last; | |
2579 } | |
2580 *inner_context = first; | |
2581 } | |
2582 | |
2583 Handle<SharedFunctionInfo> outer_info_; | |
2584 Handle<Context> innermost_context_; | |
2585 List<ContextChainElement> context_chain_; | |
2586 Isolate* isolate_; | |
2587 JavaScriptFrame* frame_; | |
2588 int inlined_jsframe_index_; | |
2589 }; | |
2590 } | |
2591 | |
2592 | |
2593 // Evaluate a piece of JavaScript in the context of a stack frame for | |
2594 // debugging. Things that need special attention are: | |
2595 // - Parameters and stack-allocated locals need to be materialized. Altered | |
2596 // values need to be written back to the stack afterwards. | |
2597 // - The arguments object needs to materialized. | |
2598 RUNTIME_FUNCTION(Runtime_DebugEvaluate) { | 1279 RUNTIME_FUNCTION(Runtime_DebugEvaluate) { |
2599 HandleScope scope(isolate); | 1280 HandleScope scope(isolate); |
2600 | 1281 |
2601 // Check the execution state and decode arguments frame and source to be | 1282 // Check the execution state and decode arguments frame and source to be |
2602 // evaluated. | 1283 // evaluated. |
2603 DCHECK(args.length() == 6); | 1284 DCHECK(args.length() == 6); |
2604 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | 1285 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); |
2605 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); | 1286 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); |
2606 | 1287 |
2607 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); | 1288 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); |
2608 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); | 1289 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); |
2609 CONVERT_ARG_HANDLE_CHECKED(String, source, 3); | 1290 CONVERT_ARG_HANDLE_CHECKED(String, source, 3); |
2610 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4); | 1291 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4); |
2611 CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 5); | 1292 CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 5); |
2612 | 1293 |
2613 // Handle the processing of break. | 1294 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); |
2614 DisableBreak disable_break_scope(isolate->debug(), disable_break); | |
2615 | |
2616 // Get the frame where the debugging is performed. | |
2617 StackFrame::Id id = UnwrapFrameId(wrapped_id); | |
2618 JavaScriptFrameIterator it(isolate, id); | |
2619 JavaScriptFrame* frame = it.frame(); | |
2620 | |
2621 // Traverse the saved contexts chain to find the active context for the | |
2622 // selected frame. | |
2623 SaveContext* save = FindSavedContextForFrame(isolate, frame); | |
2624 | |
2625 SaveContext savex(isolate); | |
2626 isolate->set_context(*(save->context())); | |
2627 | |
2628 // Materialize stack locals and the arguments object. | |
2629 | |
2630 EvaluationContextBuilder context_builder(isolate, frame, | |
2631 inlined_jsframe_index); | |
2632 if (isolate->has_pending_exception()) { | |
2633 return isolate->heap()->exception(); | |
2634 } | |
2635 | |
2636 | |
2637 Handle<Object> receiver(frame->receiver(), isolate); | |
2638 MaybeHandle<Object> maybe_result = DebugEvaluate( | |
2639 isolate, context_builder.outer_info(), | |
2640 context_builder.innermost_context(), context_extension, receiver, source); | |
2641 | 1295 |
2642 Handle<Object> result; | 1296 Handle<Object> result; |
2643 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); | 1297 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2644 context_builder.UpdateVariables(); | 1298 isolate, result, |
| 1299 DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source, |
| 1300 disable_break, context_extension)); |
2645 return *result; | 1301 return *result; |
2646 } | 1302 } |
2647 | 1303 |
2648 | 1304 |
2649 static inline bool IsDebugContext(Isolate* isolate, Context* context) { | |
2650 // Try to unwrap script context if it exist. | |
2651 if (context->IsScriptContext()) context = context->previous(); | |
2652 DCHECK_NOT_NULL(context); | |
2653 return context == *isolate->debug()->debug_context(); | |
2654 } | |
2655 | |
2656 | |
2657 RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) { | 1305 RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) { |
2658 HandleScope scope(isolate); | 1306 HandleScope scope(isolate); |
2659 | 1307 |
2660 // Check the execution state and decode arguments frame and source to be | 1308 // Check the execution state and decode arguments frame and source to be |
2661 // evaluated. | 1309 // evaluated. |
2662 DCHECK(args.length() == 4); | 1310 DCHECK(args.length() == 4); |
2663 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); | 1311 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); |
2664 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); | 1312 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id)); |
2665 | 1313 |
2666 CONVERT_ARG_HANDLE_CHECKED(String, source, 1); | 1314 CONVERT_ARG_HANDLE_CHECKED(String, source, 1); |
2667 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2); | 1315 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2); |
2668 CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 3); | 1316 CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 3); |
2669 | 1317 |
2670 // Handle the processing of break. | |
2671 DisableBreak disable_break_scope(isolate->debug(), disable_break); | |
2672 | |
2673 // Enter the top context from before the debugger was invoked. | |
2674 SaveContext save(isolate); | |
2675 SaveContext* top = &save; | |
2676 while (top != NULL && IsDebugContext(isolate, *top->context())) { | |
2677 top = top->prev(); | |
2678 } | |
2679 if (top != NULL) { | |
2680 isolate->set_context(*top->context()); | |
2681 } | |
2682 | |
2683 // Get the native context now set to the top context from before the | |
2684 // debugger was invoked. | |
2685 Handle<Context> context = isolate->native_context(); | |
2686 Handle<JSObject> receiver(context->global_proxy()); | |
2687 Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate); | |
2688 Handle<Object> result; | 1318 Handle<Object> result; |
2689 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1319 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2690 isolate, result, DebugEvaluate(isolate, outer_info, context, | 1320 isolate, result, |
2691 context_extension, receiver, source)); | 1321 DebugEvaluate::Global(isolate, source, disable_break, context_extension)); |
2692 return *result; | 1322 return *result; |
2693 } | 1323 } |
2694 | 1324 |
2695 | 1325 |
2696 RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) { | 1326 RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) { |
2697 HandleScope scope(isolate); | 1327 HandleScope scope(isolate); |
2698 DCHECK(args.length() == 0); | 1328 DCHECK(args.length() == 0); |
2699 RUNTIME_ASSERT(isolate->debug()->is_active()); | 1329 RUNTIME_ASSERT(isolate->debug()->is_active()); |
2700 | 1330 |
2701 Handle<FixedArray> instances; | 1331 Handle<FixedArray> instances; |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3191 return *isolate->factory()->undefined_value(); | 1821 return *isolate->factory()->undefined_value(); |
3192 } | 1822 } |
3193 | 1823 |
3194 | 1824 |
3195 RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) { | 1825 RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) { |
3196 UNIMPLEMENTED(); | 1826 UNIMPLEMENTED(); |
3197 return NULL; | 1827 return NULL; |
3198 } | 1828 } |
3199 } // namespace internal | 1829 } // namespace internal |
3200 } // namespace v8 | 1830 } // namespace v8 |
OLD | NEW |