Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(296)

Side by Side Diff: src/runtime/runtime-debug.cc

Issue 1264993002: Debugger: refactor ScopeIterator, FrameInspector and DebugEvaluate. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: readd include Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698