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 3117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3128 __ beq(&uninitialized_this); | 3128 __ beq(&uninitialized_this); |
3129 __ mov(r4, Operand(this_var->name())); | 3129 __ mov(r4, Operand(this_var->name())); |
3130 __ push(r4); | 3130 __ push(r4); |
3131 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 3131 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
3132 __ bind(&uninitialized_this); | 3132 __ bind(&uninitialized_this); |
3133 | 3133 |
3134 EmitVariableAssignment(this_var, Token::INIT_CONST, slot); | 3134 EmitVariableAssignment(this_var, Token::INIT_CONST, slot); |
3135 } | 3135 } |
3136 | 3136 |
3137 | 3137 |
| 3138 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |
| 3139 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
| 3140 VariableProxy* callee = expr->expression()->AsVariableProxy(); |
| 3141 if (callee->var()->IsLookupSlot()) { |
| 3142 Label slow, done; |
| 3143 SetSourcePosition(callee->position()); |
| 3144 { |
| 3145 PreservePositionScope scope(masm()->positions_recorder()); |
| 3146 // Generate code for loading from variables potentially shadowed by |
| 3147 // eval-introduced variables. |
| 3148 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
| 3149 } |
| 3150 __ bind(&slow); |
| 3151 // Call the runtime to find the function to call (returned in rax) and |
| 3152 // the object holding it (returned in rdx). |
| 3153 __ Push(context_register()); |
| 3154 __ Push(callee->name()); |
| 3155 __ CallRuntime(Runtime::kLoadLookupSlot, 2); |
| 3156 __ Push(rax); // Function. |
| 3157 __ Push(rdx); // Receiver. |
| 3158 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
| 3159 |
| 3160 // If fast case code has been generated, emit code to push the function |
| 3161 // and receiver and have the slow path jump around this code. |
| 3162 if (done.is_linked()) { |
| 3163 Label call; |
| 3164 __ jmp(&call, Label::kNear); |
| 3165 __ bind(&done); |
| 3166 // Push function. |
| 3167 __ Push(rax); |
| 3168 // Pass undefined as the receiver, which is the WithBaseObject of a |
| 3169 // non-object environment record. If the callee is sloppy, it will patch |
| 3170 // it up to be the global receiver. |
| 3171 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 3172 __ bind(&call); |
| 3173 } |
| 3174 } else { |
| 3175 VisitForStackValue(callee); |
| 3176 // refEnv.WithBaseObject() |
| 3177 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
| 3178 __ push(r5); |
| 3179 } |
| 3180 } |
| 3181 |
| 3182 |
3138 void FullCodeGenerator::VisitCall(Call* expr) { | 3183 void FullCodeGenerator::VisitCall(Call* expr) { |
3139 #ifdef DEBUG | 3184 #ifdef DEBUG |
3140 // We want to verify that RecordJSReturnSite gets called on all paths | 3185 // We want to verify that RecordJSReturnSite gets called on all paths |
3141 // through this function. Avoid early returns. | 3186 // through this function. Avoid early returns. |
3142 expr->return_is_recorded_ = false; | 3187 expr->return_is_recorded_ = false; |
3143 #endif | 3188 #endif |
3144 | 3189 |
3145 Comment cmnt(masm_, "[ Call"); | 3190 Comment cmnt(masm_, "[ Call"); |
3146 Expression* callee = expr->expression(); | 3191 Expression* callee = expr->expression(); |
3147 Call::CallType call_type = expr->GetCallType(isolate()); | 3192 Call::CallType call_type = expr->GetCallType(isolate()); |
3148 | 3193 |
3149 if (call_type == Call::POSSIBLY_EVAL_CALL) { | 3194 if (call_type == Call::POSSIBLY_EVAL_CALL) { |
3150 // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval | 3195 // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval |
3151 // to resolve the function we need to call. Then we call the resolved | 3196 // to resolve the function we need to call. Then we call the resolved |
3152 // function using the given arguments. | 3197 // function using the given arguments. |
3153 ZoneList<Expression*>* args = expr->arguments(); | 3198 ZoneList<Expression*>* args = expr->arguments(); |
3154 int arg_count = args->length(); | 3199 int arg_count = args->length(); |
3155 | 3200 |
3156 { | 3201 { |
3157 PreservePositionScope pos_scope(masm()->positions_recorder()); | 3202 PreservePositionScope pos_scope(masm()->positions_recorder()); |
3158 VisitForStackValue(callee); | 3203 PushCalleeAndWithBaseObject(expr); |
3159 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | |
3160 __ push(r5); // Reserved receiver slot. | |
3161 | 3204 |
3162 // Push the arguments. | 3205 // Push the arguments. |
3163 for (int i = 0; i < arg_count; i++) { | 3206 for (int i = 0; i < arg_count; i++) { |
3164 VisitForStackValue(args->at(i)); | 3207 VisitForStackValue(args->at(i)); |
3165 } | 3208 } |
3166 | 3209 |
3167 // Push a copy of the function (found below the arguments) and | 3210 // Push a copy of the function (found below the arguments) and |
3168 // resolve eval. | 3211 // resolve eval. |
3169 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | 3212 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); |
3170 __ push(r4); | 3213 __ push(r4); |
3171 EmitResolvePossiblyDirectEval(arg_count); | 3214 EmitResolvePossiblyDirectEval(arg_count); |
3172 | 3215 |
3173 // Touch up the stack with the resolved function. | 3216 // Touch up the stack with the resolved function. |
3174 __ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | 3217 __ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); |
3175 | 3218 |
3176 PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS); | 3219 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); |
3177 } | 3220 } |
3178 | 3221 |
3179 // Record source position for debugger. | 3222 // Record source position for debugger. |
3180 SetSourcePosition(expr->position()); | 3223 SetSourcePosition(expr->position()); |
3181 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); | 3224 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); |
3182 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | 3225 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); |
3183 __ CallStub(&stub); | 3226 __ CallStub(&stub); |
3184 RecordJSReturnSite(expr); | 3227 RecordJSReturnSite(expr); |
3185 // Restore context register. | 3228 // Restore context register. |
3186 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3229 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3187 context()->DropAndPlug(1, r3); | 3230 context()->DropAndPlug(1, r3); |
3188 } else if (call_type == Call::GLOBAL_CALL) { | 3231 } else if (call_type == Call::GLOBAL_CALL) { |
3189 EmitCallWithLoadIC(expr); | 3232 EmitCallWithLoadIC(expr); |
3190 | 3233 |
3191 } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 3234 } else if (call_type == Call::LOOKUP_SLOT_CALL) { |
3192 // Call to a lookup slot (dynamically introduced variable). | 3235 // Call to a lookup slot (dynamically introduced variable). |
3193 VariableProxy* proxy = callee->AsVariableProxy(); | 3236 PushCalleeAndWithBaseObject(expr); |
3194 Label slow, done; | |
3195 | |
3196 { | |
3197 PreservePositionScope scope(masm()->positions_recorder()); | |
3198 // Generate code for loading from variables potentially shadowed | |
3199 // by eval-introduced variables. | |
3200 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); | |
3201 } | |
3202 | |
3203 __ bind(&slow); | |
3204 // Call the runtime to find the function to call (returned in r3) | |
3205 // and the object holding it (returned in edx). | |
3206 DCHECK(!context_register().is(r5)); | |
3207 __ mov(r5, Operand(proxy->name())); | |
3208 __ Push(context_register(), r5); | |
3209 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | |
3210 __ Push(r3, r4); // Function, receiver. | |
3211 PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS); | |
3212 | |
3213 // If fast case code has been generated, emit code to push the | |
3214 // function and receiver and have the slow path jump around this | |
3215 // code. | |
3216 if (done.is_linked()) { | |
3217 Label call; | |
3218 __ b(&call); | |
3219 __ bind(&done); | |
3220 // Push function. | |
3221 __ push(r3); | |
3222 // The receiver is implicitly the global receiver. Indicate this | |
3223 // by passing the hole to the call function stub. | |
3224 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | |
3225 __ push(r4); | |
3226 __ bind(&call); | |
3227 } | |
3228 | |
3229 // The receiver is either the global receiver or an object found | |
3230 // by LoadContextSlot. | |
3231 EmitCall(expr); | 3237 EmitCall(expr); |
3232 } else if (call_type == Call::PROPERTY_CALL) { | 3238 } else if (call_type == Call::PROPERTY_CALL) { |
3233 Property* property = callee->AsProperty(); | 3239 Property* property = callee->AsProperty(); |
3234 bool is_named_call = property->key()->IsPropertyName(); | 3240 bool is_named_call = property->key()->IsPropertyName(); |
3235 if (property->IsSuperAccess()) { | 3241 if (property->IsSuperAccess()) { |
3236 if (is_named_call) { | 3242 if (is_named_call) { |
3237 EmitSuperCallWithLoadIC(expr); | 3243 EmitSuperCallWithLoadIC(expr); |
3238 } else { | 3244 } else { |
3239 EmitKeyedSuperCallWithLoadIC(expr); | 3245 EmitKeyedSuperCallWithLoadIC(expr); |
3240 } | 3246 } |
(...skipping 2326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5567 return ON_STACK_REPLACEMENT; | 5573 return ON_STACK_REPLACEMENT; |
5568 } | 5574 } |
5569 | 5575 |
5570 DCHECK(interrupt_address == | 5576 DCHECK(interrupt_address == |
5571 isolate->builtins()->OsrAfterStackCheck()->entry()); | 5577 isolate->builtins()->OsrAfterStackCheck()->entry()); |
5572 return OSR_AFTER_STACK_CHECK; | 5578 return OSR_AFTER_STACK_CHECK; |
5573 } | 5579 } |
5574 } // namespace internal | 5580 } // namespace internal |
5575 } // namespace v8 | 5581 } // namespace v8 |
5576 #endif // V8_TARGET_ARCH_PPC | 5582 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |