From 838c0ab285558064b5a7403eb58fe2ad74e52a63 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Mon, 4 Aug 2014 10:47:10 +0000 Subject: [PATCH] Reuse the nonexistent handler frontend for transition handlers 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 | 26 --------------- src/arm64/stub-cache-arm64.cc | 26 --------------- src/ia32/stub-cache-ia32.cc | 26 --------------- src/ic.cc | 3 +- src/mips/stub-cache-mips.cc | 26 --------------- src/mips64/stub-cache-mips64.cc | 26 --------------- src/stub-cache.cc | 71 +++++++++++++++++++++-------------------- src/stub-cache.h | 7 ++-- src/x64/stub-cache-x64.cc | 26 --------------- src/x87/stub-cache-x87.cc | 27 ---------------- 10 files changed, 40 insertions(+), 224 deletions(-) diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index 2cb1a0e..df37012 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -411,18 +411,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, } -void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( - Register holder_reg, Handle name, Label* miss) { - if (holder()->IsJSGlobalObject()) { - GenerateCheckPropertyCell(masm(), Handle::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 NamedStoreHandlerCompiler::CompileStoreInterceptor( } -Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle 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(); diff --git a/src/arm64/stub-cache-arm64.cc b/src/arm64/stub-cache-arm64.cc index 9335211..a2dbf72 100644 --- a/src/arm64/stub-cache-arm64.cc +++ b/src/arm64/stub-cache-arm64.cc @@ -368,18 +368,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, } -void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( - Register holder_reg, Handle name, Label* miss) { - if (holder()->IsJSGlobalObject()) { - GenerateCheckPropertyCell(masm(), Handle::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 NamedStoreHandlerCompiler::CompileStoreInterceptor( } -Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle 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 diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 1c76300..b473f5d 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -410,18 +410,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, } -void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( - Register holder_reg, Handle name, Label* miss) { - if (holder()->IsJSGlobalObject()) { - GenerateCheckPropertyCell(masm(), Handle::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 PropertyICCompiler::CompileKeyedStorePolymorphic( } -Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle 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(); diff --git a/src/ic.cc b/src/ic.cc index 4fb55fc..22367b7 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -1434,7 +1434,8 @@ Handle StoreIC::CompileStoreHandler(LookupResult* lookup, Handle 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 { diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc index 96c7d4d..efd1b54 100644 --- a/src/mips/stub-cache-mips.cc +++ b/src/mips/stub-cache-mips.cc @@ -280,19 +280,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell( } -void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( - MacroAssembler* masm, Handle holder, Register holder_reg, - Handle name, Label* miss) { - if (holder->IsJSGlobalObject()) { - GenerateCheckPropertyCell( - masm, Handle::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 NamedStoreHandlerCompiler::CompileStoreInterceptor( } -Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle 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(); diff --git a/src/mips64/stub-cache-mips64.cc b/src/mips64/stub-cache-mips64.cc index ab89182..affb10f 100644 --- a/src/mips64/stub-cache-mips64.cc +++ b/src/mips64/stub-cache-mips64.cc @@ -281,19 +281,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell( } -void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( - MacroAssembler* masm, Handle holder, Register holder_reg, - Handle name, Label* miss) { - if (holder->IsJSGlobalObject()) { - GenerateCheckPropertyCell( - masm, Handle::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 NamedStoreHandlerCompiler::CompileStoreInterceptor( } -Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle 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(); diff --git a/src/stub-cache.cc b/src/stub-cache.cc index edb6025..cd9f603 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -803,9 +803,10 @@ Register PropertyHandlerCompiler::Frontend(Register object_reg, } -void NamedLoadHandlerCompiler::NonexistentFrontend(Handle name) { - Label miss; - +void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle name, + Label* miss, + Register scratch1, + Register scratch2) { Register holder_reg; Handle last_map; if (holder().is_null()) { @@ -815,33 +816,29 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle name) { // Handle::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::cast(name)); + if (last_map->is_dictionary_map()) { + if (last_map->IsJSGlobalObjectMap()) { + Handle global = + holder().is_null() + ? Handle::cast(type()->AsConstant()->Value()) + : Handle::cast(holder()); + GenerateCheckPropertyCell(masm(), global, name, scratch1, miss); + } else { + if (!name->IsUniqueName()) { + ASSERT(name->IsString()); + name = factory()->InternalizeString(Handle::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 global = - holder().is_null() - ? Handle::cast(type()->AsConstant()->Value()) - : Handle::cast(holder()); - GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); } - - FrontendFooter(name, &miss); } @@ -861,6 +858,16 @@ Handle NamedLoadHandlerCompiler::CompileLoadConstant( } +Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( + Handle name) { + Label miss; + NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); + GenerateLoadConstant(isolate()->factory()->undefined_value()); + FrontendFooter(name, &miss); + return GetCode(kind(), Code::FAST, name); +} + + Handle NamedLoadHandlerCompiler::CompileLoadCallback( Handle name, Handle callback) { Register reg = CallbackFrontend(receiver(), name, callback); @@ -970,21 +977,15 @@ Handle 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())); diff --git a/src/stub-cache.h b/src/stub-cache.h index ec0ca4a..ba8dacb 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -391,6 +391,8 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler { virtual void FrontendFooter(Handle name, Label* miss) { UNREACHABLE(); } Register Frontend(Register object_reg, Handle name); + void NonexistentFrontendHeader(Handle 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, Handle callback); Handle CompileLoadNonexistent(Handle name); - void NonexistentFrontend(Handle name); - void GenerateLoadField(Register reg, FieldIndex field, Representation representation); @@ -589,9 +589,6 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { void GenerateRestoreName(Label* label, Handle name); private: - void GenerateNegativeHolderLookup(Register holder_reg, Handle name, - Label* miss); - void GenerateStoreTransition(Handle transition, Handle name, Register receiver_reg, Register name_reg, Register value_reg, Register scratch1, diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index b0cc929..a73efdf 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -367,18 +367,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, } -void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( - Register holder_reg, Handle name, Label* miss) { - if (holder()->IsJSGlobalObject()) { - GenerateCheckPropertyCell(masm(), Handle::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 PropertyICCompiler::CompileKeyedStorePolymorphic( } -Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle 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(); diff --git a/src/x87/stub-cache-x87.cc b/src/x87/stub-cache-x87.cc index aade4fe..80d0696 100644 --- a/src/x87/stub-cache-x87.cc +++ b/src/x87/stub-cache-x87.cc @@ -401,19 +401,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell( } -void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( - MacroAssembler* masm, Handle holder, Register holder_reg, - Handle name, Label* miss) { - if (holder->IsJSGlobalObject()) { - GenerateCheckPropertyCell( - masm, Handle::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 PropertyICCompiler::CompileKeyedStorePolymorphic( } -Handle NamedLoadHandlerCompiler::CompileLoadNonexistent( - Handle 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(); -- 2.7.4