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

[protectors] Migrate ArraySpeciesProtector to Protectors

Bug: v8:9463
Change-Id: I4d9d35222597925a289a6c3055ef0ca0aaa43a2f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1775926
Commit-Queue: Joshua Litt <joshualitt@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63553}
parent 0502ae33
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/codegen/code-factory.h" #include "src/codegen/code-factory.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
#include "src/execution/isolate.h" #include "src/execution/isolate.h"
#include "src/execution/protectors-inl.h"
#include "src/handles/global-handles.h" #include "src/handles/global-handles.h"
#include "src/logging/counters.h" #include "src/logging/counters.h"
#include "src/objects/contexts.h" #include "src/objects/contexts.h"
...@@ -1468,7 +1469,7 @@ BUILTIN(ArrayConcat) { ...@@ -1468,7 +1469,7 @@ BUILTIN(ArrayConcat) {
// Avoid a real species read to avoid extra lookups to the array constructor // Avoid a real species read to avoid extra lookups to the array constructor
if (V8_LIKELY(receiver->IsJSArray() && if (V8_LIKELY(receiver->IsJSArray() &&
Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) && Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) &&
isolate->IsArraySpeciesLookupChainIntact())) { Protectors::IsArraySpeciesLookupChainIntact(isolate))) {
if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
return *result_array; return *result_array;
} }
......
...@@ -119,25 +119,6 @@ bool Isolate::IsArrayConstructorIntact() { ...@@ -119,25 +119,6 @@ bool Isolate::IsArrayConstructorIntact() {
return array_constructor_cell.value() == Smi::FromInt(kProtectorValid); return array_constructor_cell.value() == Smi::FromInt(kProtectorValid);
} }
bool Isolate::IsArraySpeciesLookupChainIntact() {
// Note: It would be nice to have debug checks to make sure that the
// species protector is accurate, but this would be hard to do for most of
// what the protector stands for:
// - You'd need to traverse the heap to check that no Array instance has
// a constructor property
// - To check that Array[Symbol.species] == Array, JS code has to execute,
// but JS cannot be invoked in callstack overflow situations
// All that could be checked reliably is that
// Array.prototype.constructor == Array. Given that limitation, no check is
// done here. In place, there are mjsunit tests harmony/array-species* which
// ensure that behavior is correct in various invalid protector cases.
PropertyCell species_cell =
PropertyCell::cast(root(RootIndex::kArraySpeciesProtector));
return species_cell.value().IsSmi() &&
Smi::ToInt(species_cell.value()) == kProtectorValid;
}
bool Isolate::IsTypedArraySpeciesLookupChainIntact() { bool Isolate::IsTypedArraySpeciesLookupChainIntact() {
PropertyCell species_cell = PropertyCell species_cell =
PropertyCell::cast(root(RootIndex::kTypedArraySpeciesProtector)); PropertyCell::cast(root(RootIndex::kTypedArraySpeciesProtector));
......
...@@ -3999,15 +3999,6 @@ void Isolate::InvalidateArrayConstructorProtector() { ...@@ -3999,15 +3999,6 @@ void Isolate::InvalidateArrayConstructorProtector() {
DCHECK(!IsArrayConstructorIntact()); DCHECK(!IsArrayConstructorIntact());
} }
void Isolate::InvalidateArraySpeciesProtector() {
DCHECK(factory()->array_species_protector()->value().IsSmi());
DCHECK(IsArraySpeciesLookupChainIntact());
PropertyCell::SetValueWithInvalidation(
this, "array_species_protector", factory()->array_species_protector(),
handle(Smi::FromInt(kProtectorInvalid), this));
DCHECK(!IsArraySpeciesLookupChainIntact());
}
void Isolate::InvalidateTypedArraySpeciesProtector() { void Isolate::InvalidateTypedArraySpeciesProtector() {
DCHECK(factory()->typed_array_species_protector()->value().IsSmi()); DCHECK(factory()->typed_array_species_protector()->value().IsSmi());
DCHECK(IsTypedArraySpeciesLookupChainIntact()); DCHECK(IsTypedArraySpeciesLookupChainIntact());
......
...@@ -1176,7 +1176,6 @@ class Isolate final : private HiddenFactory { ...@@ -1176,7 +1176,6 @@ class Isolate final : private HiddenFactory {
bool IsArrayOrObjectOrStringPrototype(Object object); bool IsArrayOrObjectOrStringPrototype(Object object);
inline bool IsArraySpeciesLookupChainIntact();
inline bool IsTypedArraySpeciesLookupChainIntact(); inline bool IsTypedArraySpeciesLookupChainIntact();
// Check that the @@species protector is intact, which guards the lookup of // Check that the @@species protector is intact, which guards the lookup of
...@@ -1264,7 +1263,6 @@ class Isolate final : private HiddenFactory { ...@@ -1264,7 +1263,6 @@ class Isolate final : private HiddenFactory {
void TraceProtectorInvalidation(const char* protector_name); void TraceProtectorInvalidation(const char* protector_name);
void InvalidateArrayConstructorProtector(); void InvalidateArrayConstructorProtector();
void InvalidateArraySpeciesProtector();
void InvalidateTypedArraySpeciesProtector(); void InvalidateTypedArraySpeciesProtector();
void InvalidateRegExpSpeciesProtector(Handle<NativeContext> native_context); void InvalidateRegExpSpeciesProtector(Handle<NativeContext> native_context);
void InvalidatePromiseSpeciesProtector(); void InvalidatePromiseSpeciesProtector();
......
...@@ -13,13 +13,22 @@ ...@@ -13,13 +13,22 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
#define DEFINE_PROTECTOR_CHECK(name, cell) \ #define DEFINE_PROTECTOR_ON_NATIVE_CONTEXT_CHECK(name, cell) \
bool Protectors::Is##name##Intact(Handle<NativeContext> native_context) { \ bool Protectors::Is##name##Intact(Handle<NativeContext> native_context) { \
PropertyCell species_cell = native_context->cell(); \ PropertyCell species_cell = native_context->cell(); \
return species_cell.value().IsSmi() && \ return species_cell.value().IsSmi() && \
Smi::ToInt(species_cell.value()) == kProtectorValid; \ Smi::ToInt(species_cell.value()) == kProtectorValid; \
} }
DECLARED_PROTECTORS(DEFINE_PROTECTOR_CHECK) DECLARED_PROTECTORS_ON_NATIVE_CONTEXT(DEFINE_PROTECTOR_ON_NATIVE_CONTEXT_CHECK)
#define DEFINE_PROTECTOR_ON_ISOLATE_CHECK(name, root_index, unused_cell) \
bool Protectors::Is##name##Intact(Isolate* isolate) { \
PropertyCell cell = \
PropertyCell::cast(isolate->root(RootIndex::k##root_index)); \
return cell.value().IsSmi() && \
Smi::ToInt(cell.value()) == kProtectorValid; \
}
DECLARED_PROTECTORS_ON_ISOLATE(DEFINE_PROTECTOR_ON_ISOLATE_CHECK)
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
#define INVALIDATE_PROTECTOR_DEFINITION(name, cell) \ #define INVALIDATE_PROTECTOR_ON_NATIVE_CONTEXT_DEFINITION(name, cell) \
void Protectors::Invalidate##name(Isolate* isolate, \ void Protectors::Invalidate##name(Isolate* isolate, \
Handle<NativeContext> native_context) { \ Handle<NativeContext> native_context) { \
DCHECK_EQ(*native_context, isolate->raw_native_context()); \ DCHECK_EQ(*native_context, isolate->raw_native_context()); \
...@@ -28,8 +28,21 @@ namespace internal { ...@@ -28,8 +28,21 @@ namespace internal {
handle(Smi::FromInt(kProtectorInvalid), isolate)); \ handle(Smi::FromInt(kProtectorInvalid), isolate)); \
DCHECK(!Is##name##Intact(native_context)); \ DCHECK(!Is##name##Intact(native_context)); \
} }
DECLARED_PROTECTORS(INVALIDATE_PROTECTOR_DEFINITION) DECLARED_PROTECTORS_ON_NATIVE_CONTEXT(
#undef INVALIDATE_PROTECTOR_DEFINITION INVALIDATE_PROTECTOR_ON_NATIVE_CONTEXT_DEFINITION)
#undef INVALIDATE_PROTECTOR_ON_NATIVE_CONTEXT_DEFINITION
#define INVALIDATE_PROTECTOR_ON_ISOLATE_DEFINITION(name, unused_index, cell) \
void Protectors::Invalidate##name(Isolate* isolate) { \
DCHECK(isolate->factory()->cell()->value().IsSmi()); \
DCHECK(Is##name##Intact(isolate)); \
PropertyCell::SetValueWithInvalidation( \
isolate, #cell, isolate->factory()->cell(), \
handle(Smi::FromInt(kProtectorInvalid), isolate)); \
DCHECK(!Is##name##Intact(isolate)); \
}
DECLARED_PROTECTORS_ON_ISOLATE(INVALIDATE_PROTECTOR_ON_ISOLATE_DEFINITION)
#undef INVALIDATE_PROTECTOR_ON_ISOLATE_DEFINITION
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -15,15 +15,25 @@ class Protectors : public AllStatic { ...@@ -15,15 +15,25 @@ class Protectors : public AllStatic {
static const int kProtectorValid = 1; static const int kProtectorValid = 1;
static const int kProtectorInvalid = 0; static const int kProtectorInvalid = 0;
#define DECLARED_PROTECTORS(V) \ #define DECLARED_PROTECTORS_ON_NATIVE_CONTEXT(V) \
V(RegExpSpeciesLookupChainProtector, regexp_species_protector) V(RegExpSpeciesLookupChainProtector, regexp_species_protector)
#define DECLARE_PROTECTOR(name, unused_cell) \ #define DECLARED_PROTECTORS_ON_ISOLATE(V) \
V(ArraySpeciesLookupChain, ArraySpeciesProtector, array_species_protector)
#define DECLARE_PROTECTOR_ON_NATIVE_CONTEXT(name, unused_cell) \
static inline bool Is##name##Intact(Handle<NativeContext> native_context); \ static inline bool Is##name##Intact(Handle<NativeContext> native_context); \
static void Invalidate##name(Isolate* isolate, \ static void Invalidate##name(Isolate* isolate, \
Handle<NativeContext> native_context); Handle<NativeContext> native_context);
DECLARED_PROTECTORS(DECLARE_PROTECTOR) DECLARED_PROTECTORS_ON_NATIVE_CONTEXT(DECLARE_PROTECTOR_ON_NATIVE_CONTEXT)
#undef DECLARE_PROTECTOR #undef DECLARE_PROTECTOR_ON_NATIVE_CONTEXT
#define DECLARE_PROTECTOR_ON_ISOLATE(name, unused_root_index, unused_cell) \
static inline bool Is##name##Intact(Isolate* isolate); \
static void Invalidate##name(Isolate* isolate);
DECLARED_PROTECTORS_ON_ISOLATE(DECLARE_PROTECTOR_ON_ISOLATE)
#undef DECLARE_PROTECTOR_ON_ISOLATE
}; };
} // namespace internal } // namespace internal
......
...@@ -247,7 +247,7 @@ void LookupIterator::InternalUpdateProtector() { ...@@ -247,7 +247,7 @@ void LookupIterator::InternalUpdateProtector() {
native_context = Handle<JSReceiver>::cast(receiver)->GetCreationContext(); native_context = Handle<JSReceiver>::cast(receiver)->GetCreationContext();
} }
if (!isolate_->IsArraySpeciesLookupChainIntact() && if (!Protectors::IsArraySpeciesLookupChainIntact(isolate_) &&
!isolate_->IsPromiseSpeciesLookupChainIntact() && !isolate_->IsPromiseSpeciesLookupChainIntact() &&
!Protectors::IsRegExpSpeciesLookupChainProtectorIntact( !Protectors::IsRegExpSpeciesLookupChainProtectorIntact(
native_context) && native_context) &&
...@@ -256,10 +256,10 @@ void LookupIterator::InternalUpdateProtector() { ...@@ -256,10 +256,10 @@ void LookupIterator::InternalUpdateProtector() {
} }
// Setting the constructor property could change an instance's @@species // Setting the constructor property could change an instance's @@species
if (receiver->IsJSArray(isolate_)) { if (receiver->IsJSArray(isolate_)) {
if (!isolate_->IsArraySpeciesLookupChainIntact()) return; if (!Protectors::IsArraySpeciesLookupChainIntact(isolate_)) return;
isolate_->CountUsage( isolate_->CountUsage(
v8::Isolate::UseCounterFeature::kArrayInstanceConstructorModified); v8::Isolate::UseCounterFeature::kArrayInstanceConstructorModified);
isolate_->InvalidateArraySpeciesProtector(); Protectors::InvalidateArraySpeciesLookupChain(isolate_);
return; return;
} else if (receiver->IsJSPromise(isolate_)) { } else if (receiver->IsJSPromise(isolate_)) {
if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return; if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return;
...@@ -287,10 +287,10 @@ void LookupIterator::InternalUpdateProtector() { ...@@ -287,10 +287,10 @@ void LookupIterator::InternalUpdateProtector() {
// prototype is pointing the same TYPED_ARRAY_PROTOTYPE. // prototype is pointing the same TYPED_ARRAY_PROTOTYPE.
if (isolate_->IsInAnyContext(*receiver, if (isolate_->IsInAnyContext(*receiver,
Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) { Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) {
if (!isolate_->IsArraySpeciesLookupChainIntact()) return; if (!Protectors::IsArraySpeciesLookupChainIntact(isolate_)) return;
isolate_->CountUsage( isolate_->CountUsage(
v8::Isolate::UseCounterFeature::kArrayPrototypeConstructorModified); v8::Isolate::UseCounterFeature::kArrayPrototypeConstructorModified);
isolate_->InvalidateArraySpeciesProtector(); Protectors::InvalidateArraySpeciesLookupChain(isolate_);
} else if (isolate_->IsInAnyContext(*receiver, } else if (isolate_->IsInAnyContext(*receiver,
Context::PROMISE_PROTOTYPE_INDEX)) { Context::PROMISE_PROTOTYPE_INDEX)) {
if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return; if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return;
...@@ -343,7 +343,7 @@ void LookupIterator::InternalUpdateProtector() { ...@@ -343,7 +343,7 @@ void LookupIterator::InternalUpdateProtector() {
native_context = Handle<JSReceiver>::cast(receiver)->GetCreationContext(); native_context = Handle<JSReceiver>::cast(receiver)->GetCreationContext();
} }
if (!isolate_->IsArraySpeciesLookupChainIntact() && if (!Protectors::IsArraySpeciesLookupChainIntact(isolate_) &&
!isolate_->IsPromiseSpeciesLookupChainIntact() && !isolate_->IsPromiseSpeciesLookupChainIntact() &&
!Protectors::IsRegExpSpeciesLookupChainProtectorIntact( !Protectors::IsRegExpSpeciesLookupChainProtectorIntact(
native_context) && native_context) &&
...@@ -353,10 +353,10 @@ void LookupIterator::InternalUpdateProtector() { ...@@ -353,10 +353,10 @@ void LookupIterator::InternalUpdateProtector() {
// Setting the Symbol.species property of any Array, Promise or TypedArray // Setting the Symbol.species property of any Array, Promise or TypedArray
// constructor invalidates the @@species protector // constructor invalidates the @@species protector
if (isolate_->IsInAnyContext(*receiver, Context::ARRAY_FUNCTION_INDEX)) { if (isolate_->IsInAnyContext(*receiver, Context::ARRAY_FUNCTION_INDEX)) {
if (!isolate_->IsArraySpeciesLookupChainIntact()) return; if (!Protectors::IsArraySpeciesLookupChainIntact(isolate_)) return;
isolate_->CountUsage( isolate_->CountUsage(
v8::Isolate::UseCounterFeature::kArraySpeciesModified); v8::Isolate::UseCounterFeature::kArraySpeciesModified);
isolate_->InvalidateArraySpeciesProtector(); Protectors::InvalidateArraySpeciesLookupChain(isolate_);
} else if (isolate_->IsInAnyContext(*receiver, } else if (isolate_->IsInAnyContext(*receiver,
Context::PROMISE_FUNCTION_INDEX)) { Context::PROMISE_FUNCTION_INDEX)) {
if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return; if (!isolate_->IsPromiseSpeciesLookupChainIntact()) return;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "src/execution/frames-inl.h" #include "src/execution/frames-inl.h"
#include "src/execution/isolate-inl.h" #include "src/execution/isolate-inl.h"
#include "src/execution/microtask-queue.h" #include "src/execution/microtask-queue.h"
#include "src/execution/protectors-inl.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
#include "src/heap/read-only-heap.h" #include "src/heap/read-only-heap.h"
#include "src/ic/ic.h" #include "src/ic/ic.h"
...@@ -1667,7 +1668,7 @@ MaybeHandle<Object> Object::ArraySpeciesConstructor( ...@@ -1667,7 +1668,7 @@ MaybeHandle<Object> Object::ArraySpeciesConstructor(
Handle<Object> default_species = isolate->array_function(); Handle<Object> default_species = isolate->array_function();
if (original_array->IsJSArray() && if (original_array->IsJSArray() &&
Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) && Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
isolate->IsArraySpeciesLookupChainIntact()) { Protectors::IsArraySpeciesLookupChainIntact(isolate)) {
return default_species; return default_species;
} }
Handle<Object> constructor = isolate->factory()->undefined_value(); Handle<Object> constructor = isolate->factory()->undefined_value();
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "src/execution/arguments-inl.h" #include "src/execution/arguments-inl.h"
#include "src/execution/frames-inl.h" #include "src/execution/frames-inl.h"
#include "src/execution/isolate-inl.h" #include "src/execution/isolate-inl.h"
#include "src/execution/protectors-inl.h"
#include "src/execution/runtime-profiler.h" #include "src/execution/runtime-profiler.h"
#include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop. #include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop.
#include "src/heap/heap-write-barrier-inl.h" #include "src/heap/heap-write-barrier-inl.h"
...@@ -1099,7 +1100,8 @@ TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION) ...@@ -1099,7 +1100,8 @@ TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
RUNTIME_FUNCTION(Runtime_ArraySpeciesProtector) { RUNTIME_FUNCTION(Runtime_ArraySpeciesProtector) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length()); DCHECK_EQ(0, args.length());
return isolate->heap()->ToBoolean(isolate->IsArraySpeciesLookupChainIntact()); return isolate->heap()->ToBoolean(
Protectors::IsArraySpeciesLookupChainIntact(isolate));
} }
RUNTIME_FUNCTION(Runtime_MapIteratorProtector) { RUNTIME_FUNCTION(Runtime_MapIteratorProtector) {
......
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