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

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

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

Powered by Google App Engine
This is Rietveld 408576698