Reuse the nonexistent handler frontend for transition handlers
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 4 Aug 2014 10:47:10 +0000 (10:47 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 4 Aug 2014 10:47:10 +0000 (10:47 +0000)
BUG=
R=ishell@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22808 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/stub-cache-arm.cc
src/arm64/stub-cache-arm64.cc
src/ia32/stub-cache-ia32.cc
src/ic.cc
src/mips/stub-cache-mips.cc
src/mips64/stub-cache-mips64.cc
src/stub-cache.cc
src/stub-cache.h
src/x64/stub-cache-x64.cc
src/x87/stub-cache-x87.cc

index 2cb1a0e..df37012 100644 (file)
@@ -411,18 +411,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
 }
 
 
-void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
-    Register holder_reg, Handle<Name> name, Label* miss) {
-  if (holder()->IsJSGlobalObject()) {
-    GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(holder()),
-                              name, scratch1(), miss);
-  } else if (!holder()->HasFastProperties()) {
-    GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1(),
-                                     scratch2());
-  }
-}
-
-
 // Generate StoreTransition code, value is passed in r0 register.
 // When leaving generated code after success, the receiver_reg and name_reg
 // may be clobbered.  Upon branch to miss_label, the receiver and name
@@ -1127,20 +1115,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
 }
 
 
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
-    Handle<Name> name) {
-  NonexistentFrontend(name);
-
-  // Return undefined if maps of the full prototype chain are still the
-  // same and no global property with this name contains a value.
-  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
-  __ Ret();
-
-  // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
-}
-
-
 Register* PropertyAccessCompiler::load_calling_convention() {
   // receiver, name, scratch1, scratch2, scratch3, scratch4.
   Register receiver = LoadIC::ReceiverRegister();
index 9335211..a2dbf72 100644 (file)
@@ -368,18 +368,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
 }
 
 
-void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
-    Register holder_reg, Handle<Name> name, Label* miss) {
-  if (holder()->IsJSGlobalObject()) {
-    GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(holder()),
-                              name, scratch1(), miss);
-  } else if (!holder()->HasFastProperties()) {
-    GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1(),
-                                     scratch2());
-  }
-}
-
-
 // Generate StoreTransition code, value is passed in x0 register.
 // When leaving generated code after success, the receiver_reg and storage_reg
 // may be clobbered. Upon branch to miss_label, the receiver and name registers
@@ -1102,20 +1090,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
 }
 
 
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
-    Handle<Name> name) {
-  NonexistentFrontend(name);
-
-  // Return undefined if maps of the full prototype chain are still the
-  // same and no global property with this name contains a value.
-  __ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
-  __ Ret();
-
-  // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
-}
-
-
 // TODO(all): The so-called scratch registers are significant in some cases. For
 // example, PropertyAccessCompiler::keyed_store_calling_convention()[3] (x3) is
 // actually
index 1c76300..b473f5d 100644 (file)
@@ -410,18 +410,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
 }
 
 
-void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
-    Register holder_reg, Handle<Name> name, Label* miss) {
-  if (holder()->IsJSGlobalObject()) {
-    GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(holder()),
-                              name, scratch1(), miss);
-  } else if (!holder()->HasFastProperties()) {
-    GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1(),
-                                     scratch2());
-  }
-}
-
-
 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
 // store is successful.
 void NamedStoreHandlerCompiler::GenerateStoreTransition(
@@ -1151,20 +1139,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
 }
 
 
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
-    Handle<Name> name) {
-  NonexistentFrontend(name);
-
-  // Return undefined if maps of the full prototype chain are still the
-  // same and no global property with this name contains a value.
-  __ mov(eax, isolate()->factory()->undefined_value());
-  __ ret(0);
-
-  // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
-}
-
-
 Register* PropertyAccessCompiler::load_calling_convention() {
   // receiver, name, scratch1, scratch2, scratch3, scratch4.
   Register receiver = LoadIC::ReceiverRegister();
index 4fb55fc..22367b7 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1434,7 +1434,8 @@ Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup,
     Handle<Map> transition(lookup->GetTransitionTarget());
     PropertyDetails details = lookup->GetPropertyDetails();
 
-    if (details.type() != CALLBACKS && details.attributes() == NONE) {
+    if (details.type() != CALLBACKS && details.attributes() == NONE &&
+        holder->HasFastProperties()) {
       return compiler.CompileStoreTransition(transition, name);
     }
   } else {
index 96c7d4d..efd1b54 100644 (file)
@@ -280,19 +280,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
 }
 
 
-void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
-    MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg,
-    Handle<Name> name, Label* miss) {
-  if (holder->IsJSGlobalObject()) {
-    GenerateCheckPropertyCell(
-        masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss);
-  } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
-    GenerateDictionaryNegativeLookup(
-        masm, miss, holder_reg, name, scratch1(), scratch2());
-  }
-}
-
-
 // Generate StoreTransition code, value is passed in a0 register.
 // After executing generated code, the receiver_reg and name_reg
 // may be clobbered.
@@ -1130,19 +1117,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
 }
 
 
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
-    Handle<Name> name) {
-  NonexistentFrontend(name);
-
-  // Return undefined if maps of the full prototype chain is still the same.
-  __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
-  __ Ret();
-
-  // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
-}
-
-
 Register* PropertyAccessCompiler::load_calling_convention() {
   // receiver, name, scratch1, scratch2, scratch3, scratch4.
   Register receiver = LoadIC::ReceiverRegister();
index ab89182..affb10f 100644 (file)
@@ -281,19 +281,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
 }
 
 
-void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
-    MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg,
-    Handle<Name> name, Label* miss) {
-  if (holder->IsJSGlobalObject()) {
-    GenerateCheckPropertyCell(
-        masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss);
-  } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
-    GenerateDictionaryNegativeLookup(
-        masm, miss, holder_reg, name, scratch1(), scratch2());
-  }
-}
-
-
 // Generate StoreTransition code, value is passed in a0 register.
 // After executing generated code, the receiver_reg and name_reg
 // may be clobbered.
@@ -1131,19 +1118,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
 }
 
 
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
-    Handle<Name> name) {
-  NonexistentFrontend(name);
-
-  // Return undefined if maps of the full prototype chain is still the same.
-  __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
-  __ Ret();
-
-  // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
-}
-
-
 Register* PropertyAccessCompiler::load_calling_convention() {
   // receiver, name, scratch1, scratch2, scratch3, scratch4.
   Register receiver = LoadIC::ReceiverRegister();
index edb6025..cd9f603 100644 (file)
@@ -803,9 +803,10 @@ Register PropertyHandlerCompiler::Frontend(Register object_reg,
 }
 
 
-void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) {
-  Label miss;
-
+void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name,
+                                                        Label* miss,
+                                                        Register scratch1,
+                                                        Register scratch2) {
   Register holder_reg;
   Handle<Map> last_map;
   if (holder().is_null()) {
@@ -815,33 +816,29 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) {
     // Handle<JSObject>::null().
     ASSERT(last_map->prototype() == isolate()->heap()->null_value());
   } else {
-    holder_reg = FrontendHeader(receiver(), name, &miss);
+    holder_reg = FrontendHeader(receiver(), name, miss);
     last_map = handle(holder()->map());
   }
 
-  if (last_map->is_dictionary_map() && !last_map->IsJSGlobalObjectMap()) {
-    if (!name->IsUniqueName()) {
-      ASSERT(name->IsString());
-      name = factory()->InternalizeString(Handle<String>::cast(name));
+  if (last_map->is_dictionary_map()) {
+    if (last_map->IsJSGlobalObjectMap()) {
+      Handle<JSGlobalObject> global =
+          holder().is_null()
+              ? Handle<JSGlobalObject>::cast(type()->AsConstant()->Value())
+              : Handle<JSGlobalObject>::cast(holder());
+      GenerateCheckPropertyCell(masm(), global, name, scratch1, miss);
+    } else {
+      if (!name->IsUniqueName()) {
+        ASSERT(name->IsString());
+        name = factory()->InternalizeString(Handle<String>::cast(name));
+      }
+      ASSERT(holder().is_null() ||
+             holder()->property_dictionary()->FindEntry(name) ==
+                 NameDictionary::kNotFound);
+      GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1,
+                                       scratch2);
     }
-    ASSERT(holder().is_null() ||
-           holder()->property_dictionary()->FindEntry(name) ==
-               NameDictionary::kNotFound);
-    GenerateDictionaryNegativeLookup(masm(), &miss, holder_reg, name,
-                                     scratch2(), scratch3());
-  }
-
-  // If the last object in the prototype chain is a global object,
-  // check that the global property cell is empty.
-  if (last_map->IsJSGlobalObjectMap()) {
-    Handle<JSGlobalObject> global =
-        holder().is_null()
-            ? Handle<JSGlobalObject>::cast(type()->AsConstant()->Value())
-            : Handle<JSGlobalObject>::cast(holder());
-    GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
   }
-
-  FrontendFooter(name, &miss);
 }
 
 
@@ -861,6 +858,16 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(
 }
 
 
+Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
+    Handle<Name> name) {
+  Label miss;
+  NonexistentFrontendHeader(name, &miss, scratch2(), scratch3());
+  GenerateLoadConstant(isolate()->factory()->undefined_value());
+  FrontendFooter(name, &miss);
+  return GetCode(kind(), Code::FAST, name);
+}
+
+
 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
     Handle<Name> name, Handle<ExecutableAccessorInfo> callback) {
   Register reg = CallbackFrontend(receiver(), name, callback);
@@ -970,21 +977,15 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
       iter.Advance();
     }
     if (!last.is_null()) set_holder(last);
-  }
-
-  Register holder_reg = FrontendHeader(receiver(), name, &miss);
-
-  // 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 (is_nonexistent) {
-    GenerateNegativeHolderLookup(holder_reg, name, &miss);
+    NonexistentFrontendHeader(name, &miss, scratch1(), scratch2());
+  } else {
+    FrontendHeader(receiver(), name, &miss);
+    ASSERT(holder()->HasFastProperties());
   }
 
   GenerateStoreTransition(transition, name, receiver(), this->name(), value(),
                           scratch1(), scratch2(), scratch3(), &miss, &slow);
 
-  // Handle store cache miss.
   GenerateRestoreName(&miss, name);
   TailCallBuiltin(masm(), MissBuiltin(kind()));
 
index ec0ca4a..ba8dacb 100644 (file)
@@ -391,6 +391,8 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
   virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
 
   Register Frontend(Register object_reg, Handle<Name> name);
+  void NonexistentFrontendHeader(Handle<Name> name, Label* miss,
+                                 Register scratch1, Register scratch2);
 
   // TODO(verwaest): Make non-static.
   static void GenerateFastApiCall(MacroAssembler* masm,
@@ -519,8 +521,6 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
   Register CallbackFrontend(Register object_reg, Handle<Name> name,
                             Handle<Object> callback);
   Handle<Code> CompileLoadNonexistent(Handle<Name> name);
-  void NonexistentFrontend(Handle<Name> name);
-
   void GenerateLoadField(Register reg,
                          FieldIndex field,
                          Representation representation);
@@ -589,9 +589,6 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
   void GenerateRestoreName(Label* label, Handle<Name> name);
 
  private:
-  void GenerateNegativeHolderLookup(Register holder_reg, Handle<Name> name,
-                                    Label* miss);
-
   void GenerateStoreTransition(Handle<Map> transition, Handle<Name> name,
                                Register receiver_reg, Register name_reg,
                                Register value_reg, Register scratch1,
index b0cc929..a73efdf 100644 (file)
@@ -367,18 +367,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
 }
 
 
-void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
-    Register holder_reg, Handle<Name> name, Label* miss) {
-  if (holder()->IsJSGlobalObject()) {
-    GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(holder()),
-                              name, scratch1(), miss);
-  } else if (!holder()->HasFastProperties()) {
-    GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1(),
-                                     scratch2());
-  }
-}
-
-
 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
 // store is successful.
 void NamedStoreHandlerCompiler::GenerateStoreTransition(
@@ -1081,20 +1069,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
 }
 
 
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
-    Handle<Name> name) {
-  NonexistentFrontend(name);
-
-  // Return undefined if maps of the full prototype chain are still the
-  // same and no global property with this name contains a value.
-  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
-  __ ret(0);
-
-  // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
-}
-
-
 Register* PropertyAccessCompiler::load_calling_convention() {
   // receiver, name, scratch1, scratch2, scratch3, scratch4.
   Register receiver = LoadIC::ReceiverRegister();
index aade4fe..80d0696 100644 (file)
@@ -401,19 +401,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
 }
 
 
-void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup(
-    MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg,
-    Handle<Name> name, Label* miss) {
-  if (holder->IsJSGlobalObject()) {
-    GenerateCheckPropertyCell(
-        masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss);
-  } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
-    GenerateDictionaryNegativeLookup(
-        masm, miss, holder_reg, name, scratch1(), scratch2());
-  }
-}
-
-
 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
 // store is successful.
 void NamedStoreHandlerCompiler::GenerateStoreTransition(
@@ -1168,20 +1155,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
 }
 
 
-Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
-    Handle<Name> name) {
-  NonexistentFrontend(name);
-
-  // Return undefined if maps of the full prototype chain are still the
-  // same and no global property with this name contains a value.
-  __ mov(eax, isolate()->factory()->undefined_value());
-  __ ret(0);
-
-  // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
-}
-
-
 Register* PropertyAccessCompiler::load_calling_convention() {
   // receiver, name, scratch1, scratch2, scratch3, scratch4.
   Register receiver = LoadIC::ReceiverRegister();