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 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1216 Handle<SharedFunctionInfo> shared_info = | 1216 Handle<SharedFunctionInfo> shared_info = |
1217 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); | 1217 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); |
1218 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow? | 1218 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow? |
1219 builder()->CreateClosure(shared_info, | 1219 builder()->CreateClosure(shared_info, |
1220 expr->pretenure() ? TENURED : NOT_TENURED); | 1220 expr->pretenure() ? TENURED : NOT_TENURED); |
1221 execution_result()->SetResultInAccumulator(); | 1221 execution_result()->SetResultInAccumulator(); |
1222 } | 1222 } |
1223 | 1223 |
1224 | 1224 |
1225 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { | 1225 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { |
1226 UNIMPLEMENTED(); | 1226 if (expr->scope()->ContextLocalCount() > 0) { |
| 1227 VisitNewLocalBlockContext(expr->scope()); |
| 1228 ContextScope scope(this, expr->scope()); |
| 1229 VisitDeclarations(expr->scope()->declarations()); |
| 1230 VisitClassLiteralContents(expr); |
| 1231 } else { |
| 1232 VisitDeclarations(expr->scope()->declarations()); |
| 1233 VisitClassLiteralContents(expr); |
| 1234 } |
1227 } | 1235 } |
1228 | 1236 |
| 1237 void BytecodeGenerator::VisitClassLiteralContents(ClassLiteral* expr) { |
| 1238 VisitClassLiteralForRuntimeDefinition(expr); |
| 1239 // The prototype is ensured to exist by Runtime_DefineClass in |
| 1240 // VisitClassForRuntimeDefinition. No access check is needed here |
| 1241 // since the constructor is created by the class literal. |
| 1242 register_allocator()->PrepareForConsecutiveAllocations(2); |
| 1243 Register literal = register_allocator()->NextConsecutiveRegister(); |
| 1244 Register prototype = register_allocator()->NextConsecutiveRegister(); |
| 1245 builder()->StoreAccumulatorInRegister(literal); |
| 1246 builder()->LoadPrototypeOrInitialMap(); |
| 1247 builder()->StoreAccumulatorInRegister(prototype); |
| 1248 VisitClassLiteralProperties(expr, literal, prototype); |
| 1249 |
| 1250 // Set both the prototype and constructor to have fast properties, and also |
| 1251 // freeze them in strong mode. |
| 1252 builder()->CallRuntime(Runtime::kFinalizeClassDefinition, literal, 2); |
| 1253 // Assign to class variable. |
| 1254 if (expr->class_variable_proxy() != nullptr) { |
| 1255 Variable* var = expr->class_variable_proxy()->var(); |
| 1256 FeedbackVectorSlot slot = expr->NeedsProxySlot() |
| 1257 ? expr->ProxySlot() |
| 1258 : FeedbackVectorSlot::Invalid(); |
| 1259 VisitVariableAssignment(var, slot); |
| 1260 } |
| 1261 execution_result()->SetResultInAccumulator(); |
| 1262 } |
| 1263 |
| 1264 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( |
| 1265 ClassLiteral* expr) { |
| 1266 AccumulatorResultScope result_scope(this); |
| 1267 register_allocator()->PrepareForConsecutiveAllocations(4); |
| 1268 Register extends = register_allocator()->NextConsecutiveRegister(); |
| 1269 Register constructor = register_allocator()->NextConsecutiveRegister(); |
| 1270 Register start_position = register_allocator()->NextConsecutiveRegister(); |
| 1271 Register end_position = register_allocator()->NextConsecutiveRegister(); |
| 1272 VisitForAccumulatorValueOrTheHole(expr->extends()); |
| 1273 builder()->StoreAccumulatorInRegister(extends); |
| 1274 VisitForAccumulatorValue(expr->constructor()); |
| 1275 builder()->StoreAccumulatorInRegister(constructor); |
| 1276 builder()->LoadLiteral(Smi::FromInt(expr->start_position())); |
| 1277 builder()->StoreAccumulatorInRegister(start_position); |
| 1278 builder()->LoadLiteral(Smi::FromInt(expr->end_position())); |
| 1279 builder()->StoreAccumulatorInRegister(end_position); |
| 1280 builder()->CallRuntime(Runtime::kDefineClass, extends, 4); |
| 1281 result_scope.SetResultInAccumulator(); |
| 1282 } |
| 1283 |
| 1284 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, |
| 1285 Register literal, |
| 1286 Register prototype) { |
| 1287 EffectResultScope result_scope(this); |
| 1288 |
| 1289 register_allocator()->PrepareForConsecutiveAllocations(4); |
| 1290 Register receiver = register_allocator()->NextConsecutiveRegister(); |
| 1291 Register key = register_allocator()->NextConsecutiveRegister(); |
| 1292 Register value = register_allocator()->NextConsecutiveRegister(); |
| 1293 Register attr = register_allocator()->NextConsecutiveRegister(); |
| 1294 |
| 1295 bool attr_assigned = false; |
| 1296 Register old_receiver = Register::invalid_value(); |
| 1297 |
| 1298 // Create nodes to store method values into the literal. |
| 1299 for (int i = 0; i < expr->properties()->length(); i++) { |
| 1300 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 1301 |
| 1302 // Set-up receiver. |
| 1303 Register new_receiver = property->is_static() ? literal : prototype; |
| 1304 if (new_receiver != old_receiver) { |
| 1305 builder()->MoveRegister(new_receiver, receiver); |
| 1306 old_receiver = new_receiver; |
| 1307 } |
| 1308 |
| 1309 VisitForAccumulatorValue(property->key()); |
| 1310 builder()->CastAccumulatorToName(); |
| 1311 builder()->StoreAccumulatorInRegister(key); |
| 1312 // The static prototype property is read only. We handle the non computed |
| 1313 // property name case in the parser. Since this is the only case where we |
| 1314 // need to check for an own read only property we special case this so we do |
| 1315 // not need to do this for every property. |
| 1316 if (property->is_static() && property->is_computed_name()) { |
| 1317 VisitClassLiteralStaticPrototypeWithComputedName(key); |
| 1318 } |
| 1319 VisitForAccumulatorValue(property->value()); |
| 1320 builder()->StoreAccumulatorInRegister(value); |
| 1321 |
| 1322 VisitSetHomeObject(value, receiver, property); |
| 1323 |
| 1324 if ((property->kind() == ObjectLiteral::Property::GETTER || |
| 1325 property->kind() == ObjectLiteral::Property::SETTER) && |
| 1326 !attr_assigned) { |
| 1327 builder() |
| 1328 ->LoadLiteral(Smi::FromInt(DONT_ENUM)) |
| 1329 .StoreAccumulatorInRegister(attr); |
| 1330 attr_assigned = true; |
| 1331 } |
| 1332 |
| 1333 switch (property->kind()) { |
| 1334 case ObjectLiteral::Property::CONSTANT: |
| 1335 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1336 case ObjectLiteral::Property::PROTOTYPE: |
| 1337 UNREACHABLE(); |
| 1338 case ObjectLiteral::Property::COMPUTED: { |
| 1339 builder()->CallRuntime(Runtime::kDefineClassMethod, receiver, 3); |
| 1340 break; |
| 1341 } |
| 1342 case ObjectLiteral::Property::GETTER: { |
| 1343 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked, |
| 1344 receiver, 4); |
| 1345 break; |
| 1346 } |
| 1347 case ObjectLiteral::Property::SETTER: { |
| 1348 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, |
| 1349 receiver, 4); |
| 1350 break; |
| 1351 } |
| 1352 } |
| 1353 } |
| 1354 } |
| 1355 |
| 1356 void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName( |
| 1357 Register key) { |
| 1358 BytecodeLabel done; |
| 1359 builder()->LoadLiteral(isolate()->factory()->prototype_string()); |
| 1360 builder()->CompareOperation(Token::Value::EQ_STRICT, key, Strength::WEAK); |
| 1361 builder()->JumpIfFalse(&done); |
| 1362 builder()->CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0); |
| 1363 builder()->Bind(&done); |
| 1364 } |
1229 | 1365 |
1230 void BytecodeGenerator::VisitNativeFunctionLiteral( | 1366 void BytecodeGenerator::VisitNativeFunctionLiteral( |
1231 NativeFunctionLiteral* expr) { | 1367 NativeFunctionLiteral* expr) { |
1232 // Find or build a shared function info for the native function template. | 1368 // Find or build a shared function info for the native function template. |
1233 Handle<SharedFunctionInfo> shared_info = | 1369 Handle<SharedFunctionInfo> shared_info = |
1234 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name()); | 1370 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name()); |
1235 builder()->CreateClosure(shared_info, NOT_TENURED); | 1371 builder()->CreateClosure(shared_info, NOT_TENURED); |
1236 execution_result()->SetResultInAccumulator(); | 1372 execution_result()->SetResultInAccumulator(); |
1237 } | 1373 } |
1238 | 1374 |
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2508 execution_result()->SetResultInAccumulator(); | 2644 execution_result()->SetResultInAccumulator(); |
2509 } | 2645 } |
2510 | 2646 |
2511 | 2647 |
2512 // Visits the expression |expr| and places the result in the accumulator. | 2648 // Visits the expression |expr| and places the result in the accumulator. |
2513 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 2649 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
2514 AccumulatorResultScope accumulator_scope(this); | 2650 AccumulatorResultScope accumulator_scope(this); |
2515 Visit(expr); | 2651 Visit(expr); |
2516 } | 2652 } |
2517 | 2653 |
| 2654 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { |
| 2655 if (expr == nullptr) { |
| 2656 builder()->LoadTheHole(); |
| 2657 } else { |
| 2658 VisitForAccumulatorValue(expr); |
| 2659 } |
| 2660 } |
2518 | 2661 |
2519 // Visits the expression |expr| and discards the result. | 2662 // Visits the expression |expr| and discards the result. |
2520 void BytecodeGenerator::VisitForEffect(Expression* expr) { | 2663 void BytecodeGenerator::VisitForEffect(Expression* expr) { |
2521 EffectResultScope effect_scope(this); | 2664 EffectResultScope effect_scope(this); |
2522 Visit(expr); | 2665 Visit(expr); |
2523 } | 2666 } |
2524 | 2667 |
2525 | 2668 |
2526 // Visits the expression |expr| and returns the register containing | 2669 // Visits the expression |expr| and returns the register containing |
2527 // the expression result. | 2670 // the expression result. |
(...skipping 21 matching lines...) Expand all Loading... |
2549 } | 2692 } |
2550 | 2693 |
2551 | 2694 |
2552 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2695 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2553 return info()->feedback_vector()->GetIndex(slot); | 2696 return info()->feedback_vector()->GetIndex(slot); |
2554 } | 2697 } |
2555 | 2698 |
2556 } // namespace interpreter | 2699 } // namespace interpreter |
2557 } // namespace internal | 2700 } // namespace internal |
2558 } // namespace v8 | 2701 } // namespace v8 |
OLD | NEW |