| Index: src/ia32/stub-cache-ia32.cc
 | 
| diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
 | 
| index f70d5238f95f825f4c0cf9eaceaf6c3410386404..e563f681373ffe512f6c28440592af77e5a56a96 100644
 | 
| --- a/src/ia32/stub-cache-ia32.cc
 | 
| +++ b/src/ia32/stub-cache-ia32.cc
 | 
| @@ -751,23 +751,21 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm,
 | 
|  
 | 
|  // Both name_reg and receiver_reg are preserved on jumps to miss_label,
 | 
|  // but may be destroyed if store is successful.
 | 
| -void StubCompiler::GenerateStoreField(MacroAssembler* masm,
 | 
| -                                      Handle<JSObject> object,
 | 
| -                                      LookupResult* lookup,
 | 
| -                                      Handle<Map> transition,
 | 
| -                                      Handle<Name> name,
 | 
| -                                      Register receiver_reg,
 | 
| -                                      Register name_reg,
 | 
| -                                      Register value_reg,
 | 
| -                                      Register scratch1,
 | 
| -                                      Register scratch2,
 | 
| -                                      Label* miss_label,
 | 
| -                                      Label* miss_restore_name) {
 | 
| +void StubCompiler::GenerateStoreTransition(MacroAssembler* masm,
 | 
| +                                           Handle<JSObject> object,
 | 
| +                                           LookupResult* lookup,
 | 
| +                                           Handle<Map> transition,
 | 
| +                                           Handle<Name> name,
 | 
| +                                           Register receiver_reg,
 | 
| +                                           Register name_reg,
 | 
| +                                           Register value_reg,
 | 
| +                                           Register scratch1,
 | 
| +                                           Register scratch2,
 | 
| +                                           Label* miss_label,
 | 
| +                                           Label* miss_restore_name) {
 | 
|    // Check that the map of the object hasn't changed.
 | 
| -  CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
 | 
| -                                             : REQUIRE_EXACT_MAP;
 | 
|    __ CheckMap(receiver_reg, Handle<Map>(object->map()),
 | 
| -              miss_label, DO_SMI_CHECK, mode);
 | 
| +              miss_label, DO_SMI_CHECK, REQUIRE_EXACT_MAP);
 | 
|  
 | 
|    // Perform global security token check if needed.
 | 
|    if (object->IsJSGlobalProxy()) {
 | 
| @@ -775,7 +773,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
 | 
|    }
 | 
|  
 | 
|    // Check that we are allowed to write this.
 | 
| -  if (!transition.is_null() && object->GetPrototype()->IsJSObject()) {
 | 
| +  if (object->GetPrototype()->IsJSObject()) {
 | 
|      JSObject* holder;
 | 
|      // holder == object indicates that no property was found.
 | 
|      if (lookup->holder() != *object) {
 | 
| @@ -814,7 +812,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
 | 
|    ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 | 
|  
 | 
|    // Perform map transition for the receiver if necessary.
 | 
| -  if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) {
 | 
| +  if (object->map()->unused_property_fields() == 0) {
 | 
|      // The properties must be extended before we can store the value.
 | 
|      // We jump to a runtime call that extends the properties array.
 | 
|      __ pop(scratch1);  // Return address.
 | 
| @@ -830,33 +828,96 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| -  int index;
 | 
| -  if (!transition.is_null()) {
 | 
| -    // Update the map of the object.
 | 
| -    __ mov(scratch1, Immediate(transition));
 | 
| -    __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1);
 | 
| +  // Update the map of the object.
 | 
| +  __ mov(scratch1, Immediate(transition));
 | 
| +  __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1);
 | 
|  
 | 
| -    // Update the write barrier for the map field and pass the now unused
 | 
| -    // name_reg as scratch register.
 | 
| +  // Update the write barrier for the map field and pass the now unused
 | 
| +  // name_reg as scratch register.
 | 
| +  __ RecordWriteField(receiver_reg,
 | 
| +                      HeapObject::kMapOffset,
 | 
| +                      scratch1,
 | 
| +                      name_reg,
 | 
| +                      kDontSaveFPRegs,
 | 
| +                      OMIT_REMEMBERED_SET,
 | 
| +                      OMIT_SMI_CHECK);
 | 
| +  int index = transition->instance_descriptors()->GetFieldIndex(
 | 
| +      transition->LastAdded());
 | 
| +
 | 
| +  // 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.
 | 
| +  index -= object->map()->inobject_properties();
 | 
| +
 | 
| +  // TODO(verwaest): Share this code as a code stub.
 | 
| +  if (index < 0) {
 | 
| +    // Set the property straight into the object.
 | 
| +    int offset = object->map()->instance_size() + (index * kPointerSize);
 | 
| +    __ mov(FieldOperand(receiver_reg, offset), value_reg);
 | 
| +
 | 
| +    // Update the write barrier for the array address.
 | 
| +    // Pass the value being stored in the now unused name_reg.
 | 
| +    __ mov(name_reg, value_reg);
 | 
|      __ RecordWriteField(receiver_reg,
 | 
| -                        HeapObject::kMapOffset,
 | 
| -                        scratch1,
 | 
| +                        offset,
 | 
|                          name_reg,
 | 
| -                        kDontSaveFPRegs,
 | 
| -                        OMIT_REMEMBERED_SET,
 | 
| -                        OMIT_SMI_CHECK);
 | 
| -    index = transition->instance_descriptors()->GetFieldIndex(
 | 
| -        transition->LastAdded());
 | 
| +                        scratch1,
 | 
| +                        kDontSaveFPRegs);
 | 
|    } else {
 | 
| -    index = lookup->GetFieldIndex().field_index();
 | 
| +    // Write to the properties array.
 | 
| +    int offset = index * kPointerSize + FixedArray::kHeaderSize;
 | 
| +    // Get the properties array (optimistically).
 | 
| +    __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
 | 
| +    __ mov(FieldOperand(scratch1, offset), eax);
 | 
| +
 | 
| +    // Update the write barrier for the array address.
 | 
| +    // Pass the value being stored in the now unused name_reg.
 | 
| +    __ mov(name_reg, value_reg);
 | 
| +    __ RecordWriteField(scratch1,
 | 
| +                        offset,
 | 
| +                        name_reg,
 | 
| +                        receiver_reg,
 | 
| +                        kDontSaveFPRegs);
 | 
| +  }
 | 
| +
 | 
| +  // Return the value (register eax).
 | 
| +  ASSERT(value_reg.is(eax));
 | 
| +  __ ret(0);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +// Both name_reg and receiver_reg are preserved on jumps to miss_label,
 | 
| +// but may be destroyed if store is successful.
 | 
| +void StubCompiler::GenerateStoreField(MacroAssembler* masm,
 | 
| +                                      Handle<JSObject> object,
 | 
| +                                      LookupResult* lookup,
 | 
| +                                      Register receiver_reg,
 | 
| +                                      Register name_reg,
 | 
| +                                      Register value_reg,
 | 
| +                                      Register scratch1,
 | 
| +                                      Register scratch2,
 | 
| +                                      Label* miss_label) {
 | 
| +  // Check that the map of the object hasn't changed.
 | 
| +  __ CheckMap(receiver_reg, Handle<Map>(object->map()),
 | 
| +              miss_label, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
 | 
| +
 | 
| +  // Perform global security token check if needed.
 | 
| +  if (object->IsJSGlobalProxy()) {
 | 
| +    __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label);
 | 
|    }
 | 
|  
 | 
| +  // Stub never generated for non-global objects that require access
 | 
| +  // checks.
 | 
| +  ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 | 
| +
 | 
| +  int 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.
 | 
|    index -= object->map()->inobject_properties();
 | 
|  
 | 
| +  // TODO(verwaest): Share this code as a code stub.
 | 
|    if (index < 0) {
 | 
|      // Set the property straight into the object.
 | 
|      int offset = object->map()->instance_size() + (index * kPointerSize);
 | 
| 
 |