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_KERNEL_TRANSLATION_HELPER_H_ |
6 | #define RUNTIME_VM_COMPILER_FRONTEND_KERNEL_TRANSLATION_HELPER_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/backend/il.h" // For CompileType. |
13 | #include "vm/kernel.h" |
14 | #include "vm/kernel_binary.h" |
15 | #include "vm/object.h" |
16 | |
17 | namespace dart { |
18 | namespace kernel { |
19 | |
20 | class ConstantReader; |
21 | class KernelReaderHelper; |
22 | class TypeTranslator; |
23 | |
24 | class TranslationHelper { |
25 | public: |
26 | explicit TranslationHelper(Thread* thread); |
27 | |
28 | TranslationHelper(Thread* thread, Heap::Space space); |
29 | |
30 | virtual ~TranslationHelper() {} |
31 | |
32 | void Reset(); |
33 | |
34 | void InitFromScript(const Script& script); |
35 | |
36 | void InitFromKernelProgramInfo(const KernelProgramInfo& info); |
37 | |
38 | Thread* thread() { return thread_; } |
39 | |
40 | Zone* zone() { return zone_; } |
41 | |
42 | Isolate* isolate() { return isolate_; } |
43 | |
44 | Heap::Space allocation_space() { return allocation_space_; } |
45 | |
46 | // Access to strings. |
47 | const TypedData& string_offsets() const { return string_offsets_; } |
48 | void SetStringOffsets(const TypedData& string_offsets); |
49 | |
50 | const ExternalTypedData& string_data() const { return string_data_; } |
51 | void SetStringData(const ExternalTypedData& string_data); |
52 | |
53 | const TypedData& canonical_names() const { return canonical_names_; } |
54 | void SetCanonicalNames(const TypedData& canonical_names); |
55 | |
56 | const ExternalTypedData& metadata_payloads() const { |
57 | return metadata_payloads_; |
58 | } |
59 | void SetMetadataPayloads(const ExternalTypedData& metadata_payloads); |
60 | |
61 | const ExternalTypedData& metadata_mappings() const { |
62 | return metadata_mappings_; |
63 | } |
64 | void SetMetadataMappings(const ExternalTypedData& metadata_mappings); |
65 | |
66 | // Access to previously evaluated constants from the constants table. |
67 | const Array& constants() { return constants_; } |
68 | void SetConstants(const Array& constants); |
69 | |
70 | // Access to the raw bytes of the constants table. |
71 | const ExternalTypedData& constants_table() const { return constants_table_; } |
72 | void SetConstantsTable(const ExternalTypedData& constants_table); |
73 | |
74 | KernelProgramInfo& info() { return info_; } |
75 | |
76 | GrowableObjectArrayPtr EnsurePotentialPragmaFunctions(); |
77 | |
78 | void AddPotentialExtensionLibrary(const Library& library); |
79 | GrowableObjectArrayPtr GetPotentialExtensionLibraries(); |
80 | |
81 | void SetKernelProgramInfo(const KernelProgramInfo& info); |
82 | const KernelProgramInfo& GetKernelProgramInfo() const { return info_; } |
83 | |
84 | intptr_t StringOffset(StringIndex index) const; |
85 | intptr_t StringSize(StringIndex index) const; |
86 | |
87 | // The address of the backing store of the string with a given index. If the |
88 | // backing store is in the VM's heap this address is not safe for GC (call the |
89 | // function and use the result within a NoSafepointScope). |
90 | uint8_t* StringBuffer(StringIndex index) const; |
91 | |
92 | uint8_t CharacterAt(StringIndex string_index, intptr_t index); |
93 | bool StringEquals(StringIndex string_index, const char* other); |
94 | |
95 | // Accessors and predicates for canonical names. |
96 | NameIndex CanonicalNameParent(NameIndex name); |
97 | StringIndex CanonicalNameString(NameIndex name); |
98 | bool IsAdministrative(NameIndex name); |
99 | bool IsPrivate(NameIndex name); |
100 | bool IsRoot(NameIndex name); |
101 | bool IsLibrary(NameIndex name); |
102 | bool IsClass(NameIndex name); |
103 | bool IsMember(NameIndex name); |
104 | bool IsField(NameIndex name); |
105 | bool IsConstructor(NameIndex name); |
106 | bool IsProcedure(NameIndex name); |
107 | bool IsMethod(NameIndex name); |
108 | bool IsGetter(NameIndex name); |
109 | bool IsSetter(NameIndex name); |
110 | bool IsFactory(NameIndex name); |
111 | |
112 | // For a member (field, constructor, or procedure) return the canonical name |
113 | // of the enclosing class or library. |
114 | NameIndex EnclosingName(NameIndex name); |
115 | |
116 | InstancePtr Canonicalize(const Instance& instance); |
117 | |
118 | const String& DartString(const char* content) { |
119 | return DartString(content, allocation_space_); |
120 | } |
121 | const String& DartString(const char* content, Heap::Space space); |
122 | |
123 | String& DartString(StringIndex index) { |
124 | return DartString(index, allocation_space_); |
125 | } |
126 | String& DartString(StringIndex string_index, Heap::Space space); |
127 | |
128 | String& DartString(const uint8_t* utf8_array, |
129 | intptr_t len, |
130 | Heap::Space space); |
131 | |
132 | const String& DartSymbolPlain(const char* content) const; |
133 | String& DartSymbolPlain(StringIndex string_index) const; |
134 | const String& DartSymbolObfuscate(const char* content) const; |
135 | String& DartSymbolObfuscate(StringIndex string_index) const; |
136 | |
137 | String& DartIdentifier(const Library& lib, StringIndex string_index); |
138 | |
139 | const String& DartClassName(NameIndex kernel_class); |
140 | |
141 | const String& DartConstructorName(NameIndex constructor); |
142 | |
143 | const String& DartProcedureName(NameIndex procedure); |
144 | |
145 | const String& DartSetterName(NameIndex setter); |
146 | const String& DartSetterName(NameIndex parent, StringIndex setter); |
147 | |
148 | const String& DartGetterName(NameIndex getter); |
149 | const String& DartGetterName(NameIndex parent, StringIndex getter); |
150 | |
151 | const String& DartFieldName(NameIndex field); |
152 | const String& DartFieldName(NameIndex parent, StringIndex field); |
153 | |
154 | const String& DartMethodName(NameIndex method); |
155 | const String& DartMethodName(NameIndex parent, StringIndex method); |
156 | |
157 | const String& DartFactoryName(NameIndex factory); |
158 | |
159 | // A subclass overrides these when reading in the Kernel program in order to |
160 | // support recursive type expressions (e.g. for "implements X" ... |
161 | // annotations). |
162 | virtual LibraryPtr LookupLibraryByKernelLibrary(NameIndex library); |
163 | virtual ClassPtr LookupClassByKernelClass(NameIndex klass); |
164 | |
165 | FieldPtr LookupFieldByKernelField(NameIndex field); |
166 | FunctionPtr LookupStaticMethodByKernelProcedure(NameIndex procedure); |
167 | FunctionPtr LookupConstructorByKernelConstructor(NameIndex constructor); |
168 | FunctionPtr LookupConstructorByKernelConstructor(const Class& owner, |
169 | NameIndex constructor); |
170 | FunctionPtr LookupConstructorByKernelConstructor( |
171 | const Class& owner, |
172 | StringIndex constructor_name); |
173 | FunctionPtr LookupMethodByMember(NameIndex target, const String& method_name); |
174 | FunctionPtr LookupDynamicFunction(const Class& klass, const String& name); |
175 | |
176 | Type& GetDeclarationType(const Class& klass); |
177 | |
178 | void SetupFieldAccessorFunction(const Class& klass, |
179 | const Function& function, |
180 | const AbstractType& field_type); |
181 | |
182 | void ReportError(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
183 | void ReportError(const Script& script, |
184 | const TokenPosition position, |
185 | const char* format, |
186 | ...) PRINTF_ATTRIBUTE(4, 5); |
187 | void ReportError(const Error& prev_error, const char* format, ...) |
188 | PRINTF_ATTRIBUTE(3, 4); |
189 | void ReportError(const Error& prev_error, |
190 | const Script& script, |
191 | const TokenPosition position, |
192 | const char* format, |
193 | ...) PRINTF_ATTRIBUTE(5, 6); |
194 | |
195 | ArrayPtr GetBytecodeComponent() const { return info_.bytecode_component(); } |
196 | void SetBytecodeComponent(const Array& bytecode_component) { |
197 | info_.set_bytecode_component(bytecode_component); |
198 | } |
199 | |
200 | void SetExpressionEvaluationFunction(const Function& function) { |
201 | ASSERT(expression_evaluation_function_ == nullptr); |
202 | expression_evaluation_function_ = &Function::Handle(zone_, function.raw()); |
203 | } |
204 | const Function& GetExpressionEvaluationFunction() { |
205 | if (expression_evaluation_function_ == nullptr) { |
206 | return Function::null_function(); |
207 | } |
208 | return *expression_evaluation_function_; |
209 | } |
210 | void SetExpressionEvaluationRealClass(const Class& real_class) { |
211 | ASSERT(expression_evaluation_real_class_ == nullptr); |
212 | ASSERT(!real_class.IsNull()); |
213 | expression_evaluation_real_class_ = &Class::Handle(zone_, real_class.raw()); |
214 | } |
215 | ClassPtr GetExpressionEvaluationRealClass() { |
216 | ASSERT(expression_evaluation_real_class_ != nullptr); |
217 | return expression_evaluation_real_class_->raw(); |
218 | } |
219 | |
220 | private: |
221 | // This will mangle [name_to_modify] if necessary and make the result a symbol |
222 | // if asked. The result will be available in [name_to_modify] and it is also |
223 | // returned. If the name is private, the canonical name [parent] will be used |
224 | // to get the import URI of the library where the name is visible. |
225 | String& ManglePrivateName(NameIndex parent, |
226 | String* name_to_modify, |
227 | bool symbolize = true, |
228 | bool obfuscate = true); |
229 | String& ManglePrivateName(const Library& library, |
230 | String* name_to_modify, |
231 | bool symbolize = true, |
232 | bool obfuscate = true); |
233 | |
234 | Thread* thread_; |
235 | Zone* zone_; |
236 | Isolate* isolate_; |
237 | Heap::Space allocation_space_; |
238 | |
239 | TypedData& string_offsets_; |
240 | ExternalTypedData& string_data_; |
241 | TypedData& canonical_names_; |
242 | ExternalTypedData& metadata_payloads_; |
243 | ExternalTypedData& metadata_mappings_; |
244 | Array& constants_; |
245 | ExternalTypedData& constants_table_; |
246 | KernelProgramInfo& info_; |
247 | Smi& name_index_handle_; |
248 | GrowableObjectArray* potential_extension_libraries_ = nullptr; |
249 | Function* expression_evaluation_function_ = nullptr; |
250 | Class* expression_evaluation_real_class_ = nullptr; |
251 | |
252 | DISALLOW_COPY_AND_ASSIGN(TranslationHelper); |
253 | }; |
254 | |
255 | // Helper class that reads a kernel FunctionNode from binary. |
256 | // |
257 | // Use ReadUntilExcluding to read up to but not including a field. |
258 | // One can then for instance read the field from the call-site (and remember to |
259 | // call SetAt to inform this helper class), and then use this to read more. |
260 | // Simple fields are stored (e.g. integers) and can be fetched from this class. |
261 | // If asked to read a compound field (e.g. an expression) it will be skipped. |
262 | class FunctionNodeHelper { |
263 | public: |
264 | enum Field { |
265 | kStart, // tag. |
266 | kPosition, |
267 | kEndPosition, |
268 | kAsyncMarker, |
269 | kDartAsyncMarker, |
270 | kTypeParameters, |
271 | kTotalParameterCount, |
272 | kRequiredParameterCount, |
273 | kPositionalParameters, |
274 | kNamedParameters, |
275 | kReturnType, |
276 | kBody, |
277 | kEnd, |
278 | }; |
279 | |
280 | enum AsyncMarker : intptr_t { |
281 | kSync = 0, |
282 | kSyncStar = 1, |
283 | kAsync = 2, |
284 | kAsyncStar = 3, |
285 | kSyncYielding = 4, |
286 | }; |
287 | |
288 | explicit FunctionNodeHelper(KernelReaderHelper* helper) { |
289 | helper_ = helper; |
290 | next_read_ = kStart; |
291 | } |
292 | |
293 | void ReadUntilIncluding(Field field) { |
294 | ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
295 | } |
296 | |
297 | void ReadUntilExcluding(Field field); |
298 | |
299 | void SetNext(Field field) { next_read_ = field; } |
300 | void SetJustRead(Field field) { next_read_ = field + 1; } |
301 | |
302 | TokenPosition position_; |
303 | TokenPosition end_position_; |
304 | AsyncMarker async_marker_; |
305 | AsyncMarker dart_async_marker_; |
306 | intptr_t total_parameter_count_ = 0; |
307 | intptr_t required_parameter_count_ = 0; |
308 | |
309 | private: |
310 | KernelReaderHelper* helper_; |
311 | intptr_t next_read_; |
312 | |
313 | DISALLOW_COPY_AND_ASSIGN(FunctionNodeHelper); |
314 | }; |
315 | |
316 | class TypeParameterHelper { |
317 | public: |
318 | enum Field { |
319 | kStart, // tag. |
320 | kFlags, |
321 | kAnnotations, |
322 | kVariance, |
323 | kName, |
324 | kBound, |
325 | kDefaultType, |
326 | kEnd, |
327 | }; |
328 | |
329 | enum Flag { |
330 | kIsGenericCovariantImpl = 1 << 0, |
331 | }; |
332 | |
333 | explicit TypeParameterHelper(KernelReaderHelper* helper) { |
334 | helper_ = helper; |
335 | next_read_ = kStart; |
336 | } |
337 | |
338 | void ReadUntilIncluding(Field field) { |
339 | ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
340 | } |
341 | |
342 | void ReadUntilExcluding(Field field); |
343 | |
344 | void SetNext(Field field) { next_read_ = field; } |
345 | void SetJustRead(Field field) { next_read_ = field + 1; } |
346 | |
347 | void ReadUntilExcludingAndSetJustRead(Field field) { |
348 | ReadUntilExcluding(field); |
349 | SetJustRead(field); |
350 | } |
351 | |
352 | void Finish() { ReadUntilExcluding(kEnd); } |
353 | |
354 | bool IsGenericCovariantImpl() { |
355 | return (flags_ & kIsGenericCovariantImpl) != 0; |
356 | } |
357 | |
358 | TokenPosition position_; |
359 | uint8_t flags_ = 0; |
360 | StringIndex name_index_; |
361 | |
362 | private: |
363 | KernelReaderHelper* helper_; |
364 | intptr_t next_read_; |
365 | |
366 | DISALLOW_COPY_AND_ASSIGN(TypeParameterHelper); |
367 | }; |
368 | |
369 | // Helper class that reads a kernel VariableDeclaration from binary. |
370 | // |
371 | // Use ReadUntilExcluding to read up to but not including a field. |
372 | // One can then for instance read the field from the call-site (and remember to |
373 | // call SetAt to inform this helper class), and then use this to read more. |
374 | // Simple fields are stored (e.g. integers) and can be fetched from this class. |
375 | // If asked to read a compound field (e.g. an expression) it will be skipped. |
376 | class VariableDeclarationHelper { |
377 | public: |
378 | enum Field { |
379 | kPosition, |
380 | kEqualPosition, |
381 | kAnnotations, |
382 | kFlags, |
383 | kNameIndex, |
384 | kType, |
385 | kInitializer, |
386 | kEnd, |
387 | }; |
388 | |
389 | enum Flag { |
390 | kFinal = 1 << 0, |
391 | kConst = 1 << 1, |
392 | kCovariant = 1 << 3, |
393 | kIsGenericCovariantImpl = 1 << 5, |
394 | kLate = 1 << 6, |
395 | kRequired = 1 << 7, |
396 | }; |
397 | |
398 | explicit VariableDeclarationHelper(KernelReaderHelper* helper) |
399 | : annotation_count_(0), helper_(helper), next_read_(kPosition) {} |
400 | |
401 | void ReadUntilIncluding(Field field) { |
402 | ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
403 | } |
404 | |
405 | void ReadUntilExcluding(Field field); |
406 | |
407 | void SetNext(Field field) { next_read_ = field; } |
408 | void SetJustRead(Field field) { next_read_ = field + 1; } |
409 | |
410 | bool IsConst() const { return (flags_ & kConst) != 0; } |
411 | bool IsFinal() const { return (flags_ & kFinal) != 0; } |
412 | bool IsCovariant() const { return (flags_ & kCovariant) != 0; } |
413 | bool IsLate() const { return (flags_ & kLate) != 0; } |
414 | bool IsRequired() const { return (flags_ & kRequired) != 0; } |
415 | |
416 | bool IsGenericCovariantImpl() const { |
417 | return (flags_ & kIsGenericCovariantImpl) != 0; |
418 | } |
419 | |
420 | TokenPosition position_; |
421 | TokenPosition equals_position_; |
422 | uint8_t flags_ = 0; |
423 | StringIndex name_index_; |
424 | intptr_t annotation_count_ = 0; |
425 | |
426 | private: |
427 | KernelReaderHelper* helper_; |
428 | intptr_t next_read_; |
429 | |
430 | DISALLOW_COPY_AND_ASSIGN(VariableDeclarationHelper); |
431 | }; |
432 | |
433 | // Helper class that reads a kernel Field from binary. |
434 | // |
435 | // Use ReadUntilExcluding to read up to but not including a field. |
436 | // One can then for instance read the field from the call-site (and remember to |
437 | // call SetAt to inform this helper class), and then use this to read more. |
438 | // Simple fields are stored (e.g. integers) and can be fetched from this class. |
439 | // If asked to read a compound field (e.g. an expression) it will be skipped. |
440 | class FieldHelper { |
441 | public: |
442 | enum Field { |
443 | kStart, // tag. |
444 | kCanonicalName, |
445 | kSourceUriIndex, |
446 | kPosition, |
447 | kEndPosition, |
448 | kFlags, |
449 | kName, |
450 | kAnnotations, |
451 | kType, |
452 | kInitializer, |
453 | kEnd, |
454 | }; |
455 | |
456 | enum Flag { |
457 | kFinal = 1 << 0, |
458 | kConst = 1 << 1, |
459 | kStatic = 1 << 2, |
460 | kIsCovariant = 1 << 5, |
461 | kIsGenericCovariantImpl = 1 << 6, |
462 | kIsLate = 1 << 7, |
463 | kExtensionMember = 1 << 8, |
464 | }; |
465 | |
466 | explicit FieldHelper(KernelReaderHelper* helper) |
467 | : helper_(helper), next_read_(kStart) {} |
468 | |
469 | FieldHelper(KernelReaderHelper* helper, intptr_t offset); |
470 | |
471 | void ReadUntilIncluding(Field field) { |
472 | ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
473 | } |
474 | |
475 | void ReadUntilExcluding(Field field); |
476 | |
477 | void SetNext(Field field) { next_read_ = field; } |
478 | void SetJustRead(Field field) { next_read_ = field + 1; } |
479 | |
480 | bool IsConst() { return (flags_ & kConst) != 0; } |
481 | bool IsFinal() { return (flags_ & kFinal) != 0; } |
482 | bool IsStatic() { return (flags_ & kStatic) != 0; } |
483 | bool IsCovariant() const { return (flags_ & kIsCovariant) != 0; } |
484 | bool IsGenericCovariantImpl() { |
485 | return (flags_ & kIsGenericCovariantImpl) != 0; |
486 | } |
487 | bool IsLate() const { return (flags_ & kIsLate) != 0; } |
488 | bool IsExtensionMember() const { return (flags_ & kExtensionMember) != 0; } |
489 | |
490 | NameIndex canonical_name_; |
491 | TokenPosition position_; |
492 | TokenPosition end_position_; |
493 | uint32_t flags_ = 0; |
494 | intptr_t source_uri_index_ = 0; |
495 | intptr_t annotation_count_ = 0; |
496 | |
497 | private: |
498 | KernelReaderHelper* helper_; |
499 | intptr_t next_read_; |
500 | |
501 | DISALLOW_COPY_AND_ASSIGN(FieldHelper); |
502 | }; |
503 | |
504 | // Helper class that reads a kernel Procedure from binary. |
505 | // |
506 | // Use ReadUntilExcluding to read up to but not including a field. |
507 | // One can then for instance read the field from the call-site (and remember to |
508 | // call SetAt to inform this helper class), and then use this to read more. |
509 | // Simple fields are stored (e.g. integers) and can be fetched from this class. |
510 | // If asked to read a compound field (e.g. an expression) it will be skipped. |
511 | class ProcedureHelper { |
512 | public: |
513 | enum Field { |
514 | kStart, // tag. |
515 | kCanonicalName, |
516 | kSourceUriIndex, |
517 | kStartPosition, |
518 | kPosition, |
519 | kEndPosition, |
520 | kKind, |
521 | kFlags, |
522 | kName, |
523 | kAnnotations, |
524 | kForwardingStubSuperTarget, |
525 | kForwardingStubInterfaceTarget, |
526 | kMemberSignatureTarget, |
527 | kFunction, |
528 | kEnd, |
529 | }; |
530 | |
531 | enum Kind { |
532 | kMethod, |
533 | kGetter, |
534 | kSetter, |
535 | kOperator, |
536 | kFactory, |
537 | }; |
538 | |
539 | enum Flag { |
540 | kStatic = 1 << 0, |
541 | kAbstract = 1 << 1, |
542 | kExternal = 1 << 2, |
543 | kConst = 1 << 3, // Only for external const factories. |
544 | kForwardingStub = 1 << 4, |
545 | |
546 | // TODO(29841): Remove this line after the issue is resolved. |
547 | kRedirectingFactoryConstructor = 1 << 6, |
548 | kNoSuchMethodForwarder = 1 << 7, |
549 | kExtensionMember = 1 << 8, |
550 | kMemberSignature = 1 << 9, |
551 | }; |
552 | |
553 | explicit ProcedureHelper(KernelReaderHelper* helper) |
554 | : helper_(helper), next_read_(kStart) {} |
555 | |
556 | void ReadUntilIncluding(Field field) { |
557 | ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
558 | } |
559 | |
560 | void ReadUntilExcluding(Field field); |
561 | |
562 | void SetNext(Field field) { next_read_ = field; } |
563 | void SetJustRead(Field field) { next_read_ = field + 1; } |
564 | |
565 | bool IsStatic() const { return (flags_ & kStatic) != 0; } |
566 | bool IsAbstract() const { return (flags_ & kAbstract) != 0; } |
567 | bool IsExternal() const { return (flags_ & kExternal) != 0; } |
568 | bool IsConst() const { return (flags_ & kConst) != 0; } |
569 | bool IsForwardingStub() const { return (flags_ & kForwardingStub) != 0; } |
570 | bool IsRedirectingFactoryConstructor() const { |
571 | return (flags_ & kRedirectingFactoryConstructor) != 0; |
572 | } |
573 | bool IsNoSuchMethodForwarder() const { |
574 | return (flags_ & kNoSuchMethodForwarder) != 0; |
575 | } |
576 | bool IsExtensionMember() const { return (flags_ & kExtensionMember) != 0; } |
577 | bool IsMemberSignature() const { return (flags_ & kMemberSignature) != 0; } |
578 | |
579 | NameIndex canonical_name_; |
580 | TokenPosition start_position_; |
581 | TokenPosition position_; |
582 | TokenPosition end_position_; |
583 | Kind kind_; |
584 | uint32_t flags_ = 0; |
585 | intptr_t source_uri_index_ = 0; |
586 | intptr_t annotation_count_ = 0; |
587 | |
588 | // Only valid if the 'isForwardingStub' flag is set. |
589 | NameIndex forwarding_stub_super_target_; |
590 | |
591 | private: |
592 | KernelReaderHelper* helper_; |
593 | intptr_t next_read_; |
594 | |
595 | DISALLOW_COPY_AND_ASSIGN(ProcedureHelper); |
596 | }; |
597 | |
598 | // Helper class that reads a kernel Constructor from binary. |
599 | // |
600 | // Use ReadUntilExcluding to read up to but not including a field. |
601 | // One can then for instance read the field from the call-site (and remember to |
602 | // call SetAt to inform this helper class), and then use this to read more. |
603 | // Simple fields are stored (e.g. integers) and can be fetched from this class. |
604 | // If asked to read a compound field (e.g. an expression) it will be skipped. |
605 | class ConstructorHelper { |
606 | public: |
607 | enum Field { |
608 | kStart, // tag. |
609 | kCanonicalName, |
610 | kSourceUriIndex, |
611 | kStartPosition, |
612 | kPosition, |
613 | kEndPosition, |
614 | kFlags, |
615 | kName, |
616 | kAnnotations, |
617 | kFunction, |
618 | kInitializers, |
619 | kEnd, |
620 | }; |
621 | |
622 | enum Flag { |
623 | kConst = 1 << 0, |
624 | kExternal = 1 << 1, |
625 | kSynthetic = 1 << 2, |
626 | }; |
627 | |
628 | explicit ConstructorHelper(KernelReaderHelper* helper) |
629 | : helper_(helper), next_read_(kStart) {} |
630 | |
631 | void ReadUntilIncluding(Field field) { |
632 | ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
633 | } |
634 | |
635 | void ReadUntilExcluding(Field field); |
636 | |
637 | void SetNext(Field field) { next_read_ = field; } |
638 | void SetJustRead(Field field) { next_read_ = field + 1; } |
639 | |
640 | bool IsExternal() { return (flags_ & kExternal) != 0; } |
641 | bool IsConst() { return (flags_ & kConst) != 0; } |
642 | bool IsSynthetic() { return (flags_ & kSynthetic) != 0; } |
643 | |
644 | NameIndex canonical_name_; |
645 | TokenPosition start_position_; |
646 | TokenPosition position_; |
647 | TokenPosition end_position_; |
648 | uint8_t flags_ = 0; |
649 | intptr_t source_uri_index_ = 0; |
650 | intptr_t annotation_count_ = 0; |
651 | |
652 | private: |
653 | KernelReaderHelper* helper_; |
654 | intptr_t next_read_; |
655 | |
656 | DISALLOW_COPY_AND_ASSIGN(ConstructorHelper); |
657 | }; |
658 | |
659 | // Helper class that reads a kernel Class from binary. |
660 | // |
661 | // Use ReadUntilExcluding to read up to but not including a field. |
662 | // One can then for instance read the field from the call-site (and remember to |
663 | // call SetAt to inform this helper class), and then use this to read more. |
664 | // Simple fields are stored (e.g. integers) and can be fetched from this class. |
665 | // If asked to read a compound field (e.g. an expression) it will be skipped. |
666 | class ClassHelper { |
667 | public: |
668 | enum Field { |
669 | kStart, // tag. |
670 | kCanonicalName, |
671 | kSourceUriIndex, |
672 | kStartPosition, |
673 | kPosition, |
674 | kEndPosition, |
675 | kFlags, |
676 | kNameIndex, |
677 | kAnnotations, |
678 | kTypeParameters, |
679 | kSuperClass, |
680 | kMixinType, |
681 | kImplementedClasses, |
682 | kFields, |
683 | kConstructors, |
684 | kProcedures, |
685 | kClassIndex, |
686 | kEnd, |
687 | }; |
688 | |
689 | enum Flag { |
690 | kIsAbstract = 1 << 2, |
691 | kIsEnumClass = 1 << 3, |
692 | kIsAnonymousMixin = 1 << 4, |
693 | kIsEliminatedMixin = 1 << 5, |
694 | kFlagMixinDeclaration = 1 << 6, |
695 | kHasConstConstructor = 1 << 7, |
696 | }; |
697 | |
698 | explicit ClassHelper(KernelReaderHelper* helper) |
699 | : helper_(helper), next_read_(kStart) {} |
700 | |
701 | void ReadUntilIncluding(Field field) { |
702 | ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
703 | } |
704 | |
705 | void ReadUntilExcluding(Field field); |
706 | |
707 | void SetNext(Field field) { next_read_ = field; } |
708 | void SetJustRead(Field field) { next_read_ = field + 1; } |
709 | |
710 | bool is_abstract() const { return (flags_ & Flag::kIsAbstract) != 0; } |
711 | |
712 | bool is_enum_class() const { return (flags_ & Flag::kIsEnumClass) != 0; } |
713 | |
714 | bool is_transformed_mixin_application() const { |
715 | return (flags_ & Flag::kIsEliminatedMixin) != 0; |
716 | } |
717 | |
718 | bool has_const_constructor() const { |
719 | return (flags_ & Flag::kHasConstConstructor) != 0; |
720 | } |
721 | |
722 | NameIndex canonical_name_; |
723 | TokenPosition start_position_; |
724 | TokenPosition position_; |
725 | TokenPosition end_position_; |
726 | StringIndex name_index_; |
727 | intptr_t source_uri_index_ = 0; |
728 | intptr_t annotation_count_ = 0; |
729 | intptr_t procedure_count_ = 0; |
730 | uint8_t flags_ = 0; |
731 | |
732 | private: |
733 | KernelReaderHelper* helper_; |
734 | intptr_t next_read_; |
735 | |
736 | DISALLOW_COPY_AND_ASSIGN(ClassHelper); |
737 | }; |
738 | |
739 | // Helper class that reads a kernel Library from binary. |
740 | // |
741 | // Use ReadUntilExcluding to read up to but not including a field. |
742 | // One can then for instance read the field from the call-site (and remember to |
743 | // call SetAt to inform this helper class), and then use this to read more. |
744 | // Simple fields are stored (e.g. integers) and can be fetched from this class. |
745 | // If asked to read a compound field (e.g. an expression) it will be skipped. |
746 | class LibraryHelper { |
747 | public: |
748 | enum Field { |
749 | kFlags, |
750 | kLanguageVersion /* from binary version 27 */, |
751 | kCanonicalName, |
752 | kName, |
753 | kSourceUriIndex, |
754 | kProblemsAsJson, |
755 | kAnnotations, |
756 | kDependencies, |
757 | // There are other fields in a library: |
758 | // * kAdditionalExports |
759 | // * kParts |
760 | // * kTypedefs |
761 | // * kClasses |
762 | // * kToplevelField |
763 | // * kToplevelProcedures |
764 | // * kSourceReferences |
765 | // * kLibraryIndex |
766 | // but we never read them via this helper and it makes extending the format |
767 | // harder to keep the code around. |
768 | }; |
769 | |
770 | enum Flag { |
771 | kExternal = 1 << 0, |
772 | kSynthetic = 1 << 1, |
773 | kIsNonNullableByDefault = 1 << 2, |
774 | kNonNullableByDefaultCompiledModeBit1Weak = 1 << 3, |
775 | kNonNullableByDefaultCompiledModeBit2Strong = 1 << 4, |
776 | }; |
777 | |
778 | explicit LibraryHelper(KernelReaderHelper* helper, uint32_t binary_version) |
779 | : helper_(helper), binary_version_(binary_version), next_read_(kFlags) {} |
780 | |
781 | void ReadUntilIncluding(Field field) { |
782 | ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
783 | } |
784 | |
785 | void ReadUntilExcluding(Field field); |
786 | |
787 | void SetNext(Field field) { next_read_ = field; } |
788 | void SetJustRead(Field field) { next_read_ = field + 1; } |
789 | |
790 | bool IsExternal() const { return (flags_ & kExternal) != 0; } |
791 | bool IsSynthetic() const { return (flags_ & kSynthetic) != 0; } |
792 | bool IsNonNullableByDefault() const { |
793 | return (flags_ & kIsNonNullableByDefault) != 0; |
794 | } |
795 | NNBDCompiledMode GetNonNullableByDefaultCompiledMode() const { |
796 | bool weak = (flags_ & kNonNullableByDefaultCompiledModeBit1Weak) != 0; |
797 | bool strong = (flags_ & kNonNullableByDefaultCompiledModeBit2Strong) != 0; |
798 | if (weak && strong) return NNBDCompiledMode::kAgnostic; |
799 | if (strong) return NNBDCompiledMode::kStrong; |
800 | if (weak) return NNBDCompiledMode::kWeak; |
801 | return NNBDCompiledMode::kDisabled; |
802 | } |
803 | |
804 | uint8_t flags_ = 0; |
805 | NameIndex canonical_name_; |
806 | StringIndex name_index_; |
807 | intptr_t source_uri_index_ = 0; |
808 | |
809 | private: |
810 | KernelReaderHelper* helper_; |
811 | uint32_t binary_version_; |
812 | intptr_t next_read_; |
813 | |
814 | DISALLOW_COPY_AND_ASSIGN(LibraryHelper); |
815 | }; |
816 | |
817 | class LibraryDependencyHelper { |
818 | public: |
819 | enum Field { |
820 | kFileOffset, |
821 | kFlags, |
822 | kAnnotations, |
823 | kTargetLibrary, |
824 | kName, |
825 | kCombinators, |
826 | kEnd, |
827 | }; |
828 | |
829 | enum Flag { |
830 | Export = 1 << 0, |
831 | Deferred = 1 << 1, |
832 | }; |
833 | |
834 | enum CombinatorFlag { |
835 | Show = 1 << 0, |
836 | }; |
837 | |
838 | explicit LibraryDependencyHelper(KernelReaderHelper* helper) |
839 | : helper_(helper), next_read_(kFileOffset) {} |
840 | |
841 | void ReadUntilIncluding(Field field) { |
842 | ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1)); |
843 | } |
844 | |
845 | void ReadUntilExcluding(Field field); |
846 | |
847 | uint8_t flags_ = 0; |
848 | StringIndex name_index_; |
849 | NameIndex target_library_canonical_name_; |
850 | intptr_t annotation_count_ = 0; |
851 | |
852 | private: |
853 | KernelReaderHelper* helper_; |
854 | intptr_t next_read_; |
855 | |
856 | DISALLOW_COPY_AND_ASSIGN(LibraryDependencyHelper); |
857 | }; |
858 | |
859 | // Base class for helpers accessing metadata of a certain kind. |
860 | // Assumes that metadata is accessed in linear order. |
861 | class MetadataHelper { |
862 | public: |
863 | MetadataHelper(KernelReaderHelper* helper, |
864 | const char* tag, |
865 | bool precompiler_only); |
866 | |
867 | #if defined(DEBUG) |
868 | static void VerifyMetadataMappings( |
869 | const ExternalTypedData& metadata_mappings); |
870 | #endif |
871 | |
872 | protected: |
873 | // Look for metadata mapping with node offset greater or equal than the given. |
874 | intptr_t FindMetadataMapping(intptr_t node_offset); |
875 | |
876 | // Return offset of the metadata payload corresponding to the given node, |
877 | // or -1 if there is no metadata. |
878 | // Assumes metadata is accesses for nodes in linear order most of the time. |
879 | intptr_t GetNextMetadataPayloadOffset(intptr_t node_offset); |
880 | |
881 | // Returns metadata associated with component. |
882 | intptr_t GetComponentMetadataPayloadOffset(); |
883 | |
884 | KernelReaderHelper* helper_; |
885 | TranslationHelper& translation_helper_; |
886 | |
887 | private: |
888 | MetadataHelper(); |
889 | |
890 | void SetMetadataMappings(intptr_t mappings_offset, intptr_t mappings_num); |
891 | void ScanMetadataMappings(); |
892 | |
893 | const char* tag_; |
894 | bool mappings_scanned_; |
895 | bool precompiler_only_; |
896 | intptr_t mappings_offset_; |
897 | intptr_t mappings_num_; |
898 | intptr_t last_node_offset_; |
899 | intptr_t last_mapping_index_; |
900 | |
901 | DISALLOW_COPY_AND_ASSIGN(MetadataHelper); |
902 | }; |
903 | |
904 | struct DirectCallMetadata { |
905 | DirectCallMetadata(const Function& target, bool check_receiver_for_null) |
906 | : target_(target), check_receiver_for_null_(check_receiver_for_null) {} |
907 | |
908 | const Function& target_; |
909 | const bool check_receiver_for_null_; |
910 | }; |
911 | |
912 | // Helper class which provides access to direct call metadata. |
913 | class DirectCallMetadataHelper : public MetadataHelper { |
914 | public: |
915 | static const char* tag() { return "vm.direct-call.metadata" ; } |
916 | |
917 | explicit DirectCallMetadataHelper(KernelReaderHelper* helper); |
918 | |
919 | DirectCallMetadata GetDirectTargetForPropertyGet(intptr_t node_offset); |
920 | DirectCallMetadata GetDirectTargetForPropertySet(intptr_t node_offset); |
921 | DirectCallMetadata GetDirectTargetForMethodInvocation(intptr_t node_offset); |
922 | |
923 | private: |
924 | bool ReadMetadata(intptr_t node_offset, |
925 | NameIndex* target_name, |
926 | bool* check_receiver_for_null); |
927 | |
928 | DISALLOW_COPY_AND_ASSIGN(DirectCallMetadataHelper); |
929 | }; |
930 | |
931 | struct InferredTypeMetadata { |
932 | enum Flag { |
933 | kFlagNullable = 1 << 0, |
934 | kFlagInt = 1 << 1, |
935 | kFlagSkipCheck = 1 << 2, |
936 | kFlagConstant = 1 << 3, |
937 | kFlagReceiverNotInt = 1 << 4, |
938 | }; |
939 | |
940 | InferredTypeMetadata(intptr_t cid_, |
941 | uint8_t flags_, |
942 | const Object& constant_value_ = Object::null_object()) |
943 | : cid(cid_), flags(flags_), constant_value(constant_value_) {} |
944 | |
945 | const intptr_t cid; |
946 | const uint8_t flags; |
947 | const Object& constant_value; |
948 | |
949 | bool IsTrivial() const { |
950 | return (cid == kDynamicCid) && (flags == kFlagNullable); |
951 | } |
952 | bool IsNullable() const { return (flags & kFlagNullable) != 0; } |
953 | bool IsInt() const { |
954 | return (flags & kFlagInt) != 0 || cid == kMintCid || cid == kSmiCid; |
955 | } |
956 | bool IsSkipCheck() const { return (flags & kFlagSkipCheck) != 0; } |
957 | bool IsConstant() const { return (flags & kFlagConstant) != 0; } |
958 | bool ReceiverNotInt() const { return (flags & kFlagReceiverNotInt) != 0; } |
959 | |
960 | CompileType ToCompileType(Zone* zone) const { |
961 | if (IsInt() && cid == kDynamicCid) { |
962 | return CompileType::FromAbstractType( |
963 | Type::ZoneHandle( |
964 | zone, (IsNullable() ? Type::NullableIntType() : Type::IntType())), |
965 | IsNullable()); |
966 | } else { |
967 | return CompileType::CreateNullable(IsNullable(), cid); |
968 | } |
969 | } |
970 | }; |
971 | |
972 | // Helper class which provides access to inferred type metadata. |
973 | class InferredTypeMetadataHelper : public MetadataHelper { |
974 | public: |
975 | static const char* tag() { return "vm.inferred-type.metadata" ; } |
976 | |
977 | explicit InferredTypeMetadataHelper(KernelReaderHelper* helper, |
978 | ConstantReader* constant_reader); |
979 | |
980 | InferredTypeMetadata GetInferredType(intptr_t node_offset, |
981 | bool read_constant = true); |
982 | |
983 | private: |
984 | ConstantReader* constant_reader_; |
985 | |
986 | DISALLOW_COPY_AND_ASSIGN(InferredTypeMetadataHelper); |
987 | }; |
988 | |
989 | struct ProcedureAttributesMetadata { |
990 | static const int32_t kInvalidSelectorId = 0; |
991 | |
992 | bool method_or_setter_called_dynamically = true; |
993 | bool getter_called_dynamically = true; |
994 | bool has_this_uses = true; |
995 | bool has_non_this_uses = true; |
996 | bool has_tearoff_uses = true; |
997 | int32_t method_or_setter_selector_id = kInvalidSelectorId; |
998 | int32_t getter_selector_id = kInvalidSelectorId; |
999 | |
1000 | void InitializeFromFlags(uint8_t flags); |
1001 | }; |
1002 | |
1003 | // Helper class which provides access to direct call metadata. |
1004 | class ProcedureAttributesMetadataHelper : public MetadataHelper { |
1005 | public: |
1006 | static const char* tag() { return "vm.procedure-attributes.metadata" ; } |
1007 | |
1008 | explicit ProcedureAttributesMetadataHelper(KernelReaderHelper* helper); |
1009 | |
1010 | ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset); |
1011 | |
1012 | private: |
1013 | bool ReadMetadata(intptr_t node_offset, |
1014 | ProcedureAttributesMetadata* metadata); |
1015 | |
1016 | DISALLOW_COPY_AND_ASSIGN(ProcedureAttributesMetadataHelper); |
1017 | }; |
1018 | |
1019 | class ObfuscationProhibitionsMetadataHelper : public MetadataHelper { |
1020 | public: |
1021 | static const char* tag() { return "vm.obfuscation-prohibitions.metadata" ; } |
1022 | |
1023 | explicit ObfuscationProhibitionsMetadataHelper(KernelReaderHelper* helper); |
1024 | |
1025 | void ReadProhibitions() { ReadMetadata(0); } |
1026 | |
1027 | private: |
1028 | void ReadMetadata(intptr_t node_offset); |
1029 | |
1030 | DISALLOW_COPY_AND_ASSIGN(ObfuscationProhibitionsMetadataHelper); |
1031 | }; |
1032 | |
1033 | class LoadingUnitsMetadataHelper : public MetadataHelper { |
1034 | public: |
1035 | static const char* tag() { return "vm.loading-units.metadata" ; } |
1036 | |
1037 | explicit LoadingUnitsMetadataHelper(KernelReaderHelper* helper); |
1038 | |
1039 | void ReadLoadingUnits() { ReadMetadata(0); } |
1040 | |
1041 | private: |
1042 | void ReadMetadata(intptr_t node_offset); |
1043 | |
1044 | DISALLOW_COPY_AND_ASSIGN(LoadingUnitsMetadataHelper); |
1045 | }; |
1046 | |
1047 | struct CallSiteAttributesMetadata { |
1048 | const AbstractType* receiver_type = nullptr; |
1049 | }; |
1050 | |
1051 | // Helper class which provides access to direct call metadata. |
1052 | class CallSiteAttributesMetadataHelper : public MetadataHelper { |
1053 | public: |
1054 | static const char* tag() { return "vm.call-site-attributes.metadata" ; } |
1055 | |
1056 | CallSiteAttributesMetadataHelper(KernelReaderHelper* helper, |
1057 | TypeTranslator* type_translator); |
1058 | |
1059 | CallSiteAttributesMetadata GetCallSiteAttributes(intptr_t node_offset); |
1060 | |
1061 | private: |
1062 | bool ReadMetadata(intptr_t node_offset, CallSiteAttributesMetadata* metadata); |
1063 | |
1064 | TypeTranslator& type_translator_; |
1065 | |
1066 | DISALLOW_COPY_AND_ASSIGN(CallSiteAttributesMetadataHelper); |
1067 | }; |
1068 | |
1069 | // Information about a table selector computed by the TFA. |
1070 | struct TableSelectorInfo { |
1071 | int call_count = 0; |
1072 | bool called_on_null = true; |
1073 | bool torn_off = true; |
1074 | }; |
1075 | |
1076 | // Collection of table selector information for all selectors in the program. |
1077 | class TableSelectorMetadata : public ZoneAllocated { |
1078 | public: |
1079 | explicit TableSelectorMetadata(intptr_t num_selectors) |
1080 | : selectors(num_selectors) { |
1081 | selectors.FillWith(TableSelectorInfo(), 0, num_selectors); |
1082 | } |
1083 | |
1084 | GrowableArray<TableSelectorInfo> selectors; |
1085 | |
1086 | DISALLOW_COPY_AND_ASSIGN(TableSelectorMetadata); |
1087 | }; |
1088 | |
1089 | // Helper class which provides access to table selector metadata. |
1090 | class TableSelectorMetadataHelper : public MetadataHelper { |
1091 | public: |
1092 | static const char* tag() { return "vm.table-selector.metadata" ; } |
1093 | |
1094 | explicit TableSelectorMetadataHelper(KernelReaderHelper* helper); |
1095 | |
1096 | TableSelectorMetadata* GetTableSelectorMetadata(Zone* zone); |
1097 | |
1098 | private: |
1099 | static const uint8_t kCalledOnNullBit = 1 << 0; |
1100 | static const uint8_t kTornOffBit = 1 << 1; |
1101 | |
1102 | void ReadTableSelectorInfo(TableSelectorInfo* info); |
1103 | |
1104 | DISALLOW_COPY_AND_ASSIGN(TableSelectorMetadataHelper); |
1105 | }; |
1106 | |
1107 | // Information about a function regarding unboxed parameters and return value. |
1108 | class UnboxingInfoMetadata : public ZoneAllocated { |
1109 | public: |
1110 | enum UnboxingInfoTag { |
1111 | kBoxed = 0, |
1112 | kUnboxedIntCandidate = 1 << 0, |
1113 | kUnboxedDoubleCandidate = 1 << 1, |
1114 | kUnboxingCandidate = kUnboxedIntCandidate | kUnboxedDoubleCandidate, |
1115 | }; |
1116 | |
1117 | UnboxingInfoMetadata() : unboxed_args_info(0) { return_info = kBoxed; } |
1118 | |
1119 | void SetArgsCount(intptr_t num_args) { |
1120 | ASSERT(unboxed_args_info.is_empty()); |
1121 | unboxed_args_info.SetLength(num_args); |
1122 | unboxed_args_info.FillWith(kBoxed, 0, num_args); |
1123 | } |
1124 | |
1125 | GrowableArray<UnboxingInfoTag> unboxed_args_info; |
1126 | UnboxingInfoTag return_info; |
1127 | |
1128 | DISALLOW_COPY_AND_ASSIGN(UnboxingInfoMetadata); |
1129 | }; |
1130 | |
1131 | // Helper class which provides access to unboxing information metadata. |
1132 | class UnboxingInfoMetadataHelper : public MetadataHelper { |
1133 | public: |
1134 | static const char* tag() { return "vm.unboxing-info.metadata" ; } |
1135 | |
1136 | explicit UnboxingInfoMetadataHelper(KernelReaderHelper* helper); |
1137 | |
1138 | UnboxingInfoMetadata* GetUnboxingInfoMetadata(intptr_t node_offset); |
1139 | |
1140 | DISALLOW_COPY_AND_ASSIGN(UnboxingInfoMetadataHelper); |
1141 | }; |
1142 | |
1143 | class KernelReaderHelper { |
1144 | public: |
1145 | KernelReaderHelper(Zone* zone, |
1146 | TranslationHelper* translation_helper, |
1147 | const Script& script, |
1148 | const ExternalTypedData& data, |
1149 | intptr_t data_program_offset) |
1150 | : zone_(zone), |
1151 | translation_helper_(*translation_helper), |
1152 | reader_(data), |
1153 | script_(script), |
1154 | data_program_offset_(data_program_offset) {} |
1155 | |
1156 | KernelReaderHelper(Zone* zone, |
1157 | TranslationHelper* translation_helper, |
1158 | const uint8_t* data_buffer, |
1159 | intptr_t buffer_length, |
1160 | intptr_t data_program_offset) |
1161 | : zone_(zone), |
1162 | translation_helper_(*translation_helper), |
1163 | reader_(data_buffer, buffer_length), |
1164 | script_(Script::Handle(zone_)), |
1165 | data_program_offset_(data_program_offset) {} |
1166 | |
1167 | virtual ~KernelReaderHelper() = default; |
1168 | |
1169 | void SetOffset(intptr_t offset); |
1170 | |
1171 | intptr_t ReadListLength(); |
1172 | virtual void ReportUnexpectedTag(const char* variant, Tag tag); |
1173 | |
1174 | void ReadUntilFunctionNode(); |
1175 | |
1176 | Tag PeekTag(uint8_t* payload = NULL); |
1177 | |
1178 | protected: |
1179 | const Script& script() const { return script_; } |
1180 | |
1181 | virtual void set_current_script_id(intptr_t id) { |
1182 | // Do nothing by default. |
1183 | // This is overridden in KernelTokenPositionCollector. |
1184 | USE(id); |
1185 | } |
1186 | |
1187 | virtual void RecordTokenPosition(TokenPosition position) { |
1188 | // Do nothing by default. |
1189 | // This is overridden in KernelTokenPositionCollector. |
1190 | USE(position); |
1191 | } |
1192 | |
1193 | intptr_t ReaderOffset() const; |
1194 | void SkipBytes(intptr_t skip); |
1195 | bool ReadBool(); |
1196 | uint8_t ReadByte(); |
1197 | uint32_t ReadUInt(); |
1198 | uint32_t ReadUInt32(); |
1199 | uint32_t PeekUInt(); |
1200 | double ReadDouble(); |
1201 | uint32_t PeekListLength(); |
1202 | StringIndex ReadStringReference(); |
1203 | NameIndex ReadCanonicalNameReference(); |
1204 | NameIndex ReadInterfaceMemberNameReference(); |
1205 | StringIndex ReadNameAsStringIndex(); |
1206 | const String& ReadNameAsMethodName(); |
1207 | const String& ReadNameAsGetterName(); |
1208 | const String& ReadNameAsSetterName(); |
1209 | const String& ReadNameAsFieldName(); |
1210 | void SkipFlags(); |
1211 | void SkipStringReference(); |
1212 | void SkipConstantReference(); |
1213 | void SkipCanonicalNameReference(); |
1214 | void SkipInterfaceMemberNameReference(); |
1215 | void SkipDartType(); |
1216 | void SkipOptionalDartType(); |
1217 | void SkipInterfaceType(bool simple); |
1218 | void SkipFunctionType(bool simple); |
1219 | void SkipStatementList(); |
1220 | void SkipListOfExpressions(); |
1221 | void SkipListOfDartTypes(); |
1222 | void SkipListOfStrings(); |
1223 | void SkipListOfVariableDeclarations(); |
1224 | void SkipTypeParametersList(); |
1225 | void SkipInitializer(); |
1226 | void SkipExpression(); |
1227 | void SkipStatement(); |
1228 | void SkipFunctionNode(); |
1229 | void SkipName(); |
1230 | void SkipArguments(); |
1231 | void SkipVariableDeclaration(); |
1232 | void SkipLibraryCombinator(); |
1233 | void SkipLibraryDependency(); |
1234 | void SkipLibraryPart(); |
1235 | void SkipLibraryTypedef(); |
1236 | TokenPosition ReadPosition(); |
1237 | Tag ReadTag(uint8_t* payload = NULL); |
1238 | uint8_t ReadFlags() { return reader_.ReadFlags(); } |
1239 | Nullability ReadNullability(); |
1240 | Variance ReadVariance(); |
1241 | |
1242 | intptr_t SourceTableFieldCountFromFirstLibraryOffset(); |
1243 | intptr_t SourceTableSize(); |
1244 | intptr_t GetOffsetForSourceInfo(intptr_t index); |
1245 | String& SourceTableUriFor(intptr_t index); |
1246 | const String& GetSourceFor(intptr_t index); |
1247 | TypedDataPtr GetLineStartsFor(intptr_t index); |
1248 | String& SourceTableImportUriFor(intptr_t index, uint32_t binaryVersion); |
1249 | |
1250 | Zone* zone_; |
1251 | TranslationHelper& translation_helper_; |
1252 | Reader reader_; |
1253 | const Script& script_; |
1254 | // Some items like variables are specified in the kernel binary as |
1255 | // absolute offsets (as in, offsets within the whole kernel program) |
1256 | // of their declaration nodes. Hence, to cache and/or access them |
1257 | // uniquely from within a function's kernel data, we need to |
1258 | // add/subtract the offset of the kernel data in the over all |
1259 | // kernel program. |
1260 | intptr_t data_program_offset_; |
1261 | |
1262 | friend class BytecodeMetadataHelper; |
1263 | friend class BytecodeReaderHelper; |
1264 | friend class ClassHelper; |
1265 | friend class CallSiteAttributesMetadataHelper; |
1266 | friend class ConstantReader; |
1267 | friend class ConstantHelper; |
1268 | friend class ConstructorHelper; |
1269 | friend class DirectCallMetadataHelper; |
1270 | friend class FieldHelper; |
1271 | friend class FunctionNodeHelper; |
1272 | friend class InferredTypeMetadataHelper; |
1273 | friend class KernelLoader; |
1274 | friend class LibraryDependencyHelper; |
1275 | friend class LibraryHelper; |
1276 | friend class MetadataHelper; |
1277 | friend class ProcedureAttributesMetadataHelper; |
1278 | friend class ProcedureHelper; |
1279 | friend class SimpleExpressionConverter; |
1280 | friend class ScopeBuilder; |
1281 | friend class TableSelectorMetadataHelper; |
1282 | friend class TypeParameterHelper; |
1283 | friend class TypeTranslator; |
1284 | friend class UnboxingInfoMetadataHelper; |
1285 | friend class VariableDeclarationHelper; |
1286 | friend class ObfuscationProhibitionsMetadataHelper; |
1287 | friend class LoadingUnitsMetadataHelper; |
1288 | friend bool NeedsDynamicInvocationForwarder(const Function& function); |
1289 | |
1290 | private: |
1291 | DISALLOW_COPY_AND_ASSIGN(KernelReaderHelper); |
1292 | }; |
1293 | |
1294 | class ActiveClass { |
1295 | public: |
1296 | ActiveClass() |
1297 | : klass(NULL), |
1298 | member(NULL), |
1299 | enclosing(NULL), |
1300 | local_type_parameters(NULL) {} |
1301 | |
1302 | bool HasMember() { return member != NULL; } |
1303 | |
1304 | bool MemberIsProcedure() { |
1305 | ASSERT(member != NULL); |
1306 | FunctionLayout::Kind function_kind = member->kind(); |
1307 | return function_kind == FunctionLayout::kRegularFunction || |
1308 | function_kind == FunctionLayout::kGetterFunction || |
1309 | function_kind == FunctionLayout::kSetterFunction || |
1310 | function_kind == FunctionLayout::kMethodExtractor || |
1311 | function_kind == FunctionLayout::kDynamicInvocationForwarder || |
1312 | member->IsFactory(); |
1313 | } |
1314 | |
1315 | bool MemberIsFactoryProcedure() { |
1316 | ASSERT(member != NULL); |
1317 | return member->IsFactory(); |
1318 | } |
1319 | |
1320 | bool RequireLegacyErasure(bool null_safety) const { |
1321 | return klass != nullptr && !null_safety && |
1322 | Library::Handle(klass->library()).nnbd_compiled_mode() == |
1323 | NNBDCompiledMode::kAgnostic; |
1324 | } |
1325 | |
1326 | intptr_t MemberTypeParameterCount(Zone* zone); |
1327 | |
1328 | intptr_t ClassNumTypeArguments() { |
1329 | ASSERT(klass != NULL); |
1330 | return klass->NumTypeArguments(); |
1331 | } |
1332 | |
1333 | void RecordDerivedTypeParameter(Zone* zone, |
1334 | const TypeParameter& original, |
1335 | const TypeParameter& derived) { |
1336 | if (original.raw() != derived.raw() && |
1337 | original.bound() == AbstractType::null()) { |
1338 | if (derived_type_parameters == nullptr) { |
1339 | derived_type_parameters = &GrowableObjectArray::Handle( |
1340 | zone, GrowableObjectArray::New(Heap::kOld)); |
1341 | } |
1342 | derived_type_parameters->Add(derived); |
1343 | } |
1344 | } |
1345 | |
1346 | const char* ToCString() { |
1347 | return member != NULL ? member->ToCString() : klass->ToCString(); |
1348 | } |
1349 | |
1350 | // The current enclosing class (or the library top-level class). |
1351 | const Class* klass; |
1352 | |
1353 | const Function* member; |
1354 | |
1355 | // The innermost enclosing function. This is used for building types, as a |
1356 | // parent for function types. |
1357 | const Function* enclosing; |
1358 | |
1359 | const TypeArguments* local_type_parameters; |
1360 | |
1361 | GrowableObjectArray* derived_type_parameters = nullptr; |
1362 | }; |
1363 | |
1364 | class ActiveClassScope { |
1365 | public: |
1366 | ActiveClassScope(ActiveClass* active_class, const Class* klass) |
1367 | : active_class_(active_class), saved_(*active_class) { |
1368 | active_class_->klass = klass; |
1369 | } |
1370 | |
1371 | ~ActiveClassScope() { *active_class_ = saved_; } |
1372 | |
1373 | private: |
1374 | ActiveClass* active_class_; |
1375 | ActiveClass saved_; |
1376 | |
1377 | DISALLOW_COPY_AND_ASSIGN(ActiveClassScope); |
1378 | }; |
1379 | |
1380 | class ActiveMemberScope { |
1381 | public: |
1382 | ActiveMemberScope(ActiveClass* active_class, const Function* member) |
1383 | : active_class_(active_class), saved_(*active_class) { |
1384 | // The class is inherited. |
1385 | active_class_->member = member; |
1386 | } |
1387 | |
1388 | ~ActiveMemberScope() { *active_class_ = saved_; } |
1389 | |
1390 | private: |
1391 | ActiveClass* active_class_; |
1392 | ActiveClass saved_; |
1393 | |
1394 | DISALLOW_COPY_AND_ASSIGN(ActiveMemberScope); |
1395 | }; |
1396 | |
1397 | class ActiveEnclosingFunctionScope { |
1398 | public: |
1399 | ActiveEnclosingFunctionScope(ActiveClass* active_class, |
1400 | const Function* enclosing) |
1401 | : active_class_(active_class), saved_(*active_class) { |
1402 | active_class_->enclosing = enclosing; |
1403 | } |
1404 | |
1405 | ~ActiveEnclosingFunctionScope() { *active_class_ = saved_; } |
1406 | |
1407 | private: |
1408 | ActiveClass* active_class_; |
1409 | ActiveClass saved_; |
1410 | |
1411 | DISALLOW_COPY_AND_ASSIGN(ActiveEnclosingFunctionScope); |
1412 | }; |
1413 | |
1414 | class { |
1415 | public: |
1416 | // Set the local type parameters of the ActiveClass to be exactly all type |
1417 | // parameters defined by 'innermost' and any enclosing *closures* (but not |
1418 | // enclosing methods/top-level functions/classes). |
1419 | // |
1420 | // Also, the enclosing function is set to 'innermost'. |
1421 | (ActiveClass* active_class, |
1422 | const Function& innermost, |
1423 | Zone* Z); |
1424 | |
1425 | // Append the list of the local type parameters to the list in ActiveClass. |
1426 | // |
1427 | // Also, the enclosing function is set to 'function'. |
1428 | (ActiveClass* active_class, |
1429 | const Function* function, |
1430 | const TypeArguments& new_params, |
1431 | Zone* Z); |
1432 | |
1433 | () { *active_class_ = saved_; } |
1434 | |
1435 | private: |
1436 | ActiveClass* ; |
1437 | ActiveClass ; |
1438 | |
1439 | DISALLOW_COPY_AND_ASSIGN(); |
1440 | }; |
1441 | |
1442 | class TypeTranslator { |
1443 | public: |
1444 | TypeTranslator(KernelReaderHelper* helper, |
1445 | ConstantReader* constant_reader, |
1446 | ActiveClass* active_class, |
1447 | bool finalize = false, |
1448 | bool apply_legacy_erasure = false); |
1449 | |
1450 | AbstractType& BuildType(); |
1451 | AbstractType& BuildTypeWithoutFinalization(); |
1452 | |
1453 | const TypeArguments& BuildTypeArguments(intptr_t length); |
1454 | |
1455 | const TypeArguments& BuildInstantiatedTypeArguments( |
1456 | const Class& receiver_class, |
1457 | intptr_t length); |
1458 | |
1459 | void LoadAndSetupTypeParameters(ActiveClass* active_class, |
1460 | const Object& set_on, |
1461 | intptr_t type_parameter_count, |
1462 | const Function& parameterized_function); |
1463 | |
1464 | const Type& ReceiverType(const Class& klass); |
1465 | |
1466 | void SetupFunctionParameters(const Class& klass, |
1467 | const Function& function, |
1468 | bool is_method, |
1469 | bool is_closure, |
1470 | FunctionNodeHelper* function_node_helper); |
1471 | |
1472 | private: |
1473 | void SetupUnboxingInfoMetadata(const Function& function, |
1474 | intptr_t library_kernel_offset); |
1475 | void SetupUnboxingInfoMetadataForFieldAccessors( |
1476 | const Function& field_accessor, |
1477 | intptr_t library_kernel_offset); |
1478 | |
1479 | void BuildTypeInternal(); |
1480 | void BuildInterfaceType(bool simple); |
1481 | void BuildFunctionType(bool simple); |
1482 | void BuildTypeParameterType(); |
1483 | |
1484 | class TypeParameterScope { |
1485 | public: |
1486 | TypeParameterScope(TypeTranslator* translator, intptr_t parameter_count) |
1487 | : parameter_count_(parameter_count), |
1488 | outer_(translator->type_parameter_scope_), |
1489 | translator_(translator) { |
1490 | outer_parameter_count_ = 0; |
1491 | if (outer_ != NULL) { |
1492 | outer_parameter_count_ = |
1493 | outer_->outer_parameter_count_ + outer_->parameter_count_; |
1494 | } |
1495 | translator_->type_parameter_scope_ = this; |
1496 | } |
1497 | ~TypeParameterScope() { translator_->type_parameter_scope_ = outer_; } |
1498 | |
1499 | TypeParameterScope* outer() const { return outer_; } |
1500 | intptr_t parameter_count() const { return parameter_count_; } |
1501 | intptr_t outer_parameter_count() const { return outer_parameter_count_; } |
1502 | |
1503 | private: |
1504 | intptr_t parameter_count_; |
1505 | intptr_t outer_parameter_count_; |
1506 | TypeParameterScope* outer_; |
1507 | TypeTranslator* translator_; |
1508 | }; |
1509 | |
1510 | KernelReaderHelper* helper_; |
1511 | ConstantReader* constant_reader_; |
1512 | TranslationHelper& translation_helper_; |
1513 | ActiveClass* const active_class_; |
1514 | TypeParameterScope* type_parameter_scope_; |
1515 | InferredTypeMetadataHelper inferred_type_metadata_helper_; |
1516 | UnboxingInfoMetadataHelper unboxing_info_metadata_helper_; |
1517 | Zone* zone_; |
1518 | AbstractType& result_; |
1519 | bool finalize_; |
1520 | const bool apply_legacy_erasure_; |
1521 | |
1522 | friend class ScopeBuilder; |
1523 | friend class KernelLoader; |
1524 | |
1525 | DISALLOW_COPY_AND_ASSIGN(TypeTranslator); |
1526 | }; |
1527 | |
1528 | } // namespace kernel |
1529 | } // namespace dart |
1530 | |
1531 | #endif // RUNTIME_VM_COMPILER_FRONTEND_KERNEL_TRANSLATION_HELPER_H_ |
1532 | |