| 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 | 
|---|