1 | // Copyright (c) 2018, 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_COMPILER_FRONTEND_BYTECODE_READER_H_ |
6 | #define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_ |
7 | |
8 | #if defined(DART_PRECOMPILED_RUNTIME) |
9 | #error "AOT runtime should not use compiler sources (including header files)" |
10 | #endif // defined(DART_PRECOMPILED_RUNTIME) |
11 | |
12 | #include "vm/compiler/frontend/kernel_translation_helper.h" |
13 | #include "vm/constants_kbc.h" |
14 | #include "vm/object.h" |
15 | |
16 | namespace dart { |
17 | namespace kernel { |
18 | |
19 | class BytecodeComponentData; |
20 | |
21 | // Helper class which provides access to bytecode metadata. |
22 | class BytecodeMetadataHelper : public MetadataHelper { |
23 | public: |
24 | static const char* tag() { return "vm.bytecode" ; } |
25 | |
26 | explicit BytecodeMetadataHelper(KernelReaderHelper* helper, |
27 | ActiveClass* active_class); |
28 | |
29 | void ParseBytecodeFunction(ParsedFunction* parsed_function); |
30 | |
31 | // Read all library declarations. |
32 | bool ReadLibraries(); |
33 | |
34 | // Read specific library declaration. |
35 | void ReadLibrary(const Library& library); |
36 | |
37 | // Scan through libraries in the bytecode component and figure out if any of |
38 | // them will replace libraries which are already loaded. |
39 | // Return true if bytecode component is found. |
40 | bool FindModifiedLibrariesForHotReload(BitVector* modified_libs, |
41 | bool* is_empty_program, |
42 | intptr_t* p_num_classes, |
43 | intptr_t* p_num_procedures); |
44 | |
45 | LibraryPtr GetMainLibrary(); |
46 | |
47 | ArrayPtr GetBytecodeComponent(); |
48 | ArrayPtr ReadBytecodeComponent(); |
49 | |
50 | private: |
51 | ActiveClass* const active_class_; |
52 | |
53 | DISALLOW_COPY_AND_ASSIGN(BytecodeMetadataHelper); |
54 | }; |
55 | |
56 | // Helper class for reading bytecode. |
57 | class BytecodeReaderHelper : public ValueObject { |
58 | public: |
59 | explicit BytecodeReaderHelper(TranslationHelper* translation_helper, |
60 | ActiveClass* active_class, |
61 | BytecodeComponentData* bytecode_component); |
62 | |
63 | Reader& reader() { return reader_; } |
64 | |
65 | void ReadCode(const Function& function, intptr_t code_offset); |
66 | |
67 | ArrayPtr CreateForwarderChecks(const Function& function); |
68 | |
69 | void ReadMembers(const Class& cls, bool discard_fields); |
70 | |
71 | void ReadFieldDeclarations(const Class& cls, bool discard_fields); |
72 | void ReadFunctionDeclarations(const Class& cls); |
73 | void ReadClassDeclaration(const Class& cls); |
74 | void ReadLibraryDeclaration(const Library& library, bool lookup_classes); |
75 | void ReadLibraryDeclarations(intptr_t num_libraries); |
76 | void FindAndReadSpecificLibrary(const Library& library, |
77 | intptr_t num_libraries); |
78 | void FindModifiedLibrariesForHotReload(BitVector* modified_libs, |
79 | intptr_t num_libraries); |
80 | |
81 | void ParseBytecodeFunction(ParsedFunction* parsed_function, |
82 | const Function& function); |
83 | |
84 | LibraryPtr ReadMain(); |
85 | |
86 | ArrayPtr ReadBytecodeComponent(intptr_t md_offset); |
87 | void ResetObjects(); |
88 | |
89 | // Fills in [is_covariant] and [is_generic_covariant_impl] vectors |
90 | // according to covariance attributes of [function] parameters. |
91 | // |
92 | // [function] should be declared in bytecode. |
93 | // [is_covariant] and [is_generic_covariant_impl] should contain bitvectors |
94 | // of function.NumParameters() length. |
95 | void ReadParameterCovariance(const Function& function, |
96 | BitVector* is_covariant, |
97 | BitVector* is_generic_covariant_impl); |
98 | |
99 | // Returns an flattened array of tuples {isFinal, defaultValue, metadata}, |
100 | // or an Error. |
101 | ObjectPtr BuildParameterDescriptor(const Function& function); |
102 | |
103 | // Read bytecode PackedObject. |
104 | ObjectPtr ReadObject(); |
105 | |
106 | private: |
107 | // These constants should match corresponding constants in class ObjectHandle |
108 | // (pkg/vm/lib/bytecode/object_table.dart). |
109 | static const int kReferenceBit = 1 << 0; |
110 | static const int kIndexShift = 1; |
111 | static const int kKindShift = 1; |
112 | static const int kKindMask = 0x0f; |
113 | static const int kFlagBit0 = 1 << 5; |
114 | static const int kFlagBit1 = 1 << 6; |
115 | static const int kFlagBit2 = 1 << 7; |
116 | static const int kFlagBit3 = 1 << 8; |
117 | static const int kFlagBit4 = 1 << 9; |
118 | static const int kFlagBit5 = 1 << 10; |
119 | static const int kTagMask = (kFlagBit0 | kFlagBit1 | kFlagBit2 | kFlagBit3); |
120 | static const int kNullabilityMask = (kFlagBit4 | kFlagBit5); |
121 | static const int kFlagsMask = (kTagMask | kNullabilityMask); |
122 | |
123 | // Code flags, must be in sync with Code constants in |
124 | // pkg/vm/lib/bytecode/declarations.dart. |
125 | struct Code { |
126 | static const int kHasExceptionsTableFlag = 1 << 0; |
127 | static const int kHasSourcePositionsFlag = 1 << 1; |
128 | static const int kHasNullableFieldsFlag = 1 << 2; |
129 | static const int kHasClosuresFlag = 1 << 3; |
130 | static const int kHasParameterFlagsFlag = 1 << 4; |
131 | static const int kHasForwardingStubTargetFlag = 1 << 5; |
132 | static const int kHasDefaultFunctionTypeArgsFlag = 1 << 6; |
133 | static const int kHasLocalVariablesFlag = 1 << 7; |
134 | }; |
135 | |
136 | // Closure code flags, must be in sync with ClosureCode constants in |
137 | // pkg/vm/lib/bytecode/declarations.dart. |
138 | struct ClosureCode { |
139 | static const int kHasExceptionsTableFlag = 1 << 0; |
140 | static const int kHasSourcePositionsFlag = 1 << 1; |
141 | static const int kHasLocalVariablesFlag = 1 << 2; |
142 | }; |
143 | |
144 | // Parameter flags, must be in sync with ParameterDeclaration constants in |
145 | // pkg/vm/lib/bytecode/declarations.dart. |
146 | struct Parameter { |
147 | static const int kIsCovariantFlag = 1 << 0; |
148 | static const int kIsGenericCovariantImplFlag = 1 << 1; |
149 | static const int kIsFinalFlag = 1 << 2; |
150 | static const int kIsRequiredFlag = 1 << 3; |
151 | }; |
152 | |
153 | class FunctionTypeScope : public ValueObject { |
154 | public: |
155 | explicit FunctionTypeScope(BytecodeReaderHelper* bytecode_reader) |
156 | : bytecode_reader_(bytecode_reader), |
157 | saved_type_parameters_( |
158 | bytecode_reader->function_type_type_parameters_) {} |
159 | |
160 | ~FunctionTypeScope() { |
161 | bytecode_reader_->function_type_type_parameters_ = saved_type_parameters_; |
162 | } |
163 | |
164 | private: |
165 | BytecodeReaderHelper* bytecode_reader_; |
166 | const TypeArguments* const saved_type_parameters_; |
167 | }; |
168 | |
169 | class FunctionScope : public ValueObject { |
170 | public: |
171 | FunctionScope(BytecodeReaderHelper* bytecode_reader, |
172 | const Function& function, |
173 | const String& name, |
174 | const Class& cls) |
175 | : bytecode_reader_(bytecode_reader) { |
176 | ASSERT(bytecode_reader_->scoped_function_.IsNull()); |
177 | ASSERT(bytecode_reader_->scoped_function_name_.IsNull()); |
178 | ASSERT(bytecode_reader_->scoped_function_class_.IsNull()); |
179 | ASSERT(name.IsSymbol()); |
180 | bytecode_reader_->scoped_function_ = function.raw(); |
181 | bytecode_reader_->scoped_function_name_ = name.raw(); |
182 | bytecode_reader_->scoped_function_class_ = cls.raw(); |
183 | } |
184 | |
185 | ~FunctionScope() { |
186 | bytecode_reader_->scoped_function_ = Function::null(); |
187 | bytecode_reader_->scoped_function_name_ = String::null(); |
188 | bytecode_reader_->scoped_function_class_ = Class::null(); |
189 | } |
190 | |
191 | private: |
192 | BytecodeReaderHelper* bytecode_reader_; |
193 | }; |
194 | |
195 | void ReadClosureDeclaration(const Function& function, intptr_t closureIndex); |
196 | TypePtr ReadFunctionSignature(const Function& func, |
197 | bool has_optional_positional_params, |
198 | bool has_optional_named_params, |
199 | bool has_type_params, |
200 | bool has_positional_param_names, |
201 | bool has_parameter_flags, |
202 | Nullability nullability); |
203 | void ReadTypeParametersDeclaration(const Class& parameterized_class, |
204 | const Function& parameterized_function); |
205 | |
206 | // Read portion of constant pool corresponding to one function/closure. |
207 | // Start with [start_index], and stop when reaching EndClosureFunctionScope. |
208 | // Return index of the last read constant pool entry. |
209 | intptr_t ReadConstantPool(const Function& function, |
210 | const ObjectPool& pool, |
211 | intptr_t start_index); |
212 | |
213 | BytecodePtr ReadBytecode(const ObjectPool& pool); |
214 | void ReadExceptionsTable(const Bytecode& bytecode, bool has_exceptions_table); |
215 | void ReadSourcePositions(const Bytecode& bytecode, bool has_source_positions); |
216 | void ReadLocalVariables(const Bytecode& bytecode, bool has_local_variables); |
217 | TypedDataPtr NativeEntry(const Function& function, |
218 | const String& external_name); |
219 | StringPtr ConstructorName(const Class& cls, const String& name); |
220 | |
221 | ObjectPtr ReadObjectContents(uint32_t ); |
222 | ObjectPtr ReadConstObject(intptr_t tag); |
223 | ObjectPtr ReadType(intptr_t tag, Nullability nullability); |
224 | StringPtr ReadString(bool is_canonical = true); |
225 | ScriptPtr ReadSourceFile(const String& uri, intptr_t offset); |
226 | TypeArgumentsPtr ReadTypeArguments(); |
227 | void ReadAttributes(const Object& key); |
228 | PatchClassPtr GetPatchClass(const Class& cls, const Script& script); |
229 | void ParseForwarderFunction(ParsedFunction* parsed_function, |
230 | const Function& function, |
231 | const Function& target); |
232 | |
233 | bool IsExpressionEvaluationLibrary(const Library& library) const { |
234 | return expression_evaluation_library_ != nullptr && |
235 | expression_evaluation_library_->raw() == library.raw(); |
236 | } |
237 | |
238 | // Similar to cls.EnsureClassDeclaration, but may be more efficient if |
239 | // class is from the current kernel binary. |
240 | void LoadReferencedClass(const Class& cls); |
241 | |
242 | Reader reader_; |
243 | TranslationHelper& translation_helper_; |
244 | ActiveClass* const active_class_; |
245 | Thread* const thread_; |
246 | Zone* const zone_; |
247 | BytecodeComponentData* bytecode_component_; |
248 | Array* closures_ = nullptr; |
249 | const TypeArguments* function_type_type_parameters_ = nullptr; |
250 | GrowableObjectArray* pending_recursive_types_ = nullptr; |
251 | PatchClass* patch_class_ = nullptr; |
252 | Array* functions_ = nullptr; |
253 | intptr_t function_index_ = 0; |
254 | Function& scoped_function_; |
255 | String& scoped_function_name_; |
256 | Class& scoped_function_class_; |
257 | Library* expression_evaluation_library_ = nullptr; |
258 | bool loading_native_wrappers_library_ = false; |
259 | bool reading_type_arguments_of_recursive_type_ = false; |
260 | |
261 | DISALLOW_COPY_AND_ASSIGN(BytecodeReaderHelper); |
262 | }; |
263 | |
264 | class BytecodeComponentData : ValueObject { |
265 | public: |
266 | enum { |
267 | kVersion, |
268 | , |
269 | kStringsContentsOffset, |
270 | kObjectOffsetsOffset, |
271 | kNumObjects, |
272 | kObjectsContentsOffset, |
273 | kMainOffset, |
274 | kNumLibraries, |
275 | kLibraryIndexOffset, |
276 | kLibrariesOffset, |
277 | kNumClasses, |
278 | kClassesOffset, |
279 | kMembersOffset, |
280 | kNumCodes, |
281 | kCodesOffset, |
282 | kSourcePositionsOffset, |
283 | kSourceFilesOffset, |
284 | kLineStartsOffset, |
285 | kLocalVariablesOffset, |
286 | kAnnotationsOffset, |
287 | kNumFields |
288 | }; |
289 | |
290 | explicit BytecodeComponentData(Array* data) : data_(*data) {} |
291 | |
292 | void Init(const Array& data) { data_ = data.raw(); } |
293 | |
294 | intptr_t GetVersion() const; |
295 | intptr_t () const; |
296 | intptr_t GetStringsContentsOffset() const; |
297 | intptr_t GetObjectOffsetsOffset() const; |
298 | intptr_t GetNumObjects() const; |
299 | intptr_t GetObjectsContentsOffset() const; |
300 | intptr_t GetMainOffset() const; |
301 | intptr_t GetNumLibraries() const; |
302 | intptr_t GetLibraryIndexOffset() const; |
303 | intptr_t GetLibrariesOffset() const; |
304 | intptr_t GetNumClasses() const; |
305 | intptr_t GetClassesOffset() const; |
306 | intptr_t GetMembersOffset() const; |
307 | intptr_t GetNumCodes() const; |
308 | intptr_t GetCodesOffset() const; |
309 | intptr_t GetSourcePositionsOffset() const; |
310 | intptr_t GetSourceFilesOffset() const; |
311 | intptr_t GetLineStartsOffset() const; |
312 | intptr_t GetLocalVariablesOffset() const; |
313 | intptr_t GetAnnotationsOffset() const; |
314 | void SetObject(intptr_t index, const Object& obj) const; |
315 | ObjectPtr GetObject(intptr_t index) const; |
316 | |
317 | bool IsNull() const { return data_.IsNull(); } |
318 | |
319 | static ArrayPtr New(Zone* zone, |
320 | intptr_t version, |
321 | intptr_t num_objects, |
322 | intptr_t , |
323 | intptr_t strings_contents_offset, |
324 | intptr_t object_offsets_offset, |
325 | intptr_t objects_contents_offset, |
326 | intptr_t main_offset, |
327 | intptr_t num_libraries, |
328 | intptr_t library_index_offset, |
329 | intptr_t libraries_offset, |
330 | intptr_t num_classes, |
331 | intptr_t classes_offset, |
332 | intptr_t members_offset, |
333 | intptr_t num_codes, |
334 | intptr_t codes_offset, |
335 | intptr_t source_positions_offset, |
336 | intptr_t source_files_offset, |
337 | intptr_t line_starts_offset, |
338 | intptr_t local_variables_offset, |
339 | intptr_t annotations_offset, |
340 | Heap::Space space); |
341 | |
342 | private: |
343 | Array& data_; |
344 | }; |
345 | |
346 | class BytecodeReader : public AllStatic { |
347 | public: |
348 | // Reads bytecode for the given function and sets its bytecode field. |
349 | // Returns error (if any), or null. |
350 | static ErrorPtr ReadFunctionBytecode(Thread* thread, |
351 | const Function& function); |
352 | |
353 | // Read annotations for the given annotation field. |
354 | static ObjectPtr ReadAnnotation(const Field& annotation_field); |
355 | // Read the |count| annotations following given annotation field. |
356 | static ArrayPtr ReadExtendedAnnotations(const Field& annotation_field, |
357 | intptr_t count); |
358 | |
359 | static void ResetObjectTable(const KernelProgramInfo& info); |
360 | |
361 | // Read declaration of the given library. |
362 | static void LoadLibraryDeclaration(const Library& library); |
363 | |
364 | // Read declaration of the given class. |
365 | static void LoadClassDeclaration(const Class& cls); |
366 | |
367 | // Read members of the given class. |
368 | static void FinishClassLoading(const Class& cls); |
369 | |
370 | // Value of attribute [name] of Function/Field [key]. |
371 | static ObjectPtr GetBytecodeAttribute(const Object& key, const String& name); |
372 | |
373 | #if !defined(PRODUCT) |
374 | // Compute local variable descriptors for [function] with [bytecode]. |
375 | static LocalVarDescriptorsPtr ComputeLocalVarDescriptors( |
376 | Zone* zone, |
377 | const Function& function, |
378 | const Bytecode& bytecode); |
379 | #endif |
380 | }; |
381 | |
382 | class InferredTypeBytecodeAttribute : public AllStatic { |
383 | public: |
384 | // Number of array elements per entry in InferredType bytecode |
385 | // attribute (PC, type, flags). |
386 | static constexpr intptr_t kNumElements = 3; |
387 | |
388 | // Field type is the first entry with PC = -1. |
389 | static constexpr intptr_t kFieldTypePC = -1; |
390 | |
391 | // Returns PC at given index. |
392 | static intptr_t GetPCAt(const Array& attr, intptr_t index) { |
393 | return Smi::Value(Smi::RawCast(attr.At(index))); |
394 | } |
395 | |
396 | // Returns InferredType metadata at given index. |
397 | static InferredTypeMetadata GetInferredTypeAt(Zone* zone, |
398 | const Array& attr, |
399 | intptr_t index); |
400 | }; |
401 | |
402 | class BytecodeSourcePositionsIterator : ValueObject { |
403 | public: |
404 | // These constants should match corresponding constants in class |
405 | // SourcePositions (pkg/vm/lib/bytecode/source_positions.dart). |
406 | static const intptr_t kSyntheticCodeMarker = -1; |
407 | static const intptr_t kYieldPointMarker = -2; |
408 | |
409 | BytecodeSourcePositionsIterator(Zone* zone, const Bytecode& bytecode) |
410 | : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))) { |
411 | if (bytecode.HasSourcePositions()) { |
412 | reader_.set_offset(bytecode.source_positions_binary_offset()); |
413 | pairs_remaining_ = reader_.ReadUInt(); |
414 | } |
415 | } |
416 | |
417 | bool MoveNext() { |
418 | if (pairs_remaining_ == 0) { |
419 | return false; |
420 | } |
421 | ASSERT(pairs_remaining_ > 0); |
422 | --pairs_remaining_; |
423 | cur_bci_ += reader_.ReadUInt(); |
424 | cur_token_pos_ += reader_.ReadSLEB128(); |
425 | is_yield_point_ = false; |
426 | if (cur_token_pos_ == kYieldPointMarker) { |
427 | const bool result = MoveNext(); |
428 | is_yield_point_ = true; |
429 | return result; |
430 | } |
431 | return true; |
432 | } |
433 | |
434 | uword PcOffset() const { return cur_bci_; } |
435 | |
436 | TokenPosition TokenPos() const { |
437 | return (cur_token_pos_ == kSyntheticCodeMarker) |
438 | ? TokenPosition::kNoSource |
439 | : TokenPosition(cur_token_pos_); |
440 | } |
441 | |
442 | bool IsYieldPoint() const { return is_yield_point_; } |
443 | |
444 | private: |
445 | Reader reader_; |
446 | intptr_t pairs_remaining_ = 0; |
447 | intptr_t cur_bci_ = 0; |
448 | intptr_t cur_token_pos_ = 0; |
449 | bool is_yield_point_ = false; |
450 | }; |
451 | |
452 | class BytecodeLocalVariablesIterator : ValueObject { |
453 | public: |
454 | // These constants should match corresponding constants in |
455 | // pkg/vm/lib/bytecode/local_variable_table.dart. |
456 | enum { |
457 | kInvalid, |
458 | kScope, |
459 | kVariableDeclaration, |
460 | kContextVariable, |
461 | }; |
462 | |
463 | static const intptr_t kKindMask = 0xF; |
464 | static const intptr_t kIsCapturedFlag = 1 << 4; |
465 | |
466 | BytecodeLocalVariablesIterator(Zone* zone, const Bytecode& bytecode) |
467 | : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))), |
468 | object_pool_(ObjectPool::Handle(zone, bytecode.object_pool())) { |
469 | if (bytecode.HasLocalVariablesInfo()) { |
470 | reader_.set_offset(bytecode.local_variables_binary_offset()); |
471 | entries_remaining_ = reader_.ReadUInt(); |
472 | } |
473 | } |
474 | |
475 | bool MoveNext() { |
476 | if (entries_remaining_ <= 0) { |
477 | // Finished looking at the last entry, now we're done. |
478 | entries_remaining_ = -1; |
479 | return false; |
480 | } |
481 | --entries_remaining_; |
482 | cur_kind_and_flags_ = reader_.ReadByte(); |
483 | cur_start_pc_ += reader_.ReadSLEB128(); |
484 | switch (Kind()) { |
485 | case kScope: |
486 | cur_end_pc_ = cur_start_pc_ + reader_.ReadUInt(); |
487 | cur_index_ = reader_.ReadSLEB128(); |
488 | cur_token_pos_ = reader_.ReadPosition(); |
489 | cur_end_token_pos_ = reader_.ReadPosition(); |
490 | break; |
491 | case kVariableDeclaration: |
492 | cur_index_ = reader_.ReadSLEB128(); |
493 | cur_name_ = reader_.ReadUInt(); |
494 | cur_type_ = reader_.ReadUInt(); |
495 | cur_declaration_token_pos_ = reader_.ReadPosition(); |
496 | cur_token_pos_ = reader_.ReadPosition(); |
497 | break; |
498 | case kContextVariable: |
499 | cur_index_ = reader_.ReadSLEB128(); |
500 | break; |
501 | } |
502 | return true; |
503 | } |
504 | |
505 | // Returns true after iterator moved past the last entry and |
506 | // MoveNext() returned false. |
507 | bool IsDone() const { return entries_remaining_ < 0; } |
508 | |
509 | intptr_t Kind() const { return cur_kind_and_flags_ & kKindMask; } |
510 | bool IsScope() const { return Kind() == kScope; } |
511 | bool IsVariableDeclaration() const { return Kind() == kVariableDeclaration; } |
512 | bool IsContextVariable() const { return Kind() == kContextVariable; } |
513 | |
514 | intptr_t StartPC() const { return cur_start_pc_; } |
515 | intptr_t EndPC() const { |
516 | ASSERT(IsScope() || IsVariableDeclaration()); |
517 | return cur_end_pc_; |
518 | } |
519 | intptr_t ContextLevel() const { |
520 | ASSERT(IsScope()); |
521 | return cur_index_; |
522 | } |
523 | TokenPosition StartTokenPos() const { |
524 | ASSERT(IsScope() || IsVariableDeclaration()); |
525 | return cur_token_pos_; |
526 | } |
527 | TokenPosition EndTokenPos() const { |
528 | ASSERT(IsScope() || IsVariableDeclaration()); |
529 | return cur_end_token_pos_; |
530 | } |
531 | intptr_t Index() const { |
532 | ASSERT(IsVariableDeclaration() || IsContextVariable()); |
533 | return cur_index_; |
534 | } |
535 | StringPtr Name() const { |
536 | ASSERT(IsVariableDeclaration()); |
537 | return String::RawCast(object_pool_.ObjectAt(cur_name_)); |
538 | } |
539 | AbstractTypePtr Type() const { |
540 | ASSERT(IsVariableDeclaration()); |
541 | return AbstractType::RawCast(object_pool_.ObjectAt(cur_type_)); |
542 | } |
543 | TokenPosition DeclarationTokenPos() const { |
544 | ASSERT(IsVariableDeclaration()); |
545 | return cur_declaration_token_pos_; |
546 | } |
547 | bool IsCaptured() const { |
548 | ASSERT(IsVariableDeclaration()); |
549 | return (cur_kind_and_flags_ & kIsCapturedFlag) != 0; |
550 | } |
551 | |
552 | private: |
553 | Reader reader_; |
554 | const ObjectPool& object_pool_; |
555 | intptr_t entries_remaining_ = 0; |
556 | intptr_t cur_kind_and_flags_ = 0; |
557 | intptr_t cur_start_pc_ = 0; |
558 | intptr_t cur_end_pc_ = 0; |
559 | intptr_t cur_index_ = -1; |
560 | intptr_t cur_name_ = -1; |
561 | intptr_t cur_type_ = -1; |
562 | TokenPosition cur_token_pos_ = TokenPosition::kNoSource; |
563 | TokenPosition cur_declaration_token_pos_ = TokenPosition::kNoSource; |
564 | TokenPosition cur_end_token_pos_ = TokenPosition::kNoSource; |
565 | }; |
566 | |
567 | class BytecodeAttributesMapTraits { |
568 | public: |
569 | static const char* Name() { return "BytecodeAttributesMapTraits" ; } |
570 | static bool ReportStats() { return false; } |
571 | |
572 | static bool IsMatch(const Object& a, const Object& b) { |
573 | return a.raw() == b.raw(); |
574 | } |
575 | |
576 | static uword Hash(const Object& key) { |
577 | return String::HashRawSymbol(key.IsFunction() ? Function::Cast(key).name() |
578 | : Field::Cast(key).name()); |
579 | } |
580 | }; |
581 | typedef UnorderedHashMap<BytecodeAttributesMapTraits> BytecodeAttributesMap; |
582 | |
583 | bool IsStaticFieldGetterGeneratedAsInitializer(const Function& function, |
584 | Zone* zone); |
585 | |
586 | } // namespace kernel |
587 | } // namespace dart |
588 | |
589 | #endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_ |
590 | |