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" | 7 #include "src/accessors.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
680 MaybeAssignedFlag maybe_assigned_flag; | 680 MaybeAssignedFlag maybe_assigned_flag; |
681 return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag, | 681 return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag, |
682 &maybe_assigned_flag) != -1; | 682 &maybe_assigned_flag) != -1; |
683 } | 683 } |
684 | 684 |
685 | 685 |
686 // Create a plain JSObject which materializes the local scope for the specified | 686 // Create a plain JSObject which materializes the local scope for the specified |
687 // frame. | 687 // frame. |
688 MUST_USE_RESULT | 688 MUST_USE_RESULT |
689 static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector( | 689 static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector( |
690 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, | 690 Isolate* isolate, Handle<JSObject> target, Handle<ScopeInfo> scope_info, |
691 FrameInspector* frame_inspector) { | 691 FrameInspector* frame_inspector) { |
692 Handle<SharedFunctionInfo> shared(function->shared()); | |
693 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
694 | |
695 // First fill all parameters. | 692 // First fill all parameters. |
696 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | 693 for (int i = 0; i < scope_info->ParameterCount(); ++i) { |
697 // Do not materialize the parameter if it is shadowed by a context local. | 694 // Do not materialize the parameter if it is shadowed by a context local. |
698 Handle<String> name(scope_info->ParameterName(i)); | 695 Handle<String> name(scope_info->ParameterName(i)); |
699 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; | 696 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; |
700 | 697 |
698 DCHECK(frame_inspector != nullptr); | |
699 | |
701 HandleScope scope(isolate); | 700 HandleScope scope(isolate); |
702 Handle<Object> value(i < frame_inspector->GetParametersCount() | 701 Handle<Object> value(i < frame_inspector->GetParametersCount() |
703 ? frame_inspector->GetParameter(i) | 702 ? frame_inspector->GetParameter(i) |
704 : isolate->heap()->undefined_value(), | 703 : isolate->heap()->undefined_value(), |
705 isolate); | 704 isolate); |
706 DCHECK(!value->IsTheHole()); | 705 DCHECK(!value->IsTheHole()); |
707 | 706 |
708 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty( | 707 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty( |
709 isolate, target, name, value, SLOPPY), | 708 isolate, target, name, value, SLOPPY), |
710 JSObject); | 709 JSObject); |
711 } | 710 } |
712 | 711 |
713 // Second fill all stack locals. | 712 // Second fill all stack locals. |
714 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | 713 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { |
715 if (scope_info->LocalIsSynthetic(i)) continue; | 714 if (scope_info->LocalIsSynthetic(i)) continue; |
716 Handle<String> name(scope_info->StackLocalName(i)); | 715 Handle<String> name(scope_info->StackLocalName(i)); |
717 Handle<Object> value(frame_inspector->GetExpression(i), isolate); | 716 Handle<Object> value( |
718 if (value->IsTheHole()) continue; | 717 frame_inspector->GetExpression(scope_info->StackLocalIndex(i)), |
718 isolate); | |
719 if (value->IsTheHole()) { | |
720 value = isolate->factory()->undefined_value(); | |
rossberg
2015/04/17 15:16:27
Is this safe? Isn't the implication that you can n
Dmitry Lomov (no reviews)
2015/04/17 15:21:54
If we do not do that, shadowing will not work corr
rossberg
2015/04/17 15:26:07
I see. Yes, preventing the copying back sounds goo
Dmitry Lomov (no reviews)
2015/04/20 11:53:20
We actually already have the check (line 770)
| |
721 } | |
719 | 722 |
720 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty( | 723 RETURN_ON_EXCEPTION(isolate, Runtime::SetObjectProperty( |
721 isolate, target, name, value, SLOPPY), | 724 isolate, target, name, value, SLOPPY), |
722 JSObject); | 725 JSObject); |
723 } | 726 } |
724 | 727 |
725 return target; | 728 return target; |
726 } | 729 } |
727 | 730 |
731 MUST_USE_RESULT | |
732 static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector( | |
733 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, | |
734 FrameInspector* frame_inspector) { | |
735 Handle<SharedFunctionInfo> shared(function->shared()); | |
736 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
728 | 737 |
729 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate, | 738 return MaterializeStackLocalsWithFrameInspector(isolate, target, scope_info, |
730 Handle<JSObject> target, | 739 frame_inspector); |
731 Handle<JSFunction> function, | 740 } |
732 JavaScriptFrame* frame, | 741 |
733 int inlined_jsframe_index) { | 742 |
743 static void UpdateStackLocalsFromMaterializedObject( | |
744 Isolate* isolate, Handle<JSObject> target, Handle<ScopeInfo> scope_info, | |
745 JavaScriptFrame* frame, int inlined_jsframe_index) { | |
734 if (inlined_jsframe_index != 0 || frame->is_optimized()) { | 746 if (inlined_jsframe_index != 0 || frame->is_optimized()) { |
735 // Optimized frames are not supported. | 747 // Optimized frames are not supported. |
736 // TODO(yangguo): make sure all code deoptimized when debugger is active | 748 // TODO(yangguo): make sure all code deoptimized when debugger is active |
737 // and assert that this cannot happen. | 749 // and assert that this cannot happen. |
738 return; | 750 return; |
739 } | 751 } |
740 | 752 |
741 Handle<SharedFunctionInfo> shared(function->shared()); | |
742 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
743 | |
744 // Parameters. | 753 // Parameters. |
745 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | 754 for (int i = 0; i < scope_info->ParameterCount(); ++i) { |
746 // Shadowed parameters were not materialized. | 755 // Shadowed parameters were not materialized. |
747 Handle<String> name(scope_info->ParameterName(i)); | 756 Handle<String> name(scope_info->ParameterName(i)); |
748 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; | 757 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; |
749 | 758 |
750 DCHECK(!frame->GetParameter(i)->IsTheHole()); | 759 DCHECK(!frame->GetParameter(i)->IsTheHole()); |
751 HandleScope scope(isolate); | 760 HandleScope scope(isolate); |
752 Handle<Object> value = | 761 Handle<Object> value = |
753 Object::GetPropertyOrElement(target, name).ToHandleChecked(); | 762 Object::GetPropertyOrElement(target, name).ToHandleChecked(); |
754 frame->SetParameterValue(i, *value); | 763 frame->SetParameterValue(i, *value); |
755 } | 764 } |
756 | 765 |
757 // Stack locals. | 766 // Stack locals. |
758 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | 767 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { |
759 if (scope_info->LocalIsSynthetic(i)) continue; | 768 if (scope_info->LocalIsSynthetic(i)) continue; |
760 if (frame->GetExpression(i)->IsTheHole()) continue; | 769 int index = scope_info->StackLocalIndex(i); |
770 if (frame->GetExpression(index)->IsTheHole()) continue; | |
761 HandleScope scope(isolate); | 771 HandleScope scope(isolate); |
762 Handle<Object> value = Object::GetPropertyOrElement( | 772 Handle<Object> value = Object::GetPropertyOrElement( |
763 target, handle(scope_info->StackLocalName(i), | 773 target, handle(scope_info->StackLocalName(i), |
764 isolate)).ToHandleChecked(); | 774 isolate)).ToHandleChecked(); |
765 frame->SetExpression(i, *value); | 775 frame->SetExpression(index, *value); |
766 } | 776 } |
767 } | 777 } |
768 | 778 |
769 | 779 |
770 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext( | 780 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext( |
771 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, | 781 Isolate* isolate, Handle<JSObject> target, Handle<JSFunction> function, |
772 JavaScriptFrame* frame) { | 782 JavaScriptFrame* frame) { |
773 HandleScope scope(isolate); | 783 HandleScope scope(isolate); |
774 Handle<SharedFunctionInfo> shared(function->shared()); | 784 Handle<SharedFunctionInfo> shared(function->shared()); |
775 Handle<ScopeInfo> scope_info(shared->scope_info()); | 785 Handle<ScopeInfo> scope_info(shared->scope_info()); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
897 frame->SetParameterValue(i, *new_value); | 907 frame->SetParameterValue(i, *new_value); |
898 // Argument might be shadowed in heap context, don't stop here. | 908 // Argument might be shadowed in heap context, don't stop here. |
899 default_result = true; | 909 default_result = true; |
900 } | 910 } |
901 } | 911 } |
902 | 912 |
903 // Stack locals. | 913 // Stack locals. |
904 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | 914 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { |
905 HandleScope scope(isolate); | 915 HandleScope scope(isolate); |
906 if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) { | 916 if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) { |
907 frame->SetExpression(i, *new_value); | 917 frame->SetExpression(scope_info->StackLocalIndex(i), *new_value); |
908 return true; | 918 return true; |
909 } | 919 } |
910 } | 920 } |
911 | 921 |
912 if (scope_info->HasContext()) { | 922 if (scope_info->HasContext()) { |
913 // Context locals. | 923 // Context locals. |
914 Handle<Context> frame_context(Context::cast(frame->context())); | 924 Handle<Context> frame_context(Context::cast(frame->context())); |
915 Handle<Context> function_context(frame_context->declaration_context()); | 925 Handle<Context> function_context(frame_context->declaration_context()); |
916 if (SetContextLocalValue(isolate, scope_info, function_context, | 926 if (SetContextLocalValue(isolate, scope_info, function_context, |
917 variable_name, new_value)) { | 927 variable_name, new_value)) { |
(...skipping 16 matching lines...) Expand all Loading... | |
934 return true; | 944 return true; |
935 } | 945 } |
936 } | 946 } |
937 } | 947 } |
938 } | 948 } |
939 | 949 |
940 return default_result; | 950 return default_result; |
941 } | 951 } |
942 | 952 |
943 | 953 |
954 static bool SetBlockVariableValue(Isolate* isolate, | |
955 Handle<Context> block_context, | |
956 Handle<ScopeInfo> scope_info, | |
957 JavaScriptFrame* frame, | |
958 Handle<String> variable_name, | |
959 Handle<Object> new_value) { | |
960 if (frame != nullptr) { | |
961 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | |
962 HandleScope scope(isolate); | |
963 if (String::Equals(handle(scope_info->StackLocalName(i)), | |
964 variable_name)) { | |
965 frame->SetExpression(scope_info->StackLocalIndex(i), *new_value); | |
966 return true; | |
967 } | |
968 } | |
969 } | |
970 if (!block_context.is_null()) { | |
971 return SetContextLocalValue(block_context->GetIsolate(), scope_info, | |
972 block_context, variable_name, new_value); | |
973 } | |
974 return false; | |
975 } | |
976 | |
977 | |
944 // Create a plain JSObject which materializes the closure content for the | 978 // Create a plain JSObject which materializes the closure content for the |
945 // context. | 979 // context. |
946 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeClosure( | 980 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeClosure( |
947 Isolate* isolate, Handle<Context> context) { | 981 Isolate* isolate, Handle<Context> context) { |
948 DCHECK(context->IsFunctionContext()); | 982 DCHECK(context->IsFunctionContext()); |
949 | 983 |
950 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | 984 Handle<SharedFunctionInfo> shared(context->closure()->shared()); |
951 Handle<ScopeInfo> scope_info(shared->scope_info()); | 985 Handle<ScopeInfo> scope_info(shared->scope_info()); |
952 | 986 |
953 // Allocate and initialize a JSObject with all the content of this function | 987 // Allocate and initialize a JSObject with all the content of this function |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1014 Runtime::DefineObjectProperty(ext, variable_name, new_value, NONE) | 1048 Runtime::DefineObjectProperty(ext, variable_name, new_value, NONE) |
1015 .Assert(); | 1049 .Assert(); |
1016 return true; | 1050 return true; |
1017 } | 1051 } |
1018 } | 1052 } |
1019 | 1053 |
1020 return false; | 1054 return false; |
1021 } | 1055 } |
1022 | 1056 |
1023 | 1057 |
1024 static bool SetBlockContextVariableValue(Handle<Context> block_context, | |
1025 Handle<String> variable_name, | |
1026 Handle<Object> new_value) { | |
1027 DCHECK(block_context->IsBlockContext()); | |
1028 Handle<ScopeInfo> scope_info(ScopeInfo::cast(block_context->extension())); | |
1029 | |
1030 return SetContextLocalValue(block_context->GetIsolate(), scope_info, | |
1031 block_context, variable_name, new_value); | |
1032 } | |
1033 | |
1034 | |
1035 static bool SetScriptVariableValue(Handle<Context> context, | 1058 static bool SetScriptVariableValue(Handle<Context> context, |
1036 Handle<String> variable_name, | 1059 Handle<String> variable_name, |
1037 Handle<Object> new_value) { | 1060 Handle<Object> new_value) { |
1038 Handle<ScriptContextTable> script_contexts( | 1061 Handle<ScriptContextTable> script_contexts( |
1039 context->global_object()->native_context()->script_context_table()); | 1062 context->global_object()->native_context()->script_context_table()); |
1040 ScriptContextTable::LookupResult lookup_result; | 1063 ScriptContextTable::LookupResult lookup_result; |
1041 if (ScriptContextTable::Lookup(script_contexts, variable_name, | 1064 if (ScriptContextTable::Lookup(script_contexts, variable_name, |
1042 &lookup_result)) { | 1065 &lookup_result)) { |
1043 Handle<Context> script_context = ScriptContextTable::GetContext( | 1066 Handle<Context> script_context = ScriptContextTable::GetContext( |
1044 script_contexts, lookup_result.context_index); | 1067 script_contexts, lookup_result.context_index); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1076 return false; | 1099 return false; |
1077 } | 1100 } |
1078 context->set(Context::THROWN_OBJECT_INDEX, *new_value); | 1101 context->set(Context::THROWN_OBJECT_INDEX, *new_value); |
1079 return true; | 1102 return true; |
1080 } | 1103 } |
1081 | 1104 |
1082 | 1105 |
1083 // Create a plain JSObject which materializes the block scope for the specified | 1106 // Create a plain JSObject which materializes the block scope for the specified |
1084 // block context. | 1107 // block context. |
1085 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope( | 1108 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope( |
1086 Isolate* isolate, Handle<Context> context) { | 1109 Isolate* isolate, Handle<ScopeInfo> scope_info, Handle<Context> context, |
1087 DCHECK(context->IsBlockContext()); | 1110 JavaScriptFrame* frame, int inlined_jsframe_index) { |
1088 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); | |
1089 | |
1090 // Allocate and initialize a JSObject with all the arguments, stack locals | |
1091 // heap locals and extension properties of the debugged function. | |
1092 Handle<JSObject> block_scope = | 1111 Handle<JSObject> block_scope = |
1093 isolate->factory()->NewJSObject(isolate->object_function()); | 1112 isolate->factory()->NewJSObject(isolate->object_function()); |
1094 | 1113 |
1095 // Fill all context locals. | 1114 if (frame != nullptr) { |
1096 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info, context, | 1115 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); |
1097 block_scope)) { | 1116 RETURN_ON_EXCEPTION(isolate, |
1098 return MaybeHandle<JSObject>(); | 1117 MaterializeStackLocalsWithFrameInspector( |
1118 isolate, block_scope, scope_info, &frame_inspector), | |
1119 JSObject); | |
1120 } | |
1121 | |
1122 if (!context.is_null()) { | |
1123 Handle<ScopeInfo> scope_info_from_context( | |
1124 ScopeInfo::cast(context->extension())); | |
1125 // Fill all context locals. | |
1126 if (!ScopeInfo::CopyContextLocalsToScopeObject(scope_info_from_context, | |
1127 context, block_scope)) { | |
1128 return MaybeHandle<JSObject>(); | |
1129 } | |
1099 } | 1130 } |
1100 | 1131 |
1101 return block_scope; | 1132 return block_scope; |
1102 } | 1133 } |
1103 | 1134 |
1104 | 1135 |
1105 // Create a plain JSObject which materializes the module scope for the specified | 1136 // Create a plain JSObject which materializes the module scope for the specified |
1106 // module context. | 1137 // module context. |
1107 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope( | 1138 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope( |
1108 Isolate* isolate, Handle<Context> context) { | 1139 Isolate* isolate, Handle<Context> context) { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1355 DCHECK(nested_scope_chain_.length() == 1); | 1386 DCHECK(nested_scope_chain_.length() == 1); |
1356 return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_); | 1387 return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_); |
1357 case ScopeIterator::ScopeTypeWith: | 1388 case ScopeIterator::ScopeTypeWith: |
1358 // Return the with object. | 1389 // Return the with object. |
1359 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); | 1390 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); |
1360 case ScopeIterator::ScopeTypeCatch: | 1391 case ScopeIterator::ScopeTypeCatch: |
1361 return MaterializeCatchScope(isolate_, CurrentContext()); | 1392 return MaterializeCatchScope(isolate_, CurrentContext()); |
1362 case ScopeIterator::ScopeTypeClosure: | 1393 case ScopeIterator::ScopeTypeClosure: |
1363 // Materialize the content of the closure scope into a JSObject. | 1394 // Materialize the content of the closure scope into a JSObject. |
1364 return MaterializeClosure(isolate_, CurrentContext()); | 1395 return MaterializeClosure(isolate_, CurrentContext()); |
1365 case ScopeIterator::ScopeTypeBlock: | 1396 case ScopeIterator::ScopeTypeBlock: { |
1366 return MaterializeBlockScope(isolate_, CurrentContext()); | 1397 if (!nested_scope_chain_.is_empty()) { |
1398 // this is a block scope on the stack. | |
rossberg
2015/04/17 15:16:27
Nit: upper case
| |
1399 Handle<ScopeInfo> scope_info = nested_scope_chain_.last(); | |
1400 Handle<Context> context = scope_info->HasContext() | |
1401 ? CurrentContext() | |
1402 : Handle<Context>::null(); | |
1403 return MaterializeBlockScope(isolate_, scope_info, context, frame_, | |
1404 inlined_jsframe_index_); | |
1405 } else { | |
1406 return MaterializeBlockScope(isolate_, Handle<ScopeInfo>::null(), | |
1407 CurrentContext(), nullptr, 0); | |
1408 } | |
1409 } | |
1367 case ScopeIterator::ScopeTypeModule: | 1410 case ScopeIterator::ScopeTypeModule: |
1368 return MaterializeModuleScope(isolate_, CurrentContext()); | 1411 return MaterializeModuleScope(isolate_, CurrentContext()); |
1369 } | 1412 } |
1370 UNREACHABLE(); | 1413 UNREACHABLE(); |
1371 return Handle<JSObject>(); | 1414 return Handle<JSObject>(); |
1372 } | 1415 } |
1373 | 1416 |
1417 bool HasContext() { | |
1418 ScopeType type = Type(); | |
1419 if (type == ScopeTypeBlock || type == ScopeTypeLocal) { | |
1420 if (!nested_scope_chain_.is_empty()) { | |
1421 return nested_scope_chain_.last()->HasContext(); | |
1422 } | |
1423 } | |
1424 return true; | |
1425 } | |
1426 | |
1374 bool SetVariableValue(Handle<String> variable_name, | 1427 bool SetVariableValue(Handle<String> variable_name, |
1375 Handle<Object> new_value) { | 1428 Handle<Object> new_value) { |
1376 DCHECK(!failed_); | 1429 DCHECK(!failed_); |
1377 switch (Type()) { | 1430 switch (Type()) { |
1378 case ScopeIterator::ScopeTypeGlobal: | 1431 case ScopeIterator::ScopeTypeGlobal: |
1379 break; | 1432 break; |
1380 case ScopeIterator::ScopeTypeLocal: | 1433 case ScopeIterator::ScopeTypeLocal: |
1381 return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_, | 1434 return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_, |
1382 variable_name, new_value); | 1435 variable_name, new_value); |
1383 case ScopeIterator::ScopeTypeWith: | 1436 case ScopeIterator::ScopeTypeWith: |
1384 break; | 1437 break; |
1385 case ScopeIterator::ScopeTypeCatch: | 1438 case ScopeIterator::ScopeTypeCatch: |
1386 return SetCatchVariableValue(isolate_, CurrentContext(), variable_name, | 1439 return SetCatchVariableValue(isolate_, CurrentContext(), variable_name, |
1387 new_value); | 1440 new_value); |
1388 case ScopeIterator::ScopeTypeClosure: | 1441 case ScopeIterator::ScopeTypeClosure: |
1389 return SetClosureVariableValue(isolate_, CurrentContext(), | 1442 return SetClosureVariableValue(isolate_, CurrentContext(), |
1390 variable_name, new_value); | 1443 variable_name, new_value); |
1391 case ScopeIterator::ScopeTypeScript: | 1444 case ScopeIterator::ScopeTypeScript: |
1392 return SetScriptVariableValue(CurrentContext(), variable_name, | 1445 return SetScriptVariableValue(CurrentContext(), variable_name, |
1393 new_value); | 1446 new_value); |
1394 case ScopeIterator::ScopeTypeBlock: | 1447 case ScopeIterator::ScopeTypeBlock: |
1395 return SetBlockContextVariableValue(CurrentContext(), variable_name, | 1448 return SetBlockVariableValue( |
1396 new_value); | 1449 isolate_, HasContext() ? CurrentContext() : Handle<Context>::null(), |
1450 CurrentScopeInfo(), frame_, variable_name, new_value); | |
1397 case ScopeIterator::ScopeTypeModule: | 1451 case ScopeIterator::ScopeTypeModule: |
1398 // TODO(2399): should we implement it? | 1452 // TODO(2399): should we implement it? |
1399 break; | 1453 break; |
1400 } | 1454 } |
1401 return false; | 1455 return false; |
1402 } | 1456 } |
1403 | 1457 |
1404 Handle<ScopeInfo> CurrentScopeInfo() { | 1458 Handle<ScopeInfo> CurrentScopeInfo() { |
1405 DCHECK(!failed_); | 1459 DCHECK(!failed_); |
1406 if (!nested_scope_chain_.is_empty()) { | 1460 if (!nested_scope_chain_.is_empty()) { |
(...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2182 Handle<JSObject> result = | 2236 Handle<JSObject> result = |
2183 isolate->factory()->NewJSObject(isolate->object_function()); | 2237 isolate->factory()->NewJSObject(isolate->object_function()); |
2184 Handle<Map> new_map = | 2238 Handle<Map> new_map = |
2185 Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto"); | 2239 Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto"); |
2186 Map::SetPrototype(new_map, isolate->factory()->null_value()); | 2240 Map::SetPrototype(new_map, isolate->factory()->null_value()); |
2187 JSObject::MigrateToMap(result, new_map); | 2241 JSObject::MigrateToMap(result, new_map); |
2188 return result; | 2242 return result; |
2189 } | 2243 } |
2190 | 2244 |
2191 | 2245 |
2246 namespace { | |
2247 | |
2248 // This class builds a context chain for evaluation of expressions | |
2249 // in debugger. | |
2250 // The scope chain leading up to a breakpoint where evaluation occurs | |
2251 // looks like: | |
2252 // - [a mix of with, catch and block scopes] | |
2253 // - [function stack + context] | |
2254 // - [outer context] | |
2255 // The builder materializes all stack variables into properties of objects; | |
2256 // the expression is then evaluated as if it is inside a series of 'with' | |
2257 // statements using those objects. To this end, the builder builds a new | |
2258 // context chain, based on a scope chain: | |
2259 // - every With and Catch scope begets a cloned context | |
2260 // - Block scope begets one or two contexts: | |
2261 // - if a block has context-allocated varaibles, its context is cloned | |
rossberg
2015/04/17 15:16:27
typo: variables
| |
2262 // - stack locals are materizalized as a With context | |
2263 // - Local scope begets a With context for materizalized locals, chained to | |
2264 // original function context. Original function context is the end of | |
2265 // the chain. | |
2266 class EvaluationContextBuilder { | |
2267 public: | |
2268 EvaluationContextBuilder(Isolate* isolate, JavaScriptFrame* frame, | |
2269 int inlined_jsframe_index) | |
2270 : isolate_(isolate), | |
2271 frame_(frame), | |
2272 inlined_jsframe_index_(inlined_jsframe_index) { | |
2273 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); | |
2274 Handle<JSFunction> function = | |
2275 handle(JSFunction::cast(frame_inspector.GetFunction())); | |
2276 Handle<Context> outer_context = handle(function->context(), isolate); | |
2277 outer_info_ = handle(function->shared()); | |
2278 Handle<Context> inner_context; | |
2279 | |
2280 bool stop = false; | |
2281 for (ScopeIterator it(isolate, frame, inlined_jsframe_index); | |
2282 !it.Failed() && !it.Done() && !stop; it.Next()) { | |
2283 ScopeIterator::ScopeType scope_type = it.Type(); | |
2284 | |
2285 if (scope_type == ScopeIterator::ScopeTypeLocal) { | |
2286 Handle<JSObject> materialized_function = | |
2287 NewJSObjectWithNullProto(isolate); | |
2288 | |
2289 if (!MaterializeStackLocalsWithFrameInspector( | |
2290 isolate, materialized_function, function, &frame_inspector) | |
2291 .ToHandle(&materialized_function)) | |
2292 return; | |
2293 | |
2294 if (!MaterializeArgumentsObject(isolate, materialized_function, | |
2295 function) | |
2296 .ToHandle(&materialized_function)) | |
2297 return; | |
2298 | |
2299 Handle<Context> parent_context = | |
2300 it.HasContext() ? it.CurrentContext() : outer_context; | |
2301 Handle<Context> with_context = isolate->factory()->NewWithContext( | |
2302 function, parent_context, materialized_function); | |
2303 | |
2304 ContextChainElement context_chain_element; | |
2305 context_chain_element.original_context = it.CurrentContext(); | |
2306 context_chain_element.materialized_object = materialized_function; | |
2307 context_chain_element.scope_info = it.CurrentScopeInfo(); | |
2308 context_chain_.Add(context_chain_element); | |
2309 | |
2310 stop = true; | |
2311 RecordContextsInChain(&inner_context, with_context, with_context); | |
2312 } else if (scope_type == ScopeIterator::ScopeTypeCatch || | |
2313 scope_type == ScopeIterator::ScopeTypeWith) { | |
2314 Handle<Context> cloned_context = | |
2315 Handle<Context>::cast(FixedArray::CopySize( | |
2316 it.CurrentContext(), it.CurrentContext()->length())); | |
2317 | |
2318 ContextChainElement context_chain_element; | |
2319 context_chain_element.original_context = it.CurrentContext(); | |
2320 context_chain_element.cloned_context = cloned_context; | |
2321 context_chain_.Add(context_chain_element); | |
2322 | |
2323 RecordContextsInChain(&inner_context, cloned_context, cloned_context); | |
2324 } else if (scope_type == ScopeIterator::ScopeTypeBlock) { | |
2325 Handle<JSObject> materialized_object = | |
2326 NewJSObjectWithNullProto(isolate); | |
2327 if (!MaterializeStackLocalsWithFrameInspector( | |
2328 isolate, materialized_object, it.CurrentScopeInfo(), | |
2329 &frame_inspector).ToHandle(&materialized_object)) | |
2330 return; | |
2331 if (it.HasContext()) { | |
2332 Handle<Context> cloned_context = | |
2333 Handle<Context>::cast(FixedArray::CopySize( | |
2334 it.CurrentContext(), it.CurrentContext()->length())); | |
2335 Handle<Context> with_context = isolate->factory()->NewWithContext( | |
2336 function, cloned_context, materialized_object); | |
2337 | |
2338 ContextChainElement context_chain_element; | |
2339 context_chain_element.original_context = it.CurrentContext(); | |
2340 context_chain_element.cloned_context = cloned_context; | |
2341 context_chain_element.materialized_object = materialized_object; | |
2342 context_chain_element.scope_info = it.CurrentScopeInfo(); | |
2343 context_chain_.Add(context_chain_element); | |
2344 | |
2345 RecordContextsInChain(&inner_context, cloned_context, with_context); | |
2346 } else { | |
2347 Handle<Context> with_context = isolate->factory()->NewWithContext( | |
2348 function, outer_context, materialized_object); | |
2349 | |
2350 ContextChainElement context_chain_element; | |
2351 context_chain_element.materialized_object = materialized_object; | |
2352 context_chain_element.scope_info = it.CurrentScopeInfo(); | |
2353 context_chain_.Add(context_chain_element); | |
2354 | |
2355 RecordContextsInChain(&inner_context, with_context, with_context); | |
2356 } | |
2357 } else { | |
2358 stop = true; | |
2359 } | |
2360 } | |
2361 if (innermost_context_.is_null()) { | |
2362 innermost_context_ = outer_context; | |
2363 } | |
2364 DCHECK(!innermost_context_.is_null()); | |
2365 } | |
2366 | |
2367 void UpdateVariables() { | |
2368 for (int i = 0; i < context_chain_.length(); i++) { | |
2369 ContextChainElement element = context_chain_[i]; | |
2370 if (!element.original_context.is_null() && | |
2371 !element.cloned_context.is_null()) { | |
2372 Handle<Context> cloned_context = element.cloned_context; | |
2373 cloned_context->CopyTo( | |
2374 Context::MIN_CONTEXT_SLOTS, *element.original_context, | |
2375 Context::MIN_CONTEXT_SLOTS, | |
2376 cloned_context->length() - Context::MIN_CONTEXT_SLOTS); | |
2377 } | |
2378 if (!element.materialized_object.is_null()) { | |
2379 // Write back potential changes to materialized stack locals to the | |
2380 // stack. | |
2381 UpdateStackLocalsFromMaterializedObject( | |
2382 isolate_, element.materialized_object, element.scope_info, frame_, | |
2383 inlined_jsframe_index_); | |
2384 } | |
2385 } | |
2386 } | |
2387 | |
2388 Handle<Context> innermost_context() const { return innermost_context_; } | |
2389 Handle<SharedFunctionInfo> outer_info() const { return outer_info_; } | |
2390 | |
2391 private: | |
2392 struct ContextChainElement { | |
2393 Handle<Context> original_context; | |
2394 Handle<Context> cloned_context; | |
2395 Handle<JSObject> materialized_object; | |
2396 Handle<ScopeInfo> scope_info; | |
2397 }; | |
2398 | |
2399 void RecordContextsInChain(Handle<Context>* inner_context, | |
2400 Handle<Context> first, Handle<Context> last) { | |
2401 if (!inner_context->is_null()) { | |
2402 (*inner_context)->set_previous(*last); | |
2403 } else { | |
2404 innermost_context_ = last; | |
2405 } | |
2406 *inner_context = first; | |
2407 } | |
2408 | |
2409 Handle<SharedFunctionInfo> outer_info_; | |
2410 Handle<Context> innermost_context_; | |
2411 List<ContextChainElement> context_chain_; | |
2412 Isolate* isolate_; | |
2413 JavaScriptFrame* frame_; | |
2414 int inlined_jsframe_index_; | |
2415 }; | |
2416 } | |
2417 | |
2418 | |
2192 // Evaluate a piece of JavaScript in the context of a stack frame for | 2419 // Evaluate a piece of JavaScript in the context of a stack frame for |
2193 // debugging. Things that need special attention are: | 2420 // debugging. Things that need special attention are: |
2194 // - Parameters and stack-allocated locals need to be materialized. Altered | 2421 // - Parameters and stack-allocated locals need to be materialized. Altered |
2195 // values need to be written back to the stack afterwards. | 2422 // values need to be written back to the stack afterwards. |
2196 // - The arguments object needs to materialized. | 2423 // - The arguments object needs to materialized. |
2197 RUNTIME_FUNCTION(Runtime_DebugEvaluate) { | 2424 RUNTIME_FUNCTION(Runtime_DebugEvaluate) { |
2198 HandleScope scope(isolate); | 2425 HandleScope scope(isolate); |
2199 | 2426 |
2200 // Check the execution state and decode arguments frame and source to be | 2427 // Check the execution state and decode arguments frame and source to be |
2201 // evaluated. | 2428 // evaluated. |
(...skipping 16 matching lines...) Expand all Loading... | |
2218 JavaScriptFrame* frame = it.frame(); | 2445 JavaScriptFrame* frame = it.frame(); |
2219 | 2446 |
2220 // Traverse the saved contexts chain to find the active context for the | 2447 // Traverse the saved contexts chain to find the active context for the |
2221 // selected frame. | 2448 // selected frame. |
2222 SaveContext* save = FindSavedContextForFrame(isolate, frame); | 2449 SaveContext* save = FindSavedContextForFrame(isolate, frame); |
2223 | 2450 |
2224 SaveContext savex(isolate); | 2451 SaveContext savex(isolate); |
2225 isolate->set_context(*(save->context())); | 2452 isolate->set_context(*(save->context())); |
2226 | 2453 |
2227 // Materialize stack locals and the arguments object. | 2454 // Materialize stack locals and the arguments object. |
2228 Handle<JSObject> materialized; | |
2229 Handle<JSFunction> function; | |
2230 Handle<SharedFunctionInfo> outer_info; | |
2231 Handle<Context> eval_context; | |
2232 | 2455 |
2233 // We need to limit the lifetime of the FrameInspector because evaluation can | 2456 EvaluationContextBuilder context_builder(isolate, frame, |
2234 // call arbitrary code and only one FrameInspector can be active at a time. | 2457 inlined_jsframe_index); |
2235 { | 2458 if (isolate->has_pending_exception()) { |
2236 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); | 2459 return isolate->heap()->exception(); |
2237 materialized = NewJSObjectWithNullProto(isolate); | |
2238 function = handle(JSFunction::cast(frame_inspector.GetFunction())); | |
2239 outer_info = handle(function->shared()); | |
2240 eval_context = handle(Context::cast(frame_inspector.GetContext())); | |
2241 | |
2242 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
2243 isolate, materialized, | |
2244 MaterializeStackLocalsWithFrameInspector(isolate, materialized, | |
2245 function, &frame_inspector)); | |
2246 | |
2247 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
2248 isolate, materialized, | |
2249 MaterializeArgumentsObject(isolate, materialized, function)); | |
2250 } | 2460 } |
2251 | 2461 |
2252 // At this point, the lookup chain may look like this: | |
2253 // [inner context] -> [function stack]+[function context] -> [outer context] | |
2254 // The function stack is not an actual context, it complements the function | |
2255 // context. In order to have the same lookup chain when debug-evaluating, | |
2256 // we: | |
2257 // - clone inner context | |
2258 // - materialize the stack and insert it into the context chain as a | |
2259 // with-context before the function context. | |
2260 // [inner context clone] -> [with context] -> [function context] -> | |
2261 // [outer context] | |
2262 // Ordering the with-context before the function context forces a dynamic | |
2263 // lookup instead of a static lookup that could fail as the scope info is | |
2264 // outdated and may expect variables to still be stack-allocated. | |
2265 // Afterwards, we write changes to the with-context back to the stack, and | |
2266 // write changes in cloned contexts back to original contexts. | |
2267 | |
2268 DCHECK(!eval_context.is_null()); | |
2269 Handle<Context> function_context = eval_context; | |
2270 Handle<Context> outer_context(function->context(), isolate); | |
2271 Handle<Context> inner_context; | |
2272 Handle<Context> innermost_context; | |
2273 | |
2274 // We iterate to find the function's context, cloning until we hit it. | |
2275 // If the function has no context-allocated variables, we iterate until | |
2276 // we hit the outer context. | |
2277 while (!function_context->IsFunctionContext() && | |
2278 !function_context->IsScriptContext() && | |
2279 !function_context.is_identical_to(outer_context)) { | |
2280 Handle<Context> clone = Handle<Context>::cast( | |
2281 FixedArray::CopySize(function_context, function_context->length())); | |
2282 if (!inner_context.is_null()) { | |
2283 inner_context->set_previous(*clone); | |
2284 } else { | |
2285 innermost_context = clone; | |
2286 } | |
2287 inner_context = clone; | |
2288 function_context = Handle<Context>(function_context->previous(), isolate); | |
2289 } | |
2290 | |
2291 Handle<Context> materialized_context = isolate->factory()->NewWithContext( | |
2292 function, function_context, materialized); | |
2293 | |
2294 if (inner_context.is_null()) { | |
2295 // No inner context. The with-context is now inner-most. | |
2296 innermost_context = materialized_context; | |
2297 } else { | |
2298 inner_context->set_previous(*materialized_context); | |
2299 } | |
2300 | 2462 |
2301 Handle<Object> receiver(frame->receiver(), isolate); | 2463 Handle<Object> receiver(frame->receiver(), isolate); |
2302 MaybeHandle<Object> maybe_result = | 2464 MaybeHandle<Object> maybe_result = DebugEvaluate( |
2303 DebugEvaluate(isolate, outer_info, innermost_context, context_extension, | 2465 isolate, context_builder.outer_info(), |
2304 receiver, source); | 2466 context_builder.innermost_context(), context_extension, receiver, source); |
2305 | 2467 |
2306 Handle<Object> result; | 2468 Handle<Object> result; |
2307 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); | 2469 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); |
2308 | 2470 context_builder.UpdateVariables(); |
2309 // Write back potential changes to materialized stack locals to the stack. | |
2310 UpdateStackLocalsFromMaterializedObject(isolate, materialized, function, | |
2311 frame, inlined_jsframe_index); | |
2312 | |
2313 while (!innermost_context.is_identical_to(materialized_context)) { | |
2314 DCHECK(eval_context->map() == innermost_context->map()); | |
2315 innermost_context->CopyTo( | |
2316 Context::MIN_CONTEXT_SLOTS, *eval_context, Context::MIN_CONTEXT_SLOTS, | |
2317 innermost_context->length() - Context::MIN_CONTEXT_SLOTS); | |
2318 innermost_context = handle(innermost_context->previous(), isolate); | |
2319 eval_context = handle(eval_context->previous(), isolate); | |
2320 } | |
2321 | |
2322 return *result; | 2471 return *result; |
2323 } | 2472 } |
2324 | 2473 |
2325 | 2474 |
2326 RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) { | 2475 RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) { |
2327 HandleScope scope(isolate); | 2476 HandleScope scope(isolate); |
2328 | 2477 |
2329 // Check the execution state and decode arguments frame and source to be | 2478 // Check the execution state and decode arguments frame and source to be |
2330 // evaluated. | 2479 // evaluated. |
2331 DCHECK(args.length() == 4); | 2480 DCHECK(args.length() == 4); |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2837 return Smi::FromInt(isolate->debug()->is_active()); | 2986 return Smi::FromInt(isolate->debug()->is_active()); |
2838 } | 2987 } |
2839 | 2988 |
2840 | 2989 |
2841 RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) { | 2990 RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) { |
2842 UNIMPLEMENTED(); | 2991 UNIMPLEMENTED(); |
2843 return NULL; | 2992 return NULL; |
2844 } | 2993 } |
2845 } | 2994 } |
2846 } // namespace v8::internal | 2995 } // namespace v8::internal |
OLD | NEW |