Files
sdk/runtime/vm/field_table.h
T
Ryan Macnak 4bb6609724 [vm] C++20 updates.
- std::atomic_ref
  - std::bit_cast
  - std::rotl,rotr
  - designated initializers

TEST=ci
Bug: https://github.com/dart-lang/sdk/issues/42074
Change-Id: I7be17147723db6f7620a147e75d38ebe46393f8c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/484700
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
2026-03-04 12:40:19 -08:00

131 lines
3.9 KiB
C++

// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_FIELD_TABLE_H_
#define RUNTIME_VM_FIELD_TABLE_H_
#include "platform/assert.h"
#include "platform/atomic.h"
#include "vm/bitfield.h"
#include "vm/class_id.h"
#include "vm/globals.h"
#include "vm/growable_array.h"
#include "vm/tagged_pointer.h"
namespace dart {
class Isolate;
class Field;
class FieldInvalidator;
class FieldTable {
public:
explicit FieldTable(Isolate* isolate, IsolateGroup* isolate_group = nullptr)
: top_(0),
capacity_(0),
free_head_(-1),
table_(nullptr),
old_tables_(new MallocGrowableArray<ObjectPtr*>()),
isolate_(isolate),
isolate_group_(isolate_group),
is_ready_to_use_(isolate == nullptr) {}
~FieldTable();
bool IsReadyToUse() const;
void MarkReadyToUse();
intptr_t NumFieldIds() const { return top_; }
intptr_t Capacity() const { return capacity_; }
ObjectPtr* table() { return table_; }
void FreeOldTables();
// Used by the generated code.
static intptr_t FieldOffsetFor(intptr_t field_id);
bool IsValidIndex(intptr_t index) const { return index >= 0 && index < top_; }
// Returns whether registering this field caused a growth in the backing
// store.
bool Register(const Field& field, intptr_t expected_field_id = -1);
void AllocateIndex(intptr_t index);
// Static field elements are being freed only during isolate reload
// when initially created static field have to get remapped to point
// to an existing static field value.
void Free(intptr_t index);
ObjectPtr At(intptr_t index, bool concurrent_use = false) const {
ASSERT(IsValidIndex(index));
if (concurrent_use) {
ObjectPtr* table =
std::atomic_ref(table_).load(std::memory_order::acquire);
return std::atomic_ref(table[index]).load(std::memory_order_acquire);
} else {
// There is no concurrent access expected for this field, so we avoid
// using atomics. This will allow us to detect via TSAN if there are
// racy uses.
return table_[index];
}
}
void SetAt(intptr_t index,
ObjectPtr raw_instance,
bool concurrent_use = false) {
ASSERT(index < capacity_);
ObjectPtr* slot = &table_[index];
if (concurrent_use) {
reinterpret_cast<AcqRelAtomic<ObjectPtr>*>(slot)->store(raw_instance);
} else {
// There is no concurrent access expected for this field, so we avoid
// using atomics. This will allow us to detect via TSAN if there are
// racy uses.
*slot = raw_instance;
}
}
FieldTable* Clone(Isolate* for_isolate,
IsolateGroup* for_isolate_group = nullptr);
void VisitObjectPointers(ObjectPointerVisitor* visitor);
static constexpr int kInitialCapacity = 512;
static constexpr int kCapacityIncrement = 256;
private:
void Grow(intptr_t new_capacity);
intptr_t top_;
intptr_t capacity_;
// -1 if free list is empty, otherwise index of first empty element. Empty
// elements are organized into linked list - they contain index of next
// element, last element contains -1.
intptr_t free_head_;
// Mutable for atomic_ref in At.
mutable ObjectPtr* table_;
// When table_ grows and have to reallocated, keep the old one here
// so it will get freed when its are no longer in use.
MallocGrowableArray<ObjectPtr*>* old_tables_;
// If non-null, it will specify the isolate this field table belongs to.
// Growing the field table will keep the cached field table on the isolate's
// mutator thread up-to-date.
Isolate* isolate_;
IsolateGroup* isolate_group_;
// Whether this field table is ready to use by e.g. registering new static
// fields.
bool is_ready_to_use_ = false;
DISALLOW_COPY_AND_ASSIGN(FieldTable);
};
} // namespace dart
#endif // RUNTIME_VM_FIELD_TABLE_H_