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 #if V8_TARGET_ARCH_S390 | 5 #if V8_TARGET_ARCH_S390 |
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 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 __ Check(ne, kDeclarationInWithContext); | 687 __ Check(ne, kDeclarationInWithContext); |
688 __ CompareRoot(r3, Heap::kCatchContextMapRootIndex); | 688 __ CompareRoot(r3, Heap::kCatchContextMapRootIndex); |
689 __ Check(ne, kDeclarationInCatchContext); | 689 __ Check(ne, kDeclarationInCatchContext); |
690 } | 690 } |
691 } | 691 } |
692 | 692 |
693 void FullCodeGenerator::VisitVariableDeclaration( | 693 void FullCodeGenerator::VisitVariableDeclaration( |
694 VariableDeclaration* declaration) { | 694 VariableDeclaration* declaration) { |
695 VariableProxy* proxy = declaration->proxy(); | 695 VariableProxy* proxy = declaration->proxy(); |
696 Variable* variable = proxy->var(); | 696 Variable* variable = proxy->var(); |
697 DCHECK(!variable->binding_needs_init()); | |
698 switch (variable->location()) { | 697 switch (variable->location()) { |
699 case VariableLocation::UNALLOCATED: { | 698 case VariableLocation::UNALLOCATED: { |
| 699 DCHECK(!variable->binding_needs_init()); |
700 globals_->Add(variable->name(), zone()); | 700 globals_->Add(variable->name(), zone()); |
701 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); | 701 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); |
702 DCHECK(!slot.IsInvalid()); | 702 DCHECK(!slot.IsInvalid()); |
703 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); | 703 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); |
704 globals_->Add(isolate()->factory()->undefined_value(), zone()); | 704 globals_->Add(isolate()->factory()->undefined_value(), zone()); |
705 break; | 705 break; |
706 } | 706 } |
707 case VariableLocation::PARAMETER: | 707 case VariableLocation::PARAMETER: |
708 case VariableLocation::LOCAL: | 708 case VariableLocation::LOCAL: |
| 709 if (variable->binding_needs_init()) { |
| 710 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 711 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 712 __ StoreP(ip, StackOperand(variable)); |
| 713 } |
| 714 break; |
| 715 |
709 case VariableLocation::CONTEXT: | 716 case VariableLocation::CONTEXT: |
| 717 if (variable->binding_needs_init()) { |
| 718 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 719 EmitDebugCheckDeclarationContext(variable); |
| 720 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 721 __ StoreP(ip, ContextMemOperand(cp, variable->index())); |
| 722 // No write barrier since the_hole_value is in old space. |
| 723 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 724 } |
710 break; | 725 break; |
711 | 726 |
712 case VariableLocation::LOOKUP: | 727 case VariableLocation::LOOKUP: |
713 case VariableLocation::MODULE: | 728 case VariableLocation::MODULE: |
714 UNREACHABLE(); | 729 UNREACHABLE(); |
715 } | 730 } |
716 } | 731 } |
717 | 732 |
718 void FullCodeGenerator::VisitFunctionDeclaration( | 733 void FullCodeGenerator::VisitFunctionDeclaration( |
719 FunctionDeclaration* declaration) { | 734 FunctionDeclaration* declaration) { |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 context()->Plug(r2); | 1090 context()->Plug(r2); |
1076 break; | 1091 break; |
1077 } | 1092 } |
1078 | 1093 |
1079 case VariableLocation::PARAMETER: | 1094 case VariableLocation::PARAMETER: |
1080 case VariableLocation::LOCAL: | 1095 case VariableLocation::LOCAL: |
1081 case VariableLocation::CONTEXT: { | 1096 case VariableLocation::CONTEXT: { |
1082 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); | 1097 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); |
1083 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1098 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1084 : "[ Stack variable"); | 1099 : "[ Stack variable"); |
| 1100 if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { |
| 1101 // Throw a reference error when using an uninitialized let/const |
| 1102 // binding in harmony mode. |
| 1103 Label done; |
| 1104 GetVar(r2, var); |
| 1105 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |
| 1106 __ bne(&done); |
| 1107 __ mov(r2, Operand(var->name())); |
| 1108 __ push(r2); |
| 1109 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1110 __ bind(&done); |
| 1111 context()->Plug(r2); |
| 1112 break; |
| 1113 } |
1085 context()->Plug(var); | 1114 context()->Plug(var); |
1086 break; | 1115 break; |
1087 } | 1116 } |
1088 | 1117 |
1089 case VariableLocation::LOOKUP: | 1118 case VariableLocation::LOOKUP: |
1090 case VariableLocation::MODULE: | 1119 case VariableLocation::MODULE: |
1091 UNREACHABLE(); | 1120 UNREACHABLE(); |
1092 } | 1121 } |
1093 } | 1122 } |
1094 | 1123 |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1386 } else { | 1415 } else { |
1387 VisitForAccumulatorValue(expr->value()); | 1416 VisitForAccumulatorValue(expr->value()); |
1388 } | 1417 } |
1389 | 1418 |
1390 SetExpressionPosition(expr); | 1419 SetExpressionPosition(expr); |
1391 | 1420 |
1392 // Store the value. | 1421 // Store the value. |
1393 switch (assign_type) { | 1422 switch (assign_type) { |
1394 case VARIABLE: { | 1423 case VARIABLE: { |
1395 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 1424 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
1396 EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); | 1425 EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), |
| 1426 proxy->hole_check_mode()); |
1397 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 1427 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); |
1398 context()->Plug(r2); | 1428 context()->Plug(r2); |
1399 break; | 1429 break; |
1400 } | 1430 } |
1401 case NAMED_PROPERTY: | 1431 case NAMED_PROPERTY: |
1402 EmitNamedPropertyAssignment(expr); | 1432 EmitNamedPropertyAssignment(expr); |
1403 break; | 1433 break; |
1404 case KEYED_PROPERTY: | 1434 case KEYED_PROPERTY: |
1405 EmitKeyedPropertyAssignment(expr); | 1435 EmitKeyedPropertyAssignment(expr); |
1406 break; | 1436 break; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1612 FeedbackVectorSlot slot) { | 1642 FeedbackVectorSlot slot) { |
1613 DCHECK(expr->IsValidReferenceExpressionOrThis()); | 1643 DCHECK(expr->IsValidReferenceExpressionOrThis()); |
1614 | 1644 |
1615 Property* prop = expr->AsProperty(); | 1645 Property* prop = expr->AsProperty(); |
1616 LhsKind assign_type = Property::GetAssignType(prop); | 1646 LhsKind assign_type = Property::GetAssignType(prop); |
1617 | 1647 |
1618 switch (assign_type) { | 1648 switch (assign_type) { |
1619 case VARIABLE: { | 1649 case VARIABLE: { |
1620 VariableProxy* proxy = expr->AsVariableProxy(); | 1650 VariableProxy* proxy = expr->AsVariableProxy(); |
1621 EffectContext context(this); | 1651 EffectContext context(this); |
1622 EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); | 1652 EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, |
| 1653 proxy->hole_check_mode()); |
1623 break; | 1654 break; |
1624 } | 1655 } |
1625 case NAMED_PROPERTY: { | 1656 case NAMED_PROPERTY: { |
1626 PushOperand(r2); // Preserve value. | 1657 PushOperand(r2); // Preserve value. |
1627 VisitForAccumulatorValue(prop->obj()); | 1658 VisitForAccumulatorValue(prop->obj()); |
1628 __ Move(StoreDescriptor::ReceiverRegister(), r2); | 1659 __ Move(StoreDescriptor::ReceiverRegister(), r2); |
1629 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. | 1660 PopOperand(StoreDescriptor::ValueRegister()); // Restore value. |
1630 CallStoreIC(slot, prop->key()->AsLiteral()->value()); | 1661 CallStoreIC(slot, prop->key()->AsLiteral()->value()); |
1631 break; | 1662 break; |
1632 } | 1663 } |
(...skipping 21 matching lines...) Expand all Loading... |
1654 if (var->IsContextSlot()) { | 1685 if (var->IsContextSlot()) { |
1655 // RecordWrite may destroy all its register arguments. | 1686 // RecordWrite may destroy all its register arguments. |
1656 __ LoadRR(r5, result_register()); | 1687 __ LoadRR(r5, result_register()); |
1657 int offset = Context::SlotOffset(var->index()); | 1688 int offset = Context::SlotOffset(var->index()); |
1658 __ RecordWriteContextSlot(r3, offset, r5, r4, kLRHasBeenSaved, | 1689 __ RecordWriteContextSlot(r3, offset, r5, r4, kLRHasBeenSaved, |
1659 kDontSaveFPRegs); | 1690 kDontSaveFPRegs); |
1660 } | 1691 } |
1661 } | 1692 } |
1662 | 1693 |
1663 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 1694 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
1664 FeedbackVectorSlot slot) { | 1695 FeedbackVectorSlot slot, |
1665 DCHECK(!var->binding_needs_init()); | 1696 HoleCheckMode hole_check_mode) { |
1666 if (var->IsUnallocated()) { | 1697 if (var->IsUnallocated()) { |
1667 // Global var, const, or let. | 1698 // Global var, const, or let. |
1668 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); | 1699 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); |
1669 CallStoreIC(slot, var->name()); | 1700 CallStoreIC(slot, var->name()); |
1670 | 1701 |
1671 } else if (var->mode() == CONST && op != Token::INIT) { | 1702 } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { |
1672 if (var->throw_on_const_assignment(language_mode())) { | 1703 // Non-initializing assignment to let variable needs a write barrier. |
| 1704 DCHECK(!var->IsLookupSlot()); |
| 1705 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 1706 MemOperand location = VarOperand(var, r3); |
| 1707 // Perform an initialization check for lexically declared variables. |
| 1708 if (hole_check_mode == HoleCheckMode::kRequired) { |
| 1709 Label assign; |
| 1710 __ LoadP(r5, location); |
| 1711 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
| 1712 __ bne(&assign); |
| 1713 __ mov(r5, Operand(var->name())); |
| 1714 __ push(r5); |
| 1715 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1716 __ bind(&assign); |
| 1717 } |
| 1718 if (var->mode() != CONST) { |
| 1719 EmitStoreToStackLocalOrContextSlot(var, location); |
| 1720 } else if (var->throw_on_const_assignment(language_mode())) { |
1673 __ CallRuntime(Runtime::kThrowConstAssignError); | 1721 __ CallRuntime(Runtime::kThrowConstAssignError); |
1674 } | 1722 } |
| 1723 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
| 1724 // Initializing assignment to const {this} needs a write barrier. |
| 1725 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 1726 Label uninitialized_this; |
| 1727 MemOperand location = VarOperand(var, r3); |
| 1728 __ LoadP(r5, location); |
| 1729 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
| 1730 __ beq(&uninitialized_this); |
| 1731 __ mov(r3, Operand(var->name())); |
| 1732 __ push(r3); |
| 1733 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1734 __ bind(&uninitialized_this); |
| 1735 EmitStoreToStackLocalOrContextSlot(var, location); |
1675 } else { | 1736 } else { |
1676 DCHECK(!var->is_this()); | 1737 DCHECK(var->mode() != CONST || op == Token::INIT); |
1677 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 1738 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
1678 DCHECK(!var->IsLookupSlot()); | 1739 DCHECK(!var->IsLookupSlot()); |
| 1740 // Assignment to var or initializing assignment to let/const in harmony |
| 1741 // mode. |
1679 MemOperand location = VarOperand(var, r3); | 1742 MemOperand location = VarOperand(var, r3); |
| 1743 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
| 1744 // Check for an uninitialized let binding. |
| 1745 __ LoadP(r4, location); |
| 1746 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); |
| 1747 __ Check(eq, kLetBindingReInitialization); |
| 1748 } |
1680 EmitStoreToStackLocalOrContextSlot(var, location); | 1749 EmitStoreToStackLocalOrContextSlot(var, location); |
1681 } | 1750 } |
1682 } | 1751 } |
1683 | 1752 |
1684 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1753 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1685 // Assignment to a property, using a named store IC. | 1754 // Assignment to a property, using a named store IC. |
1686 Property* prop = expr->target()->AsProperty(); | 1755 Property* prop = expr->target()->AsProperty(); |
1687 DCHECK(prop != NULL); | 1756 DCHECK(prop != NULL); |
1688 DCHECK(prop->key()->IsLiteral()); | 1757 DCHECK(prop->key()->IsLiteral()); |
1689 | 1758 |
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2361 patch_site.EmitPatchInfo(); | 2430 patch_site.EmitPatchInfo(); |
2362 __ bind(&done); | 2431 __ bind(&done); |
2363 | 2432 |
2364 // Store the value returned in r2. | 2433 // Store the value returned in r2. |
2365 switch (assign_type) { | 2434 switch (assign_type) { |
2366 case VARIABLE: { | 2435 case VARIABLE: { |
2367 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2436 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2368 if (expr->is_postfix()) { | 2437 if (expr->is_postfix()) { |
2369 { | 2438 { |
2370 EffectContext context(this); | 2439 EffectContext context(this); |
2371 EmitVariableAssignment(proxy->var(), Token::ASSIGN, | 2440 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), |
2372 expr->CountSlot()); | 2441 proxy->hole_check_mode()); |
2373 PrepareForBailoutForId(expr->AssignmentId(), | 2442 PrepareForBailoutForId(expr->AssignmentId(), |
2374 BailoutState::TOS_REGISTER); | 2443 BailoutState::TOS_REGISTER); |
2375 context.Plug(r2); | 2444 context.Plug(r2); |
2376 } | 2445 } |
2377 // For all contexts except EffectConstant We have the result on | 2446 // For all contexts except EffectConstant We have the result on |
2378 // top of the stack. | 2447 // top of the stack. |
2379 if (!context()->IsEffect()) { | 2448 if (!context()->IsEffect()) { |
2380 context()->PlugTOS(); | 2449 context()->PlugTOS(); |
2381 } | 2450 } |
2382 } else { | 2451 } else { |
2383 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); | 2452 EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), |
| 2453 proxy->hole_check_mode()); |
2384 PrepareForBailoutForId(expr->AssignmentId(), | 2454 PrepareForBailoutForId(expr->AssignmentId(), |
2385 BailoutState::TOS_REGISTER); | 2455 BailoutState::TOS_REGISTER); |
2386 context()->Plug(r2); | 2456 context()->Plug(r2); |
2387 } | 2457 } |
2388 break; | 2458 break; |
2389 } | 2459 } |
2390 case NAMED_PROPERTY: { | 2460 case NAMED_PROPERTY: { |
2391 PopOperand(StoreDescriptor::ReceiverRegister()); | 2461 PopOperand(StoreDescriptor::ReceiverRegister()); |
2392 CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); | 2462 CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); |
2393 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); | 2463 PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2708 USE(kOSRBranchInstruction); | 2778 USE(kOSRBranchInstruction); |
2709 DCHECK(kOSRBranchInstruction == br_instr); | 2779 DCHECK(kOSRBranchInstruction == br_instr); |
2710 | 2780 |
2711 DCHECK(interrupt_address == | 2781 DCHECK(interrupt_address == |
2712 isolate->builtins()->OnStackReplacement()->entry()); | 2782 isolate->builtins()->OnStackReplacement()->entry()); |
2713 return ON_STACK_REPLACEMENT; | 2783 return ON_STACK_REPLACEMENT; |
2714 } | 2784 } |
2715 } // namespace internal | 2785 } // namespace internal |
2716 } // namespace v8 | 2786 } // namespace v8 |
2717 #endif // V8_TARGET_ARCH_S390 | 2787 #endif // V8_TARGET_ARCH_S390 |
OLD | NEW |