| Index: src/x64/stub-cache-x64.cc
|
| diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
|
| index a1e8f211161e9c42cbfeffa0f9d9d3eb9818bcae..53f664f0677abfda81d8c1ae3c95d84e1b51f4af 100644
|
| --- a/src/x64/stub-cache-x64.cc
|
| +++ b/src/x64/stub-cache-x64.cc
|
| @@ -436,21 +436,16 @@ static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
|
| }
|
|
|
|
|
| +static void GenerateFastApiCallBody(MacroAssembler* masm,
|
| + const CallOptimization& optimization,
|
| + int argc,
|
| + bool restore_context);
|
| +
|
| +
|
| // Generates call to API function.
|
| static void GenerateFastApiCall(MacroAssembler* masm,
|
| const CallOptimization& optimization,
|
| - int argc,
|
| - bool restore_context) {
|
| - // ----------- S t a t e -------------
|
| - // -- rsp[0] : return address
|
| - // -- rsp[8] - rsp[56] : FunctionCallbackInfo, incl.
|
| - // : object passing the type check
|
| - // (set by CheckPrototypes)
|
| - // -- rsp[64] : last argument
|
| - // -- ...
|
| - // -- rsp[(argc + 7) * 8] : first argument
|
| - // -- rsp[(argc + 8) * 8] : receiver
|
| - // -----------------------------------
|
| + int argc) {
|
| typedef FunctionCallbackArguments FCA;
|
| StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments);
|
|
|
| @@ -485,8 +480,121 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
|
|
| // Prepare arguments.
|
| STATIC_ASSERT(kFastApiCallArguments == 7);
|
| - __ lea(rbx, Operand(rsp, 1 * kPointerSize));
|
| + __ lea(rax, Operand(rsp, 1 * kPointerSize));
|
| +
|
| + GenerateFastApiCallBody(masm, optimization, argc, false);
|
| +}
|
| +
|
| +
|
| +// Generate call to api function.
|
| +// This function uses push() to generate smaller, faster code than
|
| +// the version above. It is an optimization that should will be removed
|
| +// when api call ICs are generated in hydrogen.
|
| +static void GenerateFastApiCall(MacroAssembler* masm,
|
| + const CallOptimization& optimization,
|
| + Register receiver,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + Register scratch3,
|
| + int argc,
|
| + Register* values) {
|
| + ASSERT(optimization.is_simple_api_call());
|
| +
|
| + // Copy return value.
|
| + __ pop(scratch1);
|
| +
|
| + // receiver
|
| + __ push(receiver);
|
| +
|
| + // Write the arguments to stack frame.
|
| + for (int i = 0; i < argc; i++) {
|
| + Register arg = values[argc-1-i];
|
| + ASSERT(!receiver.is(arg));
|
| + ASSERT(!scratch1.is(arg));
|
| + ASSERT(!scratch2.is(arg));
|
| + ASSERT(!scratch3.is(arg));
|
| + __ push(arg);
|
| + }
|
| +
|
| + typedef FunctionCallbackArguments FCA;
|
| +
|
| + STATIC_ASSERT(FCA::kHolderIndex == 0);
|
| + STATIC_ASSERT(FCA::kIsolateIndex == 1);
|
| + STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
|
| + STATIC_ASSERT(FCA::kReturnValueOffset == 3);
|
| + STATIC_ASSERT(FCA::kDataIndex == 4);
|
| + STATIC_ASSERT(FCA::kCalleeIndex == 5);
|
| + STATIC_ASSERT(FCA::kContextSaveIndex == 6);
|
| + STATIC_ASSERT(FCA::kArgsLength == 7);
|
| +
|
| + // context save
|
| + __ push(rsi);
|
| +
|
| + // Get the function and setup the context.
|
| + Handle<JSFunction> function = optimization.constant_function();
|
| + __ Move(scratch2, function);
|
| + __ push(scratch2);
|
| +
|
| + Isolate* isolate = masm->isolate();
|
| + Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
|
| + Handle<Object> call_data(api_call_info->data(), isolate);
|
| + // Push data from ExecutableAccessorInfo.
|
| + bool call_data_undefined = false;
|
| + if (isolate->heap()->InNewSpace(*call_data)) {
|
| + __ Move(scratch2, api_call_info);
|
| + __ movq(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
|
| + } else if (call_data->IsUndefined()) {
|
| + call_data_undefined = true;
|
| + __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
|
| + } else {
|
| + __ Move(scratch3, call_data);
|
| + }
|
| + // call data
|
| + __ push(scratch3);
|
| + if (!call_data_undefined) {
|
| + __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
|
| + }
|
| + // return value
|
| + __ push(scratch3);
|
| + // return value default
|
| + __ push(scratch3);
|
| + // isolate
|
| + __ Move(scratch3,
|
| + ExternalReference::isolate_address(masm->isolate()));
|
| + __ push(scratch3);
|
| + // holder
|
| + __ push(receiver);
|
| +
|
| + ASSERT(!scratch1.is(rax));
|
| + // store receiver address for GenerateFastApiCallBody
|
| + __ movq(rax, rsp);
|
|
|
| + // return address
|
| + __ push(scratch1);
|
| +
|
| + GenerateFastApiCallBody(masm, optimization, argc, true);
|
| +}
|
| +
|
| +
|
| +static void GenerateFastApiCallBody(MacroAssembler* masm,
|
| + const CallOptimization& optimization,
|
| + int argc,
|
| + bool restore_context) {
|
| + // ----------- S t a t e -------------
|
| + // -- rsp[0] : return address
|
| + // -- rsp[8] - rsp[56] : FunctionCallbackInfo, incl.
|
| + // : object passing the type check
|
| + // (set by CheckPrototypes)
|
| + // -- rsp[64] : last argument
|
| + // -- ...
|
| + // -- rsp[(argc + 7) * 8] : first argument
|
| + // -- rsp[(argc + 8) * 8] : receiver
|
| + //
|
| + // rax : receiver address
|
| + // -----------------------------------
|
| + typedef FunctionCallbackArguments FCA;
|
| +
|
| + Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
|
| // Function address is a foreign pointer outside V8's heap.
|
| Address function_address = v8::ToCData<Address>(api_call_info->callback());
|
|
|
| @@ -496,9 +604,9 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
|
|
| __ PrepareCallApiFunction(kApiStackSpace);
|
|
|
| - __ movq(StackSpaceOperand(0), rbx); // FunctionCallbackInfo::implicit_args_.
|
| - __ addq(rbx, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
|
| - __ movq(StackSpaceOperand(1), rbx); // FunctionCallbackInfo::values_.
|
| + __ movq(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_.
|
| + __ addq(rax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
|
| + __ movq(StackSpaceOperand(1), rax); // FunctionCallbackInfo::values_.
|
| __ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_.
|
| // FunctionCallbackInfo::is_construct_call_.
|
| __ Set(StackSpaceOperand(3), 0);
|
| @@ -532,39 +640,6 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -// Generate call to api function.
|
| -static void GenerateFastApiCall(MacroAssembler* masm,
|
| - const CallOptimization& optimization,
|
| - Register receiver,
|
| - Register scratch,
|
| - int argc,
|
| - Register* values) {
|
| - ASSERT(optimization.is_simple_api_call());
|
| - ASSERT(!receiver.is(scratch));
|
| -
|
| - const int fast_api_call_argc = argc + kFastApiCallArguments;
|
| - StackArgumentsAccessor args(rsp, fast_api_call_argc);
|
| - // argc + 1 is the argument number before FastApiCall arguments, 1 ~ receiver
|
| - const int kHolderIndex = argc + 1 +
|
| - kFastApiCallArguments - 1 - FunctionCallbackArguments::kHolderIndex;
|
| - __ movq(scratch, StackOperandForReturnAddress(0));
|
| - // Assign stack space for the call arguments and receiver.
|
| - __ subq(rsp, Immediate((fast_api_call_argc + 1) * kPointerSize));
|
| - __ movq(StackOperandForReturnAddress(0), scratch);
|
| - // Write holder to stack frame.
|
| - __ movq(args.GetArgumentOperand(kHolderIndex), receiver);
|
| - __ movq(args.GetReceiverOperand(), receiver);
|
| - // Write the arguments to stack frame.
|
| - for (int i = 0; i < argc; i++) {
|
| - ASSERT(!receiver.is(values[i]));
|
| - ASSERT(!scratch.is(values[i]));
|
| - __ movq(args.GetArgumentOperand(i + 1), values[i]);
|
| - }
|
| -
|
| - GenerateFastApiCall(masm, optimization, argc, true);
|
| -}
|
| -
|
| -
|
| class CallInterceptorCompiler BASE_EMBEDDED {
|
| public:
|
| CallInterceptorCompiler(StubCompiler* stub_compiler,
|
| @@ -675,7 +750,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
|
|
| // Invoke function.
|
| if (can_do_fast_api_call) {
|
| - GenerateFastApiCall(masm, optimization, arguments_.immediate(), false);
|
| + GenerateFastApiCall(masm, optimization, arguments_.immediate());
|
| } else {
|
| CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| ? CALL_AS_FUNCTION
|
| @@ -1294,7 +1369,8 @@ void LoadStubCompiler::GenerateLoadField(Register reg,
|
| void LoadStubCompiler::GenerateLoadCallback(
|
| const CallOptimization& call_optimization) {
|
| GenerateFastApiCall(
|
| - masm(), call_optimization, receiver(), scratch3(), 0, NULL);
|
| + masm(), call_optimization, receiver(),
|
| + scratch1(), scratch2(), name(), 0, NULL);
|
| }
|
|
|
|
|
| @@ -2501,7 +2577,7 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
|
| StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
|
| __ movq(StackOperandForReturnAddress(0), rax);
|
|
|
| - GenerateFastApiCall(masm(), optimization, argc, false);
|
| + GenerateFastApiCall(masm(), optimization, argc);
|
|
|
| __ bind(&miss);
|
| __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
|
| @@ -2821,7 +2897,8 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
|
|
|
| Register values[] = { value() };
|
| GenerateFastApiCall(
|
| - masm(), call_optimization, receiver(), scratch3(), 1, values);
|
| + masm(), call_optimization, receiver(), scratch1(),
|
| + scratch2(), this->name(), 1, values);
|
|
|
| // Return the generated code.
|
| return GetCode(kind(), Code::CALLBACKS, name);
|
|
|