Commit 3baab5e6 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Rewrite StoreIC handling using the LookupIterator. Continued from patch 494153002

BUG=
R=yangguo@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23305 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 80cd0fbd
......@@ -581,7 +581,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
}
void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
Register value_reg,
Label* miss_label) {
DCHECK(lookup->representation().IsHeapObject());
......
......@@ -531,7 +531,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
}
void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
Register value_reg,
Label* miss_label) {
DCHECK(lookup->representation().IsHeapObject());
......
......@@ -568,7 +568,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
}
void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
Register value_reg,
Label* miss_label) {
DCHECK(lookup->representation().IsHeapObject());
......
This diff is collapsed.
......@@ -183,24 +183,9 @@ 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(LookupIterator* lookup, Handle<Object> object,
Handle<Name> name,
Handle<Code> ComputeHandler(LookupIterator* lookup,
Handle<Object> value = Handle<Code>::null());
virtual Handle<Code> CompileHandler(LookupIterator* lookup,
Handle<Object> object,
Handle<Name> 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<Name> name,
Handle<Object> value = Handle<Code>::null());
virtual Handle<Code> CompileStoreHandler(LookupResult* lookup,
Handle<Object> object,
Handle<Name> name,
Handle<Object> value,
CacheHolderFlag cache_holder) {
UNREACHABLE();
......@@ -235,6 +220,9 @@ class IC {
}
Handle<HeapType> receiver_type() { return receiver_type_; }
void update_receiver_type(Handle<Object> receiver) {
receiver_type_ = CurrentTypeOf(receiver, isolate_);
}
void TargetMaps(MapHandleList* list) {
FindTargetMaps();
......@@ -493,12 +481,9 @@ class LoadIC: public IC {
// Update the inline cache and the global stub cache based on the
// lookup result.
void UpdateCaches(LookupIterator* lookup, Handle<Object> object,
Handle<Name> name);
void UpdateCaches(LookupIterator* lookup);
virtual Handle<Code> CompileHandler(LookupIterator* lookup,
Handle<Object> object,
Handle<Name> name,
Handle<Object> unused,
CacheHolderFlag cache_holder);
......@@ -633,6 +618,9 @@ class StoreIC: public IC {
JSReceiver::StoreFromKeyed store_mode =
JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
bool LookupForWrite(LookupIterator* it, Handle<Object> value,
JSReceiver::StoreFromKeyed store_mode);
protected:
virtual Handle<Code> megamorphic_stub();
......@@ -652,13 +640,9 @@ class StoreIC: public IC {
// Update the inline cache and the global stub cache based on the
// lookup result.
void UpdateCaches(LookupResult* lookup,
Handle<JSObject> receiver,
Handle<Name> name,
Handle<Object> value);
virtual Handle<Code> CompileStoreHandler(LookupResult* lookup,
Handle<Object> object,
Handle<Name> name,
void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
JSReceiver::StoreFromKeyed store_mode);
virtual Handle<Code> CompileHandler(LookupIterator* lookup,
Handle<Object> value,
CacheHolderFlag cache_holder);
......
......@@ -61,6 +61,7 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* map) {
case PROPERTY:
return NOT_FOUND;
case JSPROXY:
case TRANSITION:
UNREACHABLE();
}
UNREACHABLE();
......
......@@ -57,6 +57,18 @@ Handle<Map> LookupIterator::GetReceiverMap() const {
}
Handle<JSObject> LookupIterator::GetStoreTarget() const {
Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver());
if (receiver->IsJSGlobalProxy()) {
PrototypeIterator iter(isolate(), receiver);
if (iter.IsAtEnd()) return receiver;
return Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter));
}
return receiver;
}
bool LookupIterator::IsBootstrapping() const {
return isolate_->bootstrapper()->IsActive();
}
......@@ -90,6 +102,14 @@ bool LookupIterator::HasProperty() {
holder_map_->instance_descriptors()->GetDetails(number_);
}
LoadPropertyKind();
has_property_ = true;
return true;
}
void LookupIterator::LoadPropertyKind() {
switch (property_details_.type()) {
case v8::internal::FIELD:
case v8::internal::NORMAL:
......@@ -103,9 +123,6 @@ bool LookupIterator::HasProperty() {
case v8::internal::INTERCEPTOR:
UNREACHABLE();
}
has_property_ = true;
return true;
}
......@@ -148,27 +165,37 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
}
void LookupIterator::TransitionToDataProperty(
void LookupIterator::PrepareTransitionToDataProperty(
Handle<Object> value, PropertyAttributes attributes,
Object::StoreFromKeyed store_mode) {
DCHECK(!has_property_ || !HolderIsReceiverOrHiddenPrototype());
if (state_ == TRANSITION) return;
DCHECK(!has_property_ || property_kind_ != ACCESSOR);
DCHECK(!(has_property_ || state_ == JSPROXY) ||
!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
// observable.
Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver());
Handle<JSObject> receiver = GetStoreTarget();
if (receiver->IsJSGlobalProxy()) {
PrototypeIterator iter(isolate(), receiver);
receiver =
Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter));
if (!name().is_identical_to(isolate()->factory()->hidden_string()) &&
!receiver->map()->is_extensible()) {
return;
}
transition_map_ = Map::TransitionToDataProperty(
handle(receiver->map()), name_, value, attributes, store_mode);
state_ = TRANSITION;
}
void LookupIterator::ApplyTransitionToDataProperty() {
DCHECK_EQ(TRANSITION, state_);
Handle<JSObject> receiver = GetStoreTarget();
maybe_holder_ = receiver;
holder_map_ = Map::TransitionToDataProperty(handle(receiver->map()), name_,
value, attributes, store_mode);
holder_map_ = transition_map_;
JSObject::MigrateToMap(receiver, holder_map_);
ReloadPropertyInformation();
}
......@@ -180,14 +207,7 @@ void LookupIterator::TransitionToAccessorProperty(
// 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
// observable.
Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver());
if (receiver->IsJSGlobalProxy()) {
PrototypeIterator iter(isolate(), receiver);
receiver =
Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter));
}
Handle<JSObject> receiver = GetStoreTarget();
maybe_holder_ = receiver;
holder_map_ = Map::TransitionToAccessorProperty(
handle(receiver->map()), name_, component, accessor, attributes);
......@@ -304,6 +324,16 @@ FieldIndex LookupIterator::GetFieldIndex() const {
}
Handle<HeapType> LookupIterator::GetFieldType() const {
DCHECK(has_property_);
DCHECK_EQ(DESCRIPTOR, property_encoding_);
DCHECK_EQ(v8::internal::FIELD, property_details_.type());
return handle(
holder_map()->instance_descriptors()->GetFieldType(descriptor_number()),
isolate_);
}
Handle<PropertyCell> LookupIterator::GetPropertyCell() const {
Handle<JSObject> holder = GetHolder<JSObject>();
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
......
......@@ -37,6 +37,7 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
JSPROXY,
NOT_FOUND,
PROPERTY,
TRANSITION,
// Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
// PROPERTY lookup.
BEFORE_PROPERTY = INTERCEPTOR
......@@ -114,7 +115,12 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
Handle<Object> GetReceiver() const {
return maybe_receiver_.ToHandleChecked();
}
Handle<JSObject> GetStoreTarget() const;
Handle<Map> holder_map() const { return holder_map_; }
Handle<Map> transition_map() const {
DCHECK_EQ(TRANSITION, state_);
return transition_map_;
}
template <class T>
Handle<T> GetHolder() const {
DCHECK(IsFound());
......@@ -133,9 +139,20 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
// answer, and loads extra information about the property.
bool HasProperty();
void PrepareForDataProperty(Handle<Object> value);
void TransitionToDataProperty(Handle<Object> value,
void PrepareTransitionToDataProperty(Handle<Object> value,
PropertyAttributes attributes,
Object::StoreFromKeyed store_mode);
bool IsCacheableTransition() {
bool cacheable =
state_ == TRANSITION && transition_map()->GetBackPointer()->IsMap();
if (cacheable) {
property_details_ = transition_map_->GetLastDescriptorDetails();
LoadPropertyKind();
has_property_ = true;
}
return cacheable;
}
void ApplyTransitionToDataProperty();
void ReconfigureDataProperty(Handle<Object> value,
PropertyAttributes attributes);
void TransitionToAccessorProperty(AccessorComponent component,
......@@ -159,6 +176,7 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
return property_details().representation();
}
FieldIndex GetFieldIndex() const;
Handle<HeapType> GetFieldType() const;
int GetConstantIndex() const;
Handle<PropertyCell> GetPropertyCell() const;
Handle<Object> GetAccessors() const;
......@@ -174,6 +192,7 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
inline State LookupInHolder(Map* map);
Handle<Object> FetchValue() const;
void ReloadPropertyInformation();
void LoadPropertyKind();
bool IsBootstrapping() const;
......@@ -227,6 +246,7 @@ class LookupIterator V8_FINAL BASE_EMBEDDED {
Isolate* isolate_;
Handle<Name> name_;
Handle<Map> holder_map_;
Handle<Map> transition_map_;
MaybeHandle<Object> maybe_receiver_;
MaybeHandle<JSReceiver> maybe_holder_;
......
......@@ -576,7 +576,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
}
void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
Register value_reg,
Label* miss_label) {
DCHECK(lookup->representation().IsHeapObject());
......
......@@ -580,7 +580,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
}
void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
Register value_reg,
Label* miss_label) {
DCHECK(lookup->representation().IsHeapObject());
......
This diff is collapsed.
......@@ -1997,10 +1997,6 @@ class JSReceiver: public HeapObject {
inline static Handle<Smi> GetOrCreateIdentityHash(
Handle<JSReceiver> object);
// Lookup a property. If found, the result is valid and has
// detailed information.
void Lookup(Handle<Name> name, LookupResult* result);
enum KeyCollectionType { OWN_ONLY, INCLUDE_PROTOS };
// Computes the enumerable keys for a JSObject. Used for implementing
......@@ -2010,7 +2006,6 @@ class JSReceiver: public HeapObject {
KeyCollectionType type);
private:
void LookupOwn(Handle<Name> name, LookupResult* result);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
};
......@@ -2368,9 +2363,6 @@ class JSObject: public JSReceiver {
inline void SetInternalField(int index, Object* value);
inline void SetInternalField(int index, Smi* value);
// The following lookup functions skip interceptors.
void LookupOwnRealNamedProperty(Handle<Name> name, LookupResult* result);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
int NumberOfOwnProperties(PropertyAttributes filter = NONE);
......
......@@ -10900,6 +10900,7 @@ static Handle<Object> DebugLookupResultValue(LookupIterator* it,
for (; it->IsFound(); it->Next()) {
switch (it->state()) {
case LookupIterator::NOT_FOUND:
case LookupIterator::TRANSITION:
UNREACHABLE();
case LookupIterator::ACCESS_CHECK:
// Ignore access checks.
......
......@@ -614,14 +614,18 @@ RUNTIME_FUNCTION(StorePropertyWithInterceptor) {
Handle<Name> name = args.at<Name>(1);
Handle<Object> value = args.at<Object>(2);
#ifdef DEBUG
if (receiver->IsJSGlobalProxy()) {
PrototypeIterator iter(isolate, receiver);
DCHECK(iter.IsAtEnd() ||
Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter))
->HasNamedInterceptor());
} else {
DCHECK(receiver->HasNamedInterceptor());
PrototypeIterator iter(isolate, receiver,
PrototypeIterator::START_AT_RECEIVER);
bool found = false;
while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
Handle<Object> current = PrototypeIterator::GetCurrent(iter);
if (current->IsJSObject() &&
Handle<JSObject>::cast(current)->HasNamedInterceptor()) {
found = true;
break;
}
}
DCHECK(found);
#endif
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
......@@ -889,7 +893,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
LookupIterator* it, Handle<Name> name) {
LookupIterator* it) {
// So far the most popular follow ups for interceptor loads are FIELD and
// ExecutableAccessorInfo, so inline only them. Other cases may be added
// later.
......@@ -912,7 +916,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
}
}
Register reg = Frontend(receiver(), name);
Register reg = Frontend(receiver(), it->name());
if (inline_followup) {
// TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer.
......@@ -920,7 +924,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
} else {
GenerateLoadInterceptor(reg);
}
return GetCode(kind(), Code::FAST, name);
return GetCode(kind(), Code::FAST, it->name());
}
......@@ -1007,13 +1011,12 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition(
}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupResult* lookup,
Handle<Name> name) {
Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) {
Label miss;
GenerateStoreField(lookup, value(), &miss);
GenerateStoreField(it, value(), &miss);
__ bind(&miss);
TailCallBuiltin(masm(), MissBuiltin(kind()));
return GetCode(kind(), Code::FAST, name);
return GetCode(kind(), Code::FAST, it->name());
}
......
......@@ -476,7 +476,7 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
// The LookupIterator is used to perform a lookup behind the interceptor. If
// the iterator points to a LookupIterator::PROPERTY, its access will be
// inlined.
Handle<Code> CompileLoadInterceptor(LookupIterator* it, Handle<Name> name);
Handle<Code> CompileLoadInterceptor(LookupIterator* it);
Handle<Code> CompileLoadViaGetter(Handle<Name> name,
Handle<JSFunction> getter);
......@@ -558,7 +558,7 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
Handle<Code> CompileStoreTransition(Handle<Map> transition,
Handle<Name> name);
Handle<Code> CompileStoreField(LookupResult* lookup, Handle<Name> name);
Handle<Code> CompileStoreField(LookupIterator* it);
Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback);
Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
......@@ -590,7 +590,7 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
Register scratch2, Register scratch3,
Label* miss_label, Label* slow);
void GenerateStoreField(LookupResult* lookup, Register value_reg,
void GenerateStoreField(LookupIterator* lookup, Register value_reg,
Label* miss_label);
static Builtins::Name SlowBuiltin(Code::Kind kind) {
......
......@@ -516,7 +516,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
}
void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
Register value_reg,
Label* miss_label) {
DCHECK(lookup->representation().IsHeapObject());
......
......@@ -567,7 +567,7 @@ void NamedStoreHandlerCompiler::GenerateStoreTransition(
}
void NamedStoreHandlerCompiler::GenerateStoreField(LookupResult* lookup,
void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup,
Register value_reg,
Label* miss_label) {
DCHECK(lookup->representation().IsHeapObject());
......
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