Index: src/ia32/stub-cache-ia32.cc |
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc |
index f7e795e788f7aab6ec397302f70121496c566d3b..1a439b16e7f4c7b636bad845f949d79f9485b699 100644 |
--- a/src/ia32/stub-cache-ia32.cc |
+++ b/src/ia32/stub-cache-ia32.cc |
@@ -730,7 +730,7 @@ void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
// but may be destroyed if store is successful. |
void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
Handle<JSObject> object, |
- int index, |
+ LookupResult* lookup, |
Handle<Map> transition, |
Handle<Name> name, |
Register receiver_reg, |
@@ -740,16 +740,6 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
Register scratch2, |
Label* miss_label, |
Label* miss_restore_name) { |
- LookupResult lookup(masm->isolate()); |
- object->Lookup(*name, &lookup); |
- if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { |
- // In sloppy mode, we could just return the value and be done. However, we |
- // might be in strict mode, where we have to throw. Since we cannot tell, |
- // go into slow case unconditionally. |
- __ jmp(miss_label); |
- return; |
- } |
- |
// Check that the map of the object hasn't changed. |
CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS |
: REQUIRE_EXACT_MAP; |
@@ -764,8 +754,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
// Check that we are allowed to write this. |
if (!transition.is_null() && object->GetPrototype()->IsJSObject()) { |
JSObject* holder; |
- if (lookup.IsFound()) { |
- holder = lookup.holder(); |
+ // holder == object indicates that no property was found. |
+ if (lookup->holder() != *object) { |
+ holder = lookup->holder(); |
} else { |
// Find the top object. |
holder = *object; |
@@ -774,8 +765,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
} while (holder->GetPrototype()->IsJSObject()); |
} |
// We need an extra register, push |
- CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, |
- scratch1, scratch2, name, miss_restore_name); |
+ Register holder_reg = CheckPrototypes( |
+ object, receiver_reg, Handle<JSObject>(holder), name_reg, |
+ scratch1, scratch2, name, miss_restore_name); |
+ // If no property was found, and the holder (the last object in the |
+ // prototype chain) is in slow mode, we need to do a negative lookup on the |
+ // holder. |
+ if (lookup->holder() == *object && |
+ !holder->HasFastProperties() && |
+ !holder->IsJSGlobalProxy() && |
+ !holder->IsJSGlobalObject()) { |
+ GenerateDictionaryNegativeLookup( |
+ masm, miss_restore_name, holder_reg, name, scratch1, scratch2); |
+ } |
} |
// Stub never generated for non-global objects that require access |
@@ -799,6 +801,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
return; |
} |
+ int index; |
if (!transition.is_null()) { |
// Update the map of the object. |
__ mov(scratch1, Immediate(transition)); |
@@ -813,8 +816,13 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
kDontSaveFPRegs, |
OMIT_REMEMBERED_SET, |
OMIT_SMI_CHECK); |
+ index = transition->instance_descriptors()->GetFieldIndex( |
+ transition->LastAdded()); |
+ } else { |
+ index = lookup->GetFieldIndex().field_index(); |
} |
+ |
// Adjust for the number of properties stored in the object. Even in the |
// face of a transition we can use the old map here because the size of the |
// object and the number of in-object properties is not going to change. |