diff options
Diffstat (limited to 'deps/v8/src/lookup.cc')
-rw-r--r-- | deps/v8/src/lookup.cc | 134 |
1 files changed, 104 insertions, 30 deletions
diff --git a/deps/v8/src/lookup.cc b/deps/v8/src/lookup.cc index 58ad9318dd..2050114994 100644 --- a/deps/v8/src/lookup.cc +++ b/deps/v8/src/lookup.cc @@ -74,12 +74,17 @@ LookupIterator LookupIterator::PropertyOrElement(Isolate* isolate, return LookupIterator(receiver, name, configuration); } +// TODO(ishell): Consider removing this way of LookupIterator creation. // static LookupIterator LookupIterator::ForTransitionHandler( Isolate* isolate, Handle<Object> receiver, Handle<Name> name, - Handle<Object> value, MaybeHandle<Object> handler, - Handle<Map> transition_map) { - if (handler.is_null()) return LookupIterator(receiver, name); + Handle<Object> value, MaybeHandle<Map> maybe_transition_map) { + Handle<Map> transition_map; + if (!maybe_transition_map.ToHandle(&transition_map) || + !transition_map->IsPrototypeValidityCellValid()) { + // This map is not a valid transition handler, so full lookup is required. + return LookupIterator(receiver, name); + } PropertyDetails details = PropertyDetails::Empty(); bool has_property; @@ -90,6 +95,13 @@ LookupIterator LookupIterator::ForTransitionHandler( details = transition_map->GetLastDescriptorDetails(); has_property = true; } +#ifdef DEBUG + if (name->IsPrivate()) { + DCHECK_EQ(DONT_ENUM, details.attributes()); + } else { + DCHECK_EQ(NONE, details.attributes()); + } +#endif LookupIterator it(isolate, receiver, name, transition_map, details, has_property); @@ -260,14 +272,27 @@ void LookupIterator::InternalUpdateProtector() { if (isolate_->bootstrapper()->IsActive()) return; if (*name_ == heap()->constructor_string()) { - if (!isolate_->IsSpeciesLookupChainIntact()) return; + if (!isolate_->IsArraySpeciesLookupChainIntact() && + !isolate_->IsTypedArraySpeciesLookupChainIntact() && + !isolate_->IsPromiseSpeciesLookupChainIntact()) + return; // Setting the constructor property could change an instance's @@species - if (holder_->IsJSArray() || holder_->IsJSPromise() || - holder_->IsJSTypedArray()) { + if (holder_->IsJSArray()) { + if (!isolate_->IsArraySpeciesLookupChainIntact()) return; isolate_->CountUsage( v8::Isolate::UseCounterFeature::kArrayInstanceConstructorModified); - isolate_->InvalidateSpeciesProtector(); - } else if (holder_->map()->is_prototype_map()) { + isolate_->InvalidateArraySpeciesProtector(); + return; + } else if (holder_->IsJSPromise()) { + if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return; + isolate_->InvalidatePromiseSpeciesProtector(); + return; + } else if (holder_->IsJSTypedArray()) { + if (!isolate_->IsTypedArraySpeciesLookupChainIntact()) return; + isolate_->InvalidateTypedArraySpeciesProtector(); + return; + } + if (holder_->map()->is_prototype_map()) { DisallowHeapAllocation no_gc; // Setting the constructor of Array.prototype, Promise.prototype or // %TypedArray%.prototype of any realm also needs to invalidate the @@ -276,26 +301,49 @@ void LookupIterator::InternalUpdateProtector() { // have different prototypes for each type, and their parent prototype is // pointing the same TYPED_ARRAY_PROTOTYPE. if (isolate_->IsInAnyContext(*holder_, - Context::INITIAL_ARRAY_PROTOTYPE_INDEX) || - isolate_->IsInAnyContext(*holder_, - Context::PROMISE_PROTOTYPE_INDEX) || - isolate_->IsInAnyContext(holder_->map()->prototype(), - Context::TYPED_ARRAY_PROTOTYPE_INDEX)) { - isolate_->CountUsage(v8::Isolate::UseCounterFeature:: - kArrayPrototypeConstructorModified); - isolate_->InvalidateSpeciesProtector(); + Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) { + if (!isolate_->IsArraySpeciesLookupChainIntact()) return; + isolate_->CountUsage( + v8::Isolate::UseCounterFeature::kArrayPrototypeConstructorModified); + isolate_->InvalidateArraySpeciesProtector(); + } else if (isolate_->IsInAnyContext(*holder_, + Context::PROMISE_PROTOTYPE_INDEX)) { + if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return; + isolate_->InvalidatePromiseSpeciesProtector(); + } else if (isolate_->IsInAnyContext( + holder_->map()->prototype(), + Context::TYPED_ARRAY_PROTOTYPE_INDEX)) { + if (!isolate_->IsTypedArraySpeciesLookupChainIntact()) return; + isolate_->InvalidateTypedArraySpeciesProtector(); } } + } else if (*name_ == heap()->next_string()) { + if (!isolate_->IsArrayIteratorLookupChainIntact()) return; + // Setting the next property of %ArrayIteratorPrototype% also needs to + // invalidate the array iterator protector. + if (isolate_->IsInAnyContext( + *holder_, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX)) { + isolate_->InvalidateArrayIteratorProtector(); + } } else if (*name_ == heap()->species_symbol()) { - if (!isolate_->IsSpeciesLookupChainIntact()) return; + if (!isolate_->IsArraySpeciesLookupChainIntact() && + !isolate_->IsTypedArraySpeciesLookupChainIntact() && + !isolate_->IsPromiseSpeciesLookupChainIntact()) + return; // Setting the Symbol.species property of any Array, Promise or TypedArray // constructor invalidates the @@species protector - if (isolate_->IsInAnyContext(*holder_, Context::ARRAY_FUNCTION_INDEX) || - isolate_->IsInAnyContext(*holder_, Context::PROMISE_FUNCTION_INDEX) || - IsTypedArrayFunctionInAnyContext(isolate_, *holder_)) { + if (isolate_->IsInAnyContext(*holder_, Context::ARRAY_FUNCTION_INDEX)) { + if (!isolate_->IsArraySpeciesLookupChainIntact()) return; isolate_->CountUsage( v8::Isolate::UseCounterFeature::kArraySpeciesModified); - isolate_->InvalidateSpeciesProtector(); + isolate_->InvalidateArraySpeciesProtector(); + } else if (isolate_->IsInAnyContext(*holder_, + Context::PROMISE_FUNCTION_INDEX)) { + if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return; + isolate_->InvalidatePromiseSpeciesProtector(); + } else if (IsTypedArrayFunctionInAnyContext(isolate_, *holder_)) { + if (!isolate_->IsTypedArraySpeciesLookupChainIntact()) return; + isolate_->InvalidateTypedArraySpeciesProtector(); } } else if (*name_ == heap()->is_concat_spreadable_symbol()) { if (!isolate_->IsIsConcatSpreadableLookupChainIntact()) return; @@ -305,11 +353,25 @@ void LookupIterator::InternalUpdateProtector() { if (holder_->IsJSArray()) { isolate_->InvalidateArrayIteratorProtector(); } + } else if (*name_ == heap()->resolve_string()) { + if (!isolate_->IsPromiseResolveLookupChainIntact()) return; + // Setting the "resolve" property on any %Promise% intrinsic object + // invalidates the Promise.resolve protector. + if (isolate_->IsInAnyContext(*holder_, Context::PROMISE_FUNCTION_INDEX)) { + isolate_->InvalidatePromiseResolveProtector(); + } } else if (*name_ == heap()->then_string()) { if (!isolate_->IsPromiseThenLookupChainIntact()) return; // Setting the "then" property on any JSPromise instance or on the // initial %PromisePrototype% invalidates the Promise#then protector. + // Also setting the "then" property on the initial %ObjectPrototype% + // invalidates the Promise#then protector, since we use this protector + // to guard the fast-path in AsyncGeneratorResolve, where we can skip + // the ResolvePromise step and go directly to FulfillPromise if we + // know that the Object.prototype doesn't contain a "then" method. if (holder_->IsJSPromise() || + isolate_->IsInAnyContext(*holder_, + Context::INITIAL_OBJECT_PROTOTYPE_INDEX) || isolate_->IsInAnyContext(*holder_, Context::PROMISE_PROTOTYPE_INDEX)) { isolate_->InvalidatePromiseThenProtector(); } @@ -421,6 +483,14 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value, if (!IsElement() && !holder_obj->HasFastProperties()) { PropertyDetails details(kData, attributes, PropertyCellType::kMutable); + if (holder_obj->map()->is_prototype_map() && + (property_details_.attributes() & READ_ONLY) == 0 && + (attributes & READ_ONLY) != 0) { + // Invalidate prototype validity cell when a property is reconfigured + // from writable to read-only as this may invalidate transitioning store + // IC handlers. + JSObject::InvalidatePrototypeChains(holder->map()); + } if (holder_obj->IsJSGlobalObject()) { Handle<GlobalDictionary> dictionary( JSGlobalObject::cast(*holder_obj)->global_dictionary()); @@ -453,14 +523,12 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value, // Can only be called when the receiver is a JSObject. JSProxy has to be handled // via a trap. Adding properties to primitive values is not observable. -// Returns true if a new transition has been created, or false if an existing -// transition was followed. -bool LookupIterator::PrepareTransitionToDataProperty( +void LookupIterator::PrepareTransitionToDataProperty( Handle<JSReceiver> receiver, Handle<Object> value, PropertyAttributes attributes, Object::StoreFromKeyed store_mode) { DCHECK_IMPLIES(receiver->IsJSProxy(), name()->IsPrivate()); DCHECK(receiver.is_identical_to(GetStoreTarget<JSReceiver>())); - if (state_ == TRANSITION) return false; + if (state_ == TRANSITION) return; if (!IsElement() && name()->IsPrivate()) { attributes = static_cast<PropertyAttributes>(attributes | DONT_ENUM); @@ -506,13 +574,11 @@ bool LookupIterator::PrepareTransitionToDataProperty( PropertyDetails(kData, attributes, PropertyCellType::kNoCell); transition_ = map; } - return false; + return; } - bool created_new_map; Handle<Map> transition = Map::TransitionToDataProperty( - map, name_, value, attributes, kDefaultFieldConstness, store_mode, - &created_new_map); + map, name_, value, attributes, kDefaultFieldConstness, store_mode); state_ = TRANSITION; transition_ = transition; @@ -524,7 +590,6 @@ bool LookupIterator::PrepareTransitionToDataProperty( property_details_ = transition->GetLastDescriptorDetails(); has_property_ = true; } - return created_new_map; } void LookupIterator::ApplyTransitionToDataProperty( @@ -541,6 +606,15 @@ void LookupIterator::ApplyTransitionToDataProperty( Handle<Map> transition = transition_map(); bool simple_transition = transition->GetBackPointer() == receiver->map(); + if (configuration_ == DEFAULT && !transition->is_dictionary_map() && + !transition->IsPrototypeValidityCellValid()) { + // Only LookupIterator instances with DEFAULT (full prototype chain) + // configuration can produce valid transition handler maps. + Handle<Object> validity_cell = + Map::GetOrCreatePrototypeChainValidityCell(transition, isolate()); + transition->set_prototype_validity_cell(*validity_cell); + } + if (!receiver->IsJSProxy()) { JSObject::MigrateToMap(Handle<JSObject>::cast(receiver), transition); } |