| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 | 
| 6 | 6 | 
| 7 // Note on Mips implementation: | 7 // Note on Mips implementation: | 
| 8 // | 8 // | 
| 9 // The result_register() for mips is the 'v0' register, which is defined | 9 // The result_register() for mips is the 'v0' register, which is defined | 
| 10 // by the ABI to contain function return values. However, the first | 10 // by the ABI to contain function return values. However, the first | 
| (...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 745     __ Check(ne, kDeclarationInCatchContext, | 745     __ Check(ne, kDeclarationInCatchContext, | 
| 746         a1, Operand(a4)); | 746         a1, Operand(a4)); | 
| 747   } | 747   } | 
| 748 } | 748 } | 
| 749 | 749 | 
| 750 | 750 | 
| 751 void FullCodeGenerator::VisitVariableDeclaration( | 751 void FullCodeGenerator::VisitVariableDeclaration( | 
| 752     VariableDeclaration* declaration) { | 752     VariableDeclaration* declaration) { | 
| 753   VariableProxy* proxy = declaration->proxy(); | 753   VariableProxy* proxy = declaration->proxy(); | 
| 754   Variable* variable = proxy->var(); | 754   Variable* variable = proxy->var(); | 
| 755   DCHECK(!variable->binding_needs_init()); |  | 
| 756   switch (variable->location()) { | 755   switch (variable->location()) { | 
| 757     case VariableLocation::UNALLOCATED: { | 756     case VariableLocation::UNALLOCATED: { | 
|  | 757       DCHECK(!variable->binding_needs_init()); | 
| 758       globals_->Add(variable->name(), zone()); | 758       globals_->Add(variable->name(), zone()); | 
| 759       FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); | 759       FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); | 
| 760       DCHECK(!slot.IsInvalid()); | 760       DCHECK(!slot.IsInvalid()); | 
| 761       globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); | 761       globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); | 
| 762       globals_->Add(isolate()->factory()->undefined_value(), zone()); | 762       globals_->Add(isolate()->factory()->undefined_value(), zone()); | 
| 763       break; | 763       break; | 
| 764     } | 764     } | 
| 765     case VariableLocation::PARAMETER: | 765     case VariableLocation::PARAMETER: | 
| 766     case VariableLocation::LOCAL: | 766     case VariableLocation::LOCAL: | 
|  | 767       if (variable->binding_needs_init()) { | 
|  | 768         Comment cmnt(masm_, "[ VariableDeclaration"); | 
|  | 769         __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); | 
|  | 770         __ sd(a4, StackOperand(variable)); | 
|  | 771       } | 
|  | 772       break; | 
|  | 773 | 
| 767     case VariableLocation::CONTEXT: | 774     case VariableLocation::CONTEXT: | 
|  | 775       if (variable->binding_needs_init()) { | 
|  | 776         Comment cmnt(masm_, "[ VariableDeclaration"); | 
|  | 777         EmitDebugCheckDeclarationContext(variable); | 
|  | 778           __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 
|  | 779           __ sd(at, ContextMemOperand(cp, variable->index())); | 
|  | 780           // No write barrier since the_hole_value is in old space. | 
|  | 781           PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 
|  | 782       } | 
| 768       break; | 783       break; | 
| 769 | 784 | 
| 770     case VariableLocation::LOOKUP: | 785     case VariableLocation::LOOKUP: | 
| 771     case VariableLocation::MODULE: | 786     case VariableLocation::MODULE: | 
| 772       UNREACHABLE(); | 787       UNREACHABLE(); | 
| 773   } | 788   } | 
| 774 } | 789 } | 
| 775 | 790 | 
| 776 | 791 | 
| 777 void FullCodeGenerator::VisitFunctionDeclaration( | 792 void FullCodeGenerator::VisitFunctionDeclaration( | 
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1124         MemOperand(sp, offset * kPointerSize)); | 1139         MemOperand(sp, offset * kPointerSize)); | 
| 1125   CallStoreIC(slot, isolate()->factory()->home_object_symbol()); | 1140   CallStoreIC(slot, isolate()->factory()->home_object_symbol()); | 
| 1126 } | 1141 } | 
| 1127 | 1142 | 
| 1128 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1143 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 
| 1129                                          TypeofMode typeof_mode) { | 1144                                          TypeofMode typeof_mode) { | 
| 1130   // Record position before possible IC call. | 1145   // Record position before possible IC call. | 
| 1131   SetExpressionPosition(proxy); | 1146   SetExpressionPosition(proxy); | 
| 1132   PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 1147   PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); | 
| 1133   Variable* var = proxy->var(); | 1148   Variable* var = proxy->var(); | 
| 1134   DCHECK(!var->binding_needs_init()); |  | 
| 1135 | 1149 | 
| 1136   // Two cases: global variables and all other types of variables. | 1150   // Two cases: global variables and all other types of variables. | 
| 1137   switch (var->location()) { | 1151   switch (var->location()) { | 
| 1138     case VariableLocation::UNALLOCATED: { | 1152     case VariableLocation::UNALLOCATED: { | 
| 1139       Comment cmnt(masm_, "[ Global variable"); | 1153       Comment cmnt(masm_, "[ Global variable"); | 
| 1140       EmitGlobalVariableLoad(proxy, typeof_mode); | 1154       EmitGlobalVariableLoad(proxy, typeof_mode); | 
| 1141       context()->Plug(v0); | 1155       context()->Plug(v0); | 
| 1142       break; | 1156       break; | 
| 1143     } | 1157     } | 
| 1144 | 1158 | 
| 1145     case VariableLocation::PARAMETER: | 1159     case VariableLocation::PARAMETER: | 
| 1146     case VariableLocation::LOCAL: | 1160     case VariableLocation::LOCAL: | 
| 1147     case VariableLocation::CONTEXT: { | 1161     case VariableLocation::CONTEXT: { | 
| 1148       DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); | 1162       DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); | 
| 1149       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1163       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 
| 1150                                                : "[ Stack variable"); | 1164                                                : "[ Stack variable"); | 
|  | 1165       if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { | 
|  | 1166         // Throw a reference error when using an uninitialized let/const | 
|  | 1167         // binding in harmony mode. | 
|  | 1168         Label done; | 
|  | 1169         GetVar(v0, var); | 
|  | 1170         __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 
|  | 1171         __ dsubu(at, v0, at);  // Sub as compare: at == 0 on eq. | 
|  | 1172         __ Branch(&done, ne, at, Operand(zero_reg)); | 
|  | 1173         __ li(a0, Operand(var->name())); | 
|  | 1174         __ push(a0); | 
|  | 1175         __ CallRuntime(Runtime::kThrowReferenceError); | 
|  | 1176         __ bind(&done); | 
|  | 1177         context()->Plug(v0); | 
|  | 1178         break; | 
|  | 1179       } | 
| 1151       context()->Plug(var); | 1180       context()->Plug(var); | 
| 1152       break; | 1181       break; | 
| 1153     } | 1182     } | 
| 1154 | 1183 | 
| 1155     case VariableLocation::LOOKUP: | 1184     case VariableLocation::LOOKUP: | 
| 1156     case VariableLocation::MODULE: | 1185     case VariableLocation::MODULE: | 
| 1157       UNREACHABLE(); | 1186       UNREACHABLE(); | 
| 1158   } | 1187   } | 
| 1159 } | 1188 } | 
| 1160 | 1189 | 
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1462   } else { | 1491   } else { | 
| 1463     VisitForAccumulatorValue(expr->value()); | 1492     VisitForAccumulatorValue(expr->value()); | 
| 1464   } | 1493   } | 
| 1465 | 1494 | 
| 1466   SetExpressionPosition(expr); | 1495   SetExpressionPosition(expr); | 
| 1467 | 1496 | 
| 1468   // Store the value. | 1497   // Store the value. | 
| 1469   switch (assign_type) { | 1498   switch (assign_type) { | 
| 1470     case VARIABLE: { | 1499     case VARIABLE: { | 
| 1471       VariableProxy* proxy = expr->target()->AsVariableProxy(); | 1500       VariableProxy* proxy = expr->target()->AsVariableProxy(); | 
| 1472       EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); | 1501       EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), | 
|  | 1502                              proxy->hole_check_mode()); | 
| 1473       PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 1503       PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 
| 1474       context()->Plug(v0); | 1504       context()->Plug(v0); | 
| 1475       break; | 1505       break; | 
| 1476     } | 1506     } | 
| 1477     case NAMED_PROPERTY: | 1507     case NAMED_PROPERTY: | 
| 1478       EmitNamedPropertyAssignment(expr); | 1508       EmitNamedPropertyAssignment(expr); | 
| 1479       break; | 1509       break; | 
| 1480     case KEYED_PROPERTY: | 1510     case KEYED_PROPERTY: | 
| 1481       EmitKeyedPropertyAssignment(expr); | 1511       EmitKeyedPropertyAssignment(expr); | 
| 1482       break; | 1512       break; | 
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1653                                        FeedbackVectorSlot slot) { | 1683                                        FeedbackVectorSlot slot) { | 
| 1654   DCHECK(expr->IsValidReferenceExpressionOrThis()); | 1684   DCHECK(expr->IsValidReferenceExpressionOrThis()); | 
| 1655 | 1685 | 
| 1656   Property* prop = expr->AsProperty(); | 1686   Property* prop = expr->AsProperty(); | 
| 1657   LhsKind assign_type = Property::GetAssignType(prop); | 1687   LhsKind assign_type = Property::GetAssignType(prop); | 
| 1658 | 1688 | 
| 1659   switch (assign_type) { | 1689   switch (assign_type) { | 
| 1660     case VARIABLE: { | 1690     case VARIABLE: { | 
| 1661       VariableProxy* proxy = expr->AsVariableProxy(); | 1691       VariableProxy* proxy = expr->AsVariableProxy(); | 
| 1662       EffectContext context(this); | 1692       EffectContext context(this); | 
| 1663       EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); | 1693       EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, | 
|  | 1694                              proxy->hole_check_mode()); | 
| 1664       break; | 1695       break; | 
| 1665     } | 1696     } | 
| 1666     case NAMED_PROPERTY: { | 1697     case NAMED_PROPERTY: { | 
| 1667       PushOperand(result_register());  // Preserve value. | 1698       PushOperand(result_register());  // Preserve value. | 
| 1668       VisitForAccumulatorValue(prop->obj()); | 1699       VisitForAccumulatorValue(prop->obj()); | 
| 1669       __ mov(StoreDescriptor::ReceiverRegister(), result_register()); | 1700       __ mov(StoreDescriptor::ReceiverRegister(), result_register()); | 
| 1670       PopOperand(StoreDescriptor::ValueRegister());  // Restore value. | 1701       PopOperand(StoreDescriptor::ValueRegister());  // Restore value. | 
| 1671       CallStoreIC(slot, prop->key()->AsLiteral()->value()); | 1702       CallStoreIC(slot, prop->key()->AsLiteral()->value()); | 
| 1672       break; | 1703       break; | 
| 1673     } | 1704     } | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 1696   if (var->IsContextSlot()) { | 1727   if (var->IsContextSlot()) { | 
| 1697     // RecordWrite may destroy all its register arguments. | 1728     // RecordWrite may destroy all its register arguments. | 
| 1698     __ Move(a3, result_register()); | 1729     __ Move(a3, result_register()); | 
| 1699     int offset = Context::SlotOffset(var->index()); | 1730     int offset = Context::SlotOffset(var->index()); | 
| 1700     __ RecordWriteContextSlot( | 1731     __ RecordWriteContextSlot( | 
| 1701         a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); | 1732         a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); | 
| 1702   } | 1733   } | 
| 1703 } | 1734 } | 
| 1704 | 1735 | 
| 1705 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 1736 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 
| 1706                                                FeedbackVectorSlot slot) { | 1737                                                FeedbackVectorSlot slot, | 
| 1707   DCHECK(!var->binding_needs_init()); | 1738                                                HoleCheckMode hole_check_mode) { | 
| 1708   if (var->IsUnallocated()) { | 1739   if (var->IsUnallocated()) { | 
| 1709     // Global var, const, or let. | 1740     // Global var, const, or let. | 
| 1710     __ mov(StoreDescriptor::ValueRegister(), result_register()); | 1741     __ mov(StoreDescriptor::ValueRegister(), result_register()); | 
| 1711     __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); | 1742     __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); | 
| 1712     CallStoreIC(slot, var->name()); | 1743     CallStoreIC(slot, var->name()); | 
| 1713 | 1744 | 
| 1714   } else if (var->mode() == CONST && op != Token::INIT) { | 1745   } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { | 
| 1715     if (var->throw_on_const_assignment(language_mode())) { | 1746     DCHECK(!var->IsLookupSlot()); | 
|  | 1747     DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 
|  | 1748     MemOperand location = VarOperand(var, a1); | 
|  | 1749     // Perform an initialization check for lexically declared variables. | 
|  | 1750     if (hole_check_mode == HoleCheckMode::kRequired) { | 
|  | 1751       Label assign; | 
|  | 1752       __ ld(a3, location); | 
|  | 1753       __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); | 
|  | 1754       __ Branch(&assign, ne, a3, Operand(a4)); | 
|  | 1755       __ li(a3, Operand(var->name())); | 
|  | 1756       __ push(a3); | 
|  | 1757       __ CallRuntime(Runtime::kThrowReferenceError); | 
|  | 1758       __ bind(&assign); | 
|  | 1759     } | 
|  | 1760     if (var->mode() != CONST) { | 
|  | 1761       EmitStoreToStackLocalOrContextSlot(var, location); | 
|  | 1762     } else if (var->throw_on_const_assignment(language_mode())) { | 
| 1716       __ CallRuntime(Runtime::kThrowConstAssignError); | 1763       __ CallRuntime(Runtime::kThrowConstAssignError); | 
| 1717     } | 1764     } | 
|  | 1765   } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 
|  | 1766     // Initializing assignment to const {this} needs a write barrier. | 
|  | 1767     DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 
|  | 1768     Label uninitialized_this; | 
|  | 1769     MemOperand location = VarOperand(var, a1); | 
|  | 1770     __ ld(a3, location); | 
|  | 1771     __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 
|  | 1772     __ Branch(&uninitialized_this, eq, a3, Operand(at)); | 
|  | 1773     __ li(a0, Operand(var->name())); | 
|  | 1774     __ Push(a0); | 
|  | 1775     __ CallRuntime(Runtime::kThrowReferenceError); | 
|  | 1776     __ bind(&uninitialized_this); | 
|  | 1777     EmitStoreToStackLocalOrContextSlot(var, location); | 
|  | 1778 | 
| 1718   } else { | 1779   } else { | 
| 1719     DCHECK(!var->is_this()); | 1780     DCHECK(var->mode() != CONST || op == Token::INIT); | 
| 1720     DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 1781     DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 
| 1721     DCHECK(!var->IsLookupSlot()); | 1782     DCHECK(!var->IsLookupSlot()); | 
|  | 1783     // Assignment to var or initializing assignment to let/const in harmony | 
|  | 1784     // mode. | 
| 1722     MemOperand location = VarOperand(var, a1); | 1785     MemOperand location = VarOperand(var, a1); | 
|  | 1786     if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | 
|  | 1787       // Check for an uninitialized let binding. | 
|  | 1788       __ ld(a2, location); | 
|  | 1789       __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); | 
|  | 1790       __ Check(eq, kLetBindingReInitialization, a2, Operand(a4)); | 
|  | 1791     } | 
| 1723     EmitStoreToStackLocalOrContextSlot(var, location); | 1792     EmitStoreToStackLocalOrContextSlot(var, location); | 
| 1724   } | 1793   } | 
| 1725 } | 1794 } | 
| 1726 | 1795 | 
| 1727 | 1796 | 
| 1728 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1797 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 
| 1729   // Assignment to a property, using a named store IC. | 1798   // Assignment to a property, using a named store IC. | 
| 1730   Property* prop = expr->target()->AsProperty(); | 1799   Property* prop = expr->target()->AsProperty(); | 
| 1731   DCHECK(prop != NULL); | 1800   DCHECK(prop != NULL); | 
| 1732   DCHECK(prop->key()->IsLiteral()); | 1801   DCHECK(prop->key()->IsLiteral()); | 
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2432   CallIC(code, expr->CountBinOpFeedbackId()); | 2501   CallIC(code, expr->CountBinOpFeedbackId()); | 
| 2433   patch_site.EmitPatchInfo(); | 2502   patch_site.EmitPatchInfo(); | 
| 2434   __ bind(&done); | 2503   __ bind(&done); | 
| 2435 | 2504 | 
| 2436   // Store the value returned in v0. | 2505   // Store the value returned in v0. | 
| 2437   switch (assign_type) { | 2506   switch (assign_type) { | 
| 2438     case VARIABLE: { | 2507     case VARIABLE: { | 
| 2439       VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2508       VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 
| 2440       if (expr->is_postfix()) { | 2509       if (expr->is_postfix()) { | 
| 2441         { EffectContext context(this); | 2510         { EffectContext context(this); | 
| 2442           EmitVariableAssignment(proxy->var(), Token::ASSIGN, | 2511           EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), | 
| 2443                                  expr->CountSlot()); | 2512                                  proxy->hole_check_mode()); | 
| 2444           PrepareForBailoutForId(expr->AssignmentId(), | 2513           PrepareForBailoutForId(expr->AssignmentId(), | 
| 2445                                  BailoutState::TOS_REGISTER); | 2514                                  BailoutState::TOS_REGISTER); | 
| 2446           context.Plug(v0); | 2515           context.Plug(v0); | 
| 2447         } | 2516         } | 
| 2448         // For all contexts except EffectConstant we have the result on | 2517         // For all contexts except EffectConstant we have the result on | 
| 2449         // top of the stack. | 2518         // top of the stack. | 
| 2450         if (!context()->IsEffect()) { | 2519         if (!context()->IsEffect()) { | 
| 2451           context()->PlugTOS(); | 2520           context()->PlugTOS(); | 
| 2452         } | 2521         } | 
| 2453       } else { | 2522       } else { | 
| 2454         EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); | 2523         EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), | 
|  | 2524                                proxy->hole_check_mode()); | 
| 2455         PrepareForBailoutForId(expr->AssignmentId(), | 2525         PrepareForBailoutForId(expr->AssignmentId(), | 
| 2456                                BailoutState::TOS_REGISTER); | 2526                                BailoutState::TOS_REGISTER); | 
| 2457         context()->Plug(v0); | 2527         context()->Plug(v0); | 
| 2458       } | 2528       } | 
| 2459       break; | 2529       break; | 
| 2460     } | 2530     } | 
| 2461     case NAMED_PROPERTY: { | 2531     case NAMED_PROPERTY: { | 
| 2462       __ mov(StoreDescriptor::ValueRegister(), result_register()); | 2532       __ mov(StoreDescriptor::ValueRegister(), result_register()); | 
| 2463       PopOperand(StoreDescriptor::ReceiverRegister()); | 2533       PopOperand(StoreDescriptor::ReceiverRegister()); | 
| 2464       CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); | 2534       CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); | 
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2801          reinterpret_cast<uint64_t>( | 2871          reinterpret_cast<uint64_t>( | 
| 2802              isolate->builtins()->OnStackReplacement()->entry())); | 2872              isolate->builtins()->OnStackReplacement()->entry())); | 
| 2803   return ON_STACK_REPLACEMENT; | 2873   return ON_STACK_REPLACEMENT; | 
| 2804 } | 2874 } | 
| 2805 | 2875 | 
| 2806 | 2876 | 
| 2807 }  // namespace internal | 2877 }  // namespace internal | 
| 2808 }  // namespace v8 | 2878 }  // namespace v8 | 
| 2809 | 2879 | 
| 2810 #endif  // V8_TARGET_ARCH_MIPS64 | 2880 #endif  // V8_TARGET_ARCH_MIPS64 | 
| OLD | NEW | 
|---|