OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_PPC | 5 #if V8_TARGET_ARCH_PPC |
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 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 __ CompareRoot(r4, Heap::kCatchContextMapRootIndex); | 716 __ CompareRoot(r4, Heap::kCatchContextMapRootIndex); |
717 __ Check(ne, kDeclarationInCatchContext); | 717 __ Check(ne, kDeclarationInCatchContext); |
718 } | 718 } |
719 } | 719 } |
720 | 720 |
721 | 721 |
722 void FullCodeGenerator::VisitVariableDeclaration( | 722 void FullCodeGenerator::VisitVariableDeclaration( |
723 VariableDeclaration* declaration) { | 723 VariableDeclaration* declaration) { |
724 VariableProxy* proxy = declaration->proxy(); | 724 VariableProxy* proxy = declaration->proxy(); |
725 Variable* variable = proxy->var(); | 725 Variable* variable = proxy->var(); |
| 726 DCHECK(!variable->binding_needs_init()); |
726 switch (variable->location()) { | 727 switch (variable->location()) { |
727 case VariableLocation::UNALLOCATED: { | 728 case VariableLocation::UNALLOCATED: { |
728 DCHECK(!variable->binding_needs_init()); | |
729 globals_->Add(variable->name(), zone()); | 729 globals_->Add(variable->name(), zone()); |
730 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); | 730 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); |
731 DCHECK(!slot.IsInvalid()); | 731 DCHECK(!slot.IsInvalid()); |
732 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); | 732 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); |
733 globals_->Add(isolate()->factory()->undefined_value(), zone()); | 733 globals_->Add(isolate()->factory()->undefined_value(), zone()); |
734 break; | 734 break; |
735 } | 735 } |
736 case VariableLocation::PARAMETER: | 736 case VariableLocation::PARAMETER: |
737 case VariableLocation::LOCAL: | 737 case VariableLocation::LOCAL: |
738 if (variable->binding_needs_init()) { | |
739 Comment cmnt(masm_, "[ VariableDeclaration"); | |
740 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
741 __ StoreP(ip, StackOperand(variable)); | |
742 } | |
743 break; | |
744 | |
745 case VariableLocation::CONTEXT: | 738 case VariableLocation::CONTEXT: |
746 if (variable->binding_needs_init()) { | |
747 Comment cmnt(masm_, "[ VariableDeclaration"); | |
748 EmitDebugCheckDeclarationContext(variable); | |
749 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
750 __ StoreP(ip, ContextMemOperand(cp, variable->index()), r0); | |
751 // No write barrier since the_hole_value is in old space. | |
752 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | |
753 } | |
754 break; | 739 break; |
755 | 740 |
756 case VariableLocation::LOOKUP: | 741 case VariableLocation::LOOKUP: |
757 case VariableLocation::MODULE: | 742 case VariableLocation::MODULE: |
758 UNREACHABLE(); | 743 UNREACHABLE(); |
759 } | 744 } |
760 } | 745 } |
761 | 746 |
762 | 747 |
763 void FullCodeGenerator::VisitFunctionDeclaration( | 748 void FullCodeGenerator::VisitFunctionDeclaration( |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1111 MemOperand(sp, offset * kPointerSize)); | 1096 MemOperand(sp, offset * kPointerSize)); |
1112 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); | 1097 CallStoreIC(slot, isolate()->factory()->home_object_symbol()); |
1113 } | 1098 } |
1114 | 1099 |
1115 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1100 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
1116 TypeofMode typeof_mode) { | 1101 TypeofMode typeof_mode) { |
1117 // Record position before possible IC call. | 1102 // Record position before possible IC call. |
1118 SetExpressionPosition(proxy); | 1103 SetExpressionPosition(proxy); |
1119 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 1104 PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); |
1120 Variable* var = proxy->var(); | 1105 Variable* var = proxy->var(); |
| 1106 DCHECK(!var->binding_needs_init()); |
1121 | 1107 |
1122 // Two cases: global variables and all other types of variables. | 1108 // Two cases: global variables and all other types of variables. |
1123 switch (var->location()) { | 1109 switch (var->location()) { |
1124 case VariableLocation::UNALLOCATED: { | 1110 case VariableLocation::UNALLOCATED: { |
1125 Comment cmnt(masm_, "[ Global variable"); | 1111 Comment cmnt(masm_, "[ Global variable"); |
1126 EmitGlobalVariableLoad(proxy, typeof_mode); | 1112 EmitGlobalVariableLoad(proxy, typeof_mode); |
1127 context()->Plug(r3); | 1113 context()->Plug(r3); |
1128 break; | 1114 break; |
1129 } | 1115 } |
1130 | 1116 |
1131 case VariableLocation::PARAMETER: | 1117 case VariableLocation::PARAMETER: |
1132 case VariableLocation::LOCAL: | 1118 case VariableLocation::LOCAL: |
1133 case VariableLocation::CONTEXT: { | 1119 case VariableLocation::CONTEXT: { |
1134 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); | 1120 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); |
1135 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1121 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1136 : "[ Stack variable"); | 1122 : "[ Stack variable"); |
1137 if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { | |
1138 // Throw a reference error when using an uninitialized let/const | |
1139 // binding in harmony mode. | |
1140 Label done; | |
1141 GetVar(r3, var); | |
1142 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | |
1143 __ bne(&done); | |
1144 __ mov(r3, Operand(var->name())); | |
1145 __ push(r3); | |
1146 __ CallRuntime(Runtime::kThrowReferenceError); | |
1147 __ bind(&done); | |
1148 context()->Plug(r3); | |
1149 break; | |
1150 } | |
1151 context()->Plug(var); | 1123 context()->Plug(var); |
1152 break; | 1124 break; |
1153 } | 1125 } |
1154 | 1126 |
1155 case VariableLocation::LOOKUP: | 1127 case VariableLocation::LOOKUP: |
1156 case VariableLocation::MODULE: | 1128 case VariableLocation::MODULE: |
1157 UNREACHABLE(); | 1129 UNREACHABLE(); |
1158 } | 1130 } |
1159 } | 1131 } |
1160 | 1132 |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 } else { | 1425 } else { |
1454 VisitForAccumulatorValue(expr->value()); | 1426 VisitForAccumulatorValue(expr->value()); |
1455 } | 1427 } |
1456 | 1428 |
1457 SetExpressionPosition(expr); | 1429 SetExpressionPosition(expr); |
1458 | 1430 |
1459 // Store the value. | 1431 // Store the value. |
1460 switch (assign_type) { | 1432 switch (assign_type) { |
1461 case VARIABLE: { | 1433 case VARIABLE: { |
1462 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 1434 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
1463 EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), | 1435 EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); |
1464 proxy->hole_check_mode()); | |
1465 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 1436 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); |
1466 context()->Plug(r3); | 1437 context()->Plug(r3); |
1467 break; | 1438 break; |
1468 } | 1439 } |
1469 case NAMED_PROPERTY: | 1440 case NAMED_PROPERTY: |
1470 EmitNamedPropertyAssignment(expr); | 1441 EmitNamedPropertyAssignment(expr); |
1471 break; | 1442 break; |
1472 case KEYED_PROPERTY: | 1443 case KEYED_PROPERTY: |
1473 EmitKeyedPropertyAssignment(expr); | 1444 EmitKeyedPropertyAssignment(expr); |
1474 break; | 1445 break; |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1681 FeedbackVectorSlot slot) { | 1652 FeedbackVectorSlot slot) { |
1682 DCHECK(expr->IsValidReferenceExpressionOrThis()); | 1653 DCHECK(expr->IsValidReferenceExpressionOrThis()); |
1683 | 1654 |
1684 Property* prop = expr->AsProperty(); | 1655 Property* prop = expr->AsProperty(); |
1685 LhsKind assign_type = Property::GetAssignType(prop); | 1656 LhsKind assign_type = Property::GetAssignType(prop); |
1686 | 1657 |
1687 switch (assign_type) { | 1658 switch (assign_type) { |
1688 case VARIABLE: { | 1659 case VARIABLE: { |
1689 VariableProxy* proxy = expr->AsVariableProxy(); | 1660 VariableProxy* proxy = expr->AsVariableProxy(); |
1690 EffectContext context(this); | 1661 EffectContext context(this); |
1691 EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, | 1662 EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); |
1692 proxy->hole_check_mode()); | |
1693 break; | 1663 break; |
1694 } | 1664 } |
1695 case NAMED_PROPERTY: { | 1665 case NAMED_PROPERTY: { |
1696 PushOperand(r3); // Preserve value. | 1666 PushOperand(r3); // Preserve value. |
1697 VisitForAccumulatorValue(prop->obj()); | 1667 VisitForAccumulatorValue(prop->obj()); |
1698 __ Move(StoreDescriptor::ReceiverRegister(), r3); | 1668 __ Move(StoreDescriptor::ReceiverRegister(), r3); |
1699 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. | 1669 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. |
1700 CallStoreIC(slot, prop->key()->AsLiteral()->value()); | 1670 CallStoreIC(slot, prop->key()->AsLiteral()->value()); |
1701 break; | 1671 break; |
1702 } | 1672 } |
(...skipping 22 matching lines...) Expand all Loading... |
1725 if (var->IsContextSlot()) { | 1695 if (var->IsContextSlot()) { |
1726 // RecordWrite may destroy all its register arguments. | 1696 // RecordWrite may destroy all its register arguments. |
1727 __ mr(r6, result_register()); | 1697 __ mr(r6, result_register()); |
1728 int offset = Context::SlotOffset(var->index()); | 1698 int offset = Context::SlotOffset(var->index()); |
1729 __ RecordWriteContextSlot(r4, offset, r6, r5, kLRHasBeenSaved, | 1699 __ RecordWriteContextSlot(r4, offset, r6, r5, kLRHasBeenSaved, |
1730 kDontSaveFPRegs); | 1700 kDontSaveFPRegs); |
1731 } | 1701 } |
1732 } | 1702 } |
1733 | 1703 |
1734 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 1704 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
1735 FeedbackVectorSlot slot, | 1705 FeedbackVectorSlot slot) { |
1736 HoleCheckMode hole_check_mode) { | 1706 DCHECK(!var->binding_needs_init()); |
1737 if (var->IsUnallocated()) { | 1707 if (var->IsUnallocated()) { |
1738 // Global var, const, or let. | 1708 // Global var, const, or let. |
1739 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); | 1709 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); |
1740 CallStoreIC(slot, var->name()); | 1710 CallStoreIC(slot, var->name()); |
1741 | 1711 |
1742 } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { | 1712 } else if (var->mode() == CONST && op != Token::INIT) { |
1743 DCHECK(!var->IsLookupSlot()); | 1713 if (var->throw_on_const_assignment(language_mode())) { |
1744 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | |
1745 MemOperand location = VarOperand(var, r4); | |
1746 // Perform an initialization check for lexically declared variables. | |
1747 if (hole_check_mode == HoleCheckMode::kRequired) { | |
1748 Label assign; | |
1749 __ LoadP(r6, location); | |
1750 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); | |
1751 __ bne(&assign); | |
1752 __ mov(r6, Operand(var->name())); | |
1753 __ push(r6); | |
1754 __ CallRuntime(Runtime::kThrowReferenceError); | |
1755 __ bind(&assign); | |
1756 } | |
1757 if (var->mode() != CONST) { | |
1758 EmitStoreToStackLocalOrContextSlot(var, location); | |
1759 } else if (var->throw_on_const_assignment(language_mode())) { | |
1760 __ CallRuntime(Runtime::kThrowConstAssignError); | 1714 __ CallRuntime(Runtime::kThrowConstAssignError); |
1761 } | 1715 } |
1762 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | |
1763 // Initializing assignment to const {this} needs a write barrier. | |
1764 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | |
1765 Label uninitialized_this; | |
1766 MemOperand location = VarOperand(var, r4); | |
1767 __ LoadP(r6, location); | |
1768 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); | |
1769 __ beq(&uninitialized_this); | |
1770 __ mov(r4, Operand(var->name())); | |
1771 __ push(r4); | |
1772 __ CallRuntime(Runtime::kThrowReferenceError); | |
1773 __ bind(&uninitialized_this); | |
1774 EmitStoreToStackLocalOrContextSlot(var, location); | |
1775 | |
1776 } else { | 1716 } else { |
1777 DCHECK(var->mode() != CONST || op == Token::INIT); | 1717 DCHECK(!var->is_this()); |
1778 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 1718 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
1779 DCHECK(!var->IsLookupSlot()); | 1719 DCHECK(!var->IsLookupSlot()); |
1780 // Assignment to var or initializing assignment to let/const in harmony | |
1781 // mode. | |
1782 MemOperand location = VarOperand(var, r4); | 1720 MemOperand location = VarOperand(var, r4); |
1783 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | |
1784 // Check for an uninitialized let binding. | |
1785 __ LoadP(r5, location); | |
1786 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | |
1787 __ Check(eq, kLetBindingReInitialization); | |
1788 } | |
1789 EmitStoreToStackLocalOrContextSlot(var, location); | 1721 EmitStoreToStackLocalOrContextSlot(var, location); |
1790 } | 1722 } |
1791 } | 1723 } |
1792 | 1724 |
1793 | 1725 |
1794 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1726 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1795 // Assignment to a property, using a named store IC. | 1727 // Assignment to a property, using a named store IC. |
1796 Property* prop = expr->target()->AsProperty(); | 1728 Property* prop = expr->target()->AsProperty(); |
1797 DCHECK(prop != NULL); | 1729 DCHECK(prop != NULL); |
1798 DCHECK(prop->key()->IsLiteral()); | 1730 DCHECK(prop->key()->IsLiteral()); |
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2509 patch_site.EmitPatchInfo(); | 2441 patch_site.EmitPatchInfo(); |
2510 __ bind(&done); | 2442 __ bind(&done); |
2511 | 2443 |
2512 // Store the value returned in r3. | 2444 // Store the value returned in r3. |
2513 switch (assign_type) { | 2445 switch (assign_type) { |
2514 case VARIABLE: { | 2446 case VARIABLE: { |
2515 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2447 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2516 if (expr->is_postfix()) { | 2448 if (expr->is_postfix()) { |
2517 { | 2449 { |
2518 EffectContext context(this); | 2450 EffectContext context(this); |
2519 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), | 2451 EmitVariableAssignment(proxy->var(), Token::ASSIGN, |
2520 proxy->hole_check_mode()); | 2452 expr->CountSlot()); |
2521 PrepareForBailoutForId(expr->AssignmentId(), | 2453 PrepareForBailoutForId(expr->AssignmentId(), |
2522 BailoutState::TOS_REGISTER); | 2454 BailoutState::TOS_REGISTER); |
2523 context.Plug(r3); | 2455 context.Plug(r3); |
2524 } | 2456 } |
2525 // For all contexts except EffectConstant We have the result on | 2457 // For all contexts except EffectConstant We have the result on |
2526 // top of the stack. | 2458 // top of the stack. |
2527 if (!context()->IsEffect()) { | 2459 if (!context()->IsEffect()) { |
2528 context()->PlugTOS(); | 2460 context()->PlugTOS(); |
2529 } | 2461 } |
2530 } else { | 2462 } else { |
2531 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), | 2463 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); |
2532 proxy->hole_check_mode()); | |
2533 PrepareForBailoutForId(expr->AssignmentId(), | 2464 PrepareForBailoutForId(expr->AssignmentId(), |
2534 BailoutState::TOS_REGISTER); | 2465 BailoutState::TOS_REGISTER); |
2535 context()->Plug(r3); | 2466 context()->Plug(r3); |
2536 } | 2467 } |
2537 break; | 2468 break; |
2538 } | 2469 } |
2539 case NAMED_PROPERTY: { | 2470 case NAMED_PROPERTY: { |
2540 PopOperand(StoreDescriptor::ReceiverRegister()); | 2471 PopOperand(StoreDescriptor::ReceiverRegister()); |
2541 CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); | 2472 CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); |
2542 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 2473 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2862 | 2793 |
2863 DCHECK(Assembler::IsCrSet(Assembler::instr_at(cmp_address))); | 2794 DCHECK(Assembler::IsCrSet(Assembler::instr_at(cmp_address))); |
2864 | 2795 |
2865 DCHECK(interrupt_address == | 2796 DCHECK(interrupt_address == |
2866 isolate->builtins()->OnStackReplacement()->entry()); | 2797 isolate->builtins()->OnStackReplacement()->entry()); |
2867 return ON_STACK_REPLACEMENT; | 2798 return ON_STACK_REPLACEMENT; |
2868 } | 2799 } |
2869 } // namespace internal | 2800 } // namespace internal |
2870 } // namespace v8 | 2801 } // namespace v8 |
2871 #endif // V8_TARGET_ARCH_PPC | 2802 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |