Commit 5258364e authored by Jakob Gruber's avatar Jakob Gruber Committed by V8 LUCI CQ

[compiler] Make NativeContextRef never-serialized

Most NativeContext elements are immutable after initialization;
additionally, we now use acquire-release semantics to load/store
elements when possible. Reading and constructing Refs for elements
is thus possible from the background.

A few notes:

- A few elements are not immutable; if read from the background
thread, these must use acquire-release semantics.
- Elements can be stored from generated code; these are not compatible
with bg-thread accesses.
- While elements can be read safely from the native context, the
elements themselves may still require serialization; this is done in
NativeContextRef::Serialize.

Bug: v8:7790
Change-Id: I12e9611a292e7dd912438c712390731a5422407d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2897254
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74604}
parent feee80b0
......@@ -3310,11 +3310,6 @@ BIMODAL_ACCESSOR_WITH_FLAG(Map, Object, GetConstructor)
BIMODAL_ACCESSOR_WITH_FLAG(Map, HeapObject, GetBackPointer)
BIMODAL_ACCESSOR_C(Map, bool, is_abandoned_prototype_map)
#define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
BIMODAL_ACCESSOR(NativeContext, type, name)
BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR)
#undef DEF_NATIVE_CONTEXT_ACCESSOR
BIMODAL_ACCESSOR_C(ObjectBoilerplateDescription, int, size)
BIMODAL_ACCESSOR(PropertyCell, Object, value)
......@@ -3666,6 +3661,39 @@ bool StringRef::IsSeqString() const {
return data()->AsString()->is_seq_string();
}
void NativeContextRef::Serialize() {
// TODO(jgruber): Disable visitation if should_access_heap() once all
// NativeContext element refs can be created on background threads. Until
// then, we *must* iterate them and create refs at serialization-time (even
// though NativeContextRef itself is never-serialized).
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
if (data_->should_access_heap()) {
#define SERIALIZE_MEMBER(type, name) \
{ \
ObjectData* member_data = broker()->GetOrCreateData(object()->name()); \
if (member_data->IsMap() && !InstanceTypeChecker::IsContext( \
member_data->AsMap()->instance_type())) { \
member_data->AsMap()->SerializeConstructor(broker()); \
} \
if (member_data->IsJSFunction()) { \
member_data->AsJSFunction()->Serialize(broker()); \
} \
}
BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(SERIALIZE_MEMBER)
#undef SERIALIZE_MEMBER
} else {
data()->AsNativeContext()->Serialize(broker());
}
}
void NativeContextRef::SerializeOnBackground() {
if (data_->should_access_heap()) return;
CHECK(broker()->mode() == JSHeapBroker::kSerializing ||
broker()->mode() == JSHeapBroker::kSerialized);
data()->AsNativeContext()->SerializeOnBackground(broker());
}
bool NativeContextRef::is_unserialized_heap_object() const {
return data_->kind() == kUnserializedHeapObject;
}
......@@ -3678,15 +3706,6 @@ ScopeInfoRef NativeContextRef::scope_info() const {
return ScopeInfoRef(broker(), data()->AsNativeContext()->scope_info());
}
SharedFunctionInfoRef FeedbackVectorRef::shared_function_info() const {
if (data_->should_access_heap()) {
return MakeRef(broker(), object()->shared_function_info());
}
return SharedFunctionInfoRef(
broker(), data()->AsFeedbackVector()->shared_function_info());
}
MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const {
DCHECK_GE(index, Context::FIRST_FUNCTION_MAP_INDEX);
DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
......@@ -3719,6 +3738,18 @@ MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const {
}
}
#define DEF_NATIVE_CONTEXT_ACCESSOR(ResultType, Name) \
ResultType##Ref NativeContextRef::Name() const { \
if (data_->should_access_heap()) { \
return MakeRefAssumeMemoryFence( \
broker(), ResultType::cast(object()->Name(kAcquireLoad))); \
} \
return ResultType##Ref(broker(), \
ObjectRef::data()->AsNativeContext()->Name()); \
}
BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR)
#undef DEF_NATIVE_CONTEXT_ACCESSOR
base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction(
const MapRef& map) const {
CHECK(map.IsPrimitiveMap());
......@@ -4098,6 +4129,15 @@ bool FeedbackVectorRef::serialized() const {
return data()->AsFeedbackVector()->serialized();
}
SharedFunctionInfoRef FeedbackVectorRef::shared_function_info() const {
if (data_->should_access_heap()) {
return MakeRef(broker(), object()->shared_function_info());
}
return SharedFunctionInfoRef(
broker(), data()->AsFeedbackVector()->shared_function_info());
}
bool NameRef::IsUniqueName() const {
// Must match Name::IsUniqueName.
return IsInternalizedString() || IsSymbol();
......@@ -4367,19 +4407,6 @@ void SourceTextModuleRef::Serialize() {
data()->AsSourceTextModule()->Serialize(broker());
}
void NativeContextRef::Serialize() {
if (data_->should_access_heap()) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsNativeContext()->Serialize(broker());
}
void NativeContextRef::SerializeOnBackground() {
if (data_->should_access_heap()) return;
CHECK(broker()->mode() == JSHeapBroker::kSerializing ||
broker()->mode() == JSHeapBroker::kSerialized);
data()->AsNativeContext()->SerializeOnBackground(broker());
}
void JSTypedArrayRef::Serialize() {
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) {
// Even if the typed array object itself is no longer serialized (besides
......
......@@ -88,7 +88,7 @@ enum class RefSerializationKind {
V(JSGlobalProxy, RefSerializationKind::kSerialized) \
V(JSTypedArray, RefSerializationKind::kSerialized) \
/* Subtypes of Context */ \
V(NativeContext, RefSerializationKind::kSerialized) \
V(NativeContext, RefSerializationKind::kNeverSerialized) \
/* Subtypes of FixedArray */ \
V(ObjectBoilerplateDescription, RefSerializationKind::kNeverSerialized) \
V(ScriptContextTable, RefSerializationKind::kBackgroundSerialized) \
......
......@@ -694,6 +694,17 @@ class NativeContext : public Context {
ScriptContextTable script_context_table);
inline ScriptContextTable synchronized_script_context_table() const;
// Caution, hack: this getter ignores the AcquireLoadTag. The global_object
// slot is safe to read concurrently since it is immutable after
// initialization. This function should *not* be used from anywhere other
// than heap-refs.cc.
// TODO(jgruber): Remove this function after NativeContextRef is actually
// never serialized and BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS is removed.
JSGlobalObject global_object() { return Context::global_object(); }
JSGlobalObject global_object(AcquireLoadTag) {
return Context::global_object();
}
// Dispatched behavior.
DECL_PRINTER(NativeContext)
DECL_VERIFIER(NativeContext)
......
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