[vm] Improve Code cluster layout for startup

This change bakes binary search table which maps PC ranges
to corresponding stack maps and Code objects (if still present
in the snapshot) into RO data section of the snapshot - instead
of constructing it at load time.

This allows to considerably reduce amount of work done when
loading Code cluster for programs which have majority of their
Code objects discarded (i.e. in DWARF stack traces mode): as
we no longer write / read any information for discarded Code
objects.

This CL also changes program visitor to deduplicate Code objects
if their instructions are deduplicated in AOT mode. Only a single
Code object can be choose as a representative for the given
PC range so it does not make sense to write multiple Code objects
into the snapshot which refer to the same Instructions.

The overall improvement is hard to quantify but ReadProgramSnapshot
shows the following improvement when starting a large
Flutter application on a slow Android device:

  before  223.55±59.94 (192.02 .. 391.74) ms
  after   178.06±47.03 (151.31 .. 291.34) ms

This CL packs CompressedStackMaps next to the binary search table
itself allowing us to address them via offsets instead of
pointers.

Snapshot sizes are actually affected positively by this change. On
the same large Flutter application I see

  DWARF stack traces on:  -1.34% total SO size
  DWARF stack traces off: -1.63% total SO size

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

TEST=ci

Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-dwarf-linux-product-x64-try,vm-kernel-precomp-linux-debug-simarm64c-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-linux-release-x64-try
Change-Id: Ic997045a33daa81ec68df462a0792915885df66b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/220766
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
This commit is contained in:
Vyacheslav Egorov 2021-12-16 10:39:49 +00:00 committed by Commit Bot
parent 7701bfb3e9
commit 13d27d669d
20 changed files with 1397 additions and 761 deletions

View file

@ -131,7 +131,7 @@ Stream<Future> asyncStarThrowAsync() async* {
Future listenAsyncStarThrowAsync() async {
// Listening to an async* doesn't create the usual await-for StreamIterator.
StreamSubscription ss = asyncStarThrowAsync().listen((Future f) {});
StreamSubscription ss = asyncStarThrowAsync().listen((Future f) => 42);
await ss.asFuture();
}

File diff suppressed because it is too large Load diff

View file

@ -176,6 +176,8 @@ class SerializationRoots {
virtual void AddBaseObjects(Serializer* serializer) = 0;
virtual void PushRoots(Serializer* serializer) = 0;
virtual void WriteRoots(Serializer* serializer) = 0;
virtual const CompressedStackMaps& canonicalized_stack_map_entries() const;
};
class DeserializationRoots {
@ -228,9 +230,12 @@ class Serializer : public ThreadStackResource {
void AddBaseObject(ObjectPtr base_object,
const char* type = nullptr,
const char* name = nullptr);
intptr_t AssignRef(ObjectPtr object);
intptr_t AssignArtificialRef(ObjectPtr object = nullptr);
intptr_t GetCodeIndex(CodePtr code);
void Push(ObjectPtr object);
void AddUntracedRef() { num_written_objects_++; }
@ -418,8 +423,8 @@ class Serializer : public ThreadStackResource {
}
// Sorts Code objects and reorders instructions before writing snapshot.
// Returns length of instructions table (in bare instructions mode).
intptr_t PrepareInstructions();
// Builds binary search table for stack maps.
void PrepareInstructions(const CompressedStackMaps& canonical_smap);
void WriteInstructions(InstructionsPtr instr,
uint32_t unchecked_offset,
@ -508,12 +513,12 @@ class Serializer : public ThreadStackResource {
intptr_t num_base_objects_;
intptr_t num_written_objects_;
intptr_t next_ref_index_;
intptr_t previous_text_offset_;
FieldTable* initial_field_table_;
intptr_t dispatch_table_size_ = 0;
intptr_t bytes_heap_allocated_ = 0;
intptr_t instructions_table_len_ = 0;
intptr_t instructions_table_rodata_offset_ = 0;
// True if writing VM snapshot, false for Isolate snapshot.
bool vm_;
@ -537,6 +542,7 @@ class Serializer : public ThreadStackResource {
#if defined(DART_PRECOMPILER)
IntMap<intptr_t> deduped_instructions_sources_;
IntMap<intptr_t> code_index_;
#endif
intptr_t current_loading_unit_id_ = 0;
@ -657,6 +663,16 @@ class Deserializer : public ThreadStackResource {
return refs_->untag()->element(index);
}
CodePtr GetCodeByIndex(intptr_t code_index, uword* entry_point) const;
uword GetEntryPointByCodeIndex(intptr_t code_index) const;
// If |code_index| corresponds to a non-discarded Code object returns
// index within the code cluster that corresponds to this Code object.
// Otherwise, if |code_index| corresponds to the discarded Code then
// returns -1.
static intptr_t CodeIndexToClusterIndex(const InstructionsTable& table,
intptr_t code_index);
ObjectPtr ReadRef() { return Ref(ReadUnsigned()); }
template <typename T, typename... P>
@ -685,7 +701,7 @@ class Deserializer : public ThreadStackResource {
return Read<int32_t>();
}
void ReadInstructions(CodePtr code, bool deferred, bool discarded);
void ReadInstructions(CodePtr code, bool deferred);
void EndInstructions();
ObjectPtr GetObjectAt(uint32_t offset) const;
@ -694,10 +710,12 @@ class Deserializer : public ThreadStackResource {
DeserializationCluster* ReadCluster();
void ReadDispatchTable() {
ReadDispatchTable(&stream_, /*deferred=*/false, -1, -1);
ReadDispatchTable(&stream_, /*deferred=*/false, InstructionsTable::Handle(),
-1, -1);
}
void ReadDispatchTable(ReadStream* stream,
bool deferred,
const InstructionsTable& root_instruction_table,
intptr_t deferred_code_start_index,
intptr_t deferred_code_end_index);
@ -708,10 +726,13 @@ class Deserializer : public ThreadStackResource {
FieldTable* initial_field_table() const { return initial_field_table_; }
bool is_non_root_unit() const { return is_non_root_unit_; }
void set_code_start_index(intptr_t value) { code_start_index_ = value; }
intptr_t code_start_index() { return code_start_index_; }
intptr_t code_start_index() const { return code_start_index_; }
void set_code_stop_index(intptr_t value) { code_stop_index_ = value; }
intptr_t code_stop_index() const { return code_stop_index_; }
const InstructionsTable& instructions_table() const {
return instructions_table_;
}
intptr_t num_base_objects() const { return num_base_objects_; }
private:
Heap* heap_;
@ -724,8 +745,8 @@ class Deserializer : public ThreadStackResource {
intptr_t num_clusters_;
ArrayPtr refs_;
intptr_t next_ref_index_;
intptr_t previous_text_offset_;
intptr_t code_start_index_ = 0;
intptr_t code_stop_index_ = 0;
intptr_t instructions_index_ = 0;
DeserializationCluster** clusters_;
FieldTable* initial_field_table_;

View file

@ -53,7 +53,7 @@ ISOLATE_UNIT_TEST_CASE(BitmapBuilder) {
// Create a CompressedStackMaps object and verify its contents.
const auto& maps1 = CompressedStackMaps::Handle(
thread->zone(), MapsFromBuilder(thread->zone(), builder1));
CompressedStackMaps::Iterator it1(thread, maps1);
auto it1 = maps1.iterator(thread);
EXPECT(it1.MoveNext());
EXPECT_EQ(kTestPcOffset, it1.pc_offset());
@ -86,7 +86,7 @@ ISOLATE_UNIT_TEST_CASE(BitmapBuilder) {
const auto& maps2 = CompressedStackMaps::Handle(
thread->zone(), MapsFromBuilder(thread->zone(), builder1));
CompressedStackMaps::Iterator it2(thread, maps2);
auto it2 = maps2.iterator(thread);
EXPECT(it2.MoveNext());
EXPECT_EQ(kTestPcOffset, it2.pc_offset());

View file

@ -296,10 +296,9 @@ void Disassembler::DisassembleCodeHelper(const char* function_fullname,
{
const auto& stackmaps =
CompressedStackMaps::Handle(zone, code.compressed_stackmaps());
CompressedStackMaps::Iterator it(thread, stackmaps);
TextBuffer buffer(100);
buffer.Printf("StackMaps for function '%s' {\n", function_fullname);
it.WriteToBuffer(&buffer, "\n");
stackmaps.WriteToBuffer(&buffer, "\n");
buffer.AddString("}\n");
THR_Print("%s", buffer.buffer());
}

View file

@ -891,10 +891,14 @@ class CodeSourceMap : public AllStatic {
class CompressedStackMaps : public AllStatic {
public:
static word HeaderSize();
static word HeaderSize() { return ObjectHeaderSize() + PayloadHeaderSize(); }
static word InstanceSize();
static word InstanceSize(word payload_size);
FINAL_CLASS();
private:
static word ObjectHeaderSize();
static word PayloadHeaderSize();
};
class LocalVarDescriptors : public AllStatic {

View file

@ -39,10 +39,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 12;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 20;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
8;
static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
@ -499,8 +495,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 112;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
8;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 4;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 12;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 8;
@ -526,6 +524,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
8;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 20;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
24;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -599,10 +599,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 24;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
16;
static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
@ -1070,8 +1066,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 192;
static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
16;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 24;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
@ -1097,6 +1095,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
16;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
48;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -1171,10 +1171,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 12;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 20;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
8;
static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
@ -1628,8 +1624,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 112;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
8;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 4;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 12;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 8;
@ -1655,6 +1653,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
8;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 20;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
24;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -1728,10 +1728,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 24;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
16;
static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
@ -2200,8 +2196,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 192;
static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
16;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 24;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
@ -2227,6 +2225,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
16;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
48;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -2301,10 +2301,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 16;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
16;
static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
@ -2769,8 +2765,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 120;
static constexpr dart::compiler::target::word Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
16;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 16;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
@ -2796,6 +2794,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
16;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
48;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -2870,10 +2870,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 16;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
16;
static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
@ -3339,8 +3335,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 120;
static constexpr dart::compiler::target::word Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
16;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 16;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
@ -3366,6 +3364,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
16;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
48;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -3439,10 +3439,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 12;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 20;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
8;
static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
@ -3896,8 +3892,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 108;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
8;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 4;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 12;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 8;
@ -3923,6 +3921,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
8;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 20;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
24;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -3993,10 +3993,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 24;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
16;
static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
@ -4461,8 +4457,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 184;
static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
16;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 24;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
@ -4488,6 +4486,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
16;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
48;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -4559,10 +4559,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 12;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 20;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
8;
static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
@ -5013,8 +5009,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 108;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
8;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 4;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 12;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 8;
@ -5040,6 +5038,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
8;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 20;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
24;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -5110,10 +5110,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 24;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
16;
static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
@ -5579,8 +5575,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 184;
static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
16;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 24;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
@ -5606,6 +5604,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
16;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
48;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -5677,10 +5677,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 16;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
16;
static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
@ -6142,8 +6138,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 112;
static constexpr dart::compiler::target::word Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
16;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 16;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
@ -6169,6 +6167,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
16;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
48;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -6240,10 +6240,6 @@ static constexpr dart::compiler::target::word
ExceptionHandlers_elements_start_offset = 16;
static constexpr dart::compiler::target::word ExceptionHandlers_element_size =
12;
static constexpr dart::compiler::target::word
InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word InstructionsTable_element_size =
4;
static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
16;
static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
@ -6706,8 +6702,10 @@ static constexpr dart::compiler::target::word Class_InstanceSize = 112;
static constexpr dart::compiler::target::word Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
16;
static constexpr dart::compiler::target::word
CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word Context_header_size = 16;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
static constexpr dart::compiler::target::word DynamicLibrary_InstanceSize = 16;
@ -6733,6 +6731,8 @@ static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
16;
static constexpr dart::compiler::target::word
InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word InstructionsTable_InstanceSize =
48;
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@ -6812,10 +6812,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 12;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 20;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 8;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 4;
@ -7327,7 +7323,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 8;
AOT_CompressedStackMaps_ObjectHeaderSize = 4;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 12;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -7355,6 +7353,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 20;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
static constexpr dart::compiler::target::word
@ -7441,10 +7441,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 24;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 16;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
@ -7960,7 +7956,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 16;
AOT_CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 24;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -7988,6 +7986,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word
@ -8077,10 +8077,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 24;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 16;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
@ -8597,7 +8593,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 16;
AOT_CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 24;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -8625,6 +8623,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word
@ -8711,10 +8711,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 16;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 16;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
@ -9229,7 +9225,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 16;
AOT_CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 16;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -9257,6 +9255,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word
@ -9343,10 +9343,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 16;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 16;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
@ -9862,7 +9858,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 16;
AOT_CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 16;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -9890,6 +9888,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word
@ -9975,10 +9975,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 12;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 20;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 8;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 4;
@ -10486,7 +10482,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 8;
AOT_CompressedStackMaps_ObjectHeaderSize = 4;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 12;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -10514,6 +10512,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 20;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
static constexpr dart::compiler::target::word
@ -10597,10 +10597,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 24;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 16;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
@ -11112,7 +11108,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 16;
AOT_CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 24;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -11140,6 +11138,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word
@ -11226,10 +11226,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 24;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 16;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
@ -11742,7 +11738,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 64;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 16;
AOT_CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 24;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -11770,6 +11768,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word
@ -11853,10 +11853,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 16;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 16;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
@ -12367,7 +12363,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 16;
AOT_CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 16;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -12395,6 +12393,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word
@ -12478,10 +12478,6 @@ static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_elements_start_offset = 16;
static constexpr dart::compiler::target::word
AOT_ExceptionHandlers_element_size = 12;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_elements_start_offset = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_element_size = 4;
static constexpr dart::compiler::target::word
AOT_ObjectPool_elements_start_offset = 16;
static constexpr dart::compiler::target::word AOT_ObjectPool_element_size = 8;
@ -12993,7 +12989,9 @@ static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_HeaderSize = 16;
AOT_CompressedStackMaps_ObjectHeaderSize = 8;
static constexpr dart::compiler::target::word
AOT_CompressedStackMaps_PayloadHeaderSize = 4;
static constexpr dart::compiler::target::word AOT_Context_header_size = 16;
static constexpr dart::compiler::target::word AOT_Double_InstanceSize = 16;
static constexpr dart::compiler::target::word AOT_DynamicLibrary_InstanceSize =
@ -13021,6 +13019,8 @@ static constexpr dart::compiler::target::word
AOT_Instructions_UnalignedHeaderSize = 16;
static constexpr dart::compiler::target::word
AOT_InstructionsSection_UnalignedHeaderSize = 40;
static constexpr dart::compiler::target::word
AOT_InstructionsTable_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
static constexpr dart::compiler::target::word

View file

@ -51,7 +51,6 @@
ARRAY(Context, variable_offset) \
ARRAY(ContextScope, element_offset) \
ARRAY(ExceptionHandlers, element_offset) \
ARRAY(InstructionsTable, element_offset) \
ARRAY(ObjectPool, element_offset) \
ARRAY(OneByteString, element_offset) \
ARRAY(TypeArguments, type_at_offset) \
@ -61,7 +60,6 @@
ARRAY_SIZEOF(Context, InstanceSize, variable_offset) \
ARRAY_SIZEOF(ContextScope, InstanceSize, element_offset) \
ARRAY_SIZEOF(ExceptionHandlers, InstanceSize, element_offset) \
ARRAY_SIZEOF(InstructionsTable, InstanceSize, element_offset) \
ARRAY_SIZEOF(ObjectPool, InstanceSize, element_offset) \
ARRAY_SIZEOF(OneByteString, InstanceSize, element_offset) \
ARRAY_SIZEOF(TypeArguments, InstanceSize, type_at_offset) \
@ -350,7 +348,9 @@
SIZEOF(Closure, InstanceSize, UntaggedClosure) \
SIZEOF(ClosureData, InstanceSize, UntaggedClosureData) \
SIZEOF(CodeSourceMap, HeaderSize, UntaggedCodeSourceMap) \
SIZEOF(CompressedStackMaps, HeaderSize, UntaggedCompressedStackMaps) \
SIZEOF(CompressedStackMaps, ObjectHeaderSize, UntaggedCompressedStackMaps) \
SIZEOF(CompressedStackMaps, PayloadHeaderSize, \
UntaggedCompressedStackMaps::Payload) \
SIZEOF(Context, header_size, UntaggedContext) \
SIZEOF(Double, InstanceSize, UntaggedDouble) \
SIZEOF(DynamicLibrary, InstanceSize, UntaggedDynamicLibrary) \
@ -370,6 +370,7 @@
SIZEOF(Instructions, UnalignedHeaderSize, UntaggedInstructions) \
SIZEOF(InstructionsSection, UnalignedHeaderSize, \
UntaggedInstructionsSection) \
SIZEOF(InstructionsTable, InstanceSize, UntaggedInstructionsTable) \
SIZEOF(Int32x4, InstanceSize, UntaggedInt32x4) \
SIZEOF(Integer, InstanceSize, UntaggedInteger) \
SIZEOF(KernelProgramInfo, InstanceSize, UntaggedKernelProgramInfo) \

View file

@ -237,6 +237,12 @@ int32_t ImageWriter::GetTextOffsetFor(InstructionsPtr instructions,
return offset;
}
intptr_t ImageWriter::SizeInSnapshotForBytes(intptr_t length) {
// We are just going to write it out as a string.
return compiler::target::String::InstanceSize(
length * OneByteString::kBytesPerElement);
}
intptr_t ImageWriter::SizeInSnapshot(ObjectPtr raw_object) {
const classid_t cid = raw_object->GetClassId();
@ -280,13 +286,21 @@ intptr_t ImageWriter::SizeInSnapshot(ObjectPtr raw_object) {
}
uint32_t ImageWriter::GetDataOffsetFor(ObjectPtr raw_object) {
intptr_t snap_size = SizeInSnapshot(raw_object);
intptr_t offset = next_data_offset_;
const intptr_t snap_size = SizeInSnapshot(raw_object);
const intptr_t offset = next_data_offset_;
next_data_offset_ += snap_size;
objects_.Add(ObjectData(raw_object));
return offset;
}
uint32_t ImageWriter::AddBytesToData(uint8_t* bytes, intptr_t length) {
const intptr_t snap_size = SizeInSnapshotForBytes(length);
const intptr_t offset = next_data_offset_;
next_data_offset_ += snap_size;
objects_.Add(ObjectData(bytes, length));
return offset;
}
intptr_t ImageWriter::GetTextObjectCount() const {
return instructions_.length();
}
@ -439,9 +453,24 @@ void ImageWriter::Write(NonStreamingWriteStream* clustered_stream, bool vm) {
// the VM snapshot's text image.
heap->SetObjectId(data.insns_->ptr(), 0);
}
for (intptr_t i = 0; i < objects_.length(); i++) {
ObjectData& data = objects_[i];
data.obj_ = &Object::Handle(zone_, data.raw_obj_);
for (auto& data : objects_) {
if (data.is_object) {
data.obj = &Object::Handle(zone_, data.raw_obj);
}
}
// Once we have everything handlified we are going to do convert raw bytes
// to string objects. String is used for simplicity as a bit container,
// can't use TypedData because it has an internal pointer (data_) field.
for (auto& data : objects_) {
if (!data.is_object) {
const auto bytes = data.bytes;
data.obj = &Object::Handle(
zone_, OneByteString::New(bytes.buf, bytes.length, Heap::kOld));
data.is_object = true;
String::Cast(*data.obj).Hash();
free(bytes.buf);
}
}
// Needs to happen before WriteText, as we add information about the
@ -484,8 +513,9 @@ void ImageWriter::WriteROData(NonStreamingWriteStream* stream, bool vm) {
// Heap page objects start here.
for (intptr_t i = 0; i < objects_.length(); i++) {
const Object& obj = *objects_[i].obj_;
for (auto entry : objects_) {
ASSERT(entry.is_object);
const Object& obj = *entry.obj;
#if defined(DART_PRECOMPILER)
AutoTraceImage(obj, section_start, stream);
#endif
@ -498,10 +528,9 @@ void ImageWriter::WriteROData(NonStreamingWriteStream* stream, bool vm) {
if (obj.IsCompressedStackMaps()) {
const CompressedStackMaps& map = CompressedStackMaps::Cast(obj);
const intptr_t payload_size = map.payload_size();
stream->WriteTargetWord(map.ptr()->untag()->flags_and_size_);
ASSERT_EQUAL(stream->Position() - object_start,
compiler::target::CompressedStackMaps::HeaderSize());
stream->WriteBytes(map.ptr()->untag()->data(), payload_size);
stream->WriteFixed<uint32_t>(
map.ptr()->untag()->payload()->flags_and_size);
stream->WriteBytes(map.ptr()->untag()->payload()->data(), payload_size);
} else if (obj.IsCodeSourceMap()) {
const CodeSourceMap& map = CodeSourceMap::Cast(obj);
stream->WriteTargetWord(map.Length());

View file

@ -272,6 +272,8 @@ class ImageWriter : public ValueObject {
int32_t GetTextOffsetFor(InstructionsPtr instructions, CodePtr code);
uint32_t GetDataOffsetFor(ObjectPtr raw_object);
uint32_t AddBytesToData(uint8_t* bytes, intptr_t length);
void Write(NonStreamingWriteStream* clustered_stream, bool vm);
intptr_t data_size() const { return next_data_offset_; }
intptr_t text_size() const { return next_text_offset_; }
@ -354,12 +356,20 @@ class ImageWriter : public ValueObject {
};
struct ObjectData {
explicit ObjectData(ObjectPtr raw_obj) : raw_obj_(raw_obj) {}
explicit ObjectData(ObjectPtr raw_obj)
: raw_obj(raw_obj), is_object(true) {}
ObjectData(uint8_t* buf, intptr_t length)
: bytes({buf, length}), is_object(false) {}
union {
ObjectPtr raw_obj_;
const Object* obj_;
struct {
uint8_t* buf;
intptr_t length;
} bytes;
ObjectPtr raw_obj;
const Object* obj;
};
bool is_object;
};
// Methods abstracting out the particulars of the underlying concrete writer.
@ -447,6 +457,8 @@ class ImageWriter : public ValueObject {
friend class SnapshotTextObjectNamer; // For InstructionsData.
private:
static intptr_t SizeInSnapshotForBytes(intptr_t length);
DISALLOW_COPY_AND_ASSIGN(ImageWriter);
};

View file

@ -1036,7 +1036,7 @@ void Object::Init(IsolateGroup* isolate_group) {
empty_compressed_stackmaps_,
static_cast<CompressedStackMapsPtr>(address + kHeapObjectTag));
empty_compressed_stackmaps_->StoreNonPointer(
&empty_compressed_stackmaps_->untag()->flags_and_size_, 0);
&empty_compressed_stackmaps_->untag()->payload()->flags_and_size, 0);
empty_compressed_stackmaps_->SetCanonical();
}
@ -14569,21 +14569,27 @@ void InstructionsTable::set_end_pc(uword value) const {
StoreNonPointer(&untag()->end_pc_, value);
}
void InstructionsTable::set_descriptors(const Array& value) const {
untag()->set_descriptors(value.ptr());
void InstructionsTable::set_code_objects(const Array& value) const {
untag()->set_code_objects(value.ptr());
}
void InstructionsTable::set_rodata(uword value) const {
StoreNonPointer(
&untag()->rodata_,
reinterpret_cast<const UntaggedInstructionsTable::Data*>(value));
}
InstructionsTablePtr InstructionsTable::New(intptr_t length,
uword start_pc,
uword end_pc) {
uword end_pc,
uword rodata) {
ASSERT(Object::instructions_table_class() != Class::null());
ASSERT(length >= 0);
ASSERT(start_pc <= end_pc);
ASSERT(Utils::IsAligned(start_pc, kPayloadAlignment));
Thread* thread = Thread::Current();
InstructionsTable& result = InstructionsTable::Handle(thread->zone());
{
uword size = InstructionsTable::InstanceSize(length);
uword size = InstructionsTable::InstanceSize();
ObjectPtr raw =
Object::Allocate(InstructionsTable::kClassId, size, Heap::kOld,
InstructionsTable::ContainsCompressedPointers());
@ -14591,31 +14597,20 @@ InstructionsTablePtr InstructionsTable::New(intptr_t length,
result ^= raw;
result.set_length(length);
}
const Array& descriptors =
const Array& code_objects =
(length == 0) ? Object::empty_array()
: Array::Handle(Array::New(length, Heap::kOld));
result.set_descriptors(descriptors);
result.set_code_objects(code_objects);
result.set_start_pc(start_pc);
result.set_end_pc(end_pc);
result.set_rodata(rodata);
return result.ptr();
}
void InstructionsTable::SetEntryAt(intptr_t index,
uword payload_start,
bool has_monomorphic_entrypoint,
ObjectPtr descriptor) const {
ASSERT((0 <= index) && (index < length()));
ASSERT(ContainsPc(payload_start));
ASSERT(Utils::IsAligned(payload_start, kPayloadAlignment));
const uint32_t pc_offset = ConvertPcToOffset(payload_start);
ASSERT((index == 0) || (PcOffsetAt(index - 1) <= pc_offset));
ASSERT((pc_offset & kHasMonomorphicEntrypointFlag) == 0);
untag()->data()[index] =
pc_offset |
(has_monomorphic_entrypoint ? kHasMonomorphicEntrypointFlag : 0);
descriptors()->untag()->set_element(index, descriptor);
void InstructionsTable::SetCodeAt(intptr_t index, CodePtr code) const {
ASSERT((0 <= index) &&
(index < Smi::Value(code_objects()->untag()->length())));
code_objects()->untag()->set_element(index, code);
}
bool InstructionsTable::ContainsPc(InstructionsTablePtr table, uword pc) {
@ -14632,21 +14627,25 @@ uint32_t InstructionsTable::ConvertPcToOffset(InstructionsTablePtr table,
return pc_offset;
}
intptr_t InstructionsTable::FindEntry(InstructionsTablePtr table, uword pc) {
intptr_t InstructionsTable::FindEntry(InstructionsTablePtr table,
uword pc,
intptr_t start_index /* = 0 */) {
// This can run in the middle of GC and must not allocate handles.
NoSafepointScope no_safepoint;
if (!InstructionsTable::ContainsPc(table, pc)) return -1;
const uint32_t pc_offset = InstructionsTable::ConvertPcToOffset(table, pc);
intptr_t lo = 0;
intptr_t hi = InstructionsTable::length(table) - 1;
const auto rodata = table.untag()->rodata_;
const auto entries = rodata->entries();
intptr_t lo = start_index;
intptr_t hi = rodata->length - 1;
while (lo <= hi) {
intptr_t mid = (hi - lo + 1) / 2 + lo;
ASSERT(mid >= lo);
ASSERT(mid <= hi);
if (pc_offset < InstructionsTable::PcOffsetAt(table, mid)) {
if (pc_offset < entries[mid].pc_offset) {
hi = mid - 1;
} else if ((mid != hi) &&
(pc_offset >= InstructionsTable::PcOffsetAt(table, mid + 1))) {
} else if ((mid != hi) && (pc_offset >= entries[mid + 1].pc_offset)) {
lo = mid + 1;
} else {
return mid;
@ -14655,22 +14654,66 @@ intptr_t InstructionsTable::FindEntry(InstructionsTablePtr table, uword pc) {
return -1;
}
ObjectPtr InstructionsTable::DescriptorAt(InstructionsTablePtr table,
intptr_t index) {
ASSERT((0 <= index) && (index < InstructionsTable::length(table)));
return table->untag()->descriptors()->untag()->element(index);
const UntaggedCompressedStackMaps::Payload*
InstructionsTable::GetCanonicalStackMap(InstructionsTablePtr table) {
const auto rodata = table.untag()->rodata_;
return rodata->canonical_stack_map_entries_offset != 0
? rodata->StackMapAt(rodata->canonical_stack_map_entries_offset)
: nullptr;
}
uword InstructionsTable::PayloadStartAt(InstructionsTablePtr table,
intptr_t index) {
return InstructionsTable::start_pc(table) +
InstructionsTable::PcOffsetAt(table, index);
const UntaggedCompressedStackMaps::Payload* InstructionsTable::FindStackMap(
InstructionsTablePtr table,
uword pc,
uword* start_pc) {
// This can run in the middle of GC and must not allocate handles.
NoSafepointScope no_safepoint;
const intptr_t idx = FindEntry(table, pc);
if (idx != -1) {
const auto rodata = table.untag()->rodata_;
const auto entries = rodata->entries();
*start_pc = InstructionsTable::start_pc(table) + entries[idx].pc_offset;
return rodata->StackMapAt(entries[idx].stack_map_offset);
}
return 0;
}
uword InstructionsTable::EntryPointAt(intptr_t index) const {
return PayloadStartAt(index) + (HasMonomorphicEntryPointAt(index)
? Instructions::kPolymorphicEntryOffsetAOT
: 0);
CodePtr InstructionsTable::FindCode(InstructionsTablePtr table, uword pc) {
// This can run in the middle of GC and must not allocate handles.
NoSafepointScope no_safepoint;
if (!InstructionsTable::ContainsPc(table, pc)) return Code::null();
const auto rodata = table.untag()->rodata_;
const auto pc_offset = InstructionsTable::ConvertPcToOffset(table, pc);
if (pc_offset <= rodata->entries()[rodata->first_entry_with_code].pc_offset) {
return StubCode::UnknownDartCode().ptr();
}
const auto idx =
FindEntry(table, pc, table.untag()->rodata_->first_entry_with_code);
if (idx != -1) {
const intptr_t code_index = idx - rodata->first_entry_with_code;
ASSERT(code_index >= 0);
ASSERT(code_index <
Smi::Value(table.untag()->code_objects()->untag()->length()));
ObjectPtr result =
table.untag()->code_objects()->untag()->element(code_index);
ASSERT(result->IsCode());
// Note: can't use Code::RawCast(...) here because it allocates handles
// in DEBUG mode.
return static_cast<CodePtr>(result);
}
return Code::null();
}
uword InstructionsTable::EntryPointAt(intptr_t code_index) const {
ASSERT(0 <= code_index);
ASSERT(code_index < static_cast<intptr_t>(rodata()->length));
return InstructionsTable::start_pc(this->ptr()) +
rodata()->entries()[code_index].pc_offset;
}
const char* InstructionsTable::ToCString() const {
@ -14966,7 +15009,7 @@ const char* CodeSourceMap::ToCString() const {
uword CompressedStackMaps::Hash() const {
NoSafepointScope scope;
uint8_t* data = UnsafeMutableNonPointer(&untag()->data()[0]);
uint8_t* data = UnsafeMutableNonPointer(&untag()->payload()->data()[0]);
uint8_t* end = data + payload_size();
uint32_t hash = payload_size();
for (uint8_t* cursor = data; cursor < end; cursor++) {
@ -14975,140 +15018,11 @@ uword CompressedStackMaps::Hash() const {
return FinalizeHash(hash, kHashBits);
}
CompressedStackMaps::Iterator::Iterator(const CompressedStackMaps& maps,
const CompressedStackMaps& global_table)
: maps_(maps),
bits_container_(maps_.UsesGlobalTable() ? global_table : maps_) {
ASSERT(!maps_.IsNull());
ASSERT(!bits_container_.IsNull());
ASSERT(!maps_.IsGlobalTable());
ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
}
CompressedStackMaps::Iterator::Iterator(Thread* thread,
const CompressedStackMaps& maps)
: CompressedStackMaps::Iterator(
maps,
// Only look up the global table if the map will end up using it.
maps.UsesGlobalTable() ? CompressedStackMaps::Handle(
thread->zone(),
thread->isolate_group()
->object_store()
->canonicalized_stack_map_entries())
: Object::null_compressed_stackmaps()) {}
CompressedStackMaps::Iterator::Iterator(const CompressedStackMaps::Iterator& it)
: maps_(it.maps_),
bits_container_(it.bits_container_),
next_offset_(it.next_offset_),
current_pc_offset_(it.current_pc_offset_),
current_global_table_offset_(it.current_global_table_offset_),
current_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
current_non_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
current_bits_offset_(it.current_bits_offset_) {}
bool CompressedStackMaps::Iterator::MoveNext() {
if (next_offset_ >= maps_.payload_size()) {
return false;
}
NoSafepointScope scope;
ReadStream stream(maps_.untag()->data(), maps_.payload_size(), next_offset_);
auto const pc_delta = stream.ReadLEB128();
ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_));
current_pc_offset_ += pc_delta;
// Table-using CSMs have a table offset after the PC offset delta, whereas
// the post-delta part of inlined entries has the same information as
// global table entries.
if (maps_.UsesGlobalTable()) {
current_global_table_offset_ = stream.ReadLEB128();
ASSERT(current_global_table_offset_ < bits_container_.payload_size());
// Since generally we only use entries in the GC and the GC only needs
// the rest of the entry information if the PC offset matches, we lazily
// load and cache the information stored in the global object when it is
// actually requested.
current_spill_slot_bit_count_ = -1;
current_non_spill_slot_bit_count_ = -1;
current_bits_offset_ = -1;
next_offset_ = stream.Position();
} else {
current_spill_slot_bit_count_ = stream.ReadLEB128();
ASSERT(current_spill_slot_bit_count_ >= 0);
current_non_spill_slot_bit_count_ = stream.ReadLEB128();
ASSERT(current_non_spill_slot_bit_count_ >= 0);
const auto stackmap_bits =
current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
const uintptr_t stackmap_size =
Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
ASSERT(stackmap_size <= (maps_.payload_size() - stream.Position()));
current_bits_offset_ = stream.Position();
next_offset_ = current_bits_offset_ + stackmap_size;
}
return true;
}
intptr_t CompressedStackMaps::Iterator::Length() const {
EnsureFullyLoadedEntry();
return current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
}
intptr_t CompressedStackMaps::Iterator::SpillSlotBitCount() const {
EnsureFullyLoadedEntry();
return current_spill_slot_bit_count_;
}
bool CompressedStackMaps::Iterator::IsObject(intptr_t bit_index) const {
EnsureFullyLoadedEntry();
ASSERT(bit_index >= 0 && bit_index < Length());
const intptr_t byte_index = bit_index >> kBitsPerByteLog2;
const intptr_t bit_remainder = bit_index & (kBitsPerByte - 1);
uint8_t byte_mask = 1U << bit_remainder;
const intptr_t byte_offset = current_bits_offset_ + byte_index;
NoSafepointScope scope;
return (bits_container_.untag()->data()[byte_offset] & byte_mask) != 0;
}
void CompressedStackMaps::Iterator::LazyLoadGlobalTableEntry() const {
ASSERT(maps_.UsesGlobalTable());
ASSERT(HasLoadedEntry());
ASSERT(current_global_table_offset_ < bits_container_.payload_size());
NoSafepointScope scope;
ReadStream stream(bits_container_.untag()->data(),
bits_container_.payload_size(),
current_global_table_offset_);
current_spill_slot_bit_count_ = stream.ReadLEB128();
ASSERT(current_spill_slot_bit_count_ >= 0);
current_non_spill_slot_bit_count_ = stream.ReadLEB128();
ASSERT(current_non_spill_slot_bit_count_ >= 0);
const auto stackmap_bits = Length();
const uintptr_t stackmap_size =
Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
ASSERT(stackmap_size <= (bits_container_.payload_size() - stream.Position()));
current_bits_offset_ = stream.Position();
}
void CompressedStackMaps::Iterator::WriteToBuffer(BaseTextBuffer* buffer,
const char* separator) const {
CompressedStackMaps::Iterator it(*this);
// If we haven't loaded an entry yet, do so (but don't skip the current
// one if we have!)
if (!it.HasLoadedEntry()) {
if (!it.MoveNext()) return;
}
void CompressedStackMaps::WriteToBuffer(BaseTextBuffer* buffer,
const char* separator) const {
auto it = iterator(Thread::Current());
bool first_entry = true;
do {
while (it.MoveNext()) {
if (!first_entry) {
buffer->AddString(separator);
}
@ -15117,7 +15031,16 @@ void CompressedStackMaps::Iterator::WriteToBuffer(BaseTextBuffer* buffer,
buffer->AddString(it.IsObject(i) ? "1" : "0");
}
first_entry = false;
} while (it.MoveNext());
}
}
CompressedStackMaps::Iterator<CompressedStackMaps>
CompressedStackMaps::iterator(Thread* thread) const {
return Iterator<CompressedStackMaps>(
*this, CompressedStackMaps::Handle(
thread->zone(), thread->isolate_group()
->object_store()
->canonicalized_stack_map_entries()));
}
CompressedStackMapsPtr CompressedStackMaps::New(const void* payload,
@ -15147,12 +15070,13 @@ CompressedStackMapsPtr CompressedStackMaps::New(const void* payload,
NoSafepointScope no_safepoint;
result ^= raw;
result.StoreNonPointer(
&result.untag()->flags_and_size_,
&result.untag()->payload()->flags_and_size,
UntaggedCompressedStackMaps::GlobalTableBit::encode(is_global_table) |
UntaggedCompressedStackMaps::UsesTableBit::encode(
uses_global_table) |
UntaggedCompressedStackMaps::SizeField::encode(size));
auto cursor = result.UnsafeMutableNonPointer(result.untag()->data());
auto cursor =
result.UnsafeMutableNonPointer(result.untag()->payload()->data());
memcpy(cursor, payload, size); // NOLINT
}
@ -15167,10 +15091,9 @@ const char* CompressedStackMaps::ToCString() const {
return "CompressedStackMaps()";
}
auto const t = Thread::Current();
CompressedStackMaps::Iterator it(t, *this);
ZoneTextBuffer buffer(t->zone(), 100);
buffer.AddString("CompressedStackMaps(");
it.WriteToBuffer(&buffer, ", ");
WriteToBuffer(&buffer, ", ");
buffer.AddString(")");
return buffer.buffer();
}

View file

@ -5590,58 +5590,29 @@ class InstructionsSection : public Object {
// Used in AOT in bare instructions mode.
class InstructionsTable : public Object {
public:
static const intptr_t kBytesPerElement = sizeof(uint32_t);
static const intptr_t kMaxElements = kIntptrMax / kBytesPerElement;
static const uint32_t kHasMonomorphicEntrypointFlag = 0x1;
static const uint32_t kPayloadAlignment = Instructions::kBarePayloadAlignment;
static const uint32_t kPayloadMask = ~(kPayloadAlignment - 1);
COMPILE_ASSERT((kPayloadMask & kHasMonomorphicEntrypointFlag) == 0);
struct ArrayTraits {
static intptr_t elements_start_offset() {
return sizeof(UntaggedInstructionsTable);
}
static constexpr intptr_t kElementSize = kBytesPerElement;
};
static intptr_t InstanceSize() {
ASSERT_EQUAL(sizeof(UntaggedInstructionsTable),
OFFSET_OF_RETURNED_VALUE(UntaggedInstructionsTable, data));
return 0;
}
static intptr_t InstanceSize(intptr_t len) {
ASSERT(0 <= len && len <= kMaxElements);
return RoundedAllocationSize(sizeof(UntaggedInstructionsTable) +
len * kBytesPerElement);
}
static intptr_t InstanceSize() { return sizeof(UntaggedInstructionsTable); }
static InstructionsTablePtr New(intptr_t length,
uword start_pc,
uword end_pc);
uword end_pc,
uword rodata);
void SetEntryAt(intptr_t index,
uword payload_start,
bool has_monomorphic_entrypoint,
ObjectPtr descriptor) const;
void SetCodeAt(intptr_t index, CodePtr code) const;
bool ContainsPc(uword pc) const { return ContainsPc(ptr(), pc); }
static bool ContainsPc(InstructionsTablePtr table, uword pc);
// Looks for the entry in the [table] by the given [pc].
// Returns index of an entry which contains [pc], or -1 if not found.
static intptr_t FindEntry(InstructionsTablePtr table, uword pc);
static CodePtr FindCode(InstructionsTablePtr table, uword pc);
intptr_t length() const { return InstructionsTable::length(this->ptr()); }
static intptr_t length(InstructionsTablePtr table) {
return table->untag()->length_;
}
static const UntaggedCompressedStackMaps::Payload*
FindStackMap(InstructionsTablePtr table, uword pc, uword* start_pc);
// Returns descriptor object for the entry with given index.
ObjectPtr DescriptorAt(intptr_t index) const {
return InstructionsTable::DescriptorAt(this->ptr(), index);
static const UntaggedCompressedStackMaps::Payload* GetCanonicalStackMap(
InstructionsTablePtr table);
const UntaggedInstructionsTable::Data* rodata() const {
return ptr()->untag()->rodata_;
}
static ObjectPtr DescriptorAt(InstructionsTablePtr table, intptr_t index);
// Returns start address of the instructions entry with given index.
uword PayloadStartAt(intptr_t index) const {
@ -5663,34 +5634,26 @@ class InstructionsTable : public Object {
return table->untag()->end_pc_;
}
ArrayPtr descriptors() const { return untag()->descriptors_; }
static uint32_t DataAt(InstructionsTablePtr table, intptr_t index) {
ASSERT((0 <= index) && (index < InstructionsTable::length(table)));
return table->untag()->data()[index];
}
uint32_t PcOffsetAt(intptr_t index) const {
return InstructionsTable::PcOffsetAt(this->ptr(), index);
}
static uint32_t PcOffsetAt(InstructionsTablePtr table, intptr_t index) {
return DataAt(table, index) & kPayloadMask;
}
bool HasMonomorphicEntryPointAt(intptr_t index) const {
return (DataAt(this->ptr(), index) & kHasMonomorphicEntrypointFlag) != 0;
}
ArrayPtr code_objects() const { return untag()->code_objects_; }
void set_length(intptr_t value) const;
void set_start_pc(uword value) const;
void set_end_pc(uword value) const;
void set_descriptors(const Array& value) const;
void set_code_objects(const Array& value) const;
void set_rodata(uword rodata) const;
uint32_t ConvertPcToOffset(uword pc) const {
return InstructionsTable::ConvertPcToOffset(this->ptr(), pc);
}
static uint32_t ConvertPcToOffset(InstructionsTablePtr table, uword pc);
static intptr_t FindEntry(InstructionsTablePtr table,
uword pc,
intptr_t start_index = 0);
FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsTable, Object);
friend class Class;
friend class Deserializer;
};
class LocalVarDescriptors : public Object {
@ -5920,13 +5883,16 @@ class CompressedStackMaps : public Object {
uintptr_t payload_size() const { return PayloadSizeOf(ptr()); }
static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw) {
return UntaggedCompressedStackMaps::SizeField::decode(
raw->untag()->flags_and_size_);
raw->untag()->payload()->flags_and_size);
}
const uint8_t* data() const { return ptr()->untag()->payload()->data(); }
// Methods to allow use with PointerKeyValueTrait to create sets of CSMs.
bool Equals(const CompressedStackMaps& other) const {
// All of the table flags and payload size must match.
if (untag()->flags_and_size_ != other.untag()->flags_and_size_) {
if (untag()->payload()->flags_and_size !=
other.untag()->payload()->flags_and_size) {
return false;
}
NoSafepointScope no_safepoint;
@ -5934,7 +5900,10 @@ class CompressedStackMaps : public Object {
}
uword Hash() const;
static intptr_t HeaderSize() { return sizeof(UntaggedCompressedStackMaps); }
static intptr_t HeaderSize() {
return sizeof(UntaggedCompressedStackMaps) +
sizeof(UntaggedCompressedStackMaps::Payload);
}
static intptr_t UnroundedSize(CompressedStackMapsPtr maps) {
return UnroundedSize(CompressedStackMaps::PayloadSizeOf(maps));
}
@ -5942,8 +5911,6 @@ class CompressedStackMaps : public Object {
return HeaderSize() + length;
}
static intptr_t InstanceSize() {
ASSERT_EQUAL(sizeof(UntaggedCompressedStackMaps),
OFFSET_OF_RETURNED_VALUE(UntaggedCompressedStackMaps, data));
return 0;
}
static intptr_t InstanceSize(intptr_t length) {
@ -5953,13 +5920,13 @@ class CompressedStackMaps : public Object {
bool UsesGlobalTable() const { return UsesGlobalTable(ptr()); }
static bool UsesGlobalTable(const CompressedStackMapsPtr raw) {
return UntaggedCompressedStackMaps::UsesTableBit::decode(
raw->untag()->flags_and_size_);
raw->untag()->payload()->flags_and_size);
}
bool IsGlobalTable() const { return IsGlobalTable(ptr()); }
static bool IsGlobalTable(const CompressedStackMapsPtr raw) {
return UntaggedCompressedStackMaps::GlobalTableBit::decode(
raw->untag()->flags_and_size_);
raw->untag()->payload()->flags_and_size);
}
static CompressedStackMapsPtr NewInlined(const void* payload, intptr_t size) {
@ -5978,17 +5945,128 @@ class CompressedStackMaps : public Object {
/*uses_global_table=*/false);
}
class RawPayloadHandle {
public:
RawPayloadHandle() {}
RawPayloadHandle(const RawPayloadHandle&) = default;
RawPayloadHandle& operator=(const RawPayloadHandle&) = default;
const UntaggedCompressedStackMaps::Payload* payload() const {
return payload_;
}
bool IsNull() const { return payload_ == nullptr; }
RawPayloadHandle& operator=(
const UntaggedCompressedStackMaps::Payload* payload) {
payload_ = payload;
return *this;
}
RawPayloadHandle& operator=(const CompressedStackMaps& maps) {
ASSERT(!maps.IsNull());
payload_ = maps.untag()->payload();
return *this;
}
RawPayloadHandle& operator=(CompressedStackMapsPtr maps) {
ASSERT(maps != CompressedStackMaps::null());
payload_ = maps.untag()->payload();
return *this;
}
uintptr_t payload_size() const {
return UntaggedCompressedStackMaps::SizeField::decode(
payload()->flags_and_size);
}
const uint8_t* data() const { return payload()->data(); }
bool UsesGlobalTable() const {
return UntaggedCompressedStackMaps::UsesTableBit::decode(
payload()->flags_and_size);
}
bool IsGlobalTable() const {
return UntaggedCompressedStackMaps::GlobalTableBit::decode(
payload()->flags_and_size);
}
private:
const UntaggedCompressedStackMaps::Payload* payload_ = nullptr;
};
template <typename PayloadHandle>
class Iterator {
public:
Iterator(const CompressedStackMaps& maps,
const CompressedStackMaps& global_table);
Iterator(Thread* thread, const CompressedStackMaps& maps);
Iterator(const PayloadHandle& maps, const PayloadHandle& global_table)
: maps_(maps),
bits_container_(maps.UsesGlobalTable() ? global_table : maps) {
ASSERT(!maps_.IsNull());
ASSERT(!bits_container_.IsNull());
ASSERT(!maps_.IsGlobalTable());
ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
}
explicit Iterator(const CompressedStackMaps::Iterator& it);
Iterator(const Iterator& it)
: maps_(it.maps_),
bits_container_(it.bits_container_),
next_offset_(it.next_offset_),
current_pc_offset_(it.current_pc_offset_),
current_global_table_offset_(it.current_global_table_offset_),
current_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
current_non_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
current_bits_offset_(it.current_bits_offset_) {}
// Loads the next entry from [maps_], if any. If [maps_] is the null value,
// this always returns false.
bool MoveNext();
bool MoveNext() {
if (next_offset_ >= maps_.payload_size()) {
return false;
}
NoSafepointScope scope;
ReadStream stream(maps_.data(), maps_.payload_size(), next_offset_);
auto const pc_delta = stream.ReadLEB128();
ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_));
current_pc_offset_ += pc_delta;
// Table-using CSMs have a table offset after the PC offset delta, whereas
// the post-delta part of inlined entries has the same information as
// global table entries.
// See comments in UntaggedCompressedStackMaps for description of
// encoding.
if (maps_.UsesGlobalTable()) {
current_global_table_offset_ = stream.ReadLEB128();
ASSERT(current_global_table_offset_ < bits_container_.payload_size());
// Since generally we only use entries in the GC and the GC only needs
// the rest of the entry information if the PC offset matches, we lazily
// load and cache the information stored in the global object when it is
// actually requested.
current_spill_slot_bit_count_ = -1;
current_non_spill_slot_bit_count_ = -1;
current_bits_offset_ = -1;
next_offset_ = stream.Position();
} else {
current_spill_slot_bit_count_ = stream.ReadLEB128();
ASSERT(current_spill_slot_bit_count_ >= 0);
current_non_spill_slot_bit_count_ = stream.ReadLEB128();
ASSERT(current_non_spill_slot_bit_count_ >= 0);
const auto stackmap_bits =
current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
const uintptr_t stackmap_size =
Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
ASSERT(stackmap_size <= (maps_.payload_size() - stream.Position()));
current_bits_offset_ = stream.Position();
next_offset_ = current_bits_offset_ + stackmap_size;
}
return true;
}
// Finds the entry with the given PC offset starting at the current position
// of the iterator. If [maps_] is the null value, this always returns false.
@ -6012,21 +6090,56 @@ class CompressedStackMaps : public Object {
}
// Returns the bit length of the loaded entry.
intptr_t Length() const;
intptr_t Length() const {
EnsureFullyLoadedEntry();
return current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
}
// Returns the number of spill slot bits of the loaded entry.
intptr_t SpillSlotBitCount() const;
intptr_t SpillSlotBitCount() const {
EnsureFullyLoadedEntry();
return current_spill_slot_bit_count_;
}
// Returns whether the stack entry represented by the offset contains
// a tagged objecet.
bool IsObject(intptr_t bit_offset) const;
void WriteToBuffer(BaseTextBuffer* buffer, const char* separator) const;
// a tagged object.
bool IsObject(intptr_t bit_index) const {
EnsureFullyLoadedEntry();
ASSERT(bit_index >= 0 && bit_index < Length());
const intptr_t byte_index = bit_index >> kBitsPerByteLog2;
const intptr_t bit_remainder = bit_index & (kBitsPerByte - 1);
uint8_t byte_mask = 1U << bit_remainder;
const intptr_t byte_offset = current_bits_offset_ + byte_index;
NoSafepointScope scope;
return (bits_container_.data()[byte_offset] & byte_mask) != 0;
}
private:
bool HasLoadedEntry() const { return next_offset_ > 0; }
// Caches the corresponding values from the global table in the mutable
// fields. We lazily load these as some clients only need the PC offset.
void LazyLoadGlobalTableEntry() const;
void LazyLoadGlobalTableEntry() const {
ASSERT(maps_.UsesGlobalTable());
ASSERT(HasLoadedEntry());
ASSERT(current_global_table_offset_ < bits_container_.payload_size());
NoSafepointScope scope;
ReadStream stream(bits_container_.data(), bits_container_.payload_size(),
current_global_table_offset_);
current_spill_slot_bit_count_ = stream.ReadLEB128();
ASSERT(current_spill_slot_bit_count_ >= 0);
current_non_spill_slot_bit_count_ = stream.ReadLEB128();
ASSERT(current_non_spill_slot_bit_count_ >= 0);
const auto stackmap_bits = Length();
const uintptr_t stackmap_size =
Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
ASSERT(stackmap_size <=
(bits_container_.payload_size() - stream.Position()));
current_bits_offset_ = stream.Position();
}
void EnsureFullyLoadedEntry() const {
ASSERT(HasLoadedEntry());
@ -6036,8 +6149,8 @@ class CompressedStackMaps : public Object {
}
}
const CompressedStackMaps& maps_;
const CompressedStackMaps& bits_container_;
const PayloadHandle& maps_;
const PayloadHandle& bits_container_;
uintptr_t next_offset_ = 0;
uint32_t current_pc_offset_ = 0;
@ -6053,6 +6166,10 @@ class CompressedStackMaps : public Object {
friend class StackMapEntry;
};
Iterator<CompressedStackMaps> iterator(Thread* thread) const;
void WriteToBuffer(BaseTextBuffer* buffer, const char* separator) const;
private:
static CompressedStackMapsPtr New(const void* payload,
intptr_t size,
@ -6286,6 +6403,10 @@ class Code : public Object {
#endif
}
static uword UncheckedEntryPointOf(const CodePtr code) {
return code->untag()->unchecked_entry_point_;
}
// Returns the unchecked entry point of [instructions()].
uword UncheckedEntryPoint() const {
#if defined(DART_PRECOMPILED_RUNTIME)
@ -9762,6 +9883,7 @@ class OneByteString : public AllStatic {
friend class Symbols;
friend class Utf8;
friend class OneByteStringMessageSerializationCluster;
friend class Deserializer;
};
class TwoByteString : public AllStatic {

View file

@ -454,7 +454,8 @@ void ProgramVisitor::ShareMegamorphicBuckets(Thread* thread) {
class StackMapEntry : public ZoneAllocated {
public:
StackMapEntry(Zone* zone, const CompressedStackMaps::Iterator& it)
StackMapEntry(Zone* zone,
const CompressedStackMaps::Iterator<CompressedStackMaps>& it)
: maps_(CompressedStackMaps::Handle(zone, it.maps_.ptr())),
bits_container_(
CompressedStackMaps::Handle(zone, it.bits_container_.ptr())),
@ -525,7 +526,7 @@ class StackMapEntry : public ZoneAllocated {
}
const uint8_t* PayloadData() const {
ASSERT(!Thread::Current()->IsAtSafepoint());
return bits_container_.ptr()->untag()->data() + bits_offset_;
return bits_container_.ptr()->untag()->payload()->data() + bits_offset_;
}
const CompressedStackMaps& maps_;
@ -582,8 +583,8 @@ void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(Thread* thread) {
void VisitCode(const Code& code) {
compressed_stackmaps_ = code.compressed_stackmaps();
CompressedStackMaps::Iterator it(compressed_stackmaps_,
old_global_table_);
CompressedStackMaps::Iterator<CompressedStackMaps> it(
compressed_stackmaps_, old_global_table_);
while (it.MoveNext()) {
auto const entry = new (zone_) StackMapEntry(zone_, it);
auto const index = entry_indices_.LookupValue(entry);
@ -705,7 +706,8 @@ void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(Thread* thread) {
return Object::empty_compressed_stackmaps().ptr();
}
MallocWriteStream new_payload(maps.payload_size());
CompressedStackMaps::Iterator it(maps, old_global_table_);
CompressedStackMaps::Iterator<CompressedStackMaps> it(maps,
old_global_table_);
intptr_t last_offset = 0;
while (it.MoveNext()) {
StackMapEntry entry(zone_, it);
@ -1269,6 +1271,82 @@ void ProgramVisitor::DedupInstructions(Thread* thread) {
code_(Code::Handle(zone)),
instructions_(Instructions::Handle(zone)) {}
// Relink the program graph to eliminate references to the non-canonical
// Code objects. We want to arrive to the graph where Code objects
// and Instruction objects are in one-to-one relationship.
void PostProcess(IsolateGroup* isolate_group) {
const intptr_t canonical_count = canonical_objects_.Length();
auto& static_calls_array = Array::Handle(zone_);
auto& static_calls_table_entry = Object::Handle(zone_);
auto should_canonicalize = [&](const Object& obj) {
return CanCanonicalize(Code::Cast(obj)) && !obj.InVMIsolateHeap();
};
auto process_pool = [&](const ObjectPool& pool) {
if (pool.IsNull()) {
return;
}
auto& object = Object::Handle(zone_);
for (intptr_t i = 0; i < pool.Length(); i++) {
auto const type = pool.TypeAt(i);
if (type != ObjectPool::EntryType::kTaggedObject) continue;
object = pool.ObjectAt(i);
if (object.IsCode() && should_canonicalize(object)) {
object = Canonicalize(Code::Cast(object));
pool.SetObjectAt(i, object);
}
}
};
auto& pool = ObjectPool::Handle(zone_);
auto it = canonical_objects_.GetIterator();
while (auto canonical_code = it.Next()) {
static_calls_array = (*canonical_code)->static_calls_target_table();
if (!static_calls_array.IsNull()) {
StaticCallsTable static_calls(static_calls_array);
for (auto& view : static_calls) {
static_calls_table_entry =
view.Get<Code::kSCallTableCodeOrTypeTarget>();
if (static_calls_table_entry.IsCode() &&
should_canonicalize(static_calls_table_entry)) {
static_calls_table_entry =
Canonicalize(Code::Cast(static_calls_table_entry));
view.Set<Code::kSCallTableCodeOrTypeTarget>(
static_calls_table_entry);
}
}
}
pool = (*canonical_code)->object_pool();
process_pool(pool);
}
auto object_store = isolate_group->object_store();
const auto& dispatch_table_entries =
Array::Handle(zone_, object_store->dispatch_table_code_entries());
if (!dispatch_table_entries.IsNull()) {
auto& code = Code::Handle(zone_);
for (intptr_t i = 0; i < dispatch_table_entries.Length(); i++) {
code ^= dispatch_table_entries.At(i);
if (should_canonicalize(code)) {
code ^= Canonicalize(code);
dispatch_table_entries.SetAt(i, code);
}
}
}
// If there's a global object pool, add any visitable objects.
pool = object_store->global_object_pool();
process_pool(pool);
RELEASE_ASSERT(canonical_count == canonical_objects_.Length());
}
void VisitFunction(const Function& function) {
if (!function.HasCode()) return;
code_ = function.CurrentCode();
@ -1276,12 +1354,13 @@ void ProgramVisitor::DedupInstructions(Thread* thread) {
// ProgramWalker, but as long as the deduplication process is idempotent,
// the cached entry points won't change during the second visit.
VisitCode(code_);
function.SetInstructionsSafe(code_); // Update cached entry point.
function.SetInstructionsSafe(canonical_); // Update cached entry point.
}
void VisitCode(const Code& code) {
canonical_ = code.ptr();
if (code.IsDisabled()) return;
canonical_ = Dedup(code);
canonical_ = Canonicalize(code);
instructions_ = canonical_.instructions();
code.SetActiveInstructionsSafe(instructions_,
code.UncheckedEntryPointOffset());
@ -1291,6 +1370,14 @@ void ProgramVisitor::DedupInstructions(Thread* thread) {
private:
bool CanCanonicalize(const Code& code) const { return !code.IsDisabled(); }
CodePtr Canonicalize(const Code& code) {
canonical_ = Dedup(code);
if (!code.is_discarded() && canonical_.is_discarded()) {
canonical_.set_is_discarded(false);
}
return canonical_.ptr();
}
Code& canonical_;
Code& code_;
Instructions& instructions_;
@ -1300,6 +1387,7 @@ void ProgramVisitor::DedupInstructions(Thread* thread) {
StackZone stack_zone(thread);
DedupInstructionsWithSameMetadataVisitor visitor(thread->zone());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
visitor.PostProcess(thread->isolate_group());
return;
}
#endif // defined(DART_PRECOMPILER)

View file

@ -115,13 +115,6 @@ intptr_t UntaggedObject::HeapSizeFromClass(uword tags) const {
instance_size = InstructionsSection::InstanceSize(section_size);
break;
}
case kInstructionsTableCid: {
const InstructionsTablePtr raw_instructions_table =
static_cast<const InstructionsTablePtr>(this);
intptr_t length = raw_instructions_table->untag()->length_;
instance_size = InstructionsTable::InstanceSize(length);
break;
}
case kContextCid: {
const ContextPtr raw_context = static_cast<const ContextPtr>(this);
intptr_t num_variables = raw_context->untag()->num_variables_;
@ -575,7 +568,7 @@ VARIABLE_COMPRESSED_VISITOR(
Smi::Value(raw_obj->untag()->length()))
VARIABLE_COMPRESSED_VISITOR(ContextScope, raw_obj->untag()->num_variables_)
NULL_VISITOR(Sentinel)
VARIABLE_VISITOR(InstructionsTable, raw_obj->untag()->length_)
REGULAR_VISITOR(InstructionsTable)
NULL_VISITOR(Mint)
NULL_VISITOR(Double)
NULL_VISITOR(Float32x4)

View file

@ -1864,22 +1864,6 @@ class UntaggedInstructionsSection : public UntaggedObject {
friend class Image;
};
class UntaggedInstructionsTable : public UntaggedObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(InstructionsTable);
POINTER_FIELD(ArrayPtr, descriptors)
VISIT_FROM(descriptors)
VISIT_TO(descriptors)
intptr_t length_;
uword start_pc_;
uword end_pc_;
// Variable length data follows here.
uint32_t* data() { OPEN_ARRAY_START(uint32_t, uint32_t); }
const uint32_t* data() const { OPEN_ARRAY_START(uint32_t, uint32_t); }
};
class UntaggedPcDescriptors : public UntaggedObject {
public:
// The macro argument V is passed two arguments, the raw name of the enum value
@ -2002,75 +1986,130 @@ class UntaggedCompressedStackMaps : public UntaggedObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(CompressedStackMaps);
VISIT_NOTHING();
// The most significant bits are the length of the encoded payload, in bytes.
// The low bits determine the expected payload contents, as described below.
uint32_t flags_and_size_;
public:
struct Payload {
// The most significant bits are the length of the encoded payload, in
// bytes (excluding the header itself). The low bits determine the
// expected payload contents, as described below.
uint32_t flags_and_size;
// Variable length data follows here. The contents of the payload depend on
// the type of CompressedStackMaps (CSM) being represented. There are three
// major types of CSM:
//
// 1) GlobalTableBit = false, UsesTableBit = false: CSMs that include all
// information about the stack maps. The payload for these contain tightly
// packed entries with the following information:
//
// * A header containing the following three pieces of information:
// * An unsigned integer representing the PC offset as a delta from the
// PC offset of the previous entry (from 0 for the first entry).
// * An unsigned integer representing the number of bits used for
// spill slot entries.
// * An unsigned integer representing the number of bits used for other
// entries.
// * The body containing the bits for the stack map. The length of the body
// in bits is the sum of the spill slot and non-spill slot bit counts.
//
// 2) GlobalTableBit = false, UsesTableBit = true: CSMs where the majority of
// the stack map information has been offloaded and canonicalized into a
// global table. The payload contains tightly packed entries with the
// following information:
//
// * A header containing just an unsigned integer representing the PC offset
// delta as described above.
// * The body is just an unsigned integer containing the offset into the
// payload for the global table.
//
// 3) GlobalTableBit = true, UsesTableBit = false: A CSM implementing the
// global table. Here, the payload contains tightly packed entries with
// the following information:
//
// * A header containing the following two pieces of information:
// * An unsigned integer representing the number of bits used for
// spill slot entries.
// * An unsigned integer representing the number of bits used for other
// entries.
// * The body containing the bits for the stack map. The length of the body
// in bits is the sum of the spill slot and non-spill slot bit counts.
//
// In all types of CSM, each unsigned integer is LEB128 encoded, as generally
// they tend to fit in a single byte or two. Thus, entry headers are not a
// fixed length, and currently there is no random access of entries. In
// addition, PC offsets are currently encoded as deltas, which also inhibits
// random access without accessing previous entries. That means to find an
// entry for a given PC offset, a linear search must be done where the payload
// is decoded up to the entry whose PC offset is >= the given PC.
// Variable length data follows here. The contents of the payload depend on
// the type of CompressedStackMaps (CSM) being represented. There are three
// major types of CSM:
//
// 1) GlobalTableBit = false, UsesTableBit = false: CSMs that include all
// information about the stack maps. The payload for these contain
// tightly packed entries with the following information:
//
// * A header containing the following three pieces of information:
// * An unsigned integer representing the PC offset as a delta from the
// PC offset of the previous entry (from 0 for the first entry).
// * An unsigned integer representing the number of bits used for
// spill slot entries.
// * An unsigned integer representing the number of bits used for other
// entries.
// * The body containing the bits for the stack map. The length of
// the body in bits is the sum of the spill slot and non-spill slot
// bit counts.
//
// 2) GlobalTableBit = false, UsesTableBit = true: CSMs where the majority
// of the stack map information has been offloaded and canonicalized into
// a global table. The payload contains tightly packed entries with the
// following information:
//
// * A header containing just an unsigned integer representing the PC
// offset delta as described above.
// * The body is just an unsigned integer containing the offset into the
// payload for the global table.
//
// 3) GlobalTableBit = true, UsesTableBit = false: A CSM implementing the
// global table. Here, the payload contains tightly packed entries with
// the following information:
//
// * A header containing the following two pieces of information:
// * An unsigned integer representing the number of bits used for
// spill slot entries.
// * An unsigned integer representing the number of bits used for other
// entries.
// * The body containing the bits for the stack map. The length of the
// body in bits is the sum of the spill slot and non-spill slot bit
// counts.
//
// In all types of CSM, each unsigned integer is LEB128 encoded, as
// generally they tend to fit in a single byte or two. Thus, entry headers
// are not a fixed length, and currently there is no random access of
// entries. In addition, PC offsets are currently encoded as deltas, which
// also inhibits random access without accessing previous entries. That
// means to find an entry for a given PC offset, a linear search must be
// done where the payload is decoded up to the entry whose PC offset
// is greater or equal to the given PC.
uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
};
static_assert(sizeof(Payload) == sizeof(uint32_t));
private:
// We are using OPEN_ARRAY_START rather than embedding Payload directly into
// the UntaggedCompressedStackMaps as a field because that would introduce a
// padding at the end of UntaggedCompressedStackMaps - so we would not be
// able to use sizeof(UntaggedCompressedStackMaps) as the size of the header
// anyway.
Payload* payload() { OPEN_ARRAY_START(Payload, uint32_t); }
const Payload* payload() const { OPEN_ARRAY_START(Payload, uint32_t); }
class GlobalTableBit : public BitField<uint32_t, bool, 0, 1> {};
class UsesTableBit
: public BitField<uint32_t, bool, GlobalTableBit::kNextBit, 1> {};
class SizeField : public BitField<uint32_t,
uint32_t,
UsesTableBit::kNextBit,
sizeof(flags_and_size_) * kBitsPerByte -
UsesTableBit::kNextBit> {};
class SizeField
: public BitField<uint32_t,
uint32_t,
UsesTableBit::kNextBit,
sizeof(Payload::flags_and_size) * kBitsPerByte -
UsesTableBit::kNextBit> {};
friend class Object;
friend class ImageWriter;
friend class StackMapEntry;
};
class UntaggedInstructionsTable : public UntaggedObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(InstructionsTable);
POINTER_FIELD(ArrayPtr, code_objects)
VISIT_FROM(code_objects)
VISIT_TO(code_objects)
struct DataEntry {
uint32_t pc_offset;
uint32_t stack_map_offset;
};
static_assert(sizeof(DataEntry) == sizeof(uint32_t) * 2);
struct Data {
uint32_t canonical_stack_map_entries_offset;
uint32_t length;
uint32_t first_entry_with_code;
uint32_t padding;
const DataEntry* entries() const { OPEN_ARRAY_START(DataEntry, uint32_t); }
const UntaggedCompressedStackMaps::Payload* StackMapAt(
intptr_t offset) const {
return reinterpret_cast<UntaggedCompressedStackMaps::Payload*>(
reinterpret_cast<uword>(this) + offset);
}
};
static_assert(sizeof(Data) == sizeof(uint32_t) * 4);
intptr_t length_;
const Data* rodata_;
uword start_pc_;
uword end_pc_;
friend class Deserializer;
};
class UntaggedLocalVarDescriptors : public UntaggedObject {
public:
enum VarInfoKind {

View file

@ -104,7 +104,7 @@ namespace dart {
F(ICData, args_descriptor_) \
F(ICData, entries_) \
F(ICData, owner_) \
F(InstructionsTable, descriptors_) \
F(InstructionsTable, code_objects_) \
F(MegamorphicCache, target_name_) \
F(MegamorphicCache, args_descriptor_) \
F(MegamorphicCache, buckets_) \

View file

@ -11,10 +11,9 @@
namespace dart {
ObjectPtr ReversePc::FindCodeDescriptorInGroup(IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start) {
CodePtr ReversePc::FindCodeInGroup(IsolateGroup* group,
uword pc,
bool is_return_address) {
#if defined(DART_PRECOMPILED_RUNTIME)
// This can run in the middle of GC and must not allocate handles.
NoSafepointScope no_safepoint;
@ -31,30 +30,80 @@ ObjectPtr ReversePc::FindCodeDescriptorInGroup(IsolateGroup* group,
for (intptr_t i = 0; i < tables_length; i++) {
InstructionsTablePtr table = static_cast<InstructionsTablePtr>(
tables->untag()->data()->untag()->element(i));
intptr_t index = InstructionsTable::FindEntry(table, pc);
if (index >= 0) {
*code_start = InstructionsTable::PayloadStartAt(table, index);
return InstructionsTable::DescriptorAt(table, index);
CodePtr code = InstructionsTable::FindCode(table, pc);
if (code != Code::null()) {
return code;
}
}
#endif // defined(DART_PRECOMPILED_RUNTIME)
return Code::null();
}
const UntaggedCompressedStackMaps::Payload* ReversePc::FindStackMapInGroup(
IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start,
const UntaggedCompressedStackMaps::Payload** global_table) {
#if defined(DART_PRECOMPILED_RUNTIME)
// This can run in the middle of GC and must not allocate handles.
NoSafepointScope no_safepoint;
if (is_return_address) {
pc--;
}
// This expected number of tables is low (one per loading unit), so we go
// through them linearly. If this changes, would could sort the table list
// during deserialization and binary search for the table.
GrowableObjectArrayPtr tables = group->object_store()->instructions_tables();
intptr_t tables_length = Smi::Value(tables->untag()->length());
for (intptr_t i = 0; i < tables_length; i++) {
InstructionsTablePtr table = static_cast<InstructionsTablePtr>(
tables->untag()->data()->untag()->element(i));
auto map = InstructionsTable::FindStackMap(table, pc, code_start);
if (map != nullptr) {
// Take global table from the first table.
table = static_cast<InstructionsTablePtr>(
tables->untag()->data()->untag()->element(0));
*global_table = InstructionsTable::GetCanonicalStackMap(table);
return map;
}
}
#endif // defined(DART_PRECOMPILED_RUNTIME)
*code_start = 0;
return Object::null();
return nullptr;
}
ObjectPtr ReversePc::FindCodeDescriptor(IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start) {
const UntaggedCompressedStackMaps::Payload* ReversePc::FindStackMap(
IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start,
const UntaggedCompressedStackMaps::Payload** global_table) {
ASSERT(FLAG_precompiled_mode);
NoSafepointScope no_safepoint;
ObjectPtr code_descriptor =
FindCodeDescriptorInGroup(group, pc, is_return_address, code_start);
if (code_descriptor == Object::null()) {
code_descriptor = FindCodeDescriptorInGroup(Dart::vm_isolate_group(), pc,
is_return_address, code_start);
auto map = FindStackMapInGroup(group, pc, is_return_address, code_start,
global_table);
if (map == nullptr) {
map = FindStackMapInGroup(Dart::vm_isolate_group(), pc, is_return_address,
code_start, global_table);
}
return map;
}
CodePtr ReversePc::FindCode(IsolateGroup* group,
uword pc,
bool is_return_address) {
ASSERT(FLAG_precompiled_mode);
NoSafepointScope no_safepoint;
auto code_descriptor = FindCodeInGroup(group, pc, is_return_address);
if (code_descriptor == Code::null()) {
code_descriptor =
FindCodeInGroup(Dart::vm_isolate_group(), pc, is_return_address);
}
return code_descriptor;
}
@ -65,44 +114,7 @@ CodePtr ReversePc::Lookup(IsolateGroup* group,
ASSERT(FLAG_precompiled_mode);
NoSafepointScope no_safepoint;
uword code_start;
ObjectPtr code_descriptor =
FindCodeDescriptor(group, pc, is_return_address, &code_start);
if (code_descriptor != Object::null()) {
if (!code_descriptor->IsCode()) {
ASSERT(StubCode::UnknownDartCode().PayloadStart() == 0);
ASSERT(StubCode::UnknownDartCode().Size() == kUwordMax);
ASSERT(StubCode::UnknownDartCode().IsFunctionCode());
ASSERT(StubCode::UnknownDartCode().IsUnknownDartCode());
code_descriptor = StubCode::UnknownDartCode().ptr();
}
}
return static_cast<CodePtr>(code_descriptor);
}
CompressedStackMapsPtr ReversePc::FindCompressedStackMaps(
IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start) {
ASSERT(FLAG_precompiled_mode);
NoSafepointScope no_safepoint;
ObjectPtr code_descriptor =
FindCodeDescriptor(group, pc, is_return_address, code_start);
if (code_descriptor != Object::null()) {
if (code_descriptor->IsCode()) {
CodePtr code = static_cast<CodePtr>(code_descriptor);
ASSERT(*code_start == Code::PayloadStartOf(code));
return code->untag()->compressed_stackmaps();
} else {
ASSERT(code_descriptor->IsCompressedStackMaps());
return static_cast<CompressedStackMapsPtr>(code_descriptor);
}
}
*code_start = 0;
return CompressedStackMaps::null();
return FindCode(group, pc, is_return_address);
}
} // namespace dart

View file

@ -7,6 +7,7 @@
#include "vm/allocation.h"
#include "vm/globals.h"
#include "vm/raw_object.h"
#include "vm/tagged_pointer.h"
namespace dart {
@ -22,24 +23,27 @@ class ReversePc : public AllStatic {
// given isolate |group| and vm isolate group.
static CodePtr Lookup(IsolateGroup* group, uword pc, bool is_return_address);
// Looks for CompressedStackMaps corresponding to |pc| in the
// given isolate |group| and vm isolate group.
// Sets |code_start| to the beginning of the instructions corresponding
// to |pc| (like Code::PayloadStart()).
static CompressedStackMapsPtr FindCompressedStackMaps(IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start);
static const UntaggedCompressedStackMaps::Payload* FindStackMap(
IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start,
const UntaggedCompressedStackMaps::Payload** global_table);
private:
static ObjectPtr FindCodeDescriptorInGroup(IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start);
static ObjectPtr FindCodeDescriptor(IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start);
static const UntaggedCompressedStackMaps::Payload* FindStackMapInGroup(
IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start,
const UntaggedCompressedStackMaps::Payload** global_table);
static CodePtr FindCodeInGroup(IsolateGroup* group,
uword pc,
bool is_return_address);
static CodePtr FindCode(IsolateGroup* group,
uword pc,
bool is_return_address);
};
} // namespace dart

View file

@ -205,13 +205,18 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
// helper functions to the raw object interface.
NoSafepointScope no_safepoint;
Code code;
CompressedStackMaps maps;
CompressedStackMaps::RawPayloadHandle maps;
CompressedStackMaps::RawPayloadHandle global_table;
uword code_start;
if (FLAG_precompiled_mode) {
maps = ReversePc::FindCompressedStackMaps(isolate_group(), pc(),
/*is_return_address=*/true,
&code_start);
const UntaggedCompressedStackMaps::Payload* global_table_payload;
maps = ReversePc::FindStackMap(isolate_group(), pc(),
/*is_return_address=*/true, &code_start,
&global_table_payload);
global_table = global_table_payload;
} else {
ObjectPtr pc_marker = *(reinterpret_cast<ObjectPtr*>(
fp() + (runtime_frame_layout.code_from_fp * kWordSize)));
@ -221,8 +226,12 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
if (pc_marker->IsHeapObject() && (pc_marker->GetClassId() == kCodeCid)) {
code ^= pc_marker;
code_start = code.PayloadStart();
ASSERT(code.compressed_stackmaps() != CompressedStackMaps::null());
maps = code.compressed_stackmaps();
ASSERT(!maps.IsNull());
if (maps.UsesGlobalTable()) {
global_table =
isolate_group()->object_store()->canonicalized_stack_map_entries();
}
} else {
ASSERT(pc_marker == Object::null());
}
@ -231,11 +240,8 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
if (!maps.IsNull()) {
// Optimized frames have a stack map. We need to visit the frame based
// on the stack map.
CompressedStackMaps global_table;
global_table =
isolate_group()->object_store()->canonicalized_stack_map_entries();
CompressedStackMaps::Iterator it(maps, global_table);
CompressedStackMaps::Iterator<CompressedStackMaps::RawPayloadHandle> it(
maps, global_table);
const uint32_t pc_offset = pc() - code_start;
if (it.Find(pc_offset)) {
ObjectPtr* first = reinterpret_cast<ObjectPtr*>(sp());

View file

@ -798,7 +798,8 @@
},
"dartkp-linux-(debug|product|release)-simarm-crossword": {
"options": {
"builder-tag": "crossword"
"builder-tag": "crossword",
"use-elf": true
}
},
"dartkp-weak-asserts-linux-(debug|product|release)-simarm-crossword": {