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/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-info.h" | 10 #include "src/compilation-info.h" |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 564 global_declarations_(0, info->zone()), | 564 global_declarations_(0, info->zone()), |
| 565 function_literals_(0, info->zone()), | 565 function_literals_(0, info->zone()), |
| 566 native_function_literals_(0, info->zone()), | 566 native_function_literals_(0, info->zone()), |
| 567 execution_control_(nullptr), | 567 execution_control_(nullptr), |
| 568 execution_context_(nullptr), | 568 execution_context_(nullptr), |
| 569 execution_result_(nullptr), | 569 execution_result_(nullptr), |
| 570 generator_resume_points_(info->literal()->yield_count(), info->zone()), | 570 generator_resume_points_(info->literal()->yield_count(), info->zone()), |
| 571 generator_state_(), | 571 generator_state_(), |
| 572 loop_depth_(0), | 572 loop_depth_(0), |
| 573 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), | 573 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), |
| 574 prototype_string_(info->isolate()->factory()->prototype_string()) { | 574 prototype_string_(info->isolate()->factory()->prototype_string()), |
| 575 } | 575 name_string_(info->isolate()->factory()->name_string()) {} |
| 576 | 576 |
| 577 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { | 577 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { |
| 578 AllocateDeferredConstants(); | 578 AllocateDeferredConstants(); |
| 579 if (HasStackOverflow()) return Handle<BytecodeArray>(); | 579 if (HasStackOverflow()) return Handle<BytecodeArray>(); |
| 580 return builder()->ToBytecodeArray(isolate); | 580 return builder()->ToBytecodeArray(isolate); |
| 581 } | 581 } |
| 582 | 582 |
| 583 void BytecodeGenerator::AllocateDeferredConstants() { | 583 void BytecodeGenerator::AllocateDeferredConstants() { |
| 584 // Build global declaration pair arrays. | 584 // Build global declaration pair arrays. |
| 585 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { | 585 for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { |
| (...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1375 scope()->is_function_scope()); | 1375 scope()->is_function_scope()); |
| 1376 size_t entry = builder()->AllocateConstantPoolEntry(); | 1376 size_t entry = builder()->AllocateConstantPoolEntry(); |
| 1377 builder()->CreateClosure(entry, flags); | 1377 builder()->CreateClosure(entry, flags); |
| 1378 function_literals_.push_back(std::make_pair(expr, entry)); | 1378 function_literals_.push_back(std::make_pair(expr, entry)); |
| 1379 } | 1379 } |
| 1380 | 1380 |
| 1381 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { | 1381 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { |
| 1382 VisitClassLiteralForRuntimeDefinition(expr); | 1382 VisitClassLiteralForRuntimeDefinition(expr); |
| 1383 | 1383 |
| 1384 // Load the "prototype" from the constructor. | 1384 // Load the "prototype" from the constructor. |
| 1385 RegisterList args = register_allocator()->NewRegisterList(2); | 1385 RegisterList args = register_allocator()->NewRegisterList(3); |
| 1386 Register literal = args[0]; | 1386 Register literal = args[0]; |
| 1387 Register prototype = args[1]; | 1387 Register prototype = args[1]; |
| 1388 FeedbackVectorSlot slot = expr->PrototypeSlot(); | 1388 FeedbackVectorSlot slot = expr->PrototypeSlot(); |
| 1389 builder() | 1389 builder() |
| 1390 ->StoreAccumulatorInRegister(literal) | 1390 ->StoreAccumulatorInRegister(literal) |
| 1391 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) | 1391 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) |
| 1392 .StoreAccumulatorInRegister(prototype); | 1392 .StoreAccumulatorInRegister(prototype); |
| 1393 | 1393 |
| 1394 VisitClassLiteralProperties(expr, literal, prototype); | 1394 Register needs_name = args[2]; |
|
rmcilroy
2016/11/28 10:28:59
This shouldn't be allocated in the same RegisterLi
| |
| 1395 VisitClassLiteralProperties(expr, literal, prototype, needs_name); | |
| 1396 BuildClassLiteralNameProperty(expr, literal, needs_name); | |
| 1395 builder()->CallRuntime(Runtime::kToFastProperties, literal); | 1397 builder()->CallRuntime(Runtime::kToFastProperties, literal); |
| 1396 // Assign to class variable. | 1398 // Assign to class variable. |
| 1397 if (expr->class_variable_proxy() != nullptr) { | 1399 if (expr->class_variable_proxy() != nullptr) { |
| 1398 Variable* var = expr->class_variable_proxy()->var(); | 1400 Variable* var = expr->class_variable_proxy()->var(); |
| 1399 FeedbackVectorSlot slot = expr->NeedsProxySlot() | 1401 FeedbackVectorSlot slot = expr->NeedsProxySlot() |
| 1400 ? expr->ProxySlot() | 1402 ? expr->ProxySlot() |
| 1401 : FeedbackVectorSlot::Invalid(); | 1403 : FeedbackVectorSlot::Invalid(); |
| 1402 VisitVariableAssignment(var, Token::INIT, slot); | 1404 VisitVariableAssignment(var, Token::INIT, slot); |
| 1403 } | 1405 } |
| 1404 } | 1406 } |
| 1405 | 1407 |
| 1406 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( | 1408 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( |
| 1407 ClassLiteral* expr) { | 1409 ClassLiteral* expr) { |
| 1408 RegisterAllocationScope register_scope(this); | 1410 RegisterAllocationScope register_scope(this); |
| 1409 RegisterList args = register_allocator()->NewRegisterList(4); | 1411 RegisterList args = register_allocator()->NewRegisterList(4); |
| 1410 VisitForAccumulatorValueOrTheHole(expr->extends()); | 1412 VisitForAccumulatorValueOrTheHole(expr->extends()); |
| 1411 builder()->StoreAccumulatorInRegister(args[0]); | 1413 builder()->StoreAccumulatorInRegister(args[0]); |
| 1412 VisitForRegisterValue(expr->constructor(), args[1]); | 1414 VisitForRegisterValue(expr->constructor(), args[1]); |
| 1413 builder() | 1415 builder() |
| 1414 ->LoadLiteral(Smi::FromInt(expr->start_position())) | 1416 ->LoadLiteral(Smi::FromInt(expr->start_position())) |
| 1415 .StoreAccumulatorInRegister(args[2]) | 1417 .StoreAccumulatorInRegister(args[2]) |
| 1416 .LoadLiteral(Smi::FromInt(expr->end_position())) | 1418 .LoadLiteral(Smi::FromInt(expr->end_position())) |
| 1417 .StoreAccumulatorInRegister(args[3]) | 1419 .StoreAccumulatorInRegister(args[3]) |
| 1418 .CallRuntime(Runtime::kDefineClass, args); | 1420 .CallRuntime(Runtime::kDefineClass, args); |
| 1419 } | 1421 } |
| 1420 | 1422 |
| 1421 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, | 1423 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, |
| 1422 Register literal, | 1424 Register literal, |
| 1423 Register prototype) { | 1425 Register prototype, |
| 1426 Register needs_name) { | |
| 1424 RegisterAllocationScope register_scope(this); | 1427 RegisterAllocationScope register_scope(this); |
| 1425 RegisterList args = register_allocator()->NewRegisterList(5); | 1428 RegisterList args = register_allocator()->NewRegisterList(5); |
| 1426 Register receiver = args[0], key = args[1], value = args[2], attr = args[3], | 1429 Register receiver = args[0], key = args[1], value = args[2], attr = args[3], |
| 1427 set_function_name = args[4]; | 1430 set_function_name = args[4]; |
| 1428 | 1431 |
| 1429 bool attr_assigned = false; | 1432 bool attr_assigned = false; |
| 1430 Register old_receiver = Register::invalid_value(); | 1433 Register old_receiver = Register::invalid_value(); |
| 1431 | 1434 |
| 1435 // Initialize has_name_static_property. | |
| 1436 bool check_name = !expr->has_name_static_property() && | |
|
Toon Verwaest
2016/11/28 10:40:58
Isn't the general case that we don't have a static
| |
| 1437 !expr->constructor()->raw_name()->IsEmpty(); | |
| 1438 if (check_name) { | |
| 1439 builder()->LoadTrue().StoreAccumulatorInRegister(needs_name); | |
| 1440 } | |
| 1441 | |
| 1432 // Create nodes to store method values into the literal. | 1442 // Create nodes to store method values into the literal. |
| 1433 for (int i = 0; i < expr->properties()->length(); i++) { | 1443 for (int i = 0; i < expr->properties()->length(); i++) { |
| 1434 ClassLiteral::Property* property = expr->properties()->at(i); | 1444 ClassLiteral::Property* property = expr->properties()->at(i); |
| 1435 | 1445 |
| 1436 // Set-up receiver. | 1446 // Set-up receiver. |
| 1437 Register new_receiver = property->is_static() ? literal : prototype; | 1447 Register new_receiver = property->is_static() ? literal : prototype; |
| 1438 if (new_receiver != old_receiver) { | 1448 if (new_receiver != old_receiver) { |
| 1439 builder()->MoveRegister(new_receiver, receiver); | 1449 builder()->MoveRegister(new_receiver, receiver); |
| 1440 old_receiver = new_receiver; | 1450 old_receiver = new_receiver; |
| 1441 } | 1451 } |
| 1442 | 1452 |
| 1443 VisitForAccumulatorValue(property->key()); | 1453 VisitForAccumulatorValue(property->key()); |
| 1444 builder()->ConvertAccumulatorToName(key); | 1454 builder()->ConvertAccumulatorToName(key); |
| 1445 | 1455 |
| 1446 if (property->is_static() && property->is_computed_name()) { | 1456 if (property->is_static() && property->is_computed_name()) { |
| 1457 // Check for a static property called "name". | |
| 1458 if (check_name) { | |
| 1459 BytecodeLabel has_name; | |
| 1460 builder() | |
| 1461 ->LoadAccumulatorWithRegister(needs_name) | |
| 1462 .JumpIfFalse(&has_name) | |
| 1463 .LoadLiteral(name_string()) | |
| 1464 .CompareOperation(Token::Value::EQ_STRICT, key) | |
| 1465 .LogicalNot() | |
| 1466 .StoreAccumulatorInRegister(needs_name) | |
| 1467 .Bind(&has_name); | |
| 1468 } | |
|
rmcilroy
2016/11/28 10:28:59
I'm not keen on this extra code added to every pro
Toon Verwaest
2016/11/28 10:40:58
I agree, we should just do something more expensiv
| |
| 1469 | |
| 1447 // The static prototype property is read only. We handle the non computed | 1470 // The static prototype property is read only. We handle the non computed |
| 1448 // property name case in the parser. Since this is the only case where we | 1471 // property name case in the parser. Since this is the only case where we |
| 1449 // need to check for an own read only property we special case this so we | 1472 // need to check for an own read only property we special case this so we |
| 1450 // do not need to do this for every property. | 1473 // do not need to do this for every property. |
| 1451 BytecodeLabel done; | 1474 BytecodeLabel done; |
| 1452 builder() | 1475 builder() |
| 1453 ->LoadLiteral(prototype_string()) | 1476 ->LoadLiteral(prototype_string()) |
| 1454 .CompareOperation(Token::Value::EQ_STRICT, key) | 1477 .CompareOperation(Token::Value::EQ_STRICT, key) |
| 1455 .JumpIfFalse(&done) | 1478 .JumpIfFalse(&done) |
| 1456 .CallRuntime(Runtime::kThrowStaticPrototypeError) | 1479 .CallRuntime(Runtime::kThrowStaticPrototypeError) |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1486 break; | 1509 break; |
| 1487 } | 1510 } |
| 1488 case ClassLiteral::Property::FIELD: { | 1511 case ClassLiteral::Property::FIELD: { |
| 1489 UNREACHABLE(); | 1512 UNREACHABLE(); |
| 1490 break; | 1513 break; |
| 1491 } | 1514 } |
| 1492 } | 1515 } |
| 1493 } | 1516 } |
| 1494 } | 1517 } |
| 1495 | 1518 |
| 1519 void BytecodeGenerator::BuildClassLiteralNameProperty(ClassLiteral* expr, | |
| 1520 Register literal, | |
| 1521 Register needs_name) { | |
| 1522 bool check_name = !expr->has_name_static_property() && | |
| 1523 !expr->constructor()->raw_name()->IsEmpty(); | |
| 1524 if (check_name) { | |
| 1525 BytecodeLabel has_name; | |
| 1526 builder() | |
| 1527 ->LoadAccumulatorWithRegister(needs_name) | |
| 1528 .JumpIfFalse(&has_name) | |
| 1529 .CallRuntime(Runtime::kInstallClassNameAccessor, literal) | |
| 1530 .Bind(&has_name); | |
| 1531 } | |
| 1532 } | |
| 1533 | |
| 1496 void BytecodeGenerator::VisitNativeFunctionLiteral( | 1534 void BytecodeGenerator::VisitNativeFunctionLiteral( |
| 1497 NativeFunctionLiteral* expr) { | 1535 NativeFunctionLiteral* expr) { |
| 1498 size_t entry = builder()->AllocateConstantPoolEntry(); | 1536 size_t entry = builder()->AllocateConstantPoolEntry(); |
| 1499 builder()->CreateClosure(entry, NOT_TENURED); | 1537 builder()->CreateClosure(entry, NOT_TENURED); |
| 1500 native_function_literals_.push_back(std::make_pair(expr, entry)); | 1538 native_function_literals_.push_back(std::make_pair(expr, entry)); |
| 1501 } | 1539 } |
| 1502 | 1540 |
| 1503 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { | 1541 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { |
| 1504 VisitBlock(expr->block()); | 1542 VisitBlock(expr->block()); |
| 1505 VisitVariableProxy(expr->result()); | 1543 VisitVariableProxy(expr->result()); |
| (...skipping 1681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3187 } | 3225 } |
| 3188 | 3226 |
| 3189 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3227 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
| 3190 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3228 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 3191 : Runtime::kStoreKeyedToSuper_Sloppy; | 3229 : Runtime::kStoreKeyedToSuper_Sloppy; |
| 3192 } | 3230 } |
| 3193 | 3231 |
| 3194 } // namespace interpreter | 3232 } // namespace interpreter |
| 3195 } // namespace internal | 3233 } // namespace internal |
| 3196 } // namespace v8 | 3234 } // namespace v8 |
| OLD | NEW |