Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 4786) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -660,9 +660,25 @@ |
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 @@ |
__ IncrementCounter(&Counters::keyed_load_inline_miss, 1); |
if (!dst_.is(rax)) __ movq(dst_, rax); |
- __ pop(key_); |
- __ pop(receiver_); |
} |
@@ -5852,7 +5866,6 @@ |
frame_->Push(&arguments); |
frame_->Push(key_literal->handle()); |
*result = EmitKeyedLoad(); |
- frame_->Drop(2); // Drop key and receiver. |
done->Jump(result); |
} |
} |
@@ -7447,6 +7460,9 @@ |
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 @@ |
// 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 @@ |
__ 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 @@ |
// 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 @@ |
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 @@ |
} |
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(); |
+ } |
} |