Commit a9d7b45c authored by Joshua Litt's avatar Joshua Litt Committed by Commit Bot

[protectors] Move *IteratorProtectors to protectors

Bug: v8:9463
Change-Id: Ie36fc1b04b81dd091c4526123bee50d6b22d6917
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1807044
Commit-Queue: Joshua Litt <joshualitt@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63839}
parent 60624b56
......@@ -124,30 +124,6 @@ bool Isolate::IsArrayBufferDetachingIntact() {
return buffer_detaching.value() == Smi::FromInt(kProtectorValid);
}
bool Isolate::IsArrayIteratorLookupChainIntact() {
PropertyCell array_iterator_cell =
PropertyCell::cast(root(RootIndex::kArrayIteratorProtector));
return array_iterator_cell.value() == Smi::FromInt(kProtectorValid);
}
bool Isolate::IsMapIteratorLookupChainIntact() {
PropertyCell map_iterator_cell =
PropertyCell::cast(root(RootIndex::kMapIteratorProtector));
return map_iterator_cell.value() == Smi::FromInt(kProtectorValid);
}
bool Isolate::IsSetIteratorLookupChainIntact() {
PropertyCell set_iterator_cell =
PropertyCell::cast(root(RootIndex::kSetIteratorProtector));
return set_iterator_cell.value() == Smi::FromInt(kProtectorValid);
}
bool Isolate::IsStringIteratorLookupChainIntact() {
PropertyCell string_iterator_cell =
PropertyCell::cast(root(RootIndex::kStringIteratorProtector));
return string_iterator_cell.value() == Smi::FromInt(kProtectorValid);
}
} // namespace internal
} // namespace v8
......
......@@ -3978,42 +3978,6 @@ void Isolate::InvalidateStringLengthOverflowProtector() {
DCHECK(!IsStringLengthOverflowIntact());
}
void Isolate::InvalidateArrayIteratorProtector() {
DCHECK(factory()->array_iterator_protector()->value().IsSmi());
DCHECK(IsArrayIteratorLookupChainIntact());
PropertyCell::SetValueWithInvalidation(
this, "array_iterator_protector", factory()->array_iterator_protector(),
handle(Smi::FromInt(kProtectorInvalid), this));
DCHECK(!IsArrayIteratorLookupChainIntact());
}
void Isolate::InvalidateMapIteratorProtector() {
DCHECK(factory()->map_iterator_protector()->value().IsSmi());
DCHECK(IsMapIteratorLookupChainIntact());
PropertyCell::SetValueWithInvalidation(
this, "map_iterator_protector", factory()->map_iterator_protector(),
handle(Smi::FromInt(kProtectorInvalid), this));
DCHECK(!IsMapIteratorLookupChainIntact());
}
void Isolate::InvalidateSetIteratorProtector() {
DCHECK(factory()->set_iterator_protector()->value().IsSmi());
DCHECK(IsSetIteratorLookupChainIntact());
PropertyCell::SetValueWithInvalidation(
this, "set_iterator_protector", factory()->set_iterator_protector(),
handle(Smi::FromInt(kProtectorInvalid), this));
DCHECK(!IsSetIteratorLookupChainIntact());
}
void Isolate::InvalidateStringIteratorProtector() {
DCHECK(factory()->string_iterator_protector()->value().IsSmi());
DCHECK(IsStringIteratorLookupChainIntact());
PropertyCell::SetValueWithInvalidation(
this, "string_iterator_protector", factory()->string_iterator_protector(),
handle(Smi::FromInt(kProtectorInvalid), this));
DCHECK(!IsStringIteratorLookupChainIntact());
}
void Isolate::InvalidateArrayBufferDetachingProtector() {
DCHECK(factory()->array_buffer_detaching_protector()->value().IsSmi());
DCHECK(IsArrayBufferDetachingIntact());
......
......@@ -1177,43 +1177,6 @@ class Isolate final : private HiddenFactory {
bool IsIsConcatSpreadableLookupChainIntact();
bool IsIsConcatSpreadableLookupChainIntact(JSReceiver receiver);
inline bool IsStringLengthOverflowIntact();
inline bool IsArrayIteratorLookupChainIntact();
// The MapIterator protector protects the original iteration behaviors of
// Map.prototype.keys(), Map.prototype.values(), and Set.prototype.entries().
// It does not protect the original iteration behavior of
// Map.prototype[Symbol.iterator](). The protector is invalidated when:
// * The 'next' property is set on an object where the property holder is the
// %MapIteratorPrototype% (e.g. because the object is that very prototype).
// * The 'Symbol.iterator' property is set on an object where the property
// holder is the %IteratorPrototype%. Note that this also invalidates the
// SetIterator protector (see below).
inline bool IsMapIteratorLookupChainIntact();
// The SetIterator protector protects the original iteration behavior of
// Set.prototype.keys(), Set.prototype.values(), Set.prototype.entries(),
// and Set.prototype[Symbol.iterator](). The protector is invalidated when:
// * The 'next' property is set on an object where the property holder is the
// %SetIteratorPrototype% (e.g. because the object is that very prototype).
// * The 'Symbol.iterator' property is set on an object where the property
// holder is the %SetPrototype% OR %IteratorPrototype%. This means that
// setting Symbol.iterator on a MapIterator object can also invalidate the
// SetIterator protector, and vice versa, setting Symbol.iterator on a
// SetIterator object can also invalidate the MapIterator. This is an over-
// approximation for the sake of simplicity.
inline bool IsSetIteratorLookupChainIntact();
// The StringIteratorProtector protects the original string iteration behavior
// for primitive strings. As long as the StringIteratorProtector is valid,
// iterating over a primitive string is guaranteed to be unobservable from
// user code and can thus be cut short. More specifically, the protector gets
// invalidated as soon as either String.prototype[Symbol.iterator] or
// String.prototype[Symbol.iterator]().next is modified. This guarantee does
// not apply to string objects (as opposed to primitives), since they could
// define their own Symbol.iterator.
// String.prototype itself does not need to be protected, since it is
// non-configurable and non-writable.
inline bool IsStringIteratorLookupChainIntact();
// Make sure we do check for detached array buffers.
inline bool IsArrayBufferDetachingIntact();
......@@ -1246,10 +1209,6 @@ class Isolate final : private HiddenFactory {
void InvalidateIsConcatSpreadableProtector();
void InvalidateStringLengthOverflowProtector();
void InvalidateArrayIteratorProtector();
void InvalidateMapIteratorProtector();
void InvalidateSetIteratorProtector();
void InvalidateStringIteratorProtector();
void InvalidateArrayBufferDetachingProtector();
V8_EXPORT_PRIVATE void InvalidatePromiseHookProtector();
void InvalidatePromiseResolveProtector();
......
......@@ -21,9 +21,54 @@ class Protectors : public AllStatic {
#define DECLARED_PROTECTORS_ON_ISOLATE(V) \
V(ArraySpeciesLookupChain, ArraySpeciesProtector, array_species_protector) \
V(ArrayConstructor, ArrayConstructorProtector, array_constructor_protector) \
V(ArrayIteratorLookupChain, ArrayIteratorProtector, \
array_iterator_protector) \
\
/* The MapIterator protector protects the original iteration behaviors */ \
/* of Map.prototype.keys(), Map.prototype.values(), and */ \
/* Set.prototype.entries(). It does not protect the original iteration */ \
/* behavior of Map.prototype[Symbol.iterator](). */ \
/* The protector is invalidated when: */ \
/* * The 'next' property is set on an object where the property holder */ \
/* is the %MapIteratorPrototype% (e.g. because the object is that very */ \
/* prototype). */ \
/* * The 'Symbol.iterator' property is set on an object where the */ \
/* property holder is the %IteratorPrototype%. Note that this also */ \
/* invalidates the SetIterator protector (see below). */ \
V(MapIteratorLookupChain, MapIteratorProtector, map_iterator_protector) \
V(PromiseThenLookupChain, PromiseThenProtector, promise_then_protector) \
V(PromiseSpeciesLookupChain, PromiseSpeciesProtector, \
promise_species_protector) \
\
/* The SetIterator protector protects the original iteration behavior of */ \
/* Set.prototype.keys(), Set.prototype.values(), */ \
/* Set.prototype.entries(), and Set.prototype[Symbol.iterator](). The */ \
/* protector is invalidated when: */ \
/* * The 'next' property is set on an object where the property holder */ \
/* is the %SetIteratorPrototype% (e.g. because the object is that very */ \
/* prototype). */ \
/* * The 'Symbol.iterator' property is set on an object where the */ \
/* property holder is the %SetPrototype% OR %IteratorPrototype%. This */ \
/* means that setting Symbol.iterator on a MapIterator object can also */ \
/* invalidate the SetIterator protector, and vice versa, setting */ \
/* Symbol.iterator on a SetIterator object can also invalidate the */ \
/* MapIterator. This is an over-approximation for the sake of */ \
/* simplicity. */ \
V(SetIteratorLookupChain, SetIteratorProtector, set_iterator_protector) \
\
/* The StringIteratorProtector protects the original string iteration */ \
/* behavior for primitive strings. As long as the */ \
/* StringIteratorProtector is valid, iterating over a primitive string */ \
/* is guaranteed to be unobservable from user code and can thus be cut */ \
/* short. More specifically, the protector gets invalidated as soon as */ \
/* either String.prototype[Symbol.iterator] or */ \
/* String.prototype[Symbol.iterator]().next is modified. This guarantee */ \
/* does not apply to string objects (as opposed to primitives), since */ \
/* they could define their own Symbol.iterator. */ \
/* String.prototype itself does not need to be protected, since it is */ \
/* non-configurable and non-writable. */ \
V(StringIteratorLookupChain, StringIteratorProtector, \
string_iterator_protector) \
V(TypedArraySpeciesLookupChain, TypedArraySpeciesProtector, \
typed_array_species_protector)
......
......@@ -317,26 +317,26 @@ void LookupIterator::InternalUpdateProtector() {
*receiver, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX)) {
// Setting the next property of %ArrayIteratorPrototype% also needs to
// invalidate the array iterator protector.
if (!isolate_->IsArrayIteratorLookupChainIntact()) return;
isolate_->InvalidateArrayIteratorProtector();
if (!Protectors::IsArrayIteratorLookupChainIntact(isolate_)) return;
Protectors::InvalidateArrayIteratorLookupChain(isolate_);
} else if (receiver->IsJSMapIterator() ||
isolate_->IsInAnyContext(
*receiver, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX)) {
if (!isolate_->IsMapIteratorLookupChainIntact()) return;
isolate_->InvalidateMapIteratorProtector();
if (!Protectors::IsMapIteratorLookupChainIntact(isolate_)) return;
Protectors::InvalidateMapIteratorLookupChain(isolate_);
} else if (receiver->IsJSSetIterator() ||
isolate_->IsInAnyContext(
*receiver, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX)) {
if (!isolate_->IsSetIteratorLookupChainIntact()) return;
isolate_->InvalidateSetIteratorProtector();
if (!Protectors::IsSetIteratorLookupChainIntact(isolate_)) return;
Protectors::InvalidateSetIteratorLookupChain(isolate_);
} else if (receiver->IsJSStringIterator() ||
isolate_->IsInAnyContext(
*receiver,
Context::INITIAL_STRING_ITERATOR_PROTOTYPE_INDEX)) {
// Setting the next property of %StringIteratorPrototype% invalidates the
// string iterator protector.
if (!isolate_->IsStringIteratorLookupChainIntact()) return;
isolate_->InvalidateStringIteratorProtector();
if (!Protectors::IsStringIteratorLookupChainIntact(isolate_)) return;
Protectors::InvalidateStringIteratorLookupChain(isolate_);
}
} else if (*name_ == roots.species_symbol()) {
// Fetching the context in here since the operation is rather expensive.
......@@ -379,29 +379,29 @@ void LookupIterator::InternalUpdateProtector() {
isolate_->InvalidateIsConcatSpreadableProtector();
} else if (*name_ == roots.iterator_symbol()) {
if (receiver->IsJSArray(isolate_)) {
if (!isolate_->IsArrayIteratorLookupChainIntact()) return;
isolate_->InvalidateArrayIteratorProtector();
if (!Protectors::IsArrayIteratorLookupChainIntact(isolate_)) return;
Protectors::InvalidateArrayIteratorLookupChain(isolate_);
} else if (receiver->IsJSSet(isolate_) || receiver->IsJSSetIterator() ||
isolate_->IsInAnyContext(
*receiver, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX) ||
isolate_->IsInAnyContext(*receiver,
Context::INITIAL_SET_PROTOTYPE_INDEX)) {
if (isolate_->IsSetIteratorLookupChainIntact()) {
isolate_->InvalidateSetIteratorProtector();
if (Protectors::IsSetIteratorLookupChainIntact(isolate_)) {
Protectors::InvalidateSetIteratorLookupChain(isolate_);
}
} else if (receiver->IsJSMapIterator() ||
isolate_->IsInAnyContext(
*receiver, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX)) {
if (isolate_->IsMapIteratorLookupChainIntact()) {
isolate_->InvalidateMapIteratorProtector();
if (Protectors::IsMapIteratorLookupChainIntact(isolate_)) {
Protectors::InvalidateMapIteratorLookupChain(isolate_);
}
} else if (isolate_->IsInAnyContext(
*receiver, Context::INITIAL_ITERATOR_PROTOTYPE_INDEX)) {
if (isolate_->IsMapIteratorLookupChainIntact()) {
isolate_->InvalidateMapIteratorProtector();
if (Protectors::IsMapIteratorLookupChainIntact(isolate_)) {
Protectors::InvalidateMapIteratorLookupChain(isolate_);
}
if (isolate_->IsSetIteratorLookupChainIntact()) {
isolate_->InvalidateSetIteratorProtector();
if (Protectors::IsSetIteratorLookupChainIntact(isolate_)) {
Protectors::InvalidateSetIteratorLookupChain(isolate_);
}
} else if (isolate_->IsInAnyContext(
*receiver, Context::INITIAL_STRING_PROTOTYPE_INDEX)) {
......@@ -409,8 +409,8 @@ void LookupIterator::InternalUpdateProtector() {
// the string iterator protector. Symbol.iterator can also be set on a
// String wrapper, but not on a primitive string. We only support
// protector for primitive strings.
if (!isolate_->IsStringIteratorLookupChainIntact()) return;
isolate_->InvalidateStringIteratorProtector();
if (!Protectors::IsStringIteratorLookupChainIntact(isolate_)) return;
Protectors::InvalidateStringIteratorLookupChain(isolate_);
}
} else if (*name_ == roots.resolve_string()) {
if (!isolate_->IsPromiseResolveLookupChainIntact()) return;
......
......@@ -1770,7 +1770,7 @@ bool Object::IterationHasObservableEffects() {
// Check that the ArrayPrototype hasn't been modified in a way that would
// affect iteration.
if (!isolate->IsArrayIteratorLookupChainIntact()) return true;
if (!Protectors::IsArrayIteratorLookupChainIntact(isolate)) return true;
// For FastPacked kinds, iteration will have the same effect as simply
// accessing each property in order.
......
......@@ -1148,20 +1148,22 @@ RUNTIME_FUNCTION(Runtime_ArraySpeciesProtector) {
RUNTIME_FUNCTION(Runtime_MapIteratorProtector) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
return isolate->heap()->ToBoolean(isolate->IsMapIteratorLookupChainIntact());
return isolate->heap()->ToBoolean(
Protectors::IsMapIteratorLookupChainIntact(isolate));
}
RUNTIME_FUNCTION(Runtime_SetIteratorProtector) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
return isolate->heap()->ToBoolean(isolate->IsSetIteratorLookupChainIntact());
return isolate->heap()->ToBoolean(
Protectors::IsSetIteratorLookupChainIntact(isolate));
}
RUNTIME_FUNCTION(Runtime_StringIteratorProtector) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
return isolate->heap()->ToBoolean(
isolate->IsStringIteratorLookupChainIntact());
Protectors::IsStringIteratorLookupChainIntact(isolate));
}
// Take a compiled wasm module and serialize it into an array buffer, which is
......
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