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 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2559 ObjectLiteral::Property* property = lit->properties()->at(i); | 2559 ObjectLiteral::Property* property = lit->properties()->at(i); |
2560 Expression* value = property->value(); | 2560 Expression* value = property->value(); |
2561 | 2561 |
2562 if (property->is_static()) { | 2562 if (property->is_static()) { |
2563 __ LoadP(scratch, MemOperand(sp, kPointerSize)); // constructor | 2563 __ LoadP(scratch, MemOperand(sp, kPointerSize)); // constructor |
2564 } else { | 2564 } else { |
2565 __ LoadP(scratch, MemOperand(sp, 0)); // prototype | 2565 __ LoadP(scratch, MemOperand(sp, 0)); // prototype |
2566 } | 2566 } |
2567 __ push(scratch); | 2567 __ push(scratch); |
2568 EmitPropertyKey(property, lit->GetIdForProperty(i)); | 2568 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
| 2569 |
| 2570 // The static prototype property is read only. We handle the non computed |
| 2571 // property name case in the parser. Since this is the only case where we |
| 2572 // need to check for an own read only property we special case this so we do |
| 2573 // not need to do this for every property. |
| 2574 if (property->is_static() && property->is_computed_name()) { |
| 2575 __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1); |
| 2576 __ push(r3); |
| 2577 } |
| 2578 |
2569 VisitForStackValue(value); | 2579 VisitForStackValue(value); |
2570 EmitSetHomeObjectIfNeeded(value, 2); | 2580 EmitSetHomeObjectIfNeeded(value, 2); |
2571 | 2581 |
2572 switch (property->kind()) { | 2582 switch (property->kind()) { |
2573 case ObjectLiteral::Property::CONSTANT: | 2583 case ObjectLiteral::Property::CONSTANT: |
2574 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2584 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
2575 case ObjectLiteral::Property::PROTOTYPE: | 2585 case ObjectLiteral::Property::PROTOTYPE: |
2576 UNREACHABLE(); | 2586 UNREACHABLE(); |
2577 case ObjectLiteral::Property::COMPUTED: | 2587 case ObjectLiteral::Property::COMPUTED: |
2578 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2588 __ CallRuntime(Runtime::kDefineClassMethod, 3); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2702 } | 2712 } |
2703 | 2713 |
2704 | 2714 |
2705 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { | 2715 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { |
2706 if (var->IsUnallocated()) { | 2716 if (var->IsUnallocated()) { |
2707 // Global var, const, or let. | 2717 // Global var, const, or let. |
2708 __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); | 2718 __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); |
2709 __ LoadP(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 2719 __ LoadP(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
2710 CallStoreIC(); | 2720 CallStoreIC(); |
2711 | 2721 |
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) { | 2722 } else if (var->mode() == LET && op != Token::INIT_LET) { |
2732 // Non-initializing assignment to let variable needs a write barrier. | 2723 // Non-initializing assignment to let variable needs a write barrier. |
2733 DCHECK(!var->IsLookupSlot()); | 2724 DCHECK(!var->IsLookupSlot()); |
2734 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2725 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2735 Label assign; | 2726 Label assign; |
2736 MemOperand location = VarOperand(var, r4); | 2727 MemOperand location = VarOperand(var, r4); |
2737 __ LoadP(r6, location); | 2728 __ LoadP(r6, location); |
2738 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); | 2729 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); |
2739 __ bne(&assign); | 2730 __ bne(&assign); |
2740 __ mov(r6, Operand(var->name())); | 2731 __ mov(r6, Operand(var->name())); |
2741 __ push(r6); | 2732 __ push(r6); |
2742 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2733 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
2743 // Perform the assignment. | 2734 // Perform the assignment. |
2744 __ bind(&assign); | 2735 __ bind(&assign); |
2745 EmitStoreToStackLocalOrContextSlot(var, location); | 2736 EmitStoreToStackLocalOrContextSlot(var, location); |
2746 | 2737 |
| 2738 } else if (var->mode() == CONST && op != Token::INIT_CONST) { |
| 2739 // Assignment to const variable needs a write barrier. |
| 2740 DCHECK(!var->IsLookupSlot()); |
| 2741 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2742 Label const_error; |
| 2743 MemOperand location = VarOperand(var, r4); |
| 2744 __ LoadP(r6, location); |
| 2745 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); |
| 2746 __ bne(&const_error); |
| 2747 __ mov(r6, Operand(var->name())); |
| 2748 __ push(r6); |
| 2749 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2750 __ bind(&const_error); |
| 2751 __ CallRuntime(Runtime::kThrowConstAssignError, 0); |
| 2752 |
2747 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2753 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
2748 if (var->IsLookupSlot()) { | 2754 if (var->IsLookupSlot()) { |
2749 // Assignment to var. | 2755 // Assignment to var. |
2750 __ push(r3); // Value. | 2756 __ push(r3); // Value. |
2751 __ mov(r4, Operand(var->name())); | 2757 __ mov(r4, Operand(var->name())); |
2752 __ mov(r3, Operand(Smi::FromInt(language_mode()))); | 2758 __ mov(r3, Operand(Smi::FromInt(language_mode()))); |
2753 __ Push(cp, r4, r3); // Context, name, language mode. | 2759 __ Push(cp, r4, r3); // Context, name, language mode. |
2754 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2760 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
2755 } else { | 2761 } else { |
2756 // Assignment to var or initializing assignment to let/const in harmony | 2762 // Assignment to var or initializing assignment to let/const in harmony |
2757 // mode. | 2763 // mode. |
2758 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 2764 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
2759 MemOperand location = VarOperand(var, r4); | 2765 MemOperand location = VarOperand(var, r4); |
2760 if (generate_debug_code_ && op == Token::INIT_LET) { | 2766 if (generate_debug_code_ && op == Token::INIT_LET) { |
2761 // Check for an uninitialized let binding. | 2767 // Check for an uninitialized let binding. |
2762 __ LoadP(r5, location); | 2768 __ LoadP(r5, location); |
2763 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 2769 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
2764 __ Check(eq, kLetBindingReInitialization); | 2770 __ Check(eq, kLetBindingReInitialization); |
2765 } | 2771 } |
2766 EmitStoreToStackLocalOrContextSlot(var, location); | 2772 EmitStoreToStackLocalOrContextSlot(var, location); |
2767 } | 2773 } |
2768 } else if (IsSignallingAssignmentToConst(var, op, language_mode())) { | 2774 } else if (op == Token::INIT_CONST_LEGACY) { |
2769 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2775 // Const initializers need a write barrier. |
| 2776 DCHECK(var->mode() == CONST_LEGACY); |
| 2777 DCHECK(!var->IsParameter()); // No const parameters. |
| 2778 if (var->IsLookupSlot()) { |
| 2779 __ push(r3); |
| 2780 __ mov(r3, Operand(var->name())); |
| 2781 __ Push(cp, r3); // Context and name. |
| 2782 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); |
| 2783 } else { |
| 2784 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2785 Label skip; |
| 2786 MemOperand location = VarOperand(var, r4); |
| 2787 __ LoadP(r5, location); |
| 2788 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
| 2789 __ bne(&skip); |
| 2790 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2791 __ bind(&skip); |
| 2792 } |
| 2793 |
| 2794 } else { |
| 2795 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT_CONST_LEGACY); |
| 2796 if (is_strict(language_mode())) { |
| 2797 __ CallRuntime(Runtime::kThrowConstAssignError, 0); |
| 2798 } |
| 2799 // Silently ignore store in sloppy mode. |
2770 } | 2800 } |
2771 } | 2801 } |
2772 | 2802 |
2773 | 2803 |
2774 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2804 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2775 // Assignment to a property, using a named store IC. | 2805 // Assignment to a property, using a named store IC. |
2776 Property* prop = expr->target()->AsProperty(); | 2806 Property* prop = expr->target()->AsProperty(); |
2777 DCHECK(prop != NULL); | 2807 DCHECK(prop != NULL); |
2778 DCHECK(prop->key()->IsLiteral()); | 2808 DCHECK(prop->key()->IsLiteral()); |
2779 | 2809 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2886 | 2916 |
2887 // Get the target function. | 2917 // Get the target function. |
2888 if (call_type == CallICState::FUNCTION) { | 2918 if (call_type == CallICState::FUNCTION) { |
2889 { | 2919 { |
2890 StackValueContext context(this); | 2920 StackValueContext context(this); |
2891 EmitVariableLoad(callee->AsVariableProxy()); | 2921 EmitVariableLoad(callee->AsVariableProxy()); |
2892 PrepareForBailout(callee, NO_REGISTERS); | 2922 PrepareForBailout(callee, NO_REGISTERS); |
2893 } | 2923 } |
2894 // Push undefined as receiver. This is patched in the method prologue if it | 2924 // Push undefined as receiver. This is patched in the method prologue if it |
2895 // is a sloppy mode method. | 2925 // is a sloppy mode method. |
2896 __ Push(isolate()->factory()->undefined_value()); | 2926 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 2927 __ push(r0); |
2897 } else { | 2928 } else { |
2898 // Load the function from the receiver. | 2929 // Load the function from the receiver. |
2899 DCHECK(callee->IsProperty()); | 2930 DCHECK(callee->IsProperty()); |
2900 DCHECK(!callee->AsProperty()->IsSuperAccess()); | 2931 DCHECK(!callee->AsProperty()->IsSuperAccess()); |
2901 __ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); | 2932 __ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0)); |
2902 EmitNamedPropertyLoad(callee->AsProperty()); | 2933 EmitNamedPropertyLoad(callee->AsProperty()); |
2903 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2934 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2904 // Push the target function under the receiver. | 2935 // Push the target function under the receiver. |
2905 __ LoadP(ip, MemOperand(sp, 0)); | 2936 __ LoadP(r0, MemOperand(sp, 0)); |
2906 __ push(ip); | 2937 __ push(r0); |
2907 __ StoreP(r3, MemOperand(sp, kPointerSize)); | 2938 __ StoreP(r3, MemOperand(sp, kPointerSize)); |
2908 } | 2939 } |
2909 | 2940 |
2910 EmitCall(expr, call_type); | 2941 EmitCall(expr, call_type); |
2911 } | 2942 } |
2912 | 2943 |
2913 | 2944 |
2914 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { | 2945 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { |
2915 Expression* callee = expr->expression(); | 2946 Expression* callee = expr->expression(); |
2916 DCHECK(callee->IsProperty()); | 2947 DCHECK(callee->IsProperty()); |
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4211 Label loop; | 4242 Label loop; |
4212 __ mtctr(r3); | 4243 __ mtctr(r3); |
4213 __ bind(&loop); | 4244 __ bind(&loop); |
4214 // Pre-decrement in order to skip receiver. | 4245 // Pre-decrement in order to skip receiver. |
4215 __ LoadPU(r6, MemOperand(r5, -kPointerSize)); | 4246 __ LoadPU(r6, MemOperand(r5, -kPointerSize)); |
4216 __ Push(r6); | 4247 __ Push(r6); |
4217 __ bdnz(&loop); | 4248 __ bdnz(&loop); |
4218 } | 4249 } |
4219 | 4250 |
4220 __ bind(&args_set_up); | 4251 __ bind(&args_set_up); |
| 4252 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
| 4253 |
4221 CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL); | 4254 CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL); |
4222 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 4255 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
4223 | 4256 |
4224 __ Drop(1); | 4257 __ Drop(1); |
4225 | 4258 |
4226 context()->Plug(result_register()); | 4259 context()->Plug(result_register()); |
4227 } | 4260 } |
4228 | 4261 |
4229 | 4262 |
4230 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { | 4263 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { |
(...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5435 return ON_STACK_REPLACEMENT; | 5468 return ON_STACK_REPLACEMENT; |
5436 } | 5469 } |
5437 | 5470 |
5438 DCHECK(interrupt_address == | 5471 DCHECK(interrupt_address == |
5439 isolate->builtins()->OsrAfterStackCheck()->entry()); | 5472 isolate->builtins()->OsrAfterStackCheck()->entry()); |
5440 return OSR_AFTER_STACK_CHECK; | 5473 return OSR_AFTER_STACK_CHECK; |
5441 } | 5474 } |
5442 } | 5475 } |
5443 } // namespace v8::internal | 5476 } // namespace v8::internal |
5444 #endif // V8_TARGET_ARCH_PPC | 5477 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |