| 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 |