Chromium Code Reviews| 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/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
| 9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
| 10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
| (...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 957 expr->flags()); | 957 expr->flags()); |
| 958 execution_result()->SetResultInAccumulator(); | 958 execution_result()->SetResultInAccumulator(); |
| 959 } | 959 } |
| 960 | 960 |
| 961 | 961 |
| 962 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 962 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 963 // Deep-copy the literal boilerplate. | 963 // Deep-copy the literal boilerplate. |
| 964 builder()->CreateObjectLiteral(expr->constant_properties(), | 964 builder()->CreateObjectLiteral(expr->constant_properties(), |
| 965 expr->literal_index(), | 965 expr->literal_index(), |
| 966 expr->ComputeFlags(true)); | 966 expr->ComputeFlags(true)); |
| 967 Register literal; | 967 |
| 968 // Allocate in the outer scope since this register is returned. | |
|
rmcilroy
2016/01/15 17:15:09
/s/since.../since this register is used to return
mythria
2016/01/18 11:34:05
Thanks, Done.
| |
| 969 Register literal = register_allocator()->outer()->NewRegister(); | |
| 970 builder()->StoreAccumulatorInRegister(literal); | |
| 968 | 971 |
| 969 // Store computed values into the literal. | 972 // Store computed values into the literal. |
| 970 bool literal_in_accumulator = true; | |
| 971 int property_index = 0; | 973 int property_index = 0; |
| 972 AccessorTable accessor_table(zone()); | 974 AccessorTable accessor_table(zone()); |
| 973 for (; property_index < expr->properties()->length(); property_index++) { | 975 for (; property_index < expr->properties()->length(); property_index++) { |
| 974 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 976 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 975 if (property->is_computed_name()) break; | 977 if (property->is_computed_name()) break; |
| 976 if (property->IsCompileTimeValue()) continue; | 978 if (property->IsCompileTimeValue()) continue; |
| 977 | 979 |
| 978 if (literal_in_accumulator) { | |
| 979 literal = register_allocator()->NewRegister(); | |
| 980 builder()->StoreAccumulatorInRegister(literal); | |
| 981 literal_in_accumulator = false; | |
| 982 } | |
| 983 | |
| 984 RegisterAllocationScope inner_register_scope(this); | 980 RegisterAllocationScope inner_register_scope(this); |
| 985 Literal* literal_key = property->key()->AsLiteral(); | 981 Literal* literal_key = property->key()->AsLiteral(); |
| 986 switch (property->kind()) { | 982 switch (property->kind()) { |
| 987 case ObjectLiteral::Property::CONSTANT: | 983 case ObjectLiteral::Property::CONSTANT: |
| 988 UNREACHABLE(); | 984 UNREACHABLE(); |
| 989 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 985 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 990 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); | 986 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 991 // Fall through. | 987 // Fall through. |
| 992 case ObjectLiteral::Property::COMPUTED: { | 988 case ObjectLiteral::Property::COMPUTED: { |
| 993 // It is safe to use [[Put]] here because the boilerplate already | 989 // It is safe to use [[Put]] here because the boilerplate already |
| 994 // contains computed properties with an uninitialized value. | 990 // contains computed properties with an uninitialized value. |
| 995 if (literal_key->value()->IsInternalizedString()) { | 991 if (literal_key->value()->IsInternalizedString()) { |
| 996 if (property->emit_store()) { | 992 if (property->emit_store()) { |
| 997 VisitForAccumulatorValue(property->value()); | 993 VisitForAccumulatorValue(property->value()); |
| 998 builder()->StoreNamedProperty( | 994 builder()->StoreNamedProperty( |
| 999 literal, literal_key->AsPropertyName(), | 995 literal, literal_key->AsPropertyName(), |
| 1000 feedback_index(property->GetSlot(0)), language_mode()); | 996 feedback_index(property->GetSlot(0)), language_mode()); |
| 1001 } else { | 997 } else { |
| 1002 VisitForEffect(property->value()); | 998 VisitForEffect(property->value()); |
| 1003 } | 999 } |
| 1004 } else { | 1000 } else { |
| 1005 register_allocator()->PrepareForConsecutiveAllocations(3); | 1001 register_allocator()->PrepareForConsecutiveAllocations(4); |
| 1002 Register literal_argument = | |
| 1003 register_allocator()->NextConsecutiveRegister(); | |
| 1006 Register key = register_allocator()->NextConsecutiveRegister(); | 1004 Register key = register_allocator()->NextConsecutiveRegister(); |
| 1007 Register value = register_allocator()->NextConsecutiveRegister(); | 1005 Register value = register_allocator()->NextConsecutiveRegister(); |
| 1008 Register language = register_allocator()->NextConsecutiveRegister(); | 1006 Register language = register_allocator()->NextConsecutiveRegister(); |
| 1009 // TODO(oth): This is problematic - can't assume contiguous here. | 1007 DCHECK( |
| 1010 // literal is allocated in outer register scope, whereas key, value, | 1008 Register::AreContiguous(literal_argument, key, value, language)); |
|
rmcilroy
2016/01/15 17:15:09
This DCHECK's probably not necessary anymore.
mythria
2016/01/18 11:34:05
Done.
| |
| 1011 // language are in another. | 1009 |
| 1012 DCHECK(Register::AreContiguous(literal, key, value, language)); | 1010 builder()->MoveRegister(literal, literal_argument); |
| 1013 VisitForAccumulatorValue(property->key()); | 1011 VisitForAccumulatorValue(property->key()); |
| 1014 builder()->StoreAccumulatorInRegister(key); | 1012 builder()->StoreAccumulatorInRegister(key); |
| 1015 VisitForAccumulatorValue(property->value()); | 1013 VisitForAccumulatorValue(property->value()); |
| 1016 builder()->StoreAccumulatorInRegister(value); | 1014 builder()->StoreAccumulatorInRegister(value); |
| 1017 if (property->emit_store()) { | 1015 if (property->emit_store()) { |
| 1018 builder() | 1016 builder() |
| 1019 ->LoadLiteral(Smi::FromInt(SLOPPY)) | 1017 ->LoadLiteral(Smi::FromInt(SLOPPY)) |
| 1020 .StoreAccumulatorInRegister(language) | 1018 .StoreAccumulatorInRegister(language) |
| 1021 .CallRuntime(Runtime::kSetProperty, literal, 4); | 1019 .CallRuntime(Runtime::kSetProperty, literal_argument, 4); |
| 1022 VisitSetHomeObject(value, literal, property); | 1020 VisitSetHomeObject(value, literal, property); |
| 1023 } | 1021 } |
| 1024 } | 1022 } |
| 1025 break; | 1023 break; |
| 1026 } | 1024 } |
| 1027 case ObjectLiteral::Property::PROTOTYPE: { | 1025 case ObjectLiteral::Property::PROTOTYPE: { |
| 1028 register_allocator()->PrepareForConsecutiveAllocations(1); | |
| 1029 DCHECK(property->emit_store()); | 1026 DCHECK(property->emit_store()); |
| 1027 register_allocator()->PrepareForConsecutiveAllocations(2); | |
| 1028 Register literal_argument = | |
| 1029 register_allocator()->NextConsecutiveRegister(); | |
| 1030 Register value = register_allocator()->NextConsecutiveRegister(); | 1030 Register value = register_allocator()->NextConsecutiveRegister(); |
| 1031 DCHECK(Register::AreContiguous(literal, value)); | 1031 DCHECK(Register::AreContiguous(literal_argument, value)); |
|
rmcilroy
2016/01/15 17:15:09
ditto
mythria
2016/01/18 11:34:05
Done.
| |
| 1032 | |
| 1033 builder()->MoveRegister(literal, literal_argument); | |
| 1032 VisitForAccumulatorValue(property->value()); | 1034 VisitForAccumulatorValue(property->value()); |
| 1033 builder()->StoreAccumulatorInRegister(value).CallRuntime( | 1035 builder()->StoreAccumulatorInRegister(value).CallRuntime( |
| 1034 Runtime::kInternalSetPrototype, literal, 2); | 1036 Runtime::kInternalSetPrototype, literal_argument, 2); |
| 1035 break; | 1037 break; |
| 1036 } | 1038 } |
| 1037 case ObjectLiteral::Property::GETTER: | 1039 case ObjectLiteral::Property::GETTER: |
| 1038 if (property->emit_store()) { | 1040 if (property->emit_store()) { |
| 1039 accessor_table.lookup(literal_key)->second->getter = property; | 1041 accessor_table.lookup(literal_key)->second->getter = property; |
| 1040 } | 1042 } |
| 1041 break; | 1043 break; |
| 1042 case ObjectLiteral::Property::SETTER: | 1044 case ObjectLiteral::Property::SETTER: |
| 1043 if (property->emit_store()) { | 1045 if (property->emit_store()) { |
| 1044 accessor_table.lookup(literal_key)->second->setter = property; | 1046 accessor_table.lookup(literal_key)->second->setter = property; |
| 1045 } | 1047 } |
| 1046 break; | 1048 break; |
| 1047 } | 1049 } |
| 1048 } | 1050 } |
| 1049 | 1051 |
| 1050 // Define accessors, using only a single call to the runtime for each pair of | 1052 // Define accessors, using only a single call to the runtime for each pair of |
| 1051 // corresponding getters and setters. | 1053 // corresponding getters and setters. |
| 1052 for (AccessorTable::Iterator it = accessor_table.begin(); | 1054 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1053 it != accessor_table.end(); ++it) { | 1055 it != accessor_table.end(); ++it) { |
| 1054 RegisterAllocationScope inner_register_scope(this); | 1056 RegisterAllocationScope inner_register_scope(this); |
| 1055 register_allocator()->PrepareForConsecutiveAllocations(4); | 1057 register_allocator()->PrepareForConsecutiveAllocations(5); |
| 1058 Register literal_argument = register_allocator()->NextConsecutiveRegister(); | |
| 1056 Register name = register_allocator()->NextConsecutiveRegister(); | 1059 Register name = register_allocator()->NextConsecutiveRegister(); |
| 1057 Register getter = register_allocator()->NextConsecutiveRegister(); | 1060 Register getter = register_allocator()->NextConsecutiveRegister(); |
| 1058 Register setter = register_allocator()->NextConsecutiveRegister(); | 1061 Register setter = register_allocator()->NextConsecutiveRegister(); |
| 1059 Register attr = register_allocator()->NextConsecutiveRegister(); | 1062 Register attr = register_allocator()->NextConsecutiveRegister(); |
| 1060 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); | 1063 DCHECK( |
| 1064 Register::AreContiguous(literal_argument, name, getter, setter, attr)); | |
|
rmcilroy
2016/01/15 17:15:09
ditto
mythria
2016/01/18 11:34:05
Done.
| |
| 1065 | |
| 1066 builder()->MoveRegister(literal, literal_argument); | |
| 1061 VisitForAccumulatorValue(it->first); | 1067 VisitForAccumulatorValue(it->first); |
| 1062 builder()->StoreAccumulatorInRegister(name); | 1068 builder()->StoreAccumulatorInRegister(name); |
| 1063 VisitObjectLiteralAccessor(literal, it->second->getter, getter); | 1069 VisitObjectLiteralAccessor(literal, it->second->getter, getter); |
| 1064 VisitObjectLiteralAccessor(literal, it->second->setter, setter); | 1070 VisitObjectLiteralAccessor(literal, it->second->setter, setter); |
| 1065 builder() | 1071 builder() |
| 1066 ->LoadLiteral(Smi::FromInt(NONE)) | 1072 ->LoadLiteral(Smi::FromInt(NONE)) |
| 1067 .StoreAccumulatorInRegister(attr) | 1073 .StoreAccumulatorInRegister(attr) |
| 1068 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); | 1074 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, |
| 1075 literal_argument, 5); | |
| 1069 } | 1076 } |
| 1070 | 1077 |
| 1071 // Object literals have two parts. The "static" part on the left contains no | 1078 // Object literals have two parts. The "static" part on the left contains no |
| 1072 // computed property names, and so we can compute its map ahead of time; see | 1079 // computed property names, and so we can compute its map ahead of time; see |
| 1073 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts | 1080 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts |
| 1074 // with the first computed property name and continues with all properties to | 1081 // with the first computed property name and continues with all properties to |
| 1075 // its right. All the code from above initializes the static component of the | 1082 // its right. All the code from above initializes the static component of the |
| 1076 // object literal, and arranges for the map of the result to reflect the | 1083 // object literal, and arranges for the map of the result to reflect the |
| 1077 // static order in which the keys appear. For the dynamic properties, we | 1084 // static order in which the keys appear. For the dynamic properties, we |
| 1078 // compile them into a series of "SetOwnProperty" runtime calls. This will | 1085 // compile them into a series of "SetOwnProperty" runtime calls. This will |
| 1079 // preserve insertion order. | 1086 // preserve insertion order. |
| 1080 for (; property_index < expr->properties()->length(); property_index++) { | 1087 for (; property_index < expr->properties()->length(); property_index++) { |
| 1081 if (literal_in_accumulator) { | |
| 1082 literal = register_allocator()->NewRegister(); | |
| 1083 builder()->StoreAccumulatorInRegister(literal); | |
| 1084 literal_in_accumulator = false; | |
| 1085 } | |
| 1086 | |
| 1087 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1088 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1088 RegisterAllocationScope inner_register_scope(this); | 1089 RegisterAllocationScope inner_register_scope(this); |
| 1090 | |
| 1089 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1091 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 1090 DCHECK(property->emit_store()); | 1092 DCHECK(property->emit_store()); |
| 1091 Register value = register_allocator()->NewRegister(); | 1093 register_allocator()->PrepareForConsecutiveAllocations(2); |
| 1092 DCHECK(Register::AreContiguous(literal, value)); | 1094 Register literal_argument = |
| 1095 register_allocator()->NextConsecutiveRegister(); | |
| 1096 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 1097 DCHECK(Register::AreContiguous(literal_argument, value)); | |
|
rmcilroy
2016/01/15 17:15:09
ditto
mythria
2016/01/18 11:34:05
Done.
| |
| 1098 | |
| 1099 builder()->MoveRegister(literal, literal_argument); | |
| 1093 VisitForAccumulatorValue(property->value()); | 1100 VisitForAccumulatorValue(property->value()); |
| 1094 builder()->StoreAccumulatorInRegister(value).CallRuntime( | 1101 builder()->StoreAccumulatorInRegister(value).CallRuntime( |
| 1095 Runtime::kInternalSetPrototype, literal, 2); | 1102 Runtime::kInternalSetPrototype, literal_argument, 2); |
| 1096 continue; | 1103 continue; |
| 1097 } | 1104 } |
| 1098 | 1105 |
| 1099 register_allocator()->PrepareForConsecutiveAllocations(3); | 1106 register_allocator()->PrepareForConsecutiveAllocations(4); |
| 1107 Register literal_argument = register_allocator()->NextConsecutiveRegister(); | |
| 1100 Register key = register_allocator()->NextConsecutiveRegister(); | 1108 Register key = register_allocator()->NextConsecutiveRegister(); |
| 1101 Register value = register_allocator()->NextConsecutiveRegister(); | 1109 Register value = register_allocator()->NextConsecutiveRegister(); |
| 1102 Register attr = register_allocator()->NextConsecutiveRegister(); | 1110 Register attr = register_allocator()->NextConsecutiveRegister(); |
| 1103 DCHECK(Register::AreContiguous(literal, key, value, attr)); | 1111 DCHECK(Register::AreContiguous(literal_argument, key, value, attr)); |
| 1104 | 1112 |
| 1113 builder()->MoveRegister(literal, literal_argument); | |
| 1105 VisitForAccumulatorValue(property->key()); | 1114 VisitForAccumulatorValue(property->key()); |
| 1106 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); | 1115 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); |
| 1107 VisitForAccumulatorValue(property->value()); | 1116 VisitForAccumulatorValue(property->value()); |
| 1108 builder()->StoreAccumulatorInRegister(value); | 1117 builder()->StoreAccumulatorInRegister(value); |
| 1109 VisitSetHomeObject(value, literal, property); | 1118 VisitSetHomeObject(value, literal, property); |
| 1110 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); | 1119 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); |
| 1111 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); | 1120 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); |
| 1112 switch (property->kind()) { | 1121 switch (property->kind()) { |
| 1113 case ObjectLiteral::Property::CONSTANT: | 1122 case ObjectLiteral::Property::CONSTANT: |
| 1114 case ObjectLiteral::Property::COMPUTED: | 1123 case ObjectLiteral::Property::COMPUTED: |
| 1115 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1124 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1116 function_id = Runtime::kDefineDataPropertyUnchecked; | 1125 function_id = Runtime::kDefineDataPropertyUnchecked; |
| 1117 break; | 1126 break; |
| 1118 case ObjectLiteral::Property::PROTOTYPE: | 1127 case ObjectLiteral::Property::PROTOTYPE: |
| 1119 UNREACHABLE(); // Handled specially above. | 1128 UNREACHABLE(); // Handled specially above. |
| 1120 break; | 1129 break; |
| 1121 case ObjectLiteral::Property::GETTER: | 1130 case ObjectLiteral::Property::GETTER: |
| 1122 function_id = Runtime::kDefineGetterPropertyUnchecked; | 1131 function_id = Runtime::kDefineGetterPropertyUnchecked; |
| 1123 break; | 1132 break; |
| 1124 case ObjectLiteral::Property::SETTER: | 1133 case ObjectLiteral::Property::SETTER: |
| 1125 function_id = Runtime::kDefineSetterPropertyUnchecked; | 1134 function_id = Runtime::kDefineSetterPropertyUnchecked; |
| 1126 break; | 1135 break; |
| 1127 } | 1136 } |
| 1128 builder()->CallRuntime(function_id, literal, 4); | 1137 builder()->CallRuntime(function_id, literal_argument, 4); |
| 1129 } | 1138 } |
| 1130 | 1139 |
| 1131 // Transform literals that contain functions to fast properties. | 1140 // Transform literals that contain functions to fast properties. |
| 1132 if (expr->has_function()) { | 1141 if (expr->has_function()) { |
| 1133 DCHECK(!literal_in_accumulator); | |
| 1134 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); | 1142 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); |
| 1135 } | 1143 } |
| 1136 | 1144 |
| 1137 if (!literal_in_accumulator) { | 1145 execution_result()->SetResultInRegister(literal); |
| 1138 // Restore literal array into accumulator. | |
| 1139 builder()->LoadAccumulatorWithRegister(literal); | |
| 1140 } | |
| 1141 execution_result()->SetResultInAccumulator(); | |
| 1142 } | 1146 } |
| 1143 | 1147 |
| 1144 | 1148 |
| 1145 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1149 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 1146 // Deep-copy the literal boilerplate. | 1150 // Deep-copy the literal boilerplate. |
| 1147 builder()->CreateArrayLiteral(expr->constant_elements(), | 1151 builder()->CreateArrayLiteral(expr->constant_elements(), |
| 1148 expr->literal_index(), | 1152 expr->literal_index(), |
| 1149 expr->ComputeFlags(true)); | 1153 expr->ComputeFlags(true)); |
| 1150 Register index, literal; | 1154 Register index, literal; |
| 1151 | 1155 |
| (...skipping 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2173 } | 2177 } |
| 2174 | 2178 |
| 2175 | 2179 |
| 2176 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2180 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 2177 return info()->feedback_vector()->GetIndex(slot); | 2181 return info()->feedback_vector()->GetIndex(slot); |
| 2178 } | 2182 } |
| 2179 | 2183 |
| 2180 } // namespace interpreter | 2184 } // namespace interpreter |
| 2181 } // namespace internal | 2185 } // namespace internal |
| 2182 } // namespace v8 | 2186 } // namespace v8 |
| OLD | NEW |