OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS 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 | 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 | 4 |
5 #ifndef RUNTIME_VM_KERNEL_BINARY_H_ | 5 #ifndef RUNTIME_VM_KERNEL_BINARY_H_ |
6 #define RUNTIME_VM_KERNEL_BINARY_H_ | 6 #define RUNTIME_VM_KERNEL_BINARY_H_ |
7 | 7 |
8 #if !defined(DART_PRECOMPILED_RUNTIME) | 8 #if !defined(DART_PRECOMPILED_RUNTIME) |
9 | 9 |
10 #include <map> | 10 #include <map> |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 | 131 |
132 kSpecializedVariableGet = 128, | 132 kSpecializedVariableGet = 128, |
133 kSpecializedVariableSet = 136, | 133 kSpecializedVariableSet = 136, |
134 kSpecialIntLiteral = 144, | 134 kSpecialIntLiteral = 144, |
135 }; | 135 }; |
136 | 136 |
137 | 137 |
138 static const int SpecializedIntLiteralBias = 3; | 138 static const int SpecializedIntLiteralBias = 3; |
139 | 139 |
140 | 140 |
141 template <typename T> | |
142 class BlockStack { | |
143 public: | |
144 BlockStack() : current_count_(0) {} | |
145 | |
146 void EnterScope() { | |
147 variable_count_.Add(current_count_); | |
148 current_count_ = 0; | |
149 } | |
150 | |
151 void LeaveScope() { | |
152 variables_.TruncateTo(variables_.length() - current_count_); | |
153 current_count_ = variable_count_[variable_count_.length() - 1]; | |
154 variable_count_.RemoveLast(); | |
155 } | |
156 | |
157 T* Lookup(int index) { | |
158 ASSERT(index < variables_.length()); | |
159 return variables_[index]; | |
160 } | |
161 | |
162 void Push(T* v) { | |
163 variables_.Add(v); | |
164 current_count_++; | |
165 } | |
166 | |
167 void Push(List<T>* decl) { | |
168 for (intptr_t i = 0; i < decl->length(); i++) { | |
169 variables_.Add(decl[i]); | |
170 current_count_++; | |
171 } | |
172 } | |
173 | |
174 void Pop(T* decl) { | |
175 variables_.RemoveLast(); | |
176 current_count_--; | |
177 } | |
178 | |
179 void Pop(List<T>* decl) { | |
180 variables_.TruncateTo(variables_.length() - decl->length()); | |
181 current_count_ -= decl->length(); | |
182 } | |
183 | |
184 private: | |
185 int current_count_; | |
186 MallocGrowableArray<T*> variables_; | |
187 MallocGrowableArray<int> variable_count_; | |
188 }; | |
189 | |
190 | |
191 template <typename T> | |
192 class BlockMap { | |
193 public: | |
194 BlockMap() : current_count_(0), stack_height_(0) {} | |
195 | |
196 void EnterScope() { | |
197 variable_count_.Add(current_count_); | |
198 current_count_ = 0; | |
199 } | |
200 | |
201 void LeaveScope() { | |
202 stack_height_ -= current_count_; | |
203 current_count_ = variable_count_[variable_count_.length() - 1]; | |
204 variable_count_.RemoveLast(); | |
205 } | |
206 | |
207 int Lookup(T* object) { | |
208 typename MallocMap<T, int>::Pair* result = variables_.LookupPair(object); | |
209 ASSERT(result != NULL); | |
210 if (result == NULL) FATAL("lookup failure"); | |
211 return RawPointerKeyValueTrait<T, int>::ValueOf(*result); | |
212 } | |
213 | |
214 void Push(T* v) { | |
215 ASSERT(variables_.LookupPair(v) == NULL); | |
216 int index = stack_height_++; | |
217 variables_.Insert(v, index); | |
218 current_count_++; | |
219 } | |
220 | |
221 void Set(T* v, int index) { | |
222 typename MallocMap<T, int>::Pair* entry = variables_.LookupPair(v); | |
223 ASSERT(entry != NULL); | |
224 entry->value = index; | |
225 } | |
226 | |
227 void Push(List<T>* decl) { | |
228 for (intptr_t i = 0; i < decl->length(); i++) { | |
229 Push(decl[i]); | |
230 } | |
231 } | |
232 | |
233 void Pop(T* v) { | |
234 current_count_--; | |
235 stack_height_--; | |
236 } | |
237 | |
238 private: | |
239 int current_count_; | |
240 int stack_height_; | |
241 MallocMap<T, int> variables_; | |
242 MallocGrowableArray<int> variable_count_; | |
243 }; | |
244 | |
245 | |
246 template <typename T> | |
247 class VariableScope { | |
248 public: | |
249 explicit VariableScope(T* builder) : builder_(builder) { | |
250 builder_->variables().EnterScope(); | |
251 } | |
252 ~VariableScope() { builder_->variables().LeaveScope(); } | |
253 | |
254 private: | |
255 T* builder_; | |
256 }; | |
257 | |
258 | |
259 template <typename T> | |
260 class TypeParameterScope { | |
261 public: | |
262 explicit TypeParameterScope(T* builder) : builder_(builder) { | |
263 builder_->type_parameters().EnterScope(); | |
264 } | |
265 ~TypeParameterScope() { builder_->type_parameters().LeaveScope(); } | |
266 | |
267 private: | |
268 T* builder_; | |
269 }; | |
270 | |
271 | |
272 // Unlike other scopes, labels from enclosing functions are not visible in | |
273 // nested functions. The LabelScope class is used to hide outer labels. | |
274 template <typename Builder, typename Block> | |
275 class LabelScope { | |
276 public: | |
277 explicit LabelScope(Builder* builder) : builder_(builder) { | |
278 outer_block_ = builder_->labels(); | |
279 builder_->set_labels(&block_); | |
280 } | |
281 ~LabelScope() { builder_->set_labels(outer_block_); } | |
282 | |
283 private: | |
284 Builder* builder_; | |
285 Block block_; | |
286 Block* outer_block_; | |
287 }; | |
288 | |
289 | |
290 class ReaderHelper { | |
291 public: | |
292 ReaderHelper() : program_(NULL), labels_(NULL) {} | |
293 | |
294 Program* program() { return program_; } | |
295 void set_program(Program* program) { program_ = program; } | |
296 | |
297 BlockStack<VariableDeclaration>& variables() { return scope_; } | |
298 BlockStack<TypeParameter>& type_parameters() { return type_parameters_; } | |
299 | |
300 BlockStack<LabeledStatement>* labels() { return labels_; } | |
301 void set_labels(BlockStack<LabeledStatement>* labels) { labels_ = labels; } | |
302 | |
303 private: | |
304 Program* program_; | |
305 BlockStack<VariableDeclaration> scope_; | |
306 BlockStack<TypeParameter> type_parameters_; | |
307 BlockStack<LabeledStatement>* labels_; | |
308 }; | |
309 | |
310 | |
311 class Reader { | 141 class Reader { |
312 public: | 142 public: |
313 Reader(const uint8_t* buffer, intptr_t size) | 143 Reader(const uint8_t* buffer, intptr_t size) |
314 : buffer_(buffer), | 144 : buffer_(buffer), size_(size), offset_(0) {} |
315 size_(size), | |
316 offset_(0), | |
317 string_data_offset_(-1), | |
318 string_offsets_(NULL), | |
319 canonical_name_parents_(NULL), | |
320 canonical_name_strings_(NULL) {} | |
321 | |
322 ~Reader(); | |
323 | 145 |
324 uint32_t ReadUInt32() { | 146 uint32_t ReadUInt32() { |
325 ASSERT(offset_ + 4 <= size_); | 147 ASSERT(offset_ + 4 <= size_); |
326 | 148 |
327 uint32_t value = (buffer_[offset_ + 0] << 24) | | 149 uint32_t value = (buffer_[offset_ + 0] << 24) | |
328 (buffer_[offset_ + 1] << 16) | | 150 (buffer_[offset_ + 1] << 16) | |
329 (buffer_[offset_ + 2] << 8) | (buffer_[offset_ + 3] << 0); | 151 (buffer_[offset_ + 2] << 8) | (buffer_[offset_ + 3] << 0); |
330 offset_ += 4; | 152 offset_ += 4; |
331 return value; | 153 return value; |
332 } | 154 } |
(...skipping 15 matching lines...) Expand all Loading... |
348 // 11... | 170 // 11... |
349 ASSERT(offset_ + 4 <= size_); | 171 ASSERT(offset_ + 4 <= size_); |
350 uint32_t value = ((byte0 & ~0xc0) << 24) | (buffer_[offset_ + 1] << 16) | | 172 uint32_t value = ((byte0 & ~0xc0) << 24) | (buffer_[offset_ + 1] << 16) | |
351 (buffer_[offset_ + 2] << 8) | | 173 (buffer_[offset_ + 2] << 8) | |
352 (buffer_[offset_ + 3] << 0); | 174 (buffer_[offset_ + 3] << 0); |
353 offset_ += 4; | 175 offset_ += 4; |
354 return value; | 176 return value; |
355 } | 177 } |
356 } | 178 } |
357 | 179 |
358 void add_token_position( | |
359 MallocGrowableArray<MallocGrowableArray<intptr_t>*>* list, | |
360 TokenPosition position) { | |
361 intptr_t size = list->length(); | |
362 while (size <= current_script_id_) { | |
363 MallocGrowableArray<intptr_t>* tmp = new MallocGrowableArray<intptr_t>(); | |
364 list->Add(tmp); | |
365 size = list->length(); | |
366 } | |
367 list->At(current_script_id_)->Add(position.value()); | |
368 } | |
369 | |
370 void record_token_position(TokenPosition position) { | |
371 if (position.IsReal() && helper()->program() != NULL) { | |
372 add_token_position(&helper()->program()->valid_token_positions, position); | |
373 } | |
374 } | |
375 | |
376 void record_yield_token_position(TokenPosition position) { | |
377 if (helper()->program() != NULL) { | |
378 add_token_position(&helper()->program()->yield_token_positions, position); | |
379 } | |
380 } | |
381 | |
382 /** | 180 /** |
383 * Read and return a TokenPosition from this reader. | 181 * Read and return a TokenPosition from this reader. |
384 * @param record specifies whether or not the read position is saved as a | 182 * @param record specifies whether or not the read position is saved as a |
385 * valid token position in the current script. | 183 * valid token position in the current script. |
386 * If not be sure to record it later by calling record_token_position (after | 184 * If not be sure to record it later by calling record_token_position (after |
387 * setting the correct current_script_id). | 185 * setting the correct current_script_id). |
388 */ | 186 */ |
389 TokenPosition ReadPosition(bool record = true) { | 187 TokenPosition ReadPosition() { |
390 // Position is saved as unsigned, | 188 // Position is saved as unsigned, |
391 // but actually ranges from -1 and up (thus the -1) | 189 // but actually ranges from -1 and up (thus the -1) |
392 intptr_t value = ReadUInt() - 1; | 190 intptr_t value = ReadUInt() - 1; |
393 TokenPosition result = TokenPosition(value); | 191 TokenPosition result = TokenPosition(value); |
394 max_position_ = Utils::Maximum(max_position_, result); | 192 max_position_ = Utils::Maximum(max_position_, result); |
395 if (min_position_.IsNoSource()) { | 193 if (min_position_.IsNoSource()) { |
396 min_position_ = result; | 194 min_position_ = result; |
397 } else if (result.IsReal()) { | 195 } else if (result.IsReal()) { |
398 min_position_ = Utils::Minimum(min_position_, result); | 196 min_position_ = Utils::Minimum(min_position_, result); |
399 } | 197 } |
400 | 198 |
401 if (record) { | |
402 record_token_position(result); | |
403 } | |
404 return result; | 199 return result; |
405 } | 200 } |
406 | 201 |
407 intptr_t ReadListLength() { return ReadUInt(); } | 202 intptr_t ReadListLength() { return ReadUInt(); } |
408 | 203 |
409 uint8_t ReadByte() { return buffer_[offset_++]; } | 204 uint8_t ReadByte() { return buffer_[offset_++]; } |
410 | 205 |
411 uint8_t PeekByte() { return buffer_[offset_]; } | 206 uint8_t PeekByte() { return buffer_[offset_]; } |
412 | 207 |
413 bool ReadBool() { return (ReadByte() & 1) == 1; } | 208 bool ReadBool() { return (ReadByte() & 1) == 1; } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 | 244 |
450 void EnsureEnd() { | 245 void EnsureEnd() { |
451 if (offset_ != size_) { | 246 if (offset_ != size_) { |
452 FATAL2( | 247 FATAL2( |
453 "Reading Kernel file: Expected to be at EOF " | 248 "Reading Kernel file: Expected to be at EOF " |
454 "(offset: %" Pd ", size: %" Pd ")", | 249 "(offset: %" Pd ", size: %" Pd ")", |
455 offset_, size_); | 250 offset_, size_); |
456 } | 251 } |
457 } | 252 } |
458 | 253 |
459 void DumpOffset(const char* str) { | |
460 OS::PrintErr("@%" Pd " %s\n", offset_, str); | |
461 } | |
462 | |
463 // The largest position read yet (since last reset). | 254 // The largest position read yet (since last reset). |
464 // This is automatically updated when calling ReadPosition, | 255 // This is automatically updated when calling ReadPosition, |
465 // but can be overwritten (e.g. via the PositionScope class). | 256 // but can be overwritten (e.g. via the PositionScope class). |
466 TokenPosition max_position() { return max_position_; } | 257 TokenPosition max_position() { return max_position_; } |
467 // The smallest position read yet (since last reset). | 258 // The smallest position read yet (since last reset). |
468 // This is automatically updated when calling ReadPosition, | 259 // This is automatically updated when calling ReadPosition, |
469 // but can be overwritten (e.g. via the PositionScope class). | 260 // but can be overwritten (e.g. via the PositionScope class). |
470 TokenPosition min_position() { return min_position_; } | 261 TokenPosition min_position() { return min_position_; } |
471 // The current script id for what we are currently processing. | |
472 // Note though that this is only a convenience helper and has to be set | |
473 // manually. | |
474 intptr_t current_script_id() { return current_script_id_; } | |
475 void set_current_script_id(intptr_t script_id) { | |
476 current_script_id_ = script_id; | |
477 } | |
478 | 262 |
479 template <typename T, typename RT> | 263 template <typename T, typename RT> |
480 T* ReadOptional() { | 264 T* ReadOptional() { |
481 Tag tag = ReadTag(); | 265 Tag tag = ReadTag(); |
482 if (tag == kNothing) { | 266 if (tag == kNothing) { |
483 return NULL; | 267 return NULL; |
484 } | 268 } |
485 ASSERT(tag == kSomething); | 269 ASSERT(tag == kSomething); |
486 return RT::ReadFrom(this); | 270 return RT::ReadFrom(this); |
487 } | 271 } |
488 | 272 |
489 template <typename T> | 273 template <typename T> |
490 T* ReadOptional() { | 274 T* ReadOptional() { |
491 return ReadOptional<T, T>(); | 275 return ReadOptional<T, T>(); |
492 } | 276 } |
493 | 277 |
494 ReaderHelper* helper() { return &builder_; } | |
495 | |
496 // A canonical name reference of -1 indicates none (for optional names), not | 278 // A canonical name reference of -1 indicates none (for optional names), not |
497 // the root name as in the canonical name table. | 279 // the root name as in the canonical name table. |
498 NameIndex ReadCanonicalNameReference() { return NameIndex(ReadUInt() - 1); } | 280 NameIndex ReadCanonicalNameReference() { return NameIndex(ReadUInt() - 1); } |
499 | 281 |
500 intptr_t offset() { return offset_; } | 282 intptr_t offset() { return offset_; } |
501 void set_offset(intptr_t offset) { offset_ = offset; } | 283 void set_offset(intptr_t offset) { offset_ = offset; } |
502 intptr_t size() { return size_; } | 284 intptr_t size() { return size_; } |
503 | 285 |
504 const uint8_t* buffer() { return buffer_; } | 286 const uint8_t* buffer() { return buffer_; } |
505 | 287 |
506 intptr_t string_data_offset() { return string_data_offset_; } | |
507 void MarkStringDataOffset() { | |
508 ASSERT(string_data_offset_ == -1); | |
509 string_data_offset_ = offset_; | |
510 } | |
511 | |
512 intptr_t StringLength(StringIndex index) { | |
513 return string_offsets_[index + 1] - string_offsets_[index]; | |
514 } | |
515 | |
516 uint8_t CharacterAt(StringIndex string_index, intptr_t index) { | |
517 ASSERT(index < StringLength(string_index)); | |
518 return buffer_[string_data_offset_ + string_offsets_[string_index] + index]; | |
519 } | |
520 | |
521 // The canonical name index of a canonical name's parent (-1 indicates that | |
522 // the parent is the root name). | |
523 NameIndex CanonicalNameParent(NameIndex index) { | |
524 return canonical_name_parents_[index]; | |
525 } | |
526 | |
527 // The string index of a canonical name's name string. | |
528 StringIndex CanonicalNameString(NameIndex index) { | |
529 return canonical_name_strings_[index]; | |
530 } | |
531 | |
532 private: | 288 private: |
533 const uint8_t* buffer_; | 289 const uint8_t* buffer_; |
534 intptr_t size_; | 290 intptr_t size_; |
535 intptr_t offset_; | 291 intptr_t offset_; |
536 ReaderHelper builder_; | |
537 TokenPosition max_position_; | 292 TokenPosition max_position_; |
538 TokenPosition min_position_; | 293 TokenPosition min_position_; |
539 intptr_t current_script_id_; | 294 intptr_t current_script_id_; |
540 | 295 |
541 // The offset of the start of the string data is recorded to allow access to | |
542 // the strings during deserialization. | |
543 intptr_t string_data_offset_; | |
544 | |
545 // The string offsets are decoded to support efficient access to string UTF-8 | |
546 // encodings. | |
547 intptr_t* string_offsets_; | |
548 | |
549 // The canonical names are decoded. | |
550 NameIndex* canonical_name_parents_; | |
551 StringIndex* canonical_name_strings_; | |
552 | |
553 friend class PositionScope; | 296 friend class PositionScope; |
554 friend class Program; | 297 friend class Program; |
555 }; | 298 }; |
556 | 299 |
557 | 300 |
558 // A helper class that resets the readers min and max positions both upon | 301 // A helper class that resets the readers min and max positions both upon |
559 // initialization and upon destruction, i.e. when created the min an max | 302 // initialization and upon destruction, i.e. when created the min an max |
560 // positions will be reset to "noSource", when destructing the min and max will | 303 // positions will be reset to "noSource", when destructing the min and max will |
561 // be reset to have they value they would have had, if they hadn't been reset in | 304 // be reset to have they value they would have had, if they hadn't been reset in |
562 // the first place. | 305 // the first place. |
(...skipping 19 matching lines...) Expand all Loading... |
582 Reader* reader_; | 325 Reader* reader_; |
583 TokenPosition min_; | 326 TokenPosition min_; |
584 TokenPosition max_; | 327 TokenPosition max_; |
585 }; | 328 }; |
586 | 329 |
587 } // namespace kernel | 330 } // namespace kernel |
588 } // namespace dart | 331 } // namespace dart |
589 | 332 |
590 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 333 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
591 #endif // RUNTIME_VM_KERNEL_BINARY_H_ | 334 #endif // RUNTIME_VM_KERNEL_BINARY_H_ |
OLD | NEW |