[vm] Reland support for real unboxed floating point fields in AOT

Issue https://github.com/dart-lang/sdk/issues/40404

Change-Id: Icfa801ff0640a6b27bb3c13d0b737c40452cbf7d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133983
Commit-Queue: Victor Agnez Lima <victoragnez@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Victor Lima
2020-01-31 12:56:31 +00:00
committed by commit-bot@chromium.org
parent 906c6ea21c
commit b68d95ec9e
47 changed files with 3783 additions and 681 deletions
@@ -0,0 +1,151 @@
// 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.
// VMOptions=
// VMOptions=--use_compactor
// VMOptions=--use_compactor --force_evacuation
import 'dart:typed_data';
import 'package:observatory/service_io.dart';
import 'package:unittest/unittest.dart';
import 'test_helper.dart';
double getDoubleWithHeapObjectTag() {
final bd = ByteData(8);
bd.setUint64(0, 0x8000000000000001, Endian.host);
final double v = bd.getFloat64(0, Endian.host);
return v;
}
// small example from [Lenguaer & Tarjan 1979]
class R {
final double fld = getDoubleWithHeapObjectTag();
var x;
var y;
var z;
}
class A {
var x;
}
class B {
var x;
var y;
var z;
}
class C {
var x;
var y;
}
class D {
var x;
}
class E {
var x;
}
class F {
var x;
}
class G {
var x;
var y;
}
class H {
var x;
var y;
}
class I {
var x;
}
class J {
var x;
}
class K {
var x;
var y;
}
class L {
var x;
}
var r;
buildGraph() {
r = new R();
var a = new A();
var b = new B();
var c = new C();
var d = new D();
var e = new E();
var f = new F();
var g = new G();
var h = new H();
var i = new I();
var j = new J();
var k = new K();
var l = new L();
r.x = a;
r.y = b;
r.z = c;
a.x = d;
b.x = a;
b.y = d;
b.z = e;
c.x = f;
c.y = g;
d.x = l;
e.x = h;
f.x = i;
g.x = i;
g.y = j;
h.x = e;
h.y = k;
i.x = k;
j.x = i;
k.x = i;
k.y = r;
l.x = h;
expect(r.fld, getDoubleWithHeapObjectTag());
}
var tests = <IsolateTest>[
(Isolate isolate) async {
final graph = await isolate.fetchHeapSnapshot().done;
node(String className) {
return graph.objects.singleWhere((v) => v.klass.name == className);
}
expect(node('I').parent, equals(node('R')));
expect(node('K').parent, equals(node('R')));
expect(node('C').parent, equals(node('R')));
expect(node('H').parent, equals(node('R')));
expect(node('E').parent, equals(node('R')));
expect(node('A').parent, equals(node('R')));
expect(node('D').parent, equals(node('R')));
expect(node('B').parent, equals(node('R')));
expect(node('F').parent, equals(node('C')));
expect(node('G').parent, equals(node('C')));
expect(node('J').parent, equals(node('G')));
expect(node('L').parent, equals(node('D')));
expect(node('R'), isNotNull); // The field.
},
];
main(args) => runIsolateTests(args, tests, testeeBefore: buildGraph);
@@ -14,6 +14,11 @@ valid_source_locations_test: Pass, Slow # Generally slow, even in release-x64.
[ $arch == arm ]
process_service_test: Pass, Fail # Issue 24344
# Test uses service API and relies on correct class names
[ $builder_tag == obfuscated ]
dominator_tree_vm_test: SkipByDesign
dominator_tree_vm_with_double_field_test: SkipByDesign
# Tests with known analyzer issues
[ $compiler == dart2analyzer ]
developer_extension_test: SkipByDesign
+4
View File
@@ -417,6 +417,10 @@ typedef simd128_value_t fpu_register_t;
#define DUAL_MAPPING_SUPPORTED 1
#endif
#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
#define SUPPORT_UNBOXED_INSTANCE_FIELDS
#endif
// Short form printf format specifiers
#define Pd PRIdPTR
#define Pu PRIuPTR
+10 -4
View File
@@ -21,7 +21,7 @@ class Utils {
}
template <typename T>
static inline T Maximum(T x, T y) {
static constexpr inline T Maximum(T x, T y) {
return x > y ? x : y;
}
@@ -352,12 +352,18 @@ class Utils {
return bit_cast<word>(mask);
}
static uword Bit(uint32_t n) {
ASSERT(n < kBitsPerWord);
uword bit = 1;
template <typename T = uword>
static T Bit(uint32_t n) {
ASSERT(n < sizeof(T) * kBitsPerByte);
T bit = 1;
return bit << n;
}
template <typename T>
DART_FORCE_INLINE static bool TestBit(T mask, intptr_t position) {
return ((mask >> position) & 1) != 0;
}
// Decode integer in SLEB128 format from |data| and update |byte_index|.
template <typename ValueType>
static ValueType DecodeSLEB128(const uint8_t* data,
@@ -0,0 +1,59 @@
// 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.
import 'dart:typed_data';
import 'dart:async';
import 'dart:isolate';
import "package:expect/expect.dart";
double getDoubleWithHeapObjectTag() {
final bd = ByteData(8);
bd.setUint64(0, 0x8000000000000001, Endian.host);
final double v = bd.getFloat64(0, Endian.host);
return v;
}
class Foo {
final String clazz = "foo";
final double x = getDoubleWithHeapObjectTag();
}
// Here we ensure to have a GC pointer and a non-GC pointer field, and then a
// type argument vector, so the offset in number of words for the type arguments
// will be different between host and target when compiling from 64-bit to
// 32-bit architectures.
class Bar<T> extends Foo {
final String clazz = "bar";
final double y = getDoubleWithHeapObjectTag();
final T value;
Bar(T val) : value = val;
}
main() async {
final receivePort = new ReceivePort();
receivePort.sendPort.send(Foo());
receivePort.sendPort.send(Bar<String>("StringBar"));
receivePort.sendPort.send(Bar<double>(4.2));
final it = StreamIterator(receivePort);
Expect.isTrue(await it.moveNext());
final foo = it.current as Foo;
Expect.isTrue(await it.moveNext());
final string_bar = it.current as Bar<String>;
Expect.isTrue(await it.moveNext());
final double_bar = it.current as Bar<double>;
Expect.equals(string_bar.value, "StringBar");
Expect.equals(string_bar.clazz, "bar");
Expect.equals(string_bar.y, getDoubleWithHeapObjectTag());
Expect.equals(string_bar.x, getDoubleWithHeapObjectTag());
Expect.equals(double_bar.value, 4.2);
Expect.equals(foo.clazz, "foo");
Expect.equals(foo.x, getDoubleWithHeapObjectTag());
await it.cancel();
}
+6 -6
View File
@@ -71,17 +71,17 @@ static void Finish(Thread* thread) {
// Verify that closure field offsets are identical in Dart and C++.
ASSERT(fields.Length() == 6);
field ^= fields.At(0);
ASSERT(field.Offset() == Closure::instantiator_type_arguments_offset());
ASSERT(field.HostOffset() == Closure::instantiator_type_arguments_offset());
field ^= fields.At(1);
ASSERT(field.Offset() == Closure::function_type_arguments_offset());
ASSERT(field.HostOffset() == Closure::function_type_arguments_offset());
field ^= fields.At(2);
ASSERT(field.Offset() == Closure::delayed_type_arguments_offset());
ASSERT(field.HostOffset() == Closure::delayed_type_arguments_offset());
field ^= fields.At(3);
ASSERT(field.Offset() == Closure::function_offset());
ASSERT(field.HostOffset() == Closure::function_offset());
field ^= fields.At(4);
ASSERT(field.Offset() == Closure::context_offset());
ASSERT(field.HostOffset() == Closure::context_offset());
field ^= fields.At(5);
ASSERT(field.Offset() == Closure::hash_offset());
ASSERT(field.HostOffset() == Closure::hash_offset());
#endif // defined(DEBUG)
// Eagerly compile Bool class, bool constants are used from within compiler.
+15 -15
View File
@@ -240,33 +240,33 @@ void ClassFinalizer::VerifyBootstrapClasses() {
#if defined(DEBUG)
// Basic checking.
cls = object_store->object_class();
ASSERT(Instance::InstanceSize() == cls.instance_size());
ASSERT(Instance::InstanceSize() == cls.host_instance_size());
cls = object_store->integer_implementation_class();
ASSERT(Integer::InstanceSize() == cls.instance_size());
ASSERT(Integer::InstanceSize() == cls.host_instance_size());
cls = object_store->smi_class();
ASSERT(Smi::InstanceSize() == cls.instance_size());
ASSERT(Smi::InstanceSize() == cls.host_instance_size());
cls = object_store->mint_class();
ASSERT(Mint::InstanceSize() == cls.instance_size());
ASSERT(Mint::InstanceSize() == cls.host_instance_size());
cls = object_store->one_byte_string_class();
ASSERT(OneByteString::InstanceSize() == cls.instance_size());
ASSERT(OneByteString::InstanceSize() == cls.host_instance_size());
cls = object_store->two_byte_string_class();
ASSERT(TwoByteString::InstanceSize() == cls.instance_size());
ASSERT(TwoByteString::InstanceSize() == cls.host_instance_size());
cls = object_store->external_one_byte_string_class();
ASSERT(ExternalOneByteString::InstanceSize() == cls.instance_size());
ASSERT(ExternalOneByteString::InstanceSize() == cls.host_instance_size());
cls = object_store->external_two_byte_string_class();
ASSERT(ExternalTwoByteString::InstanceSize() == cls.instance_size());
ASSERT(ExternalTwoByteString::InstanceSize() == cls.host_instance_size());
cls = object_store->double_class();
ASSERT(Double::InstanceSize() == cls.instance_size());
ASSERT(Double::InstanceSize() == cls.host_instance_size());
cls = object_store->bool_class();
ASSERT(Bool::InstanceSize() == cls.instance_size());
ASSERT(Bool::InstanceSize() == cls.host_instance_size());
cls = object_store->array_class();
ASSERT(Array::InstanceSize() == cls.instance_size());
ASSERT(Array::InstanceSize() == cls.host_instance_size());
cls = object_store->immutable_array_class();
ASSERT(ImmutableArray::InstanceSize() == cls.instance_size());
ASSERT(ImmutableArray::InstanceSize() == cls.host_instance_size());
cls = object_store->weak_property_class();
ASSERT(WeakProperty::InstanceSize() == cls.instance_size());
ASSERT(WeakProperty::InstanceSize() == cls.host_instance_size());
cls = object_store->linked_hash_map_class();
ASSERT(LinkedHashMap::InstanceSize() == cls.instance_size());
ASSERT(LinkedHashMap::InstanceSize() == cls.host_instance_size());
#endif // defined(DEBUG)
// Remember the currently pending classes.
@@ -1358,7 +1358,7 @@ void ClassFinalizer::VerifyImplicitFieldOffsets() {
fields_array ^= cls.fields();
ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields());
field ^= fields_array.At(0);
ASSERT(field.Offset() == ByteBuffer::data_offset());
ASSERT(field.HostOffset() == ByteBuffer::data_offset());
name ^= field.name();
expected_name ^= String::New("_data");
ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
+57 -5
View File
@@ -4,6 +4,8 @@
#include "vm/class_table.h"
#include <memory>
#include "platform/atomic.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
@@ -21,7 +23,9 @@ SharedClassTable::SharedClassTable()
: top_(kNumPredefinedCids),
capacity_(0),
table_(NULL),
old_tables_(new MallocGrowableArray<intptr_t*>()) {
old_tables_(new MallocGrowableArray<intptr_t*>()),
unboxed_fields_map_(nullptr),
old_unboxed_fields_maps_(new MallocGrowableArray<UnboxedFieldBitmap*>()) {
if (Dart::vm_isolate() == NULL) {
ASSERT(kInitialCapacity >= kNumPredefinedCids);
capacity_ = kInitialCapacity;
@@ -47,6 +51,11 @@ SharedClassTable::SharedClassTable()
table_[kVoidCid] = vm_shared_class_table->SizeAt(kVoidCid);
table_[kNeverCid] = vm_shared_class_table->SizeAt(kNeverCid);
}
#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
unboxed_fields_map_ = static_cast<UnboxedFieldBitmap*>(
malloc(capacity_ * sizeof(UnboxedFieldBitmap)));
memset(unboxed_fields_map_, 0, sizeof(UnboxedFieldBitmap) * capacity_);
#endif // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
#ifndef PRODUCT
trace_allocation_table_ =
static_cast<uint8_t*>(malloc(capacity_ * sizeof(uint8_t))); // NOLINT
@@ -61,6 +70,16 @@ SharedClassTable::~SharedClassTable() {
delete old_tables_;
free(table_);
}
if (old_unboxed_fields_maps_ != nullptr) {
FreeOldUnboxedFieldsMaps();
delete old_unboxed_fields_maps_;
}
if (unboxed_fields_map_ != nullptr) {
free(unboxed_fields_map_);
}
NOT_IN_PRODUCT(free(trace_allocation_table_));
}
@@ -133,6 +152,12 @@ void SharedClassTable::FreeOldTables() {
}
}
void SharedClassTable::FreeOldUnboxedFieldsMaps() {
while (old_unboxed_fields_maps_->length() > 0) {
free(old_unboxed_fields_maps_->RemoveLast());
}
}
void ClassTable::Register(const Class& cls) {
ASSERT(Thread::Current()->IsMutatorThread());
@@ -142,7 +167,7 @@ void ClassTable::Register(const Class& cls) {
// parallel to [ClassTable].
const intptr_t instance_size =
cls.is_abstract() ? 0 : Class::instance_size(cls.raw());
cls.is_abstract() ? 0 : Class::host_instance_size(cls.raw());
const intptr_t expected_cid =
shared_class_table_->Register(index, instance_size);
@@ -239,6 +264,7 @@ void SharedClassTable::Grow(intptr_t new_capacity) {
intptr_t* new_table = static_cast<intptr_t*>(
malloc(new_capacity * sizeof(intptr_t))); // NOLINT
memmove(new_table, table_, top_ * sizeof(intptr_t));
memset(new_table + top_, 0, (new_capacity - top_) * sizeof(intptr_t));
#ifndef PRODUCT
@@ -250,10 +276,22 @@ void SharedClassTable::Grow(intptr_t new_capacity) {
new_table[i] = 0;
NOT_IN_PRODUCT(new_stats_table[i] = 0);
}
capacity_ = new_capacity;
old_tables_->Add(table_);
table_ = new_table; // TODO(koda): This should use atomics.
NOT_IN_PRODUCT(trace_allocation_table_ = new_stats_table);
#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
auto new_unboxed_fields_map = static_cast<UnboxedFieldBitmap*>(
malloc(new_capacity * sizeof(UnboxedFieldBitmap)));
memmove(new_unboxed_fields_map, unboxed_fields_map_,
top_ * sizeof(UnboxedFieldBitmap));
memset(new_unboxed_fields_map + top_, 0,
(new_capacity - top_) * sizeof(UnboxedFieldBitmap));
old_unboxed_fields_maps_->Add(unboxed_fields_map_);
unboxed_fields_map_ = new_unboxed_fields_map;
#endif // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
}
void ClassTable::Unregister(intptr_t index) {
@@ -263,6 +301,9 @@ void ClassTable::Unregister(intptr_t index) {
void SharedClassTable::Unregister(intptr_t index) {
table_[index] = 0;
#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
unboxed_fields_map_[index].Reset();
#endif // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
}
void ClassTable::Remap(intptr_t* old_to_new_cid) {
@@ -281,14 +322,24 @@ void ClassTable::Remap(intptr_t* old_to_new_cid) {
void SharedClassTable::Remap(intptr_t* old_to_new_cid) {
ASSERT(Thread::Current()->IsAtSafepoint());
const intptr_t num_cids = NumCids();
intptr_t* cls_by_old_cid = new intptr_t[num_cids];
std::unique_ptr<intptr_t[]> cls_by_old_cid(new intptr_t[num_cids]);
for (intptr_t i = 0; i < num_cids; i++) {
cls_by_old_cid[i] = table_[i];
}
for (intptr_t i = 0; i < num_cids; i++) {
table_[old_to_new_cid[i]] = cls_by_old_cid[i];
}
delete[] cls_by_old_cid;
#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
std::unique_ptr<UnboxedFieldBitmap[]> unboxed_fields_by_old_cid(
new UnboxedFieldBitmap[num_cids]);
for (intptr_t i = 0; i < num_cids; i++) {
unboxed_fields_by_old_cid[i] = unboxed_fields_map_[i];
}
for (intptr_t i = 0; i < num_cids; i++) {
unboxed_fields_map_[old_to_new_cid[i]] = unboxed_fields_by_old_cid[i];
}
#endif // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
}
void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) {
@@ -344,7 +395,8 @@ void ClassTable::Print() {
void ClassTable::SetAt(intptr_t index, RawClass* raw_cls) {
// This is called by snapshot reader and class finalizer.
ASSERT(index < capacity_);
const intptr_t size = raw_cls == nullptr ? 0 : Class::instance_size(raw_cls);
const intptr_t size =
raw_cls == nullptr ? 0 : Class::host_instance_size(raw_cls);
shared_class_table_->SetSizeAt(index, size);
table_[index] = raw_cls;
}
+53
View File
@@ -7,9 +7,11 @@
#include "platform/assert.h"
#include "platform/atomic.h"
#include "platform/utils.h"
#include "vm/bitfield.h"
#include "vm/class_id.h"
#include "vm/flags.h"
#include "vm/globals.h"
namespace dart {
@@ -28,6 +30,33 @@ class MallocGrowableArray;
class ObjectPointerVisitor;
class RawClass;
// Wraps a 64-bit integer to represent the bitmap of unboxed fields
// stored in the shared class table.
class UnboxedFieldBitmap {
public:
UnboxedFieldBitmap() : bitmap_(0) {}
explicit UnboxedFieldBitmap(uint64_t bitmap) : bitmap_(bitmap) {}
UnboxedFieldBitmap(const UnboxedFieldBitmap&) = default;
UnboxedFieldBitmap& operator=(const UnboxedFieldBitmap&) = default;
DART_FORCE_INLINE bool Get(intptr_t position) const {
return Utils::TestBit(bitmap_, position);
}
DART_FORCE_INLINE void Set(intptr_t position) {
bitmap_ |= Utils::Bit<decltype(bitmap_)>(position);
}
DART_FORCE_INLINE uint64_t Value() const { return bitmap_; }
DART_FORCE_INLINE bool IsEmpty() const { return bitmap_ == 0; }
DART_FORCE_INLINE void Reset() { bitmap_ = 0; }
DART_FORCE_INLINE static constexpr intptr_t Length() {
return sizeof(decltype(bitmap_)) * kBitsPerByte;
}
private:
uint64_t bitmap_;
};
// Registry of all known classes and their sizes.
//
// The GC will only need the information in this shared class table to scan
@@ -62,6 +91,19 @@ class SharedClassTable {
intptr_t NumCids() const { return top_; }
intptr_t Capacity() const { return capacity_; }
UnboxedFieldBitmap GetUnboxedFieldsMapAt(intptr_t index) const {
ASSERT(IsValidIndex(index));
return FLAG_precompiled_mode ? unboxed_fields_map_[index]
: UnboxedFieldBitmap();
}
void SetUnboxedFieldsMapAt(intptr_t index,
UnboxedFieldBitmap unboxed_fields_map) {
ASSERT(IsValidIndex(index));
ASSERT(unboxed_fields_map_[index].IsEmpty());
unboxed_fields_map_[index] = unboxed_fields_map;
}
// Used to drop recently added classes.
void SetNumCids(intptr_t num_cids) {
ASSERT(num_cids <= top_);
@@ -117,6 +159,9 @@ class SharedClassTable {
// Deallocates table copies. Do not call during concurrent access to table.
void FreeOldTables();
// Deallocates bitmap copies. Do not call during concurrent access to table.
void FreeOldUnboxedFieldsMaps();
#if !defined(DART_PRECOMPILED_RUNTIME)
bool IsReloading() const { return reload_context_ != nullptr; }
@@ -171,6 +216,14 @@ class SharedClassTable {
IsolateGroupReloadContext* reload_context_ = nullptr;
// Stores a 64-bit bitmap for each class. There is one bit for each word in an
// instance of the class. A 0 bit indicates that the word contains a pointer
// the GC has to scan, a 1 indicates that the word is part of e.g. an unboxed
// double and does not need to be scanned. (see Class::Calculate...() where
// the bitmap is constructed)
UnboxedFieldBitmap* unboxed_fields_map_;
MallocGrowableArray<UnboxedFieldBitmap*>* old_unboxed_fields_maps_;
DISALLOW_COPY_AND_ASSIGN(SharedClassTable);
};
+148 -36
View File
@@ -182,19 +182,57 @@ class ClassSerializationCluster : public SerializationCluster {
if (s->kind() != Snapshot::kFullAOT) {
s->Write<uint32_t>(cls->ptr()->binary_declaration_);
}
s->Write<int32_t>(cls->ptr()->instance_size_in_words_);
s->Write<int32_t>(cls->ptr()->next_field_offset_in_words_);
s->Write<int32_t>(cls->ptr()->type_arguments_field_offset_in_words_);
s->Write<int32_t>(Class::target_instance_size_in_words(cls));
s->Write<int32_t>(Class::target_next_field_offset_in_words(cls));
s->Write<int32_t>(Class::target_type_arguments_field_offset_in_words(cls));
s->Write<int16_t>(cls->ptr()->num_type_arguments_);
s->Write<uint16_t>(cls->ptr()->num_native_fields_);
s->WriteTokenPosition(cls->ptr()->token_pos_);
s->WriteTokenPosition(cls->ptr()->end_token_pos_);
s->Write<uint32_t>(cls->ptr()->state_bits_);
// In AOT, the bitmap of unboxed fields should also be serialized
if (FLAG_precompiled_mode) {
s->WriteUnsigned64(
CalculateTargetUnboxedFieldsBitmap(s, class_id).Value());
}
}
private:
GrowableArray<RawClass*> predefined_;
GrowableArray<RawClass*> objects_;
UnboxedFieldBitmap CalculateTargetUnboxedFieldsBitmap(Serializer* s,
intptr_t class_id) {
const auto unboxed_fields_bitmap_host =
s->isolate()->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
UnboxedFieldBitmap unboxed_fields_bitmap;
if (unboxed_fields_bitmap_host.IsEmpty() ||
kWordSize == compiler::target::kWordSize) {
unboxed_fields_bitmap = unboxed_fields_bitmap_host;
} else {
ASSERT(kWordSize == 8 && compiler::target::kWordSize == 4);
// A new bitmap is built if the word sizes in the target and
// host are different
unboxed_fields_bitmap.Reset();
intptr_t target_i = 0, host_i = 0;
while (host_i < UnboxedFieldBitmap::Length()) {
// Each unboxed field has constant length, therefore the number of
// words used by it should double when compiling from 64-bit to 32-bit.
if (unboxed_fields_bitmap_host.Get(host_i++)) {
unboxed_fields_bitmap.Set(target_i++);
unboxed_fields_bitmap.Set(target_i++);
} else {
// For object pointers, the field is always one word length
target_i++;
}
}
}
return unboxed_fields_bitmap;
}
};
#endif // !DART_PRECOMPILED_RUNTIME
@@ -240,18 +278,35 @@ class ClassDeserializationCluster : public DeserializationCluster {
}
#endif
if (!RawObject::IsInternalVMdefinedClassId(class_id)) {
cls->ptr()->instance_size_in_words_ = d->Read<int32_t>();
cls->ptr()->next_field_offset_in_words_ = d->Read<int32_t>();
cls->ptr()->host_instance_size_in_words_ = d->Read<int32_t>();
cls->ptr()->host_next_field_offset_in_words_ = d->Read<int32_t>();
#if !defined(DART_PRECOMPILED_RUNTIME)
// Only one pair is serialized. The target field only exists when
// DART_PRECOMPILED_RUNTIME is not defined
cls->ptr()->target_instance_size_in_words_ =
cls->ptr()->host_instance_size_in_words_;
cls->ptr()->target_next_field_offset_in_words_ =
cls->ptr()->host_next_field_offset_in_words_;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
} else {
d->Read<int32_t>(); // Skip.
d->Read<int32_t>(); // Skip.
}
cls->ptr()->type_arguments_field_offset_in_words_ = d->Read<int32_t>();
cls->ptr()->host_type_arguments_field_offset_in_words_ =
d->Read<int32_t>();
#if !defined(DART_PRECOMPILED_RUNTIME)
cls->ptr()->target_type_arguments_field_offset_in_words_ =
cls->ptr()->host_type_arguments_field_offset_in_words_;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
cls->ptr()->num_type_arguments_ = d->Read<int16_t>();
cls->ptr()->num_native_fields_ = d->Read<uint16_t>();
cls->ptr()->token_pos_ = d->ReadTokenPosition();
cls->ptr()->end_token_pos_ = d->ReadTokenPosition();
cls->ptr()->state_bits_ = d->Read<uint32_t>();
if (FLAG_precompiled_mode) {
d->ReadUnsigned64(); // Skip unboxed fields bitmap.
}
}
for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -268,9 +323,18 @@ class ClassDeserializationCluster : public DeserializationCluster {
cls->ptr()->binary_declaration_ = d->Read<uint32_t>();
}
#endif
cls->ptr()->instance_size_in_words_ = d->Read<int32_t>();
cls->ptr()->next_field_offset_in_words_ = d->Read<int32_t>();
cls->ptr()->type_arguments_field_offset_in_words_ = d->Read<int32_t>();
cls->ptr()->host_instance_size_in_words_ = d->Read<int32_t>();
cls->ptr()->host_next_field_offset_in_words_ = d->Read<int32_t>();
cls->ptr()->host_type_arguments_field_offset_in_words_ =
d->Read<int32_t>();
#if !defined(DART_PRECOMPILED_RUNTIME)
cls->ptr()->target_instance_size_in_words_ =
cls->ptr()->host_instance_size_in_words_;
cls->ptr()->target_next_field_offset_in_words_ =
cls->ptr()->host_next_field_offset_in_words_;
cls->ptr()->target_type_arguments_field_offset_in_words_ =
cls->ptr()->host_type_arguments_field_offset_in_words_;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
cls->ptr()->num_type_arguments_ = d->Read<int16_t>();
cls->ptr()->num_native_fields_ = d->Read<uint16_t>();
cls->ptr()->token_pos_ = d->ReadTokenPosition();
@@ -279,6 +343,12 @@ class ClassDeserializationCluster : public DeserializationCluster {
table->AllocateIndex(class_id);
table->SetAt(class_id, cls);
if (FLAG_precompiled_mode) {
const UnboxedFieldBitmap unboxed_fields_map(d->ReadUnsigned64());
d->isolate()->shared_class_table()->SetUnboxedFieldsMapAt(
class_id, unboxed_fields_map);
}
}
}
@@ -935,13 +1005,13 @@ class FieldSerializationCluster : public SerializationCluster {
kind == Snapshot::kFullAOT ||
// Do not reset const fields.
Field::ConstBit::decode(field->ptr()->kind_bits_)) {
s->Push(s->field_table()->At(field->ptr()->offset_or_field_id_));
s->Push(s->field_table()->At(field->ptr()->host_offset_or_field_id_));
} else {
// Otherwise, for static fields we write out the initial static value.
s->Push(field->ptr()->saved_initial_value_);
}
} else {
s->Push(Smi::New(field->ptr()->offset_or_field_id_));
s->Push(Smi::New(Field::TargetOffsetOf(field)));
}
}
@@ -1001,14 +1071,14 @@ class FieldSerializationCluster : public SerializationCluster {
Field::ConstBit::decode(field->ptr()->kind_bits_)) {
WriteFieldValue(
"static value",
s->field_table()->At(field->ptr()->offset_or_field_id_));
s->field_table()->At(field->ptr()->host_offset_or_field_id_));
} else {
// Otherwise, for static fields we write out the initial static value.
WriteFieldValue("static value", field->ptr()->saved_initial_value_);
}
s->WriteUnsigned(field->ptr()->offset_or_field_id_);
s->WriteUnsigned(field->ptr()->host_offset_or_field_id_);
} else {
WriteFieldValue("offset", Smi::New(field->ptr()->offset_or_field_id_));
WriteFieldValue("offset", Smi::New(Field::TargetOffsetOf(field)));
}
}
}
@@ -1057,10 +1127,13 @@ class FieldDeserializationCluster : public DeserializationCluster {
intptr_t field_id = d->ReadUnsigned();
d->field_table()->SetAt(
field_id, reinterpret_cast<RawInstance*>(value_or_offset));
field->ptr()->offset_or_field_id_ = field_id;
field->ptr()->host_offset_or_field_id_ = field_id;
} else {
field->ptr()->offset_or_field_id_ =
field->ptr()->host_offset_or_field_id_ =
Smi::Value(Smi::RawCast(value_or_offset));
#if !defined(DART_PRECOMPILED_RUNTIME)
field->ptr()->target_offset_ = field->ptr()->host_offset_or_field_id_;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
}
}
@@ -2722,23 +2795,34 @@ class InstanceSerializationCluster : public SerializationCluster {
explicit InstanceSerializationCluster(intptr_t cid)
: SerializationCluster("Instance"), cid_(cid) {
RawClass* cls = Isolate::Current()->class_table()->At(cid);
next_field_offset_in_words_ = cls->ptr()->next_field_offset_in_words_;
instance_size_in_words_ = cls->ptr()->instance_size_in_words_;
ASSERT(next_field_offset_in_words_ > 0);
ASSERT(instance_size_in_words_ > 0);
host_next_field_offset_in_words_ =
cls->ptr()->host_next_field_offset_in_words_;
ASSERT(host_next_field_offset_in_words_ > 0);
#if !defined(DART_PRECOMPILED_RUNTIME)
target_next_field_offset_in_words_ =
cls->ptr()->target_next_field_offset_in_words_;
target_instance_size_in_words_ = cls->ptr()->target_instance_size_in_words_;
ASSERT(target_next_field_offset_in_words_ > 0);
ASSERT(target_instance_size_in_words_ > 0);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
~InstanceSerializationCluster() {}
void Trace(Serializer* s, RawObject* object) {
RawInstance* instance = Instance::RawCast(object);
objects_.Add(instance);
intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2;
const intptr_t next_field_offset = host_next_field_offset_in_words_
<< kWordSizeLog2;
const auto unboxed_fields_bitmap =
s->isolate()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
intptr_t offset = Instance::NextFieldOffset();
while (offset < next_field_offset) {
RawObject* raw_obj = *reinterpret_cast<RawObject**>(
reinterpret_cast<uword>(instance->ptr()) + offset);
s->Push(raw_obj);
// Skips unboxed fields
if (!unboxed_fields_bitmap.Get(offset / kWordSize)) {
RawObject* raw_obj = *reinterpret_cast<RawObject**>(
reinterpret_cast<uword>(instance->ptr()) + offset);
s->Push(raw_obj);
}
offset += kWordSize;
}
}
@@ -2748,8 +2832,12 @@ class InstanceSerializationCluster : public SerializationCluster {
const intptr_t count = objects_.length();
s->WriteUnsigned(count);
s->Write<int32_t>(next_field_offset_in_words_);
s->Write<int32_t>(instance_size_in_words_);
#if !defined(DART_PRECOMPILED_RUNTIME)
s->Write<int32_t>(target_next_field_offset_in_words_);
s->Write<int32_t>(target_instance_size_in_words_);
#else
s->Write<int32_t>(host_next_field_offset_in_words_);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
for (intptr_t i = 0; i < count; i++) {
RawInstance* instance = objects_[i];
@@ -2758,17 +2846,28 @@ class InstanceSerializationCluster : public SerializationCluster {
}
void WriteFill(Serializer* s) {
intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2;
intptr_t next_field_offset = host_next_field_offset_in_words_
<< kWordSizeLog2;
const intptr_t count = objects_.length();
const auto shared_class_table = s->isolate()->shared_class_table();
for (intptr_t i = 0; i < count; i++) {
RawInstance* instance = objects_[i];
AutoTraceObject(instance);
s->Write<bool>(instance->IsCanonical());
const auto unboxed_fields_bitmap =
shared_class_table->GetUnboxedFieldsMapAt(cid_);
intptr_t offset = Instance::NextFieldOffset();
while (offset < next_field_offset) {
RawObject* raw_obj = *reinterpret_cast<RawObject**>(
reinterpret_cast<uword>(instance->ptr()) + offset);
s->WriteElementRef(raw_obj, offset);
if (unboxed_fields_bitmap.Get(offset / kWordSize)) {
// Writes 32 bits of the unboxed value at a time
const uword value = *reinterpret_cast<uword*>(
reinterpret_cast<uword>(instance->ptr()) + offset);
s->WriteWordWith32BitWrites(value);
} else {
RawObject* raw_obj = *reinterpret_cast<RawObject**>(
reinterpret_cast<uword>(instance->ptr()) + offset);
s->WriteElementRef(raw_obj, offset);
}
offset += kWordSize;
}
}
@@ -2776,8 +2875,11 @@ class InstanceSerializationCluster : public SerializationCluster {
private:
const intptr_t cid_;
intptr_t next_field_offset_in_words_;
intptr_t instance_size_in_words_;
intptr_t host_next_field_offset_in_words_;
#if !defined(DART_PRECOMPILED_RUNTIME)
intptr_t target_next_field_offset_in_words_;
intptr_t target_instance_size_in_words_;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
GrowableArray<RawInstance*> objects_;
};
#endif // !DART_PRECOMPILED_RUNTIME
@@ -2806,16 +2908,26 @@ class InstanceDeserializationCluster : public DeserializationCluster {
intptr_t instance_size =
Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
const auto shared_class_table = d->isolate()->shared_class_table();
for (intptr_t id = start_index_; id < stop_index_; id++) {
RawInstance* instance = reinterpret_cast<RawInstance*>(d->Ref(id));
bool is_canonical = d->Read<bool>();
Deserializer::InitializeHeader(instance, cid_, instance_size,
is_canonical);
const auto unboxed_fields_bitmap =
shared_class_table->GetUnboxedFieldsMapAt(cid_);
intptr_t offset = Instance::NextFieldOffset();
while (offset < next_field_offset) {
RawObject** p = reinterpret_cast<RawObject**>(
reinterpret_cast<uword>(instance->ptr()) + offset);
*p = d->ReadRef();
if (unboxed_fields_bitmap.Get(offset / kWordSize)) {
uword* p = reinterpret_cast<uword*>(
reinterpret_cast<uword>(instance->ptr()) + offset);
// Reads 32 bits of the unboxed value at a time
*p = d->ReadWordWith32BitReads();
} else {
RawObject** p = reinterpret_cast<RawObject**>(
reinterpret_cast<uword>(instance->ptr()) + offset);
*p = d->ReadRef();
}
offset += kWordSize;
}
if (offset < instance_size) {
+9
View File
@@ -234,6 +234,12 @@ class Serializer : public ThreadStackResource {
WriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
}
void WriteUnsigned(intptr_t value) { stream_.WriteUnsigned(value); }
void WriteUnsigned64(uint64_t value) { stream_.WriteUnsigned(value); }
void WriteWordWith32BitWrites(uword value) {
stream_.WriteWordWith32BitWrites(value);
}
void WriteBytes(const uint8_t* addr, intptr_t len) {
stream_.WriteBytes(addr, len);
}
@@ -496,8 +502,11 @@ class Deserializer : public ThreadStackResource {
return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
}
intptr_t ReadUnsigned() { return stream_.ReadUnsigned(); }
uint64_t ReadUnsigned64() { return stream_.ReadUnsigned<uint64_t>(); }
void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
const uint8_t* CurrentBufferAddress() const {
return stream_.AddressOfCurrentPosition();
}
+1 -1
View File
@@ -5498,7 +5498,7 @@ class AllocateObjectInstr : public AllocationInstr {
}
static bool WillAllocateNewOrRemembered(const Class& cls) {
return Heap::IsAllocatableInNewSpace(cls.instance_size());
return Heap::IsAllocatableInNewSpace(cls.target_instance_size());
}
PRINT_OPERANDS_TO_SUPPORT
+61 -9
View File
@@ -2557,7 +2557,8 @@ LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps =
((IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0));
((IsUnboxedStore() && opt) ? (FLAG_precompiled_mode ? 0 : 2)
: (IsPotentialUnboxedStore() ? 3 : 0));
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps,
((IsUnboxedStore() && opt && is_initialization()) ||
@@ -2568,8 +2569,10 @@ LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
summary->set_in(0, Location::RequiresRegister());
if (IsUnboxedStore() && opt) {
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_temp(0, Location::RequiresRegister());
summary->set_temp(1, Location::RequiresRegister());
if (!FLAG_precompiled_mode) {
summary->set_temp(0, Location::RequiresRegister());
summary->set_temp(1, Location::RequiresRegister());
}
} else if (IsPotentialUnboxedStore()) {
summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister()
: Location::RequiresRegister());
@@ -2615,10 +2618,33 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(offset_in_bytes > 0); // Field is finalized and points after header.
if (IsUnboxedStore() && compiler->is_optimizing()) {
const intptr_t cid = slot().field().UnboxedFieldCid();
const DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg());
if (FLAG_precompiled_mode) {
switch (cid) {
case kDoubleCid:
__ Comment("UnboxedDoubleStoreInstanceFieldInstr");
__ StoreDToOffset(value, instance_reg,
offset_in_bytes - kHeapObjectTag);
return;
case kFloat32x4Cid:
__ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
__ StoreMultipleDToOffset(value, 2, instance_reg,
offset_in_bytes - kHeapObjectTag);
return;
case kFloat64x2Cid:
__ Comment("UnboxedFloat64x2StoreInstanceFieldInstr");
__ StoreMultipleDToOffset(value, 2, instance_reg,
offset_in_bytes - kHeapObjectTag);
return;
default:
UNREACHABLE();
}
}
const Register temp = locs()->temp(0).reg();
const Register temp2 = locs()->temp(1).reg();
const intptr_t cid = slot().field().UnboxedFieldCid();
if (is_initialization()) {
const Class* cls = NULL;
@@ -2963,8 +2989,9 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps =
(IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 3 : 0);
const intptr_t kNumTemps = (IsUnboxedLoad() && opt)
? (FLAG_precompiled_mode ? 0 : 1)
: (IsPotentialUnboxedLoad() ? 3 : 0);
LocationSummary* locs = new (zone) LocationSummary(
zone, kNumInputs, kNumTemps,
@@ -2974,7 +3001,9 @@ LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
locs->set_in(0, Location::RequiresRegister());
if (IsUnboxedLoad() && opt) {
locs->set_temp(0, Location::RequiresRegister());
if (!FLAG_precompiled_mode) {
locs->set_temp(0, Location::RequiresRegister());
}
} else if (IsPotentialUnboxedLoad()) {
locs->set_temp(0, opt ? Location::RequiresFpuRegister()
: Location::FpuRegisterLocation(Q1));
@@ -2990,10 +3019,33 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register instance_reg = locs()->in(0).reg();
if (IsUnboxedLoad() && compiler->is_optimizing()) {
const intptr_t cid = slot().field().UnboxedFieldCid();
const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
if (FLAG_precompiled_mode) {
switch (cid) {
case kDoubleCid:
__ Comment("UnboxedDoubleLoadFieldInstr");
__ LoadDFromOffset(result, instance_reg,
OffsetInBytes() - kHeapObjectTag);
return;
case kFloat32x4Cid:
__ Comment("UnboxedFloat32x4LoadFieldInstr");
__ LoadMultipleDFromOffset(result, 2, instance_reg,
OffsetInBytes() - kHeapObjectTag);
return;
case kFloat64x2Cid:
__ Comment("UnboxedFloat64x2LoadFieldInstr");
__ LoadMultipleDFromOffset(result, 2, instance_reg,
OffsetInBytes() - kHeapObjectTag);
return;
default:
UNREACHABLE();
}
}
const Register temp = locs()->temp(0).reg();
__ LoadFieldFromOffset(kWord, temp, instance_reg, OffsetInBytes());
const intptr_t cid = slot().field().UnboxedFieldCid();
switch (cid) {
case kDoubleCid:
__ Comment("UnboxedDoubleLoadFieldInstr");
@@ -3320,7 +3372,7 @@ void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register temp = locs()->temp(0).reg();
compiler::Label no_call;
__ ldr(temp, compiler::FieldAddress(instance, field().Offset()));
__ ldr(temp, compiler::FieldAddress(instance, field().TargetOffset()));
__ CompareObject(temp, Object::sentinel());
__ b(&no_call, NE);
+58 -11
View File
@@ -2158,8 +2158,9 @@ static void EnsureMutableBox(FlowGraphCompiler* compiler,
LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps =
(IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 2 : 0);
const intptr_t kNumTemps = (IsUnboxedStore() && opt)
? (FLAG_precompiled_mode ? 0 : 2)
: (IsPotentialUnboxedStore() ? 2 : 0);
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps,
((IsUnboxedStore() && opt && is_initialization()) ||
@@ -2170,8 +2171,10 @@ LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
summary->set_in(0, Location::RequiresRegister());
if (IsUnboxedStore() && opt) {
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_temp(0, Location::RequiresRegister());
summary->set_temp(1, Location::RequiresRegister());
if (!FLAG_precompiled_mode) {
summary->set_temp(0, Location::RequiresRegister());
summary->set_temp(1, Location::RequiresRegister());
}
} else if (IsPotentialUnboxedStore()) {
summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister()
: Location::RequiresRegister());
@@ -2195,9 +2198,29 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
if (IsUnboxedStore() && compiler->is_optimizing()) {
const VRegister value = locs()->in(1).fpu_reg();
const intptr_t cid = slot().field().UnboxedFieldCid();
if (FLAG_precompiled_mode) {
switch (cid) {
case kDoubleCid:
__ Comment("UnboxedDoubleStoreInstanceFieldInstr");
__ StoreDFieldToOffset(value, instance_reg, offset_in_bytes);
return;
case kFloat32x4Cid:
__ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
__ StoreQFieldToOffset(value, instance_reg, offset_in_bytes);
return;
case kFloat64x2Cid:
__ Comment("UnboxedFloat64x2StoreInstanceFieldInstr");
__ StoreQFieldToOffset(value, instance_reg, offset_in_bytes);
return;
default:
UNREACHABLE();
}
}
const Register temp = locs()->temp(0).reg();
const Register temp2 = locs()->temp(1).reg();
const intptr_t cid = slot().field().UnboxedFieldCid();
if (is_initialization()) {
const Class* cls = NULL;
@@ -2534,8 +2557,9 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps =
(IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 1 : 0);
const intptr_t kNumTemps = (IsUnboxedLoad() && opt)
? (FLAG_precompiled_mode ? 0 : 1)
: (IsPotentialUnboxedLoad() ? 1 : 0);
LocationSummary* locs = new (zone) LocationSummary(
zone, kNumInputs, kNumTemps,
(opt && !IsPotentialUnboxedLoad()) ? LocationSummary::kNoCall
@@ -2544,7 +2568,9 @@ LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
locs->set_in(0, Location::RequiresRegister());
if (IsUnboxedLoad() && opt) {
locs->set_temp(0, Location::RequiresRegister());
if (!FLAG_precompiled_mode) {
locs->set_temp(0, Location::RequiresRegister());
}
} else if (IsPotentialUnboxedLoad()) {
locs->set_temp(0, Location::RequiresRegister());
}
@@ -2557,9 +2583,30 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register instance_reg = locs()->in(0).reg();
if (IsUnboxedLoad() && compiler->is_optimizing()) {
const VRegister result = locs()->out(0).fpu_reg();
const Register temp = locs()->temp(0).reg();
__ LoadFieldFromOffset(temp, instance_reg, OffsetInBytes());
const intptr_t cid = slot().field().UnboxedFieldCid();
if (FLAG_precompiled_mode) {
switch (cid) {
case kDoubleCid:
__ Comment("UnboxedDoubleLoadFieldInstr");
__ LoadDFieldFromOffset(result, instance_reg, OffsetInBytes());
return;
case kFloat32x4Cid:
__ Comment("UnboxedFloat32x4LoadFieldInstr");
__ LoadQFieldFromOffset(result, instance_reg, OffsetInBytes());
return;
case kFloat64x2Cid:
__ Comment("UnboxedFloat64x2LoadFieldInstr");
__ LoadQFieldFromOffset(result, instance_reg, OffsetInBytes());
return;
default:
UNREACHABLE();
}
}
const Register temp = locs()->temp(0).reg();
__ LoadFieldFromOffset(temp, instance_reg, OffsetInBytes());
switch (cid) {
case kDoubleCid:
__ Comment("UnboxedDoubleLoadFieldInstr");
@@ -2875,7 +2922,7 @@ void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register temp = locs()->temp(0).reg();
compiler::Label no_call;
__ ldr(temp, compiler::FieldAddress(instance, field().Offset()));
__ ldr(temp, compiler::FieldAddress(instance, field().TargetOffset()));
__ CompareObject(temp, Object::sentinel());
__ b(&no_call, NE);
+1 -1
View File
@@ -2753,7 +2753,7 @@ void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
compiler::Label no_call;
__ movl(temp, compiler::FieldAddress(instance, field().Offset()));
__ movl(temp, compiler::FieldAddress(instance, field().TargetOffset()));
__ CompareObject(temp, Object::sentinel());
__ j(NOT_EQUAL, &no_call, compiler::Assembler::kNearJump);
+1 -1
View File
@@ -1308,7 +1308,7 @@ void AllocateObjectInstr::AddExtraInfoToSExpression(
SExpList* sexp,
FlowGraphSerializer* s) const {
Instruction::AddExtraInfoToSExpression(sexp, s);
s->AddExtraInteger(sexp, "size", cls().instance_size());
s->AddExtraInteger(sexp, "size", cls().target_instance_size());
if (auto const closure = s->DartValueToSExp(closure_function())) {
sexp->AddExtra("closure_function", closure);
}
+65 -10
View File
@@ -2128,8 +2128,9 @@ void GuardFieldTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps =
(IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0);
const intptr_t kNumTemps = (IsUnboxedStore() && opt)
? (FLAG_precompiled_mode ? 0 : 2)
: (IsPotentialUnboxedStore() ? 3 : 0);
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps,
((IsUnboxedStore() && opt && is_initialization()) ||
@@ -2140,8 +2141,10 @@ LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
summary->set_in(0, Location::RequiresRegister());
if (IsUnboxedStore() && opt) {
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_temp(0, Location::RequiresRegister());
summary->set_temp(1, Location::RequiresRegister());
if (!FLAG_precompiled_mode) {
summary->set_temp(0, Location::RequiresRegister());
summary->set_temp(1, Location::RequiresRegister());
}
} else if (IsPotentialUnboxedStore()) {
summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister()
: Location::RequiresRegister());
@@ -2186,9 +2189,33 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
if (IsUnboxedStore() && compiler->is_optimizing()) {
XmmRegister value = locs()->in(1).fpu_reg();
const intptr_t cid = slot().field().UnboxedFieldCid();
// Real unboxed field
if (FLAG_precompiled_mode) {
switch (cid) {
case kDoubleCid:
__ Comment("UnboxedDoubleStoreInstanceFieldInstr");
__ movsd(compiler::FieldAddress(instance_reg, offset_in_bytes),
value);
return;
case kFloat32x4Cid:
__ Comment("UnboxedFloat32x4StoreInstanceFieldInstr");
__ movups(compiler::FieldAddress(instance_reg, offset_in_bytes),
value);
return;
case kFloat64x2Cid:
__ Comment("UnboxedFloat64x2StoreInstanceFieldInstr");
__ movups(compiler::FieldAddress(instance_reg, offset_in_bytes),
value);
return;
default:
UNREACHABLE();
}
}
Register temp = locs()->temp(0).reg();
Register temp2 = locs()->temp(1).reg();
const intptr_t cid = slot().field().UnboxedFieldCid();
if (is_initialization()) {
const Class* cls = NULL;
@@ -2533,8 +2560,9 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps =
(IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0);
const intptr_t kNumTemps = (IsUnboxedLoad() && opt)
? (FLAG_precompiled_mode ? 0 : 1)
: (IsPotentialUnboxedLoad() ? 2 : 0);
LocationSummary* locs = new (zone) LocationSummary(
zone, kNumInputs, kNumTemps,
(opt && !IsPotentialUnboxedLoad()) ? LocationSummary::kNoCall
@@ -2543,7 +2571,9 @@ LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,
locs->set_in(0, Location::RequiresRegister());
if (IsUnboxedLoad() && opt) {
locs->set_temp(0, Location::RequiresRegister());
if (!FLAG_precompiled_mode) {
locs->set_temp(0, Location::RequiresRegister());
}
} else if (IsPotentialUnboxedLoad()) {
locs->set_temp(0, opt ? Location::RequiresFpuRegister()
: Location::FpuRegisterLocation(XMM1));
@@ -2558,9 +2588,34 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register instance_reg = locs()->in(0).reg();
if (IsUnboxedLoad() && compiler->is_optimizing()) {
XmmRegister result = locs()->out(0).fpu_reg();
const intptr_t cid = slot().field().UnboxedFieldCid();
// Real unboxed field
if (FLAG_precompiled_mode) {
switch (cid) {
case kDoubleCid:
__ Comment("UnboxedDoubleLoadFieldInstr");
__ movsd(result,
compiler::FieldAddress(instance_reg, OffsetInBytes()));
break;
case kFloat32x4Cid:
__ Comment("UnboxedFloat32x4LoadFieldInstr");
__ movups(result,
compiler::FieldAddress(instance_reg, OffsetInBytes()));
break;
case kFloat64x2Cid:
__ Comment("UnboxedFloat64x2LoadFieldInstr");
__ movups(result,
compiler::FieldAddress(instance_reg, OffsetInBytes()));
break;
default:
UNREACHABLE();
}
return;
}
Register temp = locs()->temp(0).reg();
__ movq(temp, compiler::FieldAddress(instance_reg, OffsetInBytes()));
intptr_t cid = slot().field().UnboxedFieldCid();
switch (cid) {
case kDoubleCid:
__ Comment("UnboxedDoubleLoadFieldInstr");
@@ -2890,7 +2945,7 @@ void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
compiler::Label no_call;
__ movq(temp, compiler::FieldAddress(instance, field().Offset()));
__ movq(temp, compiler::FieldAddress(instance, field().TargetOffset()));
__ CompareObject(temp, Object::sentinel());
__ j(NOT_EQUAL, &no_call, compiler::Assembler::kNearJump);
@@ -1151,7 +1151,7 @@ void BytecodeFlowGraphBuilder::BuildCreateArrayTOS() {
}
const Slot& ClosureSlotByField(const Field& field) {
const intptr_t offset = field.Offset();
const intptr_t offset = field.HostOffset();
if (offset == Closure::instantiator_type_arguments_offset()) {
return Slot::Closure_instantiator_type_arguments();
} else if (offset == Closure::function_type_arguments_offset()) {
@@ -1178,7 +1178,7 @@ void BytecodeFlowGraphBuilder::BuildStoreFieldTOS() {
const Field& field = Field::Cast(ConstantAt(cp_index, 1).value());
ASSERT(Smi::Cast(ConstantAt(cp_index).value()).Value() * kWordSize ==
field.Offset());
field.HostOffset());
if (field.Owner() == isolate()->object_store()->closure_class()) {
// Stores to _Closure fields are lower-level.
@@ -1204,7 +1204,7 @@ void BytecodeFlowGraphBuilder::BuildLoadFieldTOS() {
const Field& field = Field::Cast(ConstantAt(cp_index, 1).value());
ASSERT(Smi::Cast(ConstantAt(cp_index).value()).Value() * kWordSize ==
field.Offset());
field.HostOffset());
if (field.Owner() == isolate()->object_store()->closure_class()) {
// Loads from _Closure fields are lower-level.
@@ -1292,7 +1292,7 @@ void BytecodeFlowGraphBuilder::BuildInitLateField() {
const Field& field = Field::Cast(ConstantAt(cp_index, 1).value());
ASSERT(Smi::Cast(ConstantAt(cp_index).value()).Value() * kWordSize ==
field.Offset());
field.HostOffset());
code_ += B->Constant(Object::sentinel());
code_ += B->StoreInstanceField(
@@ -748,7 +748,7 @@ intptr_t BytecodeReaderHelper::ReadConstantPool(const Function& function,
field ^= ReadObject();
// InstanceField constant occupies 2 entries.
// The first entry is used for field offset.
obj = Smi::New(field.Offset() / kWordSize);
obj = Smi::New(field.HostOffset() / kWordSize);
pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
ObjectPool::Patchability::kNotPatchable);
pool.SetObjectAt(i, obj);
@@ -763,7 +763,7 @@ intptr_t BytecodeReaderHelper::ReadConstantPool(const Function& function,
break;
case ConstantPoolTag::kTypeArgumentsField:
cls ^= ReadObject();
obj = Smi::New(cls.type_arguments_field_offset() / kWordSize);
obj = Smi::New(cls.host_type_arguments_field_offset() / kWordSize);
break;
case ConstantPoolTag::kType:
obj = ReadObject();
+315 -7
View File
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
#include "vm/compiler/runtime_api.h"
#include "platform/utils.h"
namespace dart {
namespace compiler {
@@ -199,7 +198,7 @@ const Field& LookupMathRandomStateFieldOffset() {
}
word LookupFieldOffsetInBytes(const Field& field) {
return field.Offset();
return field.TargetOffset();
}
#if defined(TARGET_ARCH_IA32)
@@ -337,10 +336,10 @@ static uword GetInstanceSizeImpl(const dart::Class& handle) {
case kExternalTypedData##clazz##Cid:
CLASS_LIST_TYPED_DATA(HANDLE_CASE)
#undef HANDLE_CASE
return TranslateOffsetInWords(handle.instance_size());
return handle.target_instance_size();
default:
if (handle.id() >= kNumPredefinedCids) {
return TranslateOffsetInWords(handle.instance_size());
return handle.target_instance_size();
}
}
FATAL3("Unsupported class for size translation: %s (id=%" Pd
@@ -359,11 +358,12 @@ intptr_t Class::NumTypeArguments(const dart::Class& klass) {
}
bool Class::HasTypeArgumentsField(const dart::Class& klass) {
return klass.type_arguments_field_offset() != dart::Class::kNoTypeArguments;
return klass.host_type_arguments_field_offset() !=
dart::Class::kNoTypeArguments;
}
intptr_t Class::TypeArgumentsFieldOffset(const dart::Class& klass) {
return TranslateOffsetInWords(klass.type_arguments_field_offset());
return klass.target_type_arguments_field_offset();
}
bool Class::TraceAllocation(const dart::Class& klass) {
@@ -643,7 +643,7 @@ bool Heap::IsAllocatableInNewSpace(intptr_t instance_size) {
}
word Field::OffsetOf(const dart::Field& field) {
return TranslateOffsetInWords(field.Offset());
return field.TargetOffset();
}
word FieldTable::OffsetOf(const dart::Field& field) {
@@ -651,6 +651,314 @@ word FieldTable::OffsetOf(const dart::Field& field) {
dart::FieldTable::FieldOffsetFor(field.field_id()));
}
word FreeListElement::FakeInstance::InstanceSize() {
return 0;
}
word ForwardingCorpse::FakeInstance::InstanceSize() {
return 0;
}
word Instance::NextFieldOffset() {
return TranslateOffsetInWords(dart::Instance::NextFieldOffset());
}
word Pointer::NextFieldOffset() {
return TranslateOffsetInWords(dart::Pointer::NextFieldOffset());
}
word ObjectPool::NextFieldOffset() {
return -kWordSize;
}
word Class::NextFieldOffset() {
return -kWordSize;
}
word Function::NextFieldOffset() {
return -kWordSize;
}
word ICData::NextFieldOffset() {
return -kWordSize;
}
word MegamorphicCache::NextFieldOffset() {
return -kWordSize;
}
word SingleTargetCache::NextFieldOffset() {
return -kWordSize;
}
word Array::NextFieldOffset() {
return -kWordSize;
}
word GrowableObjectArray::NextFieldOffset() {
return -kWordSize;
}
word TypedDataBase::NextFieldOffset() {
return -kWordSize;
}
word TypedData::NextFieldOffset() {
return -kWordSize;
}
word ExternalTypedData::NextFieldOffset() {
return -kWordSize;
}
word TypedDataView::NextFieldOffset() {
return -kWordSize;
}
word LinkedHashMap::NextFieldOffset() {
return -kWordSize;
}
word Type::NextFieldOffset() {
return -kWordSize;
}
word TypeRef::NextFieldOffset() {
return -kWordSize;
}
word Double::NextFieldOffset() {
return -kWordSize;
}
word Mint::NextFieldOffset() {
return -kWordSize;
}
word String::NextFieldOffset() {
return -kWordSize;
}
word OneByteString::NextFieldOffset() {
return -kWordSize;
}
word TwoByteString::NextFieldOffset() {
return -kWordSize;
}
word ExternalOneByteString::NextFieldOffset() {
return -kWordSize;
}
word ExternalTwoByteString::NextFieldOffset() {
return -kWordSize;
}
word Int32x4::NextFieldOffset() {
return -kWordSize;
}
word Float32x4::NextFieldOffset() {
return -kWordSize;
}
word Float64x2::NextFieldOffset() {
return -kWordSize;
}
word DynamicLibrary::NextFieldOffset() {
return -kWordSize;
}
word PatchClass::NextFieldOffset() {
return -kWordSize;
}
word SignatureData::NextFieldOffset() {
return -kWordSize;
}
word RedirectionData::NextFieldOffset() {
return -kWordSize;
}
word FfiTrampolineData::NextFieldOffset() {
return -kWordSize;
}
word Script::NextFieldOffset() {
return -kWordSize;
}
word Library::NextFieldOffset() {
return -kWordSize;
}
word Namespace::NextFieldOffset() {
return -kWordSize;
}
word KernelProgramInfo::NextFieldOffset() {
return -kWordSize;
}
word Bytecode::NextFieldOffset() {
return -kWordSize;
}
word PcDescriptors::NextFieldOffset() {
return -kWordSize;
}
word CodeSourceMap::NextFieldOffset() {
return -kWordSize;
}
word CompressedStackMaps::NextFieldOffset() {
return -kWordSize;
}
word LocalVarDescriptors::NextFieldOffset() {
return -kWordSize;
}
word ExceptionHandlers::NextFieldOffset() {
return -kWordSize;
}
word ContextScope::NextFieldOffset() {
return -kWordSize;
}
word ParameterTypeCheck::NextFieldOffset() {
return -kWordSize;
}
word UnlinkedCall::NextFieldOffset() {
return -kWordSize;
}
word ApiError::NextFieldOffset() {
return -kWordSize;
}
word LanguageError::NextFieldOffset() {
return -kWordSize;
}
word UnhandledException::NextFieldOffset() {
return -kWordSize;
}
word UnwindError::NextFieldOffset() {
return -kWordSize;
}
word Bool::NextFieldOffset() {
return -kWordSize;
}
word TypeParameter::NextFieldOffset() {
return -kWordSize;
}
word LibraryPrefix::NextFieldOffset() {
return -kWordSize;
}
word Capability::NextFieldOffset() {
return -kWordSize;
}
word ReceivePort::NextFieldOffset() {
return -kWordSize;
}
word SendPort::NextFieldOffset() {
return -kWordSize;
}
word TransferableTypedData::NextFieldOffset() {
return -kWordSize;
}
word StackTrace::NextFieldOffset() {
return -kWordSize;
}
word Integer::NextFieldOffset() {
return -kWordSize;
}
word Smi::NextFieldOffset() {
return -kWordSize;
}
word WeakProperty::NextFieldOffset() {
return -kWordSize;
}
word MirrorReference::NextFieldOffset() {
return -kWordSize;
}
word Number::NextFieldOffset() {
return -kWordSize;
}
word MonomorphicSmiableCall::NextFieldOffset() {
return -kWordSize;
}
word Instructions::NextFieldOffset() {
return -kWordSize;
}
word Code::NextFieldOffset() {
return -kWordSize;
}
word SubtypeTestCache::NextFieldOffset() {
return -kWordSize;
}
word Context::NextFieldOffset() {
return -kWordSize;
}
word Closure::NextFieldOffset() {
return -kWordSize;
}
word ClosureData::NextFieldOffset() {
return -kWordSize;
}
word RegExp::NextFieldOffset() {
return -kWordSize;
}
word UserTag::NextFieldOffset() {
return -kWordSize;
}
word Field::NextFieldOffset() {
return -kWordSize;
}
word TypeArguments::NextFieldOffset() {
return -kWordSize;
}
word FreeListElement::FakeInstance::NextFieldOffset() {
return -kWordSize;
}
word ForwardingCorpse::FakeInstance::NextFieldOffset() {
return -kWordSize;
}
} // namespace target
} // namespace compiler
} // namespace dart
+309 -1
View File
@@ -19,6 +19,7 @@
// in compiler::target namespace.
#include "platform/globals.h"
#include "platform/utils.h"
#include "vm/allocation.h"
#include "vm/bitfield.h"
#include "vm/bss_relocs.h"
@@ -285,6 +286,11 @@ extern const word kPageSize;
extern const word kPageSizeInWords;
extern const word kPageMask;
static constexpr intptr_t kObjectAlignment = ObjectAlignment::kObjectAlignment;
inline intptr_t RoundedAllocationSize(intptr_t size) {
return Utils::RoundUp(size, kObjectAlignment);
}
// Information about frame_layout that compiler should be targeting.
extern FrameLayout frame_layout;
@@ -376,11 +382,15 @@ class ObjectPool : public AllStatic {
public:
// Return offset to the element with the given [index] in the object pool.
static word element_offset(intptr_t index);
static word InstanceSize();
static word NextFieldOffset();
};
class Class : public AllStatic {
public:
static word type_arguments_field_offset_in_words_offset();
static word host_type_arguments_field_offset_in_words_offset();
static word target_type_arguments_field_offset_in_words_offset();
static word declaration_type_offset();
@@ -392,6 +402,10 @@ class Class : public AllStatic {
// The value used if no type arguments vector is present.
static const word kNoTypeArguments;
static word InstanceSize();
static word NextFieldOffset();
// Return class id of the given class on the target.
static classid_t GetId(const dart::Class& handle);
@@ -418,6 +432,7 @@ class Instance : public AllStatic {
static word DataOffsetFor(intptr_t cid);
static word ElementSizeFor(intptr_t cid);
static word InstanceSize();
static word NextFieldOffset();
};
class Function : public AllStatic {
@@ -425,6 +440,8 @@ class Function : public AllStatic {
static word code_offset();
static word entry_point_offset(CodeEntryKind kind = CodeEntryKind::kNormal);
static word usage_counter_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class ICData : public AllStatic {
@@ -443,6 +460,8 @@ class ICData : public AllStatic {
static word EntryPointIndexFor(word num_args);
static word NumArgsTestedShift();
static word NumArgsTestedMask();
static word InstanceSize();
static word NextFieldOffset();
};
class MegamorphicCache : public AllStatic {
@@ -451,6 +470,8 @@ class MegamorphicCache : public AllStatic {
static word mask_offset();
static word buckets_offset();
static word arguments_descriptor_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class SingleTargetCache : public AllStatic {
@@ -459,6 +480,8 @@ class SingleTargetCache : public AllStatic {
static word upper_limit_offset();
static word entry_point_offset();
static word target_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class Array : public AllStatic {
@@ -469,6 +492,8 @@ class Array : public AllStatic {
static word type_arguments_offset();
static word length_offset();
static word element_offset(intptr_t index);
static word InstanceSize();
static word NextFieldOffset();
static const word kMaxElements;
static const word kMaxNewSpaceElements;
@@ -480,6 +505,7 @@ class GrowableObjectArray : public AllStatic {
static word type_arguments_offset();
static word length_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class TypedDataBase : public AllStatic {
@@ -487,23 +513,29 @@ class TypedDataBase : public AllStatic {
static word data_field_offset();
static word length_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class TypedData : public AllStatic {
public:
static word data_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class ExternalTypedData : public AllStatic {
public:
static word data_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class TypedDataView : public AllStatic {
public:
static word offset_in_bytes_offset();
static word data_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class LinkedHashMap : public AllStatic {
@@ -513,7 +545,9 @@ class LinkedHashMap : public AllStatic {
static word hash_mask_offset();
static word used_data_offset();
static word deleted_keys_offset();
static word type_arguments_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class ArgumentsDescriptor : public AllStatic {
@@ -530,6 +564,9 @@ class ArgumentsDescriptor : public AllStatic {
class Pointer : public AllStatic {
public:
static word c_memory_address_offset();
static word type_arguments_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class AbstractType : public AllStatic {
@@ -545,11 +582,15 @@ class Type : public AllStatic {
static word signature_offset();
static word type_class_id_offset();
static word nullability_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class TypeRef : public AllStatic {
public:
static word type_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class Nullability : public AllStatic {
@@ -564,12 +605,14 @@ class Double : public AllStatic {
public:
static word value_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class Mint : public AllStatic {
public:
static word value_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class String : public AllStatic {
@@ -579,43 +622,265 @@ class String : public AllStatic {
static word hash_offset();
static word length_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class OneByteString : public AllStatic {
public:
static word data_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class TwoByteString : public AllStatic {
public:
static word data_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class ExternalOneByteString : public AllStatic {
public:
static word external_data_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class ExternalTwoByteString : public AllStatic {
public:
static word external_data_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class Int32x4 : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Float32x4 : public AllStatic {
public:
static word value_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class Float64x2 : public AllStatic {
public:
static word value_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class DynamicLibrary : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class PatchClass : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class SignatureData : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class RedirectionData : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class FfiTrampolineData : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Script : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Library : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Namespace : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class KernelProgramInfo : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Bytecode : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class PcDescriptors : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class CodeSourceMap : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class CompressedStackMaps : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class LocalVarDescriptors : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class ExceptionHandlers : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class ContextScope : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class ParameterTypeCheck : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class UnlinkedCall : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class ApiError : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class LanguageError : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class UnhandledException : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class UnwindError : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Bool : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class TypeParameter : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class LibraryPrefix : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Capability : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class ReceivePort : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class SendPort : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class TransferableTypedData : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class StackTrace : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Integer : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Smi : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class WeakProperty : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class MirrorReference : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class Number : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class TimelineStream : public AllStatic {
@@ -633,6 +898,8 @@ class MonomorphicSmiableCall : public AllStatic {
static word expected_cid_offset();
static word entrypoint_offset();
static word target_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class Thread : public AllStatic {
@@ -803,6 +1070,8 @@ class Instructions : public AllStatic {
static const word kPolymorphicEntryOffsetAOT;
static word HeaderSize();
static word UnalignedHeaderSize();
static word InstanceSize();
static word NextFieldOffset();
};
class Code : public AllStatic {
@@ -815,6 +1084,8 @@ class Code : public AllStatic {
static word entry_point_offset(CodeEntryKind kind = CodeEntryKind::kNormal);
static word saved_instructions_offset();
static word owner_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class SubtypeTestCache : public AllStatic {
@@ -829,6 +1100,8 @@ class SubtypeTestCache : public AllStatic {
static const word kInstanceParentFunctionTypeArguments;
static const word kInstanceDelayedFunctionTypeArguments;
static const word kTestResult;
static word InstanceSize();
static word NextFieldOffset();
};
class Context : public AllStatic {
@@ -838,6 +1111,8 @@ class Context : public AllStatic {
static word num_variables_offset();
static word variable_offset(word i);
static word InstanceSize(word n);
static word InstanceSize();
static word NextFieldOffset();
};
class Closure : public AllStatic {
@@ -849,6 +1124,13 @@ class Closure : public AllStatic {
static word instantiator_type_arguments_offset();
static word hash_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class ClosureData : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class HeapPage : public AllStatic {
@@ -883,11 +1165,15 @@ class NativeEntry {
class RegExp : public AllStatic {
public:
static word function_offset(classid_t cid, bool sticky);
static word InstanceSize();
static word NextFieldOffset();
};
class UserTag : public AllStatic {
public:
static word tag_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class Symbols : public AllStatic {
@@ -906,12 +1192,34 @@ class Field : public AllStatic {
static word is_nullable_offset();
static word static_value_offset();
static word kind_bits_offset();
static word InstanceSize();
static word NextFieldOffset();
};
class TypeArguments : public AllStatic {
public:
static word instantiations_offset();
static word type_at_offset(intptr_t i);
static word InstanceSize();
static word NextFieldOffset();
};
class FreeListElement : public AllStatic {
public:
class FakeInstance : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
};
class ForwardingCorpse : public AllStatic {
public:
class FakeInstance : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
};
class FieldTable : public AllStatic {
File diff suppressed because it is too large Load Diff
+71 -7
View File
@@ -64,7 +64,7 @@
FIELD(Class, declaration_type_offset) \
FIELD(Class, num_type_arguments_offset) \
FIELD(Class, super_type_offset) \
FIELD(Class, type_arguments_field_offset_in_words_offset) \
FIELD(Class, host_type_arguments_field_offset_in_words_offset) \
FIELD(ClassTable, shared_class_table_offset) \
FIELD(ClassTable, table_offset) \
NOT_IN_PRODUCT(FIELD(SharedClassTable, class_heap_stats_table_offset)) \
@@ -115,6 +115,7 @@
FIELD(LinkedHashMap, deleted_keys_offset) \
FIELD(LinkedHashMap, hash_mask_offset) \
FIELD(LinkedHashMap, index_offset) \
FIELD(LinkedHashMap, type_arguments_offset) \
FIELD(LinkedHashMap, used_data_offset) \
FIELD(MarkingStackBlock, pointers_offset) \
FIELD(MarkingStackBlock, top_offset) \
@@ -131,6 +132,7 @@
FIELD(ObjectStore, string_type_offset) \
FIELD(OneByteString, data_offset) \
FIELD(Pointer, c_memory_address_offset) \
FIELD(Pointer, type_arguments_offset) \
FIELD(SingleTargetCache, entry_point_offset) \
FIELD(SingleTargetCache, lower_limit_offset) \
FIELD(SingleTargetCache, target_offset) \
@@ -251,22 +253,84 @@
Thread, write_barrier_wrappers_thread_offset, Register, 0, \
kNumberOfCpuRegisters - 1, \
[](Register reg) { return (kDartAvailableCpuRegs & (1 << reg)) != 0; })) \
\
SIZEOF(ApiError, InstanceSize, RawApiError) \
SIZEOF(Array, InstanceSize, RawArray) \
SIZEOF(Array, header_size, RawArray) \
SIZEOF(Bool, InstanceSize, RawBool) \
SIZEOF(Bytecode, InstanceSize, RawBytecode) \
SIZEOF(Capability, InstanceSize, RawCapability) \
SIZEOF(Class, InstanceSize, RawClass) \
SIZEOF(Closure, InstanceSize, RawClosure) \
SIZEOF(ClosureData, InstanceSize, RawClosureData) \
SIZEOF(Code, InstanceSize, RawCode) \
SIZEOF(CodeSourceMap, InstanceSize, RawCodeSourceMap) \
SIZEOF(CompressedStackMaps, InstanceSize, RawCompressedStackMaps) \
SIZEOF(Context, InstanceSize, RawContext) \
SIZEOF(Context, header_size, RawContext) \
SIZEOF(ContextScope, InstanceSize, RawContextScope) \
SIZEOF(Double, InstanceSize, RawDouble) \
SIZEOF(DynamicLibrary, InstanceSize, RawDynamicLibrary) \
SIZEOF(ExceptionHandlers, InstanceSize, RawExceptionHandlers) \
SIZEOF(ExternalOneByteString, InstanceSize, RawExternalOneByteString) \
SIZEOF(ExternalTwoByteString, InstanceSize, RawExternalTwoByteString) \
SIZEOF(ExternalTypedData, InstanceSize, RawExternalTypedData) \
SIZEOF(FfiTrampolineData, InstanceSize, RawFfiTrampolineData) \
SIZEOF(Field, InstanceSize, RawField) \
SIZEOF(Float32x4, InstanceSize, RawFloat32x4) \
SIZEOF(Float64x2, InstanceSize, RawFloat64x2) \
SIZEOF(Function, InstanceSize, RawFunction) \
SIZEOF(GrowableObjectArray, InstanceSize, RawGrowableObjectArray) \
SIZEOF(ICData, InstanceSize, RawICData) \
SIZEOF(Instance, InstanceSize, RawInstance) \
SIZEOF(Instructions, InstanceSize, RawInstructions) \
SIZEOF(Instructions, UnalignedHeaderSize, RawInstructions) \
SIZEOF(Int32x4, InstanceSize, RawInt32x4) \
SIZEOF(Integer, InstanceSize, RawInteger) \
SIZEOF(KernelProgramInfo, InstanceSize, RawKernelProgramInfo) \
SIZEOF(LanguageError, InstanceSize, RawLanguageError) \
SIZEOF(Library, InstanceSize, RawLibrary) \
SIZEOF(LibraryPrefix, InstanceSize, RawLibraryPrefix) \
SIZEOF(LinkedHashMap, InstanceSize, RawLinkedHashMap) \
SIZEOF(LocalVarDescriptors, InstanceSize, RawLocalVarDescriptors) \
SIZEOF(MegamorphicCache, InstanceSize, RawMegamorphicCache) \
SIZEOF(Mint, InstanceSize, RawMint) \
SIZEOF(MirrorReference, InstanceSize, RawMirrorReference) \
SIZEOF(MonomorphicSmiableCall, InstanceSize, RawMonomorphicSmiableCall) \
SIZEOF(Namespace, InstanceSize, RawNamespace) \
SIZEOF(NativeArguments, StructSize, NativeArguments) \
SIZEOF(String, InstanceSize, RawString) \
SIZEOF(TypedData, InstanceSize, RawTypedData) \
SIZEOF(Number, InstanceSize, RawNumber) \
SIZEOF(Object, InstanceSize, RawObject) \
SIZEOF(ObjectPool, InstanceSize, RawObjectPool) \
SIZEOF(OneByteString, InstanceSize, RawOneByteString) \
SIZEOF(ParameterTypeCheck, InstanceSize, RawParameterTypeCheck) \
SIZEOF(PatchClass, InstanceSize, RawPatchClass) \
SIZEOF(PcDescriptors, InstanceSize, RawPcDescriptors) \
SIZEOF(Pointer, InstanceSize, RawPointer) \
SIZEOF(ReceivePort, InstanceSize, RawReceivePort) \
SIZEOF(RedirectionData, InstanceSize, RawRedirectionData) \
SIZEOF(RegExp, InstanceSize, RawRegExp) \
SIZEOF(Script, InstanceSize, RawScript) \
SIZEOF(SendPort, InstanceSize, RawSendPort) \
SIZEOF(SignatureData, InstanceSize, RawSignatureData) \
SIZEOF(SingleTargetCache, InstanceSize, RawSingleTargetCache) \
SIZEOF(Smi, InstanceSize, RawSmi) \
SIZEOF(StackTrace, InstanceSize, RawStackTrace) \
SIZEOF(String, InstanceSize, RawString) \
SIZEOF(SubtypeTestCache, InstanceSize, RawSubtypeTestCache) \
SIZEOF(TransferableTypedData, InstanceSize, RawTransferableTypedData) \
SIZEOF(TwoByteString, InstanceSize, RawTwoByteString) \
SIZEOF(Type, InstanceSize, RawType) \
SIZEOF(TypeArguments, InstanceSize, RawTypeArguments) \
SIZEOF(TypeParameter, InstanceSize, RawTypeParameter) \
SIZEOF(TypeRef, InstanceSize, RawTypeRef) \
SIZEOF(TypedData, InstanceSize, RawTypedData) \
SIZEOF(TypedDataBase, InstanceSize, RawTypedDataBase) \
SIZEOF(Closure, InstanceSize, RawClosure) \
SIZEOF(GrowableObjectArray, InstanceSize, RawGrowableObjectArray) \
SIZEOF(Instance, InstanceSize, RawInstance) \
SIZEOF(LinkedHashMap, InstanceSize, RawLinkedHashMap)
SIZEOF(TypedDataView, InstanceSize, RawTypedDataView) \
SIZEOF(UnhandledException, InstanceSize, RawUnhandledException) \
SIZEOF(UnlinkedCall, InstanceSize, RawUnlinkedCall) \
SIZEOF(UnwindError, InstanceSize, RawUnwindError) \
SIZEOF(UserTag, InstanceSize, RawUserTag) \
SIZEOF(WeakProperty, InstanceSize, RawWeakProperty)
#endif // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
@@ -2726,8 +2726,8 @@ static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
__ mov(kInstanceInstantiatorTypeArgumentsReg, Operand(kNullReg));
__ ldr(R9,
FieldAddress(
R9,
target::Class::type_arguments_field_offset_in_words_offset()));
R9, target::Class::
host_type_arguments_field_offset_in_words_offset()));
__ CompareImmediate(R9, target::Class::kNoTypeArguments);
__ b(&has_no_type_arguments, EQ);
__ add(R9, kInstanceReg, Operand(R9, LSL, 2));
@@ -2851,7 +2851,8 @@ static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
__ LoadClassById(R5, kInstanceCidOrFunction);
__ mov(kInstanceInstantiatorTypeArgumentsReg, kNullReg);
__ LoadFieldFromOffset(
R5, R5, target::Class::type_arguments_field_offset_in_words_offset(),
R5, R5,
target::Class::host_type_arguments_field_offset_in_words_offset(),
kWord);
__ CompareImmediate(R5, target::Class::kNoTypeArguments);
__ b(&has_no_type_arguments, EQ);
@@ -2349,11 +2349,10 @@ static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
Label has_no_type_arguments;
__ LoadClassById(EDI, kInstanceCidOrFunction);
__ movl(kInstanceInstantiatorTypeArgumentsReg, raw_null);
__ movl(
EDI,
FieldAddress(
EDI,
target::Class::type_arguments_field_offset_in_words_offset()));
__ movl(EDI,
FieldAddress(
EDI, target::Class::
host_type_arguments_field_offset_in_words_offset()));
__ cmpl(EDI, Immediate(target::Class::kNoTypeArguments));
__ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
__ movl(kInstanceInstantiatorTypeArgumentsReg,
@@ -2807,11 +2807,10 @@ static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
Label has_no_type_arguments;
__ LoadClassById(RDI, kInstanceCidOrFunction);
__ movq(kInstanceInstantiatorTypeArgumentsReg, kNullReg);
__ movl(
RDI,
FieldAddress(
RDI,
target::Class::type_arguments_field_offset_in_words_offset()));
__ movl(RDI,
FieldAddress(
RDI, target::Class::
host_type_arguments_field_offset_in_words_offset()));
__ cmpl(RDI, Immediate(target::Class::kNoTypeArguments));
__ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
__ movq(kInstanceInstantiatorTypeArgumentsReg,
+1 -1
View File
@@ -4393,7 +4393,7 @@ TEST_CASE(DartAPI_InjectNativeFields3) {
intptr_t header_size = sizeof(RawObject);
EXPECT_EQ(
Utils::RoundUp(((1 + 2) * kWordSize) + header_size, kObjectAlignment),
cls.instance_size());
cls.host_instance_size());
EXPECT_EQ(kNumNativeFields, cls.num_native_fields());
}
+32 -3
View File
@@ -72,7 +72,10 @@ class ReadStream : public ValueObject {
current_ += len;
}
intptr_t ReadUnsigned() { return Read<intptr_t>(kEndUnsignedByteMarker); }
template <typename T = intptr_t>
T ReadUnsigned() {
return Read<T>(kEndUnsignedByteMarker);
}
intptr_t Position() const { return current_ - buffer_; }
void SetPosition(intptr_t value) {
@@ -103,6 +106,19 @@ class ReadStream : public ValueObject {
return Read<T>(kEndByteMarker);
}
uword ReadWordWith32BitReads() {
constexpr intptr_t kNumBytesPerRead32 = sizeof(uint32_t);
constexpr intptr_t kNumRead32PerWord = sizeof(uword) / kNumBytesPerRead32;
constexpr intptr_t kNumBitsPerRead32 = kNumBytesPerRead32 * kBitsPerByte;
uword value = 0;
for (intptr_t j = 0; j < kNumRead32PerWord; j++) {
const auto partial_value = Raw<kNumBytesPerRead32, uint32_t>::Read(this);
value |= (static_cast<uword>(partial_value) << (j * kNumBitsPerRead32));
}
return value;
}
private:
int16_t Read16() { return Read16(kEndByteMarker); }
@@ -363,8 +379,21 @@ class WriteStream : public ValueObject {
}
};
void WriteUnsigned(intptr_t value) {
ASSERT((value >= 0) && (value <= kIntptrMax));
void WriteWordWith32BitWrites(uword value) {
constexpr intptr_t kNumBytesPerWrite32 = sizeof(uint32_t);
constexpr intptr_t kNumWrite32PerWord = sizeof(uword) / kNumBytesPerWrite32;
constexpr intptr_t kNumBitsPerWrite32 = kNumBytesPerWrite32 * kBitsPerByte;
const uint32_t mask = Utils::NBitMask(kNumBitsPerWrite32);
for (intptr_t j = 0; j < kNumWrite32PerWord; j++) {
const uint32_t shifted_value = (value >> (j * kNumBitsPerWrite32));
Raw<kNumBytesPerWrite32, uint32_t>::Write(this, shifted_value & mask);
}
}
template <typename T>
void WriteUnsigned(T value) {
ASSERT(value >= 0);
while (value > kMaxUnsignedDataPerByte) {
WriteByte(static_cast<uint8_t>(value & kByteMask));
value = value >> kDataBitsPerByte;
+1 -1
View File
@@ -307,7 +307,7 @@ void DeferredObject::Fill() {
// materialization of e.g. _ByteDataView objects which don't have
// explicit fields in Dart (all accesses to the fields are done via
// recognized native methods).
ASSERT(offset.Value() < cls.instance_size());
ASSERT(offset.Value() < cls.host_instance_size());
obj.SetFieldAtOffset(offset.Value(), value);
if (FLAG_trace_deoptimization_verbose) {
OS::PrintErr(" null Field @ offset(%" Pd ") <- %s\n",
+1 -1
View File
@@ -137,7 +137,7 @@ class ScavengerVisitor : public ObjectPointerVisitor {
view->RecomputeDataFieldForInternalTypedData();
}
void VisitPointers(RawObject** first, RawObject** last) {
virtual void VisitPointers(RawObject** first, RawObject** last) {
ASSERT(Utils::IsAligned(first, sizeof(*first)));
ASSERT(Utils::IsAligned(last, sizeof(*last)));
for (RawObject** current = first; current <= last; current++) {
+17 -17
View File
@@ -126,10 +126,9 @@ class InterpreterHelpers {
RawClass* instance_class =
thread->isolate()->class_table()->At(GetClassId(instance));
return instance_class->ptr()->num_type_arguments_ > 0
? reinterpret_cast<RawTypeArguments**>(
instance
->ptr())[instance_class->ptr()
->type_arguments_field_offset_in_words_]
? reinterpret_cast<RawTypeArguments**>(instance->ptr())
[instance_class->ptr()
->host_type_arguments_field_offset_in_words_]
: TypeArguments::null();
}
@@ -1205,7 +1204,7 @@ bool Interpreter::AssertAssignable(Thread* thread,
} else if (instance_class->ptr()->num_type_arguments_ > 0) {
instance_type_arguments = reinterpret_cast<RawTypeArguments**>(
instance->ptr())[instance_class->ptr()
->type_arguments_field_offset_in_words_];
->host_type_arguments_field_offset_in_words_];
}
parent_function_type_arguments =
static_cast<RawTypeArguments*>(null_value);
@@ -2333,7 +2332,7 @@ SwitchDispatch:
BYTECODE(InitLateField, D);
RawField* field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
intptr_t offset_in_words = field->ptr()->offset_or_field_id_;
intptr_t offset_in_words = field->ptr()->host_offset_or_field_id_;
instance->StorePointer(
reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
@@ -2362,7 +2361,7 @@ SwitchDispatch:
BYTECODE(StoreStaticTOS, D);
RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
RawInstance* value = static_cast<RawInstance*>(*SP--);
intptr_t field_id = field->ptr()->offset_or_field_id_;
intptr_t field_id = field->ptr()->host_offset_or_field_id_;
thread->field_table_values()[field_id] = value;
DISPATCH();
}
@@ -2370,7 +2369,7 @@ SwitchDispatch:
{
BYTECODE(LoadStatic, D);
RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
intptr_t field_id = field->ptr()->offset_or_field_id_;
intptr_t field_id = field->ptr()->host_offset_or_field_id_;
RawInstance* value = thread->field_table_values()[field_id];
ASSERT((value != Object::sentinel().raw()) &&
(value != Object::transition_sentinel().raw()));
@@ -2383,7 +2382,7 @@ SwitchDispatch:
RawField* field = RAW_CAST(Field, LOAD_CONSTANT(rD + 1));
RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
RawObject* value = reinterpret_cast<RawObject*>(SP[0]);
intptr_t offset_in_words = field->ptr()->offset_or_field_id_;
intptr_t offset_in_words = field->ptr()->host_offset_or_field_id_;
if (InterpreterHelpers::FieldNeedsGuardUpdate(field, value)) {
SP[1] = 0; // Unused result of runtime call.
@@ -2558,7 +2557,7 @@ SwitchDispatch:
RawClass* cls = Class::RawCast(LOAD_CONSTANT(rD));
if (LIKELY(InterpreterHelpers::IsFinalized(cls))) {
const intptr_t class_id = cls->ptr()->id_;
const intptr_t instance_size = cls->ptr()->instance_size_in_words_
const intptr_t instance_size = cls->ptr()->host_instance_size_in_words_
<< kWordSizeLog2;
RawObject* result;
if (TryAllocate(thread, class_id, instance_size, &result)) {
@@ -2588,7 +2587,7 @@ SwitchDispatch:
RawTypeArguments* type_args = TypeArguments::RawCast(SP[-1]);
if (LIKELY(InterpreterHelpers::IsFinalized(cls))) {
const intptr_t class_id = cls->ptr()->id_;
const intptr_t instance_size = cls->ptr()->instance_size_in_words_
const intptr_t instance_size = cls->ptr()->host_instance_size_in_words_
<< kWordSizeLog2;
RawObject* result;
if (TryAllocate(thread, class_id, instance_size, &result)) {
@@ -2598,7 +2597,8 @@ SwitchDispatch:
*reinterpret_cast<RawObject**>(start + offset) = null_value;
}
const intptr_t type_args_offset =
cls->ptr()->type_arguments_field_offset_in_words_ << kWordSizeLog2;
cls->ptr()->host_type_arguments_field_offset_in_words_
<< kWordSizeLog2;
*reinterpret_cast<RawObject**>(start + type_args_offset) = type_args;
*--SP = result;
DISPATCH();
@@ -3168,7 +3168,7 @@ SwitchDispatch:
// Field object is cached in function's data_.
RawField* field = reinterpret_cast<RawField*>(function->ptr()->data_);
intptr_t offset_in_words = field->ptr()->offset_or_field_id_;
intptr_t offset_in_words = field->ptr()->host_offset_or_field_id_;
const intptr_t kArgc = 1;
RawInstance* instance =
@@ -3188,7 +3188,7 @@ SwitchDispatch:
function = FrameFunction(FP);
instance = reinterpret_cast<RawInstance*>(SP[2]);
field = reinterpret_cast<RawField*>(SP[3]);
offset_in_words = field->ptr()->offset_or_field_id_;
offset_in_words = field->ptr()->host_offset_or_field_id_;
value = reinterpret_cast<RawInstance**>(instance->ptr())[offset_in_words];
}
@@ -3249,7 +3249,7 @@ SwitchDispatch:
// Field object is cached in function's data_.
RawField* field = reinterpret_cast<RawField*>(function->ptr()->data_);
intptr_t offset_in_words = field->ptr()->offset_or_field_id_;
intptr_t offset_in_words = field->ptr()->host_offset_or_field_id_;
const intptr_t kArgc = 2;
RawInstance* instance =
reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[0]);
@@ -3329,7 +3329,7 @@ SwitchDispatch:
// Field object is cached in function's data_.
RawField* field = reinterpret_cast<RawField*>(function->ptr()->data_);
intptr_t field_id = field->ptr()->offset_or_field_id_;
intptr_t field_id = field->ptr()->host_offset_or_field_id_;
RawInstance* value = thread->field_table_values()[field_id];
if (value == Object::sentinel().raw() ||
value == Object::transition_sentinel().raw()) {
@@ -3343,7 +3343,7 @@ SwitchDispatch:
function = FrameFunction(FP);
field = reinterpret_cast<RawField*>(function->ptr()->data_);
// The field is initialized by the runtime call, but not returned.
intptr_t field_id = field->ptr()->offset_or_field_id_;
intptr_t field_id = field->ptr()->host_offset_or_field_id_;
value = thread->field_table_values()[field_id];
}
+8 -7
View File
@@ -110,9 +110,9 @@ InstanceMorpher* InstanceMorpher::CreateFromClassDescriptors(
if (from.NumTypeArguments() > 0) {
// Add copying of the optional type argument field.
intptr_t from_offset = from.type_arguments_field_offset();
intptr_t from_offset = from.host_type_arguments_field_offset();
ASSERT(from_offset != Class::kNoTypeArguments);
intptr_t to_offset = to.type_arguments_field_offset();
intptr_t to_offset = to.host_type_arguments_field_offset();
ASSERT(to_offset != Class::kNoTypeArguments);
mapping->Add(from_offset);
mapping->Add(to_offset);
@@ -152,8 +152,8 @@ InstanceMorpher* InstanceMorpher::CreateFromClassDescriptors(
from_name = from_field.name();
if (from_name.Equals(to_name)) {
// Success
mapping->Add(from_field.Offset());
mapping->Add(to_field.Offset());
mapping->Add(from_field.HostOffset());
mapping->Add(to_field.HostOffset());
// Field did exist in old class deifnition.
new_field = false;
}
@@ -163,7 +163,7 @@ InstanceMorpher* InstanceMorpher::CreateFromClassDescriptors(
const Field& field = Field::Handle(to_field.raw());
field.set_needs_load_guard(true);
field.set_is_unboxing_candidate(false);
new_fields_offsets->Add(field.Offset());
new_fields_offsets->Add(field.HostOffset());
}
}
@@ -1247,8 +1247,9 @@ void IsolateGroupReloadContext::FindModifiedSources(
uri = script.url();
const bool dart_scheme = uri.StartsWith(Symbols::DartScheme());
if (dart_scheme) {
// If a user-defined class mixes in a mixin from dart:*, it's list of scripts will have
// a dart:* script as well. We don't consider those during reload.
// If a user-defined class mixes in a mixin from dart:*, it's list of
// scripts will have a dart:* script as well. We don't consider those
// during reload.
continue;
}
if (ContainsScriptUri(modified_sources_uris, uri.ToCString())) {
+12
View File
@@ -8,6 +8,7 @@
#include <memory>
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/frontend/constant_reader.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/dart_api_impl.h"
@@ -948,6 +949,17 @@ void KernelLoader::ReadInferredType(const Field& field,
field.set_guarded_cid(type.cid);
field.set_is_nullable(type.IsNullable());
field.set_guarded_list_length(Field::kNoFixedLength);
if (FLAG_precompiled_mode) {
field.set_is_unboxing_candidate(
!field.is_late() && !field.is_static() &&
((field.guarded_cid() == kDoubleCid &&
FlowGraphCompiler::SupportsUnboxedDoubles()) ||
(field.guarded_cid() == kFloat32x4Cid &&
FlowGraphCompiler::SupportsUnboxedSimd128()) ||
(field.guarded_cid() == kFloat64x2Cid &&
FlowGraphCompiler::SupportsUnboxedSimd128())) &&
!field.is_nullable());
}
}
void KernelLoader::CheckForInitializer(const Field& field) {
+473 -237
View File
File diff suppressed because it is too large Load Diff
+219 -52
View File
@@ -266,6 +266,15 @@ class ZoneTextBuffer;
#define MINT_OBJECT_IMPLEMENTATION(object, rettype, super) \
FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, rettype, super)
// In precompiled runtime, there is no access to runtime_api.cc since host
// and target are the same. In those cases, the namespace dart is used to refer
// to the target namespace
#if defined(DART_PRECOMPILED_RUNTIME)
namespace RTN = dart;
#else
namespace RTN = dart::compiler::target;
#endif // defined(DART_PRECOMPILED_RUNTIME)
class Object {
public:
using RawObjectType = RawObject;
@@ -885,36 +894,88 @@ class Class : public Object {
kInvocationDispatcherEntrySize,
};
intptr_t instance_size() const {
intptr_t host_instance_size() const {
ASSERT(is_finalized() || is_prefinalized());
return (raw_ptr()->instance_size_in_words_ * kWordSize);
return (raw_ptr()->host_instance_size_in_words_ * kWordSize);
}
static intptr_t instance_size(RawClass* clazz) {
return (clazz->ptr()->instance_size_in_words_ * kWordSize);
intptr_t target_instance_size() const {
ASSERT(is_finalized() || is_prefinalized());
#if !defined(DART_PRECOMPILED_RUNTIME)
return (raw_ptr()->target_instance_size_in_words_ *
compiler::target::kWordSize);
#else
return host_instance_size();
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
void set_instance_size(intptr_t value_in_bytes) const {
static intptr_t host_instance_size(RawClass* clazz) {
return (clazz->ptr()->host_instance_size_in_words_ * kWordSize);
}
static intptr_t target_instance_size(RawClass* clazz) {
#if !defined(DART_PRECOMPILED_RUNTIME)
return (clazz->ptr()->target_instance_size_in_words_ *
compiler::target::kWordSize);
#else
return host_instance_size(clazz);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
void set_instance_size(intptr_t host_value_in_bytes,
intptr_t target_value_in_bytes) const {
ASSERT(kWordSize != 0);
set_instance_size_in_words(value_in_bytes / kWordSize);
set_instance_size_in_words(
host_value_in_bytes / kWordSize,
target_value_in_bytes / compiler::target::kWordSize);
}
void set_instance_size_in_words(intptr_t value) const {
ASSERT(Utils::IsAligned((value * kWordSize), kObjectAlignment));
StoreNonPointer(&raw_ptr()->instance_size_in_words_, value);
void set_instance_size_in_words(intptr_t host_value,
intptr_t target_value) const {
ASSERT(Utils::IsAligned((host_value * kWordSize), kObjectAlignment));
StoreNonPointer(&raw_ptr()->host_instance_size_in_words_, host_value);
#if !defined(DART_PRECOMPILED_RUNTIME)
ASSERT(Utils::IsAligned((target_value * compiler::target::kWordSize),
compiler::target::kObjectAlignment));
StoreNonPointer(&raw_ptr()->target_instance_size_in_words_, target_value);
#else
ASSERT(host_value == target_value);
#endif // #!defined(DART_PRECOMPILED_RUNTIME)
}
intptr_t next_field_offset() const {
return raw_ptr()->next_field_offset_in_words_ * kWordSize;
intptr_t host_next_field_offset() const {
return raw_ptr()->host_next_field_offset_in_words_ * kWordSize;
}
void set_next_field_offset(intptr_t value_in_bytes) const {
ASSERT(kWordSize != 0);
set_next_field_offset_in_words(value_in_bytes / kWordSize);
intptr_t target_next_field_offset() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
return raw_ptr()->target_next_field_offset_in_words_ *
compiler::target::kWordSize;
#else
return host_next_field_offset();
#endif // #!defined(DART_PRECOMPILED_RUNTIME)
}
void set_next_field_offset_in_words(intptr_t value) const {
ASSERT((value == -1) ||
(Utils::IsAligned((value * kWordSize), kObjectAlignment) &&
(value == raw_ptr()->instance_size_in_words_)) ||
(!Utils::IsAligned((value * kWordSize), kObjectAlignment) &&
((value + 1) == raw_ptr()->instance_size_in_words_)));
StoreNonPointer(&raw_ptr()->next_field_offset_in_words_, value);
void set_next_field_offset(intptr_t host_value_in_bytes,
intptr_t target_value_in_bytes) const {
set_next_field_offset_in_words(
host_value_in_bytes / kWordSize,
target_value_in_bytes / compiler::target::kWordSize);
}
void set_next_field_offset_in_words(intptr_t host_value,
intptr_t target_value) const {
ASSERT((host_value == -1) ||
(Utils::IsAligned((host_value * kWordSize), kObjectAlignment) &&
(host_value == raw_ptr()->host_instance_size_in_words_)) ||
(!Utils::IsAligned((host_value * kWordSize), kObjectAlignment) &&
((host_value + 1) == raw_ptr()->host_instance_size_in_words_)));
StoreNonPointer(&raw_ptr()->host_next_field_offset_in_words_, host_value);
#if !defined(DART_PRECOMPILED_RUNTIME)
ASSERT((target_value == -1) ||
(Utils::IsAligned((target_value * compiler::target::kWordSize),
compiler::target::kObjectAlignment) &&
(target_value == raw_ptr()->target_instance_size_in_words_)) ||
(!Utils::IsAligned((target_value * compiler::target::kWordSize),
compiler::target::kObjectAlignment) &&
((target_value + 1) == raw_ptr()->target_instance_size_in_words_)));
StoreNonPointer(&raw_ptr()->target_next_field_offset_in_words_,
target_value);
#else
ASSERT(host_value == target_value);
#endif // #!defined(DART_PRECOMPILED_RUNTIME)
}
static bool is_valid_id(intptr_t value) {
@@ -1013,28 +1074,64 @@ class Class : public Object {
// If this class is parameterized, each instance has a type_arguments field.
static const intptr_t kNoTypeArguments = -1;
intptr_t type_arguments_field_offset() const {
intptr_t host_type_arguments_field_offset() const {
ASSERT(is_type_finalized() || is_prefinalized());
if (raw_ptr()->type_arguments_field_offset_in_words_ == kNoTypeArguments) {
if (raw_ptr()->host_type_arguments_field_offset_in_words_ ==
kNoTypeArguments) {
return kNoTypeArguments;
}
return raw_ptr()->type_arguments_field_offset_in_words_ * kWordSize;
return raw_ptr()->host_type_arguments_field_offset_in_words_ * kWordSize;
}
void set_type_arguments_field_offset(intptr_t value_in_bytes) const {
intptr_t value;
if (value_in_bytes == kNoTypeArguments) {
value = kNoTypeArguments;
} else {
ASSERT(kWordSize != 0);
value = value_in_bytes / kWordSize;
intptr_t target_type_arguments_field_offset() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
ASSERT(is_type_finalized() || is_prefinalized());
if (raw_ptr()->target_type_arguments_field_offset_in_words_ ==
compiler::target::Class::kNoTypeArguments) {
return compiler::target::Class::kNoTypeArguments;
}
set_type_arguments_field_offset_in_words(value);
return raw_ptr()->target_type_arguments_field_offset_in_words_ *
compiler::target::kWordSize;
#else
return host_type_arguments_field_offset();
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
void set_type_arguments_field_offset_in_words(intptr_t value) const {
StoreNonPointer(&raw_ptr()->type_arguments_field_offset_in_words_, value);
void set_type_arguments_field_offset(intptr_t host_value_in_bytes,
intptr_t target_value_in_bytes) const {
intptr_t host_value, target_value;
if (host_value_in_bytes == kNoTypeArguments ||
target_value_in_bytes == RTN::Class::kNoTypeArguments) {
ASSERT(host_value_in_bytes == kNoTypeArguments &&
target_value_in_bytes == RTN::Class::kNoTypeArguments);
host_value = kNoTypeArguments;
target_value = RTN::Class::kNoTypeArguments;
} else {
ASSERT(kWordSize != 0 && compiler::target::kWordSize);
host_value = host_value_in_bytes / kWordSize;
target_value = target_value_in_bytes / compiler::target::kWordSize;
}
set_type_arguments_field_offset_in_words(host_value, target_value);
}
static intptr_t type_arguments_field_offset_in_words_offset() {
return OFFSET_OF(RawClass, type_arguments_field_offset_in_words_);
void set_type_arguments_field_offset_in_words(intptr_t host_value,
intptr_t target_value) const {
StoreNonPointer(&raw_ptr()->host_type_arguments_field_offset_in_words_,
host_value);
#if !defined(DART_PRECOMPILED_RUNTIME)
StoreNonPointer(&raw_ptr()->target_type_arguments_field_offset_in_words_,
target_value);
#else
ASSERT(host_value == target_value);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
static intptr_t host_type_arguments_field_offset_in_words_offset() {
return OFFSET_OF(RawClass, host_type_arguments_field_offset_in_words_);
}
static intptr_t target_type_arguments_field_offset_in_words_offset() {
#if !defined(DART_PRECOMPILED_RUNTIME)
return OFFSET_OF(RawClass, target_type_arguments_field_offset_in_words_);
#else
return host_type_arguments_field_offset_in_words_offset();
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
// The super type of this class, Object type if not explicitly specified.
@@ -1395,7 +1492,7 @@ class Class : public Object {
RawError* EnsureIsFinalized(Thread* thread) const;
// Allocate a class used for VM internal objects.
template <class FakeObject>
template <class FakeObject, class TargetFakeObject>
static RawClass* New(Isolate* isolate, bool register_class = true);
// Allocate instance classes.
@@ -1460,6 +1557,44 @@ class Class : public Object {
const Array& args_desc,
const Function& dispatcher) const;
static int32_t host_instance_size_in_words(const RawClass* cls) {
return cls->ptr()->host_instance_size_in_words_;
}
static int32_t target_instance_size_in_words(const RawClass* cls) {
#if !defined(DART_PRECOMPILED_RUNTIME)
return cls->ptr()->target_instance_size_in_words_;
#else
return host_instance_size_in_words(cls);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
static int32_t host_next_field_offset_in_words(const RawClass* cls) {
return cls->ptr()->host_next_field_offset_in_words_;
}
static int32_t target_next_field_offset_in_words(const RawClass* cls) {
#if !defined(DART_PRECOMPILED_RUNTIME)
return cls->ptr()->target_next_field_offset_in_words_;
#else
return host_next_field_offset_in_words(cls);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
static int32_t host_type_arguments_field_offset_in_words(
const RawClass* cls) {
return cls->ptr()->host_type_arguments_field_offset_in_words_;
}
static int32_t target_type_arguments_field_offset_in_words(
const RawClass* cls) {
#if !defined(DART_PRECOMPILED_RUNTIME)
return cls->ptr()->target_type_arguments_field_offset_in_words_;
#else
return host_type_arguments_field_offset_in_words(cls);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
private:
RawType* declaration_type() const { return raw_ptr()->declaration_type_; }
@@ -1474,7 +1609,7 @@ class Class : public Object {
// Tells whether instances need morphing for reload.
bool RequiresInstanceMorphing(const Class& replacement) const;
template <class FakeObject>
template <class FakeInstance, class TargetFakeInstance>
static RawClass* NewCommon(intptr_t index);
enum MemberKind {
@@ -1538,7 +1673,8 @@ class Class : public Object {
const Array& args_desc,
RawFunction::Kind kind) const;
void CalculateFieldOffsets() const;
// Returns the bitmap of unboxed fields
UnboxedFieldBitmap CalculateFieldOffsets() const;
// functions_hash_table is in use iff there are at least this many functions.
static const intptr_t kFunctionLookupHashTreshold = 16;
@@ -1576,7 +1712,7 @@ class Class : public Object {
const String& name) const;
// Allocate an instance class which has a VM implementation.
template <class FakeInstance>
template <class FakeInstance, class TargetFakeInstance>
static RawClass* New(intptr_t id,
Isolate* isolate,
bool register_class = true,
@@ -3643,15 +3779,19 @@ class Field : public Object {
intptr_t KernelDataProgramOffset() const;
inline intptr_t Offset() const;
// Called during class finalization.
inline void SetOffset(intptr_t offset_in_bytes) const;
inline void SetOffset(intptr_t host_offset_in_bytes,
intptr_t target_offset_in_bytes) const;
inline intptr_t HostOffset() const;
inline intptr_t TargetOffset() const;
inline RawInstance* StaticValue() const;
void SetStaticValue(const Instance& value,
bool save_initial_value = false) const;
intptr_t field_id() const { return raw_ptr()->offset_or_field_id_; }
intptr_t field_id() const { return raw_ptr()->host_offset_or_field_id_; }
inline void set_field_id(intptr_t field_id) const;
#ifndef DART_PRECOMPILED_RUNTIME
@@ -3748,6 +3888,14 @@ class Field : public Object {
return OFFSET_OF(RawField, static_type_exactness_state_);
}
static inline intptr_t TargetOffsetOf(const RawField* field) {
#if !defined(DART_PRECOMPILED_RUNTIME)
return field->ptr()->target_offset_;
#else
return field->ptr()->host_offset_or_field_id_;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
// Return class id that any non-null value read from this field is guaranteed
// to have or kDynamicCid if such class id is not known.
// Stores to this field must update this information hence the name.
@@ -6554,7 +6702,7 @@ class Instance : public Object {
const Class& cls = Class::Handle(clazz());
ASSERT(cls.is_finalized() || cls.is_prefinalized());
#endif
return (clazz()->ptr()->instance_size_in_words_ * kWordSize);
return (clazz()->ptr()->host_instance_size_in_words_ * kWordSize);
}
// Returns Instance::null() if instance cannot be canonicalized.
@@ -6576,7 +6724,7 @@ class Instance : public Object {
virtual bool CheckIsCanonical(Thread* thread) const;
#endif // DEBUG
RawObject* GetField(const Field& field) const { return *FieldAddr(field); }
RawObject* GetField(const Field& field) const;
void SetField(const Field& field, const Object& value) const;
@@ -6713,7 +6861,7 @@ class Instance : public Object {
return reinterpret_cast<RawObject**>(raw_value() - kHeapObjectTag + offset);
}
RawObject** FieldAddr(const Field& field) const {
return FieldAddrAtOffset(field.Offset());
return FieldAddrAtOffset(field.HostOffset());
}
RawObject** NativeFieldsAddr() const {
return FieldAddrAtOffset(sizeof(RawObject));
@@ -10313,26 +10461,45 @@ bool Function::HasBytecode(RawFunction* function) {
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
intptr_t Field::Offset() const {
intptr_t Field::HostOffset() const {
ASSERT(is_instance()); // Valid only for dart instance fields.
return (raw_ptr()->offset_or_field_id_ * kWordSize);
return (raw_ptr()->host_offset_or_field_id_ * kWordSize);
}
void Field::SetOffset(intptr_t offset_in_bytes) const {
intptr_t Field::TargetOffset() const {
ASSERT(is_instance()); // Valid only for dart instance fields.
#if !defined(DART_PRECOMPILED_RUNTIME)
return (raw_ptr()->target_offset_ * compiler::target::kWordSize);
#else
return HostOffset();
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
void Field::SetOffset(intptr_t host_offset_in_bytes,
intptr_t target_offset_in_bytes) const {
ASSERT(is_instance()); // Valid only for dart instance fields.
ASSERT(kWordSize != 0);
StoreNonPointer(&raw_ptr()->offset_or_field_id_, offset_in_bytes / kWordSize);
StoreNonPointer(&raw_ptr()->host_offset_or_field_id_,
host_offset_in_bytes / kWordSize);
#if !defined(DART_PRECOMPILED_RUNTIME)
ASSERT(compiler::target::kWordSize != 0);
StoreNonPointer(&raw_ptr()->target_offset_,
target_offset_in_bytes / compiler::target::kWordSize);
#else
ASSERT(host_offset_in_bytes == target_offset_in_bytes);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
RawInstance* Field::StaticValue() const {
ASSERT(is_static()); // Valid only for static dart fields.
return Isolate::Current()->field_table()->At(raw_ptr()->offset_or_field_id_);
return Isolate::Current()->field_table()->At(
raw_ptr()->host_offset_or_field_id_);
}
void Field::set_field_id(intptr_t field_id) const {
ASSERT(is_static());
ASSERT(Thread::Current()->IsMutatorThread());
StoreNonPointer(&raw_ptr()->offset_or_field_id_, field_id);
StoreNonPointer(&raw_ptr()->host_offset_or_field_id_, field_id);
}
#ifndef DART_PRECOMPILED_RUNTIME
+1 -1
View File
@@ -1097,7 +1097,7 @@ void HeapSnapshotWriter::Write() {
if (field.is_instance()) {
intptr_t flags = 1; // Strong.
WriteUnsigned(flags);
intptr_t index = field.Offset() / kWordSize - 1;
intptr_t index = field.HostOffset() / kWordSize - 1;
ASSERT(index >= 0);
WriteUnsigned(index);
str = field.name();
+6 -4
View File
@@ -663,8 +663,8 @@ class InstanceSizeConflict : public ClassReasonForCancelling {
return String::NewFormatted("Instance size mismatch between '%s' (%" Pd
") and replacement "
"'%s' ( %" Pd ")",
from_.ToCString(), from_.instance_size(),
to_.ToCString(), to_.instance_size());
from_.ToCString(), from_.host_instance_size(),
to_.ToCString(), to_.host_instance_size());
}
};
@@ -748,7 +748,9 @@ bool Class::RequiresInstanceMorphing(const Class& replacement) const {
// Check that we have the same next field offset. This check is not
// redundant with the one above because the instance OffsetToFieldMap
// array length is based on the instance size (which may be aligned up).
if (next_field_offset() != replacement.next_field_offset()) return true;
if (host_next_field_offset() != replacement.host_next_field_offset()) {
return true;
}
// Verify that field names / offsets match across the entire hierarchy.
Field& field = Field::Handle();
@@ -805,7 +807,7 @@ bool Class::CanReloadPreFinalized(const Class& replacement,
return false;
}
// Check the instance sizes are equal.
if (instance_size() != replacement.instance_size()) {
if (host_instance_size() != replacement.host_instance_size()) {
context->group_reload_context()->AddReasonForCancelling(
new (context->zone())
InstanceSizeConflict(context->zone(), *this, replacement));
+3 -3
View File
@@ -217,7 +217,7 @@ ISOLATE_UNIT_TEST_CASE(InstanceClass) {
ClassFinalizer::FinalizeTypesInClass(empty_class);
empty_class.Finalize();
EXPECT_EQ(kObjectAlignment, empty_class.instance_size());
EXPECT_EQ(kObjectAlignment, empty_class.host_instance_size());
Instance& instance = Instance::Handle(Instance::New(empty_class));
EXPECT_EQ(empty_class.raw(), instance.clazz());
@@ -242,8 +242,8 @@ ISOLATE_UNIT_TEST_CASE(InstanceClass) {
one_field_class.Finalize();
intptr_t header_size = sizeof(RawObject);
EXPECT_EQ(Utils::RoundUp((header_size + (1 * kWordSize)), kObjectAlignment),
one_field_class.instance_size());
EXPECT_EQ(header_size, field.Offset());
one_field_class.host_instance_size());
EXPECT_EQ(header_size, field.HostOffset());
EXPECT(!one_field_class.is_implemented());
one_field_class.set_is_implemented();
EXPECT(one_field_class.is_implemented());
+21 -3
View File
@@ -377,14 +377,32 @@ void RawObject::VisitPointersPrecise(ObjectPointerVisitor* visitor) {
uword next_field_offset = visitor->isolate()
->GetClassForHeapWalkAt(class_id)
->ptr()
->next_field_offset_in_words_
->host_next_field_offset_in_words_
<< kWordSizeLog2;
ASSERT(next_field_offset > 0);
uword obj_addr = RawObject::ToAddr(this);
uword from = obj_addr + sizeof(RawObject);
uword to = obj_addr + next_field_offset - kWordSize;
visitor->VisitPointers(reinterpret_cast<RawObject**>(from),
reinterpret_cast<RawObject**>(to));
const auto first = reinterpret_cast<RawObject**>(from);
const auto last = reinterpret_cast<RawObject**>(to);
#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
const auto unboxed_fields_bitmap =
visitor->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
if (!unboxed_fields_bitmap.IsEmpty()) {
intptr_t bit = sizeof(RawObject) / kWordSize;
for (RawObject** current = first; current <= last; current++) {
if (!unboxed_fields_bitmap.Get(bit++)) {
visitor->VisitPointer(current);
}
}
} else {
visitor->VisitPointers(first, last);
}
#else
visitor->VisitPointers(first, last);
#endif // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
}
bool RawObject::FindObject(FindObjectVisitor* visitor) {
+70 -10
View File
@@ -474,10 +474,27 @@ class RawObject {
uword obj_addr = ToAddr(this);
uword from = obj_addr + sizeof(RawObject);
uword to = obj_addr + instance_size - kWordSize;
const auto first = reinterpret_cast<RawObject**>(from);
const auto last = reinterpret_cast<RawObject**>(to);
#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
const auto unboxed_fields_bitmap =
visitor->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
if (!unboxed_fields_bitmap.IsEmpty()) {
intptr_t bit = sizeof(RawObject) / kWordSize;
for (RawObject** current = first; current <= last; current++) {
if (!unboxed_fields_bitmap.Get(bit++)) {
visitor->VisitPointer(current);
}
}
} else {
visitor->VisitPointers(first, last);
}
#else
// Call visitor function virtually
visitor->VisitPointers(reinterpret_cast<RawObject**>(from),
reinterpret_cast<RawObject**>(to));
visitor->VisitPointers(first, last);
#endif // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
return instance_size;
}
@@ -495,10 +512,27 @@ class RawObject {
uword obj_addr = ToAddr(this);
uword from = obj_addr + sizeof(RawObject);
uword to = obj_addr + instance_size - kWordSize;
const auto first = reinterpret_cast<RawObject**>(from);
const auto last = reinterpret_cast<RawObject**>(to);
#if defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
const auto unboxed_fields_bitmap =
visitor->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
if (!unboxed_fields_bitmap.IsEmpty()) {
intptr_t bit = sizeof(RawObject) / kWordSize;
for (RawObject** current = first; current <= last; current++) {
if (!unboxed_fields_bitmap.Get(bit++)) {
visitor->V::VisitPointers(current, current);
}
}
} else {
visitor->V::VisitPointers(first, last);
}
#else
// Call visitor function non-virtually
visitor->V::VisitPointers(reinterpret_cast<RawObject**>(from),
reinterpret_cast<RawObject**>(to));
visitor->V::VisitPointers(first, last);
#endif // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
return instance_size;
}
@@ -814,14 +848,32 @@ class RawClass : public RawObject {
TokenPosition token_pos_;
TokenPosition end_token_pos_;
int32_t instance_size_in_words_; // Size if fixed len or 0 if variable len.
int32_t type_arguments_field_offset_in_words_; // Offset of type args fld.
int32_t next_field_offset_in_words_; // Offset of the next instance field.
classid_t id_; // Class Id, also index in the class table.
int16_t num_type_arguments_; // Number of type arguments in flattened vector.
uint16_t num_native_fields_;
uint32_t state_bits_;
// Size if fixed len or 0 if variable len.
int32_t host_instance_size_in_words_;
// Offset of type args fld.
int32_t host_type_arguments_field_offset_in_words_;
// Offset of the next instance field.
int32_t host_next_field_offset_in_words_;
#if !defined(DART_PRECOMPILED_RUNTIME)
// Size if fixed len or 0 if variable len (target).
int32_t target_instance_size_in_words_;
// Offset of type args fld.
int32_t target_type_arguments_field_offset_in_words_;
// Offset of the next instance field (target).
int32_t target_next_field_offset_in_words_;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(DART_PRECOMPILED_RUNTIME)
typedef BitField<uint32_t, bool, 0, 1> IsDeclaredInBytecode;
typedef BitField<uint32_t, uint32_t, 1, 31> BinaryDeclarationOffset;
@@ -1177,11 +1229,16 @@ class RawField : public RawObject {
// field.
int8_t static_type_exactness_state_;
uint16_t kind_bits_; // static, final, const, has initializer....
// - for instance fields: offset in words to the value in the class instance.
// - for static fields: index into field_table.
intptr_t offset_or_field_id_;
intptr_t host_offset_or_field_id_;
uint16_t kind_bits_; // static, final, const, has initializer....
#if !defined(DART_PRECOMPILED_RUNTIME)
// for instance fields, the offset in words in the target architecture
int32_t target_offset_;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
friend class CidRewriteVisitor;
};
@@ -1429,7 +1486,7 @@ class RawCode : public RawObject {
#endif
// Compilation timestamp.
NOT_IN_PRODUCT(int64_t compile_timestamp_);
NOT_IN_PRODUCT(alignas(8) int64_t compile_timestamp_);
// state_bits_ is a bitfield with three fields:
// The optimized bit, the alive bit, and a count of the number of pointer
@@ -2258,6 +2315,7 @@ class RawDouble : public RawNumber {
friend class Api;
friend class SnapshotReader;
friend class Class;
};
COMPILE_ASSERT(sizeof(RawDouble) == 16);
@@ -2528,6 +2586,7 @@ class RawFloat32x4 : public RawInstance {
ALIGN8 float value_[4];
friend class SnapshotReader;
friend class Class;
public:
float x() const { return value_[0]; }
@@ -2560,6 +2619,7 @@ class RawFloat64x2 : public RawInstance {
ALIGN8 double value_[2];
friend class SnapshotReader;
friend class Class;
public:
double x() const { return value_[0]; }
+47 -24
View File
@@ -593,47 +593,59 @@ RawObject* SnapshotReader::ReadInstance(intptr_t object_id,
ASSERT(!cls_.IsNull());
// Closure instances are handled by Closure::ReadFrom().
ASSERT(!cls_.IsClosureClass());
instance_size = cls_.instance_size();
instance_size = cls_.host_instance_size();
ASSERT(instance_size > 0);
// Allocate the instance and read in all the fields for the object.
*result ^= Object::Allocate(cls_.id(), instance_size, Heap::kNew);
} else {
cls_ ^= ReadObjectImpl(kAsInlinedObject);
ASSERT(!cls_.IsNull());
instance_size = cls_.instance_size();
instance_size = cls_.host_instance_size();
}
if (cls_.id() == set_class_.id()) {
EnqueueRehashingOfSet(*result);
}
if (!as_reference) {
// Read all the individual fields for inlined objects.
intptr_t next_field_offset = cls_.next_field_offset();
intptr_t next_field_offset = cls_.host_next_field_offset();
intptr_t type_argument_field_offset = cls_.type_arguments_field_offset();
intptr_t type_argument_field_offset =
cls_.host_type_arguments_field_offset();
ASSERT(next_field_offset > 0);
// Instance::NextFieldOffset() returns the offset of the first field in
// a Dart object.
bool read_as_reference = RawObject::IsCanonical(tags) ? false : true;
intptr_t offset = Instance::NextFieldOffset();
intptr_t result_cid = result->GetClassId();
const auto unboxed_fields =
isolate()->shared_class_table()->GetUnboxedFieldsMapAt(result_cid);
while (offset < next_field_offset) {
pobj_ = ReadObjectImpl(read_as_reference);
result->SetFieldAtOffset(offset, pobj_);
if ((offset != type_argument_field_offset) &&
(kind_ == Snapshot::kMessage) && isolate()->use_field_guards()) {
// TODO(fschneider): Consider hoisting these lookups out of the loop.
// This would involve creating a handle, since cls_ can't be reused
// across the call to ReadObjectImpl.
cls_ = isolate()->class_table()->At(result_cid);
array_ = cls_.OffsetToFieldMap();
field_ ^= array_.At(offset >> kWordSizeLog2);
ASSERT(!field_.IsNull());
ASSERT(field_.Offset() == offset);
obj_ = pobj_.raw();
field_.RecordStore(obj_);
if (unboxed_fields.Get(offset / kWordSize)) {
uword* p = reinterpret_cast<uword*>(result->raw_value() -
kHeapObjectTag + offset);
// Reads 32 bits of the unboxed value at a time
*p = ReadWordWith32BitReads();
} else {
pobj_ = ReadObjectImpl(read_as_reference);
result->SetFieldAtOffset(offset, pobj_);
if ((offset != type_argument_field_offset) &&
(kind_ == Snapshot::kMessage) && isolate()->use_field_guards()) {
// TODO(fschneider): Consider hoisting these lookups out of the loop.
// This would involve creating a handle, since cls_ can't be reused
// across the call to ReadObjectImpl.
cls_ = isolate()->class_table()->At(result_cid);
array_ = cls_.OffsetToFieldMap();
field_ ^= array_.At(offset >> kWordSizeLog2);
ASSERT(!field_.IsNull());
ASSERT(field_.HostOffset() == offset);
obj_ = pobj_.raw();
field_.RecordStore(obj_);
}
// TODO(fschneider): Verify the guarded cid and length for other kinds
// of snapshot (kFull, kScript) with asserts.
}
// TODO(fschneider): Verify the guarded cid and length for other kinds of
// snapshot (kFull, kScript) with asserts.
offset += kWordSize;
}
if (RawObject::IsCanonical(tags)) {
@@ -1439,7 +1451,7 @@ void SnapshotWriter::WriteInstance(RawObject* raw,
// Write out the class information for this object.
WriteObjectImpl(cls, kAsInlinedObject);
} else {
intptr_t next_field_offset = cls->ptr()->next_field_offset_in_words_
intptr_t next_field_offset = Class::host_next_field_offset_in_words(cls)
<< kWordSizeLog2;
ASSERT(next_field_offset > 0);
@@ -1455,15 +1467,26 @@ void SnapshotWriter::WriteInstance(RawObject* raw,
// Write out the class information for this object.
WriteObjectImpl(cls, kAsInlinedObject);
const auto unboxed_fields =
isolate()->shared_class_table()->GetUnboxedFieldsMapAt(cls->ptr()->id_);
// Write out all the fields for the object.
// Instance::NextFieldOffset() returns the offset of the first field in
// a Dart object.
bool write_as_reference = RawObject::IsCanonical(tags) ? false : true;
intptr_t offset = Instance::NextFieldOffset();
while (offset < next_field_offset) {
RawObject* raw_obj = *reinterpret_cast<RawObject**>(
reinterpret_cast<uword>(raw->ptr()) + offset);
WriteObjectImpl(raw_obj, write_as_reference);
if (unboxed_fields.Get(offset / kWordSize)) {
// Writes 32 bits of the unboxed value at a time
const uword value = *reinterpret_cast<uword*>(
reinterpret_cast<uword>(raw->ptr()) + offset);
WriteWordWith32BitWrites(value);
} else {
RawObject* raw_obj = *reinterpret_cast<RawObject**>(
reinterpret_cast<uword>(raw->ptr()) + offset);
WriteObjectImpl(raw_obj, write_as_reference);
}
offset += kWordSize;
}
}
+6
View File
@@ -272,6 +272,8 @@ class BaseReader {
return SerializedHeaderData::decode(value);
}
uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
private:
ReadStream stream_; // input stream.
};
@@ -529,6 +531,10 @@ class BaseWriter : public StackResource {
stream_.WriteBytes(reinterpret_cast<const uint8_t*>(&value), sizeof(value));
}
void WriteWordWith32BitWrites(uword value) {
stream_.WriteWordWith32BitWrites(value);
}
protected:
BaseWriter(ReAlloc alloc, DeAlloc dealloc, intptr_t initial_size)
: StackResource(Thread::Current()),
+16
View File
@@ -0,0 +1,16 @@
// 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.
#include "vm/visitor.h"
#include "vm/isolate.h"
namespace dart {
ObjectPointerVisitor::ObjectPointerVisitor(Isolate* isolate)
: isolate_(isolate),
gc_root_type_("unknown"),
shared_class_table_(isolate->shared_class_table()) {}
} // namespace dart
+7 -2
View File
@@ -6,6 +6,7 @@
#define RUNTIME_VM_VISITOR_H_
#include "vm/allocation.h"
#include "vm/class_table.h"
#include "vm/globals.h"
#include "vm/growable_array.h"
@@ -20,8 +21,7 @@ class RawTypedDataView;
// An object pointer visitor interface.
class ObjectPointerVisitor {
public:
explicit ObjectPointerVisitor(Isolate* isolate)
: isolate_(isolate), gc_root_type_("unknown") {}
explicit ObjectPointerVisitor(Isolate* isolate);
virtual ~ObjectPointerVisitor() {}
Isolate* isolate() const { return isolate_; }
@@ -54,9 +54,14 @@ class ObjectPointerVisitor {
virtual bool visit_weak_persistent_handles() const { return false; }
const SharedClassTable* shared_class_table() const {
return shared_class_table_;
}
private:
Isolate* isolate_;
const char* gc_root_type_;
SharedClassTable* shared_class_table_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectPointerVisitor);
};
+1
View File
@@ -357,6 +357,7 @@ vm_sources = [
"virtual_memory_fuchsia.cc",
"virtual_memory_posix.cc",
"virtual_memory_win.cc",
"visitor.cc",
"visitor.h",
"zone.cc",
"zone.h",
@@ -0,0 +1,34 @@
// 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.
import 'dart:async';
import 'dart:isolate';
import 'dart:typed_data';
import 'package:expect/expect.dart';
double getDoubleWithHeapObjectTag() {
final bd = ByteData(8);
bd.setUint64(0, 0x8000000000000001, Endian.host);
final double v = bd.getFloat64(0, Endian.host);
return v;
}
class Foo {
final double x = getDoubleWithHeapObjectTag();
final String name = "Foo Class";
Foo();
}
main(args) async {
final receivePort = new ReceivePort();
receivePort.sendPort.send(Foo());
final it = StreamIterator(receivePort);
Expect.isTrue(await it.moveNext());
final Foo receivedFoo = it.current as Foo;
Expect.equals(receivedFoo.x, getDoubleWithHeapObjectTag());
Expect.equals(receivedFoo.name, "Foo Class");
await it.cancel();
}