| 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 | |