| Index: src/ia32/codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/codegen-ia32.cc (revision 2140)
|
| +++ src/ia32/codegen-ia32.cc (working copy)
|
| @@ -5738,9 +5738,46 @@
|
| }
|
|
|
|
|
| +class DeferredReferenceSetKeyedValue: public DeferredCode {
|
| + public:
|
| + DeferredReferenceSetKeyedValue(Register value,
|
| + Register key,
|
| + Register receiver)
|
| + : value_(value), key_(key), receiver_(receiver) {
|
| + set_comment("[ DeferredReferenceSetKeyedValue");
|
| + }
|
| +
|
| + virtual void Generate();
|
| +
|
| + private:
|
| + Register value_;
|
| + Register key_;
|
| + Register receiver_;
|
| +};
|
| +
|
| +
|
| +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_);
|
| + // Call the IC stub.
|
| + Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
| + __ call(ic, RelocInfo::CODE_TARGET);
|
| + // Restore value (returned from store IC), key and receiver
|
| + // registers.
|
| + if (!value_.is(eax)) __ mov(value_, eax);
|
| + __ pop(key_);
|
| + __ pop(receiver_);
|
| +}
|
| +
|
| +
|
| #undef __
|
| #define __ ACCESS_MASM(masm)
|
|
|
| +
|
| Handle<String> Reference::GetName() {
|
| ASSERT(type_ == NAMED);
|
| Property* property = expression_->AsProperty();
|
| @@ -5859,7 +5896,7 @@
|
| // a check against an invalid map. In the inline cache code, we
|
| // patch the map check if appropriate.
|
| if (cgen_->loop_nesting() > 0) {
|
| - Comment cmnt(masm, "[ Inlined array index load");
|
| + Comment cmnt(masm, "[ Inlined load from keyed Property");
|
|
|
| Result key = cgen_->frame()->Pop();
|
| Result receiver = cgen_->frame()->Pop();
|
| @@ -6000,9 +6037,10 @@
|
| void Reference::SetValue(InitState init_state) {
|
| ASSERT(cgen_->HasValidEntryRegisters());
|
| ASSERT(!is_illegal());
|
| + MacroAssembler* masm = cgen_->masm();
|
| switch (type_) {
|
| case SLOT: {
|
| - Comment cmnt(cgen_->masm(), "[ Store to Slot");
|
| + Comment cmnt(masm, "[ Store to Slot");
|
| Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
|
| ASSERT(slot != NULL);
|
| cgen_->StoreToSlot(slot, init_state);
|
| @@ -6010,7 +6048,7 @@
|
| }
|
|
|
| case NAMED: {
|
| - Comment cmnt(cgen_->masm(), "[ Store to named Property");
|
| + Comment cmnt(masm, "[ Store to named Property");
|
| cgen_->frame()->Push(GetName());
|
| Result answer = cgen_->frame()->CallStoreIC();
|
| cgen_->frame()->Push(&answer);
|
| @@ -6018,9 +6056,93 @@
|
| }
|
|
|
| case KEYED: {
|
| - Comment cmnt(cgen_->masm(), "[ Store to keyed Property");
|
| - Result answer = cgen_->frame()->CallKeyedStoreIC();
|
| - cgen_->frame()->Push(&answer);
|
| + Comment cmnt(masm, "[ Store to keyed Property");
|
| +
|
| + // Generate inlined version of the keyed store if the code is in
|
| + // a loop and the key is likely to be a smi.
|
| + Property* property = expression()->AsProperty();
|
| + ASSERT(property != NULL);
|
| + SmiAnalysis* key_smi_analysis = property->key()->type();
|
| +
|
| + if (cgen_->loop_nesting() > 0 && key_smi_analysis->IsLikelySmi()) {
|
| + Comment cmnt(masm, "[ Inlined store to keyed Property");
|
| +
|
| + // Get the receiver, key and value into registers.
|
| + Result value = cgen_->frame()->Pop();
|
| + Result key = cgen_->frame()->Pop();
|
| + Result receiver = cgen_->frame()->Pop();
|
| +
|
| + Result tmp = cgen_->allocator_->Allocate();
|
| + ASSERT(tmp.is_valid());
|
| +
|
| + // Determine whether the value is a constant before putting it
|
| + // in a register.
|
| + bool value_is_constant = value.is_constant();
|
| +
|
| + // Make sure that value, key and receiver are in registers.
|
| + value.ToRegister();
|
| + key.ToRegister();
|
| + receiver.ToRegister();
|
| +
|
| + DeferredReferenceSetKeyedValue* deferred =
|
| + new DeferredReferenceSetKeyedValue(value.reg(),
|
| + key.reg(),
|
| + receiver.reg());
|
| +
|
| + // Check that the value is a smi if it is not a constant. We
|
| + // can skip the write barrier for smis and constants.
|
| + if (!value_is_constant) {
|
| + __ test(value.reg(), Immediate(kSmiTagMask));
|
| + deferred->Branch(not_zero);
|
| + }
|
| +
|
| + // Check that the key is a non-negative smi.
|
| + __ test(key.reg(), Immediate(kSmiTagMask | 0x80000000));
|
| + deferred->Branch(not_zero);
|
| +
|
| + // Check that the receiver is not a smi.
|
| + __ test(receiver.reg(), Immediate(kSmiTagMask));
|
| + deferred->Branch(zero);
|
| +
|
| + // Check that the receiver is a JSArray.
|
| + __ mov(tmp.reg(),
|
| + FieldOperand(receiver.reg(), HeapObject::kMapOffset));
|
| + __ movzx_b(tmp.reg(),
|
| + FieldOperand(tmp.reg(), Map::kInstanceTypeOffset));
|
| + __ cmp(tmp.reg(), JS_ARRAY_TYPE);
|
| + deferred->Branch(not_equal);
|
| +
|
| + // Check that the key is within bounds. Both the key and the
|
| + // length of the JSArray are smis.
|
| + __ cmp(key.reg(),
|
| + FieldOperand(receiver.reg(), JSArray::kLengthOffset));
|
| + deferred->Branch(greater_equal);
|
| +
|
| + // Get the elements array from the receiver and check that it
|
| + // is not a dictionary.
|
| + __ mov(tmp.reg(),
|
| + FieldOperand(receiver.reg(), JSObject::kElementsOffset));
|
| + __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
|
| + Immediate(Factory::hash_table_map()));
|
| + deferred->Branch(equal);
|
| +
|
| + // Store the value.
|
| + __ mov(Operand(tmp.reg(),
|
| + key.reg(),
|
| + times_2,
|
| + Array::kHeaderSize - kHeapObjectTag),
|
| + value.reg());
|
| + __ IncrementCounter(&Counters::keyed_store_inline, 1);
|
| +
|
| + deferred->BindExit();
|
| +
|
| + cgen_->frame()->Push(&receiver);
|
| + cgen_->frame()->Push(&key);
|
| + cgen_->frame()->Push(&value);
|
| + } else {
|
| + Result answer = cgen_->frame()->CallKeyedStoreIC();
|
| + cgen_->frame()->Push(&answer);
|
| + }
|
| break;
|
| }
|
|
|
|
|