Commit ebc21fc9 authored by whesse@chromium.org's avatar whesse@chromium.org

Change keyed load IC interface on x64 to pass arguments in registers.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4787 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c3b4097f
......@@ -8766,6 +8766,9 @@ Result CodeGenerator::EmitKeyedLoad() {
key.ToRegister();
receiver.ToRegister();
// If key and receiver are shared registers on the frame, their values will
// be automatically saved and restored when going to deferred code.
// The result is in elements, which is guaranteed non-shared.
DeferredReferenceGetKeyedValue* deferred =
new DeferredReferenceGetKeyedValue(elements.reg(),
receiver.reg(),
......
......@@ -454,11 +454,10 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ mov(edi,
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
__ cmp(edi, Operand(ecx));
__ sub(edi, Operand(ecx));
__ j(above_equal, &slow);
// Load in-object property.
__ sub(edi, Operand(ecx));
__ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
__ add(ecx, Operand(edi));
__ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));
......@@ -690,7 +689,7 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
__ fincstp();
// Fall through to slow case.
// Slow case: Load key and receiver from stack and jump to runtime.
// Slow case: Jump to runtime.
__ bind(&slow);
__ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
GenerateRuntimeGetProperty(masm);
......
......@@ -418,9 +418,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ movq(rax, Operand(rbp, kIndexOffset));
__ jmp(&entry);
__ bind(&loop);
__ movq(rcx, Operand(rbp, kArgumentsOffset)); // load arguments
__ push(rcx);
__ push(rax);
__ movq(rdx, Operand(rbp, kArgumentsOffset)); // load arguments
// Use inline caching to speed up access to arguments.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
......@@ -430,8 +428,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// we have generated an inline version of the keyed load. In this
// case, we know that we are not generating a test instruction next.
// Remove IC arguments from the stack and push the nth argument.
__ addq(rsp, Immediate(2 * kPointerSize));
// Push the nth argument.
__ push(rax);
// Update the index on the stack and in register rax.
......
......@@ -660,9 +660,25 @@ class DeferredReferenceGetKeyedValue: public DeferredCode {
void DeferredReferenceGetKeyedValue::Generate() {
__ push(receiver_); // First IC argument.
__ push(key_); // Second IC argument.
if (receiver_.is(rdx)) {
if (!key_.is(rax)) {
__ movq(rax, key_);
} // else do nothing.
} else if (receiver_.is(rax)) {
if (key_.is(rdx)) {
__ xchg(rax, rdx);
} else if (key_.is(rax)) {
__ movq(rdx, receiver_);
} else {
__ movq(rdx, receiver_);
__ movq(rax, key_);
}
} else if (key_.is(rax)) {
__ movq(rdx, receiver_);
} else {
__ movq(rax, key_);
__ movq(rdx, receiver_);
}
// Calculate the delta from the IC call instruction to the map check
// movq instruction in the inlined version. This delta is stored in
// a test(rax, delta) instruction after the call so that we can find
......@@ -686,8 +702,6 @@ void DeferredReferenceGetKeyedValue::Generate() {
__ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
if (!dst_.is(rax)) __ movq(dst_, rax);
__ pop(key_);
__ pop(receiver_);
}
......@@ -5852,7 +5866,6 @@ void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot,
frame_->Push(&arguments);
frame_->Push(key_literal->handle());
*result = EmitKeyedLoad();
frame_->Drop(2); // Drop key and receiver.
done->Jump(result);
}
}
......@@ -7447,6 +7460,9 @@ Result CodeGenerator::EmitKeyedLoad() {
key.ToRegister();
receiver.ToRegister();
// If key and receiver are shared registers on the frame, their values will
// be automatically saved and restored when going to deferred code.
// The result is returned in elements, which is not shared.
DeferredReferenceGetKeyedValue* deferred =
new DeferredReferenceGetKeyedValue(elements.reg(),
receiver.reg(),
......@@ -7459,9 +7475,9 @@ Result CodeGenerator::EmitKeyedLoad() {
// initialization code.
__ bind(deferred->patch_site());
// Use masm-> here instead of the double underscore macro since extra
// coverage code can interfere with the patching. Do not use
// root array to load null_value, since it must be patched with
// the expected receiver map.
// coverage code can interfere with the patching. Do not use a load
// from the root away to load null_value, since the load must be patched
// with the expected receiver map, which is not in the root array.
masm_->movq(kScratchRegister, Factory::null_value(),
RelocInfo::EMBEDDED_OBJECT);
masm_->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
......@@ -7504,8 +7520,6 @@ Result CodeGenerator::EmitKeyedLoad() {
__ IncrementCounter(&Counters::keyed_load_inline, 1);
deferred->BindExit();
frame_->Push(&receiver);
frame_->Push(&key);
} else {
Comment cmnt(masm_, "[ Load from keyed Property");
result = frame_->CallKeyedLoadIC(RelocInfo::CODE_TARGET);
......@@ -7516,7 +7530,7 @@ Result CodeGenerator::EmitKeyedLoad() {
// the push that follows might be peep-hole optimized away.
__ nop();
}
ASSERT(frame()->height() == original_height);
ASSERT(frame()->height() == original_height - 2);
return result;
}
......@@ -7560,7 +7574,6 @@ void Reference::GetValue() {
Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
ASSERT(slot != NULL);
cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
if (!persist_after_get_) set_unloaded();
break;
}
......@@ -7573,27 +7586,28 @@ void Reference::GetValue() {
}
Result result = cgen_->EmitNamedLoad(GetName(), is_global);
cgen_->frame()->Push(&result);
if (!persist_after_get_) {
set_unloaded();
}
break;
}
case KEYED: {
// A load of a bare identifier (load from global) cannot be keyed.
ASSERT(expression_->AsVariableProxy()->AsVariable() == NULL);
if (persist_after_get_) {
cgen_->frame()->PushElementAt(1);
cgen_->frame()->PushElementAt(1);
}
Result value = cgen_->EmitKeyedLoad();
cgen_->frame()->Push(&value);
if (!persist_after_get_) {
cgen_->UnloadReference(this);
}
break;
}
default:
UNREACHABLE();
}
if (!persist_after_get_) {
set_unloaded();
}
}
......
......@@ -124,9 +124,10 @@ void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC load call (from ic-x64.cc).
// ----------- S t a t e -------------
// No registers used on entry.
// -- rax : key
// -- rdx : receiver
// -----------------------------------
Generate_DebugBreakCallHelper(masm, 0, false);
Generate_DebugBreakCallHelper(masm, rax.bit() | rdx.bit(), false);
}
......
......@@ -1176,7 +1176,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
// Load the object.
MemOperand object_loc = EmitSlotSearch(object_slot, rax);
__ push(object_loc);
__ movq(rdx, object_loc);
// Assert that the key is a smi.
Literal* key_literal = property->key()->AsLiteral();
......@@ -1184,7 +1184,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
ASSERT(key_literal->handle()->IsSmi());
// Load the key.
__ Push(key_literal->handle());
__ Move(rax, key_literal->handle());
// Do a keyed property load.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
......@@ -1192,8 +1192,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
// Notice: We must not have a "test rax, ..." instruction after the
// call. It is treated specially by the LoadIC code.
__ nop();
// Drop key and object left on the stack by IC, and push the result.
DropAndApply(2, context, rax);
Apply(context, rax);
}
}
......@@ -1699,10 +1698,10 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
Apply(context_, rax);
} else {
VisitForValue(expr->obj(), kStack);
VisitForValue(expr->key(), kStack);
VisitForValue(expr->key(), kAccumulator);
__ pop(rdx);
EmitKeyedPropertyLoad(expr);
// Drop key and receiver left on the stack by IC.
DropAndApply(2, context_, rax);
Apply(context_, rax);
}
}
......@@ -1824,7 +1823,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// Call to a keyed property, use keyed load IC followed by function
// call.
VisitForValue(prop->obj(), kStack);
VisitForValue(prop->key(), kStack);
VisitForValue(prop->key(), kAccumulator);
__ movq(rdx, Operand(rsp, 0));
// Record source code position for IC call.
SetSourcePosition(prop->position());
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
......@@ -1832,8 +1832,6 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// By emitting a nop we make sure that we do not have a "test rax,..."
// instruction after the call it is treated specially by the LoadIC code.
__ nop();
// Drop key left on the stack by IC.
__ Drop(1);
// Pop receiver.
__ pop(rbx);
// Push result (function).
......@@ -2865,7 +2863,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
EmitNamedPropertyLoad(prop);
} else {
VisitForValue(prop->obj(), kStack);
VisitForValue(prop->key(), kStack);
VisitForValue(prop->key(), kAccumulator);
__ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack
__ push(rax); // Copy of key, needed for later store.
EmitKeyedPropertyLoad(prop);
}
}
......
This diff is collapsed.
......@@ -1505,14 +1505,12 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
JSObject* holder,
AccessorInfo* callback) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -- rsp[8] : name
// -- rsp[16] : receiver
// -----------------------------------
Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
__ movq(rcx, Operand(rsp, 2 * kPointerSize));
__ IncrementCounter(&Counters::keyed_load_callback, 1);
// Check that the name has not changed.
......@@ -1520,7 +1518,7 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
__ j(not_equal, &miss);
Failure* failure = Failure::InternalError();
bool success = GenerateLoadCallback(receiver, holder, rcx, rax, rbx, rdx,
bool success = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx,
callback, name, &miss, &failure);
if (!success) return failure;
......@@ -1535,21 +1533,19 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -- rsp[8] : name
// -- rsp[16] : receiver
// -----------------------------------
Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
__ movq(rcx, Operand(rsp, 2 * kPointerSize));
__ IncrementCounter(&Counters::keyed_load_array_length, 1);
// Check that the name has not changed.
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
GenerateLoadArrayLength(masm(), rcx, rdx, &miss);
GenerateLoadArrayLength(masm(), rdx, rcx, &miss);
__ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_array_length, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
......@@ -1564,21 +1560,19 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
JSObject* holder,
Object* value) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -- rsp[8] : name
// -- rsp[16] : receiver
// -----------------------------------
Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
__ movq(rcx, Operand(rsp, 2 * kPointerSize));
__ IncrementCounter(&Counters::keyed_load_constant_function, 1);
// Check that the name has not changed.
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
GenerateLoadConstant(receiver, holder, rcx, rbx, rdx,
GenerateLoadConstant(receiver, holder, rdx, rbx, rcx,
value, name, &miss);
__ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_constant_function, 1);
......@@ -1591,21 +1585,19 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -- rsp[8] : name
// -- rsp[16] : receiver
// -----------------------------------
Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
__ movq(rcx, Operand(rsp, 2 * kPointerSize));
__ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
// Check that the name has not changed.
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
GenerateLoadFunctionPrototype(masm(), rcx, rdx, rbx, &miss);
GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
__ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
......@@ -1619,14 +1611,12 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder,
String* name) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -- rsp[8] : name
// -- rsp[16] : receiver
// -----------------------------------
Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
__ movq(rcx, Operand(rsp, 2 * kPointerSize));
__ IncrementCounter(&Counters::keyed_load_interceptor, 1);
// Check that the name has not changed.
......@@ -1638,9 +1628,9 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
GenerateLoadInterceptor(receiver,
holder,
&lookup,
rcx,
rax,
rdx,
rax,
rcx,
rbx,
name,
&miss);
......@@ -1655,21 +1645,19 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
// ----------- S t a t e -------------
// -- rsp[0] : return address
// -- rsp[8] : name
// -- rsp[16] : receiver
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
__ movq(rcx, Operand(rsp, 2 * kPointerSize));
__ IncrementCounter(&Counters::keyed_load_string_length, 1);
// Check that the name has not changed.
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
GenerateLoadStringLength(masm(), rcx, rdx, rbx, &miss);
GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss);
__ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_string_length, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
......@@ -1847,21 +1835,19 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
JSObject* holder,
int index) {
// ----------- S t a t e -------------
// -- rsp[0] : return address
// -- rsp[8] : name
// -- rsp[16] : receiver
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
__ movq(rcx, Operand(rsp, 2 * kPointerSize));
__ IncrementCounter(&Counters::keyed_load_field, 1);
// Check that the name has not changed.
__ Cmp(rax, Handle<String>(name));
__ j(not_equal, &miss);
GenerateLoadField(receiver, holder, rcx, rbx, rdx, index, name, &miss);
GenerateLoadField(receiver, holder, rdx, rbx, rcx, index, name, &miss);
__ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_field, 1);
......
......@@ -1077,7 +1077,7 @@ Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
Result name = Pop();
Result receiver = Pop();
PrepareForCall(0, 0); // One stack arg, not callee-dropped.
PrepareForCall(0, 0);
MoveResultsToRegisters(&name, &receiver, rcx, rax);
return RawCallCodeObject(ic, mode);
......@@ -1088,7 +1088,10 @@ Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
// Key and receiver are on top of the frame. The IC expects them on
// the stack. It does not drop them.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
PrepareForCall(2, 0); // Two stack args, neither callee-dropped.
Result name = Pop();
Result receiver = Pop();
PrepareForCall(0, 0);
MoveResultsToRegisters(&name, &receiver, rax, rdx);
return RawCallCodeObject(ic, mode);
}
......
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