MIPS: Change LookupForWrite to always do a full lookup and check the result.
authorpalfia@homejinni.com <palfia@homejinni.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 25 Mar 2013 17:12:50 +0000 (17:12 +0000)
committerpalfia@homejinni.com <palfia@homejinni.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 25 Mar 2013 17:12:50 +0000 (17:12 +0000)
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

src/mips/stub-cache-mips.cc

index cf9f9f6..841fb06 100644 (file)
@@ -415,7 +415,7 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
 // may be clobbered.
 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
                                       Handle<JSObject> object,
-                                      int index,
+                                      LookupResult* lookup,
                                       Handle<Map> transition,
                                       Handle<Name> name,
                                       Register receiver_reg,
@@ -428,16 +428,6 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
   // a0 : value.
   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.
   CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS
                                              : REQUIRE_EXACT_MAP;
@@ -452,8 +442,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;
@@ -461,8 +452,19 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
         holder = JSObject::cast(holder->GetPrototype());
       } while (holder->GetPrototype()->IsJSObject());
     }
-    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
@@ -483,6 +485,7 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
     return;
   }
 
+  int index;
   if (!transition.is_null()) {
     // Update the map of the object.
     __ li(scratch1, Operand(transition));
@@ -498,6 +501,10 @@ 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