Skip to content

Commit

Permalink
[VM] Introduction of type testing stubs - Part 1
Browse files Browse the repository at this point in the history
This CL:

  * Adds a field to [RawAbstractType] which will always hold a pointer
    to the entrypoint of a type testing stub

  * Makes this new field be initialized to a default stub whenever a
    instances are created (e.g. via Type::New(), snapshot reader, ...)

  * Makes the clustered snapshotter write a reference to the
    corresponding [RawInstructions] object when writing the field and do
    the reverse when reading it.

  * Makes us call the type testing stub for performing assert-assignable
    checks.

To reduce unnecessary loads on callsites, we store the entrypoint of the
type testing stubs directly in the type objects.  This means that the
caller of type testing stubs can simply branch there without populating
a code object first.  This also means that the type testing stubs
themselves have no access to a pool and we therefore also don't hold on
to the [Code] object, only the [Instruction] object is necessary.

The type testing stubs do not setup a frame themselves and also have no
safepoint.  In the case when the type testing stubs could not determine
a positive answer they will tail-call a general-purpose stub.

The general-purpose stub sets up a stub frame, tries to consult a
[SubtypeTestCache] and bails out to runtime if this was unsuccessful.

This CL is just the the first, for ease of reviewing.  The actual
type-specialized type testing stubs will be generated in later CLs.

Issue #31798

Change-Id: I174a11b3b812799f399a60af799144c2ba3c26ec
Reviewed-on: https://dart-review.googlesource.com/44787
Reviewed-by: Vyacheslav Egorov <[email protected]>
Reviewed-by: Régis Crelier <[email protected]>
  • Loading branch information
mkustermann authored and [email protected] committed Apr 6, 2018
1 parent 52896af commit 165c583
Show file tree
Hide file tree
Showing 32 changed files with 1,259 additions and 165 deletions.
5 changes: 5 additions & 0 deletions runtime/vm/class_finalizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "vm/symbols.h"
#include "vm/timeline.h"
#include "vm/type_table.h"
#include "vm/type_testing_stubs.h"

namespace dart {

Expand Down Expand Up @@ -589,6 +590,10 @@ void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
}
}
}

// After resolving, we re-initialize the type testing stub.
type.SetTypeTestingStub(
Instructions::Handle(TypeTestingStubGenerator::DefaultCodeForType(type)));
}

void ClassFinalizer::FinalizeTypeParameters(const Class& cls,
Expand Down
155 changes: 138 additions & 17 deletions runtime/vm/clustered_snapshot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3014,7 +3014,8 @@ class LibraryPrefixDeserializationCluster : public DeserializationCluster {
#if !defined(DART_PRECOMPILED_RUNTIME)
class TypeSerializationCluster : public SerializationCluster {
public:
TypeSerializationCluster() : SerializationCluster("Type") {}
explicit TypeSerializationCluster(const TypeTestingStubFinder& ttsf)
: SerializationCluster("Type"), type_testing_stubs_(ttsf) {}
virtual ~TypeSerializationCluster() {}

void Trace(Serializer* s, RawObject* object) {
Expand Down Expand Up @@ -3069,6 +3070,12 @@ class TypeSerializationCluster : public SerializationCluster {
}
s->WriteTokenPosition(type->ptr()->token_pos_);
s->Write<int8_t>(type->ptr()->type_state_);
if (s->kind() == Snapshot::kFullAOT) {
RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
type->ptr()->type_test_stub_entry_point_);
const int32_t text_offset = s->GetTextOffset(instr, Code::null());
s->Write<int32_t>(text_offset);
}
}
count = objects_.length();
for (intptr_t i = 0; i < count; i++) {
Expand All @@ -3080,18 +3087,35 @@ class TypeSerializationCluster : public SerializationCluster {
}
s->WriteTokenPosition(type->ptr()->token_pos_);
s->Write<int8_t>(type->ptr()->type_state_);
if (s->kind() == Snapshot::kFullAOT) {
RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
type->ptr()->type_test_stub_entry_point_);
const int32_t text_offset = s->GetTextOffset(instr, Code::null());
s->Write<int32_t>(text_offset);
}
}

// The [Type::dynamic_type()] object is not serialized, so we manually send
// the type testing stub for it.
if (s->kind() == Snapshot::kFullAOT && s->for_vm_isolate()) {
RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
Type::dynamic_type().type_test_stub_entry_point());
const int32_t text_offset = s->GetTextOffset(instr, Code::null());
s->Write<int32_t>(text_offset);
}
}

private:
GrowableArray<RawType*> canonical_objects_;
GrowableArray<RawType*> objects_;
const TypeTestingStubFinder& type_testing_stubs_;
};
#endif // !DART_PRECOMPILED_RUNTIME

class TypeDeserializationCluster : public DeserializationCluster {
public:
TypeDeserializationCluster() {}
TypeDeserializationCluster()
: type_(AbstractType::Handle()), instr_(Instructions::Handle()) {}
virtual ~TypeDeserializationCluster() {}

void ReadAlloc(Deserializer* d) {
Expand Down Expand Up @@ -3126,6 +3150,12 @@ class TypeDeserializationCluster : public DeserializationCluster {
}
type->ptr()->token_pos_ = d->ReadTokenPosition();
type->ptr()->type_state_ = d->Read<int8_t>();
if (d->kind() == Snapshot::kFullAOT) {
const int32_t text_offset = d->Read<int32_t>();
instr_ = d->GetInstructionsAt(text_offset);
type_ = type;
type_.SetTypeTestingStub(instr_);
}
}

for (intptr_t id = start_index_; id < stop_index_; id++) {
Expand All @@ -3139,18 +3169,53 @@ class TypeDeserializationCluster : public DeserializationCluster {
}
type->ptr()->token_pos_ = d->ReadTokenPosition();
type->ptr()->type_state_ = d->Read<int8_t>();
if (d->kind() == Snapshot::kFullAOT) {
const int32_t text_offset = d->Read<int32_t>();
instr_ = d->GetInstructionsAt(text_offset);
type_ = type;
type_.SetTypeTestingStub(instr_);
}
}

// The [Type::dynamic_type()] object is not serialized, so we manually send
// the type testing stub for it.
if (d->kind() == Snapshot::kFullAOT && d->for_vm_isolate()) {
const int32_t text_offset = d->Read<int32_t>();
Dart::vm_isolate()->heap()->WriteProtect(false);
instr_ = d->GetInstructionsAt(text_offset);
Type::dynamic_type().SetTypeTestingStub(instr_);
Dart::vm_isolate()->heap()->WriteProtect(true);
}
}

void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
if (kind != Snapshot::kFullAOT) {
for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
id++) {
type_ ^= refs.At(id);
instr_ = TypeTestingStubGenerator::DefaultCodeForType(type_);
type_.SetTypeTestingStub(instr_);
}
for (intptr_t id = start_index_; id < stop_index_; id++) {
type_ ^= refs.At(id);
instr_ = TypeTestingStubGenerator::DefaultCodeForType(type_);
type_.SetTypeTestingStub(instr_);
}
}
}

private:
intptr_t canonical_start_index_;
intptr_t canonical_stop_index_;
AbstractType& type_;
Instructions& instr_;
};

#if !defined(DART_PRECOMPILED_RUNTIME)
class TypeRefSerializationCluster : public SerializationCluster {
public:
TypeRefSerializationCluster() : SerializationCluster("TypeRef") {}
explicit TypeRefSerializationCluster(const TypeTestingStubFinder& ttsf)
: SerializationCluster("TypeRef"), type_testing_stubs_(ttsf) {}
virtual ~TypeRefSerializationCluster() {}

void Trace(Serializer* s, RawObject* object) {
Expand Down Expand Up @@ -3183,17 +3248,25 @@ class TypeRefSerializationCluster : public SerializationCluster {
for (RawObject** p = from; p <= to; p++) {
s->WriteRef(*p);
}
if (s->kind() == Snapshot::kFullAOT) {
RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
type->ptr()->type_test_stub_entry_point_);
const int32_t text_offset = s->GetTextOffset(instr, Code::null());
s->Write<int32_t>(text_offset);
}
}
}

private:
GrowableArray<RawTypeRef*> objects_;
const TypeTestingStubFinder& type_testing_stubs_;
};
#endif // !DART_PRECOMPILED_RUNTIME

class TypeRefDeserializationCluster : public DeserializationCluster {
public:
TypeRefDeserializationCluster() {}
TypeRefDeserializationCluster()
: type_(AbstractType::Handle()), instr_(Instructions::Handle()) {}
virtual ~TypeRefDeserializationCluster() {}

void ReadAlloc(Deserializer* d) {
Expand All @@ -3218,14 +3291,26 @@ class TypeRefDeserializationCluster : public DeserializationCluster {
for (RawObject** p = from; p <= to; p++) {
*p = d->ReadRef();
}
if (d->kind() == Snapshot::kFullAOT) {
const int32_t text_offset = d->Read<int32_t>();
instr_ = d->GetInstructionsAt(text_offset);
type_ = type;
type_.SetTypeTestingStub(instr_);
}
}
}

private:
AbstractType& type_;
Instructions& instr_;
};

#if !defined(DART_PRECOMPILED_RUNTIME)
class TypeParameterSerializationCluster : public SerializationCluster {
public:
TypeParameterSerializationCluster() : SerializationCluster("TypeParameter") {}
explicit TypeParameterSerializationCluster(const TypeTestingStubFinder& ttsf)
: SerializationCluster("TypeParameter"), type_testing_stubs_(ttsf) {}

virtual ~TypeParameterSerializationCluster() {}

void Trace(Serializer* s, RawObject* object) {
Expand Down Expand Up @@ -3263,17 +3348,25 @@ class TypeParameterSerializationCluster : public SerializationCluster {
s->WriteTokenPosition(type->ptr()->token_pos_);
s->Write<int16_t>(type->ptr()->index_);
s->Write<int8_t>(type->ptr()->type_state_);
if (s->kind() == Snapshot::kFullAOT) {
RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
type->ptr()->type_test_stub_entry_point_);
const int32_t text_offset = s->GetTextOffset(instr, Code::null());
s->Write<int32_t>(text_offset);
}
}
}

private:
GrowableArray<RawTypeParameter*> objects_;
const TypeTestingStubFinder& type_testing_stubs_;
};
#endif // !DART_PRECOMPILED_RUNTIME

class TypeParameterDeserializationCluster : public DeserializationCluster {
public:
TypeParameterDeserializationCluster() {}
TypeParameterDeserializationCluster()
: type_(AbstractType::Handle()), instr_(Instructions::Handle()) {}
virtual ~TypeParameterDeserializationCluster() {}

void ReadAlloc(Deserializer* d) {
Expand Down Expand Up @@ -3303,8 +3396,28 @@ class TypeParameterDeserializationCluster : public DeserializationCluster {
type->ptr()->token_pos_ = d->ReadTokenPosition();
type->ptr()->index_ = d->Read<int16_t>();
type->ptr()->type_state_ = d->Read<int8_t>();
if (d->kind() == Snapshot::kFullAOT) {
const int32_t text_offset = d->Read<int32_t>();
instr_ = d->GetInstructionsAt(text_offset);
type_ = type;
type_.SetTypeTestingStub(instr_);
}
}
}

void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
if (kind != Snapshot::kFullAOT) {
for (intptr_t id = start_index_; id < stop_index_; id++) {
type_ ^= refs.At(id);
instr_ = TypeTestingStubGenerator::DefaultCodeForType(type_);
type_.SetTypeTestingStub(instr_);
}
}
}

private:
AbstractType& type_;
Instructions& instr_;
};

#if !defined(DART_PRECOMPILED_RUNTIME)
Expand Down Expand Up @@ -4556,7 +4669,8 @@ Serializer::Serializer(Thread* thread,
uint8_t** buffer,
ReAlloc alloc,
intptr_t initial_size,
ImageWriter* image_writer)
ImageWriter* image_writer,
bool vm_isolate)
: StackResource(thread),
heap_(thread->isolate()->heap()),
zone_(thread->zone()),
Expand All @@ -4568,7 +4682,8 @@ Serializer::Serializer(Thread* thread,
num_cids_(0),
num_base_objects_(0),
num_written_objects_(0),
next_ref_index_(1)
next_ref_index_(1),
vm_isolate_(vm_isolate)
#if defined(SNAPSHOT_BACKTRACE)
,
current_parent_(Object::null()),
Expand Down Expand Up @@ -4668,11 +4783,11 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
case kLibraryPrefixCid:
return new (Z) LibraryPrefixSerializationCluster();
case kTypeCid:
return new (Z) TypeSerializationCluster();
return new (Z) TypeSerializationCluster(type_testing_stubs_);
case kTypeRefCid:
return new (Z) TypeRefSerializationCluster();
return new (Z) TypeRefSerializationCluster(type_testing_stubs_);
case kTypeParameterCid:
return new (Z) TypeParameterSerializationCluster();
return new (Z) TypeParameterSerializationCluster(type_testing_stubs_);
case kBoundedTypeCid:
return new (Z) BoundedTypeSerializationCluster();
case kClosureCid:
Expand Down Expand Up @@ -5120,7 +5235,8 @@ Deserializer::Deserializer(Thread* thread,
const uint8_t* buffer,
intptr_t size,
const uint8_t* instructions_buffer,
const uint8_t* data_buffer)
const uint8_t* data_buffer,
bool vm_isolate)
: StackResource(thread),
heap_(thread->isolate()->heap()),
zone_(thread->zone()),
Expand All @@ -5129,7 +5245,8 @@ Deserializer::Deserializer(Thread* thread,
image_reader_(NULL),
refs_(NULL),
next_ref_index_(1),
clusters_(NULL) {
clusters_(NULL),
vm_isolate_(vm_isolate) {
if (Snapshot::IncludesCode(kind)) {
ASSERT(instructions_buffer != NULL);
ASSERT(data_buffer != NULL);
Expand Down Expand Up @@ -5716,7 +5833,8 @@ intptr_t FullSnapshotWriter::WriteVMSnapshot() {

ASSERT(vm_snapshot_data_buffer_ != NULL);
Serializer serializer(thread(), kind_, vm_snapshot_data_buffer_, alloc_,
kInitialSize, vm_image_writer_);
kInitialSize, vm_image_writer_,
/*vm_isolate=*/true);

serializer.ReserveHeader();
serializer.WriteVersionAndFeatures(true);
Expand Down Expand Up @@ -5746,7 +5864,8 @@ void FullSnapshotWriter::WriteIsolateSnapshot(intptr_t num_base_objects) {
thread(), Timeline::GetIsolateStream(), "WriteIsolateSnapshot"));

Serializer serializer(thread(), kind_, isolate_snapshot_data_buffer_, alloc_,
kInitialSize, isolate_image_writer_);
kInitialSize, isolate_image_writer_,
/*vm_isolate=*/false);
ObjectStore* object_store = isolate()->object_store();
ASSERT(object_store != NULL);

Expand Down Expand Up @@ -5816,7 +5935,8 @@ FullSnapshotReader::FullSnapshotReader(const Snapshot* snapshot,

RawApiError* FullSnapshotReader::ReadVMSnapshot() {
Deserializer deserializer(thread_, kind_, buffer_, size_,
instructions_buffer_, data_buffer_);
instructions_buffer_, data_buffer_,
/*vm_isolate=*/true);

RawApiError* error = deserializer.VerifyVersionAndFeatures(/*isolate=*/NULL);
if (error != ApiError::null()) {
Expand All @@ -5840,7 +5960,8 @@ RawApiError* FullSnapshotReader::ReadVMSnapshot() {

RawApiError* FullSnapshotReader::ReadIsolateSnapshot() {
Deserializer deserializer(thread_, kind_, buffer_, size_,
instructions_buffer_, data_buffer_);
instructions_buffer_, data_buffer_,
/*vm_isolate=*/false);

RawApiError* error =
deserializer.VerifyVersionAndFeatures(thread_->isolate());
Expand Down
Loading

0 comments on commit 165c583

Please sign in to comment.