Commit 3d4d5e9e authored by antonm@chromium.org's avatar antonm@chromium.org

Refactoring various pieces of post interceptor caching.

Review URL: http://codereview.chromium.org/596096

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3857 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 58b04396
......@@ -545,6 +545,21 @@ void MacroAssembler::InvokeFunction(Register fun,
}
void MacroAssembler::InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag) {
ASSERT(function->is_compiled());
// Get the function and setup the context.
mov(r1, Operand(Handle<JSFunction>(function)));
ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
// Invoke the cached code.
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag);
}
#ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::SaveRegistersToMemory(RegList regs) {
ASSERT((regs & ~kJSCallerSaved) == 0);
......@@ -1209,6 +1224,16 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
}
void MacroAssembler::CallExternalReference(const ExternalReference& ext,
int num_arguments) {
mov(r0, Operand(num_arguments));
mov(r1, Operand(ext));
CEntryStub stub(1);
CallStub(&stub);
}
void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
int num_arguments,
int result_size) {
......
......@@ -135,6 +135,10 @@ class MacroAssembler: public Assembler {
const ParameterCount& actual,
InvokeFlag flag);
void InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag);
#ifdef ENABLE_DEBUGGER_SUPPORT
// ---------------------------------------------------------------------------
......@@ -335,6 +339,10 @@ class MacroAssembler: public Assembler {
// Convenience function: Same as above, but takes the fid instead.
void CallRuntime(Runtime::FunctionId fid, int num_arguments);
// Convenience function: call an external reference.
void CallExternalReference(const ExternalReference& ext,
int num_arguments);
// Tail call of a runtime routine (jump).
// Like JumpToRuntime, but also takes care of passing the number
// of parameters.
......
......@@ -391,23 +391,6 @@ static void GenerateCallFunction(MacroAssembler* masm,
}
static void GenerateCallConstFunction(MacroAssembler* masm,
JSFunction* function,
const ParameterCount& arguments) {
ASSERT(function->is_compiled());
// Get the function and setup the context.
__ mov(r1, Operand(Handle<JSFunction>(function)));
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
// Jump to the cached code (tail call).
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
__ InvokeCode(code, expected, arguments,
RelocInfo::CODE_TARGET, JUMP_FUNCTION);
}
static void PushInterceptorArguments(MacroAssembler* masm,
Register receiver,
Register holder,
......@@ -458,7 +441,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
LookupResult* lookup,
String* name,
Label* miss_label) {
AccessorInfo* callback = 0;
AccessorInfo* callback = NULL;
bool optimize = false;
// So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added
......@@ -950,7 +933,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
UNREACHABLE();
}
GenerateCallConstFunction(masm(), function, arguments());
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
// Handle call cache miss.
__ bind(&miss);
......@@ -1038,9 +1021,11 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
scratch,
name,
&miss);
GenerateCallConstFunction(masm(),
lookup.GetConstantFunction(),
arguments());
__ InvokeFunction(lookup.GetConstantFunction(),
arguments(),
JUMP_FUNCTION);
__ bind(&invoke);
} else {
......@@ -1050,13 +1035,9 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
PushInterceptorArguments(masm(), receiver, holder_reg, name_reg, holder);
ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptorForCall));
__ mov(r0, Operand(5));
__ mov(r1, Operand(ref));
CEntryStub stub(1);
__ CallStub(&stub);
__ CallExternalReference(
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
5);
__ pop(name_reg);
__ LeaveInternalFrame();
......
......@@ -1145,6 +1145,16 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
}
void MacroAssembler::CallExternalReference(ExternalReference ref,
int num_arguments) {
mov(eax, Immediate(num_arguments));
mov(ebx, Immediate(ref));
CEntryStub stub(1);
CallStub(&stub);
}
Object* MacroAssembler::TryCallRuntime(Runtime::Function* f,
int num_arguments) {
if (f->nargs >= 0 && f->nargs != num_arguments) {
......@@ -1365,6 +1375,21 @@ void MacroAssembler::InvokeFunction(Register fun,
}
void MacroAssembler::InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag) {
ASSERT(function->is_compiled());
// Get the function and setup the context.
mov(edi, Immediate(Handle<JSFunction>(function)));
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
// Invoke the cached code.
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag);
}
void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
// Calls are not allowed in some stubs.
ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
......
......@@ -124,6 +124,10 @@ class MacroAssembler: public Assembler {
const ParameterCount& actual,
InvokeFlag flag);
void InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag);
// Invoke specified builtin JavaScript function. Adds an entry to
// the unresolved list if the name does not resolve.
void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
......@@ -353,6 +357,9 @@ class MacroAssembler: public Assembler {
// Convenience function: Same as above, but takes the fid instead.
void CallRuntime(Runtime::FunctionId id, int num_arguments);
// Convenience function: call an external reference.
void CallExternalReference(ExternalReference ref, int num_arguments);
// Convenience function: Same as above, but takes the fid instead.
Object* TryCallRuntime(Runtime::FunctionId id, int num_arguments);
......
......@@ -152,22 +152,6 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
}
static void PushInterceptorArguments(MacroAssembler* masm,
Register receiver,
Register holder,
Register name,
JSObject* holder_obj) {
__ push(receiver);
__ push(holder);
__ push(name);
InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
ASSERT(!Heap::InNewSpace(interceptor));
__ mov(receiver, Immediate(Handle<Object>(interceptor)));
__ push(receiver);
__ push(FieldOperand(receiver, InterceptorInfo::kDataOffset));
}
void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
int index,
Register prototype) {
......@@ -287,20 +271,31 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
}
static void PushInterceptorArguments(MacroAssembler* masm,
Register receiver,
Register holder,
Register name,
JSObject* holder_obj) {
__ push(receiver);
__ push(holder);
__ push(name);
InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
ASSERT(!Heap::InNewSpace(interceptor));
__ mov(receiver, Immediate(Handle<Object>(interceptor)));
__ push(receiver);
__ push(FieldOperand(receiver, InterceptorInfo::kDataOffset));
}
static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
Register receiver,
Register holder,
Register name,
JSObject* holder_obj) {
PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
ExternalReference ref =
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly));
__ mov(eax, Immediate(5));
__ mov(ebx, Immediate(ref));
CEntryStub stub(1);
__ CallStub(&stub);
__ CallExternalReference(
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)),
5);
}
......@@ -364,7 +359,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
LookupResult* lookup,
String* name,
Label* miss_label) {
AccessorInfo* callback = 0;
AccessorInfo* callback = NULL;
bool optimize = false;
// So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added
......@@ -683,7 +678,6 @@ class CallInterceptorCompiler BASE_EMBEDDED {
Register name)
: stub_compiler_(stub_compiler),
arguments_(arguments),
argc_(arguments.immediate()),
name_(name) {}
void Compile(MacroAssembler* masm,
......@@ -740,6 +734,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
const CallOptimization& optimization,
Label* miss_label) {
ASSERT(optimization.is_constant_call());
ASSERT(!lookup->holder()->IsGlobalObject());
int depth1 = kInvalidProtoDepth;
int depth2 = kInvalidProtoDepth;
......@@ -780,27 +775,11 @@ class CallInterceptorCompiler BASE_EMBEDDED {
scratch1, scratch2, name,
depth2, miss);
if (lookup->holder()->IsGlobalObject()) {
ASSERT(!can_do_fast_api_call);
__ mov(edx, Operand(esp, (argc_ + 1) * kPointerSize));
__ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
__ mov(Operand(esp, (argc_ + 1) * kPointerSize), edx);
}
if (can_do_fast_api_call) {
GenerateFastApiCall(masm, optimization, argc_);
GenerateFastApiCall(masm, optimization, arguments_.immediate());
} else {
// Get the function and setup the context.
JSFunction* function = optimization.constant_function();
__ mov(edi, Immediate(Handle<JSFunction>(function)));
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
// Jump to the cached code (tail call).
ASSERT(function->is_compiled());
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
__ InvokeCode(code, expected, arguments_,
RelocInfo::CODE_TARGET, JUMP_FUNCTION);
__ InvokeFunction(optimization.constant_function(), arguments_,
JUMP_FUNCTION);
}
if (can_do_fast_api_call) {
......@@ -838,13 +817,10 @@ class CallInterceptorCompiler BASE_EMBEDDED {
name_,
holder_obj);
ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptorForCall));
__ mov(eax, Immediate(5));
__ mov(ebx, Immediate(ref));
CEntryStub stub(1);
__ CallStub(&stub);
__ CallExternalReference(
ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
5);
// Restore the name_ register.
__ pop(name_);
......@@ -876,7 +852,6 @@ class CallInterceptorCompiler BASE_EMBEDDED {
StubCompiler* stub_compiler_;
const ParameterCount& arguments_;
const int argc_;
Register name_;
};
......@@ -1378,16 +1353,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
if (depth != kInvalidProtoDepth) {
GenerateFastApiCall(masm(), optimization, argc);
} else {
// Get the function and setup the context.
__ mov(edi, Immediate(Handle<JSFunction>(function)));
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
// Jump to the cached code (tail call).
ASSERT(function->is_compiled());
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
__ InvokeCode(code, expected, arguments(),
RelocInfo::CODE_TARGET, JUMP_FUNCTION);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
}
// Handle call cache miss.
......
......@@ -386,6 +386,16 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
}
void MacroAssembler::CallExternalReference(const ExternalReference& ext,
int num_arguments) {
movq(rax, Immediate(num_arguments));
movq(rbx, ext);
CEntryStub stub(1);
CallStub(&stub);
}
void MacroAssembler::TailCallRuntime(ExternalReference const& ext,
int num_arguments,
int result_size) {
......@@ -1892,6 +1902,21 @@ void MacroAssembler::InvokeFunction(Register function,
}
void MacroAssembler::InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag) {
ASSERT(function->is_compiled());
// Get the function and setup the context.
Move(rdi, Handle<JSFunction>(function));
movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
// Invoke the cached code.
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag);
}
void MacroAssembler::EnterFrame(StackFrame::Type type) {
push(rbp);
movq(rbp, rsp);
......
......@@ -149,6 +149,10 @@ class MacroAssembler: public Assembler {
const ParameterCount& actual,
InvokeFlag flag);
void InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag);
// Invoke specified builtin JavaScript function. Adds an entry to
// the unresolved list if the name does not resolve.
void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
......@@ -644,6 +648,10 @@ class MacroAssembler: public Assembler {
// Convenience function: Same as above, but takes the fid instead.
void CallRuntime(Runtime::FunctionId id, int num_arguments);
// Convenience function: call an external reference.
void CallExternalReference(const ExternalReference& ext,
int num_arguments);
// Tail call of a runtime routine (jump).
// Like JumpToRuntime, but also takes care of passing the number
// of arguments.
......
......@@ -435,7 +435,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
LookupResult* lookup,
String* name,
Label* miss_label) {
AccessorInfo* callback = 0;
AccessorInfo* callback = NULL;
bool optimize = false;
// So far the most popular follow ups for interceptor loads are FIELD
// and CALLBACKS, so inline only them, other cases may be added
......@@ -559,7 +559,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
class CallInterceptorCompiler BASE_EMBEDDED {
public:
CallInterceptorCompiler(const ParameterCount& arguments, Register name)
: arguments_(arguments), argc_(arguments.immediate()), name_(name) {}
: arguments_(arguments), name_(name) {}
void CompileCacheable(MacroAssembler* masm,
StubCompiler* stub_compiler,
......@@ -589,6 +589,8 @@ class CallInterceptorCompiler BASE_EMBEDDED {
return;
}
ASSERT(!lookup->holder()->IsGlobalObject());
__ EnterInternalFrame();
__ push(holder); // Save the holder.
__ push(name_); // Save the name.
......@@ -612,22 +614,8 @@ class CallInterceptorCompiler BASE_EMBEDDED {
scratch2,
name,
miss_label);
if (lookup->holder()->IsGlobalObject()) {
__ movq(rdx, Operand(rsp, (argc_ + 1) * kPointerSize));
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
__ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdx);
}
ASSERT(function->is_compiled());
// Get the function and setup the context.
__ Move(rdi, Handle<JSFunction>(function));
__ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
// Jump to the cached code (tail call).
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
__ InvokeCode(code, expected, arguments_,
RelocInfo::CODE_TARGET, JUMP_FUNCTION);
__ InvokeFunction(function, arguments_, JUMP_FUNCTION);
__ bind(&invoke);
}
......@@ -648,13 +636,9 @@ class CallInterceptorCompiler BASE_EMBEDDED {
name_,
holder_obj);
ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptorForCall));
__ movq(rax, Immediate(5));
__ movq(rbx, ref);
CEntryStub stub(1);
__ CallStub(&stub);
__ CallExternalReference(
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
5);
__ pop(name_);
__ LeaveInternalFrame();
......@@ -662,7 +646,6 @@ class CallInterceptorCompiler BASE_EMBEDDED {
private:
const ParameterCount& arguments_;
int argc_;
Register name_;
};
......@@ -792,16 +775,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
UNREACHABLE();
}
// Get the function and setup the context.
__ Move(rdi, Handle<JSFunction>(function));
__ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
// Jump to the cached code (tail call).
ASSERT(function->is_compiled());
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
__ InvokeCode(code, expected, arguments(),
RelocInfo::CODE_TARGET, JUMP_FUNCTION);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
// Handle call cache miss.
__ bind(&miss);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment