Revision: 20494
Author: [email protected]
Date: Fri Apr 4 04:49:07 2014 UTC
Log: Get rid of the TRANSITION PropertyType and consistently use
CanHoldValue().
[email protected]
Review URL: https://codereview.chromium.org/223193005
http://code.google.com/p/v8/source/detail?r=20494
Modified:
/branches/bleeding_edge/src/bootstrapper.cc
/branches/bleeding_edge/src/heap-snapshot-generator.cc
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects-printer.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/property-details.h
/branches/bleeding_edge/src/property.cc
/branches/bleeding_edge/src/property.h
/branches/bleeding_edge/src/runtime.cc
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Thu Apr 3 12:41:37 2014 UTC
+++ /branches/bleeding_edge/src/bootstrapper.cc Fri Apr 4 04:49:07 2014 UTC
@@ -2464,7 +2464,6 @@
// Do not occur since the from object has fast properties.
case HANDLER:
case INTERCEPTOR:
- case TRANSITION:
case NONEXISTENT:
// No element in instance descriptors have proxy or interceptor
type.
UNREACHABLE();
=======================================
--- /branches/bleeding_edge/src/heap-snapshot-generator.cc Thu Apr 3
16:32:59 2014 UTC
+++ /branches/bleeding_edge/src/heap-snapshot-generator.cc Fri Apr 4
04:49:07 2014 UTC
@@ -1671,7 +1671,6 @@
case HANDLER: // only in lookup results, not in descriptors
case INTERCEPTOR: // only in lookup results, not in descriptors
break;
- case TRANSITION:
case NONEXISTENT:
UNREACHABLE();
break;
=======================================
--- /branches/bleeding_edge/src/ic.cc Thu Apr 3 12:27:24 2014 UTC
+++ /branches/bleeding_edge/src/ic.cc Fri Apr 4 04:49:07 2014 UTC
@@ -1167,9 +1167,7 @@
// chain check. This avoids a double lookup, but requires us to pass in
the
// receiver when trying to fetch extra information from the transition.
receiver->map()->LookupTransition(*holder, *name, lookup);
- if (!lookup->IsTransition()) return false;
- PropertyDetails target_details = lookup->GetTransitionDetails();
- if (target_details.IsReadOnly()) return false;
+ if (!lookup->IsTransition() || lookup->IsReadOnly()) return false;
// If the value that's being stored does not fit in the field that the
// instance would transition to, create a new transition that fits the
value.
@@ -1178,7 +1176,7 @@
// Ensure the instance and its map were migrated before trying to update
the
// transition target.
ASSERT(!receiver->map()->is_deprecated());
- if (!value->FitsRepresentation(target_details.representation())) {
+ if (!lookup->CanHoldValue(value)) {
Handle<Map> target(lookup->GetTransitionTarget());
Map::GeneralizeRepresentation(
target, target->LastAdded(),
@@ -1327,93 +1325,94 @@
Handle<JSObject> holder(lookup->holder());
// Handlers do not use strict mode.
StoreStubCompiler compiler(isolate(), SLOPPY, kind());
- switch (lookup->type()) {
- case FIELD:
- return compiler.CompileStoreField(receiver, lookup, name);
- case TRANSITION: {
- // Explicitly pass in the receiver map since LookupForWrite may have
- // stored something else than the receiver in the holder.
- Handle<Map> transition(lookup->GetTransitionTarget());
- PropertyDetails details = transition->GetLastDescriptorDetails();
+ if (lookup->IsTransition()) {
+ // Explicitly pass in the receiver map since LookupForWrite may have
+ // stored something else than the receiver in the holder.
+ Handle<Map> transition(lookup->GetTransitionTarget());
+ PropertyDetails details = lookup->GetPropertyDetails();
- if (details.type() == CALLBACKS || details.attributes() != NONE)
break;
-
+ if (details.type() != CALLBACKS && details.attributes() == NONE) {
return compiler.CompileStoreTransition(
receiver, lookup, transition, name);
}
- case NORMAL:
- if (kind() == Code::KEYED_STORE_IC) break;
- if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
- // The stub generated for the global object picks the value
directly
- // from the property cell. So the property must be directly on the
- // global object.
- Handle<GlobalObject> global = receiver->IsJSGlobalProxy()
- ? handle(GlobalObject::cast(receiver->GetPrototype()))
- : Handle<GlobalObject>::cast(receiver);
- Handle<PropertyCell> cell(global->GetPropertyCell(lookup),
isolate());
- Handle<HeapType> union_type = PropertyCell::UpdatedType(cell,
value);
- StoreGlobalStub stub(
- union_type->IsConstant(), receiver->IsJSGlobalProxy());
- Handle<Code> code = stub.GetCodeCopyFromTemplate(
- isolate(), global, cell);
- // TODO(verwaest): Move caching of these NORMAL stubs outside as
well.
- HeapObject::UpdateMapCodeCache(receiver, name, code);
- return code;
- }
- ASSERT(holder.is_identical_to(receiver));
- return isolate()->builtins()->StoreIC_Normal();
- case CALLBACKS: {
- Handle<Object> callback(lookup->GetCallbackObject(), isolate());
- if (callback->IsExecutableAccessorInfo()) {
- Handle<ExecutableAccessorInfo> info =
- Handle<ExecutableAccessorInfo>::cast(callback);
- if (v8::ToCData<Address>(info->setter()) == 0) break;
- if (!holder->HasFastProperties()) break;
- if (!info->IsCompatibleReceiver(*receiver)) break;
- return compiler.CompileStoreCallback(receiver, holder, name, info);
- } else if (callback->IsAccessorPair()) {
- Handle<Object> setter(
- Handle<AccessorPair>::cast(callback)->setter(), isolate());
- if (!setter->IsJSFunction()) break;
- if (holder->IsGlobalObject()) break;
- if (!holder->HasFastProperties()) break;
- Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
- CallOptimization call_optimization(function);
- if (call_optimization.is_simple_api_call() &&
- call_optimization.IsCompatibleReceiver(receiver, holder)) {
- return compiler.CompileStoreCallback(
- receiver, holder, name, call_optimization);
+ } else {
+ switch (lookup->type()) {
+ case FIELD:
+ return compiler.CompileStoreField(receiver, lookup, name);
+ case NORMAL:
+ if (kind() == Code::KEYED_STORE_IC) break;
+ if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
+ // The stub generated for the global object picks the value
directly
+ // from the property cell. So the property must be directly on
the
+ // global object.
+ Handle<GlobalObject> global = receiver->IsJSGlobalProxy()
+ ? handle(GlobalObject::cast(receiver->GetPrototype()))
+ : Handle<GlobalObject>::cast(receiver);
+ Handle<PropertyCell> cell(global->GetPropertyCell(lookup),
isolate());
+ Handle<HeapType> union_type = PropertyCell::UpdatedType(cell,
value);
+ StoreGlobalStub stub(
+ union_type->IsConstant(), receiver->IsJSGlobalProxy());
+ Handle<Code> code = stub.GetCodeCopyFromTemplate(
+ isolate(), global, cell);
+ // TODO(verwaest): Move caching of these NORMAL stubs outside as
well.
+ HeapObject::UpdateMapCodeCache(receiver, name, code);
+ return code;
+ }
+ ASSERT(holder.is_identical_to(receiver));
+ return isolate()->builtins()->StoreIC_Normal();
+ case CALLBACKS: {
+ Handle<Object> callback(lookup->GetCallbackObject(), isolate());
+ if (callback->IsExecutableAccessorInfo()) {
+ Handle<ExecutableAccessorInfo> info =
+ Handle<ExecutableAccessorInfo>::cast(callback);
+ if (v8::ToCData<Address>(info->setter()) == 0) break;
+ if (!holder->HasFastProperties()) break;
+ if (!info->IsCompatibleReceiver(*receiver)) break;
+ return compiler.CompileStoreCallback(receiver, holder, name,
info);
+ } else if (callback->IsAccessorPair()) {
+ Handle<Object> setter(
+ Handle<AccessorPair>::cast(callback)->setter(), isolate());
+ if (!setter->IsJSFunction()) break;
+ if (holder->IsGlobalObject()) break;
+ if (!holder->HasFastProperties()) break;
+ Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
+ CallOptimization call_optimization(function);
+ if (call_optimization.is_simple_api_call() &&
+ call_optimization.IsCompatibleReceiver(receiver, holder)) {
+ return compiler.CompileStoreCallback(
+ receiver, holder, name, call_optimization);
+ }
+ return compiler.CompileStoreViaSetter(
+ receiver, holder, name, Handle<JSFunction>::cast(setter));
+ }
+ // TODO(dcarney): Handle correctly.
+ if (callback->IsDeclaredAccessorInfo()) break;
+ ASSERT(callback->IsForeign());
+
+ // Use specialized code for setting the length of arrays with fast
+ // properties. Slow properties might indicate redefinition of the
length
+ // property.
+ if (receiver->IsJSArray() &&
+ name->Equals(isolate()->heap()->length_string()) &&
+ Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
+ receiver->HasFastProperties()) {
+ return compiler.CompileStoreArrayLength(receiver, lookup, name);
}
- return compiler.CompileStoreViaSetter(
- receiver, holder, name, Handle<JSFunction>::cast(setter));
- }
- // TODO(dcarney): Handle correctly.
- if (callback->IsDeclaredAccessorInfo()) break;
- ASSERT(callback->IsForeign());
- // Use specialized code for setting the length of arrays with fast
- // properties. Slow properties might indicate redefinition of the
length
- // property.
- if (receiver->IsJSArray() &&
- name->Equals(isolate()->heap()->length_string()) &&
- Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
- receiver->HasFastProperties()) {
- return compiler.CompileStoreArrayLength(receiver, lookup, name);
+ // No IC support for old-style native accessors.
+ break;
}
-
- // No IC support for old-style native accessors.
- break;
+ case INTERCEPTOR:
+ if (kind() == Code::KEYED_STORE_IC) break;
+ ASSERT(HasInterceptorSetter(*holder));
+ return compiler.CompileStoreInterceptor(receiver, name);
+ case CONSTANT:
+ break;
+ case NONEXISTENT:
+ case HANDLER:
+ UNREACHABLE();
+ break;
}
- case INTERCEPTOR:
- if (kind() == Code::KEYED_STORE_IC) break;
- ASSERT(HasInterceptorSetter(*holder));
- return compiler.CompileStoreInterceptor(receiver, name);
- case CONSTANT:
- break;
- case NONEXISTENT:
- case HANDLER:
- UNREACHABLE();
- break;
}
return slow_stub();
}
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Thu Apr 3 12:27:24 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h Fri Apr 4 04:49:07 2014 UTC
@@ -2629,15 +2629,9 @@
void Map::LookupTransition(JSObject* holder,
Name* name,
LookupResult* result) {
- if (HasTransitionArray()) {
- TransitionArray* transition_array = transitions();
- int number = transition_array->Search(name);
- if (number != TransitionArray::kNotFound) {
- return result->TransitionResult(
- holder, transition_array->GetTarget(number));
- }
- }
- result->NotFound();
+ int transition_index = this->SearchTransition(name);
+ if (transition_index == TransitionArray::kNotFound) return
result->NotFound();
+ result->TransitionResult(holder, this->GetTransition(transition_index));
}
@@ -4902,6 +4896,12 @@
Map* Map::GetTransition(int transition_index) {
return transitions()->GetTarget(transition_index);
}
+
+
+int Map::SearchTransition(Name* name) {
+ if (HasTransitionArray()) return transitions()->Search(name);
+ return TransitionArray::kNotFound;
+}
MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Mon Mar 17 08:31:21 2014
UTC
+++ /branches/bleeding_edge/src/objects-printer.cc Fri Apr 4 04:49:07 2014
UTC
@@ -271,7 +271,6 @@
case HANDLER: // only in lookup results, not in descriptors
case INTERCEPTOR: // only in lookup results, not in descriptors
// There are no transitions in the descriptor array.
- case TRANSITION:
case NONEXISTENT:
UNREACHABLE();
break;
@@ -428,7 +427,6 @@
case NORMAL:
case HANDLER:
case INTERCEPTOR:
- case TRANSITION:
case NONEXISTENT:
UNREACHABLE();
break;
@@ -1223,7 +1221,6 @@
case NORMAL:
case HANDLER:
case INTERCEPTOR:
- case TRANSITION:
case NONEXISTENT:
UNREACHABLE();
break;
=======================================
--- /branches/bleeding_edge/src/objects.cc Thu Apr 3 12:27:24 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc Fri Apr 4 04:49:07 2014 UTC
@@ -670,7 +670,6 @@
}
case HANDLER:
- case TRANSITION:
case NONEXISTENT:
UNREACHABLE();
}
@@ -944,7 +943,6 @@
RETURN_IF_EMPTY_HANDLE(isolate, value);
return *value;
}
- case TRANSITION:
case NONEXISTENT:
UNREACHABLE();
break;
@@ -3077,7 +3075,6 @@
return JSProxy::SetPropertyViaPrototypesWithHandler(
proxy, object, name, value, attributes, strict_mode, done);
}
- case TRANSITION:
case NONEXISTENT:
UNREACHABLE();
break;
@@ -3915,7 +3912,7 @@
// Keep the target CONSTANT if the same value is stored.
// TODO(verwaest): Also support keeping the placeholder
// (value->IsUninitialized) as constant.
- if (!value->FitsRepresentation(details.representation()) ||
+ if (!lookup->CanHoldValue(value) ||
(details.type() == CONSTANT &&
descriptors->GetValue(descriptor) != *value)) {
transition_map = Map::GeneralizeRepresentation(transition_map,
@@ -3948,7 +3945,7 @@
Handle<Name> name,
Handle<Object> value) {
Representation representation = lookup->representation();
- if (!value->FitsRepresentation(representation) ||
+ if (!lookup->CanHoldValue(value) ||
lookup->type() == CONSTANT) {
JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()),
lookup->GetDescriptorIndex(),
@@ -4091,34 +4088,35 @@
// This is a real property that is not read-only, or it is a
// transition or null descriptor and there are no setters in the
prototypes.
Handle<Object> result = value;
- switch (lookup->type()) {
- case NORMAL:
- SetNormalizedProperty(handle(lookup->holder()), lookup, value);
- break;
- case FIELD:
- SetPropertyToField(lookup, name, value);
- break;
- case CONSTANT:
- // Only replace the constant if necessary.
- if (*value == lookup->GetConstant()) return value;
- SetPropertyToField(lookup, name, value);
- break;
- case CALLBACKS: {
- Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
- return SetPropertyWithCallback(object, callback_object, name, value,
- handle(lookup->holder()),
strict_mode);
+ if (lookup->IsTransition()) {
+ result = SetPropertyUsingTransition(handle(lookup->holder()), lookup,
+ name, value, attributes);
+ } else {
+ switch (lookup->type()) {
+ case NORMAL:
+ SetNormalizedProperty(handle(lookup->holder()), lookup, value);
+ break;
+ case FIELD:
+ SetPropertyToField(lookup, name, value);
+ break;
+ case CONSTANT:
+ // Only replace the constant if necessary.
+ if (*value == lookup->GetConstant()) return value;
+ SetPropertyToField(lookup, name, value);
+ break;
+ case CALLBACKS: {
+ Handle<Object> callback_object(lookup->GetCallbackObject(),
isolate);
+ return SetPropertyWithCallback(object, callback_object, name,
value,
+ handle(lookup->holder()),
strict_mode);
+ }
+ case INTERCEPTOR:
+ result = SetPropertyWithInterceptor(
+ handle(lookup->holder()), name, value, attributes,
strict_mode);
+ break;
+ case HANDLER:
+ case NONEXISTENT:
+ UNREACHABLE();
}
- case INTERCEPTOR:
- result = SetPropertyWithInterceptor(handle(lookup->holder()), name,
value,
- attributes, strict_mode);
- break;
- case TRANSITION:
- result = SetPropertyUsingTransition(handle(lookup->holder()), lookup,
- name, value, attributes);
- break;
- case HANDLER:
- case NONEXISTENT:
- UNREACHABLE();
}
RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
@@ -4216,33 +4214,33 @@
}
// Check of IsReadOnly removed from here in clone.
- switch (lookup.type()) {
- case NORMAL:
- ReplaceSlowProperty(object, name, value, attributes);
- break;
- case FIELD:
- SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
- break;
- case CONSTANT:
- // Only replace the constant if necessary.
- if (lookup.GetAttributes() != attributes ||
- *value != lookup.GetConstant()) {
+ if (lookup.IsTransition()) {
+ Handle<Object> result = SetPropertyUsingTransition(
+ handle(lookup.holder()), &lookup, name, value, attributes);
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
+ } else {
+ switch (lookup.type()) {
+ case NORMAL:
+ ReplaceSlowProperty(object, name, value, attributes);
+ break;
+ case FIELD:
SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
- }
- break;
- case CALLBACKS:
- ConvertAndSetLocalProperty(&lookup, name, value, attributes);
- break;
- case TRANSITION: {
- Handle<Object> result = SetPropertyUsingTransition(
- handle(lookup.holder()), &lookup, name, value, attributes);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
- break;
+ break;
+ case CONSTANT:
+ // Only replace the constant if necessary.
+ if (lookup.GetAttributes() != attributes ||
+ *value != lookup.GetConstant()) {
+ SetPropertyToFieldWithAttributes(&lookup, name, value,
attributes);
+ }
+ break;
+ case CALLBACKS:
+ ConvertAndSetLocalProperty(&lookup, name, value, attributes);
+ break;
+ case NONEXISTENT:
+ case HANDLER:
+ case INTERCEPTOR:
+ UNREACHABLE();
}
- case NONEXISTENT:
- case HANDLER:
- case INTERCEPTOR:
- UNREACHABLE();
}
if (is_observed) {
@@ -4386,7 +4384,6 @@
Handle<JSObject>::cast(receiver),
name,
continue_search);
- case TRANSITION:
case NONEXISTENT:
UNREACHABLE();
}
@@ -4629,7 +4626,6 @@
break;
case HANDLER:
case NORMAL:
- case TRANSITION:
case NONEXISTENT:
UNREACHABLE();
break;
@@ -5579,11 +5575,11 @@
}
}
- LookupResult result(isolate);
- Handle<Map> old_map(object->map());
- old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(),
&result);
- if (result.IsTransition()) {
- Handle<Map> transition_map(result.GetTransitionTarget());
+ Handle<Map> old_map(object->map(), isolate);
+ int transition_index = old_map->SearchTransition(
+ isolate->heap()->frozen_symbol());
+ if (transition_index != TransitionArray::kNotFound) {
+ Handle<Map> transition_map(old_map->GetTransition(transition_index));
ASSERT(transition_map->has_dictionary_elements());
ASSERT(transition_map->is_frozen());
ASSERT(!transition_map->is_extensible());
@@ -5635,22 +5631,19 @@
void JSObject::SetObserved(Handle<JSObject> object) {
- ASSERT(!object->map()->is_observed());
Isolate* isolate = object->GetIsolate();
-
- LookupResult result(isolate);
- object->map()->LookupTransition(*object,
- isolate->heap()->observed_symbol(),
- &result);
-
Handle<Map> new_map;
- if (result.IsTransition()) {
- new_map = handle(result.GetTransitionTarget());
+ Handle<Map> old_map(object->map(), isolate);
+ ASSERT(!old_map->is_observed());
+ int transition_index = old_map->SearchTransition(
+ isolate->heap()->observed_symbol());
+ if (transition_index != TransitionArray::kNotFound) {
+ new_map = handle(old_map->GetTransition(transition_index), isolate);
ASSERT(new_map->is_observed());
- } else if (object->map()->CanHaveMoreTransitions()) {
- new_map = Map::CopyForObserved(handle(object->map()));
+ } else if (old_map->CanHaveMoreTransitions()) {
+ new_map = Map::CopyForObserved(old_map);
} else {
- new_map = Map::Copy(handle(object->map()));
+ new_map = Map::Copy(old_map);
new_map->set_is_observed();
}
JSObject::MigrateToMap(object, new_map);
=======================================
--- /branches/bleeding_edge/src/objects.h Thu Apr 3 12:27:24 2014 UTC
+++ /branches/bleeding_edge/src/objects.h Fri Apr 4 04:49:07 2014 UTC
@@ -6001,6 +6001,7 @@
Map* transitioned_map);
inline void SetTransition(int transition_index, Map* target);
inline Map* GetTransition(int transition_index);
+ inline int SearchTransition(Name* name);
static Handle<TransitionArray> AddTransition(Handle<Map> map,
Handle<Name> key,
=======================================
--- /branches/bleeding_edge/src/property-details.h Wed Mar 12 10:11:38 2014
UTC
+++ /branches/bleeding_edge/src/property-details.h Fri Apr 4 04:49:07 2014
UTC
@@ -77,9 +77,8 @@
// Only in lookup results, not in descriptors.
HANDLER = 4,
INTERCEPTOR = 5,
- TRANSITION = 6,
// Only used as a marker in LookupResult.
- NONEXISTENT = 7
+ NONEXISTENT = 6
};
=======================================
--- /branches/bleeding_edge/src/property.cc Tue Apr 1 11:16:13 2014 UTC
+++ /branches/bleeding_edge/src/property.cc Fri Apr 4 04:49:07 2014 UTC
@@ -29,59 +29,61 @@
PrintF(out, "LookupResult:\n");
PrintF(out, " -cacheable = %s\n", IsCacheable() ? "true" : "false");
PrintF(out, " -attributes = %x\n", GetAttributes());
- switch (type()) {
- case NORMAL:
- PrintF(out, " -type = normal\n");
- PrintF(out, " -entry = %d", GetDictionaryEntry());
- break;
- case CONSTANT:
- PrintF(out, " -type = constant\n");
- PrintF(out, " -value:\n");
- GetConstant()->Print(out);
- PrintF(out, "\n");
- break;
- case FIELD:
- PrintF(out, " -type = field\n");
- PrintF(out, " -index = %d", GetFieldIndex().field_index());
- PrintF(out, "\n");
- break;
- case CALLBACKS:
- PrintF(out, " -type = call backs\n");
- PrintF(out, " -callback object:\n");
- GetCallbackObject()->Print(out);
- break;
- case HANDLER:
- PrintF(out, " -type = lookup proxy\n");
- break;
- case INTERCEPTOR:
- PrintF(out, " -type = lookup interceptor\n");
- break;
- case TRANSITION:
- switch (GetTransitionDetails().type()) {
- case FIELD:
- PrintF(out, " -type = map transition\n");
- PrintF(out, " -map:\n");
- GetTransitionTarget()->Print(out);
- PrintF(out, "\n");
- return;
- case CONSTANT:
- PrintF(out, " -type = constant property transition\n");
- PrintF(out, " -map:\n");
- GetTransitionTarget()->Print(out);
- PrintF(out, "\n");
- return;
- case CALLBACKS:
- PrintF(out, " -type = callbacks transition\n");
- PrintF(out, " -callback object:\n");
- GetCallbackObject()->Print(out);
- return;
- default:
- UNREACHABLE();
- return;
- }
- case NONEXISTENT:
- UNREACHABLE();
- break;
+ if (IsTransition()) {
+ switch (type()) {
+ case FIELD:
+ PrintF(out, " -type = map transition\n");
+ PrintF(out, " -map:\n");
+ GetTransitionTarget()->Print(out);
+ PrintF(out, "\n");
+ break;
+ case CONSTANT:
+ PrintF(out, " -type = constant property transition\n");
+ PrintF(out, " -map:\n");
+ GetTransitionTarget()->Print(out);
+ PrintF(out, "\n");
+ break;
+ case CALLBACKS:
+ PrintF(out, " -type = callbacks transition\n");
+ PrintF(out, " -callback object:\n");
+ GetCallbackObject()->Print(out);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ } else {
+ switch (type()) {
+ case NORMAL:
+ PrintF(out, " -type = normal\n");
+ PrintF(out, " -entry = %d", GetDictionaryEntry());
+ break;
+ case CONSTANT:
+ PrintF(out, " -type = constant\n");
+ PrintF(out, " -value:\n");
+ GetConstant()->Print(out);
+ PrintF(out, "\n");
+ break;
+ case FIELD:
+ PrintF(out, " -type = field\n");
+ PrintF(out, " -index = %d", GetFieldIndex().field_index());
+ PrintF(out, "\n");
+ break;
+ case CALLBACKS:
+ PrintF(out, " -type = call backs\n");
+ PrintF(out, " -callback object:\n");
+ GetCallbackObject()->Print(out);
+ break;
+ case HANDLER:
+ PrintF(out, " -type = lookup proxy\n");
+ break;
+ case INTERCEPTOR:
+ PrintF(out, " -type = lookup interceptor\n");
+ break;
+ case NONEXISTENT:
+ UNREACHABLE();
+ break;
+ }
}
}
=======================================
--- /branches/bleeding_edge/src/property.h Tue Apr 1 11:16:13 2014 UTC
+++ /branches/bleeding_edge/src/property.h Fri Apr 4 04:49:07 2014 UTC
@@ -180,16 +180,15 @@
bool CanHoldValue(Handle<Object> value) {
if (IsNormal()) return true;
- ASSERT(!IsTransition());
return value->FitsRepresentation(details_.representation());
}
void TransitionResult(JSObject* holder, Map* target) {
lookup_type_ = TRANSITION_TYPE;
- details_ = PropertyDetails(NONE, TRANSITION, Representation::None());
+ number_ = target->LastAdded();
+ details_ = target->instance_descriptors()->GetDetails(number_);
holder_ = holder;
transition_ = target;
- number_ = 0xAAAA;
}
void DictionaryResult(JSObject* holder, int entry) {
@@ -239,20 +238,17 @@
Representation representation() const {
ASSERT(IsFound());
- ASSERT(!IsTransition());
ASSERT(details_.type() != NONEXISTENT);
return details_.representation();
}
PropertyAttributes GetAttributes() const {
- ASSERT(!IsTransition());
ASSERT(IsFound());
ASSERT(details_.type() != NONEXISTENT);
return details_.attributes();
}
PropertyDetails GetPropertyDetails() const {
- ASSERT(!IsTransition());
return details_;
}
@@ -264,38 +260,40 @@
// Property callbacks does not include transitions to callbacks.
bool IsPropertyCallbacks() const {
ASSERT(!(details_.type() == CALLBACKS && !IsFound()));
- return details_.type() == CALLBACKS;
+ return !IsTransition() && details_.type() == CALLBACKS;
}
bool IsReadOnly() const {
ASSERT(IsFound());
- ASSERT(!IsTransition());
ASSERT(details_.type() != NONEXISTENT);
return details_.IsReadOnly();
}
bool IsField() const {
ASSERT(!(details_.type() == FIELD && !IsFound()));
- return details_.type() == FIELD;
+ return IsDescriptorOrDictionary() && type() == FIELD;
}
bool IsNormal() const {
ASSERT(!(details_.type() == NORMAL && !IsFound()));
- return details_.type() == NORMAL;
+ return IsDescriptorOrDictionary() && type() == NORMAL;
}
bool IsConstant() const {
ASSERT(!(details_.type() == CONSTANT && !IsFound()));
- return details_.type() == CONSTANT;
+ return IsDescriptorOrDictionary() && type() == CONSTANT;
}
bool IsConstantFunction() const {
- return IsConstant() && GetValue()->IsJSFunction();
+ return IsConstant() && GetConstant()->IsJSFunction();
}
bool IsDontDelete() const { return details_.IsDontDelete(); }
bool IsDontEnum() const { return details_.IsDontEnum(); }
bool IsFound() const { return lookup_type_ != NOT_FOUND; }
+ bool IsDescriptorOrDictionary() const {
+ return lookup_type_ == DESCRIPTOR_TYPE || lookup_type_ ==
DICTIONARY_TYPE;
+ }
bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
bool IsHandler() const { return lookup_type_ == HANDLER_TYPE; }
bool IsInterceptor() const { return lookup_type_ == INTERCEPTOR_TYPE; }
@@ -306,20 +304,30 @@
}
bool IsDataProperty() const {
- switch (type()) {
- case FIELD:
- case NORMAL:
- case CONSTANT:
- return true;
- case CALLBACKS: {
- Object* callback = GetCallbackObject();
- return callback->IsAccessorInfo() || callback->IsForeign();
- }
- case HANDLER:
- case INTERCEPTOR:
- case TRANSITION:
- case NONEXISTENT:
+ switch (lookup_type_) {
+ case NOT_FOUND:
+ case TRANSITION_TYPE:
+ case HANDLER_TYPE:
+ case INTERCEPTOR_TYPE:
return false;
+
+ case DESCRIPTOR_TYPE:
+ case DICTIONARY_TYPE:
+ switch (type()) {
+ case FIELD:
+ case NORMAL:
+ case CONSTANT:
+ return true;
+ case CALLBACKS: {
+ Object* callback = GetCallbackObject();
+ return callback->IsAccessorInfo() || callback->IsForeign();
+ }
+ case HANDLER:
+ case INTERCEPTOR:
+ case NONEXISTENT:
+ UNREACHABLE();
+ return false;
+ }
}
UNREACHABLE();
return false;
@@ -329,45 +337,52 @@
void DisallowCaching() { cacheable_ = false; }
Object* GetLazyValue() const {
- switch (type()) {
- case FIELD:
- return holder()->RawFastPropertyAt(GetFieldIndex().field_index());
- case NORMAL: {
- Object* value;
- value =
holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
- if (holder()->IsGlobalObject()) {
- value = PropertyCell::cast(value)->value();
+ switch (lookup_type_) {
+ case NOT_FOUND:
+ case TRANSITION_TYPE:
+ case HANDLER_TYPE:
+ case INTERCEPTOR_TYPE:
+ return isolate()->heap()->the_hole_value();
+
+ case DESCRIPTOR_TYPE:
+ case DICTIONARY_TYPE:
+ switch (type()) {
+ case FIELD:
+ return
holder()->RawFastPropertyAt(GetFieldIndex().field_index());
+ case NORMAL: {
+ Object* value = holder()->property_dictionary()->ValueAt(
+ GetDictionaryEntry());
+ if (holder()->IsGlobalObject()) {
+ value = PropertyCell::cast(value)->value();
+ }
+ return value;
+ }
+ case CONSTANT:
+ return GetConstant();
+ case CALLBACKS:
+ return isolate()->heap()->the_hole_value();
+ case HANDLER:
+ case INTERCEPTOR:
+ case NONEXISTENT:
+ UNREACHABLE();
+ return NULL;
}
- return value;
- }
- case CONSTANT:
- return GetConstant();
- case CALLBACKS:
- case HANDLER:
- case INTERCEPTOR:
- case TRANSITION:
- case NONEXISTENT:
- return isolate()->heap()->the_hole_value();
}
UNREACHABLE();
return NULL;
}
Map* GetTransitionTarget() const {
+ ASSERT(IsTransition());
return transition_;
}
-
- PropertyDetails GetTransitionDetails() const {
- ASSERT(IsTransition());
- return transition_->GetLastDescriptorDetails();
- }
bool IsTransitionToField() const {
- return IsTransition() && GetTransitionDetails().type() == FIELD;
+ return IsTransition() && details_.type() == FIELD;
}
bool IsTransitionToConstant() const {
- return IsTransition() && GetTransitionDetails().type() == CONSTANT;
+ return IsTransition() && details_.type() == CONSTANT;
}
int GetDescriptorIndex() const {
@@ -376,7 +391,8 @@
}
PropertyIndex GetFieldIndex() const {
- ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
+ ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
+ lookup_type_ == TRANSITION_TYPE);
return
PropertyIndex::NewFieldIndex(GetFieldIndexFromMap(holder()->map()));
}
@@ -409,7 +425,8 @@
}
Object* GetCallbackObject() const {
- ASSERT(type() == CALLBACKS && !IsTransition());
+ ASSERT(!IsTransition());
+ ASSERT(type() == CALLBACKS);
return GetValue();
}
@@ -420,6 +437,8 @@
Object* GetValue() const {
if (lookup_type_ == DESCRIPTOR_TYPE) {
return GetValueFromMap(holder()->map());
+ } else if (lookup_type_ == TRANSITION_TYPE) {
+ return GetValueFromMap(transition_);
}
// In the dictionary case, the data is held in the value field.
ASSERT(lookup_type_ == DICTIONARY_TYPE);
@@ -427,13 +446,15 @@
}
Object* GetValueFromMap(Map* map) const {
- ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
+ ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
+ lookup_type_ == TRANSITION_TYPE);
ASSERT(number_ < map->NumberOfOwnDescriptors());
return map->instance_descriptors()->GetValue(number_);
}
int GetFieldIndexFromMap(Map* map) const {
- ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
+ ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
+ lookup_type_ == TRANSITION_TYPE);
ASSERT(number_ < map->NumberOfOwnDescriptors());
return map->instance_descriptors()->GetFieldIndex(number_);
}
=======================================
--- /branches/bleeding_edge/src/runtime.cc Thu Apr 3 14:25:59 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Fri Apr 4 04:49:07 2014 UTC
@@ -5217,23 +5217,23 @@
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
LookupResult lookup(isolate);
object->LookupRealNamedProperty(*key, &lookup);
- if (!lookup.IsFound()) return isolate->heap()->undefined_value();
- switch (lookup.type()) {
- case NORMAL:
- return lookup.holder()->GetNormalizedProperty(&lookup);
- case FIELD:
- return lookup.holder()->FastPropertyAt(
- lookup.representation(),
- lookup.GetFieldIndex().field_index());
- case CONSTANT:
- return lookup.GetConstant();
- case CALLBACKS:
- case HANDLER:
- case INTERCEPTOR:
- case TRANSITION:
- return isolate->heap()->undefined_value();
- case NONEXISTENT:
- UNREACHABLE();
+ if (lookup.IsFound() && !lookup.IsTransition()) {
+ switch (lookup.type()) {
+ case NORMAL:
+ return lookup.holder()->GetNormalizedProperty(&lookup);
+ case FIELD:
+ return lookup.holder()->FastPropertyAt(
+ lookup.representation(),
+ lookup.GetFieldIndex().field_index());
+ case CONSTANT:
+ return lookup.GetConstant();
+ case CALLBACKS:
+ case HANDLER:
+ case INTERCEPTOR:
+ break;
+ case NONEXISTENT:
+ UNREACHABLE();
+ }
}
return isolate->heap()->undefined_value();
}
@@ -10783,6 +10783,7 @@
LookupResult* result,
bool* caught_exception) {
Object* value;
+ if (result->IsTransition()) return heap->undefined_value();
switch (result->type()) {
case NORMAL:
value = result->holder()->GetNormalizedProperty(result);
@@ -10826,7 +10827,6 @@
}
}
case INTERCEPTOR:
- case TRANSITION:
return heap->undefined_value();
case HANDLER:
case NONEXISTENT:
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.