Flutter Engine
The Flutter Engine
field_table.cc
Go to the documentation of this file.
1// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/field_table.h"
6
7#include "platform/atomic.h"
8#include "vm/flags.h"
9#include "vm/growable_array.h"
10#include "vm/heap/heap.h"
11#include "vm/object.h"
12#include "vm/object_graph.h"
13#include "vm/object_store.h"
14#include "vm/raw_object.h"
15#include "vm/visitor.h"
16
17namespace dart {
18
21 delete old_tables_; // Allocated in FieldTable::FieldTable()
22 free(table_); // Allocated in FieldTable::Grow()
23}
24
27 IsolateGroup::Current()->IsReloading() ||
28 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
29 return is_ready_to_use_;
30}
31
33 // The isolate will mark it's field table ready-to-use upon initialization of
34 // the isolate. Only after it was marked as ready-to-use will it participate
35 // in new static field registrations.
36 //
37 // By requiring a read lock here we ensure no other thread is is registering a
38 // new static field at this moment (it would need exclusive writer lock).
40 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
41 ASSERT(!is_ready_to_use_);
42 is_ready_to_use_ = true;
43}
44
46 while (old_tables_->length() > 0) {
47 free(old_tables_->RemoveLast());
48 }
49}
50
51intptr_t FieldTable::FieldOffsetFor(intptr_t field_id) {
52 return field_id * sizeof(ObjectPtr); // NOLINT
53}
54
55bool FieldTable::Register(const Field& field, intptr_t expected_field_id) {
57 IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
58 ASSERT(is_ready_to_use_);
59
60 if (free_head_ < 0) {
61 bool grown_backing_store = false;
62 if (top_ == capacity_) {
63 const intptr_t new_capacity = capacity_ + kCapacityIncrement;
64 Grow(new_capacity);
65 grown_backing_store = true;
66 }
67
68 ASSERT(top_ < capacity_);
69 ASSERT(expected_field_id == -1 || expected_field_id == top_);
70 field.set_field_id(top_);
71 table_[top_] = Object::sentinel().ptr();
72
73 ++top_;
74 return grown_backing_store;
75 }
76
77 // Reuse existing free element. This is "slow path" that should only be
78 // triggered after hot reload.
79 intptr_t reused_free = free_head_;
80 free_head_ = Smi::Value(Smi::RawCast(table_[free_head_]));
81 field.set_field_id(reused_free);
82 table_[reused_free] = Object::sentinel().ptr();
83 return false;
84}
85
86void FieldTable::Free(intptr_t field_id) {
87 table_[field_id] = Smi::New(free_head_);
88 free_head_ = field_id;
89}
90
91void FieldTable::AllocateIndex(intptr_t index) {
92 if (index >= capacity_) {
93 const intptr_t new_capacity = index + kCapacityIncrement;
94 Grow(new_capacity);
95 }
96
97 ASSERT(table_[index] == ObjectPtr());
98 if (index >= top_) {
99 top_ = index + 1;
100 }
101}
102
103void FieldTable::Grow(intptr_t new_capacity) {
104 ASSERT(new_capacity > capacity_);
105
106 auto old_table = table_;
107 auto new_table = static_cast<ObjectPtr*>(
108 malloc(new_capacity * sizeof(ObjectPtr))); // NOLINT
109 intptr_t i;
110 for (i = 0; i < top_; i++) {
111 new_table[i] = old_table[i];
112 }
113 for (; i < new_capacity; i++) {
114 new_table[i] = ObjectPtr();
115 }
116 capacity_ = new_capacity;
117 old_tables_->Add(old_table);
118 // Ensure that new_table_ is populated before it is published
119 // via store to table_.
120 reinterpret_cast<AcqRelAtomic<ObjectPtr*>*>(&table_)->store(new_table);
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_;
131 }
132}
133
135 IsolateGroup* for_isolate_group) {
137 IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
138
139 FieldTable* clone = new FieldTable(for_isolate, for_isolate_group);
140 ASSERT(clone->table_ == nullptr);
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 }
154 return clone;
155}
156
158 // GC might try to visit field table before it's isolate done setting it up.
159 if (table_ == nullptr) {
160 return;
161 }
162
163 ASSERT(visitor != nullptr);
164 visitor->set_gc_root_type("static fields table");
165 visitor->VisitPointers(&table_[0], &table_[top_ - 1]);
166 visitor->clear_gc_root_type();
167}
168
169} // namespace dart
SI void store(P *ptr, const T &val)
#define DEBUG_ASSERT(cond)
Definition: assert.h:321
void FreeOldTables()
Definition: field_table.cc:45
bool Register(const Field &field, intptr_t expected_field_id=-1)
Definition: field_table.cc:55
void Free(intptr_t index)
Definition: field_table.cc:86
void AllocateIndex(intptr_t index)
Definition: field_table.cc:91
bool IsReadyToUse() const
Definition: field_table.cc:25
static constexpr int kCapacityIncrement
Definition: field_table.h:97
static intptr_t FieldOffsetFor(intptr_t field_id)
Definition: field_table.cc:51
void MarkReadyToUse()
Definition: field_table.cc:32
FieldTable * Clone(Isolate *for_isolate, IsolateGroup *for_isolate_group=nullptr)
Definition: field_table.cc:134
FieldTable(Isolate *isolate, IsolateGroup *isolate_group=nullptr)
Definition: field_table.h:25
void VisitObjectPointers(ObjectPointerVisitor *visitor)
Definition: field_table.cc:157
void set_field_id(intptr_t field_id) const
Definition: object.h:13288
void ForEachIsolate(std::function< void(Isolate *isolate)> function, bool at_safepoint=false)
Definition: isolate.cc:2841
static IsolateGroup * Current()
Definition: isolate.h:539
Thread * mutator_thread() const
Definition: isolate.cc:1920
void set_gc_root_type(const char *gc_root_type)
Definition: visitor.h:58
virtual void VisitPointers(ObjectPtr *first, ObjectPtr *last)=0
static ObjectPtr RawCast(ObjectPtr obj)
Definition: object.h:325
static SmiPtr New(intptr_t value)
Definition: object.h:10006
intptr_t Value() const
Definition: object.h:9990
#define ASSERT(E)
Definition: dart_vm.cc:33
void * malloc(size_t size)
Definition: allocation.cc:19