Commit 7556a16c authored by whesse@chromium.org's avatar whesse@chromium.org

Change StoreIC interface on x64 to pass receiver in rdx, not on stack.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3765 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 29229e9b
// Copyright 2006-2008 the V8 project authors. All rights reserved. // Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -132,12 +132,13 @@ void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { ...@@ -132,12 +132,13 @@ void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
// REgister state for IC store call (from ic-ia32.cc). // Register state for IC store call (from ic-ia32.cc).
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : value // -- eax : value
// -- ecx : name // -- ecx : name
// -- edx : receiver
// ----------------------------------- // -----------------------------------
Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false); Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit() | edx.bit(), false);
} }
......
...@@ -2439,8 +2439,6 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { ...@@ -2439,8 +2439,6 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
Load(property->value()); Load(property->value());
frame_->Push(key); frame_->Push(key);
Result ignored = frame_->CallStoreIC(); Result ignored = frame_->CallStoreIC();
// Drop the duplicated receiver and ignore the result.
frame_->Drop();
break; break;
} }
// Fall through // Fall through
...@@ -6021,7 +6019,7 @@ void Reference::SetValue(InitState init_state) { ...@@ -6021,7 +6019,7 @@ void Reference::SetValue(InitState init_state) {
cgen_->frame()->Push(GetName()); cgen_->frame()->Push(GetName());
Result answer = cgen_->frame()->CallStoreIC(); Result answer = cgen_->frame()->CallStoreIC();
cgen_->frame()->Push(&answer); cgen_->frame()->Push(&answer);
cgen_->UnloadReference(this); set_unloaded();
break; break;
} }
......
// Copyright 2009 the V8 project authors. All rights reserved. // Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -158,12 +158,13 @@ void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { ...@@ -158,12 +158,13 @@ void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
// REgister state for IC store call (from ic-x64.cc). // Register state for IC store call (from ic-x64.cc).
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
// -- rdx : receiver
// ----------------------------------- // -----------------------------------
Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), false); Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit() | rdx.bit(), false);
} }
......
// Copyright 2009 the V8 project authors. All rights reserved. // Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -929,10 +929,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -929,10 +929,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
if (key->handle()->IsSymbol()) { if (key->handle()->IsSymbol()) {
VisitForValue(value, kAccumulator); VisitForValue(value, kAccumulator);
__ Move(rcx, key->handle()); __ Move(rcx, key->handle());
__ movq(rdx, Operand(rsp, 0));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET); __ call(ic, RelocInfo::CODE_TARGET);
__ nop(); __ nop();
// StoreIC leaves the receiver on the stack.
break; break;
} }
// Fall through. // Fall through.
...@@ -1054,13 +1054,12 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, ...@@ -1054,13 +1054,12 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
ASSERT(!var->is_this()); ASSERT(!var->is_this());
// Assignment to a global variable. Use inline caching for the // Assignment to a global variable. Use inline caching for the
// assignment. Right-hand-side value is passed in rax, variable name in // assignment. Right-hand-side value is passed in rax, variable name in
// rcx, and the global object on the stack. // rcx, and the global object in rdx.
__ Move(rcx, var->name()); __ Move(rcx, var->name());
__ push(CodeGenerator::GlobalObject()); __ movq(rdx, CodeGenerator::GlobalObject());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
// Overwrite the global object on the stack with the result if needed. Apply(context, rax);
DropAndApply(1, context, rax);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) { } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
__ push(result_register()); // Value. __ push(result_register()); // Value.
...@@ -1120,6 +1119,11 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { ...@@ -1120,6 +1119,11 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
// Record source code position before IC call. // Record source code position before IC call.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
__ Move(rcx, prop->key()->AsLiteral()->handle()); __ Move(rcx, prop->key()->AsLiteral()->handle());
if (expr->ends_initialization_block()) {
__ movq(rdx, Operand(rsp, 0));
} else {
__ pop(rdx);
}
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
__ nop(); __ nop();
...@@ -1130,9 +1134,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { ...@@ -1130,9 +1134,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
__ push(Operand(rsp, kPointerSize)); // Receiver is under value. __ push(Operand(rsp, kPointerSize)); // Receiver is under value.
__ CallRuntime(Runtime::kToFastProperties, 1); __ CallRuntime(Runtime::kToFastProperties, 1);
__ pop(rax); __ pop(rax);
}
DropAndApply(1, context_, rax); DropAndApply(1, context_, rax);
} else {
Apply(context_, rax);
}
} }
...@@ -1658,18 +1663,18 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -1658,18 +1663,18 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
break; break;
case NAMED_PROPERTY: { case NAMED_PROPERTY: {
__ Move(rcx, prop->key()->AsLiteral()->handle()); __ Move(rcx, prop->key()->AsLiteral()->handle());
__ pop(rdx);
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ call(ic, RelocInfo::CODE_TARGET); __ call(ic, RelocInfo::CODE_TARGET);
// This nop signals to the IC that there is no inlined code at the call // This nop signals to the IC that there is no inlined code at the call
// site for it to patch. // site for it to patch.
__ nop(); __ nop();
if (expr->is_postfix()) { if (expr->is_postfix()) {
__ Drop(1); // Result is on the stack under the receiver.
if (context_ != Expression::kEffect) { if (context_ != Expression::kEffect) {
ApplyTOS(context_); ApplyTOS(context_);
} }
} else { } else {
DropAndApply(1, context_, rax); Apply(context_, rax);
} }
break; break;
} }
......
// Copyright 2009 the V8 project authors. All rights reserved. // Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -1330,12 +1330,12 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) { ...@@ -1330,12 +1330,12 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
__ pop(rbx); __ pop(rbx);
__ push(Operand(rsp, 0)); // receiver __ push(rdx); // receiver
__ push(rcx); // name __ push(rcx); // name
__ push(rax); // value __ push(rax); // value
__ push(rbx); // return address __ push(rbx); // return address
...@@ -1348,12 +1348,12 @@ void StoreIC::GenerateExtendStorage(MacroAssembler* masm) { ...@@ -1348,12 +1348,12 @@ void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : Map (target of map transition) // -- rcx : Map (target of map transition)
// -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
__ pop(rbx); __ pop(rbx);
__ push(Operand(rsp, 0)); // receiver __ push(rdx); // receiver
__ push(rcx); // transition map __ push(rcx); // transition map
__ push(rax); // value __ push(rax); // value
__ push(rbx); // return address __ push(rbx); // return address
...@@ -1367,12 +1367,11 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { ...@@ -1367,12 +1367,11 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
// Get the receiver from the stack and probe the stub cache. // Get the receiver from the stack and probe the stub cache.
__ movq(rdx, Operand(rsp, kPointerSize));
Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
NOT_IN_LOOP, NOT_IN_LOOP,
MONOMORPHIC); MONOMORPHIC);
......
// Copyright 2009 the V8 project authors. All rights reserved. // Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -1354,25 +1354,22 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, ...@@ -1354,25 +1354,22 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Get the object from the stack.
__ movq(rbx, Operand(rsp, 1 * kPointerSize));
// Check that the object isn't a smi. // Check that the object isn't a smi.
__ JumpIfSmi(rbx, &miss); __ JumpIfSmi(rdx, &miss);
// Check that the map of the object hasn't changed. // Check that the map of the object hasn't changed.
__ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
Handle<Map>(object->map())); Handle<Map>(object->map()));
__ j(not_equal, &miss); __ j(not_equal, &miss);
// Perform global security token check if needed. // Perform global security token check if needed.
if (object->IsJSGlobalProxy()) { if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(rbx, rdx, &miss); __ CheckAccessGlobalProxy(rdx, rbx, &miss);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
...@@ -1380,7 +1377,7 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, ...@@ -1380,7 +1377,7 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ pop(rbx); // remove the return address __ pop(rbx); // remove the return address
__ push(Operand(rsp, 0)); // receiver __ push(rdx); // receiver
__ Push(Handle<AccessorInfo>(callback)); // callback info __ Push(Handle<AccessorInfo>(callback)); // callback info
__ push(rcx); // name __ push(rcx); // name
__ push(rax); // value __ push(rax); // value
...@@ -1408,21 +1405,18 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object, ...@@ -1408,21 +1405,18 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Get the object from the stack.
__ movq(rbx, Operand(rsp, 1 * kPointerSize));
// Generate store field code. Trashes the name register. // Generate store field code. Trashes the name register.
GenerateStoreField(masm(), GenerateStoreField(masm(),
Builtins::StoreIC_ExtendStorage, Builtins::StoreIC_ExtendStorage,
object, object,
index, index,
transition, transition,
rbx, rcx, rdx, rdx, rcx, rbx,
&miss); &miss);
// Handle store cache miss. // Handle store cache miss.
...@@ -1441,25 +1435,22 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, ...@@ -1441,25 +1435,22 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Get the object from the stack.
__ movq(rbx, Operand(rsp, 1 * kPointerSize));
// Check that the object isn't a smi. // Check that the object isn't a smi.
__ JumpIfSmi(rbx, &miss); __ JumpIfSmi(rdx, &miss);
// Check that the map of the object hasn't changed. // Check that the map of the object hasn't changed.
__ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
Handle<Map>(receiver->map())); Handle<Map>(receiver->map()));
__ j(not_equal, &miss); __ j(not_equal, &miss);
// Perform global security token check if needed. // Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) { if (receiver->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(rbx, rdx, &miss); __ CheckAccessGlobalProxy(rdx, rbx, &miss);
} }
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
...@@ -1467,7 +1458,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, ...@@ -1467,7 +1458,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
__ pop(rbx); // remove the return address __ pop(rbx); // remove the return address
__ push(Operand(rsp, 0)); // receiver __ push(rdx); // receiver
__ push(rcx); // name __ push(rcx); // name
__ push(rax); // value __ push(rax); // value
__ push(rbx); // restore return address __ push(rbx); // restore return address
...@@ -1493,14 +1484,13 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, ...@@ -1493,14 +1484,13 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Check that the map of the global has not changed. // Check that the map of the global has not changed.
__ movq(rbx, Operand(rsp, kPointerSize)); __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
__ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
Handle<Map>(object->map())); Handle<Map>(object->map()));
__ j(not_equal, &miss); __ j(not_equal, &miss);
......
// Copyright 2009 the V8 project authors. All rights reserved. // Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -1046,31 +1046,45 @@ Result VirtualFrame::CallConstructor(int arg_count) { ...@@ -1046,31 +1046,45 @@ Result VirtualFrame::CallConstructor(int arg_count) {
Result VirtualFrame::CallStoreIC() { Result VirtualFrame::CallStoreIC() {
// Name, value, and receiver are on top of the frame. The IC // Name, value, and receiver are on top of the frame. The IC
// expects name in rcx, value in rax, and receiver on the stack. It // expects name in rcx, value in rax, and receiver in edx.
// does not drop the receiver.
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
Result name = Pop(); Result name = Pop();
Result value = Pop(); Result value = Pop();
PrepareForCall(1, 0); // One stack arg, not callee-dropped. Result receiver = Pop();
PrepareForCall(0, 0);
if (value.is_register() && value.reg().is(rcx)) { // Optimized for case in which name is a constant value.
if (name.is_register() && name.reg().is(rax)) { if (name.is_register() && (name.reg().is(rdx) || name.reg().is(rax))) {
if (!is_used(rcx)) {
name.ToRegister(rcx);
} else if (!is_used(rbx)) {
name.ToRegister(rbx);
} else {
ASSERT(!is_used(rdi)); // Only three results are live, so rdi is free.
name.ToRegister(rdi);
}
}
// Now name is not in edx or eax, so we can fix them, then move name to ecx.
if (value.is_register() && value.reg().is(rdx)) {
if (receiver.is_register() && receiver.reg().is(rax)) {
// Wrong registers. // Wrong registers.
__ xchg(rax, rcx); __ xchg(rax, rdx);
} else { } else {
// Register rax is free for value, which frees rcx for name. // Register rax is free for value, which frees rcx for receiver.
value.ToRegister(rax); value.ToRegister(rax);
name.ToRegister(rcx); receiver.ToRegister(rdx);
} }
} else { } else {
// Register rcx is free for name, which guarantees rax is free for // Register rcx is free for receiver, which guarantees rax is free for
// value. // value.
name.ToRegister(rcx); receiver.ToRegister(rdx);
value.ToRegister(rax); value.ToRegister(rax);
} }
// Receiver and value are in the right place, so rcx is free for name.
name.ToRegister(rcx);
name.Unuse(); name.Unuse();
value.Unuse(); value.Unuse();
receiver.Unuse();
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
} }
......
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