OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/interpreter/control-flow-builders.h" | 8 #include "src/interpreter/control-flow-builders.h" |
9 #include "src/objects.h" | 9 #include "src/objects.h" |
10 #include "src/parser.h" | 10 #include "src/parser.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 generator_->set_execution_context(this); | 36 generator_->set_execution_context(this); |
37 } | 37 } |
38 | 38 |
39 ~ContextScope() { | 39 ~ContextScope() { |
40 if (outer_ && should_pop_context_) { | 40 if (outer_ && should_pop_context_) { |
41 generator_->builder()->PopContext(outer_->reg()); | 41 generator_->builder()->PopContext(outer_->reg()); |
42 } | 42 } |
43 generator_->set_execution_context(outer_); | 43 generator_->set_execution_context(outer_); |
44 } | 44 } |
45 | 45 |
46 // Returns the execution context for the given |scope| if it is a function | 46 // Returns the depth of the given |scope| for the current execution context. |
47 // local execution context, otherwise returns nullptr. | 47 int ContextChainDepth(Scope* scope) { |
48 ContextScope* Previous(Scope* scope) { | 48 return scope_->ContextChainLength(scope); |
49 int depth = scope_->ContextChainLength(scope); | 49 } |
| 50 |
| 51 // Returns the execution context at |depth| in the current context chain if it |
| 52 // is a function local execution context, otherwise returns nullptr. |
| 53 ContextScope* Previous(int depth) { |
50 if (depth > depth_) { | 54 if (depth > depth_) { |
51 return nullptr; | 55 return nullptr; |
52 } | 56 } |
53 | 57 |
54 ContextScope* previous = this; | 58 ContextScope* previous = this; |
55 for (int i = depth; i > 0; --i) { | 59 for (int i = depth; i > 0; --i) { |
56 previous = previous->outer_; | 60 previous = previous->outer_; |
57 } | 61 } |
58 return previous; | 62 return previous; |
59 } | 63 } |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 case VariableLocation::UNALLOCATED: { | 411 case VariableLocation::UNALLOCATED: { |
408 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( | 412 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( |
409 decl->fun(), info()->script(), info()); | 413 decl->fun(), info()->script(), info()); |
410 // Check for stack-overflow exception. | 414 // Check for stack-overflow exception. |
411 if (function.is_null()) return SetStackOverflow(); | 415 if (function.is_null()) return SetStackOverflow(); |
412 globals()->push_back(variable->name()); | 416 globals()->push_back(variable->name()); |
413 globals()->push_back(function); | 417 globals()->push_back(function); |
414 break; | 418 break; |
415 } | 419 } |
416 case VariableLocation::PARAMETER: | 420 case VariableLocation::PARAMETER: |
417 case VariableLocation::LOCAL: | 421 case VariableLocation::LOCAL: { |
418 case VariableLocation::CONTEXT: | 422 VisitForAccumulatorValue(decl->fun()); |
| 423 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid()); |
| 424 break; |
| 425 } |
| 426 case VariableLocation::CONTEXT: { |
| 427 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
| 428 VisitForAccumulatorValue(decl->fun()); |
| 429 builder()->StoreContextSlot(execution_context()->reg(), |
| 430 variable->index()); |
| 431 break; |
| 432 } |
419 case VariableLocation::LOOKUP: | 433 case VariableLocation::LOOKUP: |
420 UNIMPLEMENTED(); | 434 UNIMPLEMENTED(); |
421 } | 435 } |
422 } | 436 } |
423 | 437 |
424 | 438 |
425 void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) { | 439 void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) { |
426 UNIMPLEMENTED(); | 440 UNIMPLEMENTED(); |
427 } | 441 } |
428 | 442 |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
974 break; | 988 break; |
975 } | 989 } |
976 case VariableLocation::GLOBAL: | 990 case VariableLocation::GLOBAL: |
977 case VariableLocation::UNALLOCATED: { | 991 case VariableLocation::UNALLOCATED: { |
978 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); | 992 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); |
979 builder()->LoadGlobal(name_index, feedback_index(slot), language_mode()); | 993 builder()->LoadGlobal(name_index, feedback_index(slot), language_mode()); |
980 execution_result()->SetResultInAccumulator(); | 994 execution_result()->SetResultInAccumulator(); |
981 break; | 995 break; |
982 } | 996 } |
983 case VariableLocation::CONTEXT: { | 997 case VariableLocation::CONTEXT: { |
984 ContextScope* context = execution_context()->Previous(variable->scope()); | 998 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| 999 ContextScope* context = execution_context()->Previous(depth); |
| 1000 Register context_reg; |
985 if (context) { | 1001 if (context) { |
986 builder()->LoadContextSlot(context->reg(), variable->index()); | 1002 context_reg = context->reg(); |
987 execution_result()->SetResultInAccumulator(); | |
988 } else { | 1003 } else { |
989 UNIMPLEMENTED(); | 1004 context_reg = execution_result()->NewRegister(); |
| 1005 // Walk the context chain to find the context at the given depth. |
| 1006 // TODO(rmcilroy): Perform this work in a bytecode handler once we have |
| 1007 // a generic mechanism for performing jumps in interpreter.cc. |
| 1008 builder() |
| 1009 ->LoadAccumulatorWithRegister(execution_context()->reg()) |
| 1010 .StoreAccumulatorInRegister(context_reg); |
| 1011 for (int i = 0; i < depth; ++i) { |
| 1012 builder() |
| 1013 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) |
| 1014 .StoreAccumulatorInRegister(context_reg); |
| 1015 } |
990 } | 1016 } |
| 1017 builder()->LoadContextSlot(context_reg, variable->index()); |
| 1018 execution_result()->SetResultInAccumulator(); |
991 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and | 1019 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and |
992 // let variables. | 1020 // let variables. |
993 break; | 1021 break; |
994 } | 1022 } |
995 case VariableLocation::LOOKUP: | 1023 case VariableLocation::LOOKUP: |
996 UNIMPLEMENTED(); | 1024 UNIMPLEMENTED(); |
997 } | 1025 } |
998 } | 1026 } |
999 | 1027 |
1000 | 1028 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 break; | 1060 break; |
1033 } | 1061 } |
1034 case VariableLocation::GLOBAL: | 1062 case VariableLocation::GLOBAL: |
1035 case VariableLocation::UNALLOCATED: { | 1063 case VariableLocation::UNALLOCATED: { |
1036 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); | 1064 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); |
1037 builder()->StoreGlobal(name_index, feedback_index(slot), language_mode()); | 1065 builder()->StoreGlobal(name_index, feedback_index(slot), language_mode()); |
1038 break; | 1066 break; |
1039 } | 1067 } |
1040 case VariableLocation::CONTEXT: { | 1068 case VariableLocation::CONTEXT: { |
1041 // TODO(rmcilroy): support const mode initialization. | 1069 // TODO(rmcilroy): support const mode initialization. |
1042 ContextScope* context = execution_context()->Previous(variable->scope()); | 1070 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| 1071 ContextScope* context = execution_context()->Previous(depth); |
| 1072 Register context_reg; |
1043 if (context) { | 1073 if (context) { |
1044 builder()->StoreContextSlot(context->reg(), variable->index()); | 1074 context_reg = context->reg(); |
1045 } else { | 1075 } else { |
1046 UNIMPLEMENTED(); | 1076 Register value_temp = execution_result()->NewRegister(); |
| 1077 context_reg = execution_result()->NewRegister(); |
| 1078 // Walk the context chain to find the context at the given depth. |
| 1079 // TODO(rmcilroy): Perform this work in a bytecode handler once we have |
| 1080 // a generic mechanism for performing jumps in interpreter.cc. |
| 1081 builder() |
| 1082 ->StoreAccumulatorInRegister(value_temp) |
| 1083 .LoadAccumulatorWithRegister(execution_context()->reg()) |
| 1084 .StoreAccumulatorInRegister(context_reg); |
| 1085 for (int i = 0; i < depth; ++i) { |
| 1086 builder() |
| 1087 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) |
| 1088 .StoreAccumulatorInRegister(context_reg); |
| 1089 } |
| 1090 builder()->LoadAccumulatorWithRegister(value_temp); |
1047 } | 1091 } |
| 1092 builder()->StoreContextSlot(context_reg, variable->index()); |
1048 break; | 1093 break; |
1049 } | 1094 } |
1050 case VariableLocation::LOOKUP: | 1095 case VariableLocation::LOOKUP: |
1051 UNIMPLEMENTED(); | 1096 UNIMPLEMENTED(); |
1052 } | 1097 } |
1053 } | 1098 } |
1054 | 1099 |
1055 | 1100 |
1056 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 1101 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
1057 DCHECK(expr->target()->IsValidReferenceExpression()); | 1102 DCHECK(expr->target()->IsValidReferenceExpression()); |
(...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1835 } | 1880 } |
1836 | 1881 |
1837 | 1882 |
1838 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 1883 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
1839 return info()->feedback_vector()->GetIndex(slot); | 1884 return info()->feedback_vector()->GetIndex(slot); |
1840 } | 1885 } |
1841 | 1886 |
1842 } // namespace interpreter | 1887 } // namespace interpreter |
1843 } // namespace internal | 1888 } // namespace internal |
1844 } // namespace v8 | 1889 } // namespace v8 |
OLD | NEW |