| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2016, 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/kernel_reader.h" | |
| 6 | |
| 7 #include <string.h> | |
| 8 | |
| 9 #include "vm/dart_api_impl.h" | |
| 10 #include "vm/kernel_binary.h" | |
| 11 #include "vm/kernel_binary_flowgraph.h" | |
| 12 #include "vm/kernel_to_il.h" | |
| 13 #include "vm/longjump.h" | |
| 14 #include "vm/object_store.h" | |
| 15 #include "vm/parser.h" | |
| 16 #include "vm/symbols.h" | |
| 17 | |
| 18 #if !defined(DART_PRECOMPILED_RUNTIME) | |
| 19 namespace dart { | |
| 20 namespace kernel { | |
| 21 | |
| 22 #define Z (zone_) | |
| 23 #define I (isolate_) | |
| 24 #define T (builder_.type_translator_) | |
| 25 #define H (translation_helper_) | |
| 26 | |
| 27 class SimpleExpressionConverter { | |
| 28 public: | |
| 29 SimpleExpressionConverter(TranslationHelper* helper, | |
| 30 StreamingFlowGraphBuilder* builder) | |
| 31 : translation_helper_(*helper), | |
| 32 zone_(translation_helper_.zone()), | |
| 33 simple_value_(NULL), | |
| 34 builder_(builder) {} | |
| 35 | |
| 36 bool IsSimple(intptr_t kernel_offset) { | |
| 37 AlternativeReadingScope alt(builder_->reader_, kernel_offset); | |
| 38 uint8_t payload = 0; | |
| 39 Tag tag = builder_->ReadTag(&payload); // read tag. | |
| 40 switch (tag) { | |
| 41 case kBigIntLiteral: { | |
| 42 const String& literal_str = | |
| 43 H.DartString(builder_->ReadStringReference(), | |
| 44 Heap::kOld); // read index into string table. | |
| 45 simple_value_ = &Integer::ZoneHandle(Z, Integer::New(literal_str)); | |
| 46 if (simple_value_->IsNull()) { | |
| 47 H.ReportError("Integer literal %s is out of range", | |
| 48 literal_str.ToCString()); | |
| 49 UNREACHABLE(); | |
| 50 } | |
| 51 *simple_value_ = H.Canonicalize(*simple_value_); | |
| 52 return true; | |
| 53 } | |
| 54 case kStringLiteral: | |
| 55 simple_value_ = &H.DartSymbol( | |
| 56 builder_->ReadStringReference()); // read index into string table. | |
| 57 return true; | |
| 58 case kSpecialIntLiteral: | |
| 59 simple_value_ = | |
| 60 &Integer::ZoneHandle(Z, Integer::New(static_cast<int32_t>(payload) - | |
| 61 SpecializedIntLiteralBias, | |
| 62 Heap::kOld)); | |
| 63 *simple_value_ = H.Canonicalize(*simple_value_); | |
| 64 return true; | |
| 65 case kNegativeIntLiteral: | |
| 66 simple_value_ = &Integer::ZoneHandle( | |
| 67 Z, Integer::New(-static_cast<int64_t>(builder_->ReadUInt()), | |
| 68 Heap::kOld)); // read value. | |
| 69 *simple_value_ = H.Canonicalize(*simple_value_); | |
| 70 return true; | |
| 71 case kPositiveIntLiteral: | |
| 72 simple_value_ = &Integer::ZoneHandle( | |
| 73 Z, Integer::New(static_cast<int64_t>(builder_->ReadUInt()), | |
| 74 Heap::kOld)); // read value. | |
| 75 *simple_value_ = H.Canonicalize(*simple_value_); | |
| 76 return true; | |
| 77 case kDoubleLiteral: | |
| 78 simple_value_ = &Double::ZoneHandle( | |
| 79 Z, Double::New(H.DartString(builder_->ReadStringReference()), | |
| 80 Heap::kOld)); // read string reference. | |
| 81 *simple_value_ = H.Canonicalize(*simple_value_); | |
| 82 return true; | |
| 83 case kTrueLiteral: | |
| 84 simple_value_ = &Bool::Handle(Z, Bool::Get(true).raw()); | |
| 85 return true; | |
| 86 case kFalseLiteral: | |
| 87 simple_value_ = &Bool::Handle(Z, Bool::Get(false).raw()); | |
| 88 return true; | |
| 89 case kNullLiteral: | |
| 90 simple_value_ = &Instance::ZoneHandle(Z, Instance::null()); | |
| 91 return true; | |
| 92 default: | |
| 93 return false; | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 const Instance& SimpleValue() { return *simple_value_; } | |
| 98 Zone* zone() const { return zone_; } | |
| 99 | |
| 100 private: | |
| 101 TranslationHelper& translation_helper_; | |
| 102 Zone* zone_; | |
| 103 Instance* simple_value_; | |
| 104 StreamingFlowGraphBuilder* builder_; | |
| 105 }; | |
| 106 | |
| 107 RawArray* KernelReader::MakeFunctionsArray() { | |
| 108 const intptr_t len = functions_.length(); | |
| 109 const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld)); | |
| 110 for (intptr_t i = 0; i < len; i++) { | |
| 111 res.SetAt(i, *functions_[i]); | |
| 112 } | |
| 113 return res.raw(); | |
| 114 } | |
| 115 | |
| 116 RawLibrary* BuildingTranslationHelper::LookupLibraryByKernelLibrary( | |
| 117 NameIndex library) { | |
| 118 return reader_->LookupLibrary(library).raw(); | |
| 119 } | |
| 120 | |
| 121 RawClass* BuildingTranslationHelper::LookupClassByKernelClass(NameIndex klass) { | |
| 122 return reader_->LookupClass(klass).raw(); | |
| 123 } | |
| 124 | |
| 125 KernelReader::KernelReader(Program* program) | |
| 126 : program_(program), | |
| 127 thread_(Thread::Current()), | |
| 128 zone_(thread_->zone()), | |
| 129 isolate_(thread_->isolate()), | |
| 130 scripts_(Array::ZoneHandle(zone_)), | |
| 131 patch_classes_(Array::ZoneHandle(zone_)), | |
| 132 translation_helper_(this, thread_), | |
| 133 builder_(&translation_helper_, | |
| 134 zone_, | |
| 135 program_->kernel_data(), | |
| 136 program_->kernel_data_size()) { | |
| 137 T.active_class_ = &active_class_; | |
| 138 T.finalize_ = false; | |
| 139 | |
| 140 scripts_ = Array::New(builder_.SourceTableSize(), Heap::kOld); | |
| 141 patch_classes_ = Array::New(builder_.SourceTableSize(), Heap::kOld); | |
| 142 | |
| 143 // Copy the Kernel string offsets out of the binary and into the VM's heap. | |
| 144 ASSERT(program->string_table_offset() >= 0); | |
| 145 Reader reader(program->kernel_data(), program->kernel_data_size()); | |
| 146 reader.set_offset(program->string_table_offset()); | |
| 147 intptr_t count = reader.ReadUInt() + 1; | |
| 148 TypedData& offsets = TypedData::Handle( | |
| 149 Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld)); | |
| 150 offsets.SetUint32(0, 0); | |
| 151 intptr_t end_offset = 0; | |
| 152 for (intptr_t i = 1; i < count; ++i) { | |
| 153 end_offset = reader.ReadUInt(); | |
| 154 offsets.SetUint32(i << 2, end_offset); | |
| 155 } | |
| 156 | |
| 157 // Copy the string data out of the binary and into the VM's heap. | |
| 158 TypedData& data = | |
| 159 reader.CopyDataToVMHeap(Z, reader.offset(), reader.offset() + end_offset); | |
| 160 | |
| 161 // Copy the canonical names into the VM's heap. Encode them as unsigned, so | |
| 162 // the parent indexes are adjusted when extracted. | |
| 163 reader.set_offset(program->name_table_offset()); | |
| 164 count = reader.ReadUInt() * 2; | |
| 165 TypedData& names = TypedData::Handle( | |
| 166 Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld)); | |
| 167 for (intptr_t i = 0; i < count; ++i) { | |
| 168 names.SetUint32(i << 2, reader.ReadUInt()); | |
| 169 } | |
| 170 | |
| 171 H.SetStringOffsets(offsets); | |
| 172 H.SetStringData(data); | |
| 173 H.SetCanonicalNames(names); | |
| 174 } | |
| 175 | |
| 176 Object& KernelReader::ReadProgram() { | |
| 177 LongJumpScope jump; | |
| 178 if (setjmp(*jump.Set()) == 0) { | |
| 179 intptr_t length = program_->library_count(); | |
| 180 for (intptr_t i = 0; i < length; i++) { | |
| 181 ReadLibrary(library_offset(i)); | |
| 182 } | |
| 183 | |
| 184 for (intptr_t i = 0; i < length; i++) { | |
| 185 Library& library = LookupLibrary(library_canonical_name(i)); | |
| 186 if (!library.Loaded()) library.SetLoaded(); | |
| 187 } | |
| 188 | |
| 189 if (ClassFinalizer::ProcessPendingClasses(/*from_kernel=*/true)) { | |
| 190 // If 'main' is not found return a null library, this is the case | |
| 191 // when bootstrapping is in progress. | |
| 192 NameIndex main = program_->main_method(); | |
| 193 if (main == -1) { | |
| 194 return Library::Handle(Z); | |
| 195 } | |
| 196 | |
| 197 NameIndex main_library = H.EnclosingName(main); | |
| 198 Library& library = LookupLibrary(main_library); | |
| 199 // Sanity check that we can find the main entrypoint. | |
| 200 ASSERT(library.LookupObjectAllowPrivate(H.DartSymbol("main")) != | |
| 201 Object::null()); | |
| 202 return library; | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 // Either class finalization failed or we caught a compile error. | |
| 207 // In both cases sticky error would be set. | |
| 208 Error& error = Error::Handle(Z); | |
| 209 error = thread_->sticky_error(); | |
| 210 thread_->clear_sticky_error(); | |
| 211 return error; | |
| 212 } | |
| 213 | |
| 214 void KernelReader::FindModifiedLibraries(Isolate* isolate, | |
| 215 BitVector* modified_libs, | |
| 216 bool force_reload) { | |
| 217 LongJumpScope jump; | |
| 218 if (setjmp(*jump.Set()) == 0) { | |
| 219 if (force_reload) { | |
| 220 // If a reload is being forced we mark all libraries as having | |
| 221 // been modified. | |
| 222 const GrowableObjectArray& libs = | |
| 223 GrowableObjectArray::Handle(isolate->object_store()->libraries()); | |
| 224 intptr_t num_libs = libs.Length(); | |
| 225 Library& lib = dart::Library::Handle(Z); | |
| 226 for (intptr_t i = 0; i < num_libs; i++) { | |
| 227 lib ^= libs.At(i); | |
| 228 if (!lib.is_dart_scheme()) { | |
| 229 modified_libs->Add(lib.index()); | |
| 230 } | |
| 231 } | |
| 232 return; | |
| 233 } | |
| 234 // Now go through all the libraries that are present in the incremental | |
| 235 // kernel files, these will constitute the modified libraries. | |
| 236 intptr_t length = program_->library_count(); | |
| 237 for (intptr_t i = 0; i < length; i++) { | |
| 238 intptr_t kernel_offset = library_offset(i); | |
| 239 builder_.SetOffset(kernel_offset); | |
| 240 LibraryHelper library_helper(&builder_); | |
| 241 library_helper.ReadUntilIncluding(LibraryHelper::kCanonicalName); | |
| 242 dart::Library& lib = LookupLibrary(library_helper.canonical_name_); | |
| 243 if (!lib.IsNull() && !lib.is_dart_scheme()) { | |
| 244 // This is a library that already exists so mark it as being modified. | |
| 245 modified_libs->Add(lib.index()); | |
| 246 } | |
| 247 } | |
| 248 } | |
| 249 } | |
| 250 | |
| 251 void KernelReader::ReadLibrary(intptr_t kernel_offset) { | |
| 252 builder_.SetOffset(kernel_offset); | |
| 253 LibraryHelper library_helper(&builder_); | |
| 254 library_helper.ReadUntilIncluding(LibraryHelper::kCanonicalName); | |
| 255 Library& library = LookupLibrary(library_helper.canonical_name_); | |
| 256 // The Kernel library is external implies that it is already loaded. | |
| 257 ASSERT(!library_helper.IsExternal() || library.Loaded()); | |
| 258 if (library.Loaded()) return; | |
| 259 | |
| 260 library_helper.ReadUntilIncluding(LibraryHelper::kName); | |
| 261 library.SetName(H.DartSymbol(library_helper.name_index_)); | |
| 262 | |
| 263 // The bootstrapper will take care of creating the native wrapper classes, but | |
| 264 // we will add the synthetic constructors to them here. | |
| 265 if (library.name() == | |
| 266 Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).raw()) { | |
| 267 ASSERT(library.LoadInProgress()); | |
| 268 } else { | |
| 269 library.SetLoadInProgress(); | |
| 270 } | |
| 271 // Setup toplevel class (which contains library fields/procedures). | |
| 272 | |
| 273 StringIndex import_uri_index = | |
| 274 H.CanonicalNameString(library_helper.canonical_name_); | |
| 275 library_helper.ReadUntilIncluding(LibraryHelper::kSourceUriIndex); | |
| 276 Script& script = ScriptAt(library_helper.source_uri_index_, import_uri_index); | |
| 277 | |
| 278 Class& toplevel_class = | |
| 279 Class::Handle(Z, Class::New(library, Symbols::TopLevel(), script, | |
| 280 TokenPosition::kNoSource)); | |
| 281 toplevel_class.set_is_cycle_free(); | |
| 282 library.set_toplevel_class(toplevel_class); | |
| 283 | |
| 284 const GrowableObjectArray& classes = | |
| 285 GrowableObjectArray::Handle(Z, I->object_store()->pending_classes()); | |
| 286 | |
| 287 library_helper.ReadUntilExcluding(LibraryHelper::kClasses); | |
| 288 | |
| 289 // Load all classes. | |
| 290 int class_count = builder_.ReadListLength(); // read list length. | |
| 291 for (intptr_t i = 0; i < class_count; ++i) { | |
| 292 classes.Add(ReadClass(library, toplevel_class), Heap::kOld); | |
| 293 } | |
| 294 | |
| 295 fields_.Clear(); | |
| 296 functions_.Clear(); | |
| 297 ActiveClassScope active_class_scope(&active_class_, &toplevel_class); | |
| 298 // Load toplevel fields. | |
| 299 intptr_t field_count = builder_.ReadListLength(); // read list length. | |
| 300 for (intptr_t i = 0; i < field_count; ++i) { | |
| 301 intptr_t field_offset = builder_.ReaderOffset(); | |
| 302 ActiveMemberScope active_member_scope(&active_class_, NULL); | |
| 303 FieldHelper field_helper(&builder_); | |
| 304 field_helper.ReadUntilExcluding(FieldHelper::kName); | |
| 305 | |
| 306 const String& name = builder_.ReadNameAsFieldName(); | |
| 307 field_helper.SetJustRead(FieldHelper::kName); | |
| 308 field_helper.ReadUntilExcluding(FieldHelper::kType); | |
| 309 const Object& script_class = | |
| 310 ClassForScriptAt(toplevel_class, field_helper.source_uri_index_); | |
| 311 Field& field = Field::Handle( | |
| 312 Z, | |
| 313 Field::NewTopLevel(name, field_helper.IsFinal(), field_helper.IsConst(), | |
| 314 script_class, field_helper.position_)); | |
| 315 field.set_kernel_offset(field_offset); | |
| 316 const AbstractType& type = T.BuildType(); // read type. | |
| 317 field.SetFieldType(type); | |
| 318 field_helper.SetJustRead(FieldHelper::kType); | |
| 319 field_helper.ReadUntilExcluding(FieldHelper::kInitializer); | |
| 320 intptr_t field_initializer_offset = builder_.ReaderOffset(); | |
| 321 field.set_has_initializer(builder_.PeekTag() == kSomething); | |
| 322 field_helper.ReadUntilExcluding(FieldHelper::kEnd); | |
| 323 TypedData& kernel_data = builder_.reader_->CopyDataToVMHeap( | |
| 324 Z, field_offset, builder_.ReaderOffset()); | |
| 325 field.set_kernel_data(kernel_data); | |
| 326 { | |
| 327 // GenerateFieldAccessors reads (some of) the initializer. | |
| 328 AlternativeReadingScope alt(builder_.reader_, field_initializer_offset); | |
| 329 GenerateFieldAccessors(toplevel_class, field, &field_helper, | |
| 330 field_offset); | |
| 331 } | |
| 332 if (FLAG_enable_mirrors && field_helper.annotation_count_ > 0) { | |
| 333 library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset, | |
| 334 &kernel_data); | |
| 335 } | |
| 336 fields_.Add(&field); | |
| 337 library.AddObject(field, name); | |
| 338 } | |
| 339 toplevel_class.AddFields(fields_); | |
| 340 | |
| 341 // Load toplevel procedures. | |
| 342 intptr_t procedure_count = builder_.ReadListLength(); // read list length. | |
| 343 for (intptr_t i = 0; i < procedure_count; ++i) { | |
| 344 ReadProcedure(library, toplevel_class, false); | |
| 345 } | |
| 346 | |
| 347 toplevel_class.SetFunctions(Array::Handle(MakeFunctionsArray())); | |
| 348 | |
| 349 classes.Add(toplevel_class, Heap::kOld); | |
| 350 } | |
| 351 | |
| 352 void KernelReader::ReadPreliminaryClass(Class* klass, | |
| 353 ClassHelper* class_helper, | |
| 354 intptr_t type_parameter_count) { | |
| 355 // Note: This assumes that ClassHelper is exactly at the position where | |
| 356 // the length of the type parameters have been read, and that the order in | |
| 357 // the binary is as follows: [...], kTypeParameters, kSuperClass, kMixinType, | |
| 358 // kImplementedClasses, [...]. | |
| 359 | |
| 360 // Set type parameters. | |
| 361 ReadAndSetupTypeParameters(*klass, type_parameter_count, *klass, | |
| 362 Function::Handle(Z)); | |
| 363 | |
| 364 // Set super type. Some classes (e.g., Object) do not have one. | |
| 365 Tag type_tag = builder_.ReadTag(); // read super class type (part 1). | |
| 366 if (type_tag == kSomething) { | |
| 367 AbstractType& super_type = | |
| 368 T.BuildTypeWithoutFinalization(); // read super class type (part 2). | |
| 369 if (super_type.IsMalformed()) H.ReportError("Malformed super type"); | |
| 370 klass->set_super_type(super_type); | |
| 371 } | |
| 372 | |
| 373 class_helper->SetJustRead(ClassHelper::kSuperClass); | |
| 374 class_helper->ReadUntilIncluding(ClassHelper::kMixinType); | |
| 375 | |
| 376 // Build implemented interface types | |
| 377 intptr_t interface_count = builder_.ReadListLength(); | |
| 378 const Array& interfaces = | |
| 379 Array::Handle(Z, Array::New(interface_count, Heap::kOld)); | |
| 380 for (intptr_t i = 0; i < interface_count; i++) { | |
| 381 const AbstractType& type = | |
| 382 T.BuildTypeWithoutFinalization(); // read ith type. | |
| 383 if (type.IsMalformed()) H.ReportError("Malformed interface type."); | |
| 384 interfaces.SetAt(i, type); | |
| 385 } | |
| 386 class_helper->SetJustRead(ClassHelper::kImplementedClasses); | |
| 387 klass->set_interfaces(interfaces); | |
| 388 | |
| 389 if (class_helper->is_abstract_) klass->set_is_abstract(); | |
| 390 } | |
| 391 | |
| 392 Class& KernelReader::ReadClass(const Library& library, | |
| 393 const Class& toplevel_class) { | |
| 394 ClassHelper class_helper(&builder_); | |
| 395 intptr_t class_offset = builder_.ReaderOffset(); | |
| 396 class_helper.ReadUntilIncluding(ClassHelper::kCanonicalName); | |
| 397 Class& klass = LookupClass(class_helper.canonical_name_); | |
| 398 | |
| 399 // The class needs to have a script because all the functions in the class | |
| 400 // will inherit it. The predicate Function::IsOptimizable uses the absence of | |
| 401 // a script to detect test functions that should not be optimized. | |
| 402 if (klass.script() == Script::null()) { | |
| 403 class_helper.ReadUntilIncluding(ClassHelper::kSourceUriIndex); | |
| 404 klass.set_script(ScriptAt(class_helper.source_uri_index_)); | |
| 405 } | |
| 406 if (klass.token_pos() == TokenPosition::kNoSource) { | |
| 407 class_helper.ReadUntilIncluding(ClassHelper::kPosition); | |
| 408 klass.set_token_pos(class_helper.position_); | |
| 409 } | |
| 410 | |
| 411 class_helper.ReadUntilIncluding(ClassHelper::kAnnotations); | |
| 412 intptr_t class_offset_after_annotations = builder_.ReaderOffset(); | |
| 413 class_helper.ReadUntilExcluding(ClassHelper::kTypeParameters); | |
| 414 intptr_t type_parameter_counts = | |
| 415 builder_.ReadListLength(); // read type_parameters list length. | |
| 416 | |
| 417 ActiveClassScope active_class_scope(&active_class_, &klass); | |
| 418 if (!klass.is_cycle_free()) { | |
| 419 ReadPreliminaryClass(&klass, &class_helper, type_parameter_counts); | |
| 420 } else { | |
| 421 for (intptr_t i = 0; i < type_parameter_counts; ++i) { | |
| 422 builder_.SkipStringReference(); // read ith name index. | |
| 423 builder_.SkipDartType(); // read ith bound. | |
| 424 } | |
| 425 class_helper.SetJustRead(ClassHelper::kTypeParameters); | |
| 426 } | |
| 427 | |
| 428 fields_.Clear(); | |
| 429 functions_.Clear(); | |
| 430 | |
| 431 if (library.raw() == Library::InternalLibrary() && | |
| 432 klass.Name() == Symbols::ClassID().raw()) { | |
| 433 // If this is a dart:internal.ClassID class ignore field declarations | |
| 434 // contained in the Kernel file and instead inject our own const | |
| 435 // fields. | |
| 436 klass.InjectCIDFields(); | |
| 437 } else { | |
| 438 class_helper.ReadUntilExcluding(ClassHelper::kFields); | |
| 439 int field_count = builder_.ReadListLength(); // read list length. | |
| 440 for (intptr_t i = 0; i < field_count; ++i) { | |
| 441 intptr_t field_offset = builder_.ReaderOffset(); | |
| 442 ActiveMemberScope active_member(&active_class_, NULL); | |
| 443 FieldHelper field_helper(&builder_); | |
| 444 field_helper.ReadUntilExcluding(FieldHelper::kName); | |
| 445 | |
| 446 const String& name = builder_.ReadNameAsFieldName(); | |
| 447 field_helper.SetJustRead(FieldHelper::kName); | |
| 448 field_helper.ReadUntilExcluding(FieldHelper::kType); | |
| 449 const AbstractType& type = | |
| 450 T.BuildTypeWithoutFinalization(); // read type. | |
| 451 field_helper.SetJustRead(FieldHelper::kType); | |
| 452 const Object& script_class = | |
| 453 ClassForScriptAt(klass, field_helper.source_uri_index_); | |
| 454 | |
| 455 const bool is_reflectable = | |
| 456 field_helper.position_.IsReal() && | |
| 457 !(library.is_dart_scheme() && library.IsPrivate(name)); | |
| 458 Field& field = Field::Handle( | |
| 459 Z, Field::New(name, field_helper.IsStatic(), | |
| 460 // In the VM all const fields are implicitly final | |
| 461 // whereas in Kernel they are not final because they | |
| 462 // are not explicitly declared that way. | |
| 463 field_helper.IsFinal() || field_helper.IsConst(), | |
| 464 field_helper.IsConst(), is_reflectable, script_class, | |
| 465 type, field_helper.position_)); | |
| 466 field.set_kernel_offset(field_offset); | |
| 467 field_helper.ReadUntilExcluding(FieldHelper::kInitializer); | |
| 468 intptr_t field_initializer_offset = builder_.ReaderOffset(); | |
| 469 field.set_has_initializer(builder_.PeekTag() == kSomething); | |
| 470 field_helper.ReadUntilExcluding(FieldHelper::kEnd); | |
| 471 TypedData& kernel_data = builder_.reader_->CopyDataToVMHeap( | |
| 472 Z, field_offset, builder_.ReaderOffset()); | |
| 473 field.set_kernel_data(kernel_data); | |
| 474 { | |
| 475 // GenerateFieldAccessors reads (some of) the initializer. | |
| 476 AlternativeReadingScope alt(builder_.reader_, field_initializer_offset); | |
| 477 GenerateFieldAccessors(klass, field, &field_helper, field_offset); | |
| 478 } | |
| 479 if (FLAG_enable_mirrors && field_helper.annotation_count_ > 0) { | |
| 480 library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset, | |
| 481 &kernel_data); | |
| 482 } | |
| 483 fields_.Add(&field); | |
| 484 } | |
| 485 klass.AddFields(fields_); | |
| 486 class_helper.SetJustRead(ClassHelper::kFields); | |
| 487 } | |
| 488 | |
| 489 class_helper.ReadUntilExcluding(ClassHelper::kConstructors); | |
| 490 int constructor_count = builder_.ReadListLength(); // read list length. | |
| 491 for (intptr_t i = 0; i < constructor_count; ++i) { | |
| 492 intptr_t constructor_offset = builder_.ReaderOffset(); | |
| 493 ActiveMemberScope active_member_scope(&active_class_, NULL); | |
| 494 ConstructorHelper constructor_helper(&builder_); | |
| 495 constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction); | |
| 496 | |
| 497 const String& name = | |
| 498 H.DartConstructorName(constructor_helper.canonical_name_); | |
| 499 Function& function = Function::ZoneHandle( | |
| 500 Z, Function::New(name, RawFunction::kConstructor, | |
| 501 false, // is_static | |
| 502 constructor_helper.IsConst(), | |
| 503 false, // is_abstract | |
| 504 constructor_helper.IsExternal(), | |
| 505 false, // is_native | |
| 506 klass, constructor_helper.position_)); | |
| 507 function.set_end_token_pos(constructor_helper.end_position_); | |
| 508 functions_.Add(&function); | |
| 509 function.set_kernel_offset(constructor_offset); | |
| 510 function.set_result_type(T.ReceiverType(klass)); | |
| 511 | |
| 512 FunctionNodeHelper function_node_helper(&builder_); | |
| 513 function_node_helper.ReadUntilExcluding( | |
| 514 FunctionNodeHelper::kRequiredParameterCount); | |
| 515 builder_.SetupFunctionParameters(klass, function, | |
| 516 true, // is_method | |
| 517 false, // is_closure | |
| 518 &function_node_helper); | |
| 519 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd); | |
| 520 constructor_helper.SetJustRead(ConstructorHelper::kFunction); | |
| 521 constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd); | |
| 522 TypedData& kernel_data = builder_.reader_->CopyDataToVMHeap( | |
| 523 Z, constructor_offset, builder_.ReaderOffset()); | |
| 524 function.set_kernel_data(kernel_data); | |
| 525 | |
| 526 if (FLAG_enable_mirrors && constructor_helper.annotation_count_ > 0) { | |
| 527 library.AddFunctionMetadata(function, TokenPosition::kNoSource, | |
| 528 constructor_offset, &kernel_data); | |
| 529 } | |
| 530 } | |
| 531 class_helper.SetJustRead(ClassHelper::kConstructors); | |
| 532 | |
| 533 class_helper.ReadUntilExcluding(ClassHelper::kProcedures); | |
| 534 int procedure_count = builder_.ReadListLength(); // read list length. | |
| 535 for (intptr_t i = 0; i < procedure_count; ++i) { | |
| 536 ReadProcedure(library, klass, true); | |
| 537 } | |
| 538 class_helper.SetJustRead(ClassHelper::kProcedures); | |
| 539 | |
| 540 klass.SetFunctions(Array::Handle(MakeFunctionsArray())); | |
| 541 | |
| 542 if (!klass.is_marked_for_parsing()) { | |
| 543 klass.set_is_marked_for_parsing(); | |
| 544 } | |
| 545 | |
| 546 if (FLAG_enable_mirrors && class_helper.annotation_count_ > 0) { | |
| 547 TypedData& header_data = builder_.reader_->CopyDataToVMHeap( | |
| 548 Z, class_offset, class_offset_after_annotations); | |
| 549 library.AddClassMetadata(klass, toplevel_class, TokenPosition::kNoSource, | |
| 550 class_offset, &header_data); | |
| 551 } | |
| 552 | |
| 553 class_helper.ReadUntilExcluding(ClassHelper::kEnd); | |
| 554 | |
| 555 return klass; | |
| 556 } | |
| 557 | |
| 558 void KernelReader::ReadProcedure(const Library& library, | |
| 559 const Class& owner, | |
| 560 bool in_class) { | |
| 561 intptr_t procedure_offset = builder_.ReaderOffset(); | |
| 562 ProcedureHelper procedure_helper(&builder_); | |
| 563 | |
| 564 procedure_helper.ReadUntilExcluding(ProcedureHelper::kAnnotations); | |
| 565 const String& name = H.DartProcedureName(procedure_helper.canonical_name_); | |
| 566 bool is_method = in_class && !procedure_helper.IsStatic(); | |
| 567 bool is_abstract = procedure_helper.IsAbstract(); | |
| 568 bool is_external = procedure_helper.IsExternal(); | |
| 569 String* native_name = NULL; | |
| 570 intptr_t annotation_count; | |
| 571 if (is_external) { | |
| 572 // Maybe it has a native implementation, which is not external as far as | |
| 573 // the VM is concerned because it does have an implementation. Check for | |
| 574 // an ExternalName annotation and extract the string from it. | |
| 575 annotation_count = builder_.ReadListLength(); // read list length. | |
| 576 for (int i = 0; i < annotation_count; ++i) { | |
| 577 if (builder_.PeekTag() != kConstructorInvocation && | |
| 578 builder_.PeekTag() != kConstConstructorInvocation) { | |
| 579 builder_.SkipExpression(); | |
| 580 continue; | |
| 581 } | |
| 582 builder_.ReadTag(); | |
| 583 builder_.ReadPosition(); | |
| 584 NameIndex annotation_class = H.EnclosingName( | |
| 585 builder_.ReadCanonicalNameReference()); // read target reference, | |
| 586 ASSERT(H.IsClass(annotation_class)); | |
| 587 StringIndex class_name_index = H.CanonicalNameString(annotation_class); | |
| 588 // Just compare by name, do not generate the annotation class. | |
| 589 if (!H.StringEquals(class_name_index, "ExternalName")) { | |
| 590 builder_.SkipArguments(); | |
| 591 continue; | |
| 592 } | |
| 593 ASSERT(H.IsLibrary(H.CanonicalNameParent(annotation_class))); | |
| 594 StringIndex library_name_index = | |
| 595 H.CanonicalNameString(H.CanonicalNameParent(annotation_class)); | |
| 596 if (!H.StringEquals(library_name_index, "dart:_internal")) { | |
| 597 builder_.SkipArguments(); | |
| 598 continue; | |
| 599 } | |
| 600 | |
| 601 is_external = false; | |
| 602 // Read arguments: | |
| 603 intptr_t total_arguments = builder_.ReadUInt(); // read argument count. | |
| 604 builder_.SkipListOfDartTypes(); // read list of types. | |
| 605 intptr_t positional_arguments = builder_.ReadListLength(); | |
| 606 ASSERT(total_arguments == 1 && positional_arguments == 1); | |
| 607 | |
| 608 Tag tag = builder_.ReadTag(); | |
| 609 ASSERT(tag == kStringLiteral); | |
| 610 native_name = &H.DartSymbol( | |
| 611 builder_.ReadStringReference()); // read index into string table. | |
| 612 | |
| 613 // List of named. | |
| 614 intptr_t list_length = builder_.ReadListLength(); // read list length. | |
| 615 ASSERT(list_length == 0); | |
| 616 | |
| 617 // Skip remaining annotations | |
| 618 for (++i; i < annotation_count; ++i) { | |
| 619 builder_.SkipExpression(); // read ith annotation. | |
| 620 } | |
| 621 | |
| 622 break; | |
| 623 } | |
| 624 procedure_helper.SetJustRead(ProcedureHelper::kAnnotations); | |
| 625 } else { | |
| 626 procedure_helper.ReadUntilIncluding(ProcedureHelper::kAnnotations); | |
| 627 annotation_count = procedure_helper.annotation_count_; | |
| 628 } | |
| 629 const Object& script_class = | |
| 630 ClassForScriptAt(owner, procedure_helper.source_uri_index_); | |
| 631 Function& function = Function::ZoneHandle( | |
| 632 Z, Function::New(name, GetFunctionType(procedure_helper.kind_), | |
| 633 !is_method, // is_static | |
| 634 false, // is_const | |
| 635 is_abstract, is_external, | |
| 636 native_name != NULL, // is_native | |
| 637 script_class, procedure_helper.position_)); | |
| 638 function.set_end_token_pos(procedure_helper.end_position_); | |
| 639 functions_.Add(&function); | |
| 640 function.set_kernel_offset(procedure_offset); | |
| 641 | |
| 642 ActiveMemberScope active_member(&active_class_, &function); | |
| 643 | |
| 644 procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction); | |
| 645 Tag function_node_tag = builder_.ReadTag(); | |
| 646 ASSERT(function_node_tag == kSomething); | |
| 647 FunctionNodeHelper function_node_helper(&builder_); | |
| 648 function_node_helper.ReadUntilIncluding(FunctionNodeHelper::kDartAsyncMarker); | |
| 649 function.set_is_debuggable(function_node_helper.dart_async_marker_ == | |
| 650 FunctionNodeHelper::kSync); | |
| 651 switch (function_node_helper.dart_async_marker_) { | |
| 652 case FunctionNodeHelper::kSyncStar: | |
| 653 function.set_modifier(RawFunction::kSyncGen); | |
| 654 break; | |
| 655 case FunctionNodeHelper::kAsync: | |
| 656 function.set_modifier(RawFunction::kAsync); | |
| 657 function.set_is_inlinable(!FLAG_causal_async_stacks); | |
| 658 break; | |
| 659 case FunctionNodeHelper::kAsyncStar: | |
| 660 function.set_modifier(RawFunction::kAsyncGen); | |
| 661 function.set_is_inlinable(!FLAG_causal_async_stacks); | |
| 662 break; | |
| 663 default: | |
| 664 // no special modifier | |
| 665 break; | |
| 666 } | |
| 667 ASSERT(function_node_helper.async_marker_ == FunctionNodeHelper::kSync); | |
| 668 | |
| 669 if (native_name != NULL) { | |
| 670 function.set_native_name(*native_name); | |
| 671 } | |
| 672 | |
| 673 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters); | |
| 674 if (!function.IsFactory()) { | |
| 675 // Read type_parameters list length. | |
| 676 intptr_t type_parameter_count = builder_.ReadListLength(); | |
| 677 // Set type parameters. | |
| 678 ReadAndSetupTypeParameters(function, type_parameter_count, Class::Handle(Z), | |
| 679 function); | |
| 680 function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters); | |
| 681 } | |
| 682 | |
| 683 function_node_helper.ReadUntilExcluding( | |
| 684 FunctionNodeHelper::kRequiredParameterCount); | |
| 685 builder_.SetupFunctionParameters(owner, function, is_method, | |
| 686 false, // is_closure | |
| 687 &function_node_helper); | |
| 688 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd); | |
| 689 procedure_helper.SetJustRead(ProcedureHelper::kFunction); | |
| 690 | |
| 691 if (!in_class) { | |
| 692 library.AddObject(function, name); | |
| 693 ASSERT(!Object::Handle( | |
| 694 Z, library.LookupObjectAllowPrivate( | |
| 695 H.DartProcedureName(procedure_helper.canonical_name_))) | |
| 696 .IsNull()); | |
| 697 } | |
| 698 | |
| 699 procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd); | |
| 700 TypedData& kernel_data = builder_.reader_->CopyDataToVMHeap( | |
| 701 Z, procedure_offset, builder_.ReaderOffset()); | |
| 702 function.set_kernel_data(kernel_data); | |
| 703 | |
| 704 if (FLAG_enable_mirrors && annotation_count > 0) { | |
| 705 library.AddFunctionMetadata(function, TokenPosition::kNoSource, | |
| 706 procedure_offset, &kernel_data); | |
| 707 } | |
| 708 } | |
| 709 | |
| 710 void KernelReader::ReadAndSetupTypeParameters( | |
| 711 const Object& set_on, | |
| 712 intptr_t type_parameter_count, | |
| 713 const Class& parameterized_class, | |
| 714 const Function& parameterized_function) { | |
| 715 ASSERT(type_parameter_count >= 0); | |
| 716 if (type_parameter_count == 0) { | |
| 717 return; | |
| 718 } | |
| 719 // First setup the type parameters, so if any of the following code uses it | |
| 720 // (in a recursive way) we're fine. | |
| 721 TypeArguments& type_parameters = | |
| 722 TypeArguments::Handle(Z, TypeArguments::null()); | |
| 723 TypeParameter& parameter = TypeParameter::Handle(Z); | |
| 724 Type& null_bound = Type::Handle(Z, Type::null()); | |
| 725 | |
| 726 // Step a) Create array of [TypeParameter] objects (without bound). | |
| 727 type_parameters = TypeArguments::New(type_parameter_count); | |
| 728 { | |
| 729 AlternativeReadingScope alt(builder_.reader_); | |
| 730 for (intptr_t i = 0; i < type_parameter_count; i++) { | |
| 731 parameter = TypeParameter::New( | |
| 732 parameterized_class, parameterized_function, i, | |
| 733 H.DartSymbol(builder_.ReadStringReference()), // read ith name index. | |
| 734 null_bound, TokenPosition::kNoSource); | |
| 735 type_parameters.SetTypeAt(i, parameter); | |
| 736 builder_.SkipDartType(); // read guard. | |
| 737 } | |
| 738 } | |
| 739 | |
| 740 ASSERT(set_on.IsClass() || set_on.IsFunction()); | |
| 741 if (set_on.IsClass()) { | |
| 742 Class::Cast(set_on).set_type_parameters(type_parameters); | |
| 743 } else { | |
| 744 Function::Cast(set_on).set_type_parameters(type_parameters); | |
| 745 } | |
| 746 | |
| 747 // Step b) Fill in the bounds of all [TypeParameter]s. | |
| 748 for (intptr_t i = 0; i < type_parameter_count; i++) { | |
| 749 builder_.SkipStringReference(); // read ith name index. | |
| 750 | |
| 751 // TODO(github.com/dart-lang/kernel/issues/42): This should be handled | |
| 752 // by the frontend. | |
| 753 parameter ^= type_parameters.TypeAt(i); | |
| 754 Tag tag = builder_.PeekTag(); // peek ith bound type. | |
| 755 if (tag == kDynamicType) { | |
| 756 builder_.SkipDartType(); // read ith bound. | |
| 757 parameter.set_bound(Type::Handle(Z, I->object_store()->object_type())); | |
| 758 } else { | |
| 759 AbstractType& bound = | |
| 760 T.BuildTypeWithoutFinalization(); // read ith bound. | |
| 761 if (bound.IsMalformedOrMalbounded()) { | |
| 762 bound = I->object_store()->object_type(); | |
| 763 } | |
| 764 parameter.set_bound(bound); | |
| 765 } | |
| 766 } | |
| 767 } | |
| 768 | |
| 769 const Object& KernelReader::ClassForScriptAt(const Class& klass, | |
| 770 intptr_t source_uri_index) { | |
| 771 Script& correct_script = ScriptAt(source_uri_index); | |
| 772 if (klass.script() != correct_script.raw()) { | |
| 773 // Use cache for patch classes. This works best for in-order usages. | |
| 774 PatchClass& patch_class = PatchClass::ZoneHandle(Z); | |
| 775 patch_class ^= patch_classes_.At(source_uri_index); | |
| 776 if (patch_class.IsNull() || patch_class.origin_class() != klass.raw()) { | |
| 777 patch_class = PatchClass::New(klass, correct_script); | |
| 778 patch_classes_.SetAt(source_uri_index, patch_class); | |
| 779 } | |
| 780 return patch_class; | |
| 781 } | |
| 782 return klass; | |
| 783 } | |
| 784 | |
| 785 Script& KernelReader::ScriptAt(intptr_t index, StringIndex import_uri) { | |
| 786 Script& script = Script::ZoneHandle(Z); | |
| 787 script ^= scripts_.At(index); | |
| 788 if (script.IsNull()) { | |
| 789 // Create script with correct uri(s). | |
| 790 String& uri_string = builder_.SourceTableUriFor(index); | |
| 791 String& import_uri_string = | |
| 792 import_uri == -1 ? uri_string : H.DartString(import_uri, Heap::kOld); | |
| 793 script = Script::New(import_uri_string, uri_string, | |
| 794 builder_.GetSourceFor(index), RawScript::kKernelTag); | |
| 795 script.set_kernel_script_index(index); | |
| 796 script.set_kernel_string_offsets(H.string_offsets()); | |
| 797 script.set_kernel_string_data(H.string_data()); | |
| 798 script.set_kernel_canonical_names(H.canonical_names()); | |
| 799 scripts_.SetAt(index, script); | |
| 800 | |
| 801 script.set_line_starts(builder_.GetLineStartsFor(index)); | |
| 802 script.set_debug_positions(Array::Handle(Array::null())); | |
| 803 script.set_yield_positions(Array::Handle(Array::null())); | |
| 804 } | |
| 805 return script; | |
| 806 } | |
| 807 | |
| 808 void KernelReader::GenerateFieldAccessors(const Class& klass, | |
| 809 const Field& field, | |
| 810 FieldHelper* field_helper, | |
| 811 intptr_t field_offset) { | |
| 812 Tag tag = builder_.PeekTag(); | |
| 813 if (field_helper->IsStatic() && tag == kNothing) { | |
| 814 // Static fields without an initializer are implicitly initialized to null. | |
| 815 // We do not need a getter. | |
| 816 field.SetStaticValue(Instance::Handle(Z), true); | |
| 817 return; | |
| 818 } | |
| 819 if (tag == kSomething) { | |
| 820 SimpleExpressionConverter converter(&H, &builder_); | |
| 821 const bool has_simple_initializer = | |
| 822 converter.IsSimple(builder_.ReaderOffset() + 1); // ignore the tag. | |
| 823 if (field_helper->IsStatic()) { | |
| 824 // Static fields with initializers either have the static value set to the | |
| 825 // initializer value if it is simple enough or else set to an | |
| 826 // uninitialized sentinel. | |
| 827 if (has_simple_initializer) { | |
| 828 // We do not need a getter. | |
| 829 field.SetStaticValue(converter.SimpleValue(), true); | |
| 830 return; | |
| 831 } | |
| 832 // We do need a getter that evaluates the initializer if necessary. | |
| 833 field.SetStaticValue(Object::sentinel(), true); | |
| 834 } else if (has_simple_initializer) { | |
| 835 // Note: optimizer relies on DoubleInitialized bit in its field-unboxing | |
| 836 // heuristics. See JitOptimizer::VisitStoreInstanceField for more details. | |
| 837 field.RecordStore(converter.SimpleValue()); | |
| 838 if (!converter.SimpleValue().IsNull() && | |
| 839 converter.SimpleValue().IsDouble()) { | |
| 840 field.set_is_double_initialized(true); | |
| 841 } | |
| 842 } | |
| 843 } | |
| 844 | |
| 845 const String& getter_name = H.DartGetterName(field_helper->canonical_name_); | |
| 846 const Object& script_class = | |
| 847 ClassForScriptAt(klass, field_helper->source_uri_index_); | |
| 848 Function& getter = Function::ZoneHandle( | |
| 849 Z, | |
| 850 Function::New( | |
| 851 getter_name, | |
| 852 field_helper->IsStatic() ? RawFunction::kImplicitStaticFinalGetter | |
| 853 : RawFunction::kImplicitGetter, | |
| 854 field_helper->IsStatic(), | |
| 855 // The functions created by the parser have is_const for static fields | |
| 856 // that are const (not just final) and they have is_const for | |
| 857 // non-static | |
| 858 // fields that are final. | |
| 859 field_helper->IsStatic() ? field_helper->IsConst() | |
| 860 : field_helper->IsFinal(), | |
| 861 false, // is_abstract | |
| 862 false, // is_external | |
| 863 false, // is_native | |
| 864 script_class, field_helper->position_)); | |
| 865 functions_.Add(&getter); | |
| 866 getter.set_kernel_data(TypedData::Handle(Z, field.kernel_data())); | |
| 867 getter.set_end_token_pos(field_helper->end_position_); | |
| 868 getter.set_kernel_offset(field_offset); | |
| 869 getter.set_result_type(AbstractType::Handle(Z, field.type())); | |
| 870 getter.set_is_debuggable(false); | |
| 871 SetupFieldAccessorFunction(klass, getter); | |
| 872 | |
| 873 if (!field_helper->IsStatic() && !field_helper->IsFinal()) { | |
| 874 // Only static fields can be const. | |
| 875 ASSERT(!field_helper->IsConst()); | |
| 876 const String& setter_name = H.DartSetterName(field_helper->canonical_name_); | |
| 877 Function& setter = Function::ZoneHandle( | |
| 878 Z, Function::New(setter_name, RawFunction::kImplicitSetter, | |
| 879 false, // is_static | |
| 880 false, // is_const | |
| 881 false, // is_abstract | |
| 882 false, // is_external | |
| 883 false, // is_native | |
| 884 script_class, field_helper->position_)); | |
| 885 functions_.Add(&setter); | |
| 886 setter.set_kernel_data(TypedData::Handle(Z, field.kernel_data())); | |
| 887 setter.set_end_token_pos(field_helper->end_position_); | |
| 888 setter.set_kernel_offset(field_offset); | |
| 889 setter.set_result_type(Object::void_type()); | |
| 890 setter.set_is_debuggable(false); | |
| 891 SetupFieldAccessorFunction(klass, setter); | |
| 892 } | |
| 893 } | |
| 894 | |
| 895 void KernelReader::SetupFieldAccessorFunction(const Class& klass, | |
| 896 const Function& function) { | |
| 897 bool is_setter = function.IsImplicitSetterFunction(); | |
| 898 bool is_method = !function.IsStaticFunction(); | |
| 899 intptr_t parameter_count = (is_method ? 1 : 0) + (is_setter ? 1 : 0); | |
| 900 | |
| 901 function.SetNumOptionalParameters(0, false); | |
| 902 function.set_num_fixed_parameters(parameter_count); | |
| 903 function.set_parameter_types( | |
| 904 Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); | |
| 905 function.set_parameter_names( | |
| 906 Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); | |
| 907 | |
| 908 intptr_t pos = 0; | |
| 909 if (is_method) { | |
| 910 function.SetParameterTypeAt(pos, T.ReceiverType(klass)); | |
| 911 function.SetParameterNameAt(pos, Symbols::This()); | |
| 912 pos++; | |
| 913 } | |
| 914 if (is_setter) { | |
| 915 function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); | |
| 916 function.SetParameterNameAt(pos, Symbols::Value()); | |
| 917 pos++; | |
| 918 } | |
| 919 } | |
| 920 | |
| 921 Library& KernelReader::LookupLibrary(NameIndex library) { | |
| 922 Library* handle = NULL; | |
| 923 if (!libraries_.Lookup(library, &handle)) { | |
| 924 const String& url = H.DartSymbol(H.CanonicalNameString(library)); | |
| 925 handle = &Library::Handle(Z, Library::LookupLibrary(thread_, url)); | |
| 926 if (handle->IsNull()) { | |
| 927 *handle = Library::New(url); | |
| 928 handle->Register(thread_); | |
| 929 } | |
| 930 ASSERT(!handle->IsNull()); | |
| 931 libraries_.Insert(library, handle); | |
| 932 } | |
| 933 return *handle; | |
| 934 } | |
| 935 | |
| 936 Class& KernelReader::LookupClass(NameIndex klass) { | |
| 937 Class* handle = NULL; | |
| 938 if (!classes_.Lookup(klass, &handle)) { | |
| 939 Library& library = LookupLibrary(H.CanonicalNameParent(klass)); | |
| 940 const String& name = H.DartClassName(klass); | |
| 941 handle = &Class::Handle(Z, library.LookupClass(name)); | |
| 942 if (handle->IsNull()) { | |
| 943 *handle = Class::New(library, name, Script::Handle(Z), | |
| 944 TokenPosition::kNoSource); | |
| 945 library.AddClass(*handle); | |
| 946 } | |
| 947 // Insert the class in the cache before calling ReadPreliminaryClass so | |
| 948 // we do not risk allocating the class again by calling LookupClass | |
| 949 // recursively from ReadPreliminaryClass for the same class. | |
| 950 classes_.Insert(klass, handle); | |
| 951 } | |
| 952 return *handle; | |
| 953 } | |
| 954 | |
| 955 RawFunction::Kind KernelReader::GetFunctionType( | |
| 956 ProcedureHelper::Kind procedure_kind) { | |
| 957 intptr_t lookuptable[] = { | |
| 958 RawFunction::kRegularFunction, // Procedure::kMethod | |
| 959 RawFunction::kGetterFunction, // Procedure::kGetter | |
| 960 RawFunction::kSetterFunction, // Procedure::kSetter | |
| 961 RawFunction::kRegularFunction, // Procedure::kOperator | |
| 962 RawFunction::kConstructor, // Procedure::kFactory | |
| 963 }; | |
| 964 intptr_t kind = static_cast<int>(procedure_kind); | |
| 965 ASSERT(0 <= kind && kind <= ProcedureHelper::kFactory); | |
| 966 return static_cast<RawFunction::Kind>(lookuptable[kind]); | |
| 967 } | |
| 968 | |
| 969 bool KernelReader::FieldHasFunctionLiteralInitializer(const Field& field, | |
| 970 TokenPosition* start, | |
| 971 TokenPosition* end) { | |
| 972 Zone* zone = Thread::Current()->zone(); | |
| 973 const Script& script = Script::Handle(zone, field.Script()); | |
| 974 | |
| 975 TranslationHelper translation_helper( | |
| 976 Thread::Current(), script.kernel_string_offsets(), | |
| 977 script.kernel_string_data(), script.kernel_canonical_names()); | |
| 978 | |
| 979 StreamingFlowGraphBuilder builder( | |
| 980 &translation_helper, zone, field.kernel_offset(), | |
| 981 TypedData::Handle(zone, field.kernel_data())); | |
| 982 kernel::FieldHelper field_helper(&builder); | |
| 983 field_helper.ReadUntilExcluding(kernel::FieldHelper::kEnd, true); | |
| 984 return field_helper.FieldHasFunctionLiteralInitializer(start, end); | |
| 985 } | |
| 986 | |
| 987 ParsedFunction* ParseStaticFieldInitializer(Zone* zone, const Field& field) { | |
| 988 Thread* thread = Thread::Current(); | |
| 989 | |
| 990 String& init_name = String::Handle(zone, field.name()); | |
| 991 init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name); | |
| 992 | |
| 993 // Create a static initializer. | |
| 994 const Object& owner = Object::Handle(field.RawOwner()); | |
| 995 const Function& initializer_fun = Function::ZoneHandle( | |
| 996 zone, Function::New(init_name, RawFunction::kImplicitStaticFinalGetter, | |
| 997 true, // is_static | |
| 998 false, // is_const | |
| 999 false, // is_abstract | |
| 1000 false, // is_external | |
| 1001 false, // is_native | |
| 1002 owner, TokenPosition::kNoSource)); | |
| 1003 initializer_fun.set_kernel_data(TypedData::Handle(zone, field.kernel_data())); | |
| 1004 initializer_fun.set_kernel_offset(field.kernel_offset()); | |
| 1005 initializer_fun.set_result_type(AbstractType::Handle(zone, field.type())); | |
| 1006 initializer_fun.set_is_debuggable(false); | |
| 1007 initializer_fun.set_is_reflectable(false); | |
| 1008 initializer_fun.set_is_inlinable(false); | |
| 1009 return new (zone) ParsedFunction(thread, initializer_fun); | |
| 1010 } | |
| 1011 | |
| 1012 } // namespace kernel | |
| 1013 } // namespace dart | |
| 1014 #endif // !defined(DART_PRECOMPILED_RUNTIME) | |
| OLD | NEW |