Index: src/stub-cache.cc |
diff --git a/src/stub-cache.cc b/src/stub-cache.cc |
index 3173f4ddf1f24f543448980b873c159bebf4749c..839b0b0e8dc5a22c9473695dd02af6b90ece0f7d 100644 |
--- a/src/stub-cache.cc |
+++ b/src/stub-cache.cc |
@@ -203,8 +203,8 @@ Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent( |
cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); |
if (!handler.is_null()) return handler; |
- NamedLoadHandlerCompiler compiler(isolate, type, flag); |
- handler = compiler.CompileLoadNonexistent(last, cache_name); |
+ NamedLoadHandlerCompiler compiler(isolate, type, last, flag); |
+ handler = compiler.CompileLoadNonexistent(cache_name); |
Map::UpdateCodeCache(stub_holder_map, cache_name, handler); |
return handler; |
} |
@@ -749,7 +749,6 @@ Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, |
Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, |
- Handle<JSObject> holder, |
Handle<Name> name, |
Label* miss) { |
PrototypeCheckType check_type = CHECK_ALL_MAPS; |
@@ -776,19 +775,18 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, |
} |
// Check that the maps starting from the prototype haven't changed. |
- return CheckPrototypes(object_reg, holder, scratch1(), scratch2(), scratch3(), |
- name, miss, check_type); |
+ return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, |
+ miss, check_type); |
} |
// Frontend for store uses the name register. It has to be restored before a |
// miss. |
Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, |
- Handle<JSObject> holder, |
Handle<Name> name, |
Label* miss) { |
- return CheckPrototypes(object_reg, holder, this->name(), scratch1(), |
- scratch2(), name, miss, SKIP_RECEIVER); |
+ return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, |
+ miss, SKIP_RECEIVER); |
} |
@@ -801,42 +799,39 @@ bool PropertyICCompiler::IncludesNumberType(TypeHandleList* types) { |
Register PropertyHandlerCompiler::Frontend(Register object_reg, |
- Handle<JSObject> holder, |
Handle<Name> name) { |
Label miss; |
- Register reg = FrontendHeader(object_reg, holder, name, &miss); |
+ Register reg = FrontendHeader(object_reg, name, &miss); |
FrontendFooter(name, &miss); |
return reg; |
} |
-void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<JSObject> last, |
- Handle<Name> name) { |
+void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<Name> name) { |
Label miss; |
- Register holder; |
+ Register holder_reg; |
Handle<Map> last_map; |
- if (last.is_null()) { |
- holder = receiver(); |
+ if (holder().is_null()) { |
+ holder_reg = receiver(); |
last_map = IC::TypeToMap(*type(), isolate()); |
- // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). |
+ // If |type| has null as its prototype, |holder()| is |
+ // Handle<JSObject>::null(). |
ASSERT(last_map->prototype() == isolate()->heap()->null_value()); |
} else { |
- holder = FrontendHeader(receiver(), last, name, &miss); |
- last_map = handle(last->map()); |
+ holder_reg = FrontendHeader(receiver(), name, &miss); |
+ last_map = handle(holder()->map()); |
} |
- if (last_map->is_dictionary_map() && |
- !last_map->IsJSGlobalObjectMap() && |
- !last_map->IsJSGlobalProxyMap()) { |
+ if (last_map->is_dictionary_map() && !last_map->IsJSGlobalObjectMap()) { |
if (!name->IsUniqueName()) { |
ASSERT(name->IsString()); |
name = factory()->InternalizeString(Handle<String>::cast(name)); |
} |
- ASSERT(last.is_null() || |
- last->property_dictionary()->FindEntry(name) == |
+ ASSERT(holder().is_null() || |
+ holder()->property_dictionary()->FindEntry(name) == |
NameDictionary::kNotFound); |
- GenerateDictionaryNegativeLookup(masm(), &miss, holder, name, |
+ GenerateDictionaryNegativeLookup(masm(), &miss, holder_reg, name, |
scratch2(), scratch3()); |
} |
@@ -844,9 +839,9 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<JSObject> last, |
// check that the global property cell is empty. |
if (last_map->IsJSGlobalObjectMap()) { |
Handle<JSGlobalObject> global = |
- last.is_null() |
+ holder().is_null() |
? Handle<JSGlobalObject>::cast(type()->AsConstant()->Value()) |
- : Handle<JSGlobalObject>::cast(last); |
+ : Handle<JSGlobalObject>::cast(holder()); |
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
} |
@@ -855,37 +850,34 @@ void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<JSObject> last, |
Handle<Code> NamedLoadHandlerCompiler::CompileLoadField( |
- Handle<JSObject> holder, Handle<Name> name, FieldIndex field, |
- Representation representation) { |
- Register reg = Frontend(receiver(), holder, name); |
- GenerateLoadField(reg, holder, field, representation); |
+ Handle<Name> name, FieldIndex field, Representation representation) { |
+ Register reg = Frontend(receiver(), name); |
+ GenerateLoadField(reg, field, representation); |
return GetCode(kind(), Code::FAST, name); |
} |
Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant( |
- Handle<JSObject> holder, Handle<Name> name, Handle<Object> value) { |
- Frontend(receiver(), holder, name); |
+ Handle<Name> name, Handle<Object> value) { |
+ Frontend(receiver(), name); |
GenerateLoadConstant(value); |
return GetCode(kind(), Code::FAST, name); |
} |
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
- Handle<JSObject> holder, Handle<Name> name, |
- Handle<ExecutableAccessorInfo> callback) { |
- Register reg = CallbackFrontend(receiver(), holder, name, callback); |
+ Handle<Name> name, Handle<ExecutableAccessorInfo> callback) { |
+ Register reg = CallbackFrontend(receiver(), name, callback); |
GenerateLoadCallback(reg, callback); |
return GetCode(kind(), Code::FAST, name); |
} |
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
- Handle<JSObject> holder, Handle<Name> name, |
- const CallOptimization& call_optimization) { |
+ Handle<Name> name, const CallOptimization& call_optimization) { |
ASSERT(call_optimization.is_simple_api_call()); |
Handle<JSFunction> callback = call_optimization.constant_function(); |
- CallbackFrontend(receiver(), holder, name, callback); |
+ CallbackFrontend(receiver(), name, callback); |
Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); |
GenerateFastApiCall( |
masm(), call_optimization, receiver_map, |
@@ -895,52 +887,48 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( |
- Handle<JSObject> holder, Handle<Name> name) { |
+ Handle<Name> name) { |
// Perform a lookup after the interceptor. |
LookupResult lookup(isolate()); |
- holder->LookupOwnRealNamedProperty(name, &lookup); |
+ holder()->LookupOwnRealNamedProperty(name, &lookup); |
if (!lookup.IsFound()) { |
- PrototypeIterator iter(holder->GetIsolate(), holder); |
+ PrototypeIterator iter(holder()->GetIsolate(), holder()); |
if (!iter.IsAtEnd()) { |
PrototypeIterator::GetCurrent(iter)->Lookup(name, &lookup); |
} |
} |
- Register reg = Frontend(receiver(), holder, name); |
+ Register reg = Frontend(receiver(), name); |
// TODO(368): Compile in the whole chain: all the interceptors in |
// prototypes and ultimate answer. |
- GenerateLoadInterceptor(reg, holder, &lookup, name); |
+ GenerateLoadInterceptor(reg, &lookup, name); |
return GetCode(kind(), Code::FAST, name); |
} |
void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( |
- Register interceptor_reg, Handle<JSObject> interceptor_holder, |
- Handle<Name> name, LookupResult* lookup) { |
- Handle<JSObject> holder(lookup->holder()); |
+ Register interceptor_reg, Handle<Name> name, LookupResult* lookup) { |
+ Handle<JSObject> real_named_property_holder(lookup->holder()); |
if (lookup->IsField()) { |
FieldIndex field = lookup->GetFieldIndex(); |
- if (interceptor_holder.is_identical_to(holder)) { |
- GenerateLoadField( |
- interceptor_reg, holder, field, lookup->representation()); |
+ if (holder().is_identical_to(real_named_property_holder)) { |
+ GenerateLoadField(interceptor_reg, field, lookup->representation()); |
} else { |
- // We found FIELD property in prototype chain of interceptor's holder. |
- // Retrieve a field from field's holder. |
- set_type_for_object(interceptor_holder); |
- Register reg = Frontend(interceptor_reg, holder, name); |
- GenerateLoadField( |
- reg, holder, field, lookup->representation()); |
+ set_type_for_object(holder()); |
+ set_holder(real_named_property_holder); |
+ Register reg = Frontend(interceptor_reg, name); |
+ GenerateLoadField(reg, field, lookup->representation()); |
} |
} else { |
- // We found CALLBACKS property in prototype chain of interceptor's |
- // holder. |
+ // We found CALLBACKS property in prototype chain of interceptor's holder. |
ASSERT(lookup->type() == CALLBACKS); |
Handle<ExecutableAccessorInfo> callback( |
ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
ASSERT(callback->getter() != NULL); |
- set_type_for_object(interceptor_holder); |
- Register reg = CallbackFrontend(interceptor_reg, holder, name, callback); |
+ set_type_for_object(holder()); |
+ set_holder(real_named_property_holder); |
+ Register reg = CallbackFrontend(interceptor_reg, name, callback); |
GenerateLoadCallback(reg, callback); |
} |
} |
@@ -960,48 +948,44 @@ Handle<Code> PropertyICCompiler::CompileMonomorphic(Handle<HeapType> type, |
Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( |
- Handle<JSObject> holder, Handle<Name> name, Handle<JSFunction> getter) { |
- Frontend(receiver(), holder, name); |
+ Handle<Name> name, Handle<JSFunction> getter) { |
+ Frontend(receiver(), name); |
GenerateLoadViaGetter(masm(), type(), receiver(), getter); |
return GetCode(kind(), Code::FAST, name); |
} |
+// TODO(verwaest): Cleanup. holder() is actually the receiver. |
Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
- Handle<JSObject> object, LookupResult* lookup, Handle<Map> transition, |
- Handle<Name> name) { |
+ LookupResult* lookup, Handle<Map> transition, Handle<Name> name) { |
Label miss, slow; |
// Ensure no transitions to deprecated maps are followed. |
__ CheckMapDeprecated(transition, scratch1(), &miss); |
// Check that we are allowed to write this. |
- PrototypeIterator iter(object->GetIsolate(), object); |
- if (!iter.IsAtEnd()) { |
- Handle<JSObject> holder; |
- // holder == object indicates that no property was found. |
- if (lookup->holder() != *object) { |
- holder = Handle<JSObject>(lookup->holder()); |
- } else { |
- // Find the top object. |
- do { |
- holder = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
- iter.Advance(); |
- } while (!iter.IsAtEnd()); |
- } |
+ bool is_nonexistent = holder()->map() == transition->GetBackPointer(); |
+ if (is_nonexistent) { |
+ // Find the top object. |
+ Handle<JSObject> last; |
+ PrototypeIterator iter(isolate(), holder()); |
+ do { |
+ last = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
+ iter.Advance(); |
+ } while (!iter.IsAtEnd()); |
+ set_holder(last); |
+ } |
- Register holder_reg = FrontendHeader(receiver(), holder, name, &miss); |
+ 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 (lookup->holder() == *object) { |
- GenerateNegativeHolderLookup(masm(), holder, holder_reg, 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(masm(), holder(), holder_reg, name, &miss); |
} |
GenerateStoreTransition(masm(), |
- object, |
lookup, |
transition, |
name, |
@@ -1020,18 +1004,15 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
} |
-Handle<Code> NamedStoreHandlerCompiler::CompileStoreField( |
- Handle<JSObject> object, LookupResult* lookup, Handle<Name> name) { |
+Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupResult* lookup, |
+ Handle<Name> name) { |
Label miss; |
- FrontendHeader(receiver(), object, name, &miss); |
+ FrontendHeader(receiver(), name, &miss); |
// Generate store field code. |
- GenerateStoreField(masm(), |
- object, |
- lookup, |
- receiver(), this->name(), value(), scratch1(), scratch2(), |
- &miss); |
+ GenerateStoreField(masm(), holder(), lookup, receiver(), this->name(), |
+ value(), scratch1(), scratch2(), &miss); |
// Handle store cache miss. |
__ bind(&miss); |
@@ -1041,7 +1022,7 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreField( |
Handle<Code> NamedStoreHandlerCompiler::CompileStoreArrayLength( |
- Handle<JSObject> object, LookupResult* lookup, Handle<Name> name) { |
+ LookupResult* lookup, Handle<Name> name) { |
// This accepts as a receiver anything JSArray::SetElementsLength accepts |
// (currently anything except for external arrays which means anything with |
// elements of FixedArray type). Value must be a number, but only smis are |
@@ -1062,9 +1043,8 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreArrayLength( |
Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( |
- Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
- Handle<JSFunction> setter) { |
- Frontend(receiver(), holder, name); |
+ Handle<JSObject> object, Handle<Name> name, Handle<JSFunction> setter) { |
+ Frontend(receiver(), name); |
GenerateStoreViaSetter(masm(), type(), receiver(), setter); |
return GetCode(kind(), Code::FAST, name); |
@@ -1072,9 +1052,9 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( |
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
- Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
+ Handle<JSObject> object, Handle<Name> name, |
const CallOptimization& call_optimization) { |
- Frontend(receiver(), holder, name); |
+ Frontend(receiver(), name); |
Register values[] = { value() }; |
GenerateFastApiCall( |
masm(), call_optimization, handle(object->map()), |