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

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: CR feedback 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 669 matching lines...) Expand 10 before | Expand all | Expand 10 after
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);
Yang 2015/04/22 11:32:23 DCHECK_NOT_NULL
Dmitry Lomov (no reviews) 2015/04/22 12:24:30 Done.
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();
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
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
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
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
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
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.
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
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
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
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
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
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