Commit 60c08a8b authored by verwaest@chromium.org's avatar verwaest@chromium.org

Directly store the transition target on LookupResult in TransitionResult.

BUG=chromium:343964
LOG=N
R=jkummerow@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19440 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 45452cc3
...@@ -4376,14 +4376,14 @@ HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset, ...@@ -4376,14 +4376,14 @@ HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset,
HObjectAccess HObjectAccess::ForField(Handle<Map> map, HObjectAccess HObjectAccess::ForField(Handle<Map> map,
LookupResult* lookup, LookupResult* lookup,
Handle<String> name) { Handle<String> name) {
ASSERT(lookup->IsField() || lookup->IsTransitionToField(*map)); ASSERT(lookup->IsField() || lookup->IsTransitionToField());
int index; int index;
Representation representation; Representation representation;
if (lookup->IsField()) { if (lookup->IsField()) {
index = lookup->GetLocalFieldIndexFromMap(*map); index = lookup->GetLocalFieldIndexFromMap(*map);
representation = lookup->representation(); representation = lookup->representation();
} else { } else {
Map* transition = lookup->GetTransitionMapFromMap(*map); Map* transition = lookup->GetTransitionTarget();
int descriptor = transition->LastAdded(); int descriptor = transition->LastAdded();
index = transition->instance_descriptors()->GetFieldIndex(descriptor) - index = transition->instance_descriptors()->GetFieldIndex(descriptor) -
map->inobject_properties(); map->inobject_properties();
......
...@@ -5555,8 +5555,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { ...@@ -5555,8 +5555,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
if (lookup_.IsPropertyCallbacks()) return true; if (lookup_.IsPropertyCallbacks()) 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) && map->unused_property_fields() > 0) { if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) {
transition_ = handle(lookup_.GetTransitionMapFromMap(*map));
return true; return true;
} }
return false; return false;
......
...@@ -2408,7 +2408,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2408,7 +2408,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
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_; }
Handle<Object> transition() { return transition_; } Handle<Map> transition() { return handle(lookup_.GetTransitionTarget()); }
HObjectAccess access() { return access_; } HObjectAccess access() { return access_; }
private: private:
...@@ -2435,7 +2435,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2435,7 +2435,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
Handle<JSFunction> accessor_; Handle<JSFunction> accessor_;
Handle<JSObject> api_holder_; Handle<JSObject> api_holder_;
Handle<Object> constant_; Handle<Object> constant_;
Handle<Map> transition_;
HObjectAccess access_; HObjectAccess access_;
}; };
......
...@@ -1134,8 +1134,7 @@ static bool LookupForWrite(Handle<JSObject> receiver, ...@@ -1134,8 +1134,7 @@ static bool LookupForWrite(Handle<JSObject> receiver,
// receiver when trying to fetch extra information from the transition. // receiver when trying to fetch extra information from the transition.
receiver->map()->LookupTransition(*holder, *name, lookup); receiver->map()->LookupTransition(*holder, *name, lookup);
if (!lookup->IsTransition()) return false; if (!lookup->IsTransition()) return false;
PropertyDetails target_details = PropertyDetails target_details = lookup->GetTransitionDetails();
lookup->GetTransitionDetails(receiver->map());
if (target_details.IsReadOnly()) return false; if (target_details.IsReadOnly()) return false;
// If the value that's being stored does not fit in the field that the // If the value that's being stored does not fit in the field that the
...@@ -1146,7 +1145,7 @@ static bool LookupForWrite(Handle<JSObject> receiver, ...@@ -1146,7 +1145,7 @@ static bool LookupForWrite(Handle<JSObject> receiver,
// transition target. // transition target.
ASSERT(!receiver->map()->is_deprecated()); ASSERT(!receiver->map()->is_deprecated());
if (!value->FitsRepresentation(target_details.representation())) { if (!value->FitsRepresentation(target_details.representation())) {
Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map())); Handle<Map> target(lookup->GetTransitionTarget());
Map::GeneralizeRepresentation( Map::GeneralizeRepresentation(
target, target->LastAdded(), target, target->LastAdded(),
value->OptimalRepresentation(), FORCE_FIELD); value->OptimalRepresentation(), FORCE_FIELD);
...@@ -1319,12 +1318,8 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, ...@@ -1319,12 +1318,8 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
case TRANSITION: { case TRANSITION: {
// Explicitly pass in the receiver map since LookupForWrite may have // Explicitly pass in the receiver map since LookupForWrite may have
// stored something else than the receiver in the holder. // stored something else than the receiver in the holder.
Handle<Map> transition( Handle<Map> transition(lookup->GetTransitionTarget());
lookup->GetTransitionTarget(receiver->map()), isolate()); PropertyDetails details = transition->GetLastDescriptorDetails();
int descriptor = transition->LastAdded();
DescriptorArray* target_descriptors = transition->instance_descriptors();
PropertyDetails details = target_descriptors->GetDetails(descriptor);
if (details.type() == CALLBACKS || details.attributes() != NONE) break; if (details.type() == CALLBACKS || details.attributes() != NONE) break;
......
...@@ -2497,6 +2497,11 @@ int DescriptorArray::SearchWithCache(Name* name, Map* map) { ...@@ -2497,6 +2497,11 @@ int DescriptorArray::SearchWithCache(Name* name, Map* map) {
} }
PropertyDetails Map::GetLastDescriptorDetails() {
return instance_descriptors()->GetDetails(LastAdded());
}
void Map::LookupDescriptor(JSObject* holder, void Map::LookupDescriptor(JSObject* holder,
Name* name, Name* name,
LookupResult* result) { LookupResult* result) {
...@@ -2514,7 +2519,8 @@ void Map::LookupTransition(JSObject* holder, ...@@ -2514,7 +2519,8 @@ void Map::LookupTransition(JSObject* holder,
TransitionArray* transition_array = transitions(); TransitionArray* transition_array = transitions();
int number = transition_array->Search(name); int number = transition_array->Search(name);
if (number != TransitionArray::kNotFound) { if (number != TransitionArray::kNotFound) {
return result->TransitionResult(holder, number); return result->TransitionResult(
holder, transition_array->GetTarget(number));
} }
} }
result->NotFound(); result->NotFound();
......
...@@ -6088,6 +6088,8 @@ class Map: public HeapObject { ...@@ -6088,6 +6088,8 @@ class Map: public HeapObject {
Name* name, Name* name,
LookupResult* result); LookupResult* result);
inline PropertyDetails GetLastDescriptorDetails();
// The size of transition arrays are limited so they do not end up in large // The size of transition arrays are limited so they do not end up in large
// object space. Otherwise ClearNonLiveTransitions would leak memory while // object space. Otherwise ClearNonLiveTransitions would leak memory while
// applying in-place right trimming. // applying in-place right trimming.
......
...@@ -35,6 +35,7 @@ void LookupResult::Iterate(ObjectVisitor* visitor) { ...@@ -35,6 +35,7 @@ void LookupResult::Iterate(ObjectVisitor* visitor) {
LookupResult* current = this; // Could be NULL. LookupResult* current = this; // Could be NULL.
while (current != NULL) { while (current != NULL) {
visitor->VisitPointer(BitCast<Object**>(&current->holder_)); visitor->VisitPointer(BitCast<Object**>(&current->holder_));
visitor->VisitPointer(BitCast<Object**>(&current->transition_));
current = current->next_; current = current->next_;
} }
} }
...@@ -82,13 +83,13 @@ void LookupResult::Print(FILE* out) { ...@@ -82,13 +83,13 @@ void LookupResult::Print(FILE* out) {
case FIELD: case FIELD:
PrintF(out, " -type = map transition\n"); PrintF(out, " -type = map transition\n");
PrintF(out, " -map:\n"); PrintF(out, " -map:\n");
GetTransitionMap()->Print(out); GetTransitionTarget()->Print(out);
PrintF(out, "\n"); PrintF(out, "\n");
return; return;
case CONSTANT: case CONSTANT:
PrintF(out, " -type = constant property transition\n"); PrintF(out, " -type = constant property transition\n");
PrintF(out, " -map:\n"); PrintF(out, " -map:\n");
GetTransitionMap()->Print(out); GetTransitionTarget()->Print(out);
PrintF(out, "\n"); PrintF(out, "\n");
return; return;
case CALLBACKS: case CALLBACKS:
......
...@@ -184,6 +184,7 @@ class LookupResult BASE_EMBEDDED { ...@@ -184,6 +184,7 @@ class LookupResult BASE_EMBEDDED {
next_(isolate->top_lookup_result()), next_(isolate->top_lookup_result()),
lookup_type_(NOT_FOUND), lookup_type_(NOT_FOUND),
holder_(NULL), holder_(NULL),
transition_(NULL),
cacheable_(true), cacheable_(true),
details_(NONE, NONEXISTENT, Representation::None()) { details_(NONE, NONEXISTENT, Representation::None()) {
isolate->set_top_lookup_result(this); isolate->set_top_lookup_result(this);
...@@ -199,6 +200,7 @@ class LookupResult BASE_EMBEDDED { ...@@ -199,6 +200,7 @@ class LookupResult BASE_EMBEDDED {
void DescriptorResult(JSObject* holder, PropertyDetails details, int number) { void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
lookup_type_ = DESCRIPTOR_TYPE; lookup_type_ = DESCRIPTOR_TYPE;
holder_ = holder; holder_ = holder;
transition_ = NULL;
details_ = details; details_ = details;
number_ = number; number_ = number;
} }
...@@ -209,16 +211,18 @@ class LookupResult BASE_EMBEDDED { ...@@ -209,16 +211,18 @@ class LookupResult BASE_EMBEDDED {
return value->FitsRepresentation(details_.representation()); return value->FitsRepresentation(details_.representation());
} }
void TransitionResult(JSObject* holder, int number) { void TransitionResult(JSObject* holder, Map* target) {
lookup_type_ = TRANSITION_TYPE; lookup_type_ = TRANSITION_TYPE;
details_ = PropertyDetails(NONE, TRANSITION, Representation::None()); details_ = PropertyDetails(NONE, TRANSITION, Representation::None());
holder_ = holder; holder_ = holder;
number_ = number; transition_ = target;
number_ = 0xAAAA;
} }
void DictionaryResult(JSObject* holder, int entry) { void DictionaryResult(JSObject* holder, int entry) {
lookup_type_ = DICTIONARY_TYPE; lookup_type_ = DICTIONARY_TYPE;
holder_ = holder; holder_ = holder;
transition_ = NULL;
details_ = holder->property_dictionary()->DetailsAt(entry); details_ = holder->property_dictionary()->DetailsAt(entry);
number_ = entry; number_ = entry;
} }
...@@ -226,6 +230,7 @@ class LookupResult BASE_EMBEDDED { ...@@ -226,6 +230,7 @@ class LookupResult BASE_EMBEDDED {
void HandlerResult(JSProxy* proxy) { void HandlerResult(JSProxy* proxy) {
lookup_type_ = HANDLER_TYPE; lookup_type_ = HANDLER_TYPE;
holder_ = proxy; holder_ = proxy;
transition_ = NULL;
details_ = PropertyDetails(NONE, HANDLER, Representation::Tagged()); details_ = PropertyDetails(NONE, HANDLER, Representation::Tagged());
cacheable_ = false; cacheable_ = false;
} }
...@@ -233,6 +238,7 @@ class LookupResult BASE_EMBEDDED { ...@@ -233,6 +238,7 @@ class LookupResult BASE_EMBEDDED {
void InterceptorResult(JSObject* holder) { void InterceptorResult(JSObject* holder) {
lookup_type_ = INTERCEPTOR_TYPE; lookup_type_ = INTERCEPTOR_TYPE;
holder_ = holder; holder_ = holder;
transition_ = NULL;
details_ = PropertyDetails(NONE, INTERCEPTOR, Representation::Tagged()); details_ = PropertyDetails(NONE, INTERCEPTOR, Representation::Tagged());
} }
...@@ -240,6 +246,7 @@ class LookupResult BASE_EMBEDDED { ...@@ -240,6 +246,7 @@ class LookupResult BASE_EMBEDDED {
lookup_type_ = NOT_FOUND; lookup_type_ = NOT_FOUND;
details_ = PropertyDetails(NONE, NONEXISTENT, Representation::None()); details_ = PropertyDetails(NONE, NONEXISTENT, Representation::None());
holder_ = NULL; holder_ = NULL;
transition_ = NULL;
} }
JSObject* holder() const { JSObject* holder() const {
...@@ -248,7 +255,7 @@ class LookupResult BASE_EMBEDDED { ...@@ -248,7 +255,7 @@ class LookupResult BASE_EMBEDDED {
} }
JSProxy* proxy() const { JSProxy* proxy() const {
ASSERT(IsFound()); ASSERT(IsHandler());
return JSProxy::cast(holder_); return JSProxy::cast(holder_);
} }
...@@ -373,47 +380,21 @@ class LookupResult BASE_EMBEDDED { ...@@ -373,47 +380,21 @@ class LookupResult BASE_EMBEDDED {
return NULL; return NULL;
} }
Map* GetTransitionTarget(Map* map) const {
ASSERT(IsTransition());
TransitionArray* transitions = map->transitions();
return transitions->GetTarget(number_);
}
Map* GetTransitionTarget() const { Map* GetTransitionTarget() const {
return GetTransitionTarget(holder()->map()); return transition_;
}
PropertyDetails GetTransitionDetails(Map* map) const {
ASSERT(IsTransition());
TransitionArray* transitions = map->transitions();
return transitions->GetTargetDetails(number_);
} }
PropertyDetails GetTransitionDetails() const { PropertyDetails GetTransitionDetails() const {
return GetTransitionDetails(holder()->map());
}
bool IsTransitionToField(Map* map) const {
return IsTransition() && GetTransitionDetails(map).type() == FIELD;
}
bool IsTransitionToConstant(Map* map) const {
return IsTransition() && GetTransitionDetails(map).type() == CONSTANT;
}
Map* GetTransitionMap() const {
ASSERT(IsTransition()); ASSERT(IsTransition());
return Map::cast(GetValue()); return transition_->GetLastDescriptorDetails();
} }
Map* GetTransitionMapFromMap(Map* map) const { bool IsTransitionToField() const {
ASSERT(IsTransition()); return IsTransition() && GetTransitionDetails().type() == FIELD;
return map->transitions()->GetTarget(number_);
} }
int GetTransitionIndex() const { bool IsTransitionToConstant() const {
ASSERT(IsTransition()); return IsTransition() && GetTransitionDetails().type() == CONSTANT;
return number_;
} }
int GetDescriptorIndex() const { int GetDescriptorIndex() const {
...@@ -501,6 +482,7 @@ class LookupResult BASE_EMBEDDED { ...@@ -501,6 +482,7 @@ class LookupResult BASE_EMBEDDED {
} lookup_type_; } lookup_type_;
JSReceiver* holder_; JSReceiver* holder_;
Map* transition_;
int number_; int number_;
bool cacheable_; bool cacheable_;
PropertyDetails details_; PropertyDetails details_;
......
...@@ -160,9 +160,7 @@ void TransitionArray::SetTarget(int transition_number, Map* value) { ...@@ -160,9 +160,7 @@ void TransitionArray::SetTarget(int transition_number, Map* value) {
PropertyDetails TransitionArray::GetTargetDetails(int transition_number) { PropertyDetails TransitionArray::GetTargetDetails(int transition_number) {
Map* map = GetTarget(transition_number); Map* map = GetTarget(transition_number);
DescriptorArray* descriptors = map->instance_descriptors(); return map->GetLastDescriptorDetails();
int descriptor = map->LastAdded();
return descriptors->GetDetails(descriptor);
} }
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-proxies --expose-gc
var proxy = Proxy.create({ getPropertyDescriptor:function(key) {
gc();
}});
function f() { this.x = 23; }
f.prototype = proxy;
new f();
new f();
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