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() { ...@@ -124,30 +124,6 @@ bool Isolate::IsArrayBufferDetachingIntact() {
return buffer_detaching.value() == Smi::FromInt(kProtectorValid); 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 internal
} // namespace v8 } // namespace v8
......
...@@ -3978,42 +3978,6 @@ void Isolate::InvalidateStringLengthOverflowProtector() { ...@@ -3978,42 +3978,6 @@ void Isolate::InvalidateStringLengthOverflowProtector() {
DCHECK(!IsStringLengthOverflowIntact()); 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() { void Isolate::InvalidateArrayBufferDetachingProtector() {
DCHECK(factory()->array_buffer_detaching_protector()->value().IsSmi()); DCHECK(factory()->array_buffer_detaching_protector()->value().IsSmi());
DCHECK(IsArrayBufferDetachingIntact()); DCHECK(IsArrayBufferDetachingIntact());
......
...@@ -1177,43 +1177,6 @@ class Isolate final : private HiddenFactory { ...@@ -1177,43 +1177,6 @@ class Isolate final : private HiddenFactory {
bool IsIsConcatSpreadableLookupChainIntact(); bool IsIsConcatSpreadableLookupChainIntact();
bool IsIsConcatSpreadableLookupChainIntact(JSReceiver receiver); bool IsIsConcatSpreadableLookupChainIntact(JSReceiver receiver);
inline bool IsStringLengthOverflowIntact(); 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. // Make sure we do check for detached array buffers.
inline bool IsArrayBufferDetachingIntact(); inline bool IsArrayBufferDetachingIntact();
...@@ -1246,10 +1209,6 @@ class Isolate final : private HiddenFactory { ...@@ -1246,10 +1209,6 @@ class Isolate final : private HiddenFactory {
void InvalidateIsConcatSpreadableProtector(); void InvalidateIsConcatSpreadableProtector();
void InvalidateStringLengthOverflowProtector(); void InvalidateStringLengthOverflowProtector();
void InvalidateArrayIteratorProtector();
void InvalidateMapIteratorProtector();
void InvalidateSetIteratorProtector();
void InvalidateStringIteratorProtector();
void InvalidateArrayBufferDetachingProtector(); void InvalidateArrayBufferDetachingProtector();
V8_EXPORT_PRIVATE void InvalidatePromiseHookProtector(); V8_EXPORT_PRIVATE void InvalidatePromiseHookProtector();
void InvalidatePromiseResolveProtector(); void InvalidatePromiseResolveProtector();
......
...@@ -21,9 +21,54 @@ class Protectors : public AllStatic { ...@@ -21,9 +21,54 @@ class Protectors : public AllStatic {
#define DECLARED_PROTECTORS_ON_ISOLATE(V) \ #define DECLARED_PROTECTORS_ON_ISOLATE(V) \
V(ArraySpeciesLookupChain, ArraySpeciesProtector, array_species_protector) \ V(ArraySpeciesLookupChain, ArraySpeciesProtector, array_species_protector) \
V(ArrayConstructor, ArrayConstructorProtector, array_constructor_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(PromiseThenLookupChain, PromiseThenProtector, promise_then_protector) \
V(PromiseSpeciesLookupChain, PromiseSpeciesProtector, \ V(PromiseSpeciesLookupChain, PromiseSpeciesProtector, \
promise_species_protector) \ 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, \ V(TypedArraySpeciesLookupChain, TypedArraySpeciesProtector, \
typed_array_species_protector) typed_array_species_protector)
......
...@@ -317,26 +317,26 @@ void LookupIterator::InternalUpdateProtector() { ...@@ -317,26 +317,26 @@ void LookupIterator::InternalUpdateProtector() {
*receiver, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX)) { *receiver, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX)) {
// Setting the next property of %ArrayIteratorPrototype% also needs to // Setting the next property of %ArrayIteratorPrototype% also needs to
// invalidate the array iterator protector. // invalidate the array iterator protector.
if (!isolate_->IsArrayIteratorLookupChainIntact()) return; if (!Protectors::IsArrayIteratorLookupChainIntact(isolate_)) return;
isolate_->InvalidateArrayIteratorProtector(); Protectors::InvalidateArrayIteratorLookupChain(isolate_);
} else if (receiver->IsJSMapIterator() || } else if (receiver->IsJSMapIterator() ||
isolate_->IsInAnyContext( isolate_->IsInAnyContext(
*receiver, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX)) { *receiver, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX)) {
if (!isolate_->IsMapIteratorLookupChainIntact()) return; if (!Protectors::IsMapIteratorLookupChainIntact(isolate_)) return;
isolate_->InvalidateMapIteratorProtector(); Protectors::InvalidateMapIteratorLookupChain(isolate_);
} else if (receiver->IsJSSetIterator() || } else if (receiver->IsJSSetIterator() ||
isolate_->IsInAnyContext( isolate_->IsInAnyContext(
*receiver, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX)) { *receiver, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX)) {
if (!isolate_->IsSetIteratorLookupChainIntact()) return; if (!Protectors::IsSetIteratorLookupChainIntact(isolate_)) return;
isolate_->InvalidateSetIteratorProtector(); Protectors::InvalidateSetIteratorLookupChain(isolate_);
} else if (receiver->IsJSStringIterator() || } else if (receiver->IsJSStringIterator() ||
isolate_->IsInAnyContext( isolate_->IsInAnyContext(
*receiver, *receiver,
Context::INITIAL_STRING_ITERATOR_PROTOTYPE_INDEX)) { Context::INITIAL_STRING_ITERATOR_PROTOTYPE_INDEX)) {
// Setting the next property of %StringIteratorPrototype% invalidates the // Setting the next property of %StringIteratorPrototype% invalidates the
// string iterator protector. // string iterator protector.
if (!isolate_->IsStringIteratorLookupChainIntact()) return; if (!Protectors::IsStringIteratorLookupChainIntact(isolate_)) return;
isolate_->InvalidateStringIteratorProtector(); Protectors::InvalidateStringIteratorLookupChain(isolate_);
} }
} else if (*name_ == roots.species_symbol()) { } else if (*name_ == roots.species_symbol()) {
// Fetching the context in here since the operation is rather expensive. // Fetching the context in here since the operation is rather expensive.
...@@ -379,29 +379,29 @@ void LookupIterator::InternalUpdateProtector() { ...@@ -379,29 +379,29 @@ void LookupIterator::InternalUpdateProtector() {
isolate_->InvalidateIsConcatSpreadableProtector(); isolate_->InvalidateIsConcatSpreadableProtector();
} else if (*name_ == roots.iterator_symbol()) { } else if (*name_ == roots.iterator_symbol()) {
if (receiver->IsJSArray(isolate_)) { if (receiver->IsJSArray(isolate_)) {
if (!isolate_->IsArrayIteratorLookupChainIntact()) return; if (!Protectors::IsArrayIteratorLookupChainIntact(isolate_)) return;
isolate_->InvalidateArrayIteratorProtector(); Protectors::InvalidateArrayIteratorLookupChain(isolate_);
} else if (receiver->IsJSSet(isolate_) || receiver->IsJSSetIterator() || } else if (receiver->IsJSSet(isolate_) || receiver->IsJSSetIterator() ||
isolate_->IsInAnyContext( isolate_->IsInAnyContext(
*receiver, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX) || *receiver, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX) ||
isolate_->IsInAnyContext(*receiver, isolate_->IsInAnyContext(*receiver,
Context::INITIAL_SET_PROTOTYPE_INDEX)) { Context::INITIAL_SET_PROTOTYPE_INDEX)) {
if (isolate_->IsSetIteratorLookupChainIntact()) { if (Protectors::IsSetIteratorLookupChainIntact(isolate_)) {
isolate_->InvalidateSetIteratorProtector(); Protectors::InvalidateSetIteratorLookupChain(isolate_);
} }
} else if (receiver->IsJSMapIterator() || } else if (receiver->IsJSMapIterator() ||
isolate_->IsInAnyContext( isolate_->IsInAnyContext(
*receiver, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX)) { *receiver, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX)) {
if (isolate_->IsMapIteratorLookupChainIntact()) { if (Protectors::IsMapIteratorLookupChainIntact(isolate_)) {
isolate_->InvalidateMapIteratorProtector(); Protectors::InvalidateMapIteratorLookupChain(isolate_);
} }
} else if (isolate_->IsInAnyContext( } else if (isolate_->IsInAnyContext(
*receiver, Context::INITIAL_ITERATOR_PROTOTYPE_INDEX)) { *receiver, Context::INITIAL_ITERATOR_PROTOTYPE_INDEX)) {
if (isolate_->IsMapIteratorLookupChainIntact()) { if (Protectors::IsMapIteratorLookupChainIntact(isolate_)) {
isolate_->InvalidateMapIteratorProtector(); Protectors::InvalidateMapIteratorLookupChain(isolate_);
} }
if (isolate_->IsSetIteratorLookupChainIntact()) { if (Protectors::IsSetIteratorLookupChainIntact(isolate_)) {
isolate_->InvalidateSetIteratorProtector(); Protectors::InvalidateSetIteratorLookupChain(isolate_);
} }
} else if (isolate_->IsInAnyContext( } else if (isolate_->IsInAnyContext(
*receiver, Context::INITIAL_STRING_PROTOTYPE_INDEX)) { *receiver, Context::INITIAL_STRING_PROTOTYPE_INDEX)) {
...@@ -409,8 +409,8 @@ void LookupIterator::InternalUpdateProtector() { ...@@ -409,8 +409,8 @@ void LookupIterator::InternalUpdateProtector() {
// the string iterator protector. Symbol.iterator can also be set on a // the string iterator protector. Symbol.iterator can also be set on a
// String wrapper, but not on a primitive string. We only support // String wrapper, but not on a primitive string. We only support
// protector for primitive strings. // protector for primitive strings.
if (!isolate_->IsStringIteratorLookupChainIntact()) return; if (!Protectors::IsStringIteratorLookupChainIntact(isolate_)) return;
isolate_->InvalidateStringIteratorProtector(); Protectors::InvalidateStringIteratorLookupChain(isolate_);
} }
} else if (*name_ == roots.resolve_string()) { } else if (*name_ == roots.resolve_string()) {
if (!isolate_->IsPromiseResolveLookupChainIntact()) return; if (!isolate_->IsPromiseResolveLookupChainIntact()) return;
......
...@@ -1770,7 +1770,7 @@ bool Object::IterationHasObservableEffects() { ...@@ -1770,7 +1770,7 @@ bool Object::IterationHasObservableEffects() {
// Check that the ArrayPrototype hasn't been modified in a way that would // Check that the ArrayPrototype hasn't been modified in a way that would
// affect iteration. // affect iteration.
if (!isolate->IsArrayIteratorLookupChainIntact()) return true; if (!Protectors::IsArrayIteratorLookupChainIntact(isolate)) return true;
// For FastPacked kinds, iteration will have the same effect as simply // For FastPacked kinds, iteration will have the same effect as simply
// accessing each property in order. // accessing each property in order.
......
...@@ -1148,20 +1148,22 @@ RUNTIME_FUNCTION(Runtime_ArraySpeciesProtector) { ...@@ -1148,20 +1148,22 @@ RUNTIME_FUNCTION(Runtime_ArraySpeciesProtector) {
RUNTIME_FUNCTION(Runtime_MapIteratorProtector) { RUNTIME_FUNCTION(Runtime_MapIteratorProtector) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length()); DCHECK_EQ(0, args.length());
return isolate->heap()->ToBoolean(isolate->IsMapIteratorLookupChainIntact()); return isolate->heap()->ToBoolean(
Protectors::IsMapIteratorLookupChainIntact(isolate));
} }
RUNTIME_FUNCTION(Runtime_SetIteratorProtector) { RUNTIME_FUNCTION(Runtime_SetIteratorProtector) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length()); DCHECK_EQ(0, args.length());
return isolate->heap()->ToBoolean(isolate->IsSetIteratorLookupChainIntact()); return isolate->heap()->ToBoolean(
Protectors::IsSetIteratorLookupChainIntact(isolate));
} }
RUNTIME_FUNCTION(Runtime_StringIteratorProtector) { RUNTIME_FUNCTION(Runtime_StringIteratorProtector) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length()); DCHECK_EQ(0, args.length());
return isolate->heap()->ToBoolean( return isolate->heap()->ToBoolean(
isolate->IsStringIteratorLookupChainIntact()); Protectors::IsStringIteratorLookupChainIntact(isolate));
} }
// Take a compiled wasm module and serialize it into an array buffer, which is // 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