Commit 41d25b79 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Indirect LookupResult accesses over PropertyAccessInfo

BUG=
R=yangguo@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23263 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2d2396a8
...@@ -5602,7 +5602,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -5602,7 +5602,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
PropertyAccessInfo info(this, STORE, ToType(map), name); PropertyAccessInfo info(this, STORE, ToType(map), name);
if (info.CanAccessMonomorphic()) { if (info.CanAccessMonomorphic()) {
HValue* checked_literal = Add<HCheckMaps>(literal, map); HValue* checked_literal = Add<HCheckMaps>(literal, map);
DCHECK(!info.lookup()->IsPropertyCallbacks()); DCHECK(!info.IsAccessor());
store = BuildMonomorphicAccess( store = BuildMonomorphicAccess(
&info, literal, checked_literal, value, &info, literal, checked_literal, value,
BailoutId::None(), BailoutId::None()); BailoutId::None(), BailoutId::None());
...@@ -5789,9 +5789,8 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField( ...@@ -5789,9 +5789,8 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
PropertyAccessInfo* info, PropertyAccessInfo* info,
HValue* checked_object) { HValue* checked_object) {
// See if this is a load for an immutable property // See if this is a load for an immutable property
if (checked_object->ActualValue()->IsConstant() && if (checked_object->ActualValue()->IsConstant() && info->IsCacheable() &&
info->lookup()->IsCacheable() && info->IsReadOnly() && !info->IsConfigurable()) {
info->lookup()->IsReadOnly() && info->lookup()->IsDontDelete()) {
Handle<Object> object( Handle<Object> object(
HConstant::cast(checked_object->ActualValue())->handle(isolate())); HConstant::cast(checked_object->ActualValue())->handle(isolate()));
...@@ -5831,7 +5830,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( ...@@ -5831,7 +5830,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
PropertyAccessInfo* info, PropertyAccessInfo* info,
HValue* checked_object, HValue* checked_object,
HValue* value) { HValue* value) {
bool transition_to_field = info->lookup()->IsTransition(); bool transition_to_field = info->IsTransition();
// TODO(verwaest): Move this logic into PropertyAccessInfo. // TODO(verwaest): Move this logic into PropertyAccessInfo.
HObjectAccess field_access = info->access(); HObjectAccess field_access = info->access();
...@@ -5908,26 +5907,26 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( ...@@ -5908,26 +5907,26 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
if (!LookupDescriptor()) return false; if (!LookupDescriptor()) return false;
if (!lookup_.IsFound()) { if (!IsFound()) {
return (!info->lookup_.IsFound() || info->has_holder()) && return (!info->IsFound() || info->has_holder()) &&
map()->prototype() == info->map()->prototype(); map()->prototype() == info->map()->prototype();
} }
// Mismatch if the other access info found the property in the prototype // Mismatch if the other access info found the property in the prototype
// chain. // chain.
if (info->has_holder()) return false; if (info->has_holder()) return false;
if (lookup_.IsPropertyCallbacks()) { if (IsAccessor()) {
return accessor_.is_identical_to(info->accessor_) && return accessor_.is_identical_to(info->accessor_) &&
api_holder_.is_identical_to(info->api_holder_); api_holder_.is_identical_to(info->api_holder_);
} }
if (lookup_.IsConstant()) { if (IsConstant()) {
return constant_.is_identical_to(info->constant_); return constant_.is_identical_to(info->constant_);
} }
DCHECK(lookup_.IsField()); DCHECK(IsField());
if (!info->lookup_.IsField()) return false; if (!info->IsField()) return false;
Representation r = access_.representation(); Representation r = access_.representation();
if (IsLoad()) { if (IsLoad()) {
...@@ -5970,25 +5969,23 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { ...@@ -5970,25 +5969,23 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
if (!IsLoad() && lookup_.IsProperty() && if (!IsLoad() && IsProperty() && (IsReadOnly() || !IsCacheable())) {
(lookup_.IsReadOnly() || !lookup_.IsCacheable())) {
return false; return false;
} }
if (lookup_.IsField()) { if (IsField()) {
// Construct the object field access. // Construct the object field access.
int index = lookup_.GetLocalFieldIndexFromMap(*map); int index = GetLocalFieldIndexFromMap(map);
Representation representation = lookup_.representation(); access_ = HObjectAccess::ForField(map, index, representation(), name_);
access_ = HObjectAccess::ForField(map, index, representation, name_);
// Load field map for heap objects. // Load field map for heap objects.
LoadFieldMaps(map); LoadFieldMaps(map);
} else if (lookup_.IsPropertyCallbacks()) { } else if (IsAccessor()) {
Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); Handle<Object> accessors = GetAccessorsFromMap(map);
if (!callback->IsAccessorPair()) return false; if (!accessors->IsAccessorPair()) return false;
Object* raw_accessor = IsLoad() Object* raw_accessor =
? Handle<AccessorPair>::cast(callback)->getter() IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
: Handle<AccessorPair>::cast(callback)->setter(); : Handle<AccessorPair>::cast(accessors)->setter();
if (!raw_accessor->IsJSFunction()) return false; if (!raw_accessor->IsJSFunction()) return false;
Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
if (accessor->shared()->IsApiFunction()) { if (accessor->shared()->IsApiFunction()) {
...@@ -6001,8 +5998,8 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { ...@@ -6001,8 +5998,8 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
} }
} }
accessor_ = accessor; accessor_ = accessor;
} else if (lookup_.IsConstant()) { } else if (IsConstant()) {
constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); constant_ = GetConstantFromMap(map);
} }
return true; return true;
...@@ -6016,7 +6013,7 @@ void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps( ...@@ -6016,7 +6013,7 @@ void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
field_type_ = HType::Tagged(); field_type_ = HType::Tagged();
// Figure out the field type from the accessor map. // Figure out the field type from the accessor map.
Handle<HeapType> field_type(lookup_.GetFieldTypeFromMap(*map), isolate()); Handle<HeapType> field_type = GetFieldTypeFromMap(map);
// Collect the (stable) maps from the field type. // Collect the (stable) maps from the field type.
int num_field_maps = field_type->NumClasses(); int num_field_maps = field_type->NumClasses();
...@@ -6041,9 +6038,8 @@ void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps( ...@@ -6041,9 +6038,8 @@ void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
DCHECK(field_type_.IsHeapObject()); DCHECK(field_type_.IsHeapObject());
// Add dependency on the map that introduced the field. // Add dependency on the map that introduced the field.
Map::AddDependentCompilationInfo( Map::AddDependentCompilationInfo(GetFieldOwnerFromMap(map),
handle(lookup_.GetFieldOwnerFromMap(*map), isolate()), DependentCode::kFieldTypeGroup, top_info());
DependentCode::kFieldTypeGroup, top_info());
} }
...@@ -6061,7 +6057,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { ...@@ -6061,7 +6057,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
return false; return false;
} }
map->LookupDescriptor(*holder_, *name_, &lookup_); map->LookupDescriptor(*holder_, *name_, &lookup_);
if (lookup_.IsFound()) return LoadResult(map); if (IsFound()) return LoadResult(map);
} }
lookup_.NotFound(); lookup_.NotFound();
return true; return true;
...@@ -6077,14 +6073,14 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { ...@@ -6077,14 +6073,14 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
return IsLoad(); return IsLoad();
} }
if (!LookupDescriptor()) return false; if (!LookupDescriptor()) return false;
if (lookup_.IsFound()) { if (IsFound()) {
if (IsLoad()) return true; if (IsLoad()) return true;
return !lookup_.IsReadOnly() && lookup_.IsCacheable(); return !IsReadOnly() && IsCacheable();
} }
if (!LookupInPrototypes()) return false; if (!LookupInPrototypes()) return false;
if (IsLoad()) return true; if (IsLoad()) return true;
if (lookup_.IsPropertyCallbacks()) return true; if (IsAccessor()) return true;
Handle<Map> map = this->map(); Handle<Map> map = this->map();
map->LookupTransition(NULL, *name_, &lookup_); map->LookupTransition(NULL, *name_, &lookup_);
if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) { if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) {
...@@ -6131,8 +6127,8 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( ...@@ -6131,8 +6127,8 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
if (type_->Is(Type::Number())) return false; if (type_->Is(Type::Number())) return false;
// Multiple maps cannot transition to the same target map. // Multiple maps cannot transition to the same target map.
DCHECK(!IsLoad() || !lookup_.IsTransition()); DCHECK(!IsLoad() || !IsTransition());
if (lookup_.IsTransition() && types->length() > 1) return false; if (IsTransition() && types->length() > 1) return false;
for (int i = 1; i < types->length(); ++i) { for (int i = 1; i < types->length(); ++i) {
PropertyAccessInfo test_info( PropertyAccessInfo test_info(
...@@ -6186,12 +6182,12 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( ...@@ -6186,12 +6182,12 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
} }
if (!info->lookup()->IsFound()) { if (!info->IsFound()) {
DCHECK(info->IsLoad()); DCHECK(info->IsLoad());
return graph()->GetConstantUndefined(); return graph()->GetConstantUndefined();
} }
if (info->lookup()->IsField()) { if (info->IsField()) {
if (info->IsLoad()) { if (info->IsLoad()) {
return BuildLoadNamedField(info, checked_holder); return BuildLoadNamedField(info, checked_holder);
} else { } else {
...@@ -6199,12 +6195,12 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( ...@@ -6199,12 +6195,12 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
} }
} }
if (info->lookup()->IsTransition()) { if (info->IsTransition()) {
DCHECK(!info->IsLoad()); DCHECK(!info->IsLoad());
return BuildStoreNamedField(info, checked_object, value); return BuildStoreNamedField(info, checked_object, value);
} }
if (info->lookup()->IsPropertyCallbacks()) { if (info->IsAccessor()) {
Push(checked_object); Push(checked_object);
int argument_count = 1; int argument_count = 1;
if (!info->IsLoad()) { if (!info->IsLoad()) {
...@@ -6228,7 +6224,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( ...@@ -6228,7 +6224,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
return BuildCallConstantFunction(info->accessor(), argument_count); return BuildCallConstantFunction(info->accessor(), argument_count);
} }
DCHECK(info->lookup()->IsConstant()); DCHECK(info->IsConstant());
if (info->IsLoad()) { if (info->IsLoad()) {
return New<HConstant>(info->constant()); return New<HConstant>(info->constant());
} else { } else {
...@@ -7484,8 +7480,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( ...@@ -7484,8 +7480,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
i < types->length() && ordered_functions < kMaxCallPolymorphism; i < types->length() && ordered_functions < kMaxCallPolymorphism;
++i) { ++i) {
PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
if (info.CanAccessMonomorphic() && if (info.CanAccessMonomorphic() && info.IsConstant() &&
info.lookup()->IsConstant() &&
info.constant()->IsJSFunction()) { info.constant()->IsJSFunction()) {
if (info.type()->Is(Type::String())) { if (info.type()->Is(Type::String())) {
if (handled_string) continue; if (handled_string) continue;
......
...@@ -2495,7 +2495,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2495,7 +2495,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
bool has_holder() { return !holder_.is_null(); } bool has_holder() { return !holder_.is_null(); }
bool IsLoad() const { return access_type_ == LOAD; } bool IsLoad() const { return access_type_ == LOAD; }
LookupResult* lookup() { return &lookup_; }
Handle<JSObject> holder() { return holder_; } Handle<JSObject> holder() { return holder_; }
Handle<JSFunction> accessor() { return accessor_; } Handle<JSFunction> accessor() { return accessor_; }
Handle<Object> constant() { return constant_; } Handle<Object> constant() { return constant_; }
...@@ -2504,10 +2503,38 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2504,10 +2503,38 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
HType field_type() const { return field_type_; } HType field_type() const { return field_type_; }
HObjectAccess access() { return access_; } HObjectAccess access() { return access_; }
bool IsFound() const { return lookup_.IsFound(); }
bool IsProperty() const { return lookup_.IsProperty(); }
bool IsField() const { return lookup_.IsField(); }
bool IsConstant() const { return lookup_.IsConstant(); }
bool IsAccessor() const { return lookup_.IsPropertyCallbacks(); }
bool IsTransition() const { return lookup_.IsTransition(); }
bool IsConfigurable() const { return !lookup_.IsDontDelete(); }
bool IsReadOnly() const { return lookup_.IsReadOnly(); }
bool IsCacheable() const { return lookup_.IsCacheable(); }
private: private:
Handle<Object> GetAccessorsFromMap(Handle<Map> map) const {
return handle(lookup_.GetValueFromMap(*map), isolate());
}
Handle<Object> GetConstantFromMap(Handle<Map> map) const {
return handle(lookup_.GetConstantFromMap(*map), isolate());
}
Handle<HeapType> GetFieldTypeFromMap(Handle<Map> map) const {
return handle(lookup_.GetFieldTypeFromMap(*map), isolate());
}
Handle<Map> GetFieldOwnerFromMap(Handle<Map> map) const {
return handle(lookup_.GetFieldOwnerFromMap(*map));
}
int GetLocalFieldIndexFromMap(Handle<Map> map) const {
return lookup_.GetLocalFieldIndexFromMap(*map);
}
Representation representation() const { return lookup_.representation(); }
Type* ToType(Handle<Map> map) { return builder_->ToType(map); } Type* ToType(Handle<Map> map) { return builder_->ToType(map); }
Zone* zone() { return builder_->zone(); } Zone* zone() { return builder_->zone(); }
Isolate* isolate() { return lookup_.isolate(); } Isolate* isolate() const { return lookup_.isolate(); }
CompilationInfo* top_info() { return builder_->top_info(); } CompilationInfo* top_info() { return builder_->top_info(); }
CompilationInfo* current_info() { return builder_->current_info(); } CompilationInfo* current_info() { return builder_->current_info(); }
......
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