| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_PPC | 7 #if V8_TARGET_ARCH_PPC |
| 8 | 8 |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 1464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1475 // variables. | 1475 // variables. |
| 1476 switch (var->location()) { | 1476 switch (var->location()) { |
| 1477 case Variable::UNALLOCATED: { | 1477 case Variable::UNALLOCATED: { |
| 1478 Comment cmnt(masm_, "[ Global variable"); | 1478 Comment cmnt(masm_, "[ Global variable"); |
| 1479 __ LoadP(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1479 __ LoadP(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
| 1480 __ mov(LoadDescriptor::NameRegister(), Operand(var->name())); | 1480 __ mov(LoadDescriptor::NameRegister(), Operand(var->name())); |
| 1481 if (FLAG_vector_ics) { | 1481 if (FLAG_vector_ics) { |
| 1482 __ mov(VectorLoadICDescriptor::SlotRegister(), | 1482 __ mov(VectorLoadICDescriptor::SlotRegister(), |
| 1483 Operand(SmiFromSlot(proxy->VariableFeedbackSlot()))); | 1483 Operand(SmiFromSlot(proxy->VariableFeedbackSlot()))); |
| 1484 } | 1484 } |
| 1485 CallLoadIC(CONTEXTUAL); | 1485 CallGlobalLoadIC(var->name()); |
| 1486 context()->Plug(r3); | 1486 context()->Plug(r3); |
| 1487 break; | 1487 break; |
| 1488 } | 1488 } |
| 1489 | 1489 |
| 1490 case Variable::PARAMETER: | 1490 case Variable::PARAMETER: |
| 1491 case Variable::LOCAL: | 1491 case Variable::LOCAL: |
| 1492 case Variable::CONTEXT: { | 1492 case Variable::CONTEXT: { |
| 1493 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1493 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
| 1494 : "[ Stack variable"); | 1494 : "[ Stack variable"); |
| 1495 if (var->binding_needs_init()) { | 1495 if (var->binding_needs_init()) { |
| (...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2702 } | 2702 } |
| 2703 | 2703 |
| 2704 | 2704 |
| 2705 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { | 2705 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { |
| 2706 if (var->IsUnallocated()) { | 2706 if (var->IsUnallocated()) { |
| 2707 // Global var, const, or let. | 2707 // Global var, const, or let. |
| 2708 __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); | 2708 __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); |
| 2709 __ LoadP(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 2709 __ LoadP(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
| 2710 CallStoreIC(); | 2710 CallStoreIC(); |
| 2711 | 2711 |
| 2712 } else if (op == Token::INIT_CONST_LEGACY) { | |
| 2713 // Const initializers need a write barrier. | |
| 2714 DCHECK(!var->IsParameter()); // No const parameters. | |
| 2715 if (var->IsLookupSlot()) { | |
| 2716 __ push(r3); | |
| 2717 __ mov(r3, Operand(var->name())); | |
| 2718 __ Push(cp, r3); // Context and name. | |
| 2719 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | |
| 2720 } else { | |
| 2721 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | |
| 2722 Label skip; | |
| 2723 MemOperand location = VarOperand(var, r4); | |
| 2724 __ LoadP(r5, location); | |
| 2725 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | |
| 2726 __ bne(&skip); | |
| 2727 EmitStoreToStackLocalOrContextSlot(var, location); | |
| 2728 __ bind(&skip); | |
| 2729 } | |
| 2730 | |
| 2731 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2712 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2732 // Non-initializing assignment to let variable needs a write barrier. | 2713 // Non-initializing assignment to let variable needs a write barrier. |
| 2733 DCHECK(!var->IsLookupSlot()); | 2714 DCHECK(!var->IsLookupSlot()); |
| 2734 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2715 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2735 Label assign; | 2716 Label assign; |
| 2736 MemOperand location = VarOperand(var, r4); | 2717 MemOperand location = VarOperand(var, r4); |
| 2737 __ LoadP(r6, location); | 2718 __ LoadP(r6, location); |
| 2738 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); | 2719 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); |
| 2739 __ bne(&assign); | 2720 __ bne(&assign); |
| 2740 __ mov(r6, Operand(var->name())); | 2721 __ mov(r6, Operand(var->name())); |
| 2741 __ push(r6); | 2722 __ push(r6); |
| 2742 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2723 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2743 // Perform the assignment. | 2724 // Perform the assignment. |
| 2744 __ bind(&assign); | 2725 __ bind(&assign); |
| 2745 EmitStoreToStackLocalOrContextSlot(var, location); | 2726 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2746 | 2727 |
| 2728 } else if (var->mode() == CONST && op != Token::INIT_CONST) { |
| 2729 // Assignment to const variable needs a write barrier. |
| 2730 DCHECK(!var->IsLookupSlot()); |
| 2731 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2732 Label const_error; |
| 2733 MemOperand location = VarOperand(var, r4); |
| 2734 __ LoadP(r6, location); |
| 2735 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); |
| 2736 __ bne(&const_error); |
| 2737 __ mov(r6, Operand(var->name())); |
| 2738 __ push(r6); |
| 2739 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2740 __ bind(&const_error); |
| 2741 __ CallRuntime(Runtime::kThrowConstAssignError, 0); |
| 2742 |
| 2747 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2743 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2748 if (var->IsLookupSlot()) { | 2744 if (var->IsLookupSlot()) { |
| 2749 // Assignment to var. | 2745 // Assignment to var. |
| 2750 __ push(r3); // Value. | 2746 __ push(r3); // Value. |
| 2751 __ mov(r4, Operand(var->name())); | 2747 __ mov(r4, Operand(var->name())); |
| 2752 __ mov(r3, Operand(Smi::FromInt(language_mode()))); | 2748 __ mov(r3, Operand(Smi::FromInt(language_mode()))); |
| 2753 __ Push(cp, r4, r3); // Context, name, language mode. | 2749 __ Push(cp, r4, r3); // Context, name, language mode. |
| 2754 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2750 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
| 2755 } else { | 2751 } else { |
| 2756 // Assignment to var or initializing assignment to let/const in harmony | 2752 // Assignment to var or initializing assignment to let/const in harmony |
| 2757 // mode. | 2753 // mode. |
| 2758 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 2754 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
| 2759 MemOperand location = VarOperand(var, r4); | 2755 MemOperand location = VarOperand(var, r4); |
| 2760 if (generate_debug_code_ && op == Token::INIT_LET) { | 2756 if (generate_debug_code_ && op == Token::INIT_LET) { |
| 2761 // Check for an uninitialized let binding. | 2757 // Check for an uninitialized let binding. |
| 2762 __ LoadP(r5, location); | 2758 __ LoadP(r5, location); |
| 2763 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 2759 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
| 2764 __ Check(eq, kLetBindingReInitialization); | 2760 __ Check(eq, kLetBindingReInitialization); |
| 2765 } | 2761 } |
| 2766 EmitStoreToStackLocalOrContextSlot(var, location); | 2762 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2767 } | 2763 } |
| 2768 } else if (IsSignallingAssignmentToConst(var, op, language_mode())) { | 2764 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2769 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2765 // Const initializers need a write barrier. |
| 2766 DCHECK(var->mode() == CONST_LEGACY); |
| 2767 DCHECK(!var->IsParameter()); // No const parameters. |
| 2768 if (var->IsLookupSlot()) { |
| 2769 __ push(r3); |
| 2770 __ mov(r3, Operand(var->name())); |
| 2771 __ Push(cp, r3); // Context and name. |
| 2772 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); |
| 2773 } else { |
| 2774 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2775 Label skip; |
| 2776 MemOperand location = VarOperand(var, r4); |
| 2777 __ LoadP(r5, location); |
| 2778 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
| 2779 __ bne(&skip); |
| 2780 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2781 __ bind(&skip); |
| 2782 } |
| 2783 |
| 2784 } else { |
| 2785 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT_CONST_LEGACY); |
| 2786 if (is_strict(language_mode())) { |
| 2787 __ CallRuntime(Runtime::kThrowConstAssignError, 0); |
| 2788 } |
| 2789 // Silently ignore store in sloppy mode. |
| 2770 } | 2790 } |
| 2771 } | 2791 } |
| 2772 | 2792 |
| 2773 | 2793 |
| 2774 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2794 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2775 // Assignment to a property, using a named store IC. | 2795 // Assignment to a property, using a named store IC. |
| 2776 Property* prop = expr->target()->AsProperty(); | 2796 Property* prop = expr->target()->AsProperty(); |
| 2777 DCHECK(prop != NULL); | 2797 DCHECK(prop != NULL); |
| 2778 DCHECK(prop->key()->IsLiteral()); | 2798 DCHECK(prop->key()->IsLiteral()); |
| 2779 | 2799 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2886 | 2906 |
| 2887 // Get the target function. | 2907 // Get the target function. |
| 2888 if (call_type == CallICState::FUNCTION) { | 2908 if (call_type == CallICState::FUNCTION) { |
| 2889 { | 2909 { |
| 2890 StackValueContext context(this); | 2910 StackValueContext context(this); |
| 2891 EmitVariableLoad(callee->AsVariableProxy()); | 2911 EmitVariableLoad(callee->AsVariableProxy()); |
| 2892 PrepareForBailout(callee, NO_REGISTERS); | 2912 PrepareForBailout(callee, NO_REGISTERS); |
| 2893 } | 2913 } |
| 2894 // Push undefined as receiver. This is patched in the method prologue if it | 2914 // Push undefined as receiver. This is patched in the method prologue if it |
| 2895 // is a sloppy mode method. | 2915 // is a sloppy mode method. |
| 2896 __ Push(isolate()->factory()->undefined_value()); | 2916 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 2917 __ push(r0); |
| 2897 } else { | 2918 } else { |
| 2898 // Load the function from the receiver. | 2919 // Load the function from the receiver. |
| 2899 DCHECK(callee->IsProperty()); | 2920 DCHECK(callee->IsProperty()); |
| 2900 DCHECK(!callee->AsProperty()->IsSuperAccess()); | 2921 DCHECK(!callee->AsProperty()->IsSuperAccess()); |
| 2901 __ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); | 2922 __ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); |
| 2902 EmitNamedPropertyLoad(callee->AsProperty()); | 2923 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2903 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2924 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2904 // Push the target function under the receiver. | 2925 // Push the target function under the receiver. |
| 2905 __ LoadP(ip, MemOperand(sp, 0)); | 2926 __ LoadP(r0, MemOperand(sp, 0)); |
| 2906 __ push(ip); | 2927 __ push(r0); |
| 2907 __ StoreP(r3, MemOperand(sp, kPointerSize)); | 2928 __ StoreP(r3, MemOperand(sp, kPointerSize)); |
| 2908 } | 2929 } |
| 2909 | 2930 |
| 2910 EmitCall(expr, call_type); | 2931 EmitCall(expr, call_type); |
| 2911 } | 2932 } |
| 2912 | 2933 |
| 2913 | 2934 |
| 2914 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { | 2935 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { |
| 2915 Expression* callee = expr->expression(); | 2936 Expression* callee = expr->expression(); |
| 2916 DCHECK(callee->IsProperty()); | 2937 DCHECK(callee->IsProperty()); |
| (...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4211 Label loop; | 4232 Label loop; |
| 4212 __ mtctr(r3); | 4233 __ mtctr(r3); |
| 4213 __ bind(&loop); | 4234 __ bind(&loop); |
| 4214 // Pre-decrement in order to skip receiver. | 4235 // Pre-decrement in order to skip receiver. |
| 4215 __ LoadPU(r6, MemOperand(r5, -kPointerSize)); | 4236 __ LoadPU(r6, MemOperand(r5, -kPointerSize)); |
| 4216 __ Push(r6); | 4237 __ Push(r6); |
| 4217 __ bdnz(&loop); | 4238 __ bdnz(&loop); |
| 4218 } | 4239 } |
| 4219 | 4240 |
| 4220 __ bind(&args_set_up); | 4241 __ bind(&args_set_up); |
| 4242 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
| 4243 |
| 4221 CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL); | 4244 CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL); |
| 4222 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 4245 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 4223 | 4246 |
| 4224 __ Drop(1); | 4247 __ Drop(1); |
| 4225 | 4248 |
| 4226 context()->Plug(result_register()); | 4249 context()->Plug(result_register()); |
| 4227 } | 4250 } |
| 4228 | 4251 |
| 4229 | 4252 |
| 4230 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { | 4253 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { |
| (...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5435 return ON_STACK_REPLACEMENT; | 5458 return ON_STACK_REPLACEMENT; |
| 5436 } | 5459 } |
| 5437 | 5460 |
| 5438 DCHECK(interrupt_address == | 5461 DCHECK(interrupt_address == |
| 5439 isolate->builtins()->OsrAfterStackCheck()->entry()); | 5462 isolate->builtins()->OsrAfterStackCheck()->entry()); |
| 5440 return OSR_AFTER_STACK_CHECK; | 5463 return OSR_AFTER_STACK_CHECK; |
| 5441 } | 5464 } |
| 5442 } | 5465 } |
| 5443 } // namespace v8::internal | 5466 } // namespace v8::internal |
| 5444 #endif // V8_TARGET_ARCH_PPC | 5467 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |