OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
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/builtins/builtins-constructor.h" | 9 #include "src/builtins/builtins-constructor.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 __ CompareRoot(x1, Heap::kCatchContextMapRootIndex); | 741 __ CompareRoot(x1, Heap::kCatchContextMapRootIndex); |
742 __ Check(ne, kDeclarationInCatchContext); | 742 __ Check(ne, kDeclarationInCatchContext); |
743 } | 743 } |
744 } | 744 } |
745 | 745 |
746 | 746 |
747 void FullCodeGenerator::VisitVariableDeclaration( | 747 void FullCodeGenerator::VisitVariableDeclaration( |
748 VariableDeclaration* declaration) { | 748 VariableDeclaration* declaration) { |
749 VariableProxy* proxy = declaration->proxy(); | 749 VariableProxy* proxy = declaration->proxy(); |
750 Variable* variable = proxy->var(); | 750 Variable* variable = proxy->var(); |
751 DCHECK(!variable->binding_needs_init()); | |
752 switch (variable->location()) { | 751 switch (variable->location()) { |
753 case VariableLocation::UNALLOCATED: { | 752 case VariableLocation::UNALLOCATED: { |
| 753 DCHECK(!variable->binding_needs_init()); |
754 globals_->Add(variable->name(), zone()); | 754 globals_->Add(variable->name(), zone()); |
755 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); | 755 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); |
756 DCHECK(!slot.IsInvalid()); | 756 DCHECK(!slot.IsInvalid()); |
757 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); | 757 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); |
758 globals_->Add(isolate()->factory()->undefined_value(), zone()); | 758 globals_->Add(isolate()->factory()->undefined_value(), zone()); |
759 break; | 759 break; |
760 } | 760 } |
761 case VariableLocation::PARAMETER: | 761 case VariableLocation::PARAMETER: |
762 case VariableLocation::LOCAL: | 762 case VariableLocation::LOCAL: |
| 763 if (variable->binding_needs_init()) { |
| 764 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 765 __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); |
| 766 __ Str(x10, StackOperand(variable)); |
| 767 } |
| 768 break; |
| 769 |
763 case VariableLocation::CONTEXT: | 770 case VariableLocation::CONTEXT: |
| 771 if (variable->binding_needs_init()) { |
| 772 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 773 EmitDebugCheckDeclarationContext(variable); |
| 774 __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); |
| 775 __ Str(x10, ContextMemOperand(cp, variable->index())); |
| 776 // No write barrier since the_hole_value is in old space. |
| 777 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 778 } |
764 break; | 779 break; |
765 | 780 |
766 case VariableLocation::LOOKUP: | 781 case VariableLocation::LOOKUP: |
767 case VariableLocation::MODULE: | 782 case VariableLocation::MODULE: |
768 UNREACHABLE(); | 783 UNREACHABLE(); |
769 } | 784 } |
770 } | 785 } |
771 | 786 |
772 | 787 |
773 void FullCodeGenerator::VisitFunctionDeclaration( | 788 void FullCodeGenerator::VisitFunctionDeclaration( |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1110 __ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize); | 1125 __ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize); |
1111 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); | 1126 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); |
1112 } | 1127 } |
1113 | 1128 |
1114 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1129 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
1115 TypeofMode typeof_mode) { | 1130 TypeofMode typeof_mode) { |
1116 // Record position before possible IC call. | 1131 // Record position before possible IC call. |
1117 SetExpressionPosition(proxy); | 1132 SetExpressionPosition(proxy); |
1118 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 1133 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); |
1119 Variable* var = proxy->var(); | 1134 Variable* var = proxy->var(); |
1120 DCHECK(!var->binding_needs_init()); | |
1121 | 1135 |
1122 // Two cases: global variables and all other types of variables. | 1136 // Two cases: global variables and all other types of variables. |
1123 switch (var->location()) { | 1137 switch (var->location()) { |
1124 case VariableLocation::UNALLOCATED: { | 1138 case VariableLocation::UNALLOCATED: { |
1125 Comment cmnt(masm_, "Global variable"); | 1139 Comment cmnt(masm_, "Global variable"); |
1126 EmitGlobalVariableLoad(proxy, typeof_mode); | 1140 EmitGlobalVariableLoad(proxy, typeof_mode); |
1127 context()->Plug(x0); | 1141 context()->Plug(x0); |
1128 break; | 1142 break; |
1129 } | 1143 } |
1130 | 1144 |
1131 case VariableLocation::PARAMETER: | 1145 case VariableLocation::PARAMETER: |
1132 case VariableLocation::LOCAL: | 1146 case VariableLocation::LOCAL: |
1133 case VariableLocation::CONTEXT: { | 1147 case VariableLocation::CONTEXT: { |
1134 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); | 1148 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); |
1135 Comment cmnt(masm_, var->IsContextSlot() | 1149 Comment cmnt(masm_, var->IsContextSlot() |
1136 ? "Context variable" | 1150 ? "Context variable" |
1137 : "Stack variable"); | 1151 : "Stack variable"); |
| 1152 if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { |
| 1153 // Throw a reference error when using an uninitialized let/const |
| 1154 // binding in harmony mode. |
| 1155 Label done; |
| 1156 GetVar(x0, var); |
| 1157 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); |
| 1158 __ Mov(x0, Operand(var->name())); |
| 1159 __ Push(x0); |
| 1160 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1161 __ Bind(&done); |
| 1162 context()->Plug(x0); |
| 1163 break; |
| 1164 } |
1138 context()->Plug(var); | 1165 context()->Plug(var); |
1139 break; | 1166 break; |
1140 } | 1167 } |
1141 | 1168 |
1142 case VariableLocation::LOOKUP: | 1169 case VariableLocation::LOOKUP: |
1143 case VariableLocation::MODULE: | 1170 case VariableLocation::MODULE: |
1144 UNREACHABLE(); | 1171 UNREACHABLE(); |
1145 } | 1172 } |
1146 } | 1173 } |
1147 | 1174 |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1443 } else { | 1470 } else { |
1444 VisitForAccumulatorValue(expr->value()); | 1471 VisitForAccumulatorValue(expr->value()); |
1445 } | 1472 } |
1446 | 1473 |
1447 SetExpressionPosition(expr); | 1474 SetExpressionPosition(expr); |
1448 | 1475 |
1449 // Store the value. | 1476 // Store the value. |
1450 switch (assign_type) { | 1477 switch (assign_type) { |
1451 case VARIABLE: { | 1478 case VARIABLE: { |
1452 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 1479 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
1453 EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); | 1480 EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), |
| 1481 proxy->hole_check_mode()); |
1454 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 1482 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); |
1455 context()->Plug(x0); | 1483 context()->Plug(x0); |
1456 break; | 1484 break; |
1457 } | 1485 } |
1458 case NAMED_PROPERTY: | 1486 case NAMED_PROPERTY: |
1459 EmitNamedPropertyAssignment(expr); | 1487 EmitNamedPropertyAssignment(expr); |
1460 break; | 1488 break; |
1461 case KEYED_PROPERTY: | 1489 case KEYED_PROPERTY: |
1462 EmitKeyedPropertyAssignment(expr); | 1490 EmitKeyedPropertyAssignment(expr); |
1463 break; | 1491 break; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1584 FeedbackVectorSlot slot) { | 1612 FeedbackVectorSlot slot) { |
1585 DCHECK(expr->IsValidReferenceExpressionOrThis()); | 1613 DCHECK(expr->IsValidReferenceExpressionOrThis()); |
1586 | 1614 |
1587 Property* prop = expr->AsProperty(); | 1615 Property* prop = expr->AsProperty(); |
1588 LhsKind assign_type = Property::GetAssignType(prop); | 1616 LhsKind assign_type = Property::GetAssignType(prop); |
1589 | 1617 |
1590 switch (assign_type) { | 1618 switch (assign_type) { |
1591 case VARIABLE: { | 1619 case VARIABLE: { |
1592 VariableProxy* proxy = expr->AsVariableProxy(); | 1620 VariableProxy* proxy = expr->AsVariableProxy(); |
1593 EffectContext context(this); | 1621 EffectContext context(this); |
1594 EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); | 1622 EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, |
| 1623 proxy->hole_check_mode()); |
1595 break; | 1624 break; |
1596 } | 1625 } |
1597 case NAMED_PROPERTY: { | 1626 case NAMED_PROPERTY: { |
1598 PushOperand(x0); // Preserve value. | 1627 PushOperand(x0); // Preserve value. |
1599 VisitForAccumulatorValue(prop->obj()); | 1628 VisitForAccumulatorValue(prop->obj()); |
1600 // TODO(all): We could introduce a VisitForRegValue(reg, expr) to avoid | 1629 // TODO(all): We could introduce a VisitForRegValue(reg, expr) to avoid |
1601 // this copy. | 1630 // this copy. |
1602 __ Mov(StoreDescriptor::ReceiverRegister(), x0); | 1631 __ Mov(StoreDescriptor::ReceiverRegister(), x0); |
1603 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. | 1632 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. |
1604 CallStoreIC(slot, prop->key()->AsLiteral()->value()); | 1633 CallStoreIC(slot, prop->key()->AsLiteral()->value()); |
(...skipping 24 matching lines...) Expand all Loading... |
1629 if (var->IsContextSlot()) { | 1658 if (var->IsContextSlot()) { |
1630 // RecordWrite may destroy all its register arguments. | 1659 // RecordWrite may destroy all its register arguments. |
1631 __ Mov(x10, result_register()); | 1660 __ Mov(x10, result_register()); |
1632 int offset = Context::SlotOffset(var->index()); | 1661 int offset = Context::SlotOffset(var->index()); |
1633 __ RecordWriteContextSlot( | 1662 __ RecordWriteContextSlot( |
1634 x1, offset, x10, x11, kLRHasBeenSaved, kDontSaveFPRegs); | 1663 x1, offset, x10, x11, kLRHasBeenSaved, kDontSaveFPRegs); |
1635 } | 1664 } |
1636 } | 1665 } |
1637 | 1666 |
1638 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 1667 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
1639 FeedbackVectorSlot slot) { | 1668 FeedbackVectorSlot slot, |
| 1669 HoleCheckMode hole_check_mode) { |
1640 ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); | 1670 ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); |
1641 DCHECK(!var->binding_needs_init()); | |
1642 if (var->IsUnallocated()) { | 1671 if (var->IsUnallocated()) { |
1643 // Global var, const, or let. | 1672 // Global var, const, or let. |
1644 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); | 1673 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); |
1645 CallStoreIC(slot, var->name()); | 1674 CallStoreIC(slot, var->name()); |
1646 | 1675 |
1647 } else if (var->mode() == CONST && op != Token::INIT) { | 1676 } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { |
1648 if (var->throw_on_const_assignment(language_mode())) { | 1677 DCHECK(!var->IsLookupSlot()); |
| 1678 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 1679 MemOperand location = VarOperand(var, x1); |
| 1680 // Perform an initialization check for lexically declared variables. |
| 1681 if (var->binding_needs_init()) { |
| 1682 Label assign; |
| 1683 __ Ldr(x10, location); |
| 1684 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); |
| 1685 __ Mov(x10, Operand(var->name())); |
| 1686 __ Push(x10); |
| 1687 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1688 __ Bind(&assign); |
| 1689 } |
| 1690 if (var->mode() != CONST) { |
| 1691 EmitStoreToStackLocalOrContextSlot(var, location); |
| 1692 } else if (var->throw_on_const_assignment(language_mode())) { |
1649 __ CallRuntime(Runtime::kThrowConstAssignError); | 1693 __ CallRuntime(Runtime::kThrowConstAssignError); |
1650 } | 1694 } |
| 1695 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
| 1696 // Initializing assignment to const {this} needs a write barrier. |
| 1697 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 1698 Label uninitialized_this; |
| 1699 MemOperand location = VarOperand(var, x1); |
| 1700 __ Ldr(x10, location); |
| 1701 __ JumpIfRoot(x10, Heap::kTheHoleValueRootIndex, &uninitialized_this); |
| 1702 __ Mov(x0, Operand(var->name())); |
| 1703 __ Push(x0); |
| 1704 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1705 __ bind(&uninitialized_this); |
| 1706 EmitStoreToStackLocalOrContextSlot(var, location); |
| 1707 |
1651 } else { | 1708 } else { |
1652 DCHECK(!var->is_this()); | 1709 DCHECK(var->mode() != CONST || op == Token::INIT); |
1653 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 1710 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
1654 DCHECK(!var->IsLookupSlot()); | 1711 DCHECK(!var->IsLookupSlot()); |
| 1712 // Assignment to var or initializing assignment to let/const in harmony |
| 1713 // mode. |
1655 MemOperand location = VarOperand(var, x1); | 1714 MemOperand location = VarOperand(var, x1); |
| 1715 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
| 1716 __ Ldr(x10, location); |
| 1717 __ CompareRoot(x10, Heap::kTheHoleValueRootIndex); |
| 1718 __ Check(eq, kLetBindingReInitialization); |
| 1719 } |
1656 EmitStoreToStackLocalOrContextSlot(var, location); | 1720 EmitStoreToStackLocalOrContextSlot(var, location); |
1657 } | 1721 } |
1658 } | 1722 } |
1659 | 1723 |
1660 | 1724 |
1661 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1725 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1662 ASM_LOCATION("FullCodeGenerator::EmitNamedPropertyAssignment"); | 1726 ASM_LOCATION("FullCodeGenerator::EmitNamedPropertyAssignment"); |
1663 // Assignment to a property, using a named store IC. | 1727 // Assignment to a property, using a named store IC. |
1664 Property* prop = expr->target()->AsProperty(); | 1728 Property* prop = expr->target()->AsProperty(); |
1665 DCHECK(prop != NULL); | 1729 DCHECK(prop != NULL); |
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2378 patch_site.EmitPatchInfo(); | 2442 patch_site.EmitPatchInfo(); |
2379 } | 2443 } |
2380 __ Bind(&done); | 2444 __ Bind(&done); |
2381 | 2445 |
2382 // Store the value returned in x0. | 2446 // Store the value returned in x0. |
2383 switch (assign_type) { | 2447 switch (assign_type) { |
2384 case VARIABLE: { | 2448 case VARIABLE: { |
2385 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2449 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2386 if (expr->is_postfix()) { | 2450 if (expr->is_postfix()) { |
2387 { EffectContext context(this); | 2451 { EffectContext context(this); |
2388 EmitVariableAssignment(proxy->var(), Token::ASSIGN, | 2452 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), |
2389 expr->CountSlot()); | 2453 proxy->hole_check_mode()); |
2390 PrepareForBailoutForId(expr->AssignmentId(), | 2454 PrepareForBailoutForId(expr->AssignmentId(), |
2391 BailoutState::TOS_REGISTER); | 2455 BailoutState::TOS_REGISTER); |
2392 context.Plug(x0); | 2456 context.Plug(x0); |
2393 } | 2457 } |
2394 // For all contexts except EffectConstant We have the result on | 2458 // For all contexts except EffectConstant We have the result on |
2395 // top of the stack. | 2459 // top of the stack. |
2396 if (!context()->IsEffect()) { | 2460 if (!context()->IsEffect()) { |
2397 context()->PlugTOS(); | 2461 context()->PlugTOS(); |
2398 } | 2462 } |
2399 } else { | 2463 } else { |
2400 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); | 2464 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), |
| 2465 proxy->hole_check_mode()); |
2401 PrepareForBailoutForId(expr->AssignmentId(), | 2466 PrepareForBailoutForId(expr->AssignmentId(), |
2402 BailoutState::TOS_REGISTER); | 2467 BailoutState::TOS_REGISTER); |
2403 context()->Plug(x0); | 2468 context()->Plug(x0); |
2404 } | 2469 } |
2405 break; | 2470 break; |
2406 } | 2471 } |
2407 case NAMED_PROPERTY: { | 2472 case NAMED_PROPERTY: { |
2408 PopOperand(StoreDescriptor::ReceiverRegister()); | 2473 PopOperand(StoreDescriptor::ReceiverRegister()); |
2409 CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); | 2474 CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); |
2410 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 2475 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2838 } | 2903 } |
2839 | 2904 |
2840 return INTERRUPT; | 2905 return INTERRUPT; |
2841 } | 2906 } |
2842 | 2907 |
2843 | 2908 |
2844 } // namespace internal | 2909 } // namespace internal |
2845 } // namespace v8 | 2910 } // namespace v8 |
2846 | 2911 |
2847 #endif // V8_TARGET_ARCH_ARM64 | 2912 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |