Commit 621bdd64 authored by verwaest's avatar verwaest Committed by Commit bot

[runtime] Fix integer indexed property handling

This includes 2 fixes:
1) We didn't properly advance the holder when checking whether
Receiver==Holder, so we'd inadvertently block loading the property if
the first property we find is on the typed array.
2) Reflect.get may cause any object on the prototype chain of the holder
to be the receiver; so we need to recheck for this special state for
each object we perform lookup on.

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

Cr-Commit-Position: refs/heads/master@{#33689}
parent 72d768d1
......@@ -1978,7 +1978,7 @@ BUILTIN(ReflectGet) {
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::GetPropertyOrElement(
Handle<JSReceiver>::cast(target), name, receiver));
receiver, name, Handle<JSReceiver>::cast(target)));
return *result;
}
......
......@@ -390,23 +390,19 @@ void LookupIterator::TransitionToAccessorPair(Handle<Object> pair,
bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const {
DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY);
return InternalHolderIsReceiverOrHiddenPrototype();
}
bool LookupIterator::InternalHolderIsReceiverOrHiddenPrototype() const {
// Optimization that only works if configuration_ is not mutable.
if (!check_prototype_chain()) return true;
DisallowHeapAllocation no_gc;
if (!receiver_->IsJSReceiver()) return false;
JSReceiver* current = JSReceiver::cast(*receiver_);
JSReceiver* holder = *holder_;
if (current == holder) return true;
if (!holder->map()->is_hidden_prototype()) return false;
JSReceiver* object = *holder_;
if (current == object) return true;
if (!object->map()->is_hidden_prototype()) return false;
// JSProxy do not occur as hidden prototypes.
if (current->IsJSProxy()) return false;
PrototypeIterator iter(isolate(), current);
while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
if (iter.GetCurrent<JSReceiver>() == holder) return true;
if (iter.GetCurrent<JSReceiver>() == object) return true;
iter.Advance();
}
return false;
......@@ -523,26 +519,14 @@ void LookupIterator::WriteDataValue(Handle<Object> value) {
bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) {
DCHECK(exotic_index_state_ != ExoticIndexState::kNotExotic);
if (exotic_index_state_ == ExoticIndexState::kExotic) return true;
if (!InternalHolderIsReceiverOrHiddenPrototype()) {
exotic_index_state_ = ExoticIndexState::kNotExotic;
return false;
}
DCHECK(exotic_index_state_ == ExoticIndexState::kUninitialized);
bool result = false;
// Compute and cache result.
if (IsElement()) {
result = index_ >= JSTypedArray::cast(holder)->length_value();
} else if (name()->IsString()) {
Handle<String> name_string = Handle<String>::cast(name());
if (name_string->length() != 0) {
result = IsSpecialIndex(isolate_->unicode_cache(), *name_string);
}
}
exotic_index_state_ =
result ? ExoticIndexState::kExotic : ExoticIndexState::kNotExotic;
return result;
DCHECK(!IsElement());
if (!name_->IsString()) return false;
if (*receiver_ != holder) return false;
Handle<String> name_string = Handle<String>::cast(name_);
if (name_string->length() == 0) return false;
return IsSpecialIndex(isolate_->unicode_cache(), *name_string);
}
......@@ -629,14 +613,13 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* const map,
FixedArrayBase* backing_store = js_object->elements();
number_ = accessor->GetEntryForIndex(js_object, backing_store, index_);
if (number_ == kMaxUInt32) {
if (*receiver_ == Object::cast(holder) && holder->IsJSTypedArray()) {
if (*receiver_ == holder && holder->IsJSTypedArray()) {
return INTEGER_INDEXED_EXOTIC;
}
return NOT_FOUND;
}
property_details_ = accessor->GetDetails(js_object, number_);
} else if (exotic_index_state_ != ExoticIndexState::kNotExotic &&
holder->IsJSTypedArray() && IsIntegerIndexedExotic(holder)) {
} else if (holder->IsJSTypedArray() && IsIntegerIndexedExotic(holder)) {
return INTEGER_INDEXED_EXOTIC;
} else if (!map->is_dictionary_map()) {
DescriptorArray* descriptors = map->instance_descriptors();
......
......@@ -48,7 +48,6 @@ class LookupIterator final BASE_EMBEDDED {
Configuration configuration = DEFAULT)
: configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
exotic_index_state_(ExoticIndexState::kUninitialized),
interceptor_state_(InterceptorState::kUninitialized),
property_details_(PropertyDetails::Empty()),
isolate_(name->GetIsolate()),
......@@ -72,7 +71,6 @@ class LookupIterator final BASE_EMBEDDED {
Configuration configuration = DEFAULT)
: configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
exotic_index_state_(ExoticIndexState::kUninitialized),
interceptor_state_(InterceptorState::kUninitialized),
property_details_(PropertyDetails::Empty()),
isolate_(name->GetIsolate()),
......@@ -95,7 +93,6 @@ class LookupIterator final BASE_EMBEDDED {
Configuration configuration = DEFAULT)
: configuration_(configuration),
state_(NOT_FOUND),
exotic_index_state_(ExoticIndexState::kUninitialized),
interceptor_state_(InterceptorState::kUninitialized),
property_details_(PropertyDetails::Empty()),
isolate_(isolate),
......@@ -116,7 +113,6 @@ class LookupIterator final BASE_EMBEDDED {
Configuration configuration = DEFAULT)
: configuration_(configuration),
state_(NOT_FOUND),
exotic_index_state_(ExoticIndexState::kUninitialized),
interceptor_state_(InterceptorState::kUninitialized),
property_details_(PropertyDetails::Empty()),
isolate_(isolate),
......@@ -280,7 +276,6 @@ class LookupIterator final BASE_EMBEDDED {
void ReloadPropertyInformation();
inline bool SkipInterceptor(JSObject* holder);
bool HasInterceptor(Map* map) const;
bool InternalHolderIsReceiverOrHiddenPrototype() const;
inline InterceptorInfo* GetInterceptor(JSObject* holder) const {
if (IsElement()) return holder->GetIndexedInterceptor();
return holder->GetNamedInterceptor();
......@@ -320,7 +315,6 @@ class LookupIterator final BASE_EMBEDDED {
return GetRootForNonJSReceiver(isolate, receiver, index);
}
enum class ExoticIndexState { kUninitialized, kNotExotic, kExotic };
inline bool IsIntegerIndexedExotic(JSReceiver* holder);
// If configuration_ becomes mutable, update
......@@ -328,7 +322,6 @@ class LookupIterator final BASE_EMBEDDED {
const Configuration configuration_;
State state_;
bool has_property_;
ExoticIndexState exotic_index_state_;
InterceptorState interceptor_state_;
PropertyDetails property_details_;
Isolate* const isolate_;
......
......@@ -7084,10 +7084,9 @@ MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
return GetProperty(&it, language_mode);
}
MaybeHandle<Object> Object::GetPropertyOrElement(Handle<JSReceiver> holder,
MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver,
Handle<Name> name,
Handle<Object> receiver,
Handle<JSReceiver> holder,
LanguageMode language_mode) {
LookupIterator it = LookupIterator::PropertyOrElement(
name->GetIsolate(), receiver, name, holder);
......
......@@ -1276,7 +1276,7 @@ class Object {
Handle<Object> object, Handle<Name> name,
LanguageMode language_mode = SLOPPY);
MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
Handle<JSReceiver> holder, Handle<Name> name, Handle<Object> receiver,
Handle<Object> receiver, Handle<Name> name, Handle<JSReceiver> holder,
LanguageMode language_mode = SLOPPY);
MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
Isolate* isolate, Handle<Object> object, const char* key,
......
// Copyright 2016 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.
var o = {__proto__:new Int32Array(100)};
Object.prototype[1.3] = 10;
assertEquals(10, o[1.3]);
var o = new Int32Array(100);
var o2 = new Int32Array(200);
o.__proto__ = o2;
assertEquals(undefined, Reflect.get(o, 1.3, o2));
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