MIPS: Change LookupForWrite to always do a full lookup and check the result.

Port r14061 (df49702a)

Original commit message:
If we find a property in the prototype-chain that we can overwrite, and
we have a transition, keep the holder in the lookup-result as the actual
holder. We will need it for the consistency-check in GenerateStoreField.

By directly checking the entire chain we avoid having to lazily bail out
to a copy of the miss stub while generating the Field Store IC.

Currently this CL disallows a normal non-receiver holder, given that
that would require a positive lookup + details verification to ensure
the property did not become read-only. This fixes the regressions in the
attached tests.

BUG=

Review URL: https://codereview.chromium.org/12924011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14070 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
palfia@homejinni.com 2013-03-25 17:12:50 +00:00
parent a79d622720
commit cb03ff32fd

View File

@ -415,7 +415,7 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
// may be clobbered. // may be clobbered.
void StubCompiler::GenerateStoreField(MacroAssembler* masm, void StubCompiler::GenerateStoreField(MacroAssembler* masm,
Handle<JSObject> object, Handle<JSObject> object,
int index, LookupResult* lookup,
Handle<Map> transition, Handle<Map> transition,
Handle<Name> name, Handle<Name> name,
Register receiver_reg, Register receiver_reg,
@ -428,16 +428,6 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// a0 : value. // a0 : value.
Label exit; Label exit;
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. // Check that the map of the object hasn't changed.
CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
: REQUIRE_EXACT_MAP; : REQUIRE_EXACT_MAP;
@ -452,8 +442,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Check that we are allowed to write this. // Check that we are allowed to write this.
if (!transition.is_null() && object->GetPrototype()->IsJSObject()) { if (!transition.is_null() && object->GetPrototype()->IsJSObject()) {
JSObject* holder; JSObject* holder;
if (lookup.IsFound()) { // holder == object indicates that no property was found.
holder = lookup.holder(); if (lookup->holder() != *object) {
holder = lookup->holder();
} else { } else {
// Find the top object. // Find the top object.
holder = *object; holder = *object;
@ -461,8 +452,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
holder = JSObject::cast(holder->GetPrototype()); holder = JSObject::cast(holder->GetPrototype());
} while (holder->GetPrototype()->IsJSObject()); } while (holder->GetPrototype()->IsJSObject());
} }
CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, Register holder_reg = CheckPrototypes(
scratch1, scratch2, name, miss_restore_name); 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 // Stub never generated for non-global objects that require access
@ -483,6 +485,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
return; return;
} }
int index;
if (!transition.is_null()) { if (!transition.is_null()) {
// Update the map of the object. // Update the map of the object.
__ li(scratch1, Operand(transition)); __ li(scratch1, Operand(transition));
@ -498,6 +501,10 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
kDontSaveFPRegs, kDontSaveFPRegs,
OMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK); 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 // Adjust for the number of properties stored in the object. Even in the