Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 9d6be50535d46f9f01a7a531c8249b56fb28bf2e..6e67b5a812bd56382693322435a6b0940dc87ad9 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -108,6 +108,7 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it) { |
for (; it->IsFound(); it->Next()) { |
switch (it->state()) { |
case LookupIterator::NOT_FOUND: |
+ case LookupIterator::TRANSITION: |
UNREACHABLE(); |
case LookupIterator::JSPROXY: |
return JSProxy::GetPropertyWithHandler(it->GetHolder<JSProxy>(), |
@@ -150,9 +151,10 @@ Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object, |
Handle<Object> JSObject::GetDataProperty(LookupIterator* it) { |
for (; it->IsFound(); it->Next()) { |
switch (it->state()) { |
- case LookupIterator::NOT_FOUND: |
case LookupIterator::ACCESS_CHECK: |
case LookupIterator::INTERCEPTOR: |
+ case LookupIterator::NOT_FOUND: |
+ case LookupIterator::TRANSITION: |
UNREACHABLE(); |
case LookupIterator::JSPROXY: |
it->NotFound(); |
@@ -2714,6 +2716,7 @@ MaybeHandle<Map> Map::TryUpdate(Handle<Map> map) { |
// static |
Handle<Map> Map::Update(Handle<Map> map) { |
+ if (!map->is_deprecated()) return map; |
return GeneralizeRepresentation(map, 0, Representation::None(), |
HeapType::None(map->GetIsolate()), |
ALLOW_AS_CONSTANT); |
@@ -2894,11 +2897,25 @@ MaybeHandle<Object> Object::SetProperty(LookupIterator* it, |
} |
done = true; |
break; |
+ |
+ case LookupIterator::TRANSITION: |
+ done = true; |
+ break; |
} |
if (done) break; |
} |
+ // If the receiver is the JSGlobalObject, the store was contextual. In case |
+ // the property did not exist yet on the global object itself, we have to |
+ // throw a reference error in strict mode. |
+ if (it->GetReceiver()->IsJSGlobalObject() && strict_mode == STRICT) { |
+ Handle<Object> args[1] = {it->name()}; |
+ Handle<Object> error = it->isolate()->factory()->NewReferenceError( |
+ "not_defined", HandleVector(args, 1)); |
+ return it->isolate()->Throw<Object>(error); |
+ } |
+ |
return AddDataProperty(it, value, NONE, strict_mode, store_mode); |
} |
@@ -2960,20 +2977,17 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
// TODO(verwaest): Throw a TypeError with a more specific message. |
return WriteToReadOnlyProperty(it, value, strict_mode); |
} |
- Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
+ |
+ Handle<JSObject> receiver = it->GetStoreTarget(); |
// If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) |
// instead. If the prototype is Null, the proxy is detached. |
- if (receiver->IsJSGlobalProxy()) { |
- // Trying to assign to a detached proxy. |
- PrototypeIterator iter(it->isolate(), receiver); |
- if (iter.IsAtEnd()) return value; |
- receiver = |
- Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); |
- } |
+ if (receiver->IsJSGlobalProxy()) return value; |
- if (!it->name().is_identical_to(it->isolate()->factory()->hidden_string()) && |
- !receiver->map()->is_extensible()) { |
+ // Possibly migrate to the most up-to-date map that will be able to store |
+ // |value| under it->name() with |attributes|. |
+ it->PrepareTransitionToDataProperty(value, attributes, store_mode); |
+ if (it->state() != LookupIterator::TRANSITION) { |
if (strict_mode == SLOPPY) return value; |
Handle<Object> args[1] = {it->name()}; |
@@ -2981,10 +2995,7 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, |
"object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); |
return it->isolate()->Throw<Object>(error); |
} |
- |
- // Possibly migrate to the most up-to-date map that will be able to store |
- // |value| under it->name() with |attributes|. |
- it->TransitionToDataProperty(value, attributes, store_mode); |
+ it->ApplyTransitionToDataProperty(); |
// TODO(verwaest): Encapsulate dictionary handling better. |
if (receiver->map()->is_dictionary_map()) { |
@@ -3379,46 +3390,6 @@ Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, |
} |
-void JSObject::LookupOwnRealNamedProperty(Handle<Name> name, |
- LookupResult* result) { |
- DisallowHeapAllocation no_gc; |
- if (IsJSGlobalProxy()) { |
- PrototypeIterator iter(GetIsolate(), this); |
- if (iter.IsAtEnd()) return result->NotFound(); |
- DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
- return JSObject::cast(iter.GetCurrent()) |
- ->LookupOwnRealNamedProperty(name, result); |
- } |
- |
- if (HasFastProperties()) { |
- map()->LookupDescriptor(this, *name, result); |
- // A property or a map transition was found. We return all of these result |
- // types because LookupOwnRealNamedProperty is used when setting |
- // properties where map transitions are handled. |
- DCHECK(!result->IsFound() || |
- (result->holder() == this && result->IsFastPropertyType())); |
- return; |
- } |
- |
- int entry = property_dictionary()->FindEntry(name); |
- if (entry != NameDictionary::kNotFound) { |
- Object* value = property_dictionary()->ValueAt(entry); |
- if (IsGlobalObject()) { |
- PropertyDetails d = property_dictionary()->DetailsAt(entry); |
- if (d.IsDeleted() || PropertyCell::cast(value)->value()->IsTheHole()) { |
- result->NotFound(); |
- return; |
- } |
- value = PropertyCell::cast(value)->value(); |
- } |
- result->DictionaryResult(this, entry); |
- return; |
- } |
- |
- result->NotFound(); |
-} |
- |
- |
Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, |
Handle<Name> name) { |
Isolate* isolate = proxy->GetIsolate(); |
@@ -3847,9 +3818,10 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( |
*name != it.isolate()->heap()->hidden_string(); |
for (; it.IsFound(); it.Next()) { |
switch (it.state()) { |
- case LookupIterator::NOT_FOUND: |
- case LookupIterator::JSPROXY: |
case LookupIterator::INTERCEPTOR: |
+ case LookupIterator::JSPROXY: |
+ case LookupIterator::NOT_FOUND: |
+ case LookupIterator::TRANSITION: |
UNREACHABLE(); |
case LookupIterator::ACCESS_CHECK: |
@@ -4022,6 +3994,7 @@ Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes( |
for (; it->IsFound(); it->Next()) { |
switch (it->state()) { |
case LookupIterator::NOT_FOUND: |
+ case LookupIterator::TRANSITION: |
UNREACHABLE(); |
case LookupIterator::JSPROXY: |
return JSProxy::GetPropertyAttributesWithHandler( |
@@ -4961,8 +4934,9 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
for (; it.IsFound(); it.Next()) { |
switch (it.state()) { |
- case LookupIterator::NOT_FOUND: |
case LookupIterator::JSPROXY: |
+ case LookupIterator::NOT_FOUND: |
+ case LookupIterator::TRANSITION: |
UNREACHABLE(); |
case LookupIterator::ACCESS_CHECK: |
if (it.HasAccess(v8::ACCESS_DELETE)) break; |
@@ -5710,58 +5684,6 @@ int Map::NextFreePropertyIndex() { |
} |
-void JSReceiver::LookupOwn(Handle<Name> name, LookupResult* result) { |
- DisallowHeapAllocation no_gc; |
- DCHECK(name->IsName()); |
- |
- if (IsJSGlobalProxy()) { |
- PrototypeIterator iter(GetIsolate(), this); |
- if (iter.IsAtEnd()) return result->NotFound(); |
- DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
- return JSReceiver::cast(iter.GetCurrent())->LookupOwn(name, result); |
- } |
- |
- if (IsJSProxy()) { |
- result->HandlerResult(JSProxy::cast(this)); |
- return; |
- } |
- |
- // Do not use inline caching if the object is a non-global object |
- // that requires access checks. |
- if (IsAccessCheckNeeded()) { |
- result->DisallowCaching(); |
- } |
- |
- JSObject* js_object = JSObject::cast(this); |
- |
- // Check for lookup interceptor except when bootstrapping. |
- if (js_object->HasNamedInterceptor() && |
- !GetIsolate()->bootstrapper()->IsActive()) { |
- result->InterceptorResult(js_object); |
- return; |
- } |
- |
- js_object->LookupOwnRealNamedProperty(name, result); |
-} |
- |
- |
-void JSReceiver::Lookup(Handle<Name> name, LookupResult* result) { |
- DisallowHeapAllocation no_gc; |
- // Ecma-262 3rd 8.6.2.4 |
- for (PrototypeIterator iter(GetIsolate(), this, |
- PrototypeIterator::START_AT_RECEIVER); |
- !iter.IsAtEnd(); iter.Advance()) { |
- JSReceiver::cast(iter.GetCurrent())->LookupOwn(name, result); |
- if (result->IsFound()) return; |
- if (name->IsOwn()) { |
- result->NotFound(); |
- return; |
- } |
- } |
- result->NotFound(); |
-} |
- |
- |
static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { |
int len = array->length(); |
for (int i = 0; i < len; i++) { |
@@ -6397,8 +6319,9 @@ MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object, |
LookupIterator::CHECK_DERIVED_SKIP_INTERCEPTOR); |
for (; it.IsFound(); it.Next()) { |
switch (it.state()) { |
- case LookupIterator::NOT_FOUND: |
case LookupIterator::INTERCEPTOR: |
+ case LookupIterator::NOT_FOUND: |
+ case LookupIterator::TRANSITION: |
UNREACHABLE(); |
case LookupIterator::ACCESS_CHECK: |
@@ -6835,7 +6758,7 @@ Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, |
if (map->is_dictionary_map()) return map; |
// Migrate to the newest map before storing the property. |
- if (map->is_deprecated()) map = Update(map); |
+ map = Update(map); |
Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
@@ -6857,8 +6780,8 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
// Dictionary maps can always have additional data properties. |
if (map->is_dictionary_map()) return map; |
- // Migrate to the newest map before transitioning to the new property. |
- if (map->is_deprecated()) map = Update(map); |
+ // Migrate to the newest map before storing the property. |
+ map = Update(map); |
int index = map->SearchTransition(*name); |
if (index != TransitionArray::kNotFound) { |
@@ -6868,9 +6791,7 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
// TODO(verwaest): Handle attributes better. |
DescriptorArray* descriptors = transition->instance_descriptors(); |
if (descriptors->GetDetails(descriptor).attributes() != attributes) { |
- return CopyGeneralizeAllRepresentations(transition, descriptor, |
- FORCE_FIELD, attributes, |
- "attributes mismatch"); |
+ return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES); |
} |
return Map::PrepareForDataProperty(transition, descriptor, value); |
@@ -6925,7 +6846,7 @@ Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map, |
} |
// Migrate to the newest map before transitioning to the new property. |
- if (map->is_deprecated()) map = Update(map); |
+ map = Update(map); |
PropertyNormalizationMode mode = map->is_prototype_map() |
? KEEP_INOBJECT_PROPERTIES |