Commit 8ff3dc52 authored by whesse@chromium.org's avatar whesse@chromium.org

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
parent 46b8d846
...@@ -316,21 +316,45 @@ Object* LoadStubCompiler::CompileLoadCallback(JSObject* a, ...@@ -316,21 +316,45 @@ Object* LoadStubCompiler::CompileLoadCallback(JSObject* a,
} }
Object* LoadStubCompiler::CompileLoadConstant(JSObject* a, Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
JSObject* b, JSObject* holder,
Object* c, Object* value,
String* d) { String* name) {
// TODO(X64): Implement a real stub. // ----------- S t a t e -------------
return Failure::InternalError(); // -- 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, Object* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* b, JSObject* holder,
int c, int index,
String* d) { String* name) {
// TODO(X64): Implement a real stub. // ----------- S t a t e -------------
return Failure::InternalError(); // -- 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, ...@@ -347,8 +371,51 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
String* name, String* name,
bool is_dont_delete) { bool is_dont_delete) {
// TODO(X64): Implement a real stub. // ----------- S t a t e -------------
return Failure::InternalError(); // -- 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, ...@@ -442,6 +509,53 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
return result; 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 __ #undef __
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -449,6 +563,21 @@ Register StubCompiler::CheckPrototypes(JSObject* object, ...@@ -449,6 +563,21 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
#define __ ACCESS_MASM(masm) #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, void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
int index, int index,
Register prototype) { Register prototype) {
......
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