Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1187)

Side by Side Diff: runtime/vm/kernel_binary.h

Issue 2776373002: Initial steps into streaming the kernel flowgraph (Closed)
Patch Set: Changed type Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 <map>
11
12 #include "vm/kernel.h"
13 #include "vm/kernel_to_il.h"
14 #include "vm/object.h"
15
16 namespace dart {
17 namespace kernel {
18
19
20 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
21
22
23 // Keep in sync with package:dynamo/lib/binary/tag.dart
24 enum Tag {
25 kNothing = 0,
26 kSomething = 1,
27
28 kClass = 2,
29
30 kField = 4,
31 kConstructor = 5,
32 kProcedure = 6,
33
34 kInvalidInitializer = 7,
35 kFieldInitializer = 8,
36 kSuperInitializer = 9,
37 kRedirectingInitializer = 10,
38 kLocalInitializer = 11,
39
40 kDirectPropertyGet = 15,
41 kDirectPropertySet = 16,
42 kDirectMethodInvocation = 17,
43 kConstStaticInvocation = 18,
44 kInvalidExpression = 19,
45 kVariableGet = 20,
46 kVariableSet = 21,
47 kPropertyGet = 22,
48 kPropertySet = 23,
49 kSuperPropertyGet = 24,
50 kSuperPropertySet = 25,
51 kStaticGet = 26,
52 kStaticSet = 27,
53 kMethodInvocation = 28,
54 kSuperMethodInvocation = 29,
55 kStaticInvocation = 30,
56 kConstructorInvocation = 31,
57 kConstConstructorInvocation = 32,
58 kNot = 33,
59 kLogicalExpression = 34,
60 kConditionalExpression = 35,
61 kStringConcatenation = 36,
62 kIsExpression = 37,
63 kAsExpression = 38,
64 kStringLiteral = 39,
65 kDoubleLiteral = 40,
66 kTrueLiteral = 41,
67 kFalseLiteral = 42,
68 kNullLiteral = 43,
69 kSymbolLiteral = 44,
70 kTypeLiteral = 45,
71 kThisExpression = 46,
72 kRethrow = 47,
73 kThrow = 48,
74 kListLiteral = 49,
75 kMapLiteral = 50,
76 kAwaitExpression = 51,
77 kFunctionExpression = 52,
78 kLet = 53,
79
80 kPositiveIntLiteral = 55,
81 kNegativeIntLiteral = 56,
82 kBigIntLiteral = 57,
83 kConstListLiteral = 58,
84 kConstMapLiteral = 59,
85
86 kInvalidStatement = 60,
87 kExpressionStatement = 61,
88 kBlock = 62,
89 kEmptyStatement = 63,
90 kAssertStatement = 64,
91 kLabeledStatement = 65,
92 kBreakStatement = 66,
93 kWhileStatement = 67,
94 kDoStatement = 68,
95 kForStatement = 69,
96 kForInStatement = 70,
97 kSwitchStatement = 71,
98 kContinueSwitchStatement = 72,
99 kIfStatement = 73,
100 kReturnStatement = 74,
101 kTryCatch = 75,
102 kTryFinally = 76,
103 kYieldStatement = 77,
104 kVariableDeclaration = 78,
105 kFunctionDeclaration = 79,
106 kAsyncForInStatement = 80,
107
108 kInvalidType = 90,
109 kDynamicType = 91,
110 kVoidType = 92,
111 kInterfaceType = 93,
112 kFunctionType = 94,
113 kTypeParameterType = 95,
114 kSimpleInterfaceType = 96,
115 kSimpleFunctionType = 97,
116
117 kSpecializedTagHighBit = 0x80, // 10000000
118 kSpecializedTagMask = 0xF8, // 11111000
119 kSpecializedPayloadMask = 0x7, // 00000111
120
121 kSpecializedVariableGet = 128,
122 kSpecializedVariableSet = 136,
123 kSpecialIntLiteral = 144,
124 };
125
126
127 static const int SpecializedIntLiteralBias = 3;
128
129
130 template <typename T>
131 class BlockStack {
132 public:
133 BlockStack() : current_count_(0) {}
134
135 void EnterScope() {
136 variable_count_.Add(current_count_);
137 current_count_ = 0;
138 }
139
140 void LeaveScope() {
141 variables_.TruncateTo(variables_.length() - current_count_);
142 current_count_ = variable_count_[variable_count_.length() - 1];
143 variable_count_.RemoveLast();
144 }
145
146 T* Lookup(int index) {
147 ASSERT(index < variables_.length());
148 return variables_[index];
149 }
150
151 void Push(T* v) {
152 variables_.Add(v);
153 current_count_++;
154 }
155
156 void Push(List<T>* decl) {
157 for (intptr_t i = 0; i < decl->length(); i++) {
158 variables_.Add(decl[i]);
159 current_count_++;
160 }
161 }
162
163 void Pop(T* decl) {
164 variables_.RemoveLast();
165 current_count_--;
166 }
167
168 void Pop(List<T>* decl) {
169 variables_.TruncateTo(variables_.length() - decl->length());
170 current_count_ -= decl->length();
171 }
172
173 private:
174 int current_count_;
175 MallocGrowableArray<T*> variables_;
176 MallocGrowableArray<int> variable_count_;
177 };
178
179
180 template <typename T>
181 class BlockMap {
182 public:
183 BlockMap() : current_count_(0), stack_height_(0) {}
184
185 void EnterScope() {
186 variable_count_.Add(current_count_);
187 current_count_ = 0;
188 }
189
190 void LeaveScope() {
191 stack_height_ -= current_count_;
192 current_count_ = variable_count_[variable_count_.length() - 1];
193 variable_count_.RemoveLast();
194 }
195
196 int Lookup(T* object) {
197 typename MallocMap<T, int>::Pair* result = variables_.LookupPair(object);
198 ASSERT(result != NULL);
199 if (result == NULL) FATAL("lookup failure");
200 return RawPointerKeyValueTrait<T, int>::ValueOf(*result);
201 }
202
203 void Push(T* v) {
204 ASSERT(variables_.LookupPair(v) == NULL);
205 int index = stack_height_++;
206 variables_.Insert(v, index);
207 current_count_++;
208 }
209
210 void Set(T* v, int index) {
211 typename MallocMap<T, int>::Pair* entry = variables_.LookupPair(v);
212 ASSERT(entry != NULL);
213 entry->value = index;
214 }
215
216 void Push(List<T>* decl) {
217 for (intptr_t i = 0; i < decl->length(); i++) {
218 Push(decl[i]);
219 }
220 }
221
222 void Pop(T* v) {
223 current_count_--;
224 stack_height_--;
225 }
226
227 private:
228 int current_count_;
229 int stack_height_;
230 MallocMap<T, int> variables_;
231 MallocGrowableArray<int> variable_count_;
232 };
233
234
235 template <typename T>
236 class VariableScope {
237 public:
238 explicit VariableScope(T* builder) : builder_(builder) {
239 builder_->variables().EnterScope();
240 }
241 ~VariableScope() { builder_->variables().LeaveScope(); }
242
243 private:
244 T* builder_;
245 };
246
247
248 template <typename T>
249 class TypeParameterScope {
250 public:
251 explicit TypeParameterScope(T* builder) : builder_(builder) {
252 builder_->type_parameters().EnterScope();
253 }
254 ~TypeParameterScope() { builder_->type_parameters().LeaveScope(); }
255
256 private:
257 T* builder_;
258 };
259
260
261 template <typename T>
262 class SwitchCaseScope {
263 public:
264 explicit SwitchCaseScope(T* builder) : builder_(builder) {
265 builder_->switch_cases().EnterScope();
266 }
267 ~SwitchCaseScope() { builder_->switch_cases().LeaveScope(); }
268
269 private:
270 T* builder_;
271 };
272
273
274 // Unlike other scopes, labels from enclosing functions are not visible in
275 // nested functions. The LabelScope class is used to hide outer labels.
276 template <typename Builder, typename Block>
277 class LabelScope {
278 public:
279 explicit LabelScope(Builder* builder) : builder_(builder) {
280 outer_block_ = builder_->labels();
281 builder_->set_labels(&block_);
282 }
283 ~LabelScope() { builder_->set_labels(outer_block_); }
284
285 private:
286 Builder* builder_;
287 Block block_;
288 Block* outer_block_;
289 };
290
291
292 class ReaderHelper {
293 public:
294 ReaderHelper() : program_(NULL), labels_(NULL) {}
295
296 Program* program() { return program_; }
297 void set_program(Program* program) { program_ = program; }
298
299 BlockStack<VariableDeclaration>& variables() { return scope_; }
300 BlockStack<TypeParameter>& type_parameters() { return type_parameters_; }
301 BlockStack<SwitchCase>& switch_cases() { return switch_cases_; }
302
303 BlockStack<LabeledStatement>* labels() { return labels_; }
304 void set_labels(BlockStack<LabeledStatement>* labels) { labels_ = labels; }
305
306 CanonicalName* GetCanonicalName(int index) { return canonical_names_[index]; }
307 void SetCanonicalName(int index, CanonicalName* name) {
308 canonical_names_[index] = name;
309 }
310 void SetCanonicalNameCount(int count) { canonical_names_.SetLength(count); }
311
312 private:
313 Program* program_;
314 MallocGrowableArray<CanonicalName*> canonical_names_;
315 BlockStack<VariableDeclaration> scope_;
316 BlockStack<TypeParameter> type_parameters_;
317 BlockStack<SwitchCase> switch_cases_;
318 BlockStack<LabeledStatement>* labels_;
319 };
320
321 class Reader {
322 public:
323 Reader(const uint8_t* buffer, intptr_t size)
324 : buffer_(buffer), size_(size), offset_(0) {}
325
326 uint32_t ReadUInt32() {
327 ASSERT(offset_ + 4 <= size_);
328
329 uint32_t value = (buffer_[offset_ + 0] << 24) |
330 (buffer_[offset_ + 1] << 16) |
331 (buffer_[offset_ + 2] << 8) | (buffer_[offset_ + 3] << 0);
332 offset_ += 4;
333 return value;
334 }
335
336 uint32_t ReadUInt() {
337 ASSERT(offset_ + 1 <= size_);
338 uint8_t byte0 = buffer_[offset_];
339 if ((byte0 & 0x80) == 0) {
340 // 0...
341 offset_++;
342 return byte0;
343 } else if ((byte0 & 0xc0) == 0x80) {
344 // 10...
345 ASSERT(offset_ + 2 <= size_);
346 uint32_t value = ((byte0 & ~0x80) << 8) | (buffer_[offset_ + 1]);
347 offset_ += 2;
348 return value;
349 } else {
350 // 11...
351 ASSERT(offset_ + 4 <= size_);
352 uint32_t value = ((byte0 & ~0xc0) << 24) | (buffer_[offset_ + 1] << 16) |
353 (buffer_[offset_ + 2] << 8) |
354 (buffer_[offset_ + 3] << 0);
355 offset_ += 4;
356 return value;
357 }
358 }
359
360 void add_token_position(
361 MallocGrowableArray<MallocGrowableArray<intptr_t>*>* list,
362 TokenPosition position) {
363 intptr_t size = list->length();
364 while (size <= current_script_id_) {
365 MallocGrowableArray<intptr_t>* tmp = new MallocGrowableArray<intptr_t>();
366 list->Add(tmp);
367 size = list->length();
368 }
369 list->At(current_script_id_)->Add(position.value());
370 }
371
372 void record_token_position(TokenPosition position) {
373 if (position.IsReal() && helper()->program() != NULL) {
374 add_token_position(&helper()->program()->valid_token_positions, position);
375 }
376 }
377
378 void record_yield_token_position(TokenPosition position) {
379 if (helper()->program() != NULL) {
380 add_token_position(&helper()->program()->yield_token_positions, position);
381 }
382 }
383
384 /**
385 * Read and return a TokenPosition from this reader.
386 * @param record specifies whether or not the read position is saved as a
387 * valid token position in the current script.
388 * If not be sure to record it later by calling record_token_position (after
389 * setting the correct current_script_id).
390 */
391 TokenPosition ReadPosition(bool record = true) {
392 // Position is saved as unsigned,
393 // but actually ranges from -1 and up (thus the -1)
394 intptr_t value = ReadUInt() - 1;
395 TokenPosition result = TokenPosition(value);
396 max_position_ = Utils::Maximum(max_position_, result);
397 if (min_position_.IsNoSource()) {
398 min_position_ = result;
399 } else if (result.IsReal()) {
400 min_position_ = Utils::Minimum(min_position_, result);
401 }
402
403 if (record) {
404 record_token_position(result);
405 }
406 return result;
407 }
408
409 intptr_t ReadListLength() { return ReadUInt(); }
410
411 uint8_t ReadByte() { return buffer_[offset_++]; }
412
413 bool ReadBool() { return (ReadByte() & 1) == 1; }
414
415 word ReadFlags() { return ReadByte(); }
416
417 Tag ReadTag(uint8_t* payload = NULL) {
418 uint8_t byte = ReadByte();
419 bool has_payload = (byte & kSpecializedTagHighBit) != 0;
420 if (has_payload) {
421 if (payload != NULL) {
422 *payload = byte & kSpecializedPayloadMask;
423 }
424 return static_cast<Tag>(byte & kSpecializedTagMask);
425 } else {
426 return static_cast<Tag>(byte);
427 }
428 }
429
430 const uint8_t* Consume(int count) {
431 ASSERT(offset_ + count <= size_);
432 const uint8_t* old = buffer_ + offset_;
433 offset_ += count;
434 return old;
435 }
436
437 void EnsureEnd() {
438 if (offset_ != size_) {
439 FATAL2(
440 "Reading Kernel file: Expected to be at EOF "
441 "(offset: %" Pd64 ", size: %" Pd64 ")",
442 offset_, size_);
443 }
444 }
445
446 void DumpOffset(const char* str) {
447 OS::PrintErr("@%" Pd64 " %s\n", offset_, str);
448 }
449
450 // The largest position read yet (since last reset).
451 // This is automatically updated when calling ReadPosition,
452 // but can be overwritten (e.g. via the PositionScope class).
453 TokenPosition max_position() { return max_position_; }
454 // The smallest position read yet (since last reset).
455 // This is automatically updated when calling ReadPosition,
456 // but can be overwritten (e.g. via the PositionScope class).
457 TokenPosition min_position() { return min_position_; }
458 // The current script id for what we are currently processing.
459 // Note though that this is only a convenience helper and has to be set
460 // manually.
461 intptr_t current_script_id() { return current_script_id_; }
462 void set_current_script_id(intptr_t script_id) {
463 current_script_id_ = script_id;
464 }
465
466 template <typename T, typename RT>
467 T* ReadOptional() {
468 Tag tag = ReadTag();
469 if (tag == kNothing) {
470 return NULL;
471 }
472 ASSERT(tag == kSomething);
473 return RT::ReadFrom(this);
474 }
475
476 template <typename T>
477 T* ReadOptional() {
478 return ReadOptional<T, T>();
479 }
480
481 ReaderHelper* helper() { return &builder_; }
482
483 CanonicalName* ReadCanonicalNameReference() {
484 int index = ReadUInt();
485 if (index == 0) return NULL;
486 CanonicalName* name = builder_.GetCanonicalName(index - 1);
487 ASSERT(name != NULL);
488 return name;
489 }
490
491 CanonicalName* ReadDefiningCanonicalNameReference(LinkedNode* node_to_link) {
492 CanonicalName* name = ReadCanonicalNameReference();
493 ASSERT(name != NULL);
494 name->BindTo(node_to_link);
495 return name;
496 }
497
498 intptr_t offset() { return offset_; }
499 void set_offset(intptr_t offset) { offset_ = offset; }
500 intptr_t size() { return size_; }
501
502 const uint8_t* buffer() { return buffer_; }
503
504 private:
505 const uint8_t* buffer_;
506 intptr_t size_;
507 intptr_t offset_;
508 ReaderHelper builder_;
509 TokenPosition max_position_;
510 TokenPosition min_position_;
511 intptr_t current_script_id_;
512
513 friend class PositionScope;
514 };
515
516
517 // A helper class that resets the readers min and max positions both upon
518 // initialization and upon destruction, i.e. when created the min an max
519 // positions will be reset to "noSource", when destructing the min and max will
520 // be reset to have they value they would have had, if they hadn't been reset in
521 // the first place.
522 class PositionScope {
523 public:
524 explicit PositionScope(Reader* reader)
525 : reader_(reader),
526 min_(reader->min_position_),
527 max_(reader->max_position_) {
528 reader->min_position_ = reader->max_position_ = TokenPosition::kNoSource;
529 }
530
531 ~PositionScope() {
532 if (reader_->min_position_.IsNoSource()) {
533 reader_->min_position_ = min_;
534 } else if (min_.IsReal()) {
535 reader_->min_position_ = Utils::Minimum(reader_->min_position_, min_);
536 }
537 reader_->max_position_ = Utils::Maximum(reader_->max_position_, max_);
538 }
539
540 private:
541 Reader* reader_;
542 TokenPosition min_;
543 TokenPosition max_;
544 };
545
546 } // namespace kernel
547 } // namespace dart
548
549 #endif // !defined(DART_PRECOMPILED_RUNTIME)
550 #endif // RUNTIME_VM_KERNEL_BINARY_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698