| Index: src/lookup.cc
|
| diff --git a/src/lookup.cc b/src/lookup.cc
|
| index 7b26a6d89ce04048b792d58cf562012678c53933..d6cce50d909ce16a0c56675dad16e60c5b902883 100644
|
| --- a/src/lookup.cc
|
| +++ b/src/lookup.cc
|
| @@ -45,6 +45,7 @@ LookupIterator LookupIterator::PropertyOrElement(Isolate* isolate,
|
| return LookupIterator(receiver, name, configuration);
|
| }
|
|
|
| +template <bool is_element>
|
| void LookupIterator::Start() {
|
| DisallowHeapAllocation no_gc;
|
|
|
| @@ -56,12 +57,15 @@ void LookupIterator::Start() {
|
| JSReceiver* holder = *holder_;
|
| Map* map = holder->map();
|
|
|
| - state_ = LookupInHolder(map, holder);
|
| + state_ = LookupInHolder<is_element>(map, holder);
|
| if (IsFound()) return;
|
|
|
| - NextInternal(map, holder);
|
| + NextInternal<is_element>(map, holder);
|
| }
|
|
|
| +template void LookupIterator::Start<true>();
|
| +template void LookupIterator::Start<false>();
|
| +
|
| void LookupIterator::Next() {
|
| DCHECK_NE(JSPROXY, state_);
|
| DCHECK_NE(TRANSITION, state_);
|
| @@ -72,19 +76,22 @@ void LookupIterator::Next() {
|
| Map* map = holder->map();
|
|
|
| if (map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
|
| - state_ = LookupInSpecialHolder(map, holder);
|
| + state_ = IsElement() ? LookupInSpecialHolder<true>(map, holder)
|
| + : LookupInSpecialHolder<false>(map, holder);
|
| if (IsFound()) return;
|
| }
|
|
|
| - NextInternal(map, holder);
|
| + IsElement() ? NextInternal<true>(map, holder)
|
| + : NextInternal<false>(map, holder);
|
| }
|
|
|
| +template <bool is_element>
|
| void LookupIterator::NextInternal(Map* map, JSReceiver* holder) {
|
| do {
|
| JSReceiver* maybe_holder = NextHolder(map);
|
| if (maybe_holder == nullptr) {
|
| if (interceptor_state_ == InterceptorState::kSkipNonMasking) {
|
| - RestartLookupForNonMaskingInterceptors();
|
| + RestartLookupForNonMaskingInterceptors<is_element>();
|
| return;
|
| }
|
| if (holder != *holder_) holder_ = handle(holder, isolate_);
|
| @@ -92,18 +99,21 @@ void LookupIterator::NextInternal(Map* map, JSReceiver* holder) {
|
| }
|
| holder = maybe_holder;
|
| map = holder->map();
|
| - state_ = LookupInHolder(map, holder);
|
| + state_ = LookupInHolder<is_element>(map, holder);
|
| } while (!IsFound());
|
|
|
| holder_ = handle(holder, isolate_);
|
| }
|
|
|
| +template <bool is_element>
|
| void LookupIterator::RestartInternal(InterceptorState interceptor_state) {
|
| interceptor_state_ = interceptor_state;
|
| property_details_ = PropertyDetails::Empty();
|
| - Start();
|
| + Start<is_element>();
|
| }
|
|
|
| +template void LookupIterator::RestartInternal<true>(InterceptorState);
|
| +template void LookupIterator::RestartInternal<false>(InterceptorState);
|
|
|
| // static
|
| Handle<JSReceiver> LookupIterator::GetRootForNonJSReceiver(
|
| @@ -139,11 +149,11 @@ bool LookupIterator::HasAccess() const {
|
| GetHolder<JSObject>());
|
| }
|
|
|
| -
|
| +template <bool is_element>
|
| void LookupIterator::ReloadPropertyInformation() {
|
| state_ = BEFORE_PROPERTY;
|
| interceptor_state_ = InterceptorState::kUninitialized;
|
| - state_ = LookupInHolder(holder_->map(), *holder_);
|
| + state_ = LookupInHolder<is_element>(holder_->map(), *holder_);
|
| DCHECK(IsFound() || !holder_->HasFastProperties());
|
| }
|
|
|
| @@ -168,7 +178,7 @@ void LookupIterator::UpdateProtector() {
|
| if (isolate_->bootstrapper()->IsActive()) return;
|
| if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
|
|
|
| - if (*name_ == *isolate_->factory()->constructor_string()) {
|
| + if (*name_ == heap()->constructor_string()) {
|
| // Setting the constructor property could change an instance's @@species
|
| if (holder_->IsJSArray()) {
|
| isolate_->CountUsage(
|
| @@ -183,7 +193,7 @@ void LookupIterator::UpdateProtector() {
|
| isolate_->InvalidateArraySpeciesProtector();
|
| }
|
| }
|
| - } else if (*name_ == *isolate_->factory()->species_symbol()) {
|
| + } else if (*name_ == heap()->species_symbol()) {
|
| // Setting the Symbol.species property of any Array constructor invalidates
|
| // the species protector
|
| if (HolderIsInContextIndex(Context::ARRAY_FUNCTION_INDEX)) {
|
| @@ -233,7 +243,7 @@ void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
|
| }
|
|
|
| JSObject::MigrateToMap(holder, new_map);
|
| - ReloadPropertyInformation();
|
| + ReloadPropertyInformation<false>();
|
| }
|
|
|
|
|
| @@ -248,19 +258,23 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
|
| Handle<FixedArrayBase> elements(holder->elements());
|
| holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value,
|
| attributes);
|
| - } else if (!holder->HasFastProperties()) {
|
| - PropertyDetails details(attributes, v8::internal::DATA, 0,
|
| - PropertyCellType::kMutable);
|
| - JSObject::SetNormalizedProperty(holder, name(), value, details);
|
| + ReloadPropertyInformation<true>();
|
| } else {
|
| - Handle<Map> old_map(holder->map(), isolate_);
|
| - Handle<Map> new_map = Map::ReconfigureExistingProperty(
|
| - old_map, descriptor_number(), i::kData, attributes);
|
| - new_map = Map::PrepareForDataProperty(new_map, descriptor_number(), value);
|
| - JSObject::MigrateToMap(holder, new_map);
|
| + if (!holder->HasFastProperties()) {
|
| + PropertyDetails details(attributes, v8::internal::DATA, 0,
|
| + PropertyCellType::kMutable);
|
| + JSObject::SetNormalizedProperty(holder, name(), value, details);
|
| + } else {
|
| + Handle<Map> old_map(holder->map(), isolate_);
|
| + Handle<Map> new_map = Map::ReconfigureExistingProperty(
|
| + old_map, descriptor_number(), i::kData, attributes);
|
| + new_map =
|
| + Map::PrepareForDataProperty(new_map, descriptor_number(), value);
|
| + JSObject::MigrateToMap(holder, new_map);
|
| + }
|
| + ReloadPropertyInformation<false>();
|
| }
|
|
|
| - ReloadPropertyInformation();
|
| WriteDataValue(value);
|
|
|
| #if VERIFY_HEAP
|
| @@ -328,7 +342,7 @@ void LookupIterator::ApplyTransitionToDataProperty(Handle<JSObject> receiver) {
|
| property_details_ = transition->GetLastDescriptorDetails();
|
| state_ = DATA;
|
| } else {
|
| - ReloadPropertyInformation();
|
| + ReloadPropertyInformation<false>();
|
| }
|
| }
|
|
|
| @@ -347,7 +361,7 @@ void LookupIterator::Delete() {
|
| if (holder->HasFastProperties()) {
|
| JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0,
|
| "DeletingProperty");
|
| - ReloadPropertyInformation();
|
| + ReloadPropertyInformation<false>();
|
| }
|
| // TODO(verwaest): Get rid of the name_ argument.
|
| JSReceiver::DeleteNormalizedProperty(holder, name_, number_);
|
| @@ -375,7 +389,7 @@ void LookupIterator::TransitionToAccessorProperty(
|
| old_map, name_, component, accessor, attributes);
|
| JSObject::MigrateToMap(receiver, new_map);
|
|
|
| - ReloadPropertyInformation();
|
| + ReloadPropertyInformation<false>();
|
|
|
| if (!new_map->is_dictionary_map()) return;
|
| }
|
| @@ -435,6 +449,8 @@ void LookupIterator::TransitionToAccessorPair(Handle<Object> pair,
|
| } else {
|
| receiver->set_elements(*dictionary);
|
| }
|
| +
|
| + ReloadPropertyInformation<true>();
|
| } else {
|
| PropertyNormalizationMode mode = receiver->map()->is_prototype_map()
|
| ? KEEP_INOBJECT_PROPERTIES
|
| @@ -445,9 +461,9 @@ void LookupIterator::TransitionToAccessorPair(Handle<Object> pair,
|
|
|
| JSObject::SetNormalizedProperty(receiver, name_, pair, details);
|
| JSObject::ReoptimizeIfPrototype(receiver);
|
| - }
|
|
|
| - ReloadPropertyInformation();
|
| + ReloadPropertyInformation<false>();
|
| + }
|
| }
|
|
|
|
|
| @@ -587,12 +603,6 @@ void LookupIterator::WriteDataValue(Handle<Object> value) {
|
| }
|
|
|
|
|
| -bool LookupIterator::HasInterceptor(Map* map) const {
|
| - if (IsElement()) return map->has_indexed_interceptor();
|
| - return map->has_named_interceptor();
|
| -}
|
| -
|
| -
|
| bool LookupIterator::SkipInterceptor(JSObject* holder) {
|
| auto info = GetInterceptor(holder);
|
| // TODO(dcarney): check for symbol/can_intercept_symbols here as well.
|
| @@ -639,26 +649,37 @@ LookupIterator::State LookupIterator::NotFound(JSReceiver* const holder) const {
|
| : NOT_FOUND;
|
| }
|
|
|
| +namespace {
|
| +
|
| +template <bool is_element>
|
| +bool HasInterceptor(Map* map) {
|
| + return is_element ? map->has_indexed_interceptor()
|
| + : map->has_named_interceptor();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +template <bool is_element>
|
| LookupIterator::State LookupIterator::LookupInSpecialHolder(
|
| Map* const map, JSReceiver* const holder) {
|
| STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY);
|
| switch (state_) {
|
| case NOT_FOUND:
|
| if (map->IsJSProxyMap()) {
|
| - if (IsElement() || !name_->IsPrivate()) return JSPROXY;
|
| + if (is_element || !name_->IsPrivate()) return JSPROXY;
|
| }
|
| if (map->is_access_check_needed()) {
|
| - if (IsElement() || !name_->IsPrivate()) return ACCESS_CHECK;
|
| + if (is_element || !name_->IsPrivate()) return ACCESS_CHECK;
|
| }
|
| // Fall through.
|
| case ACCESS_CHECK:
|
| - if (check_interceptor() && HasInterceptor(map) &&
|
| + if (check_interceptor() && HasInterceptor<is_element>(map) &&
|
| !SkipInterceptor(JSObject::cast(holder))) {
|
| - if (IsElement() || !name_->IsPrivate()) return INTERCEPTOR;
|
| + if (is_element || !name_->IsPrivate()) return INTERCEPTOR;
|
| }
|
| // Fall through.
|
| case INTERCEPTOR:
|
| - if (!IsElement() && map->IsJSGlobalObjectMap()) {
|
| + if (!is_element && map->IsJSGlobalObjectMap()) {
|
| GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary();
|
| int number = dict->FindEntry(name_);
|
| if (number == GlobalDictionary::kNotFound) return NOT_FOUND;
|
| @@ -675,7 +696,7 @@ LookupIterator::State LookupIterator::LookupInSpecialHolder(
|
| return ACCESSOR;
|
| }
|
| }
|
| - return LookupInRegularHolder(map, holder);
|
| + return LookupInRegularHolder<is_element>(map, holder);
|
| case ACCESSOR:
|
| case DATA:
|
| return NOT_FOUND;
|
| @@ -688,6 +709,7 @@ LookupIterator::State LookupIterator::LookupInSpecialHolder(
|
| return NOT_FOUND;
|
| }
|
|
|
| +template <bool is_element>
|
| LookupIterator::State LookupIterator::LookupInRegularHolder(
|
| Map* const map, JSReceiver* const holder) {
|
| DisallowHeapAllocation no_gc;
|
| @@ -695,7 +717,7 @@ LookupIterator::State LookupIterator::LookupInRegularHolder(
|
| return NOT_FOUND;
|
| }
|
|
|
| - if (IsElement()) {
|
| + if (is_element) {
|
| JSObject* js_object = JSObject::cast(holder);
|
| ElementsAccessor* accessor = js_object->GetElementsAccessor();
|
| FixedArrayBase* backing_store = js_object->elements();
|
|
|