X64: Implement inline caches for loads

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2515 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2009-07-21 11:06:24 +00:00
parent 46b8d84659
commit 8ff3dc5280

View File

@ -316,21 +316,45 @@ Object* LoadStubCompiler::CompileLoadCallback(JSObject* a,
}
Object* LoadStubCompiler::CompileLoadConstant(JSObject* a,
JSObject* b,
Object* c,
String* d) {
// TODO(X64): Implement a real stub.
return Failure::InternalError();
Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
JSObject* holder,
Object* value,
String* name) {
// ----------- S t a t e -------------
// -- rcx : name
// -- rsp[0] : return address
// -- rsp[8] : receiver
// -----------------------------------
Label miss;
__ movq(rax, (Operand(rsp, kPointerSize)));
GenerateLoadConstant(object, holder, rax, rbx, rdx, value, name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC);
// Return the generated code.
return GetCode(CONSTANT_FUNCTION, name);
}
Object* LoadStubCompiler::CompileLoadField(JSObject* a,
JSObject* b,
int c,
String* d) {
// TODO(X64): Implement a real stub.
return Failure::InternalError();
Object* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* holder,
int index,
String* name) {
// ----------- S t a t e -------------
// -- rcx : name
// -- rsp[0] : return address
// -- rsp[8] : receiver
// -----------------------------------
Label miss;
__ movq(rax, (Operand(rsp, kPointerSize)));
GenerateLoadField(object, holder, rax, rbx, rdx, index, name, &miss);
__ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC);
// Return the generated code.
return GetCode(FIELD, name);
}
@ -347,8 +371,51 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
JSGlobalPropertyCell* cell,
String* name,
bool is_dont_delete) {
// TODO(X64): Implement a real stub.
return Failure::InternalError();
// ----------- S t a t e -------------
// -- rcx : name
// -- rsp[0] : return address
// -- rsp[8] : receiver
// -----------------------------------
Label miss;
__ IncrementCounter(&Counters::named_load_global_inline, 1);
// Get the receiver from the stack.
__ movq(rax, (Operand(rsp, kPointerSize)));
// If the object is the holder then we know that it's a global
// object which can only happen for contextual loads. In this case,
// the receiver cannot be a smi.
if (object != holder) {
__ testl(rax, Immediate(kSmiTagMask));
__ j(zero, &miss);
}
// Check that the maps haven't changed.
CheckPrototypes(object, rax, holder, rbx, rdx, name, &miss);
// Get the value from the cell.
__ Move(rax, Handle<JSGlobalPropertyCell>(cell));
__ movq(rax, FieldOperand(rax, JSGlobalPropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
__ Cmp(rax, Factory::the_hole_value());
__ j(equal, &miss);
} else if (FLAG_debug_code) {
__ Cmp(rax, Factory::the_hole_value());
__ Check(not_equal, "DontDelete cells can't contain the hole");
}
__ ret(0);
__ bind(&miss);
__ DecrementCounter(&Counters::named_load_global_inline, 1);
__ IncrementCounter(&Counters::named_load_global_inline_miss, 1);
GenerateLoadMiss(masm(), Code::LOAD_IC);
// Return the generated code.
return GetCode(NORMAL, name);
}
@ -442,6 +509,53 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
return result;
}
void StubCompiler::GenerateLoadField(JSObject* object,
JSObject* holder,
Register receiver,
Register scratch1,
Register scratch2,
int index,
String* name,
Label* miss) {
// Check that the receiver isn't a smi.
__ testl(receiver, Immediate(kSmiTagMask));
__ j(zero, miss);
// Check the prototype chain.
Register reg =
CheckPrototypes(object, receiver, holder,
scratch1, scratch2, name, miss);
// Get the value from the properties.
GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
__ ret(0);
}
void StubCompiler::GenerateLoadConstant(JSObject* object,
JSObject* holder,
Register receiver,
Register scratch1,
Register scratch2,
Object* value,
String* name,
Label* miss) {
// Check that the receiver isn't a smi.
__ testl(receiver, Immediate(kSmiTagMask));
__ j(zero, miss);
// Check that the maps haven't changed.
Register reg =
CheckPrototypes(object, receiver, holder,
scratch1, scratch2, name, miss);
// Return the constant value.
__ Move(rax, Handle<Object>(value));
__ ret(0);
}
#undef __
//-----------------------------------------------------------------------------
@ -449,6 +563,21 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
#define __ ACCESS_MASM(masm)
void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
Code* code = NULL;
if (kind == Code::LOAD_IC) {
code = Builtins::builtin(Builtins::LoadIC_Miss);
} else {
code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
}
Handle<Code> ic(code);
__ Jump(ic, RelocInfo::CODE_TARGET);
}
void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
int index,
Register prototype) {