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