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

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

Issue 2776373002: Initial steps into streaming the kernel flowgraph (Closed)
Patch Set: Rebase + fix lint error Created 3 years, 8 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
« no previous file with comments | « runtime/vm/kernel.h ('k') | runtime/vm/kernel_binary.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
322 class Reader {
323 public:
324 Reader(const uint8_t* buffer, intptr_t size)
325 : buffer_(buffer), size_(size), offset_(0) {}
326
327 uint32_t ReadUInt32() {
328 ASSERT(offset_ + 4 <= size_);
329
330 uint32_t value = (buffer_[offset_ + 0] << 24) |
331 (buffer_[offset_ + 1] << 16) |
332 (buffer_[offset_ + 2] << 8) | (buffer_[offset_ + 3] << 0);
333 offset_ += 4;
334 return value;
335 }
336
337 uint32_t ReadUInt() {
338 ASSERT(offset_ + 1 <= size_);
339 uint8_t byte0 = buffer_[offset_];
340 if ((byte0 & 0x80) == 0) {
341 // 0...
342 offset_++;
343 return byte0;
344 } else if ((byte0 & 0xc0) == 0x80) {
345 // 10...
346 ASSERT(offset_ + 2 <= size_);
347 uint32_t value = ((byte0 & ~0x80) << 8) | (buffer_[offset_ + 1]);
348 offset_ += 2;
349 return value;
350 } else {
351 // 11...
352 ASSERT(offset_ + 4 <= size_);
353 uint32_t value = ((byte0 & ~0xc0) << 24) | (buffer_[offset_ + 1] << 16) |
354 (buffer_[offset_ + 2] << 8) |
355 (buffer_[offset_ + 3] << 0);
356 offset_ += 4;
357 return value;
358 }
359 }
360
361 void add_token_position(
362 MallocGrowableArray<MallocGrowableArray<intptr_t>*>* list,
363 TokenPosition position) {
364 intptr_t size = list->length();
365 while (size <= current_script_id_) {
366 MallocGrowableArray<intptr_t>* tmp = new MallocGrowableArray<intptr_t>();
367 list->Add(tmp);
368 size = list->length();
369 }
370 list->At(current_script_id_)->Add(position.value());
371 }
372
373 void record_token_position(TokenPosition position) {
374 if (position.IsReal() && helper()->program() != NULL) {
375 add_token_position(&helper()->program()->valid_token_positions, position);
376 }
377 }
378
379 void record_yield_token_position(TokenPosition position) {
380 if (helper()->program() != NULL) {
381 add_token_position(&helper()->program()->yield_token_positions, position);
382 }
383 }
384
385 /**
386 * Read and return a TokenPosition from this reader.
387 * @param record specifies whether or not the read position is saved as a
388 * valid token position in the current script.
389 * If not be sure to record it later by calling record_token_position (after
390 * setting the correct current_script_id).
391 */
392 TokenPosition ReadPosition(bool record = true) {
393 // Position is saved as unsigned,
394 // but actually ranges from -1 and up (thus the -1)
395 intptr_t value = ReadUInt() - 1;
396 TokenPosition result = TokenPosition(value);
397 max_position_ = Utils::Maximum(max_position_, result);
398 if (min_position_.IsNoSource()) {
399 min_position_ = result;
400 } else if (result.IsReal()) {
401 min_position_ = Utils::Minimum(min_position_, result);
402 }
403
404 if (record) {
405 record_token_position(result);
406 }
407 return result;
408 }
409
410 intptr_t ReadListLength() { return ReadUInt(); }
411
412 uint8_t ReadByte() { return buffer_[offset_++]; }
413
414 bool ReadBool() { return (ReadByte() & 1) == 1; }
415
416 word ReadFlags() { return ReadByte(); }
417
418 Tag ReadTag(uint8_t* payload = NULL) {
419 uint8_t byte = ReadByte();
420 bool has_payload = (byte & kSpecializedTagHighBit) != 0;
421 if (has_payload) {
422 if (payload != NULL) {
423 *payload = byte & kSpecializedPayloadMask;
424 }
425 return static_cast<Tag>(byte & kSpecializedTagMask);
426 } else {
427 return static_cast<Tag>(byte);
428 }
429 }
430
431 const uint8_t* Consume(int count) {
432 ASSERT(offset_ + count <= size_);
433 const uint8_t* old = buffer_ + offset_;
434 offset_ += count;
435 return old;
436 }
437
438 void EnsureEnd() {
439 if (offset_ != size_) {
440 FATAL2(
441 "Reading Kernel file: Expected to be at EOF "
442 "(offset: %" Pd ", size: %" Pd ")",
443 offset_, size_);
444 }
445 }
446
447 void DumpOffset(const char* str) {
448 OS::PrintErr("@%" Pd " %s\n", offset_, str);
449 }
450
451 // The largest position read yet (since last reset).
452 // This is automatically updated when calling ReadPosition,
453 // but can be overwritten (e.g. via the PositionScope class).
454 TokenPosition max_position() { return max_position_; }
455 // The smallest position read yet (since last reset).
456 // This is automatically updated when calling ReadPosition,
457 // but can be overwritten (e.g. via the PositionScope class).
458 TokenPosition min_position() { return min_position_; }
459 // The current script id for what we are currently processing.
460 // Note though that this is only a convenience helper and has to be set
461 // manually.
462 intptr_t current_script_id() { return current_script_id_; }
463 void set_current_script_id(intptr_t script_id) {
464 current_script_id_ = script_id;
465 }
466
467 template <typename T, typename RT>
468 T* ReadOptional() {
469 Tag tag = ReadTag();
470 if (tag == kNothing) {
471 return NULL;
472 }
473 ASSERT(tag == kSomething);
474 return RT::ReadFrom(this);
475 }
476
477 template <typename T>
478 T* ReadOptional() {
479 return ReadOptional<T, T>();
480 }
481
482 ReaderHelper* helper() { return &builder_; }
483
484 CanonicalName* ReadCanonicalNameReference() {
485 int index = ReadUInt();
486 if (index == 0) return NULL;
487 CanonicalName* name = builder_.GetCanonicalName(index - 1);
488 ASSERT(name != NULL);
489 return name;
490 }
491
492 intptr_t offset() { return offset_; }
493 void set_offset(intptr_t offset) { offset_ = offset; }
494 intptr_t size() { return size_; }
495
496 const uint8_t* buffer() { return buffer_; }
497
498 private:
499 const uint8_t* buffer_;
500 intptr_t size_;
501 intptr_t offset_;
502 ReaderHelper builder_;
503 TokenPosition max_position_;
504 TokenPosition min_position_;
505 intptr_t current_script_id_;
506
507 friend class PositionScope;
508 };
509
510
511 // A helper class that resets the readers min and max positions both upon
512 // initialization and upon destruction, i.e. when created the min an max
513 // positions will be reset to "noSource", when destructing the min and max will
514 // be reset to have they value they would have had, if they hadn't been reset in
515 // the first place.
516 class PositionScope {
517 public:
518 explicit PositionScope(Reader* reader)
519 : reader_(reader),
520 min_(reader->min_position_),
521 max_(reader->max_position_) {
522 reader->min_position_ = reader->max_position_ = TokenPosition::kNoSource;
523 }
524
525 ~PositionScope() {
526 if (reader_->min_position_.IsNoSource()) {
527 reader_->min_position_ = min_;
528 } else if (min_.IsReal()) {
529 reader_->min_position_ = Utils::Minimum(reader_->min_position_, min_);
530 }
531 reader_->max_position_ = Utils::Maximum(reader_->max_position_, max_);
532 }
533
534 private:
535 Reader* reader_;
536 TokenPosition min_;
537 TokenPosition max_;
538 };
539
540 } // namespace kernel
541 } // namespace dart
542
543 #endif // !defined(DART_PRECOMPILED_RUNTIME)
544 #endif // RUNTIME_VM_KERNEL_BINARY_H_
OLDNEW
« no previous file with comments | « runtime/vm/kernel.h ('k') | runtime/vm/kernel_binary.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698