[protectors] Migrate final two protectors to their own file
Bug: v8:9463 Change-Id: I62290f29086c370b1f4f773de9a4d8f926edf313 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1818732 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Commit-Queue: Joshua Litt <joshualitt@chromium.org> Cr-Commit-Position: refs/heads/master@{#64005}
This commit is contained in:
parent
43f44e5311
commit
318d66d95f
@ -16,6 +16,7 @@
|
||||
#include "src/compiler/bytecode-analysis.h"
|
||||
#include "src/compiler/graph-reducer.h"
|
||||
#include "src/compiler/per-isolate-compiler-cache.h"
|
||||
#include "src/execution/protectors-inl.h"
|
||||
#include "src/init/bootstrapper.h"
|
||||
#include "src/objects/allocation-site-inl.h"
|
||||
#include "src/objects/api-callbacks.h"
|
||||
@ -1120,7 +1121,7 @@ bool SupportsFastArrayIteration(Isolate* isolate, Handle<Map> map) {
|
||||
map->prototype().IsJSArray() &&
|
||||
isolate->IsAnyInitialArrayPrototype(
|
||||
handle(JSArray::cast(map->prototype()), isolate)) &&
|
||||
isolate->IsNoElementsProtectorIntact();
|
||||
Protectors::IsNoElementsIntact(isolate);
|
||||
}
|
||||
|
||||
bool SupportsFastArrayResize(Isolate* isolate, Handle<Map> map) {
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "src/execution/isolate-inl.h"
|
||||
#include "src/execution/messages.h"
|
||||
#include "src/execution/microtask-queue.h"
|
||||
#include "src/execution/protectors-inl.h"
|
||||
#include "src/execution/runtime-profiler.h"
|
||||
#include "src/execution/simulator.h"
|
||||
#include "src/execution/v8threads.h"
|
||||
@ -3796,134 +3797,12 @@ bool Isolate::IsInAnyContext(Object object, uint32_t index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Isolate::IsNoElementsProtectorIntact(Context context) {
|
||||
PropertyCell no_elements_cell = heap()->no_elements_protector();
|
||||
bool cell_reports_intact =
|
||||
no_elements_cell.value().IsSmi() &&
|
||||
Smi::ToInt(no_elements_cell.value()) == kProtectorValid;
|
||||
|
||||
#ifdef DEBUG
|
||||
Context native_context = context.native_context();
|
||||
|
||||
Map root_array_map =
|
||||
native_context.GetInitialJSArrayMap(GetInitialFastElementsKind());
|
||||
JSObject initial_array_proto = JSObject::cast(
|
||||
native_context.get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
|
||||
JSObject initial_object_proto = JSObject::cast(
|
||||
native_context.get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX));
|
||||
JSObject initial_string_proto = JSObject::cast(
|
||||
native_context.get(Context::INITIAL_STRING_PROTOTYPE_INDEX));
|
||||
|
||||
if (root_array_map.is_null() || initial_array_proto == initial_object_proto) {
|
||||
// We are in the bootstrapping process, and the entire check sequence
|
||||
// shouldn't be performed.
|
||||
return cell_reports_intact;
|
||||
}
|
||||
|
||||
// Check that the array prototype hasn't been altered WRT empty elements.
|
||||
if (root_array_map.prototype() != initial_array_proto) {
|
||||
DCHECK_EQ(false, cell_reports_intact);
|
||||
return cell_reports_intact;
|
||||
}
|
||||
|
||||
FixedArrayBase elements = initial_array_proto.elements();
|
||||
ReadOnlyRoots roots(heap());
|
||||
if (elements != roots.empty_fixed_array() &&
|
||||
elements != roots.empty_slow_element_dictionary()) {
|
||||
DCHECK_EQ(false, cell_reports_intact);
|
||||
return cell_reports_intact;
|
||||
}
|
||||
|
||||
// Check that the Object.prototype hasn't been altered WRT empty elements.
|
||||
elements = initial_object_proto.elements();
|
||||
if (elements != roots.empty_fixed_array() &&
|
||||
elements != roots.empty_slow_element_dictionary()) {
|
||||
DCHECK_EQ(false, cell_reports_intact);
|
||||
return cell_reports_intact;
|
||||
}
|
||||
|
||||
// Check that the Array.prototype has the Object.prototype as its
|
||||
// [[Prototype]] and that the Object.prototype has a null [[Prototype]].
|
||||
PrototypeIterator iter(this, initial_array_proto);
|
||||
if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) {
|
||||
DCHECK_EQ(false, cell_reports_intact);
|
||||
DCHECK(!has_pending_exception());
|
||||
return cell_reports_intact;
|
||||
}
|
||||
iter.Advance();
|
||||
if (!iter.IsAtEnd()) {
|
||||
DCHECK_EQ(false, cell_reports_intact);
|
||||
DCHECK(!has_pending_exception());
|
||||
return cell_reports_intact;
|
||||
}
|
||||
DCHECK(!has_pending_exception());
|
||||
|
||||
// Check that the String.prototype hasn't been altered WRT empty elements.
|
||||
elements = initial_string_proto.elements();
|
||||
if (elements != roots.empty_fixed_array() &&
|
||||
elements != roots.empty_slow_element_dictionary()) {
|
||||
DCHECK_EQ(false, cell_reports_intact);
|
||||
return cell_reports_intact;
|
||||
}
|
||||
|
||||
// Check that the String.prototype has the Object.prototype
|
||||
// as its [[Prototype]] still.
|
||||
if (initial_string_proto.map().prototype() != initial_object_proto) {
|
||||
DCHECK_EQ(false, cell_reports_intact);
|
||||
return cell_reports_intact;
|
||||
}
|
||||
#endif
|
||||
|
||||
return cell_reports_intact;
|
||||
}
|
||||
|
||||
bool Isolate::IsNoElementsProtectorIntact() {
|
||||
return Isolate::IsNoElementsProtectorIntact(context());
|
||||
}
|
||||
|
||||
bool Isolate::IsPromiseHookProtectorIntact() {
|
||||
PropertyCell promise_hook_cell = heap()->promise_hook_protector();
|
||||
bool is_promise_hook_protector_intact =
|
||||
Smi::ToInt(promise_hook_cell.value()) == kProtectorValid;
|
||||
DCHECK_IMPLIES(is_promise_hook_protector_intact,
|
||||
!promise_hook_or_async_event_delegate_);
|
||||
DCHECK_IMPLIES(is_promise_hook_protector_intact,
|
||||
!promise_hook_or_debug_is_active_or_async_event_delegate_);
|
||||
return is_promise_hook_protector_intact;
|
||||
}
|
||||
|
||||
void Isolate::UpdateNoElementsProtectorOnSetElement(Handle<JSObject> object) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
if (!object->map().is_prototype_map()) return;
|
||||
if (!IsNoElementsProtectorIntact()) return;
|
||||
if (!Protectors::IsNoElementsIntact(this)) return;
|
||||
if (!IsArrayOrObjectOrStringPrototype(*object)) return;
|
||||
PropertyCell::SetValueWithInvalidation(
|
||||
this, "no_elements_protector", factory()->no_elements_protector(),
|
||||
handle(Smi::FromInt(kProtectorInvalid), this));
|
||||
}
|
||||
|
||||
void Isolate::TraceProtectorInvalidation(const char* protector_name) {
|
||||
static constexpr char kInvalidateProtectorTracingCategory[] =
|
||||
"V8.InvalidateProtector";
|
||||
static constexpr char kInvalidateProtectorTracingArg[] = "protector-name";
|
||||
|
||||
DCHECK(FLAG_trace_protector_invalidation);
|
||||
|
||||
// TODO(jgruber): Remove the PrintF once tracing can output to stdout.
|
||||
i::PrintF("Invalidating protector cell %s in isolate %p\n", protector_name,
|
||||
this);
|
||||
TRACE_EVENT_INSTANT1("v8", kInvalidateProtectorTracingCategory,
|
||||
TRACE_EVENT_SCOPE_THREAD, kInvalidateProtectorTracingArg,
|
||||
protector_name);
|
||||
}
|
||||
|
||||
void Isolate::InvalidatePromiseHookProtector() {
|
||||
DCHECK(factory()->promise_hook_protector()->value().IsSmi());
|
||||
DCHECK(IsPromiseHookProtectorIntact());
|
||||
PropertyCell::SetValueWithInvalidation(
|
||||
this, "promise_hook_protector", factory()->promise_hook_protector(),
|
||||
handle(Smi::FromInt(kProtectorInvalid), this));
|
||||
DCHECK(!IsPromiseHookProtectorIntact());
|
||||
Protectors::InvalidateNoElements(this);
|
||||
}
|
||||
|
||||
bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) {
|
||||
@ -4073,9 +3952,9 @@ void Isolate::PromiseHookStateUpdated() {
|
||||
bool promise_hook_or_debug_is_active_or_async_event_delegate =
|
||||
promise_hook_or_async_event_delegate || debug()->is_active();
|
||||
if (promise_hook_or_debug_is_active_or_async_event_delegate &&
|
||||
IsPromiseHookProtectorIntact()) {
|
||||
Protectors::IsPromiseHookIntact(this)) {
|
||||
HandleScope scope(this);
|
||||
InvalidatePromiseHookProtector();
|
||||
Protectors::InvalidatePromiseHook(this);
|
||||
}
|
||||
promise_hook_or_async_event_delegate_ = promise_hook_or_async_event_delegate;
|
||||
promise_hook_or_debug_is_active_or_async_event_delegate_ =
|
||||
|
@ -1166,18 +1166,8 @@ class Isolate final : private HiddenFactory {
|
||||
static const int kProtectorValid = 1;
|
||||
static const int kProtectorInvalid = 0;
|
||||
|
||||
// The version with an explicit context parameter can be used when
|
||||
// Isolate::context is not set up, e.g. when calling directly into C++ from
|
||||
// CSA.
|
||||
bool IsNoElementsProtectorIntact(Context context);
|
||||
V8_EXPORT_PRIVATE bool IsNoElementsProtectorIntact();
|
||||
|
||||
bool IsArrayOrObjectOrStringPrototype(Object object);
|
||||
|
||||
// Disable promise optimizations if promise (debug) hooks have ever been
|
||||
// active, because those can observe promises.
|
||||
bool IsPromiseHookProtectorIntact();
|
||||
|
||||
// On intent to set an element in object, make sure that appropriate
|
||||
// notifications occur if the set is on the elements of the array or
|
||||
// object prototype. Also ensure that changes to prototype chain between
|
||||
@ -1193,11 +1183,6 @@ class Isolate final : private HiddenFactory {
|
||||
UpdateNoElementsProtectorOnSetElement(object);
|
||||
}
|
||||
|
||||
// The `protector_name` C string must be statically allocated.
|
||||
void TraceProtectorInvalidation(const char* protector_name);
|
||||
|
||||
V8_EXPORT_PRIVATE void InvalidatePromiseHookProtector();
|
||||
|
||||
// Returns true if array is the initial array prototype in any native context.
|
||||
bool IsAnyInitialArrayPrototype(Handle<JSArray> array);
|
||||
|
||||
|
@ -16,12 +16,32 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
void TraceProtectorInvalidation(const char* protector_name) {
|
||||
DCHECK(FLAG_trace_protector_invalidation);
|
||||
static constexpr char kInvalidateProtectorTracingCategory[] =
|
||||
"V8.InvalidateProtector";
|
||||
static constexpr char kInvalidateProtectorTracingArg[] = "protector-name";
|
||||
|
||||
DCHECK(FLAG_trace_protector_invalidation);
|
||||
|
||||
// TODO(jgruber): Remove the PrintF once tracing can output to stdout.
|
||||
i::PrintF("Invalidating protector cell %s", protector_name);
|
||||
TRACE_EVENT_INSTANT1("v8", kInvalidateProtectorTracingCategory,
|
||||
TRACE_EVENT_SCOPE_THREAD, kInvalidateProtectorTracingArg,
|
||||
protector_name);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#define INVALIDATE_PROTECTOR_ON_NATIVE_CONTEXT_DEFINITION(name, cell) \
|
||||
void Protectors::Invalidate##name(Isolate* isolate, \
|
||||
Handle<NativeContext> native_context) { \
|
||||
DCHECK_EQ(*native_context, isolate->raw_native_context()); \
|
||||
DCHECK(native_context->cell().value().IsSmi()); \
|
||||
DCHECK(Is##name##Intact(native_context)); \
|
||||
if (FLAG_trace_protector_invalidation) { \
|
||||
TraceProtectorInvalidation(#name); \
|
||||
} \
|
||||
Handle<PropertyCell> species_cell(native_context->cell(), isolate); \
|
||||
PropertyCell::SetValueWithInvalidation( \
|
||||
isolate, #cell, species_cell, \
|
||||
@ -36,6 +56,9 @@ DECLARED_PROTECTORS_ON_NATIVE_CONTEXT(
|
||||
void Protectors::Invalidate##name(Isolate* isolate) { \
|
||||
DCHECK(isolate->factory()->cell()->value().IsSmi()); \
|
||||
DCHECK(Is##name##Intact(isolate)); \
|
||||
if (FLAG_trace_protector_invalidation) { \
|
||||
TraceProtectorInvalidation(#name); \
|
||||
} \
|
||||
PropertyCell::SetValueWithInvalidation( \
|
||||
isolate, #cell, isolate->factory()->cell(), \
|
||||
handle(Smi::FromInt(kProtectorInvalid), isolate)); \
|
||||
|
@ -27,6 +27,7 @@ class Protectors : public AllStatic {
|
||||
V(ArraySpeciesLookupChain, ArraySpeciesProtector, array_species_protector) \
|
||||
V(IsConcatSpreadableLookupChain, IsConcatSpreadableProtector, \
|
||||
is_concat_spreadable_protector) \
|
||||
V(NoElements, NoElementsProtector, no_elements_protector) \
|
||||
\
|
||||
/* The MapIterator protector protects the original iteration behaviors */ \
|
||||
/* of Map.prototype.keys(), Map.prototype.values(), and */ \
|
||||
@ -40,6 +41,7 @@ class Protectors : public AllStatic {
|
||||
/* property holder is the %IteratorPrototype%. Note that this also */ \
|
||||
/* invalidates the SetIterator protector (see below). */ \
|
||||
V(MapIteratorLookupChain, MapIteratorProtector, map_iterator_protector) \
|
||||
V(PromiseHook, PromiseHookProtector, promise_hook_protector) \
|
||||
V(PromiseThenLookupChain, PromiseThenProtector, promise_then_protector) \
|
||||
V(PromiseResolveLookupChain, PromiseResolveProtector, \
|
||||
promise_resolve_protector) \
|
||||
@ -81,15 +83,17 @@ class Protectors : public AllStatic {
|
||||
typed_array_species_protector)
|
||||
|
||||
#define DECLARE_PROTECTOR_ON_NATIVE_CONTEXT(name, unused_cell) \
|
||||
static inline bool Is##name##Intact(Handle<NativeContext> native_context); \
|
||||
static void Invalidate##name(Isolate* isolate, \
|
||||
Handle<NativeContext> native_context);
|
||||
V8_EXPORT_PRIVATE static inline bool Is##name##Intact( \
|
||||
Handle<NativeContext> native_context); \
|
||||
V8_EXPORT_PRIVATE static void Invalidate##name( \
|
||||
Isolate* isolate, Handle<NativeContext> native_context);
|
||||
|
||||
DECLARED_PROTECTORS_ON_NATIVE_CONTEXT(DECLARE_PROTECTOR_ON_NATIVE_CONTEXT)
|
||||
#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);
|
||||
V8_EXPORT_PRIVATE static inline bool Is##name##Intact(Isolate* isolate); \
|
||||
V8_EXPORT_PRIVATE static void Invalidate##name(Isolate* isolate);
|
||||
|
||||
DECLARED_PROTECTORS_ON_ISOLATE(DECLARE_PROTECTOR_ON_ISOLATE)
|
||||
#undef DECLARE_PROTECTOR_ON_ISOLATE
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "src/execution/execution.h"
|
||||
#include "src/execution/frames-inl.h"
|
||||
#include "src/execution/isolate-inl.h"
|
||||
#include "src/execution/protectors-inl.h"
|
||||
#include "src/execution/runtime-profiler.h"
|
||||
#include "src/handles/handles-inl.h"
|
||||
#include "src/ic/call-optimization.h"
|
||||
@ -1076,7 +1077,7 @@ bool AllowConvertHoleElementToUndefined(Isolate* isolate,
|
||||
}
|
||||
|
||||
// For other {receiver}s we need to check the "no elements" protector.
|
||||
if (isolate->IsNoElementsProtectorIntact()) {
|
||||
if (Protectors::IsNoElementsIntact(isolate)) {
|
||||
if (receiver_map->IsStringMap()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "src/execution/arguments.h"
|
||||
#include "src/execution/frames.h"
|
||||
#include "src/execution/isolate-inl.h"
|
||||
#include "src/execution/protectors-inl.h"
|
||||
#include "src/heap/factory.h"
|
||||
#include "src/heap/heap-inl.h" // For MaxNumberToStringCacheSize.
|
||||
#include "src/heap/heap-write-barrier-inl.h"
|
||||
@ -3499,7 +3500,7 @@ class TypedElementsAccessor
|
||||
return true;
|
||||
}
|
||||
|
||||
return !isolate->IsNoElementsProtectorIntact(context);
|
||||
return !Protectors::IsNoElementsIntact(isolate);
|
||||
}
|
||||
|
||||
static bool TryCopyElementsFastNumber(Context context, JSArray source,
|
||||
|
@ -1781,7 +1781,7 @@ bool Object::IterationHasObservableEffects() {
|
||||
// the prototype. This could have different results if the prototype has been
|
||||
// changed.
|
||||
if (IsHoleyElementsKind(array_kind) &&
|
||||
isolate->IsNoElementsProtectorIntact()) {
|
||||
Protectors::IsNoElementsIntact(isolate)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -7897,9 +7897,6 @@ void PropertyCell::SetValueWithInvalidation(Isolate* isolate,
|
||||
Handle<PropertyCell> cell,
|
||||
Handle<Object> new_value) {
|
||||
if (cell->value() != *new_value) {
|
||||
if (FLAG_trace_protector_invalidation) {
|
||||
isolate->TraceProtectorInvalidation(cell_name);
|
||||
}
|
||||
cell->set_value(*new_value);
|
||||
cell->dependent_code().DeoptimizeDependentCodeGroup(
|
||||
isolate, DependentCode::kPropertyCellChangedGroup);
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "src/execution/arguments.h"
|
||||
#include "src/execution/execution.h"
|
||||
#include "src/execution/futex-emulation.h"
|
||||
#include "src/execution/protectors-inl.h"
|
||||
#include "src/execution/vm-state.h"
|
||||
#include "src/handles/global-handles.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
@ -18188,10 +18189,10 @@ static void BreakArrayGuarantees(const char* script) {
|
||||
v8::Context::Scope context_scope(context);
|
||||
v8::internal::Isolate* i_isolate =
|
||||
reinterpret_cast<v8::internal::Isolate*>(isolate1);
|
||||
CHECK(i_isolate->IsNoElementsProtectorIntact());
|
||||
CHECK(v8::internal::Protectors::IsNoElementsIntact(i_isolate));
|
||||
// Run something in new isolate.
|
||||
CompileRun(script);
|
||||
CHECK(!i_isolate->IsNoElementsProtectorIntact());
|
||||
CHECK(!v8::internal::Protectors::IsNoElementsIntact(i_isolate));
|
||||
}
|
||||
isolate1->Exit();
|
||||
isolate1->Dispose();
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/simplified-operator.h"
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/execution/protectors.h"
|
||||
#include "src/heap/factory.h"
|
||||
#include "src/objects/feedback-vector.h"
|
||||
#include "test/unittests/compiler/graph-unittest.h"
|
||||
@ -193,7 +194,7 @@ TEST_F(JSCallReducerTest, PromiseConstructorWithHook) {
|
||||
graph()->NewNode(javascript()->Construct(3), promise, executor, promise,
|
||||
context, frame_state, effect, control);
|
||||
|
||||
isolate()->InvalidatePromiseHookProtector();
|
||||
Protectors::InvalidatePromiseHook(isolate());
|
||||
|
||||
Reduction r = Reduce(construct);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user