Commit 838c0ab2 authored by verwaest@chromium.org's avatar verwaest@chromium.org

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
parent 3a476eb7
...@@ -411,18 +411,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, ...@@ -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. // Generate StoreTransition code, value is passed in r0 register.
// When leaving generated code after success, the receiver_reg and name_reg // When leaving generated code after success, the receiver_reg and name_reg
// may be clobbered. Upon branch to miss_label, the receiver and name // may be clobbered. Upon branch to miss_label, the receiver and name
...@@ -1127,20 +1115,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( ...@@ -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() { Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3, scratch4. // receiver, name, scratch1, scratch2, scratch3, scratch4.
Register receiver = LoadIC::ReceiverRegister(); Register receiver = LoadIC::ReceiverRegister();
......
...@@ -368,18 +368,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, ...@@ -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. // Generate StoreTransition code, value is passed in x0 register.
// When leaving generated code after success, the receiver_reg and storage_reg // 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 // may be clobbered. Upon branch to miss_label, the receiver and name registers
...@@ -1102,20 +1090,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( ...@@ -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 // TODO(all): The so-called scratch registers are significant in some cases. For
// example, PropertyAccessCompiler::keyed_store_calling_convention()[3] (x3) is // example, PropertyAccessCompiler::keyed_store_calling_convention()[3] (x3) is
// actually // actually
......
...@@ -410,18 +410,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, ...@@ -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 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
// store is successful. // store is successful.
void NamedStoreHandlerCompiler::GenerateStoreTransition( void NamedStoreHandlerCompiler::GenerateStoreTransition(
...@@ -1151,20 +1139,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( ...@@ -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() { Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3, scratch4. // receiver, name, scratch1, scratch2, scratch3, scratch4.
Register receiver = LoadIC::ReceiverRegister(); Register receiver = LoadIC::ReceiverRegister();
......
...@@ -1434,7 +1434,8 @@ Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup, ...@@ -1434,7 +1434,8 @@ Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup,
Handle<Map> transition(lookup->GetTransitionTarget()); Handle<Map> transition(lookup->GetTransitionTarget());
PropertyDetails details = lookup->GetPropertyDetails(); 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); return compiler.CompileStoreTransition(transition, name);
} }
} else { } else {
......
...@@ -280,19 +280,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell( ...@@ -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. // Generate StoreTransition code, value is passed in a0 register.
// After executing generated code, the receiver_reg and name_reg // After executing generated code, the receiver_reg and name_reg
// may be clobbered. // may be clobbered.
...@@ -1130,19 +1117,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( ...@@ -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() { Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3, scratch4. // receiver, name, scratch1, scratch2, scratch3, scratch4.
Register receiver = LoadIC::ReceiverRegister(); Register receiver = LoadIC::ReceiverRegister();
......
...@@ -281,19 +281,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell( ...@@ -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. // Generate StoreTransition code, value is passed in a0 register.
// After executing generated code, the receiver_reg and name_reg // After executing generated code, the receiver_reg and name_reg
// may be clobbered. // may be clobbered.
...@@ -1131,19 +1118,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( ...@@ -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() { Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3, scratch4. // receiver, name, scratch1, scratch2, scratch3, scratch4.
Register receiver = LoadIC::ReceiverRegister(); Register receiver = LoadIC::ReceiverRegister();
......
...@@ -803,9 +803,10 @@ Register PropertyHandlerCompiler::Frontend(Register object_reg, ...@@ -803,9 +803,10 @@ Register PropertyHandlerCompiler::Frontend(Register object_reg,
} }
void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) { void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name,
Label miss; Label* miss,
Register scratch1,
Register scratch2) {
Register holder_reg; Register holder_reg;
Handle<Map> last_map; Handle<Map> last_map;
if (holder().is_null()) { if (holder().is_null()) {
...@@ -815,11 +816,18 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) { ...@@ -815,11 +816,18 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) {
// Handle<JSObject>::null(). // Handle<JSObject>::null().
ASSERT(last_map->prototype() == isolate()->heap()->null_value()); ASSERT(last_map->prototype() == isolate()->heap()->null_value());
} else { } else {
holder_reg = FrontendHeader(receiver(), name, &miss); holder_reg = FrontendHeader(receiver(), name, miss);
last_map = handle(holder()->map()); last_map = handle(holder()->map());
} }
if (last_map->is_dictionary_map() && !last_map->IsJSGlobalObjectMap()) { 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()) { if (!name->IsUniqueName()) {
ASSERT(name->IsString()); ASSERT(name->IsString());
name = factory()->InternalizeString(Handle<String>::cast(name)); name = factory()->InternalizeString(Handle<String>::cast(name));
...@@ -827,21 +835,10 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) { ...@@ -827,21 +835,10 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) {
ASSERT(holder().is_null() || ASSERT(holder().is_null() ||
holder()->property_dictionary()->FindEntry(name) == holder()->property_dictionary()->FindEntry(name) ==
NameDictionary::kNotFound); NameDictionary::kNotFound);
GenerateDictionaryNegativeLookup(masm(), &miss, holder_reg, name, GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1,
scratch2(), scratch3()); scratch2);
} }
// 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( ...@@ -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<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
Handle<Name> name, Handle<ExecutableAccessorInfo> callback) { Handle<Name> name, Handle<ExecutableAccessorInfo> callback) {
Register reg = CallbackFrontend(receiver(), name, callback); Register reg = CallbackFrontend(receiver(), name, callback);
...@@ -970,21 +977,15 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( ...@@ -970,21 +977,15 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
iter.Advance(); iter.Advance();
} }
if (!last.is_null()) set_holder(last); if (!last.is_null()) set_holder(last);
} NonexistentFrontendHeader(name, &miss, scratch1(), scratch2());
} else {
Register holder_reg = FrontendHeader(receiver(), name, &miss); FrontendHeader(receiver(), name, &miss);
ASSERT(holder()->HasFastProperties());
// 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);
} }
GenerateStoreTransition(transition, name, receiver(), this->name(), value(), GenerateStoreTransition(transition, name, receiver(), this->name(), value(),
scratch1(), scratch2(), scratch3(), &miss, &slow); scratch1(), scratch2(), scratch3(), &miss, &slow);
// Handle store cache miss.
GenerateRestoreName(&miss, name); GenerateRestoreName(&miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind())); TailCallBuiltin(masm(), MissBuiltin(kind()));
......
...@@ -391,6 +391,8 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler { ...@@ -391,6 +391,8 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); } virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
Register Frontend(Register object_reg, Handle<Name> name); Register Frontend(Register object_reg, Handle<Name> name);
void NonexistentFrontendHeader(Handle<Name> name, Label* miss,
Register scratch1, Register scratch2);
// TODO(verwaest): Make non-static. // TODO(verwaest): Make non-static.
static void GenerateFastApiCall(MacroAssembler* masm, static void GenerateFastApiCall(MacroAssembler* masm,
...@@ -519,8 +521,6 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { ...@@ -519,8 +521,6 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
Register CallbackFrontend(Register object_reg, Handle<Name> name, Register CallbackFrontend(Register object_reg, Handle<Name> name,
Handle<Object> callback); Handle<Object> callback);
Handle<Code> CompileLoadNonexistent(Handle<Name> name); Handle<Code> CompileLoadNonexistent(Handle<Name> name);
void NonexistentFrontend(Handle<Name> name);
void GenerateLoadField(Register reg, void GenerateLoadField(Register reg,
FieldIndex field, FieldIndex field,
Representation representation); Representation representation);
...@@ -589,9 +589,6 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { ...@@ -589,9 +589,6 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
void GenerateRestoreName(Label* label, Handle<Name> name); void GenerateRestoreName(Label* label, Handle<Name> name);
private: private:
void GenerateNegativeHolderLookup(Register holder_reg, Handle<Name> name,
Label* miss);
void GenerateStoreTransition(Handle<Map> transition, Handle<Name> name, void GenerateStoreTransition(Handle<Map> transition, Handle<Name> name,
Register receiver_reg, Register name_reg, Register receiver_reg, Register name_reg,
Register value_reg, Register scratch1, Register value_reg, Register scratch1,
......
...@@ -367,18 +367,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, ...@@ -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 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
// store is successful. // store is successful.
void NamedStoreHandlerCompiler::GenerateStoreTransition( void NamedStoreHandlerCompiler::GenerateStoreTransition(
...@@ -1081,20 +1069,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( ...@@ -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() { Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3, scratch4. // receiver, name, scratch1, scratch2, scratch3, scratch4.
Register receiver = LoadIC::ReceiverRegister(); Register receiver = LoadIC::ReceiverRegister();
......
...@@ -401,19 +401,6 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell( ...@@ -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 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
// store is successful. // store is successful.
void NamedStoreHandlerCompiler::GenerateStoreTransition( void NamedStoreHandlerCompiler::GenerateStoreTransition(
...@@ -1168,20 +1155,6 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( ...@@ -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() { Register* PropertyAccessCompiler::load_calling_convention() {
// receiver, name, scratch1, scratch2, scratch3, scratch4. // receiver, name, scratch1, scratch2, scratch3, scratch4.
Register receiver = LoadIC::ReceiverRegister(); Register receiver = LoadIC::ReceiverRegister();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment