Revision: 18146
Author: [email protected]
Date: Fri Nov 29 09:02:00 2013 UTC
Log: Revert r18131 and r18139 "Clean up in the CallStubCompiler".
and "Fix register usage."
[email protected]
Review URL: https://codereview.chromium.org/96573002
http://code.google.com/p/v8/source/detail?r=18146
Modified:
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/stub-cache.cc
/branches/bleeding_edge/src/stub-cache.h
/branches/bleeding_edge/src/x64/macro-assembler-x64.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.h
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Thu Nov 28
15:26:04 2013 UTC
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Fri Nov 29
09:02:00 2013 UTC
@@ -1229,7 +1229,7 @@
}
-void MacroAssembler::InvokeFunction(Register function,
+void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
@@ -1238,10 +1238,8 @@
// You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame());
- // Contract with called JS functions requires that function is passed in
r1.
- ASSERT(function.is(r1));
-
// Get the function and setup the context.
+ Move(r1, function);
ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
// We call indirectly through the code field in the function to
@@ -1250,17 +1248,6 @@
ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
InvokeCode(r3, expected, actual, flag, call_wrapper, call_kind);
}
-
-
-void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
- const ParameterCount& expected,
- const ParameterCount& actual,
- InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind) {
- Move(r1, function);
- InvokeFunction(r1, expected, actual, flag, call_wrapper, call_kind);
-}
void MacroAssembler::IsObjectJSObjectType(Register heap_object,
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Thu Nov 28
15:26:04 2013 UTC
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Fri Nov 29
09:02:00 2013 UTC
@@ -613,13 +613,6 @@
const CallWrapper& call_wrapper,
CallKind call_kind);
- void InvokeFunction(Register function,
- const ParameterCount& expected,
- const ParameterCount& actual,
- InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind);
-
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Nov 28 18:11:15
2013 UTC
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Fri Nov 29 09:02:00
2013 UTC
@@ -740,6 +740,36 @@
__ mov(this->name(), Operand(name));
}
}
+
+
+static void GenerateCallFunction(MacroAssembler* masm,
+ Handle<Object> object,
+ const ParameterCount& arguments,
+ Label* miss,
+ Code::ExtraICState extra_ic_state) {
+ // ----------- S t a t e -------------
+ // -- r0: receiver
+ // -- r1: function to call
+ // -----------------------------------
+
+ // Check that the function really is a function.
+ __ JumpIfSmi(r1, miss);
+ __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
+ __ b(ne, miss);
+
+ if (object->IsGlobalObject()) {
+ const int argc = arguments.immediate();
+ const int receiver_offset = argc * kPointerSize;
+ __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
+ __ str(r3, MemOperand(sp, receiver_offset));
+ }
+
+ // Invoke the function.
+ CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(),
call_kind);
+}
static void PushInterceptorArguments(MacroAssembler* masm,
@@ -925,7 +955,7 @@
class CallInterceptorCompiler BASE_EMBEDDED {
public:
- CallInterceptorCompiler(CallStubCompiler* stub_compiler,
+ CallInterceptorCompiler(StubCompiler* stub_compiler,
const ParameterCount& arguments,
Register name,
ExtraICState extra_ic_state)
@@ -1037,8 +1067,13 @@
GenerateFastApiDirectCall(
masm, optimization, arguments_.immediate(), false);
} else {
+ CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
Handle<JSFunction> function = optimization.constant_function();
- stub_compiler_->GenerateJumpFunction(object, function);
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments_,
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
// Deferred code for fast API call case---clean preallocated space.
@@ -1104,7 +1139,7 @@
__ b(ne, interceptor_succeeded);
}
- CallStubCompiler* stub_compiler_;
+ StubCompiler* stub_compiler_;
const ParameterCount& arguments_;
Register name_;
ExtraICState extra_ic_state_;
@@ -1504,15 +1539,6 @@
__ b(ne, miss);
}
}
-
-
-void CallStubCompiler::GenerateFunctionCheck(Register function,
- Register scratch,
- Label* miss) {
- __ JumpIfSmi(function, miss);
- __ CompareObjectType(function, scratch, scratch, JS_FUNCTION_TYPE);
- __ b(ne, miss);
-}
void CallStubCompiler::GenerateLoadFunctionFromCell(
@@ -1530,7 +1556,9 @@
// the nice side effect that multiple closures based on the same
// function can all use this call IC. Before we load through the
// function, we have to verify that it still is a function.
- GenerateFunctionCheck(r1, r3, miss);
+ __ JumpIfSmi(r1, miss);
+ __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
+ __ b(ne, miss);
// Check the shared function info. Make sure it hasn't changed.
__ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
@@ -1562,7 +1590,8 @@
object, holder, name, RECEIVER_MAP_CHECK, &miss);
GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder),
index.translate(holder),
Representation::Tagged());
- GenerateJumpFunction(object, r1, &miss);
+
+ GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
HandlerFrontendFooter(&miss);
@@ -1977,7 +2006,8 @@
__ bind(&miss);
// Restore function name in r2.
__ Move(r2, name);
- HandlerFrontendFooter(&name_miss);
+ __ bind(&name_miss);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(type, name);
@@ -2043,7 +2073,8 @@
__ bind(&miss);
// Restore function name in r2.
__ Move(r2, name);
- HandlerFrontendFooter(&name_miss);
+ __ bind(&name_miss);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(type, name);
@@ -2090,10 +2121,12 @@
StubRuntimeCallHelper call_helper;
generator.GenerateSlow(masm(), call_helper);
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
__ bind(&slow);
- // We do not have to patch the receiver because the function makes no
use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss);
@@ -2181,9 +2214,11 @@
__ Ret();
__ bind(&slow);
- // We do not have to patch the receiver because the function makes no
use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss);
@@ -2261,10 +2296,12 @@
__ Drop(argc + 1);
__ Ret();
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
__ bind(&slow);
- // We do not have to patch the receiver because the function makes no
use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss);
@@ -2317,7 +2354,8 @@
__ bind(&miss);
FreeSpaceForFastApiCall(masm());
- HandlerFrontendFooter(&miss_before_stack_reserved);
+ __ bind(&miss_before_stack_reserved);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(function);
@@ -2338,7 +2376,7 @@
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
- if (!object.is_null() && object->IsGlobalObject()) {
+ if (object->IsGlobalObject()) {
const int argc = arguments().immediate();
const int receiver_offset = argc * kPointerSize;
__ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
@@ -2434,18 +2472,39 @@
}
-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
- Register function,
- Label* miss) {
- ASSERT(function.is(r1));
- // Check that the function really is a function.
- GenerateFunctionCheck(function, r3, miss);
- if (!function.is(r1)) __ mov(r1, function);
+void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
+}
+
+
+Handle<Code> CallStubCompiler::CompileCallConstant(
+ Handle<Object> object,
+ Handle<JSObject> holder,
+ Handle<Name> name,
+ CheckType check,
+ Handle<JSFunction> function) {
+ if (HasCustomCallGenerator(function)) {
+ Handle<Code> code = CompileCustomCall(object, holder,
+ Handle<Cell>::null(),
+ function,
Handle<String>::cast(name),
+ Code::FAST);
+ // A null handle means bail out to the regular compiler code below.
+ if (!code.is_null()) return code;
+ }
+
+ Label miss;
+ HandlerFrontendHeader(object, holder, name, check, &miss);
PatchGlobalProxy(object);
+ CompileHandlerBackend(function);
+ HandlerFrontendFooter(&miss);
- // Invoke the function.
- __ InvokeFunction(r1, arguments(), JUMP_FUNCTION,
- NullCallWrapper(), call_kind());
+ // Return the generated code.
+ return GetCode(function);
}
@@ -2472,9 +2531,11 @@
// Restore receiver.
__ ldr(r0, MemOperand(sp, argc * kPointerSize));
- GenerateJumpFunction(object, r1, &miss);
+ GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
- HandlerFrontendFooter(&miss);
+ // Handle call cache miss.
+ __ bind(&miss);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(Code::FAST, name);
@@ -2497,13 +2558,26 @@
Label miss;
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- // Potentially loads a closure that matches the shared function info of
the
- // function, rather than function.
GenerateLoadFunctionFromCell(cell, function, &miss);
+ PatchGlobalProxy(object);
+
+ // Set up the context (function already in r1).
+ __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
+ // Jump to the cached code (tail call).
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
- GenerateJumpFunction(object, r1, function);
+ ParameterCount expected(function->shared()->formal_parameter_count());
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ // We call indirectly through the code field in the function to
+ // allow recompilation to take effect without changing any of the
+ // call sites.
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
+ __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
+ NullCallWrapper(), call_kind);
+
HandlerFrontendFooter(&miss);
// Return the generated code.
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Thu Nov 28
15:26:04 2013 UTC
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Fri Nov 29
09:02:00 2013 UTC
@@ -2636,7 +2636,7 @@
}
-void MacroAssembler::InvokeFunction(Register fun,
+void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
@@ -2645,23 +2645,16 @@
// You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame());
- ASSERT(fun.is(edi));
+ // Get the function and setup the context.
+ LoadHeapObject(edi, function);
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
+ // We call indirectly through the code field in the function to
+ // allow recompilation to take effect without changing any of the
+ // call sites.
InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
expected, actual, flag, call_wrapper, call_kind);
}
-
-
-void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
- const ParameterCount& expected,
- const ParameterCount& actual,
- InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind) {
- LoadHeapObject(edi, function);
- InvokeFunction(edi, expected, actual, flag, call_wrapper, call_kind);
-}
void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Thu Nov 28
15:26:04 2013 UTC
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Fri Nov 29
09:02:00 2013 UTC
@@ -349,13 +349,6 @@
const CallWrapper& call_wrapper,
CallKind call_kind);
- void InvokeFunction(Register function,
- const ParameterCount& expected,
- const ParameterCount& actual,
- InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind);
-
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Thu Nov 28 18:11:15
2013 UTC
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Nov 29 09:02:00
2013 UTC
@@ -645,7 +645,7 @@
class CallInterceptorCompiler BASE_EMBEDDED {
public:
- CallInterceptorCompiler(CallStubCompiler* stub_compiler,
+ CallInterceptorCompiler(StubCompiler* stub_compiler,
const ParameterCount& arguments,
Register name,
ExtraICState extra_state)
@@ -756,8 +756,13 @@
if (can_do_fast_api_call) {
GenerateFastApiCall(masm, optimization, arguments_.immediate());
} else {
- Handle<JSFunction> fun = optimization.constant_function();
- stub_compiler_->GenerateJumpFunction(object, fun);
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ Handle<JSFunction> function = optimization.constant_function();
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments_,
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
// Deferred code for fast API call case---clean preallocated space.
@@ -825,7 +830,7 @@
__ j(not_equal, interceptor_succeeded);
}
- CallStubCompiler* stub_compiler_;
+ StubCompiler* stub_compiler_;
const ParameterCount& arguments_;
Register name_;
ExtraICState extra_state_;
@@ -1596,15 +1601,6 @@
}
}
-
-void CallStubCompiler::GenerateFunctionCheck(Register function,
- Register scratch,
- Label* miss) {
- __ JumpIfSmi(function, miss);
- __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
- __ j(not_equal, miss);
-}
-
void CallStubCompiler::GenerateLoadFunctionFromCell(
Handle<Cell> cell,
@@ -1625,7 +1621,9 @@
// the nice side effect that multiple closures based on the same
// function can all use this call IC. Before we load through the
// function, we have to verify that it still is a function.
- GenerateFunctionCheck(edi, ebx, miss);
+ __ JumpIfSmi(edi, miss);
+ __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
+ __ j(not_equal, miss);
// Check the shared function info. Make sure it hasn't changed.
__ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
@@ -1658,7 +1656,20 @@
GenerateFastPropertyLoad(
masm(), edi, reg, index.is_inobject(holder),
index.translate(holder), Representation::Tagged());
- GenerateJumpFunction(object, edi, &miss);
+
+ // Check that the function really is a function.
+ __ JumpIfSmi(edi, &miss);
+ __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
+ __ j(not_equal, &miss);
+
+ PatchGlobalProxy(object);
+
+ // Invoke the function.
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
+ NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss);
@@ -2070,7 +2081,8 @@
__ bind(&miss);
// Restore function name in ecx.
__ Set(ecx, Immediate(name));
- HandlerFrontendFooter(&name_miss);
+ __ bind(&name_miss);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(type, name);
@@ -2138,7 +2150,8 @@
__ bind(&miss);
// Restore function name in ecx.
__ Set(ecx, Immediate(name));
- HandlerFrontendFooter(&name_miss);
+ __ bind(&name_miss);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(type, name);
@@ -2187,10 +2200,15 @@
StubRuntimeCallHelper call_helper;
generator.GenerateSlow(masm(), call_helper);
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
__ bind(&slow);
- // We do not have to patch the receiver because the function makes no
use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss);
@@ -2297,10 +2315,12 @@
__ mov(eax, Operand(esp, 1 * kPointerSize));
__ ret(2 * kPointerSize);
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
__ bind(&slow);
- // We do not have to patch the receiver because the function makes no
use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss);
@@ -2384,10 +2404,12 @@
__ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
__ ret(2 * kPointerSize);
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
__ bind(&slow);
- // We do not have to patch the receiver because the function makes no
use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss);
@@ -2447,7 +2469,8 @@
__ bind(&miss);
__ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
- HandlerFrontendFooter(&miss_before_stack_reserved);
+ __ bind(&miss_before_stack_reserved);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(function);
@@ -2466,7 +2489,7 @@
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
- if (!object.is_null() && object->IsGlobalObject()) {
+ if (object->IsGlobalObject()) {
const int argc = arguments().immediate();
const int receiver_offset = (argc + 1) * kPointerSize;
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
@@ -2556,18 +2579,40 @@
}
-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
- Register function,
- Label* miss) {
- // Check that the function really is a function.
- GenerateFunctionCheck(function, ebx, miss);
+void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
+}
- if (!function.is(edi)) __ mov(edi, function);
+
+Handle<Code> CallStubCompiler::CompileCallConstant(
+ Handle<Object> object,
+ Handle<JSObject> holder,
+ Handle<Name> name,
+ CheckType check,
+ Handle<JSFunction> function) {
+
+ if (HasCustomCallGenerator(function)) {
+ Handle<Code> code = CompileCustomCall(object, holder,
+ Handle<Cell>::null(),
+ function,
Handle<String>::cast(name),
+ Code::FAST);
+ // A null handle means bail out to the regular compiler code below.
+ if (!code.is_null()) return code;
+ }
+
+ Label miss;
+ HandlerFrontendHeader(object, holder, name, check, &miss);
PatchGlobalProxy(object);
+ CompileHandlerBackend(function);
+ HandlerFrontendFooter(&miss);
- // Invoke the function.
- __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
- NullCallWrapper(), call_kind());
+ // Return the generated code.
+ return GetCode(function);
}
@@ -2594,9 +2639,29 @@
// Restore receiver.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
- GenerateJumpFunction(object, eax, &miss);
+ // Check that the function really is a function.
+ __ JumpIfSmi(eax, &miss);
+ __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
+ __ j(not_equal, &miss);
+
+ // Patch the receiver on the stack with the global proxy if
+ // necessary.
+ if (object->IsGlobalObject()) {
+ __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+ __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+ }
+
+ // Invoke the function.
+ __ mov(edi, eax);
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
+ NullCallWrapper(), call_kind);
- HandlerFrontendFooter(&miss);
+ // Handle load cache miss.
+ __ bind(&miss);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(Code::FAST, name);
@@ -2619,10 +2684,25 @@
Label miss;
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- // Potentially loads a closure that matches the shared function info of
the
- // function, rather than function.
GenerateLoadFunctionFromCell(cell, function, &miss);
- GenerateJumpFunction(object, edi, function);
+ PatchGlobalProxy(object);
+
+ // Set up the context (function already in edi).
+ __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
+
+ // Jump to the cached code (tail call).
+ Counters* counters = isolate()->counters();
+ __ IncrementCounter(counters->call_global_inline(), 1);
+ ParameterCount expected(function->shared()->formal_parameter_count());
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ // We call indirectly through the code field in the function to
+ // allow recompilation to take effect without changing any of the
+ // call sites.
+ __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
+ expected, arguments(), JUMP_FUNCTION,
+ NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss);
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc Thu Nov 28 18:13:30 2013 UTC
+++ /branches/bleeding_edge/src/stub-cache.cc Fri Nov 29 09:02:00 2013 UTC
@@ -1128,67 +1128,10 @@
#define __ ACCESS_MASM(masm())
-CallKind CallStubCompiler::call_kind() {
- return CallICBase::Contextual::decode(extra_state_)
- ? CALL_AS_FUNCTION
- : CALL_AS_METHOD;
-}
-
-
void CallStubCompiler::HandlerFrontendFooter(Label* miss) {
__ bind(miss);
GenerateMissBranch();
}
-
-
-void CallStubCompiler::GenerateJumpFunctionIgnoreReceiver(
- Handle<JSFunction> function) {
- ParameterCount expected(function);
- __ InvokeFunction(function, expected, arguments(),
- JUMP_FUNCTION, NullCallWrapper(), call_kind());
-}
-
-
-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
- Handle<JSFunction> function) {
- PatchGlobalProxy(object);
- GenerateJumpFunctionIgnoreReceiver(function);
-}
-
-
-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
- Register actual_closure,
- Handle<JSFunction> function) {
- PatchGlobalProxy(object);
- ParameterCount expected(function);
- __ InvokeFunction(actual_closure, expected, arguments(),
- JUMP_FUNCTION, NullCallWrapper(), call_kind());
-}
-
-
-Handle<Code> CallStubCompiler::CompileCallConstant(
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Name> name,
- CheckType check,
- Handle<JSFunction> function) {
- if (HasCustomCallGenerator(function)) {
- Handle<Code> code = CompileCustomCall(object, holder,
- Handle<Cell>::null(),
- function,
Handle<String>::cast(name),
- Code::FAST);
- // A null handle means bail out to the regular compiler code below.
- if (!code.is_null()) return code;
- }
-
- Label miss;
- HandlerFrontendHeader(object, holder, name, check, &miss);
- GenerateJumpFunction(object, function);
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(function);
-}
Register LoadStubCompiler::HandlerFrontendHeader(
=======================================
--- /branches/bleeding_edge/src/stub-cache.h Thu Nov 28 18:13:30 2013 UTC
+++ /branches/bleeding_edge/src/stub-cache.h Fri Nov 29 09:02:00 2013 UTC
@@ -919,17 +919,7 @@
Label* miss);
void HandlerFrontendFooter(Label* miss);
- void GenerateJumpFunctionIgnoreReceiver(Handle<JSFunction> function);
- void GenerateJumpFunction(Handle<Object> object,
- Handle<JSFunction> function);
- void GenerateJumpFunction(Handle<Object> object,
- Register function,
- Label* miss);
- // Use to call |actual_closure|, a closure with the same shared function
info
- // as |function|.
- void GenerateJumpFunction(Handle<Object> object,
- Register actual_closure,
- Handle<JSFunction> function);
+ void CompileHandlerBackend(Handle<JSFunction> function);
Handle<Code> CompileCallConstant(Handle<Object> object,
Handle<JSObject> holder,
@@ -978,8 +968,6 @@
Handle<JSFunction> function,
Handle<String> name);
- CallKind call_kind();
-
Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
Handle<Code> GetCode(Handle<JSFunction> function);
@@ -993,8 +981,6 @@
Handle<JSFunction> function,
Label* miss);
- void GenerateFunctionCheck(Register function, Register scratch, Label*
miss);
-
// Generates a jump to CallIC miss stub.
void GenerateMissBranch();
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Thu Nov 28
15:26:04 2013 UTC
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Fri Nov 29
09:02:00 2013 UTC
@@ -3601,7 +3601,7 @@
}
-void MacroAssembler::InvokeFunction(Register function,
+void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
@@ -3610,25 +3610,16 @@
// You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame());
- ASSERT(function.is(rdi));
- movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
- // Advances rdx to the end of the Code object header, to the start of
- // the executable code.
+ // Get the function and setup the context.
+ Move(rdi, function);
+ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
+
+ // We call indirectly through the code field in the function to
+ // allow recompilation to take effect without changing any of the
+ // call sites.
movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
-
InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
}
-
-
-void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
- const ParameterCount& expected,
- const ParameterCount& actual,
- InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind) {
- Move(rdi, function);
- InvokeFunction(rdi, expected, actual, flag, call_wrapper, call_kind);
-}
void MacroAssembler::InvokePrologue(const ParameterCount& expected,
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Thu Nov 28
15:26:04 2013 UTC
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Fri Nov 29
09:02:00 2013 UTC
@@ -371,13 +371,6 @@
const CallWrapper& call_wrapper,
CallKind call_kind);
- void InvokeFunction(Register function,
- const ParameterCount& expected,
- const ParameterCount& actual,
- InvokeFlag flag,
- const CallWrapper& call_wrapper,
- CallKind call_kind);
-
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Thu Nov 28 18:11:15
2013 UTC
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Fri Nov 29 09:02:00
2013 UTC
@@ -637,7 +637,7 @@
class CallInterceptorCompiler BASE_EMBEDDED {
public:
- CallInterceptorCompiler(CallStubCompiler* stub_compiler,
+ CallInterceptorCompiler(StubCompiler* stub_compiler,
const ParameterCount& arguments,
Register name,
ExtraICState extra_ic_state)
@@ -748,8 +748,13 @@
if (can_do_fast_api_call) {
GenerateFastApiCall(masm, optimization, arguments_.immediate());
} else {
+ CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
Handle<JSFunction> fun = optimization.constant_function();
- stub_compiler_->GenerateJumpFunction(object, fun);
+ ParameterCount expected(fun);
+ __ InvokeFunction(fun, expected, arguments_,
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
// Deferred code for fast API call case---clean preallocated space.
@@ -817,7 +822,7 @@
__ j(not_equal, interceptor_succeeded);
}
- CallStubCompiler* stub_compiler_;
+ StubCompiler* stub_compiler_;
const ParameterCount& arguments_;
Register name_;
ExtraICState extra_ic_state_;
@@ -1530,15 +1535,6 @@
__ j(not_equal, miss);
}
}
-
-
-void CallStubCompiler::GenerateFunctionCheck(Register function,
- Register scratch,
- Label* miss) {
- __ JumpIfSmi(function, miss);
- __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
- __ j(not_equal, miss);
-}
void CallStubCompiler::GenerateLoadFunctionFromCell(
@@ -1556,7 +1552,9 @@
// the nice side effect that multiple closures based on the same
// function can all use this call IC. Before we load through the
// function, we have to verify that it still is a function.
- GenerateFunctionCheck(rdi, rax, miss);
+ __ JumpIfSmi(rdi, miss);
+ __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
+ __ j(not_equal, miss);
// Check the shared function info. Make sure it hasn't changed.
__ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
@@ -1588,7 +1586,20 @@
GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
index.translate(holder),
Representation::Tagged());
- GenerateJumpFunction(object, rdi, &miss);
+
+ // Check that the function really is a function.
+ __ JumpIfSmi(rdi, &miss);
+ __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
+ __ j(not_equal, &miss);
+
+ PatchGlobalProxy(object);
+
+ // Invoke the function.
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
+ NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss);
@@ -2003,7 +2014,8 @@
__ bind(&miss);
// Restore function name in rcx.
__ Move(rcx, name);
- HandlerFrontendFooter(&name_miss);
+ __ bind(&name_miss);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(type, name);
@@ -2068,7 +2080,8 @@
__ bind(&miss);
// Restore function name in rcx.
__ Move(rcx, name);
- HandlerFrontendFooter(&name_miss);
+ __ bind(&name_miss);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(type, name);
@@ -2114,10 +2127,15 @@
StubRuntimeCallHelper call_helper;
generator.GenerateSlow(masm(), call_helper);
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
__ bind(&slow);
- // We do not have to patch the receiver because the function makes no
use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss);
@@ -2220,10 +2238,12 @@
__ movq(rax, args.GetArgumentOperand(1));
__ ret(2 * kPointerSize);
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
__ bind(&slow);
- // We do not have to patch the receiver because the function makes no
use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
HandlerFrontendFooter(&miss);
@@ -2304,10 +2324,15 @@
__ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx);
__ ret(2 * kPointerSize);
+ // Tail call the full function. We do not have to patch the receiver
+ // because the function makes no use of it.
__ bind(&slow);
- // We do not have to patch the receiver because the function makes no
use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
HandlerFrontendFooter(&miss);
@@ -2365,7 +2390,8 @@
__ bind(&miss);
__ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
- HandlerFrontendFooter(&miss_before_stack_reserved);
+ __ bind(&miss_before_stack_reserved);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(function);
@@ -2384,7 +2410,7 @@
void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
- if (!object.is_null() && object->IsGlobalObject()) {
+ if (object->IsGlobalObject()) {
StackArgumentsAccessor args(rsp, arguments());
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(args.GetReceiverOperand(), rdx);
@@ -2473,18 +2499,39 @@
}
-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
- Register function,
- Label* miss) {
- // Check that the function really is a function.
- GenerateFunctionCheck(function, rbx, miss);
+void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ ParameterCount expected(function);
+ __ InvokeFunction(function, expected, arguments(),
+ JUMP_FUNCTION, NullCallWrapper(), call_kind);
+}
- if (!function.is(rdi)) __ movq(rdi, function);
+
+Handle<Code> CallStubCompiler::CompileCallConstant(
+ Handle<Object> object,
+ Handle<JSObject> holder,
+ Handle<Name> name,
+ CheckType check,
+ Handle<JSFunction> function) {
+ if (HasCustomCallGenerator(function)) {
+ Handle<Code> code = CompileCustomCall(object, holder,
+ Handle<PropertyCell>::null(),
+ function,
Handle<String>::cast(name),
+ Code::FAST);
+ // A null handle means bail out to the regular compiler code below.
+ if (!code.is_null()) return code;
+ }
+
+ Label miss;
+ HandlerFrontendHeader(object, holder, name, check, &miss);
PatchGlobalProxy(object);
+ CompileHandlerBackend(function);
+ HandlerFrontendFooter(&miss);
- // Invoke the function.
- __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
- NullCallWrapper(), call_kind());
+ // Return the generated code.
+ return GetCode(function);
}
@@ -2508,9 +2555,29 @@
// Restore receiver.
__ movq(rdx, args.GetReceiverOperand());
- GenerateJumpFunction(object, rax, &miss);
+ // Check that the function really is a function.
+ __ JumpIfSmi(rax, &miss);
+ __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
+ __ j(not_equal, &miss);
+
+ // Patch the receiver on the stack with the global proxy if
+ // necessary.
+ if (object->IsGlobalObject()) {
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
+ __ movq(args.GetReceiverOperand(), rdx);
+ }
+
+ // Invoke the function.
+ __ movq(rdi, rax);
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
+ NullCallWrapper(), call_kind);
- HandlerFrontendFooter(&miss);
+ // Handle load cache miss.
+ __ bind(&miss);
+ GenerateMissBranch();
// Return the generated code.
return GetCode(Code::FAST, name);
@@ -2533,12 +2600,26 @@
Label miss;
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- // Potentially loads a closure that matches the shared function info of
the
- // function, rather than function.
GenerateLoadFunctionFromCell(cell, function, &miss);
+ PatchGlobalProxy(object);
+
+ // Set up the context (function already in rdi).
+ __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
+
+ // Jump to the cached code (tail call).
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->call_global_inline(), 1);
- GenerateJumpFunction(object, rdi, function);
+ ParameterCount expected(function->shared()->formal_parameter_count());
+ CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
+ ? CALL_AS_FUNCTION
+ : CALL_AS_METHOD;
+ // We call indirectly through the code field in the function to
+ // allow recompilation to take effect without changing any of the
+ // call sites.
+ __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
+ __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
+ NullCallWrapper(), call_kind);
+
HandlerFrontendFooter(&miss);
// Return the generated code.
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.