Skip to content

Commit f3d7a74

Browse files
aamCommit Queue
authored and
Commit Queue
committed
[vm/shared] Snapshot initial values of shared fields.
BUG=#56016 BUG=#55991 TEST=shared_test in appjit Change-Id: I94ee12355cea95ca1c2698ee77e7ceffe81e27e1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/371944 Commit-Queue: Alexander Aprelev <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent ae3de54 commit f3d7a74

File tree

7 files changed

+99
-50
lines changed

7 files changed

+99
-50
lines changed

runtime/vm/app_snapshot.cc

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7112,10 +7112,11 @@ class ProgramSerializationRoots : public SerializationRoots {
71127112
s->Push(initial_field_table->At(i));
71137113
}
71147114

7115-
FieldTable* shared_field_table =
7116-
s->thread()->isolate_group()->shared_field_table();
7117-
for (intptr_t i = 0, n = shared_field_table->NumFieldIds(); i < n; i++) {
7118-
s->Push(shared_field_table->At(i));
7115+
FieldTable* shared_initial_field_table =
7116+
s->thread()->isolate_group()->shared_initial_field_table();
7117+
for (intptr_t i = 0, n = shared_initial_field_table->NumFieldIds(); i < n;
7118+
i++) {
7119+
s->Push(shared_initial_field_table->At(i));
71197120
}
71207121

71217122
dispatch_table_entries_ = object_store_->dispatch_table_code_entries();
@@ -7150,12 +7151,13 @@ class ProgramSerializationRoots : public SerializationRoots {
71507151
s->WriteRootRef(initial_field_table->At(i), "some-static-field");
71517152
}
71527153

7153-
FieldTable* shared_field_table =
7154-
s->thread()->isolate_group()->shared_field_table();
7155-
intptr_t n_shared = shared_field_table->NumFieldIds();
7154+
FieldTable* shared_initial_field_table =
7155+
s->thread()->isolate_group()->shared_initial_field_table();
7156+
intptr_t n_shared = shared_initial_field_table->NumFieldIds();
71567157
s->WriteUnsigned(n_shared);
71577158
for (intptr_t i = 0; i < n_shared; i++) {
7158-
s->WriteRootRef(shared_field_table->At(i), "some-shared-static-field");
7159+
s->WriteRootRef(shared_initial_field_table->At(i),
7160+
"some-shared-static-field");
71597161
}
71607162

71617163
// The dispatch table is serialized only for precompiled snapshots.
@@ -7212,12 +7214,14 @@ class ProgramDeserializationRoots : public DeserializationRoots {
72127214
}
72137215

72147216
{
7215-
FieldTable* shared_field_table =
7216-
d->thread()->isolate_group()->shared_field_table();
7217+
FieldTable* shared_initial_field_table =
7218+
d->thread()->isolate_group()->shared_initial_field_table();
72177219
intptr_t n_shared = d->ReadUnsigned();
7218-
shared_field_table->AllocateIndex(n_shared);
7219-
for (intptr_t i = 0; i < n_shared; i++) {
7220-
shared_field_table->SetAt(i, d->ReadRef());
7220+
if (n_shared > 0) {
7221+
shared_initial_field_table->AllocateIndex(n_shared - 1);
7222+
for (intptr_t i = 0; i < n_shared; i++) {
7223+
shared_initial_field_table->SetAt(i, d->ReadRef());
7224+
}
72217225
}
72227226
}
72237227

runtime/vm/compiler/aot/precompiler.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,7 @@ void Precompiler::AddField(const Field& field) {
13291329
fields_to_retain_.Insert(&Field::ZoneHandle(Z, field.ptr()));
13301330

13311331
if (field.is_static()) {
1332-
auto field_table = field.is_shared() ? IG->shared_field_table()
1332+
auto field_table = field.is_shared() ? IG->shared_initial_field_table()
13331333
: IG->initial_field_table();
13341334
const Object& value = Object::Handle(Z, field_table->At(field.field_id()));
13351335
// Should not be in the middle of initialization while precompiling.

runtime/vm/dart.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,12 @@ ErrorPtr Dart::InitializeIsolateGroup(Thread* T,
920920
Object::VerifyBuiltinVtables();
921921

922922
auto IG = T->isolate_group();
923+
{
924+
SafepointReadRwLocker reader(T, IG->program_lock());
925+
IG->set_shared_field_table(T, IG->shared_initial_field_table()->Clone(
926+
/*for_isolate=*/nullptr,
927+
/*for_isolate_group=*/IG));
928+
}
923929
DEBUG_ONLY(IG->heap()->Verify("InitializeIsolate", kForbidMarked));
924930

925931
#if !defined(DART_PRECOMPILED_RUNTIME)

runtime/vm/field_table.cc

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ intptr_t FieldTable::FieldOffsetFor(intptr_t field_id) {
5555
bool FieldTable::Register(const Field& field, intptr_t expected_field_id) {
5656
DEBUG_ASSERT(
5757
IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
58-
ASSERT(is_shared_ == field.is_shared());
5958
ASSERT(is_ready_to_use_);
6059

6160
if (free_head_ < 0) {
@@ -119,28 +118,39 @@ void FieldTable::Grow(intptr_t new_capacity) {
119118
// Ensure that new_table_ is populated before it is published
120119
// via store to table_.
121120
reinterpret_cast<AcqRelAtomic<ObjectPtr*>*>(&table_)->store(new_table);
122-
if (isolate_ != nullptr && isolate_->mutator_thread() != nullptr) {
123-
if (is_shared_) {
124-
isolate_->mutator_thread()->shared_field_table_values_ = table_;
125-
} else {
126-
isolate_->mutator_thread()->field_table_values_ = table_;
127-
}
121+
if (isolate_group_ != nullptr) {
122+
isolate_group_->ForEachIsolate(
123+
[&](Isolate* isolate) {
124+
if (isolate->mutator_thread() != nullptr) {
125+
isolate->mutator_thread()->shared_field_table_values_ = table_;
126+
}
127+
},
128+
/*at_safepoint=*/false);
129+
} else if (isolate_ != nullptr && isolate_->mutator_thread() != nullptr) {
130+
isolate_->mutator_thread()->field_table_values_ = table_;
128131
}
129132
}
130133

131-
FieldTable* FieldTable::Clone(Isolate* for_isolate) {
134+
FieldTable* FieldTable::Clone(Isolate* for_isolate,
135+
IsolateGroup* for_isolate_group) {
132136
DEBUG_ASSERT(
133137
IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
134138

135-
FieldTable* clone = new FieldTable(for_isolate);
136-
auto new_table =
137-
static_cast<ObjectPtr*>(malloc(capacity_ * sizeof(ObjectPtr))); // NOLINT
138-
memmove(new_table, table_, capacity_ * sizeof(ObjectPtr));
139+
FieldTable* clone = new FieldTable(for_isolate, for_isolate_group);
139140
ASSERT(clone->table_ == nullptr);
140-
clone->table_ = new_table;
141-
clone->capacity_ = capacity_;
142-
clone->top_ = top_;
143-
clone->free_head_ = free_head_;
141+
if (table_ == nullptr) {
142+
ASSERT(capacity_ == 0);
143+
ASSERT(top_ == 0);
144+
ASSERT(free_head_ == -1);
145+
} else {
146+
auto new_table = static_cast<ObjectPtr*>(
147+
malloc(capacity_ * sizeof(ObjectPtr))); // NOLINT
148+
memmove(new_table, table_, capacity_ * sizeof(ObjectPtr));
149+
clone->table_ = new_table;
150+
clone->capacity_ = capacity_;
151+
clone->top_ = top_;
152+
clone->free_head_ = free_head_;
153+
}
144154
return clone;
145155
}
146156

runtime/vm/field_table.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ class FieldInvalidator;
2222

2323
class FieldTable {
2424
public:
25-
explicit FieldTable(Isolate* isolate, bool is_shared = false)
25+
explicit FieldTable(Isolate* isolate, IsolateGroup* isolate_group = nullptr)
2626
: top_(0),
2727
capacity_(0),
2828
free_head_(-1),
2929
table_(nullptr),
3030
old_tables_(new MallocGrowableArray<ObjectPtr*>()),
3131
isolate_(isolate),
32-
is_ready_to_use_(isolate == nullptr),
33-
is_shared_(is_shared) {}
32+
isolate_group_(isolate_group),
33+
is_ready_to_use_(isolate == nullptr) {}
3434

3535
~FieldTable();
3636

@@ -88,7 +88,8 @@ class FieldTable {
8888
}
8989
}
9090

91-
FieldTable* Clone(Isolate* for_isolate);
91+
FieldTable* Clone(Isolate* for_isolate,
92+
IsolateGroup* for_isolate_group = nullptr);
9293

9394
void VisitObjectPointers(ObjectPointerVisitor* visitor);
9495

@@ -114,15 +115,12 @@ class FieldTable {
114115
// Growing the field table will keep the cached field table on the isolate's
115116
// mutator thread up-to-date.
116117
Isolate* isolate_;
118+
IsolateGroup* isolate_group_;
117119

118120
// Whether this field table is ready to use by e.g. registering new static
119121
// fields.
120122
bool is_ready_to_use_ = false;
121123

122-
// Is this the shared field table? Need to know what is the isolate's property
123-
// that have to be updated.
124-
bool is_shared_ = false;
125-
126124
DISALLOW_COPY_AND_ASSIGN(FieldTable);
127125
};
128126

runtime/vm/isolate.cc

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,9 @@ IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
351351
heap_(nullptr),
352352
saved_unlinked_calls_(Array::null()),
353353
initial_field_table_(new FieldTable(/*isolate=*/nullptr)),
354-
shared_field_table_(new FieldTable(/*isolate=*/nullptr, /*shared=*/true)),
354+
shared_initial_field_table_(new FieldTable(/*isolate=*/nullptr,
355+
/*isolate_group=*/nullptr)),
356+
shared_field_table_(new FieldTable(/*isolate=*/nullptr, this)),
355357
#if !defined(DART_PRECOMPILED_RUNTIME)
356358
background_compiler_(new BackgroundCompiler(this)),
357359
#endif
@@ -784,21 +786,35 @@ void IsolateGroup::ValidateClassTable() {
784786
}
785787
#endif // DEBUG
786788

789+
void IsolateGroup::RegisterSharedStaticField(const Field& field,
790+
const Object& initial_value) {
791+
const bool need_to_grow_backing_store =
792+
shared_initial_field_table()->Register(field);
793+
const intptr_t field_id = field.field_id();
794+
shared_initial_field_table()->SetAt(field_id, initial_value.ptr());
795+
796+
if (need_to_grow_backing_store) {
797+
// We have to stop other isolates from accessing shared isolate group
798+
// field state, since we'll have to grow the backing store.
799+
GcSafepointOperationScope scope(Thread::Current());
800+
const bool need_to_grow_other_backing_store =
801+
shared_field_table()->Register(field, field_id);
802+
ASSERT(need_to_grow_other_backing_store);
803+
} else {
804+
const bool need_to_grow_other_backing_store =
805+
shared_field_table()->Register(field, field_id);
806+
ASSERT(!need_to_grow_other_backing_store);
807+
}
808+
shared_field_table()->SetAt(field_id, initial_value.ptr());
809+
}
810+
787811
void IsolateGroup::RegisterStaticField(const Field& field,
788812
const Object& initial_value) {
789813
ASSERT(program_lock()->IsCurrentThreadWriter());
790814

791815
ASSERT(field.is_static());
792816
if (field.is_shared()) {
793-
GcSafepointOperationScope scope(Thread::Current());
794-
if (shared_field_table()->Register(field)) {
795-
for (auto isolate : isolates_) {
796-
isolate->mutator_thread()->shared_field_table_values_ =
797-
shared_field_table()->table();
798-
}
799-
}
800-
const intptr_t field_id = field.field_id();
801-
shared_field_table()->SetAt(field_id, initial_value.ptr());
817+
RegisterSharedStaticField(field, initial_value);
802818
return;
803819
}
804820
const bool need_to_grow_backing_store =
@@ -2915,6 +2931,7 @@ void IsolateGroup::VisitSharedPointers(ObjectPointerVisitor* visitor) {
29152931
}
29162932
visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&saved_unlinked_calls_));
29172933
initial_field_table()->VisitObjectPointers(visitor);
2934+
shared_initial_field_table()->VisitObjectPointers(visitor);
29182935
shared_field_table()->VisitObjectPointers(visitor);
29192936

29202937
// Visit the boxed_field_list_.

runtime/vm/isolate.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,17 +747,30 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
747747
initial_field_table_ = field_table;
748748
}
749749

750+
FieldTable* shared_initial_field_table() const {
751+
return shared_initial_field_table_.get();
752+
}
753+
std::shared_ptr<FieldTable> shared_initial_field_table_shareable() {
754+
return shared_initial_field_table_;
755+
}
756+
void set_shared_initial_field_table(std::shared_ptr<FieldTable> field_table) {
757+
shared_initial_field_table_ = field_table;
758+
}
759+
750760
FieldTable* shared_field_table() const { return shared_field_table_.get(); }
751761
std::shared_ptr<FieldTable> shared_field_table_shareable() {
752762
return shared_field_table_;
753763
}
754-
void set_shared_field_table(std::shared_ptr<FieldTable> field_table) {
755-
shared_field_table_ = field_table;
764+
void set_shared_field_table(Thread* T, FieldTable* shared_field_table) {
765+
shared_field_table_.reset(shared_field_table);
766+
T->shared_field_table_values_ = shared_field_table->table();
756767
}
757768

758769
MutatorThreadPool* thread_pool() { return thread_pool_.get(); }
759770

760771
void RegisterClass(const Class& cls);
772+
void RegisterSharedStaticField(const Field& field,
773+
const Object& initial_value);
761774
void RegisterStaticField(const Field& field, const Object& initial_value);
762775
void FreeStaticField(const Field& field);
763776

@@ -872,6 +885,7 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
872885
intptr_t dispatch_table_snapshot_size_ = 0;
873886
ArrayPtr saved_unlinked_calls_;
874887
std::shared_ptr<FieldTable> initial_field_table_;
888+
std::shared_ptr<FieldTable> shared_initial_field_table_;
875889
std::shared_ptr<FieldTable> shared_field_table_;
876890
uint32_t isolate_group_flags_ = 0;
877891

0 commit comments

Comments
 (0)