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

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

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

Powered by Google App Engine
This is Rietveld 408576698