Avoid one repeated property lookup when computing load ICs.

R=verwaest@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22802 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f66ddb18
......@@ -1221,7 +1221,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
FrontendHeader(receiver(), name, &miss);
......@@ -1231,7 +1231,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
__ ldr(result, FieldMemOperand(result, Cell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
if (is_configurable) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(result, ip);
__ b(eq, &miss);
......
......@@ -1195,7 +1195,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
FrontendHeader(receiver(), name, &miss);
......@@ -1205,7 +1205,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
__ Ldr(result, FieldMemOperand(result, Cell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
if (is_configurable) {
__ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss);
}
......
......@@ -1245,7 +1245,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
FrontendHeader(receiver(), name, &miss);
......@@ -1259,7 +1259,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
}
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
if (is_configurable) {
__ cmp(result, factory()->the_hole_value());
__ j(equal, &miss);
} else if (FLAG_debug_code) {
......
This diff is collapsed.
......@@ -179,17 +179,29 @@ class IC {
static void PostPatching(Address address, Code* target, Code* old_target);
// Compute the handler either by compiling or by retrieving a cached version.
Handle<Code> ComputeHandler(LookupResult* lookup,
Handle<Object> object,
Handle<Code> ComputeHandler(LookupIterator* lookup, Handle<Object> object,
Handle<String> name,
Handle<Object> value = Handle<Code>::null());
virtual Handle<Code> CompileHandler(LookupResult* lookup,
virtual Handle<Code> CompileHandler(LookupIterator* lookup,
Handle<Object> object,
Handle<String> name, Handle<Object> value,
CacheHolderFlag cache_holder) {
UNREACHABLE();
return Handle<Code>::null();
}
// Temporary copy of the above, but using a LookupResult.
// TODO(jkummerow): Migrate callers to LookupIterator and delete these.
Handle<Code> ComputeStoreHandler(LookupResult* lookup, Handle<Object> object,
Handle<String> name,
Handle<Object> value = Handle<Code>::null());
virtual Handle<Code> CompileStoreHandler(LookupResult* lookup,
Handle<Object> object,
Handle<String> name,
Handle<Object> value,
CacheHolderFlag cache_holder) {
UNREACHABLE();
return Handle<Code>::null();
}
void UpdateMonomorphicIC(Handle<Code> handler, Handle<String> name);
bool UpdatePolymorphicIC(Handle<String> name, Handle<Code> code);
......@@ -474,11 +486,10 @@ class LoadIC: public IC {
// Update the inline cache and the global stub cache based on the
// lookup result.
void UpdateCaches(LookupResult* lookup,
Handle<Object> object,
void UpdateCaches(LookupIterator* lookup, Handle<Object> object,
Handle<String> name);
virtual Handle<Code> CompileHandler(LookupResult* lookup,
virtual Handle<Code> CompileHandler(LookupIterator* lookup,
Handle<Object> object,
Handle<String> name,
Handle<Object> unused,
......@@ -638,10 +649,11 @@ class StoreIC: public IC {
Handle<JSObject> receiver,
Handle<String> name,
Handle<Object> value);
virtual Handle<Code> CompileHandler(LookupResult* lookup,
Handle<Object> object,
Handle<String> name, Handle<Object> value,
CacheHolderFlag cache_holder);
virtual Handle<Code> CompileStoreHandler(LookupResult* lookup,
Handle<Object> object,
Handle<String> name,
Handle<Object> value,
CacheHolderFlag cache_holder);
private:
void set_target(Code* code) {
......
......@@ -120,8 +120,9 @@ bool LookupIterator::HasProperty() {
return false;
}
} else {
property_details_ = holder_map_->instance_descriptors()->GetDetails(
number_);
// Can't use descriptor_number() yet because has_property_ is still false.
property_details_ =
holder_map_->instance_descriptors()->GetDetails(number_);
}
switch (property_details_.type()) {
......@@ -146,9 +147,10 @@ bool LookupIterator::HasProperty() {
void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
ASSERT(has_property_);
ASSERT(HolderIsReceiver());
ASSERT(HolderIsReceiverOrHiddenPrototype());
if (property_encoding_ == DICTIONARY) return;
holder_map_ = Map::PrepareForDataProperty(holder_map_, number_, value);
holder_map_ =
Map::PrepareForDataProperty(holder_map_, descriptor_number(), value);
JSObject::MigrateToMap(GetHolder<JSObject>(), holder_map_);
// Reload property information.
if (holder_map_->is_dictionary_map()) {
......@@ -163,7 +165,7 @@ void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
void LookupIterator::TransitionToDataProperty(
Handle<Object> value, PropertyAttributes attributes,
Object::StoreFromKeyed store_mode) {
ASSERT(!has_property_ || !HolderIsReceiver());
ASSERT(!has_property_ || !HolderIsReceiverOrHiddenPrototype());
// Can only be called when the receiver is a JSObject. JSProxy has to be
// handled via a trap. Adding properties to primitive values is not
......@@ -194,7 +196,7 @@ void LookupIterator::TransitionToDataProperty(
}
bool LookupIterator::HolderIsReceiver() const {
bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const {
ASSERT(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY);
DisallowHeapAllocation no_gc;
Handle<Object> receiver = GetReceiver();
......@@ -228,8 +230,8 @@ Handle<Object> LookupIterator::FetchValue() const {
break;
case DESCRIPTOR:
if (property_details_.type() == v8::internal::FIELD) {
FieldIndex field_index = FieldIndex::ForDescriptor(
*holder_map_, number_);
FieldIndex field_index =
FieldIndex::ForDescriptor(*holder_map_, number_);
return JSObject::FastPropertyAt(
holder, property_details_.representation(), field_index);
}
......@@ -239,6 +241,23 @@ Handle<Object> LookupIterator::FetchValue() const {
}
FieldIndex LookupIterator::GetFieldIndex() const {
ASSERT_EQ(PROPERTY, state_);
int index =
holder_map()->instance_descriptors()->GetFieldIndex(descriptor_number());
bool is_double = representation().IsDouble();
return FieldIndex::ForPropertyIndex(*holder_map(), index, is_double);
}
Handle<PropertyCell> LookupIterator::GetPropertyCell() const {
Handle<JSObject> holder = GetHolder<JSObject>();
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
Object* value = global->property_dictionary()->ValueAt(dictionary_entry());
return Handle<PropertyCell>(PropertyCell::cast(value));
}
Handle<Object> LookupIterator::GetAccessors() const {
ASSERT(has_property_);
ASSERT_EQ(ACCESSOR, property_kind_);
......@@ -262,13 +281,13 @@ void LookupIterator::WriteDataValue(Handle<Object> value) {
NameDictionary* property_dictionary = holder->property_dictionary();
if (holder->IsGlobalObject()) {
Handle<PropertyCell> cell(
PropertyCell::cast(property_dictionary->ValueAt(number_)));
PropertyCell::cast(property_dictionary->ValueAt(dictionary_entry())));
PropertyCell::SetValueInferType(cell, value);
} else {
property_dictionary->ValueAtPut(number_, *value);
property_dictionary->ValueAtPut(dictionary_entry(), *value);
}
} else if (property_details_.type() == v8::internal::FIELD) {
holder->WriteToField(number_, *value);
holder->WriteToField(descriptor_number(), *value);
} else {
ASSERT_EQ(v8::internal::CONSTANT, property_details_.type());
}
......
......@@ -99,7 +99,7 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
return Handle<T>::cast(maybe_holder_.ToHandleChecked());
}
Handle<JSReceiver> GetRoot() const;
bool HolderIsReceiver() const;
bool HolderIsReceiverOrHiddenPrototype() const;
/* Dynamically reduce the trapped types. */
void skip_interceptor() {
......@@ -127,15 +127,20 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
ASSERT(has_property_);
return property_kind_;
}
PropertyEncoding property_encoding() const {
ASSERT(has_property_);
return property_encoding_;
}
PropertyDetails property_details() const {
ASSERT(has_property_);
return property_details_;
}
int descriptor_number() const {
ASSERT(has_property_);
ASSERT_EQ(DESCRIPTOR, property_encoding_);
return number_;
bool IsConfigurable() const { return !property_details().IsDontDelete(); }
Representation representation() const {
return property_details().representation();
}
FieldIndex GetFieldIndex() const;
Handle<PropertyCell> GetPropertyCell() const;
Handle<Object> GetAccessors() const;
Handle<Object> GetDataValue() const;
void WriteDataValue(Handle<Object> value);
......@@ -170,6 +175,16 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
bool check_access_check() const {
return (configuration_ & CHECK_ACCESS_CHECK) != 0;
}
int descriptor_number() const {
ASSERT(has_property_);
ASSERT_EQ(DESCRIPTOR, property_encoding_);
return number_;
}
int dictionary_entry() const {
ASSERT(has_property_);
ASSERT_EQ(DICTIONARY, property_encoding_);
return number_;
}
Configuration configuration_;
State state_;
......
......@@ -1210,7 +1210,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
FrontendHeader(receiver(), name, &miss);
......@@ -1221,7 +1221,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
__ lw(result, FieldMemOperand(result, Cell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
if (is_configurable) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&miss, eq, result, Operand(at));
}
......
......@@ -1211,7 +1211,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
FrontendHeader(receiver(), name, &miss);
......@@ -1222,7 +1222,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
__ ld(result, FieldMemOperand(result, Cell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
if (is_configurable) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&miss, eq, result, Operand(at));
}
......
......@@ -3011,7 +3011,7 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
strict_mode);
case LookupIterator::JSPROXY:
if (it->HolderIsReceiver()) {
if (it->HolderIsReceiverOrHiddenPrototype()) {
return JSProxy::SetPropertyWithHandler(it->GetHolder<JSProxy>(),
it->GetReceiver(), it->name(),
value, strict_mode);
......@@ -3028,7 +3028,7 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
break;
case LookupIterator::INTERCEPTOR:
if (it->HolderIsReceiver()) {
if (it->HolderIsReceiverOrHiddenPrototype()) {
MaybeHandle<Object> maybe_result =
JSObject::SetPropertyWithInterceptor(it, value);
if (!maybe_result.is_null()) return maybe_result;
......@@ -3052,7 +3052,7 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
}
switch (it->property_kind()) {
case LookupIterator::ACCESSOR:
if (it->HolderIsReceiver() ||
if (it->HolderIsReceiverOrHiddenPrototype() ||
!it->GetAccessors()->IsDeclaredAccessorInfo()) {
return SetPropertyWithAccessor(it->GetReceiver(), it->name(),
value, it->GetHolder<JSObject>(),
......@@ -3060,7 +3060,9 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it,
}
break;
case LookupIterator::DATA:
if (it->HolderIsReceiver()) return SetDataProperty(it, value);
if (it->HolderIsReceiverOrHiddenPrototype()) {
return SetDataProperty(it, value);
}
}
done = true;
break;
......@@ -3092,7 +3094,7 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
// Store on the holder which may be hidden behind the receiver.
ASSERT(it->HolderIsReceiver());
ASSERT(it->HolderIsReceiverOrHiddenPrototype());
// Old value for the observation change record.
// Fetch before transforming the object since the encoding may become
......
......@@ -478,7 +478,7 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
Handle<JSFunction> getter);
Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
bool is_dont_delete);
bool is_configurable);
// Static interface
static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
......
......@@ -1180,7 +1180,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) {
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
FrontendHeader(receiver(), name, &miss);
......@@ -1190,7 +1190,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
__ movp(result, FieldOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
if (is_configurable) {
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
__ j(equal, &miss);
} else if (FLAG_debug_code) {
......
......@@ -1258,7 +1258,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
}
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
if (is_configurable) {
__ cmp(result, factory()->the_hole_value());
__ j(equal, &miss);
} else if (FLAG_debug_code) {
......
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