Flutter Engine
The Flutter Engine
kernel_binary.h
Go to the documentation of this file.
1// Copyright (c) 2017, 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_KERNEL_BINARY_H_
6#define RUNTIME_VM_KERNEL_BINARY_H_
7
8#if !defined(DART_PRECOMPILED_RUNTIME)
9
10#include "platform/unaligned.h"
11#include "vm/kernel.h"
12#include "vm/object.h"
13
14namespace dart {
15namespace kernel {
16
17// Keep in sync with package:kernel/lib/binary/tag.dart,
18// package:kernel/binary.md.
19
20static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
21static const uint32_t kSupportedKernelFormatVersion = 119;
22
23// Keep in sync with package:kernel/lib/binary/tag.dart
24#define KERNEL_TAG_LIST(V) \
25 V(Nothing, 0) \
26 V(Something, 1) \
27 V(Class, 2) \
28 V(Extension, 115) \
29 V(ExtensionTypeDeclaration, 85) \
30 V(FunctionNode, 3) \
31 V(Field, 4) \
32 V(Constructor, 5) \
33 V(Procedure, 6) \
34 V(InvalidInitializer, 7) \
35 V(FieldInitializer, 8) \
36 V(SuperInitializer, 9) \
37 V(RedirectingInitializer, 10) \
38 V(LocalInitializer, 11) \
39 V(AssertInitializer, 12) \
40 V(CheckLibraryIsLoaded, 13) \
41 V(LoadLibrary, 14) \
42 V(EqualsNull, 15) \
43 V(EqualsCall, 16) \
44 V(StaticTearOff, 17) \
45 V(ConstStaticInvocation, 18) \
46 V(InvalidExpression, 19) \
47 V(VariableGet, 20) \
48 V(VariableSet, 21) \
49 V(AbstractSuperPropertyGet, 22) \
50 V(AbstractSuperPropertySet, 23) \
51 V(SuperPropertyGet, 24) \
52 V(SuperPropertySet, 25) \
53 V(StaticGet, 26) \
54 V(StaticSet, 27) \
55 V(AbstractSuperMethodInvocation, 28) \
56 V(SuperMethodInvocation, 29) \
57 V(StaticInvocation, 30) \
58 V(ConstructorInvocation, 31) \
59 V(ConstConstructorInvocation, 32) \
60 V(Not, 33) \
61 V(NullCheck, 117) \
62 V(LogicalExpression, 34) \
63 V(ConditionalExpression, 35) \
64 V(StringConcatenation, 36) \
65 V(ListConcatenation, 111) \
66 V(SetConcatenation, 112) \
67 V(MapConcatenation, 113) \
68 V(InstanceCreation, 114) \
69 V(FileUriExpression, 116) \
70 V(IsExpression, 37) \
71 V(AsExpression, 38) \
72 V(StringLiteral, 39) \
73 V(DoubleLiteral, 40) \
74 V(TrueLiteral, 41) \
75 V(FalseLiteral, 42) \
76 V(NullLiteral, 43) \
77 V(SymbolLiteral, 44) \
78 V(TypeLiteral, 45) \
79 V(ThisExpression, 46) \
80 V(Rethrow, 47) \
81 V(Throw, 48) \
82 V(ListLiteral, 49) \
83 V(SetLiteral, 109) \
84 V(MapLiteral, 50) \
85 V(AwaitExpression, 51) \
86 V(FunctionExpression, 52) \
87 V(Let, 53) \
88 V(BlockExpression, 82) \
89 V(Instantiation, 54) \
90 V(PositiveIntLiteral, 55) \
91 V(NegativeIntLiteral, 56) \
92 V(BigIntLiteral, 57) \
93 V(ConstListLiteral, 58) \
94 V(ConstSetLiteral, 110) \
95 V(ConstMapLiteral, 59) \
96 V(ConstructorTearOff, 60) \
97 V(TypedefTearOff, 83) \
98 V(RedirectingFactoryTearOff, 84) \
99 V(RecordIndexGet, 101) \
100 V(RecordNameGet, 102) \
101 V(RecordLiteral, 104) \
102 V(ConstRecordLiteral, 105) \
103 V(ExpressionStatement, 61) \
104 V(Block, 62) \
105 V(EmptyStatement, 63) \
106 V(AssertStatement, 64) \
107 V(LabeledStatement, 65) \
108 V(BreakStatement, 66) \
109 V(WhileStatement, 67) \
110 V(DoStatement, 68) \
111 V(ForStatement, 69) \
112 V(ForInStatement, 70) \
113 V(SwitchStatement, 71) \
114 V(ContinueSwitchStatement, 72) \
115 V(IfStatement, 73) \
116 V(ReturnStatement, 74) \
117 V(TryCatch, 75) \
118 V(TryFinally, 76) \
119 V(YieldStatement, 77) \
120 V(VariableDeclaration, 78) \
121 V(FunctionDeclaration, 79) \
122 V(AsyncForInStatement, 80) \
123 V(AssertBlock, 81) \
124 V(TypedefType, 87) \
125 V(InvalidType, 90) \
126 V(DynamicType, 91) \
127 V(VoidType, 92) \
128 V(InterfaceType, 93) \
129 V(FunctionType, 94) \
130 V(TypeParameterType, 95) \
131 V(SimpleInterfaceType, 96) \
132 V(SimpleFunctionType, 97) \
133 V(NeverType, 98) \
134 V(IntersectionType, 99) \
135 V(RecordType, 100) \
136 V(ExtensionType, 103) \
137 V(ConstantExpression, 106) \
138 V(FutureOrType, 107) \
139 V(FileUriConstantExpression, 108) \
140 V(InstanceGet, 118) \
141 V(InstanceSet, 119) \
142 V(InstanceInvocation, 120) \
143 V(InstanceGetterInvocation, 89) \
144 V(InstanceTearOff, 121) \
145 V(DynamicGet, 122) \
146 V(DynamicSet, 123) \
147 V(DynamicInvocation, 124) \
148 V(FunctionInvocation, 125) \
149 V(FunctionTearOff, 126) \
150 V(LocalFunctionInvocation, 127) \
151 V(AndPattern, 128) \
152 V(AssignedVariablePattern, 129) \
153 V(CastPattern, 130) \
154 V(ConstantPattern, 131) \
155 V(InvalidPattern, 132) \
156 V(ListPattern, 133) \
157 V(MapPattern, 134) \
158 V(NamedPattern, 135) \
159 V(NullAssertPattern, 136) \
160 V(NullCheckPattern, 137) \
161 V(ObjectPattern, 138) \
162 V(OrPattern, 139) \
163 V(RecordPattern, 140) \
164 V(RelationalPattern, 141) \
165 V(RestPattern, 142) \
166 V(VariablePattern, 143) \
167 V(WildcardPattern, 144) \
168 V(MapPatternEntry, 145) \
169 V(MapPatternRestEntry, 146) \
170 V(PatternSwitchStatement, 147) \
171 V(SwitchExpression, 148) \
172 V(IfCaseStatement, 149) \
173 V(PatternAssignment, 150) \
174 V(PatternVariableDeclaration, 151) \
175 V(NullType, 152) \
176 V(SpecializedVariableGet, 224) \
177 V(SpecializedVariableSet, 232) \
178 V(SpecializedIntLiteral, 240)
179
180static constexpr intptr_t kSpecializedTagHighBits = 0xe0;
181static constexpr intptr_t kSpecializedTagMask = 0xf8;
182static constexpr intptr_t kSpecializedPayloadMask = 0x7;
183
184enum Tag {
185#define DECLARE(Name, value) k##Name = value,
187#undef DECLARE
188};
189
190// Keep in sync with package:kernel/lib/binary/tag.dart
205 // These constants are not expected to be seen by the VM, because all
206 // constants are fully evaluated.
212};
213
214// Keep in sync with package:kernel/lib/ast.dart
215enum class KernelNullability : int8_t {
216 kUndetermined = 0,
217 kNullable = 1,
218 kNonNullable = 2,
219 kLegacy = 3,
220};
221
222// Keep in sync with package:kernel/lib/ast.dart
229};
230
231// Keep in sync with package:kernel/lib/ast.dart
237};
238
239// Keep in sync with package:kernel/lib/ast.dart
243};
244
245// Keep in sync with package:kernel/lib/ast.dart
248};
249
250// Keep in sync with package:kernel/lib/ast.dart
253};
254
255// Keep in sync with package:kernel/lib/ast.dart
258};
259
260// Keep in sync with package:kernel/lib/ast.dart
261enum class NamedTypeFlags : uint8_t {
262 kIsRequired = 1 << 0,
263};
264
265// Keep in sync with package:kernel/lib/ast.dart
267 kFunction,
270 kNullable,
271};
272
273static constexpr int SpecializedIntLiteralBias = 3;
274static constexpr int LibraryCountFieldCountFromEnd = 1;
275static constexpr int KernelFormatVersionOffset = 4;
277
278static constexpr int HeaderSize = 8; // 'magic', 'formatVersion'.
279
280class Reader : public ValueObject {
281 public:
283 : thread_(Thread::Current()), typed_data_(&typed_data) {
284 Init();
285 }
286
287 uint32_t ReadFromIndex(intptr_t end_offset,
288 intptr_t fields_before,
289 intptr_t list_size,
290 intptr_t list_index) {
291 intptr_t org_offset = offset();
292 uint32_t result =
293 ReadFromIndexNoReset(end_offset, fields_before, list_size, list_index);
294 offset_ = org_offset;
295 return result;
296 }
297
298 uint32_t ReadUInt32At(intptr_t offset) const {
299 ASSERT((size_ >= 4) && (offset >= 0) && (offset <= size_ - 4));
300 uint32_t value =
301 LoadUnaligned(reinterpret_cast<const uint32_t*>(raw_buffer_ + offset));
303 }
304
305 uint32_t ReadFromIndexNoReset(intptr_t end_offset,
306 intptr_t fields_before,
307 intptr_t list_size,
308 intptr_t list_index) {
309 offset_ = end_offset - (fields_before + list_size - list_index) * 4;
310 return ReadUInt32();
311 }
312
313 uint32_t ReadUInt32() {
314 uint32_t value = ReadUInt32At(offset_);
315 offset_ += 4;
316 return value;
317 }
318
319 double ReadDouble() {
320 ASSERT((size_ >= 8) && (offset_ >= 0) && (offset_ <= size_ - 8));
321 double value =
322 LoadUnaligned(reinterpret_cast<const double*>(&raw_buffer_[offset_]));
323 offset_ += 8;
324 return value;
325 }
326
327 uint32_t ReadUInt() {
328 ASSERT((size_ >= 1) && (offset_ >= 0) && (offset_ <= size_ - 1));
329
330 const uint8_t* buffer = raw_buffer_;
331 uword byte0 = buffer[offset_];
332 if ((byte0 & 0x80) == 0) {
333 // 0...
334 offset_++;
335 return byte0;
336 } else if ((byte0 & 0xc0) == 0x80) {
337 // 10...
338 ASSERT((size_ >= 2) && (offset_ >= 0) && (offset_ <= size_ - 2));
339 uint32_t value =
340 ((byte0 & ~static_cast<uword>(0x80)) << 8) | (buffer[offset_ + 1]);
341 offset_ += 2;
342 return value;
343 } else {
344 // 11...
345 ASSERT((size_ >= 4) && (offset_ >= 0) && (offset_ <= size_ - 4));
346 uint32_t value = ((byte0 & ~static_cast<uword>(0xc0)) << 24) |
347 (buffer[offset_ + 1] << 16) |
348 (buffer[offset_ + 2] << 8) | (buffer[offset_ + 3] << 0);
349 offset_ += 4;
350 return value;
351 }
352 }
353
354 intptr_t ReadSLEB128() {
355 ReadStream stream(raw_buffer_, size_, offset_);
356 const intptr_t result = stream.ReadSLEB128();
357 offset_ = stream.Position();
358 return result;
359 }
360
362 ReadStream stream(raw_buffer_, size_, offset_);
363 const int64_t result = stream.ReadSLEB128<int64_t>();
364 offset_ = stream.Position();
365 return result;
366 }
367
368 /**
369 * Read and return a TokenPosition from this reader.
370 */
372 // Position is saved as unsigned,
373 // but actually ranges from -1 and up (thus the -1)
374 intptr_t value = ReadUInt() - 1;
376 max_position_ = TokenPosition::Max(max_position_, result);
377 min_position_ = TokenPosition::Min(min_position_, result);
378 return result;
379 }
380
381 intptr_t ReadListLength() { return ReadUInt(); }
382
383 uint8_t ReadByte() { return raw_buffer_[offset_++]; }
384
385 uint8_t PeekByte() { return raw_buffer_[offset_]; }
386
387 void ReadBytes(uint8_t* buffer, uint8_t size) {
388 for (int i = 0; i < size; i++) {
389 buffer[i] = ReadByte();
390 }
391 }
392
393 bool ReadBool() { return (ReadByte() & 1) == 1; }
394
395 uint8_t ReadFlags() { return ReadByte(); }
396
397 static const char* TagName(Tag tag);
398
399 Tag ReadTag(uint8_t* payload = nullptr) {
400 uint8_t byte = ReadByte();
401 bool has_payload =
403 if (has_payload) {
404 if (payload != nullptr) {
405 *payload = byte & kSpecializedPayloadMask;
406 }
407 return static_cast<Tag>(byte & kSpecializedTagMask);
408 } else {
409 return static_cast<Tag>(byte);
410 }
411 }
412
413 Tag PeekTag(uint8_t* payload = nullptr) {
414 uint8_t byte = PeekByte();
415 bool has_payload =
417 if (has_payload) {
418 if (payload != nullptr) {
419 *payload = byte & kSpecializedPayloadMask;
420 }
421 return static_cast<Tag>(byte & kSpecializedTagMask);
422 } else {
423 return static_cast<Tag>(byte);
424 }
425 }
426
428 switch (kernel_nullability) {
435 FATAL("Legacy nullability is not supported.");
436 }
437 UNREACHABLE();
438 }
439
441 const uint8_t byte = ReadByte();
442 return ConvertNullability(static_cast<KernelNullability>(byte));
443 }
444
446 uint8_t byte = ReadByte();
447 return static_cast<Variance>(byte);
448 }
449
450 void EnsureEnd() {
451 if (offset_ != size_) {
452 FATAL(
453 "Reading Kernel file: Expected to be at EOF "
454 "(offset: %" Pd ", size: %" Pd ")",
455 offset_, size_);
456 }
457 }
458
459 // The largest position read yet (since last reset).
460 // This is automatically updated when calling ReadPosition,
461 // but can be overwritten (e.g. via the PositionScope class).
462 TokenPosition max_position() { return max_position_; }
463 // The smallest position read yet (since last reset).
464 // This is automatically updated when calling ReadPosition,
465 // but can be overwritten (e.g. via the PositionScope class).
466 TokenPosition min_position() { return min_position_; }
467
468 // A canonical name reference of -1 indicates none (for optional names), not
469 // the root name as in the canonical name table.
471
472 const TypedDataBase* typed_data() { return typed_data_; }
473
474 intptr_t offset() const { return offset_; }
475 void set_offset(intptr_t offset) {
476 ASSERT(offset < size_);
477 offset_ = offset;
478 }
479 intptr_t size() const { return size_; }
480
481 TypedDataViewPtr ViewFromTo(intptr_t start, intptr_t end) {
482 return typed_data_->ViewFromTo(start, end, Heap::kOld);
483 }
484
485 const uint8_t* BufferAt(intptr_t offset) {
486 ASSERT((offset >= 0) && (offset < size_));
487 return &raw_buffer_[offset];
488 }
489
490 TypedDataPtr ReadLineStartsData(intptr_t line_start_count);
491
492 private:
493 friend class Program;
496
497 Reader(const uint8_t* buffer, intptr_t size)
498 : thread_(nullptr), raw_buffer_(buffer), size_(size) {}
499
500 void Init() {
501 ASSERT(typed_data_->IsExternalOrExternalView());
502 raw_buffer_ = reinterpret_cast<uint8_t*>(typed_data_->DataAddr(0));
503 size_ = typed_data_->LengthInBytes();
504 offset_ = 0;
505 }
506
507 Thread* thread_ = nullptr;
508
509 // A external typed data or a view on an external typed data.
510 const TypedDataBase* typed_data_ = nullptr;
511
512 // The raw data size/length of [typed_data_].
513 const uint8_t* raw_buffer_ = nullptr;
514 intptr_t size_ = 0;
515
516 intptr_t offset_ = 0;
517 TokenPosition max_position_ = TokenPosition::kNoSource;
518 TokenPosition min_position_ = TokenPosition::kNoSource;
519 intptr_t current_script_id_ = -1;
520
521 friend class PositionScope;
522 friend class Program;
523};
524
525// A helper class that saves the current reader position, goes to another reader
526// position, and upon destruction, resets to the original reader position.
528 public:
529 AlternativeReadingScope(Reader* reader, intptr_t new_position)
530 : reader_(reader), saved_offset_(reader_->offset_) {
531 reader_->offset_ = new_position;
532 }
533
535 : reader_(reader), saved_offset_(reader_->offset_) {}
536
537 ~AlternativeReadingScope() { reader_->offset_ = saved_offset_; }
538
539 intptr_t saved_offset() { return saved_offset_; }
540
541 private:
542 Reader* const reader_;
543 const intptr_t saved_offset_;
544
545 DISALLOW_COPY_AND_ASSIGN(AlternativeReadingScope);
546};
547
548// Similar to AlternativeReadingScope, but also switches reading to another
549// typed data array.
551 public:
553 const TypedDataBase* new_typed_data,
554 intptr_t new_position)
555 : reader_(reader),
556 saved_size_(reader_->size_),
557 saved_raw_buffer_(reader_->raw_buffer_),
558 saved_typed_data_(reader_->typed_data_),
559 saved_offset_(reader_->offset_) {
560 reader_->typed_data_ = new_typed_data;
561 reader_->Init();
562 reader_->offset_ = new_position;
563 }
564
566 reader_->raw_buffer_ = saved_raw_buffer_;
567 reader_->typed_data_ = saved_typed_data_;
568 reader_->size_ = saved_size_;
569 reader_->offset_ = saved_offset_;
570 }
571
572 intptr_t saved_offset() { return saved_offset_; }
573
574 private:
575 Reader* reader_;
576 intptr_t saved_size_;
577 const uint8_t* saved_raw_buffer_;
578 const TypedDataBase* saved_typed_data_;
579 intptr_t saved_offset_;
580
581 DISALLOW_COPY_AND_ASSIGN(AlternativeReadingScopeWithNewData);
582};
583
584// A helper class that resets the readers min and max positions both upon
585// initialization and upon destruction, i.e. when created the min an max
586// positions will be reset to "noSource", when destructing the min and max will
587// be reset to have they value they would have had, if they hadn't been reset in
588// the first place.
590 public:
591 explicit PositionScope(Reader* reader)
592 : reader_(reader),
593 min_(reader->min_position_),
594 max_(reader->max_position_) {
595 reader->min_position_ = reader->max_position_ = TokenPosition::kNoSource;
596 }
597
599 reader_->min_position_ = TokenPosition::Min(reader_->min_position_, min_);
600 reader_->max_position_ = TokenPosition::Max(reader_->max_position_, max_);
601 }
602
603 private:
604 Reader* reader_;
605 TokenPosition min_;
606 TokenPosition max_;
607
608 DISALLOW_COPY_AND_ASSIGN(PositionScope);
609};
610
611} // namespace kernel
612} // namespace dart
613
614#endif // !defined(DART_PRECOMPILED_RUNTIME)
615#endif // RUNTIME_VM_KERNEL_BINARY_H_
#define UNREACHABLE()
Definition: assert.h:248
@ kOld
Definition: heap.h:39
static const TokenPosition & Min(const TokenPosition &a, const TokenPosition &b)
static TokenPosition Deserialize(int32_t value)
static const TokenPosition & Max(const TokenPosition &a, const TokenPosition &b)
TypedDataViewPtr ViewFromTo(intptr_t start, intptr_t end, Heap::Space space=Heap::kNew) const
Definition: object.cc:25682
intptr_t LengthInBytes() const
Definition: object.h:11523
bool IsExternalOrExternalView() const
Definition: object.cc:25672
void * DataAddr(intptr_t byte_offset) const
Definition: object.h:11571
static uint32_t BigEndianToHost32(uint32_t be_value)
Definition: utils.h:518
AlternativeReadingScopeWithNewData(Reader *reader, const TypedDataBase *new_typed_data, intptr_t new_position)
AlternativeReadingScope(Reader *reader, intptr_t new_position)
PositionScope(Reader *reader)
const TypedDataBase * typed_data()
static Nullability ConvertNullability(KernelNullability kernel_nullability)
TokenPosition ReadPosition()
uint32_t ReadFromIndexNoReset(intptr_t end_offset, intptr_t fields_before, intptr_t list_size, intptr_t list_index)
intptr_t offset() const
void set_offset(intptr_t offset)
TokenPosition min_position()
TokenPosition max_position()
uint32_t ReadUInt32At(intptr_t offset) const
Reader(const TypedDataBase &typed_data)
TypedDataViewPtr ViewFromTo(intptr_t start, intptr_t end)
uint32_t ReadFromIndex(intptr_t end_offset, intptr_t fields_before, intptr_t list_size, intptr_t list_index)
intptr_t size() const
void ReadBytes(uint8_t *buffer, uint8_t size)
TypedDataPtr ReadLineStartsData(intptr_t line_start_count)
Nullability ReadNullability()
Tag ReadTag(uint8_t *payload=nullptr)
int64_t ReadSLEB128AsInt64()
static const char * TagName(Tag tag)
Tag PeekTag(uint8_t *payload=nullptr)
NameIndex ReadCanonicalNameReference()
const uint8_t * BufferAt(intptr_t offset)
intptr_t ReadListLength()
#define ASSERT(E)
#define FATAL(error)
glong glong end
uint8_t value
GAsyncResult * result
void Init()
#define DECLARE(Name, value)
#define KERNEL_TAG_LIST(V)
Definition: kernel_binary.h:24
@ kConstructorTearOffConstant
@ kRedirectingFactoryTearOffConstant
static constexpr int SpecializedIntLiteralBias
@ kYieldStatementFlagYieldStar
static const uint32_t kMagicProgramFile
Definition: kernel_binary.h:20
static constexpr int SourceTableFieldCountFromFirstLibraryOffset
static constexpr int LibraryCountFieldCountFromEnd
static constexpr intptr_t kSpecializedPayloadMask
static constexpr intptr_t kSpecializedTagHighBits
static const uint32_t kSupportedKernelFormatVersion
Definition: kernel_binary.h:21
@ kDynamicInvocationFlagImplicitCall
static constexpr intptr_t kSpecializedTagMask
@ kInstanceInvocationFlagBoundsSafe
@ kInstanceInvocationFlagInvariant
static constexpr int HeaderSize
@ kAsExpressionFlagUnchecked
@ kAsExpressionFlagCovarianceCheck
@ kAsExpressionFlagForDynamic
@ kAsExpressionFlagTypeError
static constexpr int KernelFormatVersionOffset
Definition: dart_vm.cc:33
Nullability
Definition: object.h:1112
uintptr_t uword
Definition: globals.h:501
static T LoadUnaligned(const T *ptr)
Definition: unaligned.h:14
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
#define Pd
Definition: globals.h:408