Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 4691) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -680,11 +680,51 @@ |
void DeferredReferenceSetKeyedValue::Generate() { |
__ IncrementCounter(&Counters::keyed_store_inline_miss, 1); |
- // Push receiver and key arguments on the stack. |
- __ push(receiver_); |
- __ push(key_); |
- // Move value argument to eax as expected by the IC stub. |
- if (!value_.is(rax)) __ movq(rax, value_); |
+ // Move value, receiver, and key to registers rax, rdx, and rcx, as |
+ // the IC stub expects. |
+ // Move value to rax, using xchg if the receiver or key is in rax. |
+ if (!value_.is(rax)) { |
+ if (!receiver_.is(rax) && !key_.is(rax)) { |
+ __ movq(rax, value_); |
+ } else { |
+ __ xchg(rax, value_); |
+ // Update receiver_ and key_ if they are affected by the swap. |
+ if (receiver_.is(rax)) { |
+ receiver_ = value_; |
+ } else if (receiver_.is(value_)) { |
+ receiver_ = rax; |
+ } |
+ if (key_.is(rax)) { |
+ key_ = value_; |
+ } else if (key_.is(value_)) { |
+ key_ = rax; |
+ } |
+ } |
+ } |
+ // Value is now in rax. Its original location is remembered in value_, |
+ // and the value is restored to value_ before returning. |
+ // The variables receiver_ and key_ are not preserved. |
+ // Move receiver and key to rdx and rcx, swapping if necessary. |
+ if (receiver_.is(rdx)) { |
+ if (!key_.is(rcx)) { |
+ __ movq(rcx, key_); |
+ } // Else everything is already in the right place. |
+ } else if (receiver_.is(rcx)) { |
+ if (key_.is(rdx)) { |
+ __ xchg(rcx, rdx); |
+ } else if (key_.is(rcx)) { |
+ __ movq(rdx, receiver_); |
+ } else { |
+ __ movq(rdx, receiver_); |
+ __ movq(rcx, key_); |
+ } |
+ } else if (key_.is(rcx)) { |
+ __ movq(rdx, receiver_); |
+ } else { |
+ __ movq(rcx, key_); |
+ __ movq(rdx, receiver_); |
+ } |
+ |
// Call the IC stub. |
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
__ Call(ic, RelocInfo::CODE_TARGET); |
@@ -697,11 +737,8 @@ |
// Here we use masm_-> instead of the __ macro because this is the |
// instruction that gets patched and coverage code gets in the way. |
masm_->testl(rax, Immediate(-delta_to_patch_site)); |
- // Restore value (returned from store IC), key and receiver |
- // registers. |
+ // Restore value (returned from store IC). |
if (!value_.is(rax)) __ movq(value_, rax); |
- __ pop(key_); |
- __ pop(receiver_); |
} |
@@ -7533,8 +7570,6 @@ |
deferred->BindExit(); |
- cgen_->frame()->Push(&receiver); |
- cgen_->frame()->Push(&key); |
cgen_->frame()->Push(&value); |
} else { |
Result answer = cgen_->frame()->CallKeyedStoreIC(); |
@@ -7545,7 +7580,7 @@ |
masm->nop(); |
cgen_->frame()->Push(&answer); |
} |
- cgen_->UnloadReference(this); |
+ set_unloaded(); |
break; |
} |