| Index: src/x64/stub-cache-x64.cc | 
| diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc | 
| index 5721e9b373169180d64ce58f5734d5099d6274c6..57dcb08d84610a838243e7160257be5725c979e1 100644 | 
| --- a/src/x64/stub-cache-x64.cc | 
| +++ b/src/x64/stub-cache-x64.cc | 
| @@ -731,10 +731,22 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 
| Handle<JSObject> object, | 
| int index, | 
| Handle<Map> transition, | 
| +                                      Handle<String> name, | 
| Register receiver_reg, | 
| Register name_reg, | 
| -                                      Register scratch, | 
| +                                      Register scratch1, | 
| +                                      Register scratch2, | 
| Label* miss_label) { | 
| +  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; | 
| @@ -743,7 +755,32 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 
|  | 
| // Perform global security token check if needed. | 
| if (object->IsJSGlobalProxy()) { | 
| -    __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 
| +    __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); | 
| +  } | 
| + | 
| +  // Check that we are allowed to write this. | 
| +  if (!transition.is_null() && object->GetPrototype()->IsJSObject()) { | 
| +    JSObject* holder; | 
| +    if (lookup.IsFound()) { | 
| +      holder = lookup.holder(); | 
| +    } else { | 
| +      // Find the top object. | 
| +      holder = *object; | 
| +      do { | 
| +        holder = JSObject::cast(holder->GetPrototype()); | 
| +      } while (holder->GetPrototype()->IsJSObject()); | 
| +    } | 
| +    // We need an extra register, push | 
| +    __ push(name_reg); | 
| +    Label miss_pop, done_check; | 
| +    CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, | 
| +                    scratch1, scratch2, name, &miss_pop); | 
| +    __ jmp(&done_check); | 
| +    __ bind(&miss_pop); | 
| +    __ pop(name_reg); | 
| +    __ jmp(miss_label); | 
| +    __ bind(&done_check); | 
| +    __ pop(name_reg); | 
| } | 
|  | 
| // Stub never generated for non-global objects that require access | 
| @@ -754,11 +791,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 
| if (!transition.is_null() && (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(scratch);  // Return address. | 
| +    __ pop(scratch1);  // Return address. | 
| __ push(receiver_reg); | 
| __ Push(transition); | 
| __ push(rax); | 
| -    __ push(scratch); | 
| +    __ push(scratch1); | 
| __ TailCallExternalReference( | 
| ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 
| masm->isolate()), | 
| @@ -787,19 +824,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 
| // Pass the value being stored in the now unused name_reg. | 
| __ movq(name_reg, rax); | 
| __ RecordWriteField( | 
| -        receiver_reg, offset, name_reg, scratch, kDontSaveFPRegs); | 
| +        receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs); | 
| } else { | 
| // Write to the properties array. | 
| int offset = index * kPointerSize + FixedArray::kHeaderSize; | 
| // Get the properties array (optimistically). | 
| -    __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 
| -    __ movq(FieldOperand(scratch, offset), rax); | 
| +    __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 
| +    __ movq(FieldOperand(scratch1, offset), rax); | 
|  | 
| // Update the write barrier for the array address. | 
| // Pass the value being stored in the now unused name_reg. | 
| __ movq(name_reg, rax); | 
| __ RecordWriteField( | 
| -        scratch, offset, name_reg, receiver_reg, kDontSaveFPRegs); | 
| +        scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs); | 
| } | 
|  | 
| // Return the value (register rax). | 
| @@ -2296,7 +2333,13 @@ Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 
| Label miss; | 
|  | 
| // Generate store field code.  Preserves receiver and name on jump to miss. | 
| -  GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); | 
| +  GenerateStoreField(masm(), | 
| +                     object, | 
| +                     index, | 
| +                     transition, | 
| +                     name, | 
| +                     rdx, rcx, rbx, rdi, | 
| +                     &miss); | 
|  | 
| // Handle store cache miss. | 
| __ bind(&miss); | 
| @@ -2469,7 +2512,13 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 
| __ j(not_equal, &miss); | 
|  | 
| // Generate store field code.  Preserves receiver and name on jump to miss. | 
| -  GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); | 
| +  GenerateStoreField(masm(), | 
| +                     object, | 
| +                     index, | 
| +                     transition, | 
| +                     name, | 
| +                     rdx, rcx, rbx, rdi, | 
| +                     &miss); | 
|  | 
| // Handle store cache miss. | 
| __ bind(&miss); | 
|  |