| 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 | #include "vm/compiler/frontend/kernel_translation_helper.h" |
| 6 | |
| 7 | #include "vm/class_finalizer.h" |
| 8 | #include "vm/compiler/aot/precompiler.h" |
| 9 | #include "vm/compiler/backend/flow_graph_compiler.h" |
| 10 | #include "vm/compiler/frontend/constant_reader.h" |
| 11 | #include "vm/flags.h" |
| 12 | #include "vm/log.h" |
| 13 | #include "vm/object_store.h" |
| 14 | #include "vm/parser.h" // for ParsedFunction |
| 15 | #include "vm/symbols.h" |
| 16 | |
| 17 | #define Z (zone_) |
| 18 | #define H (translation_helper_) |
| 19 | #define T (type_translator_) |
| 20 | #define I Isolate::Current() |
| 21 | |
| 22 | namespace dart { |
| 23 | namespace kernel { |
| 24 | |
| 25 | TranslationHelper::TranslationHelper(Thread* thread) |
| 26 | : thread_(thread), |
| 27 | zone_(thread->zone()), |
| 28 | isolate_(thread->isolate()), |
| 29 | allocation_space_(Heap::kNew), |
| 30 | string_offsets_(TypedData::Handle(Z)), |
| 31 | string_data_(ExternalTypedData::Handle(Z)), |
| 32 | canonical_names_(TypedData::Handle(Z)), |
| 33 | metadata_payloads_(ExternalTypedData::Handle(Z)), |
| 34 | metadata_mappings_(ExternalTypedData::Handle(Z)), |
| 35 | constants_(Array::Handle(Z)), |
| 36 | constants_table_(ExternalTypedData::Handle(Z)), |
| 37 | info_(KernelProgramInfo::Handle(Z)), |
| 38 | name_index_handle_(Smi::Handle(Z)) {} |
| 39 | |
| 40 | TranslationHelper::TranslationHelper(Thread* thread, Heap::Space space) |
| 41 | : thread_(thread), |
| 42 | zone_(thread->zone()), |
| 43 | isolate_(thread->isolate()), |
| 44 | allocation_space_(space), |
| 45 | string_offsets_(TypedData::Handle(Z)), |
| 46 | string_data_(ExternalTypedData::Handle(Z)), |
| 47 | canonical_names_(TypedData::Handle(Z)), |
| 48 | metadata_payloads_(ExternalTypedData::Handle(Z)), |
| 49 | metadata_mappings_(ExternalTypedData::Handle(Z)), |
| 50 | constants_(Array::Handle(Z)), |
| 51 | constants_table_(ExternalTypedData::Handle(Z)), |
| 52 | info_(KernelProgramInfo::Handle(Z)), |
| 53 | name_index_handle_(Smi::Handle(Z)) {} |
| 54 | |
| 55 | void TranslationHelper::Reset() { |
| 56 | string_offsets_ = TypedData::null(); |
| 57 | string_data_ = ExternalTypedData::null(); |
| 58 | canonical_names_ = TypedData::null(); |
| 59 | metadata_payloads_ = ExternalTypedData::null(); |
| 60 | metadata_mappings_ = ExternalTypedData::null(); |
| 61 | constants_ = Array::null(); |
| 62 | } |
| 63 | |
| 64 | void TranslationHelper::InitFromScript(const Script& script) { |
| 65 | const KernelProgramInfo& info = |
| 66 | KernelProgramInfo::Handle(Z, script.kernel_program_info()); |
| 67 | if (info.IsNull()) { |
| 68 | // If there is no kernel data associated with the script, then |
| 69 | // do not bother initializing!. |
| 70 | // This can happen with few special functions like |
| 71 | // NoSuchMethodDispatcher and InvokeFieldDispatcher. |
| 72 | return; |
| 73 | } |
| 74 | InitFromKernelProgramInfo(info); |
| 75 | } |
| 76 | |
| 77 | void TranslationHelper::InitFromKernelProgramInfo( |
| 78 | const KernelProgramInfo& info) { |
| 79 | SetStringOffsets(TypedData::Handle(Z, info.string_offsets())); |
| 80 | SetStringData(ExternalTypedData::Handle(Z, info.string_data())); |
| 81 | SetCanonicalNames(TypedData::Handle(Z, info.canonical_names())); |
| 82 | SetMetadataPayloads(ExternalTypedData::Handle(Z, info.metadata_payloads())); |
| 83 | SetMetadataMappings(ExternalTypedData::Handle(Z, info.metadata_mappings())); |
| 84 | SetConstants(Array::Handle(Z, info.constants())); |
| 85 | SetConstantsTable(ExternalTypedData::Handle(Z, info.constants_table())); |
| 86 | SetKernelProgramInfo(info); |
| 87 | } |
| 88 | |
| 89 | GrowableObjectArrayPtr TranslationHelper::EnsurePotentialPragmaFunctions() { |
| 90 | auto& funcs = |
| 91 | GrowableObjectArray::Handle(Z, info_.potential_pragma_functions()); |
| 92 | if (funcs.IsNull()) { |
| 93 | funcs = GrowableObjectArray::New(16, Heap::kNew); |
| 94 | info_.set_potential_pragma_functions(funcs); |
| 95 | } |
| 96 | return funcs.raw(); |
| 97 | } |
| 98 | |
| 99 | void TranslationHelper::AddPotentialExtensionLibrary(const Library& library) { |
| 100 | if (potential_extension_libraries_ == nullptr) { |
| 101 | potential_extension_libraries_ = |
| 102 | &GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
| 103 | } |
| 104 | potential_extension_libraries_->Add(library); |
| 105 | } |
| 106 | |
| 107 | GrowableObjectArrayPtr TranslationHelper::GetPotentialExtensionLibraries() { |
| 108 | if (potential_extension_libraries_ != nullptr) { |
| 109 | GrowableObjectArray* result = potential_extension_libraries_; |
| 110 | potential_extension_libraries_ = nullptr; |
| 111 | return result->raw(); |
| 112 | } |
| 113 | return GrowableObjectArray::null(); |
| 114 | } |
| 115 | |
| 116 | void TranslationHelper::SetStringOffsets(const TypedData& string_offsets) { |
| 117 | ASSERT(string_offsets_.IsNull()); |
| 118 | string_offsets_ = string_offsets.raw(); |
| 119 | } |
| 120 | |
| 121 | void TranslationHelper::SetStringData(const ExternalTypedData& string_data) { |
| 122 | ASSERT(string_data_.IsNull()); |
| 123 | string_data_ = string_data.raw(); |
| 124 | } |
| 125 | |
| 126 | void TranslationHelper::SetCanonicalNames(const TypedData& canonical_names) { |
| 127 | ASSERT(canonical_names_.IsNull()); |
| 128 | canonical_names_ = canonical_names.raw(); |
| 129 | } |
| 130 | |
| 131 | void TranslationHelper::SetMetadataPayloads( |
| 132 | const ExternalTypedData& metadata_payloads) { |
| 133 | ASSERT(metadata_payloads_.IsNull()); |
| 134 | ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize)); |
| 135 | metadata_payloads_ = metadata_payloads.raw(); |
| 136 | } |
| 137 | |
| 138 | void TranslationHelper::SetMetadataMappings( |
| 139 | const ExternalTypedData& metadata_mappings) { |
| 140 | ASSERT(metadata_mappings_.IsNull()); |
| 141 | metadata_mappings_ = metadata_mappings.raw(); |
| 142 | } |
| 143 | |
| 144 | void TranslationHelper::SetConstants(const Array& constants) { |
| 145 | ASSERT(constants_.IsNull() || |
| 146 | (constants.IsNull() || constants.Length() == 0)); |
| 147 | constants_ = constants.raw(); |
| 148 | } |
| 149 | |
| 150 | void TranslationHelper::SetConstantsTable( |
| 151 | const ExternalTypedData& constants_table) { |
| 152 | ASSERT(constants_table_.IsNull()); |
| 153 | constants_table_ = constants_table.raw(); |
| 154 | } |
| 155 | |
| 156 | void TranslationHelper::SetKernelProgramInfo(const KernelProgramInfo& info) { |
| 157 | info_ = info.raw(); |
| 158 | } |
| 159 | |
| 160 | intptr_t TranslationHelper::StringOffset(StringIndex index) const { |
| 161 | return string_offsets_.GetUint32(index << 2); |
| 162 | } |
| 163 | |
| 164 | intptr_t TranslationHelper::StringSize(StringIndex index) const { |
| 165 | return StringOffset(StringIndex(index + 1)) - StringOffset(index); |
| 166 | } |
| 167 | |
| 168 | uint8_t TranslationHelper::CharacterAt(StringIndex string_index, |
| 169 | intptr_t index) { |
| 170 | ASSERT(index < StringSize(string_index)); |
| 171 | return string_data_.GetUint8(StringOffset(string_index) + index); |
| 172 | } |
| 173 | |
| 174 | uint8_t* TranslationHelper::StringBuffer(StringIndex string_index) const { |
| 175 | // Though this implementation appears like it could be replaced by |
| 176 | // string_data_.DataAddr(StringOffset(string_index)), it can't quite. If the |
| 177 | // last string in the string table is a zero length string, then the latter |
| 178 | // expression will try to return the address that is one past the backing |
| 179 | // store of the string_data_ table. Though this is safe in C++ as long as the |
| 180 | // address is not dereferenced, it will trigger the assert in |
| 181 | // ExternalTypedData::DataAddr. |
| 182 | ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0); |
| 183 | return reinterpret_cast<uint8_t*>(string_data_.DataAddr(0)) + |
| 184 | StringOffset(string_index); |
| 185 | } |
| 186 | |
| 187 | bool TranslationHelper::StringEquals(StringIndex string_index, |
| 188 | const char* other) { |
| 189 | intptr_t length = strlen(other); |
| 190 | if (length != StringSize(string_index)) return false; |
| 191 | |
| 192 | NoSafepointScope no_safepoint; |
| 193 | return memcmp(StringBuffer(string_index), other, length) == 0; |
| 194 | } |
| 195 | |
| 196 | NameIndex TranslationHelper::CanonicalNameParent(NameIndex name) { |
| 197 | // Canonical names are pairs of 4-byte parent and string indexes, so the size |
| 198 | // of an entry is 8 bytes. The parent is biased: 0 represents the root name |
| 199 | // and N+1 represents the name with index N. |
| 200 | return NameIndex(static_cast<intptr_t>(canonical_names_.GetUint32(8 * name)) - |
| 201 | 1); |
| 202 | } |
| 203 | |
| 204 | StringIndex TranslationHelper::CanonicalNameString(NameIndex name) { |
| 205 | return StringIndex(canonical_names_.GetUint32((8 * name) + 4)); |
| 206 | } |
| 207 | |
| 208 | bool TranslationHelper::IsAdministrative(NameIndex name) { |
| 209 | // Administrative names start with '@'. |
| 210 | StringIndex name_string = CanonicalNameString(name); |
| 211 | return (StringSize(name_string) > 0) && (CharacterAt(name_string, 0) == '@'); |
| 212 | } |
| 213 | |
| 214 | bool TranslationHelper::IsPrivate(NameIndex name) { |
| 215 | // Private names start with '_'. |
| 216 | StringIndex name_string = CanonicalNameString(name); |
| 217 | return (StringSize(name_string) > 0) && (CharacterAt(name_string, 0) == '_'); |
| 218 | } |
| 219 | |
| 220 | bool TranslationHelper::IsRoot(NameIndex name) { |
| 221 | return name == -1; |
| 222 | } |
| 223 | |
| 224 | bool TranslationHelper::IsLibrary(NameIndex name) { |
| 225 | // Libraries are the only canonical names with the root as their parent. |
| 226 | return !IsRoot(name) && IsRoot(CanonicalNameParent(name)); |
| 227 | } |
| 228 | |
| 229 | bool TranslationHelper::IsClass(NameIndex name) { |
| 230 | // Classes have the library as their parent and are not an administrative |
| 231 | // name starting with @. |
| 232 | return !IsAdministrative(name) && !IsRoot(name) && |
| 233 | IsLibrary(CanonicalNameParent(name)); |
| 234 | } |
| 235 | |
| 236 | bool TranslationHelper::IsMember(NameIndex name) { |
| 237 | return IsConstructor(name) || IsField(name) || IsProcedure(name); |
| 238 | } |
| 239 | |
| 240 | bool TranslationHelper::IsField(NameIndex name) { |
| 241 | // Fields with private names have the import URI of the library where they are |
| 242 | // visible as the parent and the string "@fields" as the parent's parent. |
| 243 | // Fields with non-private names have the string "@fields' as the parent. |
| 244 | if (IsRoot(name)) { |
| 245 | return false; |
| 246 | } |
| 247 | NameIndex kind = CanonicalNameParent(name); |
| 248 | if (IsPrivate(name)) { |
| 249 | kind = CanonicalNameParent(kind); |
| 250 | } |
| 251 | return StringEquals(CanonicalNameString(kind), "@fields" ); |
| 252 | } |
| 253 | |
| 254 | bool TranslationHelper::IsConstructor(NameIndex name) { |
| 255 | // Constructors with private names have the import URI of the library where |
| 256 | // they are visible as the parent and the string "@constructors" as the |
| 257 | // parent's parent. Constructors with non-private names have the string |
| 258 | // "@constructors" as the parent. |
| 259 | if (IsRoot(name)) { |
| 260 | return false; |
| 261 | } |
| 262 | NameIndex kind = CanonicalNameParent(name); |
| 263 | if (IsPrivate(name)) { |
| 264 | kind = CanonicalNameParent(kind); |
| 265 | } |
| 266 | return StringEquals(CanonicalNameString(kind), "@constructors" ); |
| 267 | } |
| 268 | |
| 269 | bool TranslationHelper::IsProcedure(NameIndex name) { |
| 270 | return IsMethod(name) || IsGetter(name) || IsSetter(name) || IsFactory(name); |
| 271 | } |
| 272 | |
| 273 | bool TranslationHelper::IsMethod(NameIndex name) { |
| 274 | // Methods with private names have the import URI of the library where they |
| 275 | // are visible as the parent and the string "@methods" as the parent's parent. |
| 276 | // Methods with non-private names have the string "@methods" as the parent. |
| 277 | if (IsRoot(name)) { |
| 278 | return false; |
| 279 | } |
| 280 | NameIndex kind = CanonicalNameParent(name); |
| 281 | if (IsPrivate(name)) { |
| 282 | kind = CanonicalNameParent(kind); |
| 283 | } |
| 284 | return StringEquals(CanonicalNameString(kind), "@methods" ); |
| 285 | } |
| 286 | |
| 287 | bool TranslationHelper::IsGetter(NameIndex name) { |
| 288 | // Getters with private names have the import URI of the library where they |
| 289 | // are visible as the parent and the string "@getters" as the parent's parent. |
| 290 | // Getters with non-private names have the string "@getters" as the parent. |
| 291 | if (IsRoot(name)) { |
| 292 | return false; |
| 293 | } |
| 294 | NameIndex kind = CanonicalNameParent(name); |
| 295 | if (IsPrivate(name)) { |
| 296 | kind = CanonicalNameParent(kind); |
| 297 | } |
| 298 | return StringEquals(CanonicalNameString(kind), "@getters" ); |
| 299 | } |
| 300 | |
| 301 | bool TranslationHelper::IsSetter(NameIndex name) { |
| 302 | // Setters with private names have the import URI of the library where they |
| 303 | // are visible as the parent and the string "@setters" as the parent's parent. |
| 304 | // Setters with non-private names have the string "@setters" as the parent. |
| 305 | if (IsRoot(name)) { |
| 306 | return false; |
| 307 | } |
| 308 | NameIndex kind = CanonicalNameParent(name); |
| 309 | if (IsPrivate(name)) { |
| 310 | kind = CanonicalNameParent(kind); |
| 311 | } |
| 312 | return StringEquals(CanonicalNameString(kind), "@setters" ); |
| 313 | } |
| 314 | |
| 315 | bool TranslationHelper::IsFactory(NameIndex name) { |
| 316 | // Factories with private names have the import URI of the library where they |
| 317 | // are visible as the parent and the string "@factories" as the parent's |
| 318 | // parent. Factories with non-private names have the string "@factories" as |
| 319 | // the parent. |
| 320 | if (IsRoot(name)) { |
| 321 | return false; |
| 322 | } |
| 323 | NameIndex kind = CanonicalNameParent(name); |
| 324 | if (IsPrivate(name)) { |
| 325 | kind = CanonicalNameParent(kind); |
| 326 | } |
| 327 | return StringEquals(CanonicalNameString(kind), "@factories" ); |
| 328 | } |
| 329 | |
| 330 | NameIndex TranslationHelper::EnclosingName(NameIndex name) { |
| 331 | ASSERT(IsField(name) || IsConstructor(name) || IsProcedure(name)); |
| 332 | NameIndex enclosing = CanonicalNameParent(CanonicalNameParent(name)); |
| 333 | if (IsPrivate(name)) { |
| 334 | enclosing = CanonicalNameParent(enclosing); |
| 335 | } |
| 336 | ASSERT(IsLibrary(enclosing) || IsClass(enclosing)); |
| 337 | return enclosing; |
| 338 | } |
| 339 | |
| 340 | InstancePtr TranslationHelper::Canonicalize(const Instance& instance) { |
| 341 | if (instance.IsNull()) return instance.raw(); |
| 342 | |
| 343 | const char* error_str = NULL; |
| 344 | InstancePtr result = instance.CheckAndCanonicalize(thread(), &error_str); |
| 345 | if (result == Object::null()) { |
| 346 | ReportError("Invalid const object %s" , error_str); |
| 347 | } |
| 348 | return result; |
| 349 | } |
| 350 | |
| 351 | const String& TranslationHelper::DartString(const char* content, |
| 352 | Heap::Space space) { |
| 353 | return String::ZoneHandle(Z, String::New(content, space)); |
| 354 | } |
| 355 | |
| 356 | String& TranslationHelper::DartString(StringIndex string_index, |
| 357 | Heap::Space space) { |
| 358 | intptr_t length = StringSize(string_index); |
| 359 | uint8_t* buffer = Z->Alloc<uint8_t>(length); |
| 360 | { |
| 361 | NoSafepointScope no_safepoint; |
| 362 | memmove(buffer, StringBuffer(string_index), length); |
| 363 | } |
| 364 | return String::ZoneHandle(Z, String::FromUTF8(buffer, length, space)); |
| 365 | } |
| 366 | |
| 367 | String& TranslationHelper::DartString(const uint8_t* utf8_array, |
| 368 | intptr_t len, |
| 369 | Heap::Space space) { |
| 370 | return String::ZoneHandle(Z, String::FromUTF8(utf8_array, len, space)); |
| 371 | } |
| 372 | |
| 373 | const String& TranslationHelper::DartSymbolPlain(const char* content) const { |
| 374 | return String::ZoneHandle(Z, Symbols::New(thread_, content)); |
| 375 | } |
| 376 | |
| 377 | String& TranslationHelper::DartSymbolPlain(StringIndex string_index) const { |
| 378 | intptr_t length = StringSize(string_index); |
| 379 | uint8_t* buffer = Z->Alloc<uint8_t>(length); |
| 380 | { |
| 381 | NoSafepointScope no_safepoint; |
| 382 | memmove(buffer, StringBuffer(string_index), length); |
| 383 | } |
| 384 | String& result = |
| 385 | String::ZoneHandle(Z, Symbols::FromUTF8(thread_, buffer, length)); |
| 386 | return result; |
| 387 | } |
| 388 | |
| 389 | const String& TranslationHelper::DartSymbolObfuscate( |
| 390 | const char* content) const { |
| 391 | String& result = String::ZoneHandle(Z, Symbols::New(thread_, content)); |
| 392 | if (I->obfuscate()) { |
| 393 | Obfuscator obfuscator(thread_, String::Handle(Z)); |
| 394 | result = obfuscator.Rename(result, true); |
| 395 | } |
| 396 | return result; |
| 397 | } |
| 398 | |
| 399 | String& TranslationHelper::DartSymbolObfuscate(StringIndex string_index) const { |
| 400 | intptr_t length = StringSize(string_index); |
| 401 | uint8_t* buffer = Z->Alloc<uint8_t>(length); |
| 402 | { |
| 403 | NoSafepointScope no_safepoint; |
| 404 | memmove(buffer, StringBuffer(string_index), length); |
| 405 | } |
| 406 | String& result = |
| 407 | String::ZoneHandle(Z, Symbols::FromUTF8(thread_, buffer, length)); |
| 408 | if (I->obfuscate()) { |
| 409 | Obfuscator obfuscator(thread_, String::Handle(Z)); |
| 410 | result = obfuscator.Rename(result, true); |
| 411 | } |
| 412 | return result; |
| 413 | } |
| 414 | |
| 415 | String& TranslationHelper::DartIdentifier(const Library& lib, |
| 416 | StringIndex string_index) { |
| 417 | String& name = DartString(string_index); |
| 418 | ManglePrivateName(lib, &name); |
| 419 | return name; |
| 420 | } |
| 421 | |
| 422 | const String& TranslationHelper::DartClassName(NameIndex kernel_class) { |
| 423 | ASSERT(IsClass(kernel_class)); |
| 424 | String& name = DartString(CanonicalNameString(kernel_class)); |
| 425 | return ManglePrivateName(CanonicalNameParent(kernel_class), &name); |
| 426 | } |
| 427 | |
| 428 | const String& TranslationHelper::DartConstructorName(NameIndex constructor) { |
| 429 | ASSERT(IsConstructor(constructor)); |
| 430 | return DartFactoryName(constructor); |
| 431 | } |
| 432 | |
| 433 | const String& TranslationHelper::DartProcedureName(NameIndex procedure) { |
| 434 | ASSERT(IsProcedure(procedure)); |
| 435 | if (IsSetter(procedure)) { |
| 436 | return DartSetterName(procedure); |
| 437 | } else if (IsGetter(procedure)) { |
| 438 | return DartGetterName(procedure); |
| 439 | } else if (IsFactory(procedure)) { |
| 440 | return DartFactoryName(procedure); |
| 441 | } else { |
| 442 | return DartMethodName(procedure); |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | const String& TranslationHelper::DartSetterName(NameIndex setter) { |
| 447 | return DartSetterName(CanonicalNameParent(setter), |
| 448 | CanonicalNameString(setter)); |
| 449 | } |
| 450 | |
| 451 | const String& TranslationHelper::DartSetterName(NameIndex parent, |
| 452 | StringIndex setter) { |
| 453 | // The names flowing into [setter] are coming from the Kernel file: |
| 454 | // * user-defined setters: `fieldname=` |
| 455 | // * property-set expressions: `fieldname` |
| 456 | // |
| 457 | // The VM uses `get:fieldname` and `set:fieldname`. |
| 458 | // |
| 459 | // => In order to be consistent, we remove the `=` always and adopt the VM |
| 460 | // conventions. |
| 461 | intptr_t size = StringSize(setter); |
| 462 | ASSERT(size > 0); |
| 463 | if (CharacterAt(setter, size - 1) == '=') { |
| 464 | --size; |
| 465 | } |
| 466 | uint8_t* buffer = Z->Alloc<uint8_t>(size); |
| 467 | { |
| 468 | NoSafepointScope no_safepoint; |
| 469 | memmove(buffer, StringBuffer(setter), size); |
| 470 | } |
| 471 | String& name = |
| 472 | String::ZoneHandle(Z, String::FromUTF8(buffer, size, allocation_space_)); |
| 473 | ManglePrivateName(parent, &name); |
| 474 | name = Field::SetterSymbol(name); |
| 475 | return name; |
| 476 | } |
| 477 | |
| 478 | const String& TranslationHelper::DartGetterName(NameIndex getter) { |
| 479 | return DartGetterName(CanonicalNameParent(getter), |
| 480 | CanonicalNameString(getter)); |
| 481 | } |
| 482 | |
| 483 | const String& TranslationHelper::DartGetterName(NameIndex parent, |
| 484 | StringIndex getter) { |
| 485 | String& name = DartString(getter); |
| 486 | ManglePrivateName(parent, &name); |
| 487 | name = Field::GetterSymbol(name); |
| 488 | return name; |
| 489 | } |
| 490 | |
| 491 | const String& TranslationHelper::DartFieldName(NameIndex field) { |
| 492 | return DartFieldName(CanonicalNameParent(field), CanonicalNameString(field)); |
| 493 | } |
| 494 | |
| 495 | const String& TranslationHelper::DartFieldName(NameIndex parent, |
| 496 | StringIndex field) { |
| 497 | String& name = DartString(field); |
| 498 | return ManglePrivateName(parent, &name); |
| 499 | } |
| 500 | |
| 501 | const String& TranslationHelper::DartMethodName(NameIndex method) { |
| 502 | return DartMethodName(CanonicalNameParent(method), |
| 503 | CanonicalNameString(method)); |
| 504 | } |
| 505 | |
| 506 | const String& TranslationHelper::DartMethodName(NameIndex parent, |
| 507 | StringIndex method) { |
| 508 | String& name = DartString(method); |
| 509 | return ManglePrivateName(parent, &name); |
| 510 | } |
| 511 | |
| 512 | const String& TranslationHelper::DartFactoryName(NameIndex factory) { |
| 513 | ASSERT(IsConstructor(factory) || IsFactory(factory)); |
| 514 | GrowableHandlePtrArray<const String> pieces(Z, 3); |
| 515 | pieces.Add(DartClassName(EnclosingName(factory))); |
| 516 | pieces.Add(Symbols::Dot()); |
| 517 | // [DartMethodName] will mangle the name. |
| 518 | pieces.Add(DartMethodName(factory)); |
| 519 | return String::ZoneHandle(Z, Symbols::FromConcatAll(thread_, pieces)); |
| 520 | } |
| 521 | |
| 522 | // TODO(https://github.com/dart-lang/sdk/issues/37517): Should emit code to |
| 523 | // throw a NoSuchMethodError. |
| 524 | static void CheckStaticLookup(const Object& target) { |
| 525 | if (target.IsNull()) { |
| 526 | #ifndef PRODUCT |
| 527 | ASSERT(Isolate::Current()->HasAttemptedReload()); |
| 528 | Report::LongJump(LanguageError::Handle(LanguageError::New(String::Handle( |
| 529 | String::New("Unimplemented handling of missing static target" ))))); |
| 530 | #else |
| 531 | UNREACHABLE(); |
| 532 | #endif |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | LibraryPtr TranslationHelper::LookupLibraryByKernelLibrary( |
| 537 | NameIndex kernel_library) { |
| 538 | // We only use the string and don't rely on having any particular parent. |
| 539 | // This ASSERT is just a sanity check. |
| 540 | ASSERT(IsLibrary(kernel_library) || |
| 541 | IsAdministrative(CanonicalNameParent(kernel_library))); |
| 542 | { |
| 543 | name_index_handle_ = Smi::New(kernel_library); |
| 544 | LibraryPtr raw_lib = info_.LookupLibrary(thread_, name_index_handle_); |
| 545 | NoSafepointScope no_safepoint_scope(thread_); |
| 546 | if (raw_lib != Library::null()) { |
| 547 | return raw_lib; |
| 548 | } |
| 549 | } |
| 550 | |
| 551 | const String& library_name = |
| 552 | DartSymbolPlain(CanonicalNameString(kernel_library)); |
| 553 | ASSERT(!library_name.IsNull()); |
| 554 | const Library& library = |
| 555 | Library::Handle(Z, Library::LookupLibrary(thread_, library_name)); |
| 556 | CheckStaticLookup(library); |
| 557 | name_index_handle_ = Smi::New(kernel_library); |
| 558 | return info_.InsertLibrary(thread_, name_index_handle_, library); |
| 559 | } |
| 560 | |
| 561 | ClassPtr TranslationHelper::LookupClassByKernelClass(NameIndex kernel_class) { |
| 562 | ASSERT(IsClass(kernel_class)); |
| 563 | { |
| 564 | name_index_handle_ = Smi::New(kernel_class); |
| 565 | ClassPtr raw_class = info_.LookupClass(thread_, name_index_handle_); |
| 566 | NoSafepointScope no_safepoint_scope(thread_); |
| 567 | if (raw_class != Class::null()) { |
| 568 | return raw_class; |
| 569 | } |
| 570 | } |
| 571 | |
| 572 | const String& class_name = DartClassName(kernel_class); |
| 573 | NameIndex kernel_library = CanonicalNameParent(kernel_class); |
| 574 | Library& library = |
| 575 | Library::Handle(Z, LookupLibraryByKernelLibrary(kernel_library)); |
| 576 | ASSERT(!library.IsNull()); |
| 577 | const Class& klass = |
| 578 | Class::Handle(Z, library.LookupClassAllowPrivate(class_name)); |
| 579 | CheckStaticLookup(klass); |
| 580 | ASSERT(!klass.IsNull()); |
| 581 | if (klass.is_declared_in_bytecode()) { |
| 582 | klass.EnsureDeclarationLoaded(); |
| 583 | } |
| 584 | name_index_handle_ = Smi::New(kernel_class); |
| 585 | return info_.InsertClass(thread_, name_index_handle_, klass); |
| 586 | } |
| 587 | |
| 588 | FieldPtr TranslationHelper::LookupFieldByKernelField(NameIndex kernel_field) { |
| 589 | ASSERT(IsField(kernel_field)); |
| 590 | NameIndex enclosing = EnclosingName(kernel_field); |
| 591 | |
| 592 | Class& klass = Class::Handle(Z); |
| 593 | if (IsLibrary(enclosing)) { |
| 594 | Library& library = |
| 595 | Library::Handle(Z, LookupLibraryByKernelLibrary(enclosing)); |
| 596 | klass = library.toplevel_class(); |
| 597 | CheckStaticLookup(klass); |
| 598 | } else { |
| 599 | ASSERT(IsClass(enclosing)); |
| 600 | klass = LookupClassByKernelClass(enclosing); |
| 601 | } |
| 602 | Field& field = Field::Handle( |
| 603 | Z, klass.LookupFieldAllowPrivate( |
| 604 | DartSymbolObfuscate(CanonicalNameString(kernel_field)))); |
| 605 | CheckStaticLookup(field); |
| 606 | return field.raw(); |
| 607 | } |
| 608 | |
| 609 | FunctionPtr TranslationHelper::LookupStaticMethodByKernelProcedure( |
| 610 | NameIndex procedure) { |
| 611 | const String& procedure_name = DartProcedureName(procedure); |
| 612 | |
| 613 | // The parent is either a library or a class (in which case the procedure is a |
| 614 | // static method). |
| 615 | NameIndex enclosing = EnclosingName(procedure); |
| 616 | if (IsLibrary(enclosing)) { |
| 617 | Library& library = |
| 618 | Library::Handle(Z, LookupLibraryByKernelLibrary(enclosing)); |
| 619 | Function& function = |
| 620 | Function::Handle(Z, library.LookupFunctionAllowPrivate(procedure_name)); |
| 621 | CheckStaticLookup(function); |
| 622 | return function.raw(); |
| 623 | } else { |
| 624 | ASSERT(IsClass(enclosing)); |
| 625 | Class& klass = Class::Handle(Z, LookupClassByKernelClass(enclosing)); |
| 626 | Function& function = Function::ZoneHandle( |
| 627 | Z, klass.LookupFunctionAllowPrivate(procedure_name)); |
| 628 | CheckStaticLookup(function); |
| 629 | // Redirecting factory must be resolved. |
| 630 | ASSERT(!function.IsRedirectingFactory() || |
| 631 | function.RedirectionTarget() != Function::null()); |
| 632 | return function.raw(); |
| 633 | } |
| 634 | } |
| 635 | |
| 636 | FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor( |
| 637 | NameIndex constructor) { |
| 638 | ASSERT(IsConstructor(constructor)); |
| 639 | Class& klass = |
| 640 | Class::Handle(Z, LookupClassByKernelClass(EnclosingName(constructor))); |
| 641 | CheckStaticLookup(klass); |
| 642 | return LookupConstructorByKernelConstructor(klass, constructor); |
| 643 | } |
| 644 | |
| 645 | FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor( |
| 646 | const Class& owner, |
| 647 | NameIndex constructor) { |
| 648 | ASSERT(IsConstructor(constructor)); |
| 649 | Function& function = Function::Handle( |
| 650 | Z, owner.LookupConstructorAllowPrivate(DartConstructorName(constructor))); |
| 651 | CheckStaticLookup(function); |
| 652 | return function.raw(); |
| 653 | } |
| 654 | |
| 655 | FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor( |
| 656 | const Class& owner, |
| 657 | StringIndex constructor_name) { |
| 658 | GrowableHandlePtrArray<const String> pieces(Z, 3); |
| 659 | pieces.Add(String::Handle(Z, owner.Name())); |
| 660 | pieces.Add(Symbols::Dot()); |
| 661 | String& name = DartSymbolPlain(constructor_name); |
| 662 | pieces.Add(ManglePrivateName(Library::Handle(owner.library()), &name)); |
| 663 | |
| 664 | String& new_name = |
| 665 | String::ZoneHandle(Z, Symbols::FromConcatAll(thread_, pieces)); |
| 666 | FunctionPtr function = owner.LookupConstructorAllowPrivate(new_name); |
| 667 | ASSERT(function != Object::null()); |
| 668 | return function; |
| 669 | } |
| 670 | |
| 671 | FunctionPtr TranslationHelper::LookupMethodByMember(NameIndex target, |
| 672 | const String& method_name) { |
| 673 | NameIndex kernel_class = EnclosingName(target); |
| 674 | Class& klass = Class::Handle(Z, LookupClassByKernelClass(kernel_class)); |
| 675 | |
| 676 | Function& function = |
| 677 | Function::Handle(Z, klass.LookupFunctionAllowPrivate(method_name)); |
| 678 | #ifdef DEBUG |
| 679 | if (function.IsNull()) { |
| 680 | THR_Print("Unable to find \'%s\' in %s\n" , method_name.ToCString(), |
| 681 | klass.ToCString()); |
| 682 | } |
| 683 | #endif |
| 684 | CheckStaticLookup(function); |
| 685 | ASSERT(!function.IsNull()); |
| 686 | return function.raw(); |
| 687 | } |
| 688 | |
| 689 | FunctionPtr TranslationHelper::LookupDynamicFunction(const Class& klass, |
| 690 | const String& name) { |
| 691 | // Search the superclass chain for the selector. |
| 692 | Class& iterate_klass = Class::Handle(Z, klass.raw()); |
| 693 | while (!iterate_klass.IsNull()) { |
| 694 | FunctionPtr function = |
| 695 | iterate_klass.LookupDynamicFunctionAllowPrivate(name); |
| 696 | if (function != Object::null()) { |
| 697 | return function; |
| 698 | } |
| 699 | iterate_klass = iterate_klass.SuperClass(); |
| 700 | } |
| 701 | return Function::null(); |
| 702 | } |
| 703 | |
| 704 | Type& TranslationHelper::GetDeclarationType(const Class& klass) { |
| 705 | ASSERT(!klass.IsNull()); |
| 706 | // Note that if cls is _Closure, the returned type will be _Closure, |
| 707 | // and not the signature type. |
| 708 | Type& type = Type::ZoneHandle(Z); |
| 709 | if (klass.is_type_finalized()) { |
| 710 | type = klass.DeclarationType(); |
| 711 | } else { |
| 712 | // Note that the type argument vector is not yet extended. |
| 713 | type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()), |
| 714 | klass.token_pos()); |
| 715 | } |
| 716 | return type; |
| 717 | } |
| 718 | |
| 719 | void TranslationHelper::SetupFieldAccessorFunction( |
| 720 | const Class& klass, |
| 721 | const Function& function, |
| 722 | const AbstractType& field_type) { |
| 723 | bool is_setter = function.IsImplicitSetterFunction(); |
| 724 | bool is_method = !function.IsStaticFunction(); |
| 725 | intptr_t parameter_count = (is_method ? 1 : 0) + (is_setter ? 1 : 0); |
| 726 | |
| 727 | function.SetNumOptionalParameters(0, false); |
| 728 | function.set_num_fixed_parameters(parameter_count); |
| 729 | function.set_parameter_types( |
| 730 | Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); |
| 731 | function.set_parameter_names( |
| 732 | Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); |
| 733 | |
| 734 | intptr_t pos = 0; |
| 735 | if (is_method) { |
| 736 | function.SetParameterTypeAt(pos, GetDeclarationType(klass)); |
| 737 | function.SetParameterNameAt(pos, Symbols::This()); |
| 738 | pos++; |
| 739 | } |
| 740 | if (is_setter) { |
| 741 | function.SetParameterTypeAt(pos, field_type); |
| 742 | function.SetParameterNameAt(pos, Symbols::Value()); |
| 743 | pos++; |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | void TranslationHelper::ReportError(const char* format, ...) { |
| 748 | const Script& null_script = Script::Handle(Z); |
| 749 | |
| 750 | va_list args; |
| 751 | va_start(args, format); |
| 752 | Report::MessageV(Report::kError, null_script, TokenPosition::kNoSource, |
| 753 | Report::AtLocation, format, args); |
| 754 | va_end(args); |
| 755 | UNREACHABLE(); |
| 756 | } |
| 757 | |
| 758 | void TranslationHelper::ReportError(const Script& script, |
| 759 | const TokenPosition position, |
| 760 | const char* format, |
| 761 | ...) { |
| 762 | va_list args; |
| 763 | va_start(args, format); |
| 764 | Report::MessageV(Report::kError, script, position, Report::AtLocation, format, |
| 765 | args); |
| 766 | va_end(args); |
| 767 | UNREACHABLE(); |
| 768 | } |
| 769 | |
| 770 | void TranslationHelper::ReportError(const Error& prev_error, |
| 771 | const char* format, |
| 772 | ...) { |
| 773 | const Script& null_script = Script::Handle(Z); |
| 774 | |
| 775 | va_list args; |
| 776 | va_start(args, format); |
| 777 | Report::LongJumpV(prev_error, null_script, TokenPosition::kNoSource, format, |
| 778 | args); |
| 779 | va_end(args); |
| 780 | UNREACHABLE(); |
| 781 | } |
| 782 | |
| 783 | void TranslationHelper::ReportError(const Error& prev_error, |
| 784 | const Script& script, |
| 785 | const TokenPosition position, |
| 786 | const char* format, |
| 787 | ...) { |
| 788 | va_list args; |
| 789 | va_start(args, format); |
| 790 | Report::LongJumpV(prev_error, script, position, format, args); |
| 791 | va_end(args); |
| 792 | UNREACHABLE(); |
| 793 | } |
| 794 | |
| 795 | String& TranslationHelper::ManglePrivateName(NameIndex parent, |
| 796 | String* name_to_modify, |
| 797 | bool symbolize, |
| 798 | bool obfuscate) { |
| 799 | if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_') { |
| 800 | const Library& library = |
| 801 | Library::Handle(Z, LookupLibraryByKernelLibrary(parent)); |
| 802 | *name_to_modify = library.PrivateName(*name_to_modify); |
| 803 | if (obfuscate && I->obfuscate()) { |
| 804 | const String& library_key = String::Handle(library.private_key()); |
| 805 | Obfuscator obfuscator(thread_, library_key); |
| 806 | *name_to_modify = obfuscator.Rename(*name_to_modify); |
| 807 | } |
| 808 | } else if (symbolize) { |
| 809 | *name_to_modify = Symbols::New(thread_, *name_to_modify); |
| 810 | if (obfuscate && I->obfuscate()) { |
| 811 | const String& library_key = String::Handle(); |
| 812 | Obfuscator obfuscator(thread_, library_key); |
| 813 | *name_to_modify = obfuscator.Rename(*name_to_modify); |
| 814 | } |
| 815 | } |
| 816 | return *name_to_modify; |
| 817 | } |
| 818 | |
| 819 | String& TranslationHelper::ManglePrivateName(const Library& library, |
| 820 | String* name_to_modify, |
| 821 | bool symbolize, |
| 822 | bool obfuscate) { |
| 823 | if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_') { |
| 824 | *name_to_modify = library.PrivateName(*name_to_modify); |
| 825 | if (obfuscate && I->obfuscate()) { |
| 826 | const String& library_key = String::Handle(library.private_key()); |
| 827 | Obfuscator obfuscator(thread_, library_key); |
| 828 | *name_to_modify = obfuscator.Rename(*name_to_modify); |
| 829 | } |
| 830 | } else if (symbolize) { |
| 831 | *name_to_modify = Symbols::New(thread_, *name_to_modify); |
| 832 | if (obfuscate && I->obfuscate()) { |
| 833 | const String& library_key = String::Handle(); |
| 834 | Obfuscator obfuscator(thread_, library_key); |
| 835 | *name_to_modify = obfuscator.Rename(*name_to_modify); |
| 836 | } |
| 837 | } |
| 838 | return *name_to_modify; |
| 839 | } |
| 840 | |
| 841 | void FunctionNodeHelper::ReadUntilExcluding(Field field) { |
| 842 | if (field <= next_read_) return; |
| 843 | |
| 844 | // Ordered with fall-through. |
| 845 | switch (next_read_) { |
| 846 | case kStart: { |
| 847 | Tag tag = helper_->ReadTag(); // read tag. |
| 848 | ASSERT(tag == kFunctionNode); |
| 849 | if (++next_read_ == field) return; |
| 850 | } |
| 851 | FALL_THROUGH; |
| 852 | case kPosition: |
| 853 | position_ = helper_->ReadPosition(); // read position. |
| 854 | if (++next_read_ == field) return; |
| 855 | FALL_THROUGH; |
| 856 | case kEndPosition: |
| 857 | end_position_ = helper_->ReadPosition(); // read end position. |
| 858 | if (++next_read_ == field) return; |
| 859 | FALL_THROUGH; |
| 860 | case kAsyncMarker: |
| 861 | async_marker_ = static_cast<AsyncMarker>(helper_->ReadByte()); |
| 862 | if (++next_read_ == field) return; |
| 863 | FALL_THROUGH; |
| 864 | case kDartAsyncMarker: |
| 865 | dart_async_marker_ = static_cast<AsyncMarker>( |
| 866 | helper_->ReadByte()); // read dart async marker. |
| 867 | if (++next_read_ == field) return; |
| 868 | FALL_THROUGH; |
| 869 | case kTypeParameters: |
| 870 | helper_->SkipTypeParametersList(); // read type parameters. |
| 871 | if (++next_read_ == field) return; |
| 872 | FALL_THROUGH; |
| 873 | case kTotalParameterCount: |
| 874 | total_parameter_count_ = |
| 875 | helper_->ReadUInt(); // read total parameter count. |
| 876 | if (++next_read_ == field) return; |
| 877 | FALL_THROUGH; |
| 878 | case kRequiredParameterCount: |
| 879 | required_parameter_count_ = |
| 880 | helper_->ReadUInt(); // read required parameter count. |
| 881 | if (++next_read_ == field) return; |
| 882 | FALL_THROUGH; |
| 883 | case kPositionalParameters: |
| 884 | helper_->SkipListOfVariableDeclarations(); // read positionals. |
| 885 | if (++next_read_ == field) return; |
| 886 | FALL_THROUGH; |
| 887 | case kNamedParameters: |
| 888 | helper_->SkipListOfVariableDeclarations(); // read named. |
| 889 | if (++next_read_ == field) return; |
| 890 | FALL_THROUGH; |
| 891 | case kReturnType: |
| 892 | helper_->SkipDartType(); // read return type. |
| 893 | if (++next_read_ == field) return; |
| 894 | FALL_THROUGH; |
| 895 | case kBody: |
| 896 | if (helper_->ReadTag() == kSomething) |
| 897 | helper_->SkipStatement(); // read body. |
| 898 | if (++next_read_ == field) return; |
| 899 | FALL_THROUGH; |
| 900 | case kEnd: |
| 901 | return; |
| 902 | } |
| 903 | } |
| 904 | |
| 905 | void TypeParameterHelper::ReadUntilExcluding(Field field) { |
| 906 | for (; next_read_ < field; ++next_read_) { |
| 907 | switch (next_read_) { |
| 908 | case kFlags: |
| 909 | flags_ = helper_->ReadFlags(); |
| 910 | break; |
| 911 | case kAnnotations: |
| 912 | helper_->SkipListOfExpressions(); // read annotations. |
| 913 | break; |
| 914 | case kVariance: |
| 915 | helper_->ReadVariance(); |
| 916 | break; |
| 917 | case kName: |
| 918 | name_index_ = helper_->ReadStringReference(); // read name index. |
| 919 | break; |
| 920 | case kBound: |
| 921 | helper_->SkipDartType(); |
| 922 | break; |
| 923 | case kDefaultType: |
| 924 | if (helper_->ReadTag() == kSomething) { |
| 925 | helper_->SkipDartType(); |
| 926 | } |
| 927 | break; |
| 928 | case kEnd: |
| 929 | return; |
| 930 | } |
| 931 | } |
| 932 | } |
| 933 | |
| 934 | void VariableDeclarationHelper::ReadUntilExcluding(Field field) { |
| 935 | if (field <= next_read_) return; |
| 936 | |
| 937 | // Ordered with fall-through. |
| 938 | switch (next_read_) { |
| 939 | case kPosition: |
| 940 | position_ = helper_->ReadPosition(); // read position. |
| 941 | if (++next_read_ == field) return; |
| 942 | FALL_THROUGH; |
| 943 | case kEqualPosition: |
| 944 | equals_position_ = helper_->ReadPosition(); // read equals position. |
| 945 | if (++next_read_ == field) return; |
| 946 | FALL_THROUGH; |
| 947 | case kAnnotations: |
| 948 | annotation_count_ = helper_->ReadListLength(); // read list length. |
| 949 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
| 950 | helper_->SkipExpression(); // read ith expression. |
| 951 | } |
| 952 | if (++next_read_ == field) return; |
| 953 | FALL_THROUGH; |
| 954 | case kFlags: |
| 955 | flags_ = helper_->ReadFlags(); |
| 956 | if (++next_read_ == field) return; |
| 957 | FALL_THROUGH; |
| 958 | case kNameIndex: |
| 959 | name_index_ = helper_->ReadStringReference(); // read name index. |
| 960 | if (++next_read_ == field) return; |
| 961 | FALL_THROUGH; |
| 962 | case kType: |
| 963 | helper_->SkipDartType(); // read type. |
| 964 | if (++next_read_ == field) return; |
| 965 | FALL_THROUGH; |
| 966 | case kInitializer: |
| 967 | if (helper_->ReadTag() == kSomething) |
| 968 | helper_->SkipExpression(); // read initializer. |
| 969 | if (++next_read_ == field) return; |
| 970 | FALL_THROUGH; |
| 971 | case kEnd: |
| 972 | return; |
| 973 | } |
| 974 | } |
| 975 | |
| 976 | FieldHelper::FieldHelper(KernelReaderHelper* helper, intptr_t offset) |
| 977 | : helper_(helper), next_read_(kStart) { |
| 978 | helper_->SetOffset(offset); |
| 979 | } |
| 980 | |
| 981 | void FieldHelper::ReadUntilExcluding(Field field) { |
| 982 | if (field <= next_read_) return; |
| 983 | |
| 984 | // Ordered with fall-through. |
| 985 | switch (next_read_) { |
| 986 | case kStart: { |
| 987 | Tag tag = helper_->ReadTag(); // read tag. |
| 988 | ASSERT(tag == kField); |
| 989 | if (++next_read_ == field) return; |
| 990 | } |
| 991 | FALL_THROUGH; |
| 992 | case kCanonicalName: |
| 993 | canonical_name_ = |
| 994 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
| 995 | if (++next_read_ == field) return; |
| 996 | FALL_THROUGH; |
| 997 | case kSourceUriIndex: |
| 998 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
| 999 | helper_->set_current_script_id(source_uri_index_); |
| 1000 | if (++next_read_ == field) return; |
| 1001 | FALL_THROUGH; |
| 1002 | case kPosition: |
| 1003 | position_ = helper_->ReadPosition(); // read position. |
| 1004 | if (++next_read_ == field) return; |
| 1005 | FALL_THROUGH; |
| 1006 | case kEndPosition: |
| 1007 | end_position_ = helper_->ReadPosition(); // read end position. |
| 1008 | if (++next_read_ == field) return; |
| 1009 | FALL_THROUGH; |
| 1010 | case kFlags: |
| 1011 | flags_ = helper_->ReadUInt(); |
| 1012 | if (++next_read_ == field) return; |
| 1013 | FALL_THROUGH; |
| 1014 | case kName: |
| 1015 | helper_->SkipName(); // read name. |
| 1016 | if (++next_read_ == field) return; |
| 1017 | FALL_THROUGH; |
| 1018 | case kAnnotations: { |
| 1019 | annotation_count_ = helper_->ReadListLength(); // read list length. |
| 1020 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
| 1021 | helper_->SkipExpression(); // read ith expression. |
| 1022 | } |
| 1023 | if (++next_read_ == field) return; |
| 1024 | } |
| 1025 | FALL_THROUGH; |
| 1026 | case kType: |
| 1027 | helper_->SkipDartType(); // read type. |
| 1028 | if (++next_read_ == field) return; |
| 1029 | FALL_THROUGH; |
| 1030 | case kInitializer: |
| 1031 | if (helper_->ReadTag() == kSomething) { |
| 1032 | helper_->SkipExpression(); // read initializer. |
| 1033 | } |
| 1034 | if (++next_read_ == field) return; |
| 1035 | FALL_THROUGH; |
| 1036 | case kEnd: |
| 1037 | return; |
| 1038 | } |
| 1039 | } |
| 1040 | |
| 1041 | void ProcedureHelper::ReadUntilExcluding(Field field) { |
| 1042 | if (field <= next_read_) return; |
| 1043 | |
| 1044 | // Ordered with fall-through. |
| 1045 | switch (next_read_) { |
| 1046 | case kStart: { |
| 1047 | Tag tag = helper_->ReadTag(); // read tag. |
| 1048 | ASSERT(tag == kProcedure); |
| 1049 | if (++next_read_ == field) return; |
| 1050 | } |
| 1051 | FALL_THROUGH; |
| 1052 | case kCanonicalName: |
| 1053 | canonical_name_ = |
| 1054 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
| 1055 | if (++next_read_ == field) return; |
| 1056 | FALL_THROUGH; |
| 1057 | case kSourceUriIndex: |
| 1058 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
| 1059 | helper_->set_current_script_id(source_uri_index_); |
| 1060 | if (++next_read_ == field) return; |
| 1061 | FALL_THROUGH; |
| 1062 | case kStartPosition: |
| 1063 | start_position_ = helper_->ReadPosition(); // read position. |
| 1064 | if (++next_read_ == field) return; |
| 1065 | FALL_THROUGH; |
| 1066 | case kPosition: |
| 1067 | position_ = helper_->ReadPosition(); // read position. |
| 1068 | if (++next_read_ == field) return; |
| 1069 | FALL_THROUGH; |
| 1070 | case kEndPosition: |
| 1071 | end_position_ = helper_->ReadPosition(); // read end position. |
| 1072 | if (++next_read_ == field) return; |
| 1073 | FALL_THROUGH; |
| 1074 | case kKind: |
| 1075 | kind_ = static_cast<Kind>(helper_->ReadByte()); |
| 1076 | if (++next_read_ == field) return; |
| 1077 | FALL_THROUGH; |
| 1078 | case kFlags: |
| 1079 | flags_ = helper_->ReadUInt(); |
| 1080 | if (++next_read_ == field) return; |
| 1081 | FALL_THROUGH; |
| 1082 | case kName: |
| 1083 | helper_->SkipName(); // read name. |
| 1084 | if (++next_read_ == field) return; |
| 1085 | FALL_THROUGH; |
| 1086 | case kAnnotations: { |
| 1087 | annotation_count_ = helper_->ReadListLength(); // read list length. |
| 1088 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
| 1089 | helper_->SkipExpression(); // read ith expression. |
| 1090 | } |
| 1091 | if (++next_read_ == field) return; |
| 1092 | } |
| 1093 | FALL_THROUGH; |
| 1094 | case kForwardingStubSuperTarget: |
| 1095 | forwarding_stub_super_target_ = helper_->ReadCanonicalNameReference(); |
| 1096 | if (++next_read_ == field) return; |
| 1097 | FALL_THROUGH; |
| 1098 | case kForwardingStubInterfaceTarget: |
| 1099 | helper_->ReadCanonicalNameReference(); |
| 1100 | if (++next_read_ == field) return; |
| 1101 | FALL_THROUGH; |
| 1102 | case kMemberSignatureTarget: |
| 1103 | helper_->ReadCanonicalNameReference(); |
| 1104 | if (++next_read_ == field) return; |
| 1105 | FALL_THROUGH; |
| 1106 | case kFunction: |
| 1107 | if (helper_->ReadTag() == kSomething) { |
| 1108 | helper_->SkipFunctionNode(); // read function node. |
| 1109 | } |
| 1110 | if (++next_read_ == field) return; |
| 1111 | FALL_THROUGH; |
| 1112 | case kEnd: |
| 1113 | return; |
| 1114 | } |
| 1115 | } |
| 1116 | |
| 1117 | void ConstructorHelper::ReadUntilExcluding(Field field) { |
| 1118 | if (field <= next_read_) return; |
| 1119 | |
| 1120 | // Ordered with fall-through. |
| 1121 | switch (next_read_) { |
| 1122 | case kStart: { |
| 1123 | Tag tag = helper_->ReadTag(); // read tag. |
| 1124 | ASSERT(tag == kConstructor); |
| 1125 | if (++next_read_ == field) return; |
| 1126 | } |
| 1127 | FALL_THROUGH; |
| 1128 | case kCanonicalName: |
| 1129 | canonical_name_ = |
| 1130 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
| 1131 | if (++next_read_ == field) return; |
| 1132 | FALL_THROUGH; |
| 1133 | case kSourceUriIndex: |
| 1134 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
| 1135 | helper_->set_current_script_id(source_uri_index_); |
| 1136 | if (++next_read_ == field) return; |
| 1137 | FALL_THROUGH; |
| 1138 | case kStartPosition: |
| 1139 | start_position_ = helper_->ReadPosition(); // read position. |
| 1140 | if (++next_read_ == field) return; |
| 1141 | FALL_THROUGH; |
| 1142 | case kPosition: |
| 1143 | position_ = helper_->ReadPosition(); // read position. |
| 1144 | if (++next_read_ == field) return; |
| 1145 | FALL_THROUGH; |
| 1146 | case kEndPosition: |
| 1147 | end_position_ = helper_->ReadPosition(); // read end position. |
| 1148 | if (++next_read_ == field) return; |
| 1149 | FALL_THROUGH; |
| 1150 | case kFlags: |
| 1151 | flags_ = helper_->ReadFlags(); |
| 1152 | if (++next_read_ == field) return; |
| 1153 | FALL_THROUGH; |
| 1154 | case kName: |
| 1155 | helper_->SkipName(); // read name. |
| 1156 | if (++next_read_ == field) return; |
| 1157 | FALL_THROUGH; |
| 1158 | case kAnnotations: { |
| 1159 | annotation_count_ = helper_->ReadListLength(); // read list length. |
| 1160 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
| 1161 | helper_->SkipExpression(); // read ith expression. |
| 1162 | } |
| 1163 | if (++next_read_ == field) return; |
| 1164 | } |
| 1165 | FALL_THROUGH; |
| 1166 | case kFunction: |
| 1167 | helper_->SkipFunctionNode(); // read function. |
| 1168 | if (++next_read_ == field) return; |
| 1169 | FALL_THROUGH; |
| 1170 | case kInitializers: { |
| 1171 | intptr_t list_length = |
| 1172 | helper_->ReadListLength(); // read initializers list length. |
| 1173 | for (intptr_t i = 0; i < list_length; i++) { |
| 1174 | helper_->SkipInitializer(); |
| 1175 | } |
| 1176 | if (++next_read_ == field) return; |
| 1177 | } |
| 1178 | FALL_THROUGH; |
| 1179 | case kEnd: |
| 1180 | return; |
| 1181 | } |
| 1182 | } |
| 1183 | |
| 1184 | void ClassHelper::ReadUntilExcluding(Field field) { |
| 1185 | if (field <= next_read_) return; |
| 1186 | |
| 1187 | // Ordered with fall-through. |
| 1188 | switch (next_read_) { |
| 1189 | case kStart: { |
| 1190 | Tag tag = helper_->ReadTag(); // read tag. |
| 1191 | ASSERT(tag == kClass); |
| 1192 | if (++next_read_ == field) return; |
| 1193 | } |
| 1194 | FALL_THROUGH; |
| 1195 | case kCanonicalName: |
| 1196 | canonical_name_ = |
| 1197 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
| 1198 | if (++next_read_ == field) return; |
| 1199 | FALL_THROUGH; |
| 1200 | case kSourceUriIndex: |
| 1201 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
| 1202 | helper_->set_current_script_id(source_uri_index_); |
| 1203 | if (++next_read_ == field) return; |
| 1204 | FALL_THROUGH; |
| 1205 | case kStartPosition: |
| 1206 | start_position_ = helper_->ReadPosition(); // read position. |
| 1207 | if (++next_read_ == field) return; |
| 1208 | FALL_THROUGH; |
| 1209 | case kPosition: |
| 1210 | position_ = helper_->ReadPosition(); // read position. |
| 1211 | if (++next_read_ == field) return; |
| 1212 | FALL_THROUGH; |
| 1213 | case kEndPosition: |
| 1214 | end_position_ = helper_->ReadPosition(); // read end position. |
| 1215 | if (++next_read_ == field) return; |
| 1216 | FALL_THROUGH; |
| 1217 | case kFlags: |
| 1218 | flags_ = helper_->ReadFlags(); // read flags. |
| 1219 | if (++next_read_ == field) return; |
| 1220 | FALL_THROUGH; |
| 1221 | case kNameIndex: |
| 1222 | name_index_ = helper_->ReadStringReference(); // read name index. |
| 1223 | if (++next_read_ == field) return; |
| 1224 | FALL_THROUGH; |
| 1225 | case kAnnotations: { |
| 1226 | annotation_count_ = helper_->ReadListLength(); // read list length. |
| 1227 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
| 1228 | helper_->SkipExpression(); // read ith expression. |
| 1229 | } |
| 1230 | if (++next_read_ == field) return; |
| 1231 | } |
| 1232 | FALL_THROUGH; |
| 1233 | case kTypeParameters: |
| 1234 | helper_->SkipTypeParametersList(); // read type parameters. |
| 1235 | if (++next_read_ == field) return; |
| 1236 | FALL_THROUGH; |
| 1237 | case kSuperClass: { |
| 1238 | Tag type_tag = helper_->ReadTag(); // read super class type (part 1). |
| 1239 | if (type_tag == kSomething) { |
| 1240 | helper_->SkipDartType(); // read super class type (part 2). |
| 1241 | } |
| 1242 | if (++next_read_ == field) return; |
| 1243 | } |
| 1244 | FALL_THROUGH; |
| 1245 | case kMixinType: { |
| 1246 | Tag type_tag = helper_->ReadTag(); // read mixin type (part 1). |
| 1247 | if (type_tag == kSomething) { |
| 1248 | helper_->SkipDartType(); // read mixin type (part 2). |
| 1249 | } |
| 1250 | if (++next_read_ == field) return; |
| 1251 | } |
| 1252 | FALL_THROUGH; |
| 1253 | case kImplementedClasses: |
| 1254 | helper_->SkipListOfDartTypes(); // read implemented_classes. |
| 1255 | if (++next_read_ == field) return; |
| 1256 | FALL_THROUGH; |
| 1257 | case kFields: { |
| 1258 | intptr_t list_length = |
| 1259 | helper_->ReadListLength(); // read fields list length. |
| 1260 | for (intptr_t i = 0; i < list_length; i++) { |
| 1261 | FieldHelper field_helper(helper_); |
| 1262 | field_helper.ReadUntilExcluding(FieldHelper::kEnd); // read field. |
| 1263 | } |
| 1264 | if (++next_read_ == field) return; |
| 1265 | } |
| 1266 | FALL_THROUGH; |
| 1267 | case kConstructors: { |
| 1268 | intptr_t list_length = |
| 1269 | helper_->ReadListLength(); // read constructors list length. |
| 1270 | for (intptr_t i = 0; i < list_length; i++) { |
| 1271 | ConstructorHelper constructor_helper(helper_); |
| 1272 | constructor_helper.ReadUntilExcluding( |
| 1273 | ConstructorHelper::kEnd); // read constructor. |
| 1274 | } |
| 1275 | if (++next_read_ == field) return; |
| 1276 | } |
| 1277 | FALL_THROUGH; |
| 1278 | case kProcedures: { |
| 1279 | procedure_count_ = helper_->ReadListLength(); // read procedures #. |
| 1280 | for (intptr_t i = 0; i < procedure_count_; i++) { |
| 1281 | ProcedureHelper procedure_helper(helper_); |
| 1282 | procedure_helper.ReadUntilExcluding( |
| 1283 | ProcedureHelper::kEnd); // read procedure. |
| 1284 | } |
| 1285 | if (++next_read_ == field) return; |
| 1286 | } |
| 1287 | FALL_THROUGH; |
| 1288 | case kClassIndex: |
| 1289 | // Read class index. |
| 1290 | for (intptr_t i = 0; i < procedure_count_; ++i) { |
| 1291 | helper_->reader_.ReadUInt32(); |
| 1292 | } |
| 1293 | helper_->reader_.ReadUInt32(); |
| 1294 | helper_->reader_.ReadUInt32(); |
| 1295 | if (++next_read_ == field) return; |
| 1296 | FALL_THROUGH; |
| 1297 | case kEnd: |
| 1298 | return; |
| 1299 | } |
| 1300 | } |
| 1301 | |
| 1302 | void LibraryHelper::ReadUntilExcluding(Field field) { |
| 1303 | if (field <= next_read_) return; |
| 1304 | |
| 1305 | // Ordered with fall-through. |
| 1306 | switch (next_read_) { |
| 1307 | // Note that this (up to canonical name) needs to be kept in sync with |
| 1308 | // "library_canonical_name" (currently in "kernel_loader.h"). |
| 1309 | case kFlags: { |
| 1310 | flags_ = helper_->ReadFlags(); |
| 1311 | if (++next_read_ == field) return; |
| 1312 | FALL_THROUGH; |
| 1313 | } |
| 1314 | case kLanguageVersion: { |
| 1315 | helper_->ReadUInt(); // Read major language version. |
| 1316 | helper_->ReadUInt(); // Read minor language version. |
| 1317 | if (++next_read_ == field) return; |
| 1318 | FALL_THROUGH; |
| 1319 | } |
| 1320 | case kCanonicalName: |
| 1321 | canonical_name_ = |
| 1322 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
| 1323 | if (++next_read_ == field) return; |
| 1324 | FALL_THROUGH; |
| 1325 | case kName: |
| 1326 | name_index_ = helper_->ReadStringReference(); // read name index. |
| 1327 | if (++next_read_ == field) return; |
| 1328 | FALL_THROUGH; |
| 1329 | case kSourceUriIndex: |
| 1330 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
| 1331 | helper_->set_current_script_id(source_uri_index_); |
| 1332 | if (++next_read_ == field) return; |
| 1333 | FALL_THROUGH; |
| 1334 | case kProblemsAsJson: { |
| 1335 | intptr_t length = helper_->ReadUInt(); // read length of table. |
| 1336 | for (intptr_t i = 0; i < length; ++i) { |
| 1337 | helper_->SkipBytes(helper_->ReadUInt()); // read strings. |
| 1338 | } |
| 1339 | if (++next_read_ == field) return; |
| 1340 | } |
| 1341 | FALL_THROUGH; |
| 1342 | case kAnnotations: |
| 1343 | helper_->SkipListOfExpressions(); // read annotations. |
| 1344 | if (++next_read_ == field) return; |
| 1345 | FALL_THROUGH; |
| 1346 | case kDependencies: { |
| 1347 | intptr_t dependency_count = helper_->ReadUInt(); // read list length. |
| 1348 | for (intptr_t i = 0; i < dependency_count; ++i) { |
| 1349 | helper_->SkipLibraryDependency(); |
| 1350 | } |
| 1351 | if (++next_read_ == field) return; |
| 1352 | } |
| 1353 | return; |
| 1354 | } |
| 1355 | } |
| 1356 | |
| 1357 | void LibraryDependencyHelper::ReadUntilExcluding(Field field) { |
| 1358 | if (field <= next_read_) return; |
| 1359 | |
| 1360 | // Ordered with fall-through. |
| 1361 | switch (next_read_) { |
| 1362 | case kFileOffset: { |
| 1363 | helper_->ReadPosition(); |
| 1364 | if (++next_read_ == field) return; |
| 1365 | FALL_THROUGH; |
| 1366 | } |
| 1367 | case kFlags: { |
| 1368 | flags_ = helper_->ReadFlags(); |
| 1369 | if (++next_read_ == field) return; |
| 1370 | FALL_THROUGH; |
| 1371 | } |
| 1372 | case kAnnotations: { |
| 1373 | annotation_count_ = helper_->ReadListLength(); |
| 1374 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
| 1375 | helper_->SkipExpression(); // read ith expression. |
| 1376 | } |
| 1377 | if (++next_read_ == field) return; |
| 1378 | } |
| 1379 | FALL_THROUGH; |
| 1380 | case kTargetLibrary: { |
| 1381 | target_library_canonical_name_ = helper_->ReadCanonicalNameReference(); |
| 1382 | if (++next_read_ == field) return; |
| 1383 | } |
| 1384 | FALL_THROUGH; |
| 1385 | case kName: { |
| 1386 | name_index_ = helper_->ReadStringReference(); |
| 1387 | if (++next_read_ == field) return; |
| 1388 | } |
| 1389 | FALL_THROUGH; |
| 1390 | case kCombinators: { |
| 1391 | intptr_t count = helper_->ReadListLength(); |
| 1392 | for (intptr_t i = 0; i < count; ++i) { |
| 1393 | // Skip flags |
| 1394 | helper_->SkipBytes(1); |
| 1395 | // Skip list of names. |
| 1396 | helper_->SkipListOfStrings(); |
| 1397 | } |
| 1398 | if (++next_read_ == field) return; |
| 1399 | } |
| 1400 | FALL_THROUGH; |
| 1401 | case kEnd: |
| 1402 | return; |
| 1403 | } |
| 1404 | } |
| 1405 | |
| 1406 | #if defined(DEBUG) |
| 1407 | |
| 1408 | void MetadataHelper::VerifyMetadataMappings( |
| 1409 | const ExternalTypedData& metadata_mappings) { |
| 1410 | const intptr_t kUInt32Size = 4; |
| 1411 | Reader reader(metadata_mappings); |
| 1412 | if (reader.size() == 0) { |
| 1413 | return; |
| 1414 | } |
| 1415 | |
| 1416 | // Scan through metadata mappings in reverse direction. |
| 1417 | |
| 1418 | // Read metadataMappings length. |
| 1419 | intptr_t offset = reader.size() - kUInt32Size; |
| 1420 | const intptr_t metadata_num = reader.ReadUInt32At(offset); |
| 1421 | |
| 1422 | if (metadata_num == 0) { |
| 1423 | ASSERT(metadata_mappings.LengthInBytes() == kUInt32Size); |
| 1424 | return; |
| 1425 | } |
| 1426 | |
| 1427 | // Read metadataMappings elements. |
| 1428 | for (intptr_t i = 0; i < metadata_num; ++i) { |
| 1429 | // Read nodeOffsetToMetadataOffset length. |
| 1430 | offset -= kUInt32Size; |
| 1431 | const intptr_t mappings_num = reader.ReadUInt32At(offset); |
| 1432 | |
| 1433 | // Skip nodeOffsetToMetadataOffset. |
| 1434 | offset -= mappings_num * 2 * kUInt32Size; |
| 1435 | |
| 1436 | // Verify that node offsets are sorted. |
| 1437 | intptr_t prev_node_offset = -1; |
| 1438 | reader.set_offset(offset); |
| 1439 | for (intptr_t j = 0; j < mappings_num; ++j) { |
| 1440 | const intptr_t node_offset = reader.ReadUInt32(); |
| 1441 | const intptr_t md_offset = reader.ReadUInt32(); |
| 1442 | |
| 1443 | ASSERT(node_offset >= 0 && md_offset >= 0); |
| 1444 | ASSERT(node_offset > prev_node_offset); |
| 1445 | prev_node_offset = node_offset; |
| 1446 | } |
| 1447 | |
| 1448 | // Skip tag. |
| 1449 | offset -= kUInt32Size; |
| 1450 | } |
| 1451 | } |
| 1452 | |
| 1453 | #endif // defined(DEBUG) |
| 1454 | |
| 1455 | MetadataHelper::MetadataHelper(KernelReaderHelper* helper, |
| 1456 | const char* tag, |
| 1457 | bool precompiler_only) |
| 1458 | : helper_(helper), |
| 1459 | translation_helper_(helper->translation_helper_), |
| 1460 | tag_(tag), |
| 1461 | mappings_scanned_(false), |
| 1462 | precompiler_only_(precompiler_only), |
| 1463 | mappings_offset_(0), |
| 1464 | mappings_num_(0), |
| 1465 | last_node_offset_(0), |
| 1466 | last_mapping_index_(0) {} |
| 1467 | |
| 1468 | void MetadataHelper::SetMetadataMappings(intptr_t mappings_offset, |
| 1469 | intptr_t mappings_num) { |
| 1470 | ASSERT((mappings_offset_ == 0) && (mappings_num_ == 0)); |
| 1471 | ASSERT((mappings_offset != 0) && (mappings_num != 0)); |
| 1472 | mappings_offset_ = mappings_offset; |
| 1473 | mappings_num_ = mappings_num; |
| 1474 | last_node_offset_ = kIntptrMax; |
| 1475 | last_mapping_index_ = 0; |
| 1476 | } |
| 1477 | |
| 1478 | void MetadataHelper::ScanMetadataMappings() { |
| 1479 | const intptr_t kUInt32Size = 4; |
| 1480 | Reader reader(H.metadata_mappings()); |
| 1481 | if (reader.size() == 0) { |
| 1482 | return; |
| 1483 | } |
| 1484 | |
| 1485 | // Scan through metadata mappings in reverse direction. |
| 1486 | |
| 1487 | // Read metadataMappings length. |
| 1488 | intptr_t offset = reader.size() - kUInt32Size; |
| 1489 | uint32_t metadata_num = reader.ReadUInt32At(offset); |
| 1490 | |
| 1491 | if (metadata_num == 0) { |
| 1492 | ASSERT(H.metadata_mappings().LengthInBytes() == kUInt32Size); |
| 1493 | return; |
| 1494 | } |
| 1495 | |
| 1496 | // Read metadataMappings elements. |
| 1497 | for (uint32_t i = 0; i < metadata_num; ++i) { |
| 1498 | // Read nodeOffsetToMetadataOffset length. |
| 1499 | offset -= kUInt32Size; |
| 1500 | uint32_t mappings_num = reader.ReadUInt32At(offset); |
| 1501 | |
| 1502 | // Skip nodeOffsetToMetadataOffset and read tag. |
| 1503 | offset -= mappings_num * 2 * kUInt32Size + kUInt32Size; |
| 1504 | StringIndex tag = StringIndex(reader.ReadUInt32At(offset)); |
| 1505 | |
| 1506 | if (mappings_num == 0) { |
| 1507 | continue; |
| 1508 | } |
| 1509 | |
| 1510 | if (H.StringEquals(tag, tag_)) { |
| 1511 | if ((!FLAG_precompiled_mode) && precompiler_only_) { |
| 1512 | FATAL1("%s metadata is allowed in precompiled mode only" , tag_); |
| 1513 | } |
| 1514 | SetMetadataMappings(offset + kUInt32Size, mappings_num); |
| 1515 | return; |
| 1516 | } |
| 1517 | } |
| 1518 | } |
| 1519 | |
| 1520 | intptr_t MetadataHelper::FindMetadataMapping(intptr_t node_offset) { |
| 1521 | const intptr_t kUInt32Size = 4; |
| 1522 | ASSERT(mappings_num_ > 0); |
| 1523 | |
| 1524 | Reader reader(H.metadata_mappings()); |
| 1525 | |
| 1526 | intptr_t left = 0; |
| 1527 | intptr_t right = mappings_num_ - 1; |
| 1528 | while (left < right) { |
| 1529 | intptr_t mid = ((right - left) / 2) + left; |
| 1530 | intptr_t mid_node_offset = |
| 1531 | reader.ReadUInt32At(mappings_offset_ + mid * 2 * kUInt32Size); |
| 1532 | |
| 1533 | if (node_offset < mid_node_offset) { |
| 1534 | right = mid - 1; |
| 1535 | } else if (node_offset > mid_node_offset) { |
| 1536 | left = mid + 1; |
| 1537 | } else { |
| 1538 | return mid; // Exact match found. |
| 1539 | } |
| 1540 | } |
| 1541 | ASSERT((0 <= left) && (left <= mappings_num_)); |
| 1542 | |
| 1543 | // Approximate match is found. Make sure it has an offset greater or equal |
| 1544 | // to the given node offset. |
| 1545 | if (left < mappings_num_) { |
| 1546 | intptr_t found_node_offset = |
| 1547 | reader.ReadUInt32At(mappings_offset_ + left * 2 * kUInt32Size); |
| 1548 | |
| 1549 | if (found_node_offset < node_offset) { |
| 1550 | ++left; |
| 1551 | } |
| 1552 | } |
| 1553 | ASSERT((left == mappings_num_) || |
| 1554 | static_cast<intptr_t>(reader.ReadUInt32At( |
| 1555 | mappings_offset_ + left * 2 * kUInt32Size)) >= node_offset); |
| 1556 | |
| 1557 | return left; |
| 1558 | } |
| 1559 | |
| 1560 | intptr_t MetadataHelper::GetNextMetadataPayloadOffset(intptr_t node_offset) { |
| 1561 | if (!mappings_scanned_) { |
| 1562 | ScanMetadataMappings(); |
| 1563 | mappings_scanned_ = true; |
| 1564 | } |
| 1565 | |
| 1566 | if (mappings_num_ == 0) { |
| 1567 | return -1; // No metadata. |
| 1568 | } |
| 1569 | |
| 1570 | node_offset += helper_->data_program_offset_; |
| 1571 | |
| 1572 | // Nodes are parsed in linear order most of the time, so do the search |
| 1573 | // only if looking back. |
| 1574 | if (node_offset < last_node_offset_) { |
| 1575 | last_mapping_index_ = FindMetadataMapping(node_offset); |
| 1576 | } |
| 1577 | |
| 1578 | intptr_t index = last_mapping_index_; |
| 1579 | intptr_t mapping_node_offset = 0; |
| 1580 | intptr_t mapping_md_offset = -1; |
| 1581 | |
| 1582 | Reader reader(H.metadata_mappings()); |
| 1583 | const intptr_t kUInt32Size = 4; |
| 1584 | reader.set_offset(mappings_offset_ + index * 2 * kUInt32Size); |
| 1585 | |
| 1586 | for (; index < mappings_num_; ++index) { |
| 1587 | mapping_node_offset = reader.ReadUInt32(); |
| 1588 | mapping_md_offset = reader.ReadUInt32(); |
| 1589 | |
| 1590 | if (mapping_node_offset >= node_offset) { |
| 1591 | break; |
| 1592 | } |
| 1593 | } |
| 1594 | |
| 1595 | last_mapping_index_ = index; |
| 1596 | last_node_offset_ = node_offset; |
| 1597 | |
| 1598 | if ((index < mappings_num_) && (mapping_node_offset == node_offset)) { |
| 1599 | ASSERT(mapping_md_offset >= 0); |
| 1600 | return mapping_md_offset; |
| 1601 | } else { |
| 1602 | return -1; |
| 1603 | } |
| 1604 | } |
| 1605 | |
| 1606 | intptr_t MetadataHelper::GetComponentMetadataPayloadOffset() { |
| 1607 | const intptr_t kComponentNodeOffset = 0; |
| 1608 | return GetNextMetadataPayloadOffset(kComponentNodeOffset - |
| 1609 | helper_->data_program_offset_); |
| 1610 | } |
| 1611 | |
| 1612 | DirectCallMetadataHelper::DirectCallMetadataHelper(KernelReaderHelper* helper) |
| 1613 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
| 1614 | |
| 1615 | bool DirectCallMetadataHelper::ReadMetadata(intptr_t node_offset, |
| 1616 | NameIndex* target_name, |
| 1617 | bool* check_receiver_for_null) { |
| 1618 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
| 1619 | if (md_offset < 0) { |
| 1620 | return false; |
| 1621 | } |
| 1622 | |
| 1623 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
| 1624 | &H.metadata_payloads(), md_offset); |
| 1625 | |
| 1626 | *target_name = helper_->ReadCanonicalNameReference(); |
| 1627 | *check_receiver_for_null = helper_->ReadBool(); |
| 1628 | return true; |
| 1629 | } |
| 1630 | |
| 1631 | DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertyGet( |
| 1632 | intptr_t node_offset) { |
| 1633 | NameIndex kernel_name; |
| 1634 | bool check_receiver_for_null = false; |
| 1635 | if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) { |
| 1636 | return DirectCallMetadata(Function::null_function(), false); |
| 1637 | } |
| 1638 | |
| 1639 | if (H.IsProcedure(kernel_name) && !H.IsGetter(kernel_name)) { |
| 1640 | // Tear-off. Use method extractor as direct call target. |
| 1641 | const String& method_name = H.DartMethodName(kernel_name); |
| 1642 | const Function& target_method = Function::ZoneHandle( |
| 1643 | helper_->zone_, H.LookupMethodByMember(kernel_name, method_name)); |
| 1644 | const String& getter_name = H.DartGetterName(kernel_name); |
| 1645 | return DirectCallMetadata( |
| 1646 | Function::ZoneHandle(helper_->zone_, |
| 1647 | target_method.GetMethodExtractor(getter_name)), |
| 1648 | check_receiver_for_null); |
| 1649 | } else { |
| 1650 | const String& getter_name = H.DartGetterName(kernel_name); |
| 1651 | const Function& target = Function::ZoneHandle( |
| 1652 | helper_->zone_, H.LookupMethodByMember(kernel_name, getter_name)); |
| 1653 | ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction()); |
| 1654 | return DirectCallMetadata(target, check_receiver_for_null); |
| 1655 | } |
| 1656 | } |
| 1657 | |
| 1658 | DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertySet( |
| 1659 | intptr_t node_offset) { |
| 1660 | NameIndex kernel_name; |
| 1661 | bool check_receiver_for_null = false; |
| 1662 | if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) { |
| 1663 | return DirectCallMetadata(Function::null_function(), false); |
| 1664 | } |
| 1665 | |
| 1666 | const String& method_name = H.DartSetterName(kernel_name); |
| 1667 | const Function& target = Function::ZoneHandle( |
| 1668 | helper_->zone_, H.LookupMethodByMember(kernel_name, method_name)); |
| 1669 | ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction()); |
| 1670 | |
| 1671 | return DirectCallMetadata(target, check_receiver_for_null); |
| 1672 | } |
| 1673 | |
| 1674 | DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForMethodInvocation( |
| 1675 | intptr_t node_offset) { |
| 1676 | NameIndex kernel_name; |
| 1677 | bool check_receiver_for_null = false; |
| 1678 | if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) { |
| 1679 | return DirectCallMetadata(Function::null_function(), false); |
| 1680 | } |
| 1681 | |
| 1682 | const String& method_name = H.DartProcedureName(kernel_name); |
| 1683 | const Function& target = Function::ZoneHandle( |
| 1684 | helper_->zone_, H.LookupMethodByMember(kernel_name, method_name)); |
| 1685 | |
| 1686 | return DirectCallMetadata(target, check_receiver_for_null); |
| 1687 | } |
| 1688 | |
| 1689 | InferredTypeMetadataHelper::InferredTypeMetadataHelper( |
| 1690 | KernelReaderHelper* helper, |
| 1691 | ConstantReader* constant_reader) |
| 1692 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true), |
| 1693 | constant_reader_(constant_reader) {} |
| 1694 | |
| 1695 | InferredTypeMetadata InferredTypeMetadataHelper::GetInferredType( |
| 1696 | intptr_t node_offset, |
| 1697 | bool read_constant) { |
| 1698 | const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
| 1699 | if (md_offset < 0) { |
| 1700 | return InferredTypeMetadata(kDynamicCid, |
| 1701 | InferredTypeMetadata::kFlagNullable); |
| 1702 | } |
| 1703 | |
| 1704 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
| 1705 | &H.metadata_payloads(), md_offset); |
| 1706 | |
| 1707 | const NameIndex kernel_name = helper_->ReadCanonicalNameReference(); |
| 1708 | const uint8_t flags = helper_->ReadByte(); |
| 1709 | |
| 1710 | const Object* constant_value = &Object::null_object(); |
| 1711 | if ((flags & InferredTypeMetadata::kFlagConstant) != 0) { |
| 1712 | const intptr_t constant_offset = helper_->ReadUInt(); |
| 1713 | if (read_constant) { |
| 1714 | constant_value = &Object::ZoneHandle( |
| 1715 | H.zone(), constant_reader_->ReadConstant(constant_offset)); |
| 1716 | } |
| 1717 | } |
| 1718 | |
| 1719 | if (H.IsRoot(kernel_name)) { |
| 1720 | ASSERT((flags & InferredTypeMetadata::kFlagConstant) == 0); |
| 1721 | return InferredTypeMetadata(kDynamicCid, flags); |
| 1722 | } |
| 1723 | |
| 1724 | const Class& klass = |
| 1725 | Class::Handle(helper_->zone_, H.LookupClassByKernelClass(kernel_name)); |
| 1726 | ASSERT(!klass.IsNull()); |
| 1727 | |
| 1728 | intptr_t cid = klass.id(); |
| 1729 | if (cid == kClosureCid) { |
| 1730 | // VM uses more specific function types and doesn't expect instances of |
| 1731 | // _Closure class, so inferred _Closure class doesn't make sense for the VM. |
| 1732 | cid = kDynamicCid; |
| 1733 | } |
| 1734 | |
| 1735 | return InferredTypeMetadata(cid, flags, *constant_value); |
| 1736 | } |
| 1737 | |
| 1738 | void ProcedureAttributesMetadata::InitializeFromFlags(uint8_t flags) { |
| 1739 | const int kMethodOrSetterCalledDynamicallyBit = 1 << 0; |
| 1740 | const int kNonThisUsesBit = 1 << 1; |
| 1741 | const int kTearOffUsesBit = 1 << 2; |
| 1742 | const int kThisUsesBit = 1 << 3; |
| 1743 | const int kGetterCalledDynamicallyBit = 1 << 4; |
| 1744 | |
| 1745 | method_or_setter_called_dynamically = |
| 1746 | (flags & kMethodOrSetterCalledDynamicallyBit) != 0; |
| 1747 | getter_called_dynamically = (flags & kGetterCalledDynamicallyBit) != 0; |
| 1748 | has_this_uses = (flags & kThisUsesBit) != 0; |
| 1749 | has_non_this_uses = (flags & kNonThisUsesBit) != 0; |
| 1750 | has_tearoff_uses = (flags & kTearOffUsesBit) != 0; |
| 1751 | } |
| 1752 | |
| 1753 | ProcedureAttributesMetadataHelper::ProcedureAttributesMetadataHelper( |
| 1754 | KernelReaderHelper* helper) |
| 1755 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
| 1756 | |
| 1757 | bool ProcedureAttributesMetadataHelper::ReadMetadata( |
| 1758 | intptr_t node_offset, |
| 1759 | ProcedureAttributesMetadata* metadata) { |
| 1760 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
| 1761 | if (md_offset < 0) { |
| 1762 | return false; |
| 1763 | } |
| 1764 | |
| 1765 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
| 1766 | &H.metadata_payloads(), md_offset); |
| 1767 | |
| 1768 | const uint8_t flags = helper_->ReadByte(); |
| 1769 | metadata->InitializeFromFlags(flags); |
| 1770 | metadata->method_or_setter_selector_id = helper_->ReadUInt(); |
| 1771 | metadata->getter_selector_id = helper_->ReadUInt(); |
| 1772 | return true; |
| 1773 | } |
| 1774 | |
| 1775 | ProcedureAttributesMetadata |
| 1776 | ProcedureAttributesMetadataHelper::GetProcedureAttributes( |
| 1777 | intptr_t node_offset) { |
| 1778 | ProcedureAttributesMetadata metadata; |
| 1779 | ReadMetadata(node_offset, &metadata); |
| 1780 | return metadata; |
| 1781 | } |
| 1782 | |
| 1783 | ObfuscationProhibitionsMetadataHelper::ObfuscationProhibitionsMetadataHelper( |
| 1784 | KernelReaderHelper* helper) |
| 1785 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
| 1786 | |
| 1787 | void ObfuscationProhibitionsMetadataHelper::ReadMetadata(intptr_t node_offset) { |
| 1788 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
| 1789 | if (md_offset < 0) { |
| 1790 | return; |
| 1791 | } |
| 1792 | |
| 1793 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
| 1794 | &H.metadata_payloads(), md_offset); |
| 1795 | Obfuscator O(Thread::Current(), String::Handle()); |
| 1796 | |
| 1797 | intptr_t len = helper_->ReadUInt32(); |
| 1798 | for (int i = 0; i < len; ++i) { |
| 1799 | StringIndex name = helper_->ReadStringReference(); |
| 1800 | O.PreventRenaming(translation_helper_.DartSymbolPlain(name)); |
| 1801 | } |
| 1802 | return; |
| 1803 | } |
| 1804 | |
| 1805 | LoadingUnitsMetadataHelper::LoadingUnitsMetadataHelper( |
| 1806 | KernelReaderHelper* helper) |
| 1807 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
| 1808 | |
| 1809 | void LoadingUnitsMetadataHelper::ReadMetadata(intptr_t node_offset) { |
| 1810 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
| 1811 | if (md_offset < 0) { |
| 1812 | return; |
| 1813 | } |
| 1814 | |
| 1815 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
| 1816 | &H.metadata_payloads(), md_offset); |
| 1817 | |
| 1818 | Thread* T = Thread::Current(); |
| 1819 | Zone* Z = T->zone(); |
| 1820 | intptr_t unit_count = helper_->ReadUInt(); |
| 1821 | Array& loading_units = Array::Handle(Z, Array::New(unit_count + 1)); |
| 1822 | LoadingUnit& unit = LoadingUnit::Handle(Z); |
| 1823 | LoadingUnit& parent = LoadingUnit::Handle(Z); |
| 1824 | Library& lib = Library::Handle(Z); |
| 1825 | |
| 1826 | for (int i = 0; i < unit_count; i++) { |
| 1827 | intptr_t id = helper_->ReadUInt(); |
| 1828 | unit = LoadingUnit::New(); |
| 1829 | unit.set_id(id); |
| 1830 | |
| 1831 | intptr_t parent_id = helper_->ReadUInt(); |
| 1832 | RELEASE_ASSERT(parent_id < id); |
| 1833 | parent ^= loading_units.At(parent_id); |
| 1834 | RELEASE_ASSERT(parent.IsNull() == (parent_id == 0)); |
| 1835 | unit.set_parent(parent); |
| 1836 | |
| 1837 | intptr_t library_count = helper_->ReadUInt(); |
| 1838 | for (intptr_t j = 0; j < library_count; j++) { |
| 1839 | const String& uri = |
| 1840 | translation_helper_.DartSymbolPlain(helper_->ReadStringReference()); |
| 1841 | lib = Library::LookupLibrary(T, uri); |
| 1842 | if (lib.IsNull()) { |
| 1843 | FATAL1("Missing library: %s\n" , uri.ToCString()); |
| 1844 | } |
| 1845 | lib.set_loading_unit(unit); |
| 1846 | } |
| 1847 | |
| 1848 | loading_units.SetAt(id, unit); |
| 1849 | } |
| 1850 | |
| 1851 | ObjectStore* object_store = Isolate::Current()->object_store(); |
| 1852 | ASSERT(object_store->loading_units() == Array::null()); |
| 1853 | object_store->set_loading_units(loading_units); |
| 1854 | } |
| 1855 | |
| 1856 | CallSiteAttributesMetadataHelper::CallSiteAttributesMetadataHelper( |
| 1857 | KernelReaderHelper* helper, |
| 1858 | TypeTranslator* type_translator) |
| 1859 | : MetadataHelper(helper, tag(), /* precompiler_only = */ false), |
| 1860 | type_translator_(*type_translator) {} |
| 1861 | |
| 1862 | bool CallSiteAttributesMetadataHelper::ReadMetadata( |
| 1863 | intptr_t node_offset, |
| 1864 | CallSiteAttributesMetadata* metadata) { |
| 1865 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
| 1866 | if (md_offset < 0) { |
| 1867 | return false; |
| 1868 | } |
| 1869 | |
| 1870 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
| 1871 | &H.metadata_payloads(), md_offset); |
| 1872 | |
| 1873 | metadata->receiver_type = &type_translator_.BuildType(); |
| 1874 | return true; |
| 1875 | } |
| 1876 | |
| 1877 | CallSiteAttributesMetadata |
| 1878 | CallSiteAttributesMetadataHelper::GetCallSiteAttributes(intptr_t node_offset) { |
| 1879 | CallSiteAttributesMetadata metadata; |
| 1880 | ReadMetadata(node_offset, &metadata); |
| 1881 | return metadata; |
| 1882 | } |
| 1883 | |
| 1884 | TableSelectorMetadataHelper::TableSelectorMetadataHelper( |
| 1885 | KernelReaderHelper* helper) |
| 1886 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
| 1887 | |
| 1888 | TableSelectorMetadata* TableSelectorMetadataHelper::GetTableSelectorMetadata( |
| 1889 | Zone* zone) { |
| 1890 | const intptr_t node_offset = GetComponentMetadataPayloadOffset(); |
| 1891 | const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
| 1892 | if (md_offset < 0) { |
| 1893 | return nullptr; |
| 1894 | } |
| 1895 | |
| 1896 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
| 1897 | &H.metadata_payloads(), md_offset); |
| 1898 | |
| 1899 | const intptr_t num_selectors = helper_->ReadUInt(); |
| 1900 | TableSelectorMetadata* metadata = |
| 1901 | new (zone) TableSelectorMetadata(num_selectors); |
| 1902 | for (intptr_t i = 0; i < num_selectors; i++) { |
| 1903 | ReadTableSelectorInfo(&metadata->selectors[i]); |
| 1904 | } |
| 1905 | return metadata; |
| 1906 | } |
| 1907 | |
| 1908 | void TableSelectorMetadataHelper::ReadTableSelectorInfo( |
| 1909 | TableSelectorInfo* info) { |
| 1910 | info->call_count = helper_->ReadUInt(); |
| 1911 | uint8_t flags = helper_->ReadByte(); |
| 1912 | info->called_on_null = (flags & kCalledOnNullBit) != 0; |
| 1913 | info->torn_off = (flags & kTornOffBit) != 0; |
| 1914 | } |
| 1915 | |
| 1916 | UnboxingInfoMetadataHelper::UnboxingInfoMetadataHelper( |
| 1917 | KernelReaderHelper* helper) |
| 1918 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
| 1919 | |
| 1920 | UnboxingInfoMetadata* UnboxingInfoMetadataHelper::GetUnboxingInfoMetadata( |
| 1921 | intptr_t node_offset) { |
| 1922 | const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
| 1923 | |
| 1924 | if (md_offset < 0) { |
| 1925 | return nullptr; |
| 1926 | } |
| 1927 | |
| 1928 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
| 1929 | &H.metadata_payloads(), md_offset); |
| 1930 | |
| 1931 | const intptr_t num_args = helper_->ReadUInt(); |
| 1932 | const auto info = new (helper_->zone_) UnboxingInfoMetadata(); |
| 1933 | info->SetArgsCount(num_args); |
| 1934 | for (intptr_t i = 0; i < num_args; i++) { |
| 1935 | const auto arg_info = helper_->ReadByte(); |
| 1936 | assert(arg_info >= UnboxingInfoMetadata::kBoxed && |
| 1937 | arg_info < UnboxingInfoMetadata::kUnboxingCandidate); |
| 1938 | info->unboxed_args_info[i] = |
| 1939 | static_cast<UnboxingInfoMetadata::UnboxingInfoTag>(arg_info); |
| 1940 | } |
| 1941 | const auto return_info = helper_->ReadByte(); |
| 1942 | assert(return_info >= UnboxingInfoMetadata::kBoxed && |
| 1943 | return_info < UnboxingInfoMetadata::kUnboxingCandidate); |
| 1944 | info->return_info = |
| 1945 | static_cast<UnboxingInfoMetadata::UnboxingInfoTag>(return_info); |
| 1946 | return info; |
| 1947 | } |
| 1948 | |
| 1949 | intptr_t KernelReaderHelper::ReaderOffset() const { |
| 1950 | return reader_.offset(); |
| 1951 | } |
| 1952 | |
| 1953 | void KernelReaderHelper::SetOffset(intptr_t offset) { |
| 1954 | reader_.set_offset(offset); |
| 1955 | } |
| 1956 | |
| 1957 | void KernelReaderHelper::SkipBytes(intptr_t bytes) { |
| 1958 | reader_.set_offset(ReaderOffset() + bytes); |
| 1959 | } |
| 1960 | |
| 1961 | bool KernelReaderHelper::ReadBool() { |
| 1962 | return reader_.ReadBool(); |
| 1963 | } |
| 1964 | |
| 1965 | uint8_t KernelReaderHelper::ReadByte() { |
| 1966 | return reader_.ReadByte(); |
| 1967 | } |
| 1968 | |
| 1969 | uint32_t KernelReaderHelper::ReadUInt() { |
| 1970 | return reader_.ReadUInt(); |
| 1971 | } |
| 1972 | |
| 1973 | uint32_t KernelReaderHelper::ReadUInt32() { |
| 1974 | return reader_.ReadUInt32(); |
| 1975 | } |
| 1976 | |
| 1977 | uint32_t KernelReaderHelper::PeekUInt() { |
| 1978 | AlternativeReadingScope alt(&reader_); |
| 1979 | return reader_.ReadUInt(); |
| 1980 | } |
| 1981 | |
| 1982 | double KernelReaderHelper::ReadDouble() { |
| 1983 | return reader_.ReadDouble(); |
| 1984 | } |
| 1985 | |
| 1986 | uint32_t KernelReaderHelper::PeekListLength() { |
| 1987 | AlternativeReadingScope alt(&reader_); |
| 1988 | return reader_.ReadListLength(); |
| 1989 | } |
| 1990 | |
| 1991 | intptr_t KernelReaderHelper::ReadListLength() { |
| 1992 | return reader_.ReadListLength(); |
| 1993 | } |
| 1994 | |
| 1995 | StringIndex KernelReaderHelper::ReadStringReference() { |
| 1996 | return StringIndex(ReadUInt()); |
| 1997 | } |
| 1998 | |
| 1999 | NameIndex KernelReaderHelper::ReadCanonicalNameReference() { |
| 2000 | return reader_.ReadCanonicalNameReference(); |
| 2001 | } |
| 2002 | |
| 2003 | NameIndex KernelReaderHelper::ReadInterfaceMemberNameReference() { |
| 2004 | NameIndex name_index = reader_.ReadCanonicalNameReference(); |
| 2005 | NameIndex origin_name_index = reader_.ReadCanonicalNameReference(); |
| 2006 | if (!FLAG_precompiled_mode && origin_name_index != NameIndex::kInvalidName) { |
| 2007 | // Reference to a skipped member signature target, return the origin target. |
| 2008 | return origin_name_index; |
| 2009 | } |
| 2010 | return name_index; |
| 2011 | } |
| 2012 | |
| 2013 | StringIndex KernelReaderHelper::ReadNameAsStringIndex() { |
| 2014 | StringIndex name_index = ReadStringReference(); // read name index. |
| 2015 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
| 2016 | ReadUInt(); // read library index. |
| 2017 | } |
| 2018 | return name_index; |
| 2019 | } |
| 2020 | |
| 2021 | const String& KernelReaderHelper::ReadNameAsMethodName() { |
| 2022 | StringIndex name_index = ReadStringReference(); // read name index. |
| 2023 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
| 2024 | NameIndex library_reference = |
| 2025 | ReadCanonicalNameReference(); // read library index. |
| 2026 | return H.DartMethodName(library_reference, name_index); |
| 2027 | } else { |
| 2028 | return H.DartMethodName(NameIndex(), name_index); |
| 2029 | } |
| 2030 | } |
| 2031 | |
| 2032 | const String& KernelReaderHelper::ReadNameAsSetterName() { |
| 2033 | StringIndex name_index = ReadStringReference(); // read name index. |
| 2034 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
| 2035 | NameIndex library_reference = |
| 2036 | ReadCanonicalNameReference(); // read library index. |
| 2037 | return H.DartSetterName(library_reference, name_index); |
| 2038 | } else { |
| 2039 | return H.DartSetterName(NameIndex(), name_index); |
| 2040 | } |
| 2041 | } |
| 2042 | |
| 2043 | const String& KernelReaderHelper::ReadNameAsGetterName() { |
| 2044 | StringIndex name_index = ReadStringReference(); // read name index. |
| 2045 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
| 2046 | NameIndex library_reference = |
| 2047 | ReadCanonicalNameReference(); // read library index. |
| 2048 | return H.DartGetterName(library_reference, name_index); |
| 2049 | } else { |
| 2050 | return H.DartGetterName(NameIndex(), name_index); |
| 2051 | } |
| 2052 | } |
| 2053 | |
| 2054 | const String& KernelReaderHelper::ReadNameAsFieldName() { |
| 2055 | StringIndex name_index = ReadStringReference(); // read name index. |
| 2056 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
| 2057 | NameIndex library_reference = |
| 2058 | ReadCanonicalNameReference(); // read library index. |
| 2059 | return H.DartFieldName(library_reference, name_index); |
| 2060 | } else { |
| 2061 | return H.DartFieldName(NameIndex(), name_index); |
| 2062 | } |
| 2063 | } |
| 2064 | |
| 2065 | void KernelReaderHelper::SkipFlags() { |
| 2066 | ReadFlags(); |
| 2067 | } |
| 2068 | |
| 2069 | void KernelReaderHelper::SkipStringReference() { |
| 2070 | ReadUInt(); |
| 2071 | } |
| 2072 | |
| 2073 | void KernelReaderHelper::SkipConstantReference() { |
| 2074 | ReadUInt(); |
| 2075 | } |
| 2076 | |
| 2077 | void KernelReaderHelper::SkipCanonicalNameReference() { |
| 2078 | ReadUInt(); |
| 2079 | } |
| 2080 | |
| 2081 | void KernelReaderHelper::SkipInterfaceMemberNameReference() { |
| 2082 | SkipCanonicalNameReference(); |
| 2083 | SkipCanonicalNameReference(); |
| 2084 | } |
| 2085 | |
| 2086 | void KernelReaderHelper::ReportUnexpectedTag(const char* variant, Tag tag) { |
| 2087 | FATAL3("Unexpected tag %d (%s) in ?, expected %s" , tag, Reader::TagName(tag), |
| 2088 | variant); |
| 2089 | } |
| 2090 | |
| 2091 | void KernelReaderHelper::ReadUntilFunctionNode() { |
| 2092 | const Tag tag = PeekTag(); |
| 2093 | if (tag == kProcedure) { |
| 2094 | ProcedureHelper procedure_helper(this); |
| 2095 | procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction); |
| 2096 | if (ReadTag() == kNothing) { // read function node tag. |
| 2097 | // Running a procedure without a function node doesn't make sense. |
| 2098 | UNREACHABLE(); |
| 2099 | } |
| 2100 | // Now at start of FunctionNode. |
| 2101 | } else if (tag == kConstructor) { |
| 2102 | ConstructorHelper constructor_helper(this); |
| 2103 | constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction); |
| 2104 | // Now at start of FunctionNode. |
| 2105 | // Notice that we also have a list of initializers after that! |
| 2106 | } else if (tag == kFunctionNode) { |
| 2107 | // Already at start of FunctionNode. |
| 2108 | } else { |
| 2109 | ReportUnexpectedTag("a procedure, a constructor or a function node" , tag); |
| 2110 | UNREACHABLE(); |
| 2111 | } |
| 2112 | } |
| 2113 | |
| 2114 | void KernelReaderHelper::SkipDartType() { |
| 2115 | Tag tag = ReadTag(); |
| 2116 | switch (tag) { |
| 2117 | case kInvalidType: |
| 2118 | case kDynamicType: |
| 2119 | case kVoidType: |
| 2120 | case kBottomType: |
| 2121 | // those contain nothing. |
| 2122 | return; |
| 2123 | case kNeverType: |
| 2124 | ReadNullability(); |
| 2125 | return; |
| 2126 | case kInterfaceType: |
| 2127 | SkipInterfaceType(false); |
| 2128 | return; |
| 2129 | case kSimpleInterfaceType: |
| 2130 | SkipInterfaceType(true); |
| 2131 | return; |
| 2132 | case kFunctionType: |
| 2133 | SkipFunctionType(false); |
| 2134 | return; |
| 2135 | case kSimpleFunctionType: |
| 2136 | SkipFunctionType(true); |
| 2137 | return; |
| 2138 | case kTypedefType: |
| 2139 | ReadNullability(); // read nullability. |
| 2140 | ReadUInt(); // read index for canonical name. |
| 2141 | SkipListOfDartTypes(); // read list of types. |
| 2142 | return; |
| 2143 | case kTypeParameterType: |
| 2144 | ReadNullability(); // read nullability. |
| 2145 | ReadUInt(); // read index for parameter. |
| 2146 | SkipOptionalDartType(); // read bound bound. |
| 2147 | return; |
| 2148 | default: |
| 2149 | ReportUnexpectedTag("type" , tag); |
| 2150 | UNREACHABLE(); |
| 2151 | } |
| 2152 | } |
| 2153 | |
| 2154 | void KernelReaderHelper::SkipOptionalDartType() { |
| 2155 | Tag tag = ReadTag(); // read tag. |
| 2156 | if (tag == kNothing) { |
| 2157 | return; |
| 2158 | } |
| 2159 | ASSERT(tag == kSomething); |
| 2160 | |
| 2161 | SkipDartType(); // read type. |
| 2162 | } |
| 2163 | |
| 2164 | void KernelReaderHelper::SkipInterfaceType(bool simple) { |
| 2165 | ReadNullability(); // read nullability. |
| 2166 | ReadUInt(); // read klass_name. |
| 2167 | if (!simple) { |
| 2168 | SkipListOfDartTypes(); // read list of types. |
| 2169 | } |
| 2170 | } |
| 2171 | |
| 2172 | void KernelReaderHelper::SkipFunctionType(bool simple) { |
| 2173 | ReadNullability(); // read nullability. |
| 2174 | |
| 2175 | if (!simple) { |
| 2176 | SkipTypeParametersList(); // read type_parameters. |
| 2177 | ReadUInt(); // read required parameter count. |
| 2178 | ReadUInt(); // read total parameter count. |
| 2179 | } |
| 2180 | |
| 2181 | SkipListOfDartTypes(); // read positional_parameters types. |
| 2182 | |
| 2183 | if (!simple) { |
| 2184 | const intptr_t named_count = |
| 2185 | ReadListLength(); // read named_parameters list length. |
| 2186 | for (intptr_t i = 0; i < named_count; ++i) { |
| 2187 | // read string reference (i.e. named_parameters[i].name). |
| 2188 | SkipStringReference(); |
| 2189 | SkipDartType(); // read named_parameters[i].type. |
| 2190 | SkipBytes(1); // read flags |
| 2191 | } |
| 2192 | } |
| 2193 | |
| 2194 | if (!simple) { |
| 2195 | SkipOptionalDartType(); // read typedef type. |
| 2196 | } |
| 2197 | |
| 2198 | SkipDartType(); // read return type. |
| 2199 | } |
| 2200 | |
| 2201 | void KernelReaderHelper::SkipStatementList() { |
| 2202 | intptr_t list_length = ReadListLength(); // read list length. |
| 2203 | for (intptr_t i = 0; i < list_length; ++i) { |
| 2204 | SkipStatement(); // read ith expression. |
| 2205 | } |
| 2206 | } |
| 2207 | |
| 2208 | void KernelReaderHelper::SkipListOfExpressions() { |
| 2209 | intptr_t list_length = ReadListLength(); // read list length. |
| 2210 | for (intptr_t i = 0; i < list_length; ++i) { |
| 2211 | SkipExpression(); // read ith expression. |
| 2212 | } |
| 2213 | } |
| 2214 | |
| 2215 | void KernelReaderHelper::SkipListOfDartTypes() { |
| 2216 | intptr_t list_length = ReadListLength(); // read list length. |
| 2217 | for (intptr_t i = 0; i < list_length; ++i) { |
| 2218 | SkipDartType(); // read ith type. |
| 2219 | } |
| 2220 | } |
| 2221 | |
| 2222 | void KernelReaderHelper::SkipListOfStrings() { |
| 2223 | intptr_t list_length = ReadListLength(); // read list length. |
| 2224 | for (intptr_t i = 0; i < list_length; ++i) { |
| 2225 | SkipStringReference(); // read ith string index. |
| 2226 | } |
| 2227 | } |
| 2228 | |
| 2229 | void KernelReaderHelper::SkipListOfVariableDeclarations() { |
| 2230 | intptr_t list_length = ReadListLength(); // read list length. |
| 2231 | for (intptr_t i = 0; i < list_length; ++i) { |
| 2232 | SkipVariableDeclaration(); // read ith variable declaration. |
| 2233 | } |
| 2234 | } |
| 2235 | |
| 2236 | void KernelReaderHelper::SkipTypeParametersList() { |
| 2237 | intptr_t list_length = ReadListLength(); // read list length. |
| 2238 | for (intptr_t i = 0; i < list_length; ++i) { |
| 2239 | TypeParameterHelper helper(this); |
| 2240 | helper.Finish(); |
| 2241 | } |
| 2242 | } |
| 2243 | |
| 2244 | void KernelReaderHelper::SkipInitializer() { |
| 2245 | Tag tag = ReadTag(); |
| 2246 | ReadByte(); // read isSynthetic flag. |
| 2247 | switch (tag) { |
| 2248 | case kInvalidInitializer: |
| 2249 | return; |
| 2250 | case kFieldInitializer: |
| 2251 | SkipCanonicalNameReference(); // read field_reference. |
| 2252 | SkipExpression(); // read value. |
| 2253 | return; |
| 2254 | case kSuperInitializer: |
| 2255 | ReadPosition(); // read position. |
| 2256 | SkipCanonicalNameReference(); // read target_reference. |
| 2257 | SkipArguments(); // read arguments. |
| 2258 | return; |
| 2259 | case kRedirectingInitializer: |
| 2260 | ReadPosition(); // read position. |
| 2261 | SkipCanonicalNameReference(); // read target_reference. |
| 2262 | SkipArguments(); // read arguments. |
| 2263 | return; |
| 2264 | case kLocalInitializer: |
| 2265 | SkipVariableDeclaration(); // read variable. |
| 2266 | return; |
| 2267 | case kAssertInitializer: |
| 2268 | SkipStatement(); |
| 2269 | return; |
| 2270 | default: |
| 2271 | ReportUnexpectedTag("initializer" , tag); |
| 2272 | UNREACHABLE(); |
| 2273 | } |
| 2274 | } |
| 2275 | |
| 2276 | void KernelReaderHelper::SkipExpression() { |
| 2277 | uint8_t payload = 0; |
| 2278 | Tag tag = ReadTag(&payload); |
| 2279 | switch (tag) { |
| 2280 | case kInvalidExpression: |
| 2281 | ReadPosition(); |
| 2282 | SkipStringReference(); |
| 2283 | return; |
| 2284 | case kVariableGet: |
| 2285 | ReadPosition(); // read position. |
| 2286 | ReadUInt(); // read kernel position. |
| 2287 | ReadUInt(); // read relative variable index. |
| 2288 | SkipOptionalDartType(); // read promoted type. |
| 2289 | return; |
| 2290 | case kSpecializedVariableGet: |
| 2291 | ReadPosition(); // read position. |
| 2292 | ReadUInt(); // read kernel position. |
| 2293 | return; |
| 2294 | case kVariableSet: |
| 2295 | ReadPosition(); // read position. |
| 2296 | ReadUInt(); // read kernel position. |
| 2297 | ReadUInt(); // read relative variable index. |
| 2298 | SkipExpression(); // read expression. |
| 2299 | return; |
| 2300 | case kSpecializedVariableSet: |
| 2301 | ReadPosition(); // read position. |
| 2302 | ReadUInt(); // read kernel position. |
| 2303 | SkipExpression(); // read expression. |
| 2304 | return; |
| 2305 | case kPropertyGet: |
| 2306 | ReadPosition(); // read position. |
| 2307 | SkipExpression(); // read receiver. |
| 2308 | SkipName(); // read name. |
| 2309 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
| 2310 | return; |
| 2311 | case kPropertySet: |
| 2312 | ReadPosition(); // read position. |
| 2313 | SkipExpression(); // read receiver. |
| 2314 | SkipName(); // read name. |
| 2315 | SkipExpression(); // read value. |
| 2316 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
| 2317 | return; |
| 2318 | case kSuperPropertyGet: |
| 2319 | ReadPosition(); // read position. |
| 2320 | SkipName(); // read name. |
| 2321 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
| 2322 | return; |
| 2323 | case kSuperPropertySet: |
| 2324 | ReadPosition(); // read position. |
| 2325 | SkipName(); // read name. |
| 2326 | SkipExpression(); // read value. |
| 2327 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
| 2328 | return; |
| 2329 | case kDirectPropertyGet: |
| 2330 | ReadPosition(); // read position. |
| 2331 | SkipExpression(); // read receiver. |
| 2332 | SkipInterfaceMemberNameReference(); // read target_reference. |
| 2333 | return; |
| 2334 | case kDirectPropertySet: |
| 2335 | ReadPosition(); // read position. |
| 2336 | SkipExpression(); // read receiver. |
| 2337 | SkipInterfaceMemberNameReference(); // read target_reference. |
| 2338 | SkipExpression(); // read value· |
| 2339 | return; |
| 2340 | case kStaticGet: |
| 2341 | ReadPosition(); // read position. |
| 2342 | SkipCanonicalNameReference(); // read target_reference. |
| 2343 | return; |
| 2344 | case kStaticSet: |
| 2345 | ReadPosition(); // read position. |
| 2346 | SkipCanonicalNameReference(); // read target_reference. |
| 2347 | SkipExpression(); // read expression. |
| 2348 | return; |
| 2349 | case kMethodInvocation: |
| 2350 | ReadPosition(); // read position. |
| 2351 | SkipExpression(); // read receiver. |
| 2352 | SkipName(); // read name. |
| 2353 | SkipArguments(); // read arguments. |
| 2354 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
| 2355 | return; |
| 2356 | case kSuperMethodInvocation: |
| 2357 | ReadPosition(); // read position. |
| 2358 | SkipName(); // read name. |
| 2359 | SkipArguments(); // read arguments. |
| 2360 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
| 2361 | return; |
| 2362 | case kDirectMethodInvocation: |
| 2363 | ReadPosition(); // read position. |
| 2364 | SkipExpression(); // read receiver. |
| 2365 | SkipInterfaceMemberNameReference(); // read target_reference. |
| 2366 | SkipArguments(); // read arguments. |
| 2367 | return; |
| 2368 | case kStaticInvocation: |
| 2369 | ReadPosition(); // read position. |
| 2370 | SkipCanonicalNameReference(); // read procedure_reference. |
| 2371 | SkipArguments(); // read arguments. |
| 2372 | return; |
| 2373 | case kConstructorInvocation: |
| 2374 | ReadPosition(); // read position. |
| 2375 | SkipCanonicalNameReference(); // read target_reference. |
| 2376 | SkipArguments(); // read arguments. |
| 2377 | return; |
| 2378 | case kNot: |
| 2379 | SkipExpression(); // read expression. |
| 2380 | return; |
| 2381 | case kNullCheck: |
| 2382 | ReadPosition(); // read position. |
| 2383 | SkipExpression(); // read expression. |
| 2384 | return; |
| 2385 | case kLogicalExpression: |
| 2386 | SkipExpression(); // read left. |
| 2387 | SkipBytes(1); // read operator. |
| 2388 | SkipExpression(); // read right. |
| 2389 | return; |
| 2390 | case kConditionalExpression: |
| 2391 | SkipExpression(); // read condition. |
| 2392 | SkipExpression(); // read then. |
| 2393 | SkipExpression(); // read otherwise. |
| 2394 | SkipOptionalDartType(); // read unused static type. |
| 2395 | return; |
| 2396 | case kStringConcatenation: |
| 2397 | ReadPosition(); // read position. |
| 2398 | SkipListOfExpressions(); // read list of expressions. |
| 2399 | return; |
| 2400 | case kIsExpression: |
| 2401 | ReadPosition(); // read position. |
| 2402 | if (translation_helper_.info().kernel_binary_version() >= 38) { |
| 2403 | SkipFlags(); // read flags. |
| 2404 | } |
| 2405 | SkipExpression(); // read operand. |
| 2406 | SkipDartType(); // read type. |
| 2407 | return; |
| 2408 | case kAsExpression: |
| 2409 | ReadPosition(); // read position. |
| 2410 | SkipFlags(); // read flags. |
| 2411 | SkipExpression(); // read operand. |
| 2412 | SkipDartType(); // read type. |
| 2413 | return; |
| 2414 | case kTypeLiteral: |
| 2415 | SkipDartType(); // read type. |
| 2416 | return; |
| 2417 | case kThisExpression: |
| 2418 | return; |
| 2419 | case kRethrow: |
| 2420 | ReadPosition(); // read position. |
| 2421 | return; |
| 2422 | case kThrow: |
| 2423 | ReadPosition(); // read position. |
| 2424 | SkipExpression(); // read expression. |
| 2425 | return; |
| 2426 | case kListLiteral: |
| 2427 | ReadPosition(); // read position. |
| 2428 | SkipDartType(); // read type. |
| 2429 | SkipListOfExpressions(); // read list of expressions. |
| 2430 | return; |
| 2431 | case kSetLiteral: |
| 2432 | // Set literals are currently desugared in the frontend and will not |
| 2433 | // reach the VM. See http://dartbug.com/35124 for discussion. |
| 2434 | UNREACHABLE(); |
| 2435 | return; |
| 2436 | case kMapLiteral: { |
| 2437 | ReadPosition(); // read position. |
| 2438 | SkipDartType(); // read key type. |
| 2439 | SkipDartType(); // read value type. |
| 2440 | intptr_t list_length = ReadListLength(); // read list length. |
| 2441 | for (intptr_t i = 0; i < list_length; ++i) { |
| 2442 | SkipExpression(); // read ith key. |
| 2443 | SkipExpression(); // read ith value. |
| 2444 | } |
| 2445 | return; |
| 2446 | } |
| 2447 | case kFunctionExpression: |
| 2448 | ReadPosition(); // read position. |
| 2449 | SkipFunctionNode(); // read function node. |
| 2450 | return; |
| 2451 | case kLet: |
| 2452 | SkipVariableDeclaration(); // read variable declaration. |
| 2453 | SkipExpression(); // read expression. |
| 2454 | return; |
| 2455 | case kBlockExpression: |
| 2456 | SkipStatementList(); |
| 2457 | SkipExpression(); // read expression. |
| 2458 | return; |
| 2459 | case kInstantiation: |
| 2460 | SkipExpression(); // read expression. |
| 2461 | SkipListOfDartTypes(); // read type arguments. |
| 2462 | return; |
| 2463 | case kBigIntLiteral: |
| 2464 | SkipStringReference(); // read string reference. |
| 2465 | return; |
| 2466 | case kStringLiteral: |
| 2467 | SkipStringReference(); // read string reference. |
| 2468 | return; |
| 2469 | case kSpecializedIntLiteral: |
| 2470 | return; |
| 2471 | case kNegativeIntLiteral: |
| 2472 | ReadUInt(); // read value. |
| 2473 | return; |
| 2474 | case kPositiveIntLiteral: |
| 2475 | ReadUInt(); // read value. |
| 2476 | return; |
| 2477 | case kDoubleLiteral: |
| 2478 | ReadDouble(); // read value. |
| 2479 | return; |
| 2480 | case kTrueLiteral: |
| 2481 | return; |
| 2482 | case kFalseLiteral: |
| 2483 | return; |
| 2484 | case kNullLiteral: |
| 2485 | return; |
| 2486 | case kConstantExpression: |
| 2487 | ReadPosition(); // read position. |
| 2488 | SkipDartType(); // read type. |
| 2489 | SkipConstantReference(); |
| 2490 | return; |
| 2491 | case kLoadLibrary: |
| 2492 | case kCheckLibraryIsLoaded: |
| 2493 | ReadUInt(); // skip library index |
| 2494 | return; |
| 2495 | case kConstStaticInvocation: |
| 2496 | case kConstConstructorInvocation: |
| 2497 | case kConstListLiteral: |
| 2498 | case kConstSetLiteral: |
| 2499 | case kConstMapLiteral: |
| 2500 | case kSymbolLiteral: |
| 2501 | // Const invocations and const literals are removed by the |
| 2502 | // constant evaluator. |
| 2503 | case kListConcatenation: |
| 2504 | case kSetConcatenation: |
| 2505 | case kMapConcatenation: |
| 2506 | case kInstanceCreation: |
| 2507 | case kFileUriExpression: |
| 2508 | // Collection concatenation, instance creation operations and |
| 2509 | // in-expression URI changes are internal to the front end and |
| 2510 | // removed by the constant evaluator. |
| 2511 | default: |
| 2512 | ReportUnexpectedTag("expression" , tag); |
| 2513 | UNREACHABLE(); |
| 2514 | } |
| 2515 | } |
| 2516 | |
| 2517 | void KernelReaderHelper::SkipStatement() { |
| 2518 | Tag tag = ReadTag(); // read tag. |
| 2519 | switch (tag) { |
| 2520 | case kExpressionStatement: |
| 2521 | SkipExpression(); // read expression. |
| 2522 | return; |
| 2523 | case kBlock: |
| 2524 | SkipStatementList(); |
| 2525 | return; |
| 2526 | case kEmptyStatement: |
| 2527 | return; |
| 2528 | case kAssertBlock: |
| 2529 | SkipStatementList(); |
| 2530 | return; |
| 2531 | case kAssertStatement: |
| 2532 | SkipExpression(); // Read condition. |
| 2533 | ReadPosition(); // read condition start offset. |
| 2534 | ReadPosition(); // read condition end offset. |
| 2535 | if (ReadTag() == kSomething) { |
| 2536 | SkipExpression(); // read (rest of) message. |
| 2537 | } |
| 2538 | return; |
| 2539 | case kLabeledStatement: |
| 2540 | SkipStatement(); // read body. |
| 2541 | return; |
| 2542 | case kBreakStatement: |
| 2543 | ReadPosition(); // read position. |
| 2544 | ReadUInt(); // read target_index. |
| 2545 | return; |
| 2546 | case kWhileStatement: |
| 2547 | ReadPosition(); // read position. |
| 2548 | SkipExpression(); // read condition. |
| 2549 | SkipStatement(); // read body. |
| 2550 | return; |
| 2551 | case kDoStatement: |
| 2552 | ReadPosition(); // read position. |
| 2553 | SkipStatement(); // read body. |
| 2554 | SkipExpression(); // read condition. |
| 2555 | return; |
| 2556 | case kForStatement: { |
| 2557 | ReadPosition(); // read position. |
| 2558 | SkipListOfVariableDeclarations(); // read variables. |
| 2559 | Tag tag = ReadTag(); // Read first part of condition. |
| 2560 | if (tag == kSomething) { |
| 2561 | SkipExpression(); // read rest of condition. |
| 2562 | } |
| 2563 | SkipListOfExpressions(); // read updates. |
| 2564 | SkipStatement(); // read body. |
| 2565 | return; |
| 2566 | } |
| 2567 | case kForInStatement: |
| 2568 | case kAsyncForInStatement: |
| 2569 | ReadPosition(); // read position. |
| 2570 | ReadPosition(); // read body position. |
| 2571 | SkipVariableDeclaration(); // read variable. |
| 2572 | SkipExpression(); // read iterable. |
| 2573 | SkipStatement(); // read body. |
| 2574 | return; |
| 2575 | case kSwitchStatement: { |
| 2576 | ReadPosition(); // read position. |
| 2577 | SkipExpression(); // read condition. |
| 2578 | int case_count = ReadListLength(); // read number of cases. |
| 2579 | for (intptr_t i = 0; i < case_count; ++i) { |
| 2580 | int expression_count = ReadListLength(); // read number of expressions. |
| 2581 | for (intptr_t j = 0; j < expression_count; ++j) { |
| 2582 | ReadPosition(); // read jth position. |
| 2583 | SkipExpression(); // read jth expression. |
| 2584 | } |
| 2585 | ReadBool(); // read is_default. |
| 2586 | SkipStatement(); // read body. |
| 2587 | } |
| 2588 | return; |
| 2589 | } |
| 2590 | case kContinueSwitchStatement: |
| 2591 | ReadPosition(); // read position. |
| 2592 | ReadUInt(); // read target_index. |
| 2593 | return; |
| 2594 | case kIfStatement: |
| 2595 | ReadPosition(); // read position. |
| 2596 | SkipExpression(); // read condition. |
| 2597 | SkipStatement(); // read then. |
| 2598 | SkipStatement(); // read otherwise. |
| 2599 | return; |
| 2600 | case kReturnStatement: { |
| 2601 | ReadPosition(); // read position |
| 2602 | Tag tag = ReadTag(); // read (first part of) expression. |
| 2603 | if (tag == kSomething) { |
| 2604 | SkipExpression(); // read (rest of) expression. |
| 2605 | } |
| 2606 | return; |
| 2607 | } |
| 2608 | case kTryCatch: { |
| 2609 | SkipStatement(); // read body. |
| 2610 | ReadByte(); // read flags |
| 2611 | intptr_t catch_count = ReadListLength(); // read number of catches. |
| 2612 | for (intptr_t i = 0; i < catch_count; ++i) { |
| 2613 | ReadPosition(); // read position. |
| 2614 | SkipDartType(); // read guard. |
| 2615 | tag = ReadTag(); // read first part of exception. |
| 2616 | if (tag == kSomething) { |
| 2617 | SkipVariableDeclaration(); // read exception. |
| 2618 | } |
| 2619 | tag = ReadTag(); // read first part of stack trace. |
| 2620 | if (tag == kSomething) { |
| 2621 | SkipVariableDeclaration(); // read stack trace. |
| 2622 | } |
| 2623 | SkipStatement(); // read body. |
| 2624 | } |
| 2625 | return; |
| 2626 | } |
| 2627 | case kTryFinally: |
| 2628 | SkipStatement(); // read body. |
| 2629 | SkipStatement(); // read finalizer. |
| 2630 | return; |
| 2631 | case kYieldStatement: { |
| 2632 | ReadPosition(); // read position. |
| 2633 | ReadByte(); // read flags. |
| 2634 | SkipExpression(); // read expression. |
| 2635 | return; |
| 2636 | } |
| 2637 | case kVariableDeclaration: |
| 2638 | SkipVariableDeclaration(); // read variable declaration. |
| 2639 | return; |
| 2640 | case kFunctionDeclaration: |
| 2641 | ReadPosition(); // read position. |
| 2642 | SkipVariableDeclaration(); // read variable. |
| 2643 | SkipFunctionNode(); // read function node. |
| 2644 | return; |
| 2645 | default: |
| 2646 | ReportUnexpectedTag("statement" , tag); |
| 2647 | UNREACHABLE(); |
| 2648 | } |
| 2649 | } |
| 2650 | |
| 2651 | void KernelReaderHelper::SkipFunctionNode() { |
| 2652 | FunctionNodeHelper function_node_helper(this); |
| 2653 | function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd); |
| 2654 | } |
| 2655 | |
| 2656 | void KernelReaderHelper::SkipName() { |
| 2657 | StringIndex name_index = ReadStringReference(); // read name index. |
| 2658 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
| 2659 | SkipCanonicalNameReference(); // read library index. |
| 2660 | } |
| 2661 | } |
| 2662 | |
| 2663 | void KernelReaderHelper::SkipArguments() { |
| 2664 | ReadUInt(); // read argument count. |
| 2665 | |
| 2666 | SkipListOfDartTypes(); // read list of types. |
| 2667 | SkipListOfExpressions(); // read positionals. |
| 2668 | |
| 2669 | // List of named. |
| 2670 | intptr_t list_length = ReadListLength(); // read list length. |
| 2671 | for (intptr_t i = 0; i < list_length; ++i) { |
| 2672 | SkipStringReference(); // read ith name index. |
| 2673 | SkipExpression(); // read ith expression. |
| 2674 | } |
| 2675 | } |
| 2676 | |
| 2677 | void KernelReaderHelper::SkipVariableDeclaration() { |
| 2678 | VariableDeclarationHelper helper(this); |
| 2679 | helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd); |
| 2680 | } |
| 2681 | |
| 2682 | void KernelReaderHelper::SkipLibraryCombinator() { |
| 2683 | ReadBool(); // read is_show. |
| 2684 | intptr_t name_count = ReadUInt(); // read list length. |
| 2685 | for (intptr_t j = 0; j < name_count; ++j) { |
| 2686 | ReadUInt(); // read ith entry of name_indices. |
| 2687 | } |
| 2688 | } |
| 2689 | |
| 2690 | void KernelReaderHelper::SkipLibraryDependency() { |
| 2691 | ReadPosition(); // read file offset. |
| 2692 | ReadFlags(); |
| 2693 | SkipListOfExpressions(); // Annotations. |
| 2694 | ReadCanonicalNameReference(); |
| 2695 | ReadStringReference(); // Name. |
| 2696 | intptr_t combinator_count = ReadListLength(); |
| 2697 | for (intptr_t i = 0; i < combinator_count; ++i) { |
| 2698 | SkipLibraryCombinator(); |
| 2699 | } |
| 2700 | } |
| 2701 | |
| 2702 | void KernelReaderHelper::SkipLibraryPart() { |
| 2703 | SkipListOfExpressions(); // Read annotations. |
| 2704 | SkipStringReference(); // Read part URI index. |
| 2705 | } |
| 2706 | |
| 2707 | void KernelReaderHelper::SkipLibraryTypedef() { |
| 2708 | SkipCanonicalNameReference(); // read canonical name. |
| 2709 | ReadUInt(); // read source_uri_index. |
| 2710 | ReadPosition(); // read position. |
| 2711 | SkipStringReference(); // read name index. |
| 2712 | SkipListOfExpressions(); // read annotations. |
| 2713 | SkipTypeParametersList(); // read type parameters. |
| 2714 | SkipDartType(); // read type. |
| 2715 | SkipTypeParametersList(); // read type parameters of function type. |
| 2716 | SkipListOfVariableDeclarations(); // read positional parameters. |
| 2717 | SkipListOfVariableDeclarations(); // read named parameters. |
| 2718 | } |
| 2719 | |
| 2720 | TokenPosition KernelReaderHelper::ReadPosition() { |
| 2721 | TokenPosition position = reader_.ReadPosition(); |
| 2722 | RecordTokenPosition(position); |
| 2723 | return position; |
| 2724 | } |
| 2725 | |
| 2726 | intptr_t KernelReaderHelper::SourceTableFieldCountFromFirstLibraryOffset() { |
| 2727 | return SourceTableFieldCountFromFirstLibraryOffset41Plus; |
| 2728 | } |
| 2729 | |
| 2730 | intptr_t KernelReaderHelper::SourceTableSize() { |
| 2731 | AlternativeReadingScope alt(&reader_); |
| 2732 | intptr_t library_count = reader_.ReadFromIndexNoReset( |
| 2733 | reader_.size(), LibraryCountFieldCountFromEnd, 1, 0); |
| 2734 | |
| 2735 | const intptr_t count_from_first_library_offset = |
| 2736 | SourceTableFieldCountFromFirstLibraryOffset(); |
| 2737 | |
| 2738 | intptr_t source_table_offset = reader_.ReadFromIndexNoReset( |
| 2739 | reader_.size(), |
| 2740 | LibraryCountFieldCountFromEnd + 1 + library_count + 1 + |
| 2741 | count_from_first_library_offset, |
| 2742 | 1, 0); |
| 2743 | SetOffset(source_table_offset); // read source table offset. |
| 2744 | return reader_.ReadUInt32(); // read source table size. |
| 2745 | } |
| 2746 | |
| 2747 | intptr_t KernelReaderHelper::GetOffsetForSourceInfo(intptr_t index) { |
| 2748 | AlternativeReadingScope alt(&reader_); |
| 2749 | intptr_t library_count = reader_.ReadFromIndexNoReset( |
| 2750 | reader_.size(), LibraryCountFieldCountFromEnd, 1, 0); |
| 2751 | |
| 2752 | const intptr_t count_from_first_library_offset = |
| 2753 | SourceTableFieldCountFromFirstLibraryOffset(); |
| 2754 | |
| 2755 | intptr_t source_table_offset = reader_.ReadFromIndexNoReset( |
| 2756 | reader_.size(), |
| 2757 | LibraryCountFieldCountFromEnd + 1 + library_count + 1 + |
| 2758 | count_from_first_library_offset, |
| 2759 | 1, 0); |
| 2760 | intptr_t next_field_offset = reader_.ReadUInt32(); |
| 2761 | SetOffset(source_table_offset); |
| 2762 | intptr_t size = reader_.ReadUInt32(); // read source table size. |
| 2763 | |
| 2764 | return reader_.ReadFromIndexNoReset(next_field_offset, 0, size, index); |
| 2765 | } |
| 2766 | |
| 2767 | String& KernelReaderHelper::SourceTableUriFor(intptr_t index) { |
| 2768 | AlternativeReadingScope alt(&reader_); |
| 2769 | SetOffset(GetOffsetForSourceInfo(index)); |
| 2770 | intptr_t size = ReadUInt(); // read uri List<byte> size. |
| 2771 | return H.DartString(reader_.BufferAt(ReaderOffset()), size, Heap::kOld); |
| 2772 | } |
| 2773 | |
| 2774 | const String& KernelReaderHelper::GetSourceFor(intptr_t index) { |
| 2775 | AlternativeReadingScope alt(&reader_); |
| 2776 | SetOffset(GetOffsetForSourceInfo(index)); |
| 2777 | SkipBytes(ReadUInt()); // skip uri. |
| 2778 | intptr_t size = ReadUInt(); // read source List<byte> size. |
| 2779 | ASSERT(size >= 0); |
| 2780 | if (size == 0) { |
| 2781 | return Symbols::Empty(); |
| 2782 | } else { |
| 2783 | return H.DartString(reader_.BufferAt(ReaderOffset()), size, Heap::kOld); |
| 2784 | } |
| 2785 | } |
| 2786 | |
| 2787 | TypedDataPtr KernelReaderHelper::GetLineStartsFor(intptr_t index) { |
| 2788 | // Line starts are delta encoded. So get the max delta first so that we |
| 2789 | // can store them as tighly as possible. |
| 2790 | AlternativeReadingScope alt(&reader_); |
| 2791 | SetOffset(GetOffsetForSourceInfo(index)); |
| 2792 | SkipBytes(ReadUInt()); // skip uri. |
| 2793 | SkipBytes(ReadUInt()); // skip source. |
| 2794 | const intptr_t line_start_count = ReadUInt(); |
| 2795 | return reader_.ReadLineStartsData(line_start_count); |
| 2796 | } |
| 2797 | |
| 2798 | String& KernelReaderHelper::SourceTableImportUriFor(intptr_t index, |
| 2799 | uint32_t binaryVersion) { |
| 2800 | if (binaryVersion < 22) { |
| 2801 | return SourceTableUriFor(index); |
| 2802 | } |
| 2803 | |
| 2804 | AlternativeReadingScope alt(&reader_); |
| 2805 | SetOffset(GetOffsetForSourceInfo(index)); |
| 2806 | SkipBytes(ReadUInt()); // skip uri. |
| 2807 | SkipBytes(ReadUInt()); // skip source. |
| 2808 | const intptr_t line_start_count = ReadUInt(); // read number of line start |
| 2809 | // entries. |
| 2810 | for (intptr_t i = 0; i < line_start_count; ++i) { |
| 2811 | ReadUInt(); |
| 2812 | } |
| 2813 | |
| 2814 | intptr_t size = ReadUInt(); // read import uri List<byte> size. |
| 2815 | return H.DartString(reader_.BufferAt(ReaderOffset()), size, Heap::kOld); |
| 2816 | } |
| 2817 | |
| 2818 | intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) { |
| 2819 | ASSERT(member != NULL); |
| 2820 | if (member->IsFactory()) { |
| 2821 | TypeArguments& class_types = |
| 2822 | TypeArguments::Handle(zone, klass->type_parameters()); |
| 2823 | return class_types.Length(); |
| 2824 | } else if (member->IsMethodExtractor()) { |
| 2825 | Function& = |
| 2826 | Function::Handle(zone, member->extracted_method_closure()); |
| 2827 | TypeArguments& function_types = |
| 2828 | TypeArguments::Handle(zone, extracted.type_parameters()); |
| 2829 | return function_types.Length(); |
| 2830 | } else { |
| 2831 | TypeArguments& function_types = |
| 2832 | TypeArguments::Handle(zone, member->type_parameters()); |
| 2833 | return function_types.Length(); |
| 2834 | } |
| 2835 | } |
| 2836 | |
| 2837 | ActiveTypeParametersScope::(ActiveClass* active_class, |
| 2838 | const Function& innermost, |
| 2839 | Zone* Z) |
| 2840 | : active_class_(active_class), saved_(*active_class) { |
| 2841 | active_class_->enclosing = &innermost; |
| 2842 | |
| 2843 | intptr_t num_params = 0; |
| 2844 | |
| 2845 | Function& f = Function::Handle(Z); |
| 2846 | TypeArguments& f_params = TypeArguments::Handle(Z); |
| 2847 | for (f = innermost.raw(); f.parent_function() != Object::null(); |
| 2848 | f = f.parent_function()) { |
| 2849 | f_params = f.type_parameters(); |
| 2850 | num_params += f_params.Length(); |
| 2851 | } |
| 2852 | if (num_params == 0) return; |
| 2853 | |
| 2854 | TypeArguments& params = |
| 2855 | TypeArguments::Handle(Z, TypeArguments::New(num_params)); |
| 2856 | |
| 2857 | intptr_t index = num_params; |
| 2858 | for (f = innermost.raw(); f.parent_function() != Object::null(); |
| 2859 | f = f.parent_function()) { |
| 2860 | f_params = f.type_parameters(); |
| 2861 | for (intptr_t j = f_params.Length() - 1; j >= 0; --j) { |
| 2862 | params.SetTypeAt(--index, AbstractType::Handle(Z, f_params.TypeAt(j))); |
| 2863 | } |
| 2864 | } |
| 2865 | |
| 2866 | active_class_->local_type_parameters = ¶ms; |
| 2867 | } |
| 2868 | |
| 2869 | ActiveTypeParametersScope::( |
| 2870 | ActiveClass* active_class, |
| 2871 | const Function* function, |
| 2872 | const TypeArguments& new_params, |
| 2873 | Zone* Z) |
| 2874 | : active_class_(active_class), saved_(*active_class) { |
| 2875 | active_class_->enclosing = function; |
| 2876 | |
| 2877 | if (new_params.IsNull()) return; |
| 2878 | |
| 2879 | const TypeArguments* old_params = active_class->local_type_parameters; |
| 2880 | const intptr_t old_param_count = |
| 2881 | old_params == NULL ? 0 : old_params->Length(); |
| 2882 | const TypeArguments& extended_params = TypeArguments::Handle( |
| 2883 | Z, TypeArguments::New(old_param_count + new_params.Length())); |
| 2884 | |
| 2885 | intptr_t index = 0; |
| 2886 | for (intptr_t i = 0; i < old_param_count; ++i) { |
| 2887 | extended_params.SetTypeAt( |
| 2888 | index++, AbstractType::ZoneHandle(Z, old_params->TypeAt(i))); |
| 2889 | } |
| 2890 | for (intptr_t i = 0; i < new_params.Length(); ++i) { |
| 2891 | extended_params.SetTypeAt( |
| 2892 | index++, AbstractType::ZoneHandle(Z, new_params.TypeAt(i))); |
| 2893 | } |
| 2894 | |
| 2895 | active_class_->local_type_parameters = &extended_params; |
| 2896 | } |
| 2897 | |
| 2898 | TypeTranslator::TypeTranslator(KernelReaderHelper* helper, |
| 2899 | ConstantReader* constant_reader, |
| 2900 | ActiveClass* active_class, |
| 2901 | bool finalize, |
| 2902 | bool apply_legacy_erasure) |
| 2903 | : helper_(helper), |
| 2904 | constant_reader_(constant_reader), |
| 2905 | translation_helper_(helper->translation_helper_), |
| 2906 | active_class_(active_class), |
| 2907 | type_parameter_scope_(NULL), |
| 2908 | inferred_type_metadata_helper_(helper_, constant_reader_), |
| 2909 | unboxing_info_metadata_helper_(helper_), |
| 2910 | zone_(translation_helper_.zone()), |
| 2911 | result_(AbstractType::Handle(translation_helper_.zone())), |
| 2912 | finalize_(finalize), |
| 2913 | apply_legacy_erasure_(apply_legacy_erasure) {} |
| 2914 | |
| 2915 | AbstractType& TypeTranslator::BuildType() { |
| 2916 | BuildTypeInternal(); |
| 2917 | |
| 2918 | // We return a new `ZoneHandle` here on purpose: The intermediate language |
| 2919 | // instructions do not make a copy of the handle, so we do it. |
| 2920 | return AbstractType::ZoneHandle(Z, result_.raw()); |
| 2921 | } |
| 2922 | |
| 2923 | AbstractType& TypeTranslator::BuildTypeWithoutFinalization() { |
| 2924 | bool saved_finalize = finalize_; |
| 2925 | finalize_ = false; |
| 2926 | BuildTypeInternal(); |
| 2927 | finalize_ = saved_finalize; |
| 2928 | |
| 2929 | // We return a new `ZoneHandle` here on purpose: The intermediate language |
| 2930 | // instructions do not make a copy of the handle, so we do it. |
| 2931 | return AbstractType::ZoneHandle(Z, result_.raw()); |
| 2932 | } |
| 2933 | |
| 2934 | void TypeTranslator::BuildTypeInternal() { |
| 2935 | Tag tag = helper_->ReadTag(); |
| 2936 | switch (tag) { |
| 2937 | case kInvalidType: |
| 2938 | case kDynamicType: |
| 2939 | result_ = Object::dynamic_type().raw(); |
| 2940 | break; |
| 2941 | case kVoidType: |
| 2942 | result_ = Object::void_type().raw(); |
| 2943 | break; |
| 2944 | case kNeverType: { |
| 2945 | const Nullability nullability = helper_->ReadNullability(); |
| 2946 | if (apply_legacy_erasure_) { |
| 2947 | result_ = I->object_store()->null_type(); |
| 2948 | } else { |
| 2949 | result_ = Type::Handle(Z, I->object_store()->never_type()) |
| 2950 | .ToNullability(nullability, Heap::kOld); |
| 2951 | } |
| 2952 | break; |
| 2953 | } |
| 2954 | case kBottomType: |
| 2955 | // Map Bottom type to Null type until not emitted by CFE anymore. |
| 2956 | result_ = I->object_store()->null_type(); |
| 2957 | ASSERT(result_.IsNullable()); |
| 2958 | break; |
| 2959 | case kInterfaceType: |
| 2960 | BuildInterfaceType(false); |
| 2961 | break; |
| 2962 | case kSimpleInterfaceType: |
| 2963 | BuildInterfaceType(true); |
| 2964 | break; |
| 2965 | case kFunctionType: |
| 2966 | BuildFunctionType(false); |
| 2967 | break; |
| 2968 | case kSimpleFunctionType: |
| 2969 | BuildFunctionType(true); |
| 2970 | break; |
| 2971 | case kTypeParameterType: |
| 2972 | BuildTypeParameterType(); |
| 2973 | break; |
| 2974 | default: |
| 2975 | helper_->ReportUnexpectedTag("type" , tag); |
| 2976 | UNREACHABLE(); |
| 2977 | } |
| 2978 | } |
| 2979 | |
| 2980 | void TypeTranslator::BuildInterfaceType(bool simple) { |
| 2981 | // NOTE: That an interface type like `T<A, B>` is considered to be |
| 2982 | // malformed iff `T` is malformed. |
| 2983 | // => We therefore ignore errors in `A` or `B`. |
| 2984 | |
| 2985 | Nullability nullability = helper_->ReadNullability(); |
| 2986 | if (apply_legacy_erasure_) { |
| 2987 | nullability = Nullability::kLegacy; |
| 2988 | } |
| 2989 | |
| 2990 | NameIndex klass_name = |
| 2991 | helper_->ReadCanonicalNameReference(); // read klass_name. |
| 2992 | |
| 2993 | const Class& klass = Class::Handle(Z, H.LookupClassByKernelClass(klass_name)); |
| 2994 | ASSERT(!klass.IsNull()); |
| 2995 | if (klass.is_declared_in_bytecode()) { |
| 2996 | klass.EnsureDeclarationLoaded(); |
| 2997 | } |
| 2998 | if (simple) { |
| 2999 | if (finalize_ || klass.is_type_finalized()) { |
| 3000 | // Fast path for non-generic types: retrieve or populate the class's only |
| 3001 | // canonical type (as long as only one nullability variant is used), which |
| 3002 | // is its declaration type. |
| 3003 | result_ = klass.DeclarationType(); |
| 3004 | result_ = Type::Cast(result_).ToNullability(nullability, Heap::kOld); |
| 3005 | } else { |
| 3006 | // Note that the type argument vector is not yet extended. |
| 3007 | result_ = Type::New(klass, Object::null_type_arguments(), |
| 3008 | klass.token_pos(), nullability); |
| 3009 | } |
| 3010 | return; |
| 3011 | } |
| 3012 | |
| 3013 | intptr_t length = |
| 3014 | helper_->ReadListLength(); // read type_arguments list length. |
| 3015 | const TypeArguments& type_arguments = |
| 3016 | BuildTypeArguments(length); // read type arguments. |
| 3017 | result_ = |
| 3018 | Type::New(klass, type_arguments, TokenPosition::kNoSource, nullability); |
| 3019 | result_ = result_.NormalizeFutureOrType(Heap::kOld); |
| 3020 | if (finalize_) { |
| 3021 | ASSERT(active_class_->klass != NULL); |
| 3022 | result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_); |
| 3023 | } |
| 3024 | } |
| 3025 | |
| 3026 | void TypeTranslator::BuildFunctionType(bool simple) { |
| 3027 | Function& signature_function = Function::ZoneHandle( |
| 3028 | Z, Function::NewSignatureFunction(*active_class_->klass, |
| 3029 | active_class_->enclosing != NULL |
| 3030 | ? *active_class_->enclosing |
| 3031 | : Function::Handle(Z), |
| 3032 | TokenPosition::kNoSource)); |
| 3033 | |
| 3034 | Nullability nullability = helper_->ReadNullability(); |
| 3035 | if (apply_legacy_erasure_) { |
| 3036 | nullability = Nullability::kLegacy; |
| 3037 | } |
| 3038 | |
| 3039 | // Suspend finalization of types inside this one. They will be finalized after |
| 3040 | // the whole function type is constructed. |
| 3041 | // |
| 3042 | // TODO(31213): Test further when nested generic function types |
| 3043 | // are supported by fasta. |
| 3044 | bool finalize = finalize_; |
| 3045 | finalize_ = false; |
| 3046 | |
| 3047 | if (!simple) { |
| 3048 | LoadAndSetupTypeParameters(active_class_, signature_function, |
| 3049 | helper_->ReadListLength(), signature_function); |
| 3050 | } |
| 3051 | |
| 3052 | ActiveTypeParametersScope scope( |
| 3053 | active_class_, &signature_function, |
| 3054 | TypeArguments::Handle(Z, signature_function.type_parameters()), Z); |
| 3055 | |
| 3056 | intptr_t required_count; |
| 3057 | intptr_t all_count; |
| 3058 | intptr_t positional_count; |
| 3059 | if (!simple) { |
| 3060 | required_count = helper_->ReadUInt(); // read required parameter count. |
| 3061 | all_count = helper_->ReadUInt(); // read total parameter count. |
| 3062 | positional_count = |
| 3063 | helper_->ReadListLength(); // read positional_parameters list length. |
| 3064 | } else { |
| 3065 | positional_count = |
| 3066 | helper_->ReadListLength(); // read positional_parameters list length. |
| 3067 | required_count = positional_count; |
| 3068 | all_count = positional_count; |
| 3069 | } |
| 3070 | |
| 3071 | const intptr_t all_count_with_receiver = all_count + 1; |
| 3072 | const Array& parameter_types = |
| 3073 | Array::Handle(Z, Array::New(all_count_with_receiver, Heap::kOld)); |
| 3074 | signature_function.set_parameter_types(parameter_types); |
| 3075 | const Array& parameter_names = Array::Handle( |
| 3076 | Z, Array::New(simple ? all_count_with_receiver |
| 3077 | : Function::NameArrayLengthIncludingFlags( |
| 3078 | all_count_with_receiver), |
| 3079 | Heap::kOld)); |
| 3080 | signature_function.set_parameter_names(parameter_names); |
| 3081 | |
| 3082 | intptr_t pos = 0; |
| 3083 | parameter_types.SetAt(pos, AbstractType::dynamic_type()); |
| 3084 | parameter_names.SetAt(pos, H.DartSymbolPlain("_receiver_" )); |
| 3085 | ++pos; |
| 3086 | for (intptr_t i = 0; i < positional_count; ++i, ++pos) { |
| 3087 | BuildTypeInternal(); // read ith positional parameter. |
| 3088 | parameter_types.SetAt(pos, result_); |
| 3089 | parameter_names.SetAt(pos, H.DartSymbolPlain("noname" )); |
| 3090 | } |
| 3091 | |
| 3092 | // The additional first parameter is the receiver type (set to dynamic). |
| 3093 | signature_function.set_num_fixed_parameters(1 + required_count); |
| 3094 | signature_function.SetNumOptionalParameters( |
| 3095 | all_count - required_count, positional_count > required_count); |
| 3096 | |
| 3097 | if (!simple) { |
| 3098 | const intptr_t named_count = |
| 3099 | helper_->ReadListLength(); // read named_parameters list length. |
| 3100 | for (intptr_t i = 0; i < named_count; ++i, ++pos) { |
| 3101 | // read string reference (i.e. named_parameters[i].name). |
| 3102 | String& name = H.DartSymbolObfuscate(helper_->ReadStringReference()); |
| 3103 | BuildTypeInternal(); // read named_parameters[i].type. |
| 3104 | const uint8_t flags = helper_->ReadFlags(); // read flags |
| 3105 | parameter_types.SetAt(pos, result_); |
| 3106 | parameter_names.SetAt(pos, name); |
| 3107 | if (!apply_legacy_erasure_ && |
| 3108 | (flags & static_cast<uint8_t>(NamedTypeFlags::kIsRequired)) != 0) { |
| 3109 | signature_function.SetIsRequiredAt(pos); |
| 3110 | } |
| 3111 | } |
| 3112 | signature_function.TruncateUnusedParameterFlags(); |
| 3113 | } |
| 3114 | |
| 3115 | if (!simple) { |
| 3116 | helper_->SkipOptionalDartType(); // read typedef type. |
| 3117 | } |
| 3118 | |
| 3119 | BuildTypeInternal(); // read return type. |
| 3120 | signature_function.set_result_type(result_); |
| 3121 | |
| 3122 | finalize_ = finalize; |
| 3123 | |
| 3124 | Type& signature_type = |
| 3125 | Type::ZoneHandle(Z, signature_function.SignatureType(nullability)); |
| 3126 | |
| 3127 | if (finalize_) { |
| 3128 | signature_type ^= |
| 3129 | ClassFinalizer::FinalizeType(*active_class_->klass, signature_type); |
| 3130 | // Do not refer to signature_function anymore, since it may have been |
| 3131 | // replaced during canonicalization. |
| 3132 | signature_function = Function::null(); |
| 3133 | } |
| 3134 | |
| 3135 | result_ = signature_type.raw(); |
| 3136 | } |
| 3137 | |
| 3138 | void TypeTranslator::BuildTypeParameterType() { |
| 3139 | Nullability nullability = helper_->ReadNullability(); |
| 3140 | if (apply_legacy_erasure_) { |
| 3141 | nullability = Nullability::kLegacy; |
| 3142 | } |
| 3143 | |
| 3144 | intptr_t parameter_index = helper_->ReadUInt(); // read parameter index. |
| 3145 | helper_->SkipOptionalDartType(); // read bound. |
| 3146 | |
| 3147 | const TypeArguments& class_types = |
| 3148 | TypeArguments::Handle(Z, active_class_->klass->type_parameters()); |
| 3149 | if (parameter_index < class_types.Length()) { |
| 3150 | // The index of the type parameter in [parameters] is |
| 3151 | // the same index into the `klass->type_parameters()` array. |
| 3152 | const auto& type_param = |
| 3153 | TypeParameter::CheckedHandle(Z, class_types.TypeAt(parameter_index)); |
| 3154 | result_ = type_param.ToNullability(nullability, Heap::kOld); |
| 3155 | active_class_->RecordDerivedTypeParameter(Z, type_param, |
| 3156 | TypeParameter::Cast(result_)); |
| 3157 | return; |
| 3158 | } |
| 3159 | parameter_index -= class_types.Length(); |
| 3160 | |
| 3161 | if (active_class_->HasMember()) { |
| 3162 | if (active_class_->MemberIsFactoryProcedure()) { |
| 3163 | // |
| 3164 | // WARNING: This is a little hackish: |
| 3165 | // |
| 3166 | // We have a static factory constructor. The kernel IR gives the factory |
| 3167 | // constructor function its own type parameters (which are equal in name |
| 3168 | // and number to the ones of the enclosing class). I.e., |
| 3169 | // |
| 3170 | // class A<T> { |
| 3171 | // factory A.x() { return new B<T>(); } |
| 3172 | // } |
| 3173 | // |
| 3174 | // is basically translated to this: |
| 3175 | // |
| 3176 | // class A<T> { |
| 3177 | // static A.x<T'>() { return new B<T'>(); } |
| 3178 | // } |
| 3179 | // |
| 3180 | if (class_types.Length() > parameter_index) { |
| 3181 | const auto& type_param = TypeParameter::CheckedHandle( |
| 3182 | Z, class_types.TypeAt(parameter_index)); |
| 3183 | result_ = type_param.ToNullability(nullability, Heap::kOld); |
| 3184 | active_class_->RecordDerivedTypeParameter(Z, type_param, |
| 3185 | TypeParameter::Cast(result_)); |
| 3186 | return; |
| 3187 | } |
| 3188 | parameter_index -= class_types.Length(); |
| 3189 | } |
| 3190 | // Factory function should not be considered as procedure. |
| 3191 | intptr_t procedure_type_parameter_count = |
| 3192 | (active_class_->MemberIsProcedure() && |
| 3193 | !active_class_->MemberIsFactoryProcedure()) |
| 3194 | ? active_class_->MemberTypeParameterCount(Z) |
| 3195 | : 0; |
| 3196 | if (procedure_type_parameter_count > 0) { |
| 3197 | if (procedure_type_parameter_count > parameter_index) { |
| 3198 | const auto& type_param = TypeParameter::CheckedHandle( |
| 3199 | Z, |
| 3200 | TypeArguments::Handle(Z, active_class_->member->type_parameters()) |
| 3201 | .TypeAt(parameter_index)); |
| 3202 | result_ = type_param.ToNullability(nullability, Heap::kOld); |
| 3203 | active_class_->RecordDerivedTypeParameter(Z, type_param, |
| 3204 | TypeParameter::Cast(result_)); |
| 3205 | if (finalize_) { |
| 3206 | result_ = |
| 3207 | ClassFinalizer::FinalizeType(*active_class_->klass, result_); |
| 3208 | } |
| 3209 | return; |
| 3210 | } |
| 3211 | parameter_index -= procedure_type_parameter_count; |
| 3212 | } |
| 3213 | } |
| 3214 | |
| 3215 | if (active_class_->local_type_parameters != NULL) { |
| 3216 | if (parameter_index < active_class_->local_type_parameters->Length()) { |
| 3217 | const auto& type_param = TypeParameter::CheckedHandle( |
| 3218 | Z, active_class_->local_type_parameters->TypeAt(parameter_index)); |
| 3219 | result_ = type_param.ToNullability(nullability, Heap::kOld); |
| 3220 | active_class_->RecordDerivedTypeParameter(Z, type_param, |
| 3221 | TypeParameter::Cast(result_)); |
| 3222 | if (finalize_) { |
| 3223 | result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_); |
| 3224 | } |
| 3225 | return; |
| 3226 | } |
| 3227 | parameter_index -= active_class_->local_type_parameters->Length(); |
| 3228 | } |
| 3229 | |
| 3230 | if (type_parameter_scope_ != NULL && |
| 3231 | parameter_index < type_parameter_scope_->outer_parameter_count() + |
| 3232 | type_parameter_scope_->parameter_count()) { |
| 3233 | result_ = Type::DynamicType(); |
| 3234 | return; |
| 3235 | } |
| 3236 | |
| 3237 | H.ReportError( |
| 3238 | helper_->script(), TokenPosition::kNoSource, |
| 3239 | "Unbound type parameter found in %s. Please report this at dartbug.com." , |
| 3240 | active_class_->ToCString()); |
| 3241 | } |
| 3242 | |
| 3243 | const TypeArguments& TypeTranslator::BuildTypeArguments(intptr_t length) { |
| 3244 | bool only_dynamic = true; |
| 3245 | intptr_t offset = helper_->ReaderOffset(); |
| 3246 | for (intptr_t i = 0; i < length; ++i) { |
| 3247 | if (helper_->ReadTag() != kDynamicType) { // Read the ith types tag. |
| 3248 | only_dynamic = false; |
| 3249 | helper_->SetOffset(offset); |
| 3250 | break; |
| 3251 | } |
| 3252 | } |
| 3253 | TypeArguments& type_arguments = TypeArguments::ZoneHandle(Z); |
| 3254 | if (!only_dynamic) { |
| 3255 | type_arguments = TypeArguments::New(length); |
| 3256 | for (intptr_t i = 0; i < length; ++i) { |
| 3257 | BuildTypeInternal(); // read ith type. |
| 3258 | type_arguments.SetTypeAt(i, result_); |
| 3259 | } |
| 3260 | |
| 3261 | if (finalize_) { |
| 3262 | type_arguments = type_arguments.Canonicalize(); |
| 3263 | } |
| 3264 | } |
| 3265 | return type_arguments; |
| 3266 | } |
| 3267 | |
| 3268 | const TypeArguments& TypeTranslator::BuildInstantiatedTypeArguments( |
| 3269 | const Class& receiver_class, |
| 3270 | intptr_t length) { |
| 3271 | const TypeArguments& type_arguments = BuildTypeArguments(length); |
| 3272 | |
| 3273 | // If type_arguments is null all arguments are dynamic. |
| 3274 | // If, however, this class doesn't specify all the type arguments directly we |
| 3275 | // still need to finalize the type below in order to get any non-dynamic types |
| 3276 | // from any super. See http://www.dartbug.com/29537. |
| 3277 | if (type_arguments.IsNull() && receiver_class.NumTypeArguments() == length) { |
| 3278 | return type_arguments; |
| 3279 | } |
| 3280 | |
| 3281 | // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to |
| 3282 | // finalize the argument types. |
| 3283 | // (This can for example make the [type_arguments] vector larger) |
| 3284 | Type& type = Type::Handle( |
| 3285 | Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource)); |
| 3286 | if (finalize_) { |
| 3287 | type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type); |
| 3288 | } |
| 3289 | |
| 3290 | const TypeArguments& instantiated_type_arguments = |
| 3291 | TypeArguments::ZoneHandle(Z, type.arguments()); |
| 3292 | return instantiated_type_arguments; |
| 3293 | } |
| 3294 | |
| 3295 | void TypeTranslator::LoadAndSetupTypeParameters( |
| 3296 | ActiveClass* active_class, |
| 3297 | const Object& set_on, |
| 3298 | intptr_t type_parameter_count, |
| 3299 | const Function& parameterized_function) { |
| 3300 | ASSERT(type_parameter_count >= 0); |
| 3301 | if (type_parameter_count == 0) { |
| 3302 | return; |
| 3303 | } |
| 3304 | ASSERT(set_on.IsClass() || set_on.IsFunction()); |
| 3305 | bool set_on_class = set_on.IsClass(); |
| 3306 | ASSERT(set_on_class == parameterized_function.IsNull()); |
| 3307 | |
| 3308 | // First setup the type parameters, so if any of the following code uses it |
| 3309 | // (in a recursive way) we're fine. |
| 3310 | TypeArguments& type_parameters = TypeArguments::Handle(Z); |
| 3311 | TypeParameter& parameter = TypeParameter::Handle(Z); |
| 3312 | const Type& null_bound = Type::Handle(Z); |
| 3313 | |
| 3314 | const NNBDMode nnbd_mode = set_on.IsClass() |
| 3315 | ? Class::Cast(set_on).nnbd_mode() |
| 3316 | : Function::Cast(set_on).nnbd_mode(); |
| 3317 | const Nullability nullability = (nnbd_mode == NNBDMode::kOptedInLib) |
| 3318 | ? Nullability::kNonNullable |
| 3319 | : Nullability::kLegacy; |
| 3320 | |
| 3321 | // Step a) Create array of [TypeParameter] objects (without bound). |
| 3322 | type_parameters = TypeArguments::New(type_parameter_count); |
| 3323 | const Library& lib = Library::Handle(Z, active_class->klass->library()); |
| 3324 | { |
| 3325 | AlternativeReadingScope alt(&helper_->reader_); |
| 3326 | for (intptr_t i = 0; i < type_parameter_count; i++) { |
| 3327 | TypeParameterHelper helper(helper_); |
| 3328 | helper.Finish(); |
| 3329 | parameter = TypeParameter::New( |
| 3330 | set_on_class ? *active_class->klass : Class::Handle(Z), |
| 3331 | parameterized_function, i, |
| 3332 | H.DartIdentifier(lib, helper.name_index_), // read ith name index. |
| 3333 | null_bound, helper.IsGenericCovariantImpl(), nullability, |
| 3334 | TokenPosition::kNoSource); |
| 3335 | parameter.SetCanonical(); |
| 3336 | parameter.SetDeclaration(true); |
| 3337 | type_parameters.SetTypeAt(i, parameter); |
| 3338 | } |
| 3339 | } |
| 3340 | |
| 3341 | if (set_on.IsClass()) { |
| 3342 | Class::Cast(set_on).set_type_parameters(type_parameters); |
| 3343 | } else { |
| 3344 | Function::Cast(set_on).set_type_parameters(type_parameters); |
| 3345 | } |
| 3346 | |
| 3347 | const Function* enclosing = NULL; |
| 3348 | if (!parameterized_function.IsNull()) { |
| 3349 | enclosing = ¶meterized_function; |
| 3350 | } |
| 3351 | ActiveTypeParametersScope scope(active_class, enclosing, type_parameters, Z); |
| 3352 | |
| 3353 | // Step b) Fill in the bounds of all [TypeParameter]s. |
| 3354 | for (intptr_t i = 0; i < type_parameter_count; i++) { |
| 3355 | TypeParameterHelper helper(helper_); |
| 3356 | helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound); |
| 3357 | |
| 3358 | // TODO(github.com/dart-lang/kernel/issues/42): This should be handled |
| 3359 | // by the frontend. |
| 3360 | parameter ^= type_parameters.TypeAt(i); |
| 3361 | const Tag tag = helper_->PeekTag(); // peek ith bound type. |
| 3362 | if (tag == kDynamicType) { |
| 3363 | helper_->SkipDartType(); // read ith bound. |
| 3364 | parameter.set_bound( |
| 3365 | Type::Handle(Z, nnbd_mode == NNBDMode::kOptedInLib |
| 3366 | ? I->object_store()->nullable_object_type() |
| 3367 | : I->object_store()->legacy_object_type())); |
| 3368 | } else { |
| 3369 | AbstractType& bound = BuildTypeWithoutFinalization(); // read ith bound. |
| 3370 | parameter.set_bound(bound); |
| 3371 | } |
| 3372 | |
| 3373 | helper.Finish(); |
| 3374 | } |
| 3375 | |
| 3376 | // Fix bounds in all derived type parameters (with different nullabilities). |
| 3377 | if (active_class->derived_type_parameters != nullptr) { |
| 3378 | auto& derived = TypeParameter::Handle(Z); |
| 3379 | auto& bound = AbstractType::Handle(Z); |
| 3380 | for (intptr_t i = 0, n = active_class->derived_type_parameters->Length(); |
| 3381 | i < n; ++i) { |
| 3382 | derived ^= active_class->derived_type_parameters->At(i); |
| 3383 | if (derived.bound() == AbstractType::null() && |
| 3384 | (derived.parameterized_class() == set_on.raw() || |
| 3385 | derived.parameterized_function() == set_on.raw())) { |
| 3386 | ASSERT(!derived.IsFinalized()); |
| 3387 | parameter ^= type_parameters.TypeAt(derived.index()); |
| 3388 | bound = parameter.bound(); |
| 3389 | derived.set_bound(bound); |
| 3390 | } |
| 3391 | } |
| 3392 | } |
| 3393 | } |
| 3394 | |
| 3395 | const Type& TypeTranslator::ReceiverType(const Class& klass) { |
| 3396 | ASSERT(!klass.IsNull()); |
| 3397 | ASSERT(!klass.IsTypedefClass()); |
| 3398 | // Note that if klass is _Closure, the returned type will be _Closure, |
| 3399 | // and not the signature type. |
| 3400 | Type& type = Type::ZoneHandle(Z); |
| 3401 | if (finalize_ || klass.is_type_finalized()) { |
| 3402 | type = klass.DeclarationType(); |
| 3403 | } else { |
| 3404 | type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()), |
| 3405 | klass.token_pos(), Nullability::kNonNullable); |
| 3406 | } |
| 3407 | return type; |
| 3408 | } |
| 3409 | |
| 3410 | static void SetupUnboxingInfoOfParameter(const Function& function, |
| 3411 | intptr_t param_index, |
| 3412 | const UnboxingInfoMetadata* metadata) { |
| 3413 | const intptr_t param_pos = |
| 3414 | param_index + (function.HasThisParameter() ? 1 : 0); |
| 3415 | |
| 3416 | if (param_pos < function.maximum_unboxed_parameter_count()) { |
| 3417 | switch (metadata->unboxed_args_info[param_index]) { |
| 3418 | case UnboxingInfoMetadata::kUnboxedIntCandidate: |
| 3419 | if (FlowGraphCompiler::SupportsUnboxedInt64()) { |
| 3420 | function.set_unboxed_integer_parameter_at(param_pos); |
| 3421 | } |
| 3422 | break; |
| 3423 | case UnboxingInfoMetadata::kUnboxedDoubleCandidate: |
| 3424 | if (FlowGraphCompiler::SupportsUnboxedDoubles()) { |
| 3425 | function.set_unboxed_double_parameter_at(param_pos); |
| 3426 | } |
| 3427 | break; |
| 3428 | case UnboxingInfoMetadata::kUnboxingCandidate: |
| 3429 | UNREACHABLE(); |
| 3430 | break; |
| 3431 | case UnboxingInfoMetadata::kBoxed: |
| 3432 | break; |
| 3433 | default: |
| 3434 | UNREACHABLE(); |
| 3435 | break; |
| 3436 | } |
| 3437 | } |
| 3438 | } |
| 3439 | |
| 3440 | static void SetupUnboxingInfoOfReturnValue( |
| 3441 | const Function& function, |
| 3442 | const UnboxingInfoMetadata* metadata) { |
| 3443 | switch (metadata->return_info) { |
| 3444 | case UnboxingInfoMetadata::kUnboxedIntCandidate: |
| 3445 | if (FlowGraphCompiler::SupportsUnboxedInt64()) { |
| 3446 | function.set_unboxed_integer_return(); |
| 3447 | } |
| 3448 | break; |
| 3449 | case UnboxingInfoMetadata::kUnboxedDoubleCandidate: |
| 3450 | if (FlowGraphCompiler::SupportsUnboxedDoubles()) { |
| 3451 | function.set_unboxed_double_return(); |
| 3452 | } |
| 3453 | break; |
| 3454 | case UnboxingInfoMetadata::kUnboxingCandidate: |
| 3455 | UNREACHABLE(); |
| 3456 | break; |
| 3457 | case UnboxingInfoMetadata::kBoxed: |
| 3458 | break; |
| 3459 | default: |
| 3460 | UNREACHABLE(); |
| 3461 | break; |
| 3462 | } |
| 3463 | } |
| 3464 | |
| 3465 | void TypeTranslator::SetupUnboxingInfoMetadata(const Function& function, |
| 3466 | intptr_t library_kernel_offset) { |
| 3467 | const intptr_t kernel_offset = |
| 3468 | function.kernel_offset() + library_kernel_offset; |
| 3469 | const auto unboxing_info = |
| 3470 | unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset); |
| 3471 | |
| 3472 | // TODO(dartbug.com/32292): accept unboxed parameters and return value |
| 3473 | // when FLAG_use_table_dispatch == false. |
| 3474 | if (FLAG_precompiled_mode && unboxing_info != nullptr && |
| 3475 | FLAG_use_table_dispatch && FLAG_use_bare_instructions) { |
| 3476 | for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) { |
| 3477 | SetupUnboxingInfoOfParameter(function, i, unboxing_info); |
| 3478 | } |
| 3479 | SetupUnboxingInfoOfReturnValue(function, unboxing_info); |
| 3480 | } |
| 3481 | } |
| 3482 | |
| 3483 | void TypeTranslator::SetupUnboxingInfoMetadataForFieldAccessors( |
| 3484 | const Function& field_accessor, |
| 3485 | intptr_t library_kernel_offset) { |
| 3486 | const intptr_t kernel_offset = |
| 3487 | field_accessor.kernel_offset() + library_kernel_offset; |
| 3488 | const auto unboxing_info = |
| 3489 | unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset); |
| 3490 | |
| 3491 | // TODO(dartbug.com/32292): accept unboxed parameters and return value |
| 3492 | // when FLAG_use_table_dispatch == false. |
| 3493 | if (FLAG_precompiled_mode && unboxing_info != nullptr && |
| 3494 | FLAG_use_table_dispatch && FLAG_use_bare_instructions) { |
| 3495 | if (field_accessor.IsImplicitSetterFunction()) { |
| 3496 | for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) { |
| 3497 | SetupUnboxingInfoOfParameter(field_accessor, i, unboxing_info); |
| 3498 | } |
| 3499 | } else { |
| 3500 | ASSERT(field_accessor.IsImplicitGetterFunction() || |
| 3501 | field_accessor.IsImplicitStaticGetterFunction()); |
| 3502 | SetupUnboxingInfoOfReturnValue(field_accessor, unboxing_info); |
| 3503 | } |
| 3504 | } |
| 3505 | } |
| 3506 | |
| 3507 | void TypeTranslator::SetupFunctionParameters( |
| 3508 | const Class& klass, |
| 3509 | const Function& function, |
| 3510 | bool is_method, |
| 3511 | bool is_closure, |
| 3512 | FunctionNodeHelper* function_node_helper) { |
| 3513 | ASSERT(!(is_method && is_closure)); |
| 3514 | bool is_factory = function.IsFactory(); |
| 3515 | intptr_t = (is_method || is_closure || is_factory) ? 1 : 0; |
| 3516 | |
| 3517 | if (!is_factory) { |
| 3518 | LoadAndSetupTypeParameters(active_class_, function, |
| 3519 | helper_->ReadListLength(), function); |
| 3520 | function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters); |
| 3521 | } |
| 3522 | |
| 3523 | ActiveTypeParametersScope scope(active_class_, function, Z); |
| 3524 | |
| 3525 | function_node_helper->ReadUntilExcluding( |
| 3526 | FunctionNodeHelper::kPositionalParameters); |
| 3527 | |
| 3528 | intptr_t required_parameter_count = |
| 3529 | function_node_helper->required_parameter_count_; |
| 3530 | intptr_t total_parameter_count = function_node_helper->total_parameter_count_; |
| 3531 | |
| 3532 | intptr_t positional_parameter_count = |
| 3533 | helper_->ReadListLength(); // read list length. |
| 3534 | |
| 3535 | intptr_t named_parameter_count = |
| 3536 | total_parameter_count - positional_parameter_count; |
| 3537 | |
| 3538 | function.set_num_fixed_parameters(extra_parameters + |
| 3539 | required_parameter_count); |
| 3540 | if (named_parameter_count > 0) { |
| 3541 | function.SetNumOptionalParameters(named_parameter_count, false); |
| 3542 | } else { |
| 3543 | function.SetNumOptionalParameters( |
| 3544 | positional_parameter_count - required_parameter_count, true); |
| 3545 | } |
| 3546 | intptr_t parameter_count = extra_parameters + total_parameter_count; |
| 3547 | |
| 3548 | function.set_parameter_types( |
| 3549 | Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); |
| 3550 | const Array& parameter_names = Array::Handle( |
| 3551 | Z, Array::New(Function::NameArrayLengthIncludingFlags(parameter_count), |
| 3552 | Heap::kOld)); |
| 3553 | function.set_parameter_names(parameter_names); |
| 3554 | intptr_t pos = 0; |
| 3555 | if (is_method) { |
| 3556 | ASSERT(!klass.IsNull()); |
| 3557 | function.SetParameterTypeAt(pos, H.GetDeclarationType(klass)); |
| 3558 | function.SetParameterNameAt(pos, Symbols::This()); |
| 3559 | pos++; |
| 3560 | } else if (is_closure) { |
| 3561 | function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
| 3562 | function.SetParameterNameAt(pos, Symbols::ClosureParameter()); |
| 3563 | pos++; |
| 3564 | } else if (is_factory) { |
| 3565 | function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
| 3566 | function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter()); |
| 3567 | pos++; |
| 3568 | } |
| 3569 | |
| 3570 | const Library& lib = Library::Handle(Z, active_class_->klass->library()); |
| 3571 | for (intptr_t i = 0; i < positional_parameter_count; ++i, ++pos) { |
| 3572 | // Read ith variable declaration. |
| 3573 | VariableDeclarationHelper helper(helper_); |
| 3574 | helper.ReadUntilExcluding(VariableDeclarationHelper::kType); |
| 3575 | // The required flag should only be set on named parameters. |
| 3576 | ASSERT(!helper.IsRequired()); |
| 3577 | const AbstractType& type = BuildTypeWithoutFinalization(); // read type. |
| 3578 | Tag tag = helper_->ReadTag(); // read (first part of) initializer. |
| 3579 | if (tag == kSomething) { |
| 3580 | helper_->SkipExpression(); // read (actual) initializer. |
| 3581 | } |
| 3582 | |
| 3583 | function.SetParameterTypeAt(pos, type); |
| 3584 | function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_)); |
| 3585 | } |
| 3586 | |
| 3587 | intptr_t named_parameter_count_check = |
| 3588 | helper_->ReadListLength(); // read list length. |
| 3589 | ASSERT(named_parameter_count_check == named_parameter_count); |
| 3590 | for (intptr_t i = 0; i < named_parameter_count; ++i, ++pos) { |
| 3591 | // Read ith variable declaration. |
| 3592 | VariableDeclarationHelper helper(helper_); |
| 3593 | helper.ReadUntilExcluding(VariableDeclarationHelper::kType); |
| 3594 | const AbstractType& type = BuildTypeWithoutFinalization(); // read type. |
| 3595 | Tag tag = helper_->ReadTag(); // read (first part of) initializer. |
| 3596 | if (tag == kSomething) { |
| 3597 | helper_->SkipExpression(); // read (actual) initializer. |
| 3598 | } |
| 3599 | |
| 3600 | function.SetParameterTypeAt(pos, type); |
| 3601 | function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_)); |
| 3602 | if (helper.IsRequired()) { |
| 3603 | function.SetIsRequiredAt(pos); |
| 3604 | } |
| 3605 | } |
| 3606 | function.TruncateUnusedParameterFlags(); |
| 3607 | |
| 3608 | function_node_helper->SetJustRead(FunctionNodeHelper::kNamedParameters); |
| 3609 | |
| 3610 | // The result type for generative constructors has already been set. |
| 3611 | if (!function.IsGenerativeConstructor()) { |
| 3612 | const AbstractType& return_type = |
| 3613 | BuildTypeWithoutFinalization(); // read return type. |
| 3614 | function.set_result_type(return_type); |
| 3615 | function_node_helper->SetJustRead(FunctionNodeHelper::kReturnType); |
| 3616 | } |
| 3617 | } |
| 3618 | |
| 3619 | } // namespace kernel |
| 3620 | } // namespace dart |
| 3621 | |