| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_X64 | 7 #if V8_TARGET_ARCH_X64 | 
| 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 3014 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3025   Label uninitialized_this; | 3025   Label uninitialized_this; | 
| 3026   __ j(equal, &uninitialized_this); | 3026   __ j(equal, &uninitialized_this); | 
| 3027   __ Push(this_var->name()); | 3027   __ Push(this_var->name()); | 
| 3028   __ CallRuntime(Runtime::kThrowReferenceError, 1); | 3028   __ CallRuntime(Runtime::kThrowReferenceError, 1); | 
| 3029   __ bind(&uninitialized_this); | 3029   __ bind(&uninitialized_this); | 
| 3030 | 3030 | 
| 3031   EmitVariableAssignment(this_var, Token::INIT_CONST, slot); | 3031   EmitVariableAssignment(this_var, Token::INIT_CONST, slot); | 
| 3032 } | 3032 } | 
| 3033 | 3033 | 
| 3034 | 3034 | 
|  | 3035 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | 
|  | 3036 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | 
|  | 3037   VariableProxy* callee = expr->expression()->AsVariableProxy(); | 
|  | 3038   if (callee->var()->IsLookupSlot()) { | 
|  | 3039     Label slow, done; | 
|  | 3040     SetSourcePosition(callee->position()); | 
|  | 3041     { | 
|  | 3042       PreservePositionScope scope(masm()->positions_recorder()); | 
|  | 3043       // Generate code for loading from variables potentially shadowed by | 
|  | 3044       // eval-introduced variables. | 
|  | 3045       EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 
|  | 3046     } | 
|  | 3047     __ bind(&slow); | 
|  | 3048     // Call the runtime to find the function to call (returned in rax) and | 
|  | 3049     // the object holding it (returned in rdx). | 
|  | 3050     __ Push(context_register()); | 
|  | 3051     __ Push(callee->name()); | 
|  | 3052     __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 
|  | 3053     __ Push(rax);  // Function. | 
|  | 3054     __ Push(rdx);  // Receiver. | 
|  | 3055     PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); | 
|  | 3056 | 
|  | 3057     // If fast case code has been generated, emit code to push the function | 
|  | 3058     // and receiver and have the slow path jump around this code. | 
|  | 3059     if (done.is_linked()) { | 
|  | 3060       Label call; | 
|  | 3061       __ jmp(&call, Label::kNear); | 
|  | 3062       __ bind(&done); | 
|  | 3063       // Push function. | 
|  | 3064       __ Push(rax); | 
|  | 3065       // Pass undefined as the receiver, which is the WithBaseObject of a | 
|  | 3066       // non-object environment record.  If the callee is sloppy, it will patch | 
|  | 3067       // it up to be the global receiver. | 
|  | 3068       __ PushRoot(Heap::kUndefinedValueRootIndex); | 
|  | 3069       __ bind(&call); | 
|  | 3070     } | 
|  | 3071   } else { | 
|  | 3072     VisitForStackValue(callee); | 
|  | 3073     // refEnv.WithBaseObject() | 
|  | 3074     __ PushRoot(Heap::kUndefinedValueRootIndex); | 
|  | 3075   } | 
|  | 3076 } | 
|  | 3077 | 
|  | 3078 | 
| 3035 void FullCodeGenerator::VisitCall(Call* expr) { | 3079 void FullCodeGenerator::VisitCall(Call* expr) { | 
| 3036 #ifdef DEBUG | 3080 #ifdef DEBUG | 
| 3037   // We want to verify that RecordJSReturnSite gets called on all paths | 3081   // We want to verify that RecordJSReturnSite gets called on all paths | 
| 3038   // through this function.  Avoid early returns. | 3082   // through this function.  Avoid early returns. | 
| 3039   expr->return_is_recorded_ = false; | 3083   expr->return_is_recorded_ = false; | 
| 3040 #endif | 3084 #endif | 
| 3041 | 3085 | 
| 3042   Comment cmnt(masm_, "[ Call"); | 3086   Comment cmnt(masm_, "[ Call"); | 
| 3043   Expression* callee = expr->expression(); | 3087   Expression* callee = expr->expression(); | 
| 3044   Call::CallType call_type = expr->GetCallType(isolate()); | 3088   Call::CallType call_type = expr->GetCallType(isolate()); | 
| 3045 | 3089 | 
| 3046   if (call_type == Call::POSSIBLY_EVAL_CALL) { | 3090   if (call_type == Call::POSSIBLY_EVAL_CALL) { | 
| 3047     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval | 3091     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval | 
| 3048     // to resolve the function we need to call.  Then we call the resolved | 3092     // to resolve the function we need to call.  Then we call the resolved | 
| 3049     // function using the given arguments. | 3093     // function using the given arguments. | 
| 3050     ZoneList<Expression*>* args = expr->arguments(); | 3094     ZoneList<Expression*>* args = expr->arguments(); | 
| 3051     int arg_count = args->length(); | 3095     int arg_count = args->length(); | 
| 3052     { PreservePositionScope pos_scope(masm()->positions_recorder()); | 3096     { PreservePositionScope pos_scope(masm()->positions_recorder()); | 
| 3053       VisitForStackValue(callee); | 3097       PushCalleeAndWithBaseObject(expr); | 
| 3054       __ PushRoot(Heap::kUndefinedValueRootIndex);  // Reserved receiver slot. |  | 
| 3055 | 3098 | 
| 3056       // Push the arguments. | 3099       // Push the arguments. | 
| 3057       for (int i = 0; i < arg_count; i++) { | 3100       for (int i = 0; i < arg_count; i++) { | 
| 3058         VisitForStackValue(args->at(i)); | 3101         VisitForStackValue(args->at(i)); | 
| 3059       } | 3102       } | 
| 3060 | 3103 | 
| 3061       // Push a copy of the function (found below the arguments) and resolve | 3104       // Push a copy of the function (found below the arguments) and resolve | 
| 3062       // eval. | 3105       // eval. | 
| 3063       __ Push(Operand(rsp, (arg_count + 1) * kPointerSize)); | 3106       __ Push(Operand(rsp, (arg_count + 1) * kPointerSize)); | 
| 3064       EmitResolvePossiblyDirectEval(arg_count); | 3107       EmitResolvePossiblyDirectEval(arg_count); | 
| 3065 | 3108 | 
| 3066       // Touch up the callee. | 3109       // Touch up the callee. | 
| 3067       __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax); | 3110       __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax); | 
| 3068 | 3111 | 
| 3069       PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS); | 3112       PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); | 
| 3070     } | 3113     } | 
| 3071     // Record source position for debugger. | 3114     // Record source position for debugger. | 
| 3072     SetSourcePosition(expr->position()); | 3115     SetSourcePosition(expr->position()); | 
| 3073     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); | 3116     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); | 
| 3074     __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); | 3117     __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); | 
| 3075     __ CallStub(&stub); | 3118     __ CallStub(&stub); | 
| 3076     RecordJSReturnSite(expr); | 3119     RecordJSReturnSite(expr); | 
| 3077     // Restore context register. | 3120     // Restore context register. | 
| 3078     __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3121     __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 
| 3079     context()->DropAndPlug(1, rax); | 3122     context()->DropAndPlug(1, rax); | 
| 3080   } else if (call_type == Call::GLOBAL_CALL) { | 3123   } else if (call_type == Call::GLOBAL_CALL) { | 
| 3081     EmitCallWithLoadIC(expr); | 3124     EmitCallWithLoadIC(expr); | 
| 3082 | 3125 | 
| 3083   } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 3126   } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 
| 3084     // Call to a lookup slot (dynamically introduced variable). | 3127     // Call to a lookup slot (dynamically introduced variable). | 
| 3085     VariableProxy* proxy = callee->AsVariableProxy(); | 3128     PushCalleeAndWithBaseObject(expr); | 
| 3086     Label slow, done; |  | 
| 3087 |  | 
| 3088     { PreservePositionScope scope(masm()->positions_recorder()); |  | 
| 3089       // Generate code for loading from variables potentially shadowed by |  | 
| 3090       // eval-introduced variables. |  | 
| 3091       EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); |  | 
| 3092     } |  | 
| 3093     __ bind(&slow); |  | 
| 3094     // Call the runtime to find the function to call (returned in rax) and |  | 
| 3095     // the object holding it (returned in rdx). |  | 
| 3096     __ Push(context_register()); |  | 
| 3097     __ Push(proxy->name()); |  | 
| 3098     __ CallRuntime(Runtime::kLoadLookupSlot, 2); |  | 
| 3099     __ Push(rax);  // Function. |  | 
| 3100     __ Push(rdx);  // Receiver. |  | 
| 3101     PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS); |  | 
| 3102 |  | 
| 3103     // If fast case code has been generated, emit code to push the function |  | 
| 3104     // and receiver and have the slow path jump around this code. |  | 
| 3105     if (done.is_linked()) { |  | 
| 3106       Label call; |  | 
| 3107       __ jmp(&call, Label::kNear); |  | 
| 3108       __ bind(&done); |  | 
| 3109       // Push function. |  | 
| 3110       __ Push(rax); |  | 
| 3111       // The receiver is implicitly the global receiver. Indicate this by |  | 
| 3112       // passing the hole to the call function stub. |  | 
| 3113       __ PushRoot(Heap::kUndefinedValueRootIndex); |  | 
| 3114       __ bind(&call); |  | 
| 3115     } |  | 
| 3116 |  | 
| 3117     // The receiver is either the global receiver or an object found by |  | 
| 3118     // LoadContextSlot. |  | 
| 3119     EmitCall(expr); | 3129     EmitCall(expr); | 
| 3120   } else if (call_type == Call::PROPERTY_CALL) { | 3130   } else if (call_type == Call::PROPERTY_CALL) { | 
| 3121     Property* property = callee->AsProperty(); | 3131     Property* property = callee->AsProperty(); | 
| 3122     bool is_named_call = property->key()->IsPropertyName(); | 3132     bool is_named_call = property->key()->IsPropertyName(); | 
| 3123     if (property->IsSuperAccess()) { | 3133     if (property->IsSuperAccess()) { | 
| 3124       if (is_named_call) { | 3134       if (is_named_call) { | 
| 3125         EmitSuperCallWithLoadIC(expr); | 3135         EmitSuperCallWithLoadIC(expr); | 
| 3126       } else { | 3136       } else { | 
| 3127         EmitKeyedSuperCallWithLoadIC(expr); | 3137         EmitKeyedSuperCallWithLoadIC(expr); | 
| 3128       } | 3138       } | 
| (...skipping 2374 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5503             Assembler::target_address_at(call_target_address, | 5513             Assembler::target_address_at(call_target_address, | 
| 5504                                          unoptimized_code)); | 5514                                          unoptimized_code)); | 
| 5505   return OSR_AFTER_STACK_CHECK; | 5515   return OSR_AFTER_STACK_CHECK; | 
| 5506 } | 5516 } | 
| 5507 | 5517 | 
| 5508 | 5518 | 
| 5509 }  // namespace internal | 5519 }  // namespace internal | 
| 5510 }  // namespace v8 | 5520 }  // namespace v8 | 
| 5511 | 5521 | 
| 5512 #endif  // V8_TARGET_ARCH_X64 | 5522 #endif  // V8_TARGET_ARCH_X64 | 
| OLD | NEW | 
|---|