Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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 = 117;
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
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
230
231// Keep in sync with package:kernel/lib/ast.dart
239
240// Keep in sync with package:kernel/lib/ast.dart
244
245// Keep in sync with package:kernel/lib/ast.dart
250
251// Keep in sync with package:kernel/lib/ast.dart
255
256// Keep in sync with package:kernel/lib/ast.dart
260
261// Keep in sync with package:kernel/lib/ast.dart
265
266// Keep in sync with package:kernel/lib/ast.dart
267enum class NamedTypeFlags : uint8_t {
268 kIsRequired = 1 << 0,
269};
270
271// Keep in sync with package:kernel/lib/ast.dart
273 kFunction,
276 kNullable,
277};
278
279static constexpr int SpecializedIntLiteralBias = 3;
280static constexpr int LibraryCountFieldCountFromEnd = 1;
281static constexpr int KernelFormatVersionOffset = 4;
283
284static constexpr int HeaderSize = 8; // 'magic', 'formatVersion'.
285
286class Reader : public ValueObject {
287 public:
289 : thread_(Thread::Current()), typed_data_(&typed_data) {
290 Init();
291 }
292
293 uint32_t ReadFromIndex(intptr_t end_offset,
294 intptr_t fields_before,
295 intptr_t list_size,
296 intptr_t list_index) {
297 intptr_t org_offset = offset();
298 uint32_t result =
299 ReadFromIndexNoReset(end_offset, fields_before, list_size, list_index);
300 offset_ = org_offset;
301 return result;
302 }
303
304 uint32_t ReadUInt32At(intptr_t offset) const {
305 ASSERT((size_ >= 4) && (offset >= 0) && (offset <= size_ - 4));
306 uint32_t value =
307 LoadUnaligned(reinterpret_cast<const uint32_t*>(raw_buffer_ + offset));
309 }
310
311 uint32_t ReadFromIndexNoReset(intptr_t end_offset,
312 intptr_t fields_before,
313 intptr_t list_size,
314 intptr_t list_index) {
315 offset_ = end_offset - (fields_before + list_size - list_index) * 4;
316 return ReadUInt32();
317 }
318
319 uint32_t ReadUInt32() {
320 uint32_t value = ReadUInt32At(offset_);
321 offset_ += 4;
322 return value;
323 }
324
325 double ReadDouble() {
326 ASSERT((size_ >= 8) && (offset_ >= 0) && (offset_ <= size_ - 8));
327 double value =
328 LoadUnaligned(reinterpret_cast<const double*>(&raw_buffer_[offset_]));
329 offset_ += 8;
330 return value;
331 }
332
333 uint32_t ReadUInt() {
334 ASSERT((size_ >= 1) && (offset_ >= 0) && (offset_ <= size_ - 1));
335
336 const uint8_t* buffer = raw_buffer_;
337 uword byte0 = buffer[offset_];
338 if ((byte0 & 0x80) == 0) {
339 // 0...
340 offset_++;
341 return byte0;
342 } else if ((byte0 & 0xc0) == 0x80) {
343 // 10...
344 ASSERT((size_ >= 2) && (offset_ >= 0) && (offset_ <= size_ - 2));
345 uint32_t value =
346 ((byte0 & ~static_cast<uword>(0x80)) << 8) | (buffer[offset_ + 1]);
347 offset_ += 2;
348 return value;
349 } else {
350 // 11...
351 ASSERT((size_ >= 4) && (offset_ >= 0) && (offset_ <= size_ - 4));
352 uint32_t value = ((byte0 & ~static_cast<uword>(0xc0)) << 24) |
353 (buffer[offset_ + 1] << 16) |
354 (buffer[offset_ + 2] << 8) | (buffer[offset_ + 3] << 0);
355 offset_ += 4;
356 return value;
357 }
358 }
359
360 intptr_t ReadSLEB128() {
361 ReadStream stream(raw_buffer_, size_, offset_);
362 const intptr_t result = stream.ReadSLEB128();
363 offset_ = stream.Position();
364 return result;
365 }
366
368 ReadStream stream(raw_buffer_, size_, offset_);
369 const int64_t result = stream.ReadSLEB128<int64_t>();
370 offset_ = stream.Position();
371 return result;
372 }
373
374 /**
375 * Read and return a TokenPosition from this reader.
376 */
378 // Position is saved as unsigned,
379 // but actually ranges from -1 and up (thus the -1)
380 intptr_t value = ReadUInt() - 1;
382 max_position_ = TokenPosition::Max(max_position_, result);
383 min_position_ = TokenPosition::Min(min_position_, result);
384 return result;
385 }
386
387 intptr_t ReadListLength() { return ReadUInt(); }
388
389 uint8_t ReadByte() { return raw_buffer_[offset_++]; }
390
391 uint8_t PeekByte() { return raw_buffer_[offset_]; }
392
393 void ReadBytes(uint8_t* buffer, uint8_t size) {
394 for (int i = 0; i < size; i++) {
395 buffer[i] = ReadByte();
396 }
397 }
398
399 bool ReadBool() { return (ReadByte() & 1) == 1; }
400
401 uint8_t ReadFlags() { return ReadByte(); }
402
403 static const char* TagName(Tag tag);
404
405 Tag ReadTag(uint8_t* payload = nullptr) {
406 uint8_t byte = ReadByte();
407 bool has_payload =
409 if (has_payload) {
410 if (payload != nullptr) {
411 *payload = byte & kSpecializedPayloadMask;
412 }
413 return static_cast<Tag>(byte & kSpecializedTagMask);
414 } else {
415 return static_cast<Tag>(byte);
416 }
417 }
418
419 Tag PeekTag(uint8_t* payload = nullptr) {
420 uint8_t byte = PeekByte();
421 bool has_payload =
423 if (has_payload) {
424 if (payload != nullptr) {
425 *payload = byte & kSpecializedPayloadMask;
426 }
427 return static_cast<Tag>(byte & kSpecializedTagMask);
428 } else {
429 return static_cast<Tag>(byte);
430 }
431 }
432
434 switch (kernel_nullability) {
442 }
443 UNREACHABLE();
444 }
445
447 const uint8_t byte = ReadByte();
448 return ConvertNullability(static_cast<KernelNullability>(byte));
449 }
450
452 uint8_t byte = ReadByte();
453 return static_cast<Variance>(byte);
454 }
455
456 void EnsureEnd() {
457 if (offset_ != size_) {
458 FATAL(
459 "Reading Kernel file: Expected to be at EOF "
460 "(offset: %" Pd ", size: %" Pd ")",
461 offset_, size_);
462 }
463 }
464
465 // The largest position read yet (since last reset).
466 // This is automatically updated when calling ReadPosition,
467 // but can be overwritten (e.g. via the PositionScope class).
468 TokenPosition max_position() { return max_position_; }
469 // The smallest position read yet (since last reset).
470 // This is automatically updated when calling ReadPosition,
471 // but can be overwritten (e.g. via the PositionScope class).
472 TokenPosition min_position() { return min_position_; }
473
474 // A canonical name reference of -1 indicates none (for optional names), not
475 // the root name as in the canonical name table.
477
478 const TypedDataBase* typed_data() { return typed_data_; }
479
480 intptr_t offset() const { return offset_; }
481 void set_offset(intptr_t offset) {
482 ASSERT(offset < size_);
483 offset_ = offset;
484 }
485 intptr_t size() const { return size_; }
486
487 TypedDataViewPtr ViewFromTo(intptr_t start, intptr_t end) {
488 return typed_data_->ViewFromTo(start, end, Heap::kOld);
489 }
490
491 const uint8_t* BufferAt(intptr_t offset) {
492 ASSERT((offset >= 0) && (offset < size_));
493 return &raw_buffer_[offset];
494 }
495
496 TypedDataPtr ReadLineStartsData(intptr_t line_start_count);
497
498 private:
499 friend class Program;
502
503 Reader(const uint8_t* buffer, intptr_t size)
504 : thread_(nullptr), raw_buffer_(buffer), size_(size) {}
505
506 void Init() {
507 ASSERT(typed_data_->IsExternalOrExternalView());
508 raw_buffer_ = reinterpret_cast<uint8_t*>(typed_data_->DataAddr(0));
509 size_ = typed_data_->LengthInBytes();
510 offset_ = 0;
511 }
512
513 Thread* thread_ = nullptr;
514
515 // A external typed data or a view on an external typed data.
516 const TypedDataBase* typed_data_ = nullptr;
517
518 // The raw data size/length of [typed_data_].
519 const uint8_t* raw_buffer_ = nullptr;
520 intptr_t size_ = 0;
521
522 intptr_t offset_ = 0;
523 TokenPosition max_position_ = TokenPosition::kNoSource;
524 TokenPosition min_position_ = TokenPosition::kNoSource;
525 intptr_t current_script_id_ = -1;
526
527 friend class PositionScope;
528 friend class Program;
529};
530
531// A helper class that saves the current reader position, goes to another reader
532// position, and upon destruction, resets to the original reader position.
534 public:
535 AlternativeReadingScope(Reader* reader, intptr_t new_position)
536 : reader_(reader), saved_offset_(reader_->offset_) {
537 reader_->offset_ = new_position;
538 }
539
541 : reader_(reader), saved_offset_(reader_->offset_) {}
542
543 ~AlternativeReadingScope() { reader_->offset_ = saved_offset_; }
544
545 intptr_t saved_offset() { return saved_offset_; }
546
547 private:
548 Reader* const reader_;
549 const intptr_t saved_offset_;
550
552};
553
554// Similar to AlternativeReadingScope, but also switches reading to another
555// typed data array.
557 public:
559 const TypedDataBase* new_typed_data,
560 intptr_t new_position)
561 : reader_(reader),
562 saved_size_(reader_->size_),
563 saved_raw_buffer_(reader_->raw_buffer_),
564 saved_typed_data_(reader_->typed_data_),
565 saved_offset_(reader_->offset_) {
566 reader_->typed_data_ = new_typed_data;
567 reader_->Init();
568 reader_->offset_ = new_position;
569 }
570
572 reader_->raw_buffer_ = saved_raw_buffer_;
573 reader_->typed_data_ = saved_typed_data_;
574 reader_->size_ = saved_size_;
575 reader_->offset_ = saved_offset_;
576 }
577
578 intptr_t saved_offset() { return saved_offset_; }
579
580 private:
581 Reader* reader_;
582 intptr_t saved_size_;
583 const uint8_t* saved_raw_buffer_;
584 const TypedDataBase* saved_typed_data_;
585 intptr_t saved_offset_;
586
588};
589
590// A helper class that resets the readers min and max positions both upon
591// initialization and upon destruction, i.e. when created the min an max
592// positions will be reset to "noSource", when destructing the min and max will
593// be reset to have they value they would have had, if they hadn't been reset in
594// the first place.
596 public:
597 explicit PositionScope(Reader* reader)
598 : reader_(reader),
599 min_(reader->min_position_),
600 max_(reader->max_position_) {
601 reader->min_position_ = reader->max_position_ = TokenPosition::kNoSource;
602 }
603
605 reader_->min_position_ = TokenPosition::Min(reader_->min_position_, min_);
606 reader_->max_position_ = TokenPosition::Max(reader_->max_position_, max_);
607 }
608
609 private:
610 Reader* reader_;
611 TokenPosition min_;
612 TokenPosition max_;
613
615};
616
617} // namespace kernel
618} // namespace dart
619
620#endif // !defined(DART_PRECOMPILED_RUNTIME)
621#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:25761
intptr_t LengthInBytes() const
Definition object.h:11497
bool IsExternalOrExternalView() const
Definition object.cc:25751
void * DataAddr(intptr_t byte_offset) const
Definition object.h:11545
static uint32_t BigEndianToHost32(uint32_t be_value)
Definition utils.h:503
AlternativeReadingScopeWithNewData(Reader *reader, const TypedDataBase *new_typed_data, intptr_t new_position)
AlternativeReadingScope(Reader *reader, intptr_t new_position)
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)
static const char * TagName(Tag tag)
Tag PeekTag(uint8_t *payload=nullptr)
NameIndex ReadCanonicalNameReference()
const uint8_t * BufferAt(intptr_t offset)
#define ASSERT(E)
#define FATAL(error)
glong glong end
static const uint8_t buffer[]
uint8_t value
GAsyncResult * result
void Init()
#define DECLARE(Name, value)
#define KERNEL_TAG_LIST(V)
@ kConstructorTearOffConstant
@ kRedirectingFactoryTearOffConstant
static constexpr int SpecializedIntLiteralBias
@ kYieldStatementFlagYieldStar
static const uint32_t kMagicProgramFile
static constexpr int SourceTableFieldCountFromFirstLibraryOffset
static constexpr int LibraryCountFieldCountFromEnd
static constexpr intptr_t kSpecializedPayloadMask
static constexpr intptr_t kSpecializedTagHighBits
static const uint32_t kSupportedKernelFormatVersion
@ kDynamicInvocationFlagImplicitCall
static constexpr intptr_t kSpecializedTagMask
@ kInstanceInvocationFlagBoundsSafe
@ kInstanceInvocationFlagInvariant
static constexpr int HeaderSize
@ kAsExpressionFlagCovarianceCheck
@ kAsExpressionFlagForDynamic
static constexpr int KernelFormatVersionOffset
Nullability
Definition object.h:1112
uintptr_t uword
Definition globals.h:501
static T LoadUnaligned(const T *ptr)
Definition unaligned.h:14
#define Pd
Definition globals.h:408
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581