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 1474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1485 // Load the "prototype" from the constructor. | 1485 // Load the "prototype" from the constructor. |
1486 register_allocator()->PrepareForConsecutiveAllocations(2); | 1486 register_allocator()->PrepareForConsecutiveAllocations(2); |
1487 Register literal = register_allocator()->NextConsecutiveRegister(); | 1487 Register literal = register_allocator()->NextConsecutiveRegister(); |
1488 Register prototype = register_allocator()->NextConsecutiveRegister(); | 1488 Register prototype = register_allocator()->NextConsecutiveRegister(); |
1489 FeedbackVectorSlot slot = expr->PrototypeSlot(); | 1489 FeedbackVectorSlot slot = expr->PrototypeSlot(); |
1490 builder() | 1490 builder() |
1491 ->StoreAccumulatorInRegister(literal) | 1491 ->StoreAccumulatorInRegister(literal) |
1492 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) | 1492 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) |
1493 .StoreAccumulatorInRegister(prototype); | 1493 .StoreAccumulatorInRegister(prototype); |
1494 | 1494 |
1495 // The below proxy exists to allow static field initializers to have the | |
1496 // correct home object and receiver. It's only necessary if the initializers | |
1497 // are called as a part of class definition instead of immediately after it, | |
1498 // in which case they could simply refer to the class just constructed. The | |
1499 // latter is actually what's currently specified, and this will need to be | |
1500 // changed if that behavior is settled upon. See also | |
1501 // https://github.com/tc39/proposal-class-public-fields/issues/50 | |
1502 VariableProxy* static_initializer_proxy = expr->static_initializer_proxy(); | |
1503 if (static_initializer_proxy != nullptr) { | |
1504 Variable* variable = static_initializer_proxy->var(); | |
1505 builder()->LoadAccumulatorWithRegister(literal); | |
1506 VisitVariableAssignment(variable, Token::INIT, | |
1507 FeedbackVectorSlot::Invalid()); | |
1508 } | |
1509 | |
1495 VisitClassLiteralProperties(expr, literal, prototype); | 1510 VisitClassLiteralProperties(expr, literal, prototype); |
1496 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); | 1511 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); |
1497 // Assign to class variable. | 1512 // Assign to class variable. |
1498 if (expr->class_variable_proxy() != nullptr) { | 1513 if (expr->class_variable_proxy() != nullptr) { |
1499 Variable* var = expr->class_variable_proxy()->var(); | 1514 Variable* var = expr->class_variable_proxy()->var(); |
1500 FeedbackVectorSlot slot = expr->NeedsProxySlot() | 1515 FeedbackVectorSlot slot = expr->NeedsProxySlot() |
1501 ? expr->ProxySlot() | 1516 ? expr->ProxySlot() |
1502 : FeedbackVectorSlot::Invalid(); | 1517 : FeedbackVectorSlot::Invalid(); |
1503 VisitVariableAssignment(var, Token::INIT, slot); | 1518 VisitVariableAssignment(var, Token::INIT, slot); |
1504 } | 1519 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1539 Register attr = register_allocator()->NextConsecutiveRegister(); | 1554 Register attr = register_allocator()->NextConsecutiveRegister(); |
1540 Register set_function_name = register_allocator()->NextConsecutiveRegister(); | 1555 Register set_function_name = register_allocator()->NextConsecutiveRegister(); |
1541 | 1556 |
1542 bool attr_assigned = false; | 1557 bool attr_assigned = false; |
1543 Register old_receiver = Register::invalid_value(); | 1558 Register old_receiver = Register::invalid_value(); |
1544 | 1559 |
1545 // Create nodes to store method values into the literal. | 1560 // Create nodes to store method values into the literal. |
1546 for (int i = 0; i < expr->properties()->length(); i++) { | 1561 for (int i = 0; i < expr->properties()->length(); i++) { |
1547 ClassLiteral::Property* property = expr->properties()->at(i); | 1562 ClassLiteral::Property* property = expr->properties()->at(i); |
1548 | 1563 |
1564 if (property->kind() == ClassLiteral::Property::FIELD && | |
1565 !property->is_static()) { | |
1566 // Non-static properties produced by the parser have as their 'key' an | |
1567 // expression producing their name and as their 'value' a variable which | |
1568 // is refered to by the synthetic initializer function in order to | |
1569 // determine the name during class instantiation. This is necessary | |
1570 // because computed names must only be evaluated once, at class definition | |
1571 // time. | |
1572 // That is, code which looks like `class C { [f()] = 1; }` is desugared | |
1573 // into something like | |
1574 // class C { constructor(){ this.[.class-field-0-name] = 1; } }; | |
1575 // let .class-field-0-name = f(); | |
1576 // except that the assignment to .class-field-name-0 occurs interleaved | |
1577 // with the rest of the class body; it is performed by the block in which | |
1578 // this comment appears. | |
1579 DCHECK(property->value()->IsVariableProxy()); | |
1580 Variable* variable = property->value()->AsVariableProxy()->var(); | |
1581 VisitForAccumulatorValue(property->key()); | |
1582 VisitVariableAssignment(variable, Token::INIT, | |
1583 FeedbackVectorSlot::Invalid()); | |
1584 continue; | |
rmcilroy
2016/09/16 09:33:35
Drive-by - could you add an example of class field
bakkot
2016/09/16 18:59:53
Done.
rmcilroy
2016/09/19 10:06:08
Thanks!
| |
1585 } | |
1586 | |
1549 // Set-up receiver. | 1587 // Set-up receiver. |
1550 Register new_receiver = property->is_static() ? literal : prototype; | 1588 Register new_receiver = property->is_static() ? literal : prototype; |
1551 if (new_receiver != old_receiver) { | 1589 if (new_receiver != old_receiver) { |
1552 builder()->MoveRegister(new_receiver, receiver); | 1590 builder()->MoveRegister(new_receiver, receiver); |
1553 old_receiver = new_receiver; | 1591 old_receiver = new_receiver; |
1554 } | 1592 } |
1555 | 1593 |
1556 VisitForAccumulatorValue(property->key()); | 1594 VisitForAccumulatorValue(property->key()); |
1557 builder()->ConvertAccumulatorToName(key); | 1595 builder()->ConvertAccumulatorToName(key); |
1558 // The static prototype property is read only. We handle the non computed | 1596 // The static prototype property is read only. We handle the non computed |
(...skipping 28 matching lines...) Expand all Loading... | |
1587 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked, | 1625 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked, |
1588 receiver, 4); | 1626 receiver, 4); |
1589 break; | 1627 break; |
1590 } | 1628 } |
1591 case ClassLiteral::Property::SETTER: { | 1629 case ClassLiteral::Property::SETTER: { |
1592 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, | 1630 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, |
1593 receiver, 4); | 1631 receiver, 4); |
1594 break; | 1632 break; |
1595 } | 1633 } |
1596 case ClassLiteral::Property::FIELD: { | 1634 case ClassLiteral::Property::FIELD: { |
1597 UNREACHABLE(); | 1635 DCHECK(property->is_static()); |
1636 builder() | |
1637 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName())) | |
1638 .StoreAccumulatorInRegister(set_function_name); | |
1639 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, receiver, | |
1640 5); | |
1598 break; | 1641 break; |
1599 } | 1642 } |
1600 } | 1643 } |
1601 } | 1644 } |
1602 } | 1645 } |
1603 | 1646 |
1604 void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName( | 1647 void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName( |
1605 Register key) { | 1648 Register key) { |
1606 BytecodeLabel done; | 1649 BytecodeLabel done; |
1607 builder() | 1650 builder() |
(...skipping 1783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3391 return execution_context()->scope()->language_mode(); | 3434 return execution_context()->scope()->language_mode(); |
3392 } | 3435 } |
3393 | 3436 |
3394 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3437 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3395 return TypeFeedbackVector::GetIndex(slot); | 3438 return TypeFeedbackVector::GetIndex(slot); |
3396 } | 3439 } |
3397 | 3440 |
3398 } // namespace interpreter | 3441 } // namespace interpreter |
3399 } // namespace internal | 3442 } // namespace internal |
3400 } // namespace v8 | 3443 } // namespace v8 |
OLD | NEW |