Flutter Engine
The Flutter Engine
il_serializer.h
Go to the documentation of this file.
1// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_BACKEND_IL_SERIALIZER_H_
6#define RUNTIME_VM_COMPILER_BACKEND_IL_SERIALIZER_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
12#include <utility> // For std::move.
13
14#include "platform/globals.h"
15#include "vm/allocation.h"
17
18namespace dart {
19
20class AliasIdentity;
21class BlockEntryInstr;
22class CallTargets;
23class CatchBlockEntryInstr;
24struct CidRangeValue;
25class Cids;
26class Code;
27class ComparisonInstr;
28class CompileType;
29class Definition;
30class Environment;
31class FunctionEntryInstr;
32class Instruction;
33class FlowGraph;
34class GraphEntryInstr;
35class Heap;
36class IndirectEntryInstr;
37class JoinEntryInstr;
38class LocalVariable;
39class LocationSummary;
40class MoveOperands;
41class MoveSchedule;
42class NonStreamingWriteStream;
43class OsrEntryInstr;
44class ParsedFunction;
45class ParallelMoveInstr;
46class PhiInstr;
47class Range;
48class ReadStream;
49class RecordShape;
50class TargetEntryInstr;
51class TokenPosition;
52
53namespace compiler {
54struct TableSelector;
55
56namespace ffi {
57class CallbackMarshaller;
58class CallMarshaller;
59class NativeCallingConvention;
60} // namespace ffi
61} // namespace compiler
62
63// The list of types which are handled by flow graph serializer/deserializer.
64// For each type there is a corresponding Write<T>(T) and Read<T>() methods.
65//
66// This list includes all types of fields of IL instructions
67// which are serialized via DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS macro,
68// except enum types which are unwrapped with serializable_type_t.
69//
70// The list is sorted alphabetically by type name.
71#define IL_SERIALIZABLE_TYPE_LIST(V) \
72 V(AliasIdentity) \
73 V(const AbstractType&) \
74 V(const AbstractType*) \
75 V(const Array&) \
76 V(bool) \
77 V(const compiler::ffi::CallbackMarshaller&) \
78 V(const compiler::ffi::CallMarshaller&) \
79 V(const CallTargets&) \
80 V(const char*) \
81 V(CidRangeValue) \
82 V(const Cids&) \
83 V(const Class&) \
84 V(const Code&) \
85 V(ComparisonInstr*) \
86 V(CompileType*) \
87 V(ConstantInstr*) \
88 V(Definition*) \
89 V(double) \
90 V(Environment*) \
91 V(const Field&) \
92 V(const ICData*) \
93 V(const Instance&) \
94 V(int8_t) \
95 V(int16_t) \
96 V(int32_t) \
97 V(int64_t) \
98 V(const Function&) \
99 V(const FunctionType&) \
100 V(Instruction*) \
101 V(const LocalVariable&) \
102 V(LocationSummary*) \
103 V(MoveOperands*) \
104 V(const MoveSchedule*) \
105 V(const Object&) \
106 V(ParallelMoveInstr*) \
107 V(PhiInstr*) \
108 V(Range*) \
109 V(RecordShape) \
110 V(Representation) \
111 V(const Slot&) \
112 V(const Slot*) \
113 V(const String&) \
114 V(const compiler::TableSelector*) \
115 V(TokenPosition) \
116 V(const TypeArguments&) \
117 V(const TypeParameters&) \
118 V(uint8_t) \
119 V(uint16_t) \
120 V(uint32_t) \
121 V(uint64_t) \
122 V(Value*)
123
124// List of types serializable as references.
125#define IL_SERIALIZABLE_REF_TYPE_LIST(V) \
126 V(BlockEntryInstr*) \
127 V(CatchBlockEntryInstr*) \
128 V(Definition*) \
129 V(FunctionEntryInstr*) \
130 V(IndirectEntryInstr*) \
131 V(JoinEntryInstr*) \
132 V(OsrEntryInstr*) \
133 V(TargetEntryInstr*)
134
135// Serializes flow graph, including constants and references
136// to objects of program structure.
137//
138// Each IL instruction is serialized in 2 step:
139// - the main step (T::WriteTo / T::T()) serializes
140// instruction fields, basically everything required to
141// re-create instruction object.
142// - the extra step (T::WriteExtra / T::ReadExtra) serializes
143// references to other instructions, including inputs,
144// environments, locations (may reference constants) and successors.
145//
147 public:
150
151 // Writes [flow_graph] into the stream.
152 // The graph should be compacted via CompactSSA().
153 // [detached_defs] should contain all definitions which are
154 // detached from the graph but can still be referenced from
155 // environments.
156 void WriteFlowGraph(const FlowGraph& flow_graph,
157 const ZoneGrowableArray<Definition*>& detached_defs);
158
159 // Implementation of 'Write' method, specialized for a particular type.
160 // This struct is used for the partial template instantiations below.
161 //
162 // Explicit (full) specializations of 'Write' method are not provided as
163 // gcc doesn't support explicit template specializations of members of
164 // a non-template class
165 // (CWG 730 https://cplusplus.github.io/CWG/issues/730.html).
166 // The 2nd template argument is used to make all template instantiations
167 // partial as gcc doesn't support explicit (full) template specializations
168 // in class scope (CWG 727 https://cplusplus.github.io/CWG/issues/727.html).
169 template <typename T, class = void>
170 struct WriteTrait {
171 using ArgType = T;
172 };
173
174 template <typename T>
176 using ArgType = const GrowableArray<T>&;
178 const intptr_t len = x.length();
179 s->Write<intptr_t>(len);
180 for (intptr_t i = 0; i < len; ++i) {
181 s->Write<T>(x[i]);
182 }
183 }
184 };
185
186 template <typename T>
187 struct WriteTrait<const GrowableArray<T>&> {
188 using ArgType = const GrowableArray<T>&;
191 }
192 };
193
194 template <typename T>
198 if (x == nullptr) {
199 s->Write<intptr_t>(-1);
200 return;
201 }
202 const intptr_t len = x->length();
203 s->Write<intptr_t>(len);
204 for (intptr_t i = 0; i < len; ++i) {
205 s->Write<T>((*x)[i]);
206 }
207 }
208 };
209
210 template <typename T>
215 }
216 };
217
218 // Specialization in case intptr_t is not mapped to intN_t.
219 template <typename T>
220 struct WriteTrait<T,
221 std::enable_if_t<std::is_same_v<intptr_t, T> &&
222 !std::is_same_v<intptr_t, int32_t> &&
223 !std::is_same_v<intptr_t, int64_t>>> {
224 using ArgType = intptr_t;
225 static void Write(FlowGraphSerializer* s, intptr_t x) {
226#ifdef ARCH_IS_64_BIT
227 s->Write<int64_t>(x);
228#else
229 s->Write<int32_t>(x);
230#endif
231 }
232 };
233
234 // Specialization in case uintptr_t is not mapped to uintN_t.
235 template <typename T>
236 struct WriteTrait<T,
237 std::enable_if_t<std::is_same_v<uintptr_t, T> &&
238 !std::is_same_v<uintptr_t, uint32_t> &&
239 !std::is_same_v<uintptr_t, uint64_t>>> {
240 using ArgType = uintptr_t;
241 static void Write(FlowGraphSerializer* s, uintptr_t x) {
242#ifdef ARCH_IS_64_BIT
243 s->Write<uint64_t>(x);
244#else
245 s->Write<uint32_t>(x);
246#endif
247 }
248 };
249
250#define DECLARE_WRITE_TRAIT(type) \
251 template <typename T> \
252 struct WriteTrait<T, std::enable_if_t<std::is_same_v<type, T>>> { \
253 using ArgType = type; \
254 static void Write(FlowGraphSerializer* s, type x); \
255 };
257#undef DECLARE_WRITE_TRAIT
258
259 template <typename T>
261 WriteTrait<T>::Write(this, x);
262 }
263
264 // Implementation of 'WriteRef' method, specialized for a particular type.
265 // This struct is used for the partial template instantiations below.
266 //
267 // Explicit (full) specializations of 'WriteRef' method are not provided as
268 // gcc doesn't support explicit template specializations of members of
269 // a non-template class
270 // (CWG 730 https://cplusplus.github.io/CWG/issues/730.html).
271 // The 2nd template argument is used to make all template instantiations
272 // partial as gcc doesn't support explicit (full) template specializations
273 // in class scope (CWG 727 https://cplusplus.github.io/CWG/issues/727.html).
274 template <typename T, class = void>
275 struct WriteRefTrait {};
276
277#define DECLARE_WRITE_REF_TRAIT(type) \
278 template <typename T> \
279 struct WriteRefTrait<T, std::enable_if_t<std::is_same_v<type, T>>> { \
280 static void WriteRef(FlowGraphSerializer* s, T x); \
281 };
283#undef DECLARE_WRITE_REF_TRAIT
284
285 template <typename T>
286 void WriteRef(T x) {
288 }
289
290 template <typename T>
292 const intptr_t len = array.length();
293 Write<intptr_t>(len);
294 for (intptr_t i = 0; i < len; ++i) {
295 WriteRef<T>(array[i]);
296 }
297 }
298
299 BaseWriteStream* stream() const { return stream_; }
300 Zone* zone() const { return zone_; }
301 Thread* thread() const { return thread_; }
302 IsolateGroup* isolate_group() const { return isolate_group_; }
303 Heap* heap() const { return heap_; }
304 bool can_write_refs() const { return can_write_refs_; }
305
306 private:
307 void WriteObjectImpl(const Object& x, intptr_t cid, intptr_t object_index);
308 bool IsWritten(const Object& obj);
309 bool HasEnclosingTypes(const Object& obj);
310 bool WriteObjectWithEnclosingTypes(const Object& type);
311 void WriteEnclosingTypes(const Object& type,
312 intptr_t num_free_fun_type_params);
313
315 Zone* zone_;
316 Thread* thread_;
317 IsolateGroup* isolate_group_;
318 Heap* heap_;
319 intptr_t object_counter_ = 0;
320 bool can_write_refs_ = false;
321 intptr_t num_free_fun_type_params_ = kMaxInt;
322};
323
324// Deserializes flow graph.
325// All constants and types are canonicalized during deserialization.
327 public:
330
331 const ParsedFunction& parsed_function() const { return parsed_function_; }
332
333 Zone* zone() const { return zone_; }
334 ReadStream* stream() const { return stream_; }
335 Thread* thread() const { return thread_; }
336 IsolateGroup* isolate_group() const { return isolate_group_; }
337
338 GraphEntryInstr* graph_entry() const { return graph_entry_; }
339 void set_graph_entry(GraphEntryInstr* entry) { graph_entry_ = entry; }
340
341 BlockEntryInstr* current_block() const { return current_block_; }
342 void set_current_block(BlockEntryInstr* block) { current_block_ = block; }
343
344 BlockEntryInstr* block(intptr_t block_id) const {
345 BlockEntryInstr* b = blocks_[block_id];
346 ASSERT(b != nullptr);
347 return b;
348 }
349 void set_block(intptr_t block_id, BlockEntryInstr* block) {
350 ASSERT(blocks_[block_id] == nullptr);
351 blocks_[block_id] = block;
352 }
353
354 Definition* definition(intptr_t ssa_temp_index) const {
355 Definition* def = definitions_[ssa_temp_index];
356 ASSERT(def != nullptr);
357 return def;
358 }
359 void set_definition(intptr_t ssa_temp_index, Definition* def) {
360 ASSERT(definitions_[ssa_temp_index] == nullptr);
361 definitions_[ssa_temp_index] = def;
362 }
363
365
366 // Implementation of 'Read' method, specialized for a particular type.
367 // This struct is used for the partial template instantiations below.
368 //
369 // Explicit (full) specializations of 'Read' method are not provided as
370 // gcc doesn't support explicit template specializations of members of
371 // a non-template class
372 // (CWG 730 https://cplusplus.github.io/CWG/issues/730.html).
373 // The 2nd template argument is used to make all template instantiations
374 // partial as gcc doesn't support explicit (full) template specializations
375 // in class scope (CWG 727 https://cplusplus.github.io/CWG/issues/727.html).
376 template <typename T, class = void>
377 struct ReadTrait {};
378
379 template <typename T>
382 const intptr_t len = d->Read<intptr_t>();
383 GrowableArray<T> array(len);
384 for (int i = 0; i < len; ++i) {
385 array.Add(d->Read<T>());
386 }
387 return array;
388 }
389 };
390
391 template <typename T>
392 struct ReadTrait<const GrowableArray<T>&> {
395 }
396 };
397
398 template <typename T>
401 const intptr_t len = d->Read<intptr_t>();
402 if (len < 0) {
403 return nullptr;
404 }
405 auto* array = new (d->zone()) ZoneGrowableArray<T>(d->zone(), len);
406 for (int i = 0; i < len; ++i) {
407 array->Add(d->Read<T>());
408 }
409 return array;
410 }
411 };
412
413 template <typename T>
414 struct ReadTrait<const ZoneGrowableArray<T>&> {
417 }
418 };
419
420 // Specialization in case intptr_t is not mapped to intN_t.
421 template <typename T>
422 struct ReadTrait<T,
423 std::enable_if_t<std::is_same_v<intptr_t, T> &&
424 !std::is_same_v<intptr_t, int32_t> &&
425 !std::is_same_v<intptr_t, int64_t>>> {
426 static intptr_t Read(FlowGraphDeserializer* d) {
427#ifdef ARCH_IS_64_BIT
428 return d->Read<int64_t>();
429#else
430 return d->Read<int32_t>();
431#endif
432 }
433 };
434
435 // Specialization in case uintptr_t is not mapped to uintN_t.
436 template <typename T>
437 struct ReadTrait<T,
438 std::enable_if_t<std::is_same_v<uintptr_t, T> &&
439 !std::is_same_v<uintptr_t, uint32_t> &&
440 !std::is_same_v<uintptr_t, uint64_t>>> {
441 static uintptr_t Read(FlowGraphDeserializer* d) {
442#ifdef ARCH_IS_64_BIT
443 return d->Read<uint64_t>();
444#else
445 return d->Read<uint32_t>();
446#endif
447 }
448 };
449
450#define DECLARE_READ_TRAIT(type) \
451 template <typename T> \
452 struct ReadTrait<T, std::enable_if_t<std::is_same_v<type, T>>> { \
453 static type Read(FlowGraphDeserializer* d); \
454 };
456#undef DECLARE_READ_TRAIT
457
458 template <typename T>
459 T Read() {
460 return ReadTrait<T>::Read(this);
461 }
462
463 // Implementation of 'ReadRef' method, specialized for a particular type.
464 // This struct is used for the partial template instantiations below.
465 //
466 // Explicit (full) specializations of 'ReadRef' method are not provided as
467 // gcc doesn't support explicit template specializations of members of
468 // a non-template class
469 // (CWG 730 https://cplusplus.github.io/CWG/issues/730.html).
470 // The 2nd template argument is used to make all template instantiations
471 // partial as gcc doesn't support explicit (full) template specializations
472 // in class scope (CWG 727 https://cplusplus.github.io/CWG/issues/727.html).
473 template <typename T, class = void>
474 struct ReadRefTrait {};
475
476#define DECLARE_READ_REF_TRAIT(type) \
477 template <typename T> \
478 struct ReadRefTrait<T, std::enable_if_t<std::is_same_v<type, T>>> { \
479 static T ReadRef(FlowGraphDeserializer* d); \
480 };
482#undef DECLARE_READ_REF_TRAIT
483
484 template <typename T>
486 return ReadRefTrait<T>::ReadRef(this);
487 }
488
489 template <typename T>
491 const intptr_t len = Read<intptr_t>();
492 GrowableArray<T> array(len);
493 for (int i = 0; i < len; ++i) {
494 array.Add(ReadRef<T>());
495 }
496 return array;
497 }
498
499 private:
500 ClassPtr GetClassById(classid_t id) const;
501 const Object& ReadObjectImpl(intptr_t cid, intptr_t object_index);
502 void SetObjectAt(intptr_t object_index, const Object& object);
503 const Object& ReadObjectWithEnclosingTypes();
504
505 const ParsedFunction& parsed_function_;
506 ReadStream* stream_;
507 Zone* zone_;
508 Thread* thread_;
509 IsolateGroup* isolate_group_;
510
511 // Deserialized objects.
512 GraphEntryInstr* graph_entry_ = nullptr;
513 BlockEntryInstr* current_block_ = nullptr;
515 GrowableArray<Definition*> definitions_;
517 intptr_t object_counter_ = 0;
518};
519
520} // namespace dart
521
522#endif // RUNTIME_VM_COMPILER_BACKEND_IL_SERIALIZER_H_
GLenum type
void Add(const T &value)
intptr_t length() const
GraphEntryInstr * graph_entry() const
void set_block(intptr_t block_id, BlockEntryInstr *block)
void set_graph_entry(GraphEntryInstr *entry)
FlowGraphDeserializer(const ParsedFunction &parsed_function, ReadStream *stream)
BlockEntryInstr * block(intptr_t block_id) const
IsolateGroup * isolate_group() const
Definition * definition(intptr_t ssa_temp_index) const
BlockEntryInstr * current_block() const
const ParsedFunction & parsed_function() const
void set_definition(intptr_t ssa_temp_index, Definition *def)
void set_current_block(BlockEntryInstr *block)
GrowableArray< T > ReadGrowableArrayOfRefs()
ReadStream * stream() const
IsolateGroup * isolate_group() const
void WriteGrowableArrayOfRefs(const GrowableArray< T > &array)
BaseWriteStream * stream() const
void Write(typename WriteTrait< T >::ArgType x)
FlowGraphSerializer(NonStreamingWriteStream *stream)
void WriteFlowGraph(const FlowGraph &flow_graph, const ZoneGrowableArray< Definition * > &detached_defs)
Thread * thread() const
#define ASSERT(E)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
static bool b
struct MyStruct s
#define DECLARE_READ_TRAIT(type)
#define IL_SERIALIZABLE_REF_TYPE_LIST(V)
#define DECLARE_WRITE_TRAIT(type)
#define DECLARE_READ_REF_TRAIT(type)
#define IL_SERIALIZABLE_TYPE_LIST(V)
Definition: il_serializer.h:71
#define DECLARE_WRITE_REF_TRAIT(type)
double x
Definition: dart_vm.cc:33
constexpr int kMaxInt
Definition: globals.h:490
int32_t classid_t
Definition: globals.h:524
const intptr_t cid
Definition: ref_ptr.h:256
#define T
Definition: precompiler.cc:65
BlockEntryInstr * ReadRef(FlowGraphDeserializer *d)
static GrowableArray< T > Read(FlowGraphDeserializer *d)
static ZoneGrowableArray< T > * Read(FlowGraphDeserializer *d)
static const GrowableArray< T > & Read(FlowGraphDeserializer *d)
static const ZoneGrowableArray< T > & Read(FlowGraphDeserializer *d)
const AbstractType * Read(FlowGraphDeserializer *d)
void WriteRef(FlowGraphSerializer *s, BlockEntryInstr *x)
static void Write(FlowGraphSerializer *s, ArgType x)
static void Write(FlowGraphSerializer *s, ArgType x)
static void Write(FlowGraphSerializer *s, ArgType x)
void Write(FlowGraphSerializer *s, const AbstractType *x)