diff options
Diffstat (limited to 'deps/v8/src/lookup.cc')
-rw-r--r-- | deps/v8/src/lookup.cc | 183 |
1 files changed, 171 insertions, 12 deletions
diff --git a/deps/v8/src/lookup.cc b/deps/v8/src/lookup.cc index 809c35e4a5..f60563b19e 100644 --- a/deps/v8/src/lookup.cc +++ b/deps/v8/src/lookup.cc @@ -6,13 +6,45 @@ #include "src/bootstrapper.h" #include "src/deoptimizer.h" +#include "src/elements.h" #include "src/isolate-inl.h" -#include "src/lookup-inl.h" namespace v8 { namespace internal { +// static +LookupIterator LookupIterator::PropertyOrElement(Isolate* isolate, + Handle<Object> receiver, + Handle<Object> key, + bool* success, + Configuration configuration) { + uint32_t index = 0; + if (key->ToArrayIndex(&index)) { + *success = true; + return LookupIterator(isolate, receiver, index, configuration); + } + + Handle<Name> name; + *success = Object::ToName(isolate, key).ToHandle(&name); + if (!*success) { + DCHECK(isolate->has_pending_exception()); + // Return an unusable dummy. + return LookupIterator(receiver, isolate->factory()->empty_string()); + } + + if (name->AsArrayIndex(&index)) { + LookupIterator it(isolate, receiver, index, configuration); + // Here we try to avoid having to rebuild the string later + // by storing it on the indexed LookupIterator. + it.name_ = name; + return it; + } + + return LookupIterator(receiver, name, configuration); +} + + void LookupIterator::Next() { DCHECK_NE(JSPROXY, state_); DCHECK_NE(TRANSITION, state_); @@ -48,13 +80,13 @@ void LookupIterator::Next() { } -void LookupIterator::RestartLookupForNonMaskingInterceptors() { - interceptor_state_ = InterceptorState::kProcessNonMasking; +void LookupIterator::RestartInternal(InterceptorState interceptor_state) { state_ = NOT_FOUND; + interceptor_state_ = interceptor_state; property_details_ = PropertyDetails::Empty(); - number_ = DescriptorArray::kNotFound; holder_ = initial_holder_; holder_map_ = handle(holder_->map(), isolate_); + number_ = DescriptorArray::kNotFound; Next(); } @@ -102,7 +134,8 @@ Handle<JSObject> LookupIterator::GetStoreTarget() const { bool LookupIterator::HasAccess() const { DCHECK_EQ(ACCESS_CHECK, state_); - return isolate_->MayAccess(GetHolder<JSObject>()); + return isolate_->MayAccess(handle(isolate_->context()), + GetHolder<JSObject>()); } @@ -212,11 +245,11 @@ void LookupIterator::PrepareTransitionToDataProperty( state_ = TRANSITION; transition_ = transition; - if (receiver->IsGlobalObject()) { + if (receiver->IsJSGlobalObject()) { // Install a property cell. InternalizeName(); - auto cell = GlobalObject::EnsurePropertyCell( - Handle<GlobalObject>::cast(receiver), name()); + auto cell = JSGlobalObject::EnsurePropertyCell( + Handle<JSGlobalObject>::cast(receiver), name()); DCHECK(cell->value()->IsTheHole()); transition_ = cell; } else if (!transition->is_dictionary_map()) { @@ -230,7 +263,7 @@ void LookupIterator::ApplyTransitionToDataProperty() { DCHECK_EQ(TRANSITION, state_); Handle<JSObject> receiver = GetStoreTarget(); - if (receiver->IsGlobalObject()) return; + if (receiver->IsJSGlobalObject()) return; holder_ = receiver; holder_map_ = transition_map(); JSObject::MigrateToMap(receiver, holder_map_); @@ -394,7 +427,7 @@ Handle<Object> LookupIterator::FetchValue() const { ElementsAccessor* accessor = holder->GetElementsAccessor(); return accessor->Get(handle(holder->elements()), number_); - } else if (holder_map_->IsGlobalObjectMap()) { + } else if (holder_map_->IsJSGlobalObjectMap()) { result = holder->global_dictionary()->ValueAt(number_); DCHECK(result->IsPropertyCell()); result = PropertyCell::cast(result)->value(); @@ -453,7 +486,7 @@ Handle<HeapType> LookupIterator::GetFieldType() const { Handle<PropertyCell> LookupIterator::GetPropertyCell() const { DCHECK(!IsElement()); Handle<JSObject> holder = GetHolder<JSObject>(); - Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); + Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(holder); Object* value = global->global_dictionary()->ValueAt(dictionary_entry()); DCHECK(value->IsPropertyCell()); return handle(PropertyCell::cast(value)); @@ -479,7 +512,7 @@ void LookupIterator::WriteDataValue(Handle<Object> value) { if (IsElement()) { ElementsAccessor* accessor = holder->GetElementsAccessor(); accessor->Set(holder->elements(), number_, *value); - } else if (holder->IsGlobalObject()) { + } else if (holder->IsJSGlobalObject()) { Handle<GlobalDictionary> property_dictionary = handle(holder->global_dictionary()); PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value, @@ -561,5 +594,131 @@ bool LookupIterator::SkipInterceptor(JSObject* holder) { } return interceptor_state_ == InterceptorState::kProcessNonMasking; } + + +JSReceiver* LookupIterator::NextHolder(Map* map) { + DisallowHeapAllocation no_gc; + if (!map->prototype()->IsJSReceiver()) return NULL; + + JSReceiver* next = JSReceiver::cast(map->prototype()); + DCHECK(!next->map()->IsJSGlobalObjectMap() || + next->map()->is_hidden_prototype()); + + if (!check_prototype_chain() && + !(check_hidden() && next->map()->is_hidden_prototype()) && + // Always lookup behind the JSGlobalProxy into the JSGlobalObject, even + // when not checking other hidden prototypes. + !map->IsJSGlobalProxyMap()) { + return NULL; + } + + return next; +} + + +LookupIterator::State LookupIterator::LookupInHolder(Map* const map, + JSReceiver* const holder) { + STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY); + DisallowHeapAllocation no_gc; + if (interceptor_state_ == InterceptorState::kProcessNonMasking) { + return LookupNonMaskingInterceptorInHolder(map, holder); + } + switch (state_) { + case NOT_FOUND: + if (map->IsJSProxyMap()) return JSPROXY; + if (map->is_access_check_needed() && + (IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) { + return ACCESS_CHECK; + } + // Fall through. + case ACCESS_CHECK: + if (exotic_index_state_ != ExoticIndexState::kNotExotic && + IsIntegerIndexedExotic(holder)) { + return INTEGER_INDEXED_EXOTIC; + } + if (check_interceptor() && HasInterceptor(map) && + !SkipInterceptor(JSObject::cast(holder))) { + return INTERCEPTOR; + } + // Fall through. + case INTERCEPTOR: + if (IsElement()) { + // TODO(verwaest): Optimize. + if (holder->IsStringObjectWithCharacterAt(index_)) { + PropertyAttributes attributes = + static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); + property_details_ = PropertyDetails(attributes, v8::internal::DATA, 0, + PropertyCellType::kNoCell); + } else { + JSObject* js_object = JSObject::cast(holder); + if (js_object->elements() == isolate()->heap()->empty_fixed_array()) { + return NOT_FOUND; + } + + ElementsAccessor* accessor = js_object->GetElementsAccessor(); + FixedArrayBase* backing_store = js_object->elements(); + number_ = + accessor->GetEntryForIndex(js_object, backing_store, index_); + if (number_ == kMaxUInt32) return NOT_FOUND; + property_details_ = accessor->GetDetails(backing_store, number_); + } + } else if (!map->is_dictionary_map()) { + DescriptorArray* descriptors = map->instance_descriptors(); + int number = descriptors->SearchWithCache(*name_, map); + if (number == DescriptorArray::kNotFound) return NOT_FOUND; + number_ = static_cast<uint32_t>(number); + property_details_ = descriptors->GetDetails(number_); + } else if (map->IsJSGlobalObjectMap()) { + GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary(); + int number = dict->FindEntry(name_); + if (number == GlobalDictionary::kNotFound) return NOT_FOUND; + number_ = static_cast<uint32_t>(number); + DCHECK(dict->ValueAt(number_)->IsPropertyCell()); + PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_)); + if (cell->value()->IsTheHole()) return NOT_FOUND; + property_details_ = cell->property_details(); + } else { + NameDictionary* dict = JSObject::cast(holder)->property_dictionary(); + int number = dict->FindEntry(name_); + if (number == NameDictionary::kNotFound) return NOT_FOUND; + number_ = static_cast<uint32_t>(number); + property_details_ = dict->DetailsAt(number_); + } + has_property_ = true; + switch (property_details_.kind()) { + case v8::internal::kData: + return DATA; + case v8::internal::kAccessor: + return ACCESSOR; + } + case ACCESSOR: + case DATA: + return NOT_FOUND; + case INTEGER_INDEXED_EXOTIC: + case JSPROXY: + case TRANSITION: + UNREACHABLE(); + } + UNREACHABLE(); + return state_; +} + + +LookupIterator::State LookupIterator::LookupNonMaskingInterceptorInHolder( + Map* const map, JSReceiver* const holder) { + switch (state_) { + case NOT_FOUND: + if (check_interceptor() && HasInterceptor(map) && + !SkipInterceptor(JSObject::cast(holder))) { + return INTERCEPTOR; + } + // Fall through. + default: + return NOT_FOUND; + } + UNREACHABLE(); + return state_; +} + } // namespace internal } // namespace v8 |