| Index: src/ia32/codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/codegen-ia32.cc (revision 3954)
|
| +++ src/ia32/codegen-ia32.cc (working copy)
|
| @@ -6694,8 +6694,12 @@
|
| public:
|
| DeferredReferenceSetKeyedValue(Register value,
|
| Register key,
|
| - Register receiver)
|
| - : value_(value), key_(key), receiver_(receiver) {
|
| + Register receiver,
|
| + Register scratch)
|
| + : value_(value),
|
| + key_(key),
|
| + receiver_(receiver),
|
| + scratch_(scratch) {
|
| set_comment("[ DeferredReferenceSetKeyedValue");
|
| }
|
|
|
| @@ -6707,17 +6711,65 @@
|
| Register value_;
|
| Register key_;
|
| Register receiver_;
|
| + Register scratch_;
|
| Label patch_site_;
|
| };
|
|
|
|
|
| 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(eax)) __ mov(eax, value_);
|
| + // Move value_ to eax, key_ to ecx, and receiver_ to edx.
|
| + Register old_value = value_;
|
| +
|
| + // First, move value to eax.
|
| + if (!value_.is(eax)) {
|
| + if (key_.is(eax)) {
|
| + // Move key_ out of eax, preferably to ecx.
|
| + if (!value_.is(ecx) && !receiver_.is(ecx)) {
|
| + __ mov(ecx, key_);
|
| + key_ = ecx;
|
| + } else {
|
| + __ mov(scratch_, key_);
|
| + key_ = scratch_;
|
| + }
|
| + }
|
| + if (receiver_.is(eax)) {
|
| + // Move receiver_ out of eax, preferably to edx.
|
| + if (!value_.is(edx) && !key_.is(edx)) {
|
| + __ mov(edx, receiver_);
|
| + receiver_ = edx;
|
| + } else {
|
| + // Both moves to scratch are from eax, also, no valid path hits both.
|
| + __ mov(scratch_, receiver_);
|
| + receiver_ = scratch_;
|
| + }
|
| + }
|
| + __ mov(eax, value_);
|
| + value_ = eax;
|
| + }
|
| +
|
| + // Now value_ is in eax. Move the other two to the right positions.
|
| + // We do not update the variables key_ and receiver_ to ecx and edx.
|
| + if (key_.is(ecx)) {
|
| + if (!receiver_.is(edx)) {
|
| + __ mov(edx, receiver_);
|
| + }
|
| + } else if (key_.is(edx)) {
|
| + if (receiver_.is(ecx)) {
|
| + __ xchg(edx, ecx);
|
| + } else {
|
| + __ mov(ecx, key_);
|
| + if (!receiver_.is(edx)) {
|
| + __ mov(edx, receiver_);
|
| + }
|
| + }
|
| + } else { // Key is not in edx or ecx.
|
| + if (!receiver_.is(edx)) {
|
| + __ mov(edx, receiver_);
|
| + }
|
| + __ mov(ecx, key_);
|
| + }
|
| +
|
| // Call the IC stub.
|
| Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
| __ call(ic, RelocInfo::CODE_TARGET);
|
| @@ -6730,11 +6782,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_->test(eax, Immediate(-delta_to_patch_site));
|
| - // Restore value (returned from store IC), key and receiver
|
| - // registers.
|
| - if (!value_.is(eax)) __ mov(value_, eax);
|
| - __ pop(key_);
|
| - __ pop(receiver_);
|
| + // Restore value (returned from store IC) register.
|
| + if (!old_value.is(eax)) __ mov(old_value, eax);
|
| }
|
|
|
|
|
| @@ -6933,7 +6982,8 @@
|
| DeferredReferenceSetKeyedValue* deferred =
|
| new DeferredReferenceSetKeyedValue(result.reg(),
|
| key.reg(),
|
| - receiver.reg());
|
| + receiver.reg(),
|
| + tmp.reg());
|
|
|
| // Check that the value is a smi if it is not a constant. We can skip
|
| // the write barrier for smis and constants.
|
| @@ -6993,7 +7043,6 @@
|
| // indicate that we have generated an inline version of the
|
| // keyed store.
|
| __ nop();
|
| - frame()->Drop(2);
|
| }
|
| ASSERT(frame()->height() == original_height - 3);
|
| return result;
|
| @@ -7135,6 +7184,7 @@
|
| Comment cmnt(masm, "[ Store to keyed Property");
|
| Property* property = expression()->AsProperty();
|
| ASSERT(property != NULL);
|
| +
|
| Result answer = cgen_->EmitKeyedStore(property->key()->type());
|
| cgen_->frame()->Push(&answer);
|
| set_unloaded();
|
|
|