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/dil_reader.h" |
| 6 |
| 7 #include <string.h> |
| 8 |
| 9 #include "vm/dart_api_impl.h" |
| 10 #include "vm/longjump.h" |
| 11 #include "vm/object_store.h" |
| 12 #include "vm/parser.h" |
| 13 #include "vm/symbols.h" |
| 14 |
| 15 namespace dart { |
| 16 namespace dil { |
| 17 |
| 18 #define Z (zone_) |
| 19 #define I (isolate_) |
| 20 #define T (type_translator_) |
| 21 #define H (translation_helper_) |
| 22 |
| 23 // FIXME(kustermann): We should add support for type conversion to annotate |
| 24 // fields/parameters/variables with proper types. |
| 25 |
| 26 |
| 27 class SimpleExpressionConverter : public ExpressionVisitor { |
| 28 public: |
| 29 SimpleExpressionConverter(Thread* thread, Zone* zone) |
| 30 : translation_helper_(thread, zone, NULL), |
| 31 zone_(zone), |
| 32 is_simple_(false), |
| 33 simple_value_(NULL) {} |
| 34 |
| 35 virtual void VisitDefaultExpression(Expression* node) { is_simple_ = false; } |
| 36 |
| 37 virtual void VisitIntLiteral(IntLiteral* node) { |
| 38 is_simple_ = true; |
| 39 simple_value_ = |
| 40 &Integer::ZoneHandle(Z, Integer::New(node->value(), Heap::kOld)); |
| 41 *simple_value_ = H.Canonicalize(*simple_value_); |
| 42 } |
| 43 |
| 44 virtual void VisitBigintLiteral(BigintLiteral* node) { |
| 45 is_simple_ = true; |
| 46 simple_value_ = &Integer::ZoneHandle( |
| 47 Z, Integer::New(H.DartString(node->value(), Heap::kOld))); |
| 48 *simple_value_ = H.Canonicalize(*simple_value_); |
| 49 } |
| 50 |
| 51 virtual void VisitDoubleLiteral(DoubleLiteral* node) { |
| 52 is_simple_ = true; |
| 53 simple_value_ = &Double::ZoneHandle( |
| 54 Z, Double::New(H.DartString(node->value()), Heap::kOld)); |
| 55 *simple_value_ = H.Canonicalize(*simple_value_); |
| 56 } |
| 57 |
| 58 virtual void VisitBoolLiteral(BoolLiteral* node) { |
| 59 is_simple_ = true; |
| 60 simple_value_ = &Bool::Handle(Z, Bool::Get(node->value()).raw()); |
| 61 } |
| 62 |
| 63 virtual void VisitNullLiteral(NullLiteral* node) { |
| 64 is_simple_ = true; |
| 65 simple_value_ = &dart::Instance::ZoneHandle(Z, dart::Instance::null()); |
| 66 } |
| 67 |
| 68 virtual void VisitStringLiteral(StringLiteral* node) { |
| 69 is_simple_ = true; |
| 70 simple_value_ = &H.DartSymbol(node->value()); |
| 71 } |
| 72 |
| 73 bool IsSimple(Expression* expression) { |
| 74 expression->AcceptExpressionVisitor(this); |
| 75 return is_simple_; |
| 76 } |
| 77 |
| 78 const dart::Instance& SimpleValue() { return *simple_value_; } |
| 79 |
| 80 private: |
| 81 TranslationHelper translation_helper_; |
| 82 dart::Zone* zone_; |
| 83 bool is_simple_; |
| 84 dart::Instance* simple_value_; |
| 85 }; |
| 86 |
| 87 void BuildingTranslationHelper::SetFinalize(bool finalize) { |
| 88 reader_->finalize_ = finalize; |
| 89 } |
| 90 |
| 91 RawLibrary* BuildingTranslationHelper::LookupLibraryByDilLibrary( |
| 92 Library* library) { |
| 93 return reader_->LookupLibrary(library).raw(); |
| 94 } |
| 95 |
| 96 RawClass* BuildingTranslationHelper::LookupClassByDilClass(Class* klass) { |
| 97 return reader_->LookupClass(klass).raw(); |
| 98 } |
| 99 |
| 100 Object& DilReader::ReadProgram() { |
| 101 ASSERT(!bootstrapping_); |
| 102 Program* program = ReadPrecompiledDilFromBuffer(buffer_, buffer_length_); |
| 103 if (program == NULL) { |
| 104 const dart::String& error = H.DartString("Failed to read .dill file"); |
| 105 return Object::Handle(Z, ApiError::New(error)); |
| 106 } |
| 107 |
| 108 LongJumpScope jump; |
| 109 if (setjmp(*jump.Set()) == 0) { |
| 110 Procedure* main = program->main_method(); |
| 111 Library* dil_main_library = Library::Cast(main->parent()); |
| 112 |
| 113 intptr_t length = program->libraries().length(); |
| 114 for (intptr_t i = 0; i < length; i++) { |
| 115 Library* dil_library = program->libraries()[i]; |
| 116 ReadLibrary(dil_library); |
| 117 } |
| 118 |
| 119 // We finalize classes after we've constructed all classes since we |
| 120 // currently don't construct them in pre-order of the class hierarchy (and |
| 121 // finalization of a class needs all of its superclasses to be finalized). |
| 122 dart::String& name = dart::String::Handle(); |
| 123 for (intptr_t i = 0; i < length; i++) { |
| 124 Library* dil_library = program->libraries()[i]; |
| 125 dart::Library& library = LookupLibrary(dil_library); |
| 126 name = library.url(); |
| 127 |
| 128 // TODO(vegorov) unskip this library when we fix underlying issue. |
| 129 if (name.Equals("dart:vmservice_io")) { |
| 130 continue; |
| 131 } |
| 132 |
| 133 if (!library.Loaded()) { |
| 134 dart::Class& klass = dart::Class::Handle(Z); |
| 135 for (intptr_t i = 0; i < dil_library->classes().length(); i++) { |
| 136 klass = LookupClass(dil_library->classes()[i]).raw(); |
| 137 ClassFinalizer::FinalizeTypesInClass(klass); |
| 138 ClassFinalizer::FinalizeClass(klass); |
| 139 } |
| 140 library.SetLoaded(); |
| 141 } |
| 142 } |
| 143 |
| 144 dart::Library& library = LookupLibrary(dil_main_library); |
| 145 |
| 146 // Sanity check that we can find the main entrypoint. |
| 147 Object& main_obj = Object::Handle( |
| 148 Z, library.LookupObjectAllowPrivate(H.DartSymbol("main"))); |
| 149 ASSERT(!main_obj.IsNull()); |
| 150 return library; |
| 151 } else { |
| 152 // Everything else is a compile-time error. We don't use the [error] since |
| 153 // it sometimes causes the higher-level error handling to try to read the |
| 154 // script and token position (which we don't have) to produce a nice error |
| 155 // message. |
| 156 Error& error = Error::Handle(Z); |
| 157 error = thread_->sticky_error(); |
| 158 thread_->clear_sticky_error(); |
| 159 |
| 160 // Instead we simply make a non-informative error message. |
| 161 const dart::String& error_message = |
| 162 H.DartString("Failed to read .dill file => CompileTimeError."); |
| 163 return Object::Handle(Z, LanguageError::New(error_message)); |
| 164 } |
| 165 } |
| 166 |
| 167 void DilReader::ReadLibrary(Library* dil_library) { |
| 168 dart::Library& library = LookupLibrary(dil_library); |
| 169 if (library.Loaded()) return; |
| 170 |
| 171 // The bootstrapper will take care of creating the native wrapper classes, but |
| 172 // we will add the synthetic constructors to them here. |
| 173 if (library.name() == |
| 174 Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).raw()) { |
| 175 ASSERT(library.LoadInProgress()); |
| 176 } else { |
| 177 library.SetLoadInProgress(); |
| 178 } |
| 179 // Setup toplevel class (which contains library fields/procedures). |
| 180 |
| 181 // FIXME(kustermann): Figure out why we need this script stuff here. |
| 182 Script& script = Script::Handle( |
| 183 Z, |
| 184 Script::New(H.DartString(""), H.DartString(""), RawScript::kScriptTag)); |
| 185 script.SetLocationOffset(0, 0); |
| 186 script.Tokenize(H.DartString("nop() {}")); |
| 187 dart::Class& toplevel_class = dart::Class::Handle(dart::Class::New( |
| 188 library, Symbols::TopLevel(), script, TokenPosition::kNoSource)); |
| 189 toplevel_class.set_is_cycle_free(); |
| 190 library.set_toplevel_class(toplevel_class); |
| 191 if (bootstrapping_) { |
| 192 GrowableObjectArray::Handle(I->object_store()->pending_classes()) |
| 193 .Add(toplevel_class, Heap::kOld); |
| 194 } |
| 195 |
| 196 ActiveClassScope active_class_scope(&active_class_, NULL, &toplevel_class); |
| 197 // Load toplevel fields. |
| 198 for (intptr_t i = 0; i < dil_library->fields().length(); i++) { |
| 199 Field* dil_field = dil_library->fields()[i]; |
| 200 |
| 201 ActiveMemberScope active_member_scope(&active_class_, dil_field); |
| 202 const dart::String& name = H.DartFieldName(dil_field->name()); |
| 203 dart::Field& field = dart::Field::Handle( |
| 204 Z, dart::Field::NewTopLevel(name, dil_field->IsFinal(), |
| 205 dil_field->IsConst(), toplevel_class, |
| 206 TokenPosition::kNoSource)); |
| 207 field.set_dil_field(reinterpret_cast<intptr_t>(dil_field)); |
| 208 const AbstractType& type = T.TranslateType(dil_field->type()); |
| 209 field.SetFieldType(type); |
| 210 field.set_has_initializer(dil_field->initializer() != NULL); |
| 211 GenerateFieldAccessors(toplevel_class, field, dil_field); |
| 212 toplevel_class.AddField(field); |
| 213 library.AddObject(field, name); |
| 214 } |
| 215 |
| 216 // Load toplevel procedures. |
| 217 for (intptr_t i = 0; i < dil_library->procedures().length(); i++) { |
| 218 Procedure* dil_procedure = dil_library->procedures()[i]; |
| 219 ReadProcedure(library, toplevel_class, dil_procedure); |
| 220 } |
| 221 |
| 222 // Load all classes. |
| 223 for (intptr_t i = 0; i < dil_library->classes().length(); i++) { |
| 224 Class* dil_klass = dil_library->classes()[i]; |
| 225 ReadClass(library, dil_klass); |
| 226 } |
| 227 } |
| 228 |
| 229 void DilReader::ReadPreliminaryClass(dart::Class* klass, Class* dil_klass) { |
| 230 ActiveClassScope active_class_scope(&active_class_, dil_klass, klass); |
| 231 |
| 232 // First setup the type parameters, so if any of the following code uses it |
| 233 // (in a recursive way) we're fine. |
| 234 TypeArguments& type_parameters = |
| 235 TypeArguments::Handle(Z, TypeArguments::null()); |
| 236 intptr_t num_type_parameters = dil_klass->type_parameters().length(); |
| 237 if (num_type_parameters > 0) { |
| 238 dart::TypeParameter& parameter = dart::TypeParameter::Handle(Z); |
| 239 Type& null_bound = Type::Handle(Z, Type::null()); |
| 240 |
| 241 // Step a) Create array of [TypeParameter] objects (without bound). |
| 242 type_parameters = TypeArguments::New(num_type_parameters); |
| 243 for (intptr_t i = 0; i < num_type_parameters; i++) { |
| 244 parameter = dart::TypeParameter::New( |
| 245 *klass, Function::Handle(Z), i, |
| 246 H.DartSymbol(dil_klass->type_parameters()[i]->name()), null_bound, |
| 247 TokenPosition::kNoSource); |
| 248 type_parameters.SetTypeAt(i, parameter); |
| 249 } |
| 250 klass->set_type_parameters(type_parameters); |
| 251 |
| 252 // Step b) Fill in the bounds of all [TypeParameter]s. |
| 253 for (intptr_t i = 0; i < num_type_parameters; i++) { |
| 254 TypeParameter* dil_parameter = dil_klass->type_parameters()[i]; |
| 255 // There is no dynamic bound, only Object. |
| 256 // TODO(kustermann): Should we fix this in the kernel IR generator? |
| 257 if (dil_parameter->bound()->IsDynamicType()) { |
| 258 parameter ^= type_parameters.TypeAt(i); |
| 259 parameter.set_bound(Type::Handle(Z, I->object_store()->object_type())); |
| 260 } else { |
| 261 AbstractType& bound = |
| 262 T.TranslateTypeWithoutFinalization(dil_parameter->bound()); |
| 263 if (bound.IsMalformedOrMalbounded()) { |
| 264 bound = I->object_store()->object_type(); |
| 265 } |
| 266 |
| 267 parameter ^= type_parameters.TypeAt(i); |
| 268 parameter.set_bound(bound); |
| 269 } |
| 270 } |
| 271 } |
| 272 |
| 273 if (dil_klass->IsNormalClass()) { |
| 274 NormalClass* dil_normal_class = NormalClass::Cast(dil_klass); |
| 275 |
| 276 // Set super type. Some classes (e.g., Object) do not have one. |
| 277 if (dil_normal_class->super_class() != NULL) { |
| 278 AbstractType& super_type = |
| 279 T.TranslateTypeWithoutFinalization(dil_normal_class->super_class()); |
| 280 if (super_type.IsMalformed()) H.ReportError("Malformed super type"); |
| 281 klass->set_super_type(super_type); |
| 282 } |
| 283 } else { |
| 284 MixinClass* dil_mixin = MixinClass::Cast(dil_klass); |
| 285 |
| 286 // Set super type. |
| 287 AbstractType& super_type = |
| 288 T.TranslateTypeWithoutFinalization(dil_mixin->first()); |
| 289 if (super_type.IsMalformed()) H.ReportError("Malformed super type."); |
| 290 klass->set_super_type(super_type); |
| 291 |
| 292 // Tell the rest of the system there is nothing to resolve. |
| 293 super_type.SetIsResolved(); |
| 294 |
| 295 // Set mixin type. |
| 296 AbstractType& mixin_type = |
| 297 T.TranslateTypeWithoutFinalization(dil_mixin->second()); |
| 298 if (mixin_type.IsMalformed()) H.ReportError("Malformed mixin type."); |
| 299 klass->set_mixin(Type::Cast(mixin_type)); |
| 300 } |
| 301 |
| 302 // Build implemented interface types |
| 303 intptr_t interface_count = dil_klass->implemented_classes().length(); |
| 304 const dart::Array& interfaces = |
| 305 dart::Array::Handle(Z, dart::Array::New(interface_count)); |
| 306 dart::Class& interface_class = dart::Class::Handle(Z); |
| 307 for (intptr_t i = 0; i < interface_count; i++) { |
| 308 InterfaceType* dil_interface_type = dil_klass->implemented_classes()[i]; |
| 309 const AbstractType& type = |
| 310 T.TranslateTypeWithoutFinalization(dil_interface_type); |
| 311 if (type.IsMalformed()) H.ReportError("Malformed interface type."); |
| 312 interfaces.SetAt(i, type); |
| 313 |
| 314 // NOTE: Normally the DartVM keeps a list of pending classes and iterates |
| 315 // through them later on using `ClassFinalizer::ProcessPendingClasses()`. |
| 316 // This involes calling `ClassFinalizer::ResolveSuperTypeAndInterfaces()` |
| 317 // which does a lot of error validation (e.g. cycle checks) which we don't |
| 318 // need here. But we do need to do one thing which this resolving phase |
| 319 // normally does for us: set the `is_implemented` boolean. |
| 320 |
| 321 // TODO(kustermann): Maybe we can do this differently once we have |
| 322 // "bootstrapping from dill"-support. |
| 323 interface_class = type.type_class(); |
| 324 interface_class.set_is_implemented(); |
| 325 } |
| 326 klass->set_interfaces(interfaces); |
| 327 if (dil_klass->is_abstract()) klass->set_is_abstract(); |
| 328 klass->set_is_cycle_free(); |
| 329 |
| 330 // When bootstrapping we should not finalize types yet because they will be |
| 331 // finalized when the object store's pending_classes list is drained by |
| 332 // ClassFinalizer::ProcessPendingClasses. Even when not bootstrapping we are |
| 333 // careful not to eagerly finalize types that may introduce a circularity |
| 334 // (such as type arguments, interface types, field types, etc.). |
| 335 if (finalize_) ClassFinalizer::FinalizeTypesInClass(*klass); |
| 336 } |
| 337 |
| 338 void DilReader::ReadClass(const dart::Library& library, Class* dil_klass) { |
| 339 // This will trigger a call to [ReadPreliminaryClass] if not already done. |
| 340 dart::Class& klass = LookupClass(dil_klass); |
| 341 |
| 342 ActiveClassScope active_class_scope(&active_class_, dil_klass, &klass); |
| 343 |
| 344 TokenPosition pos(0); |
| 345 |
| 346 for (intptr_t i = 0; i < dil_klass->fields().length(); i++) { |
| 347 Field* dil_field = dil_klass->fields()[i]; |
| 348 ActiveMemberScope active_member_scope(&active_class_, dil_field); |
| 349 |
| 350 const dart::String& name = H.DartFieldName(dil_field->name()); |
| 351 // TODO(vegorov) check if this might have some ordering issues |
| 352 // e.g. addressing types that are not loaded yet. |
| 353 const AbstractType& type = |
| 354 T.TranslateTypeWithoutFinalization(dil_field->type()); |
| 355 dart::Field& field = dart::Field::Handle( |
| 356 Z, dart::Field::New(name, dil_field->IsStatic(), |
| 357 // In the VM all const fields are implicitly final |
| 358 // whereas in Kernel they are not final because they |
| 359 // are not explicitly declared that way. |
| 360 dil_field->IsFinal() || dil_field->IsConst(), |
| 361 dil_field->IsConst(), |
| 362 false, // is_reflectable |
| 363 klass, type, pos)); |
| 364 field.set_dil_field(reinterpret_cast<intptr_t>(dil_field)); |
| 365 field.set_has_initializer(dil_field->initializer() != NULL); |
| 366 GenerateFieldAccessors(klass, field, dil_field); |
| 367 klass.AddField(field); |
| 368 } |
| 369 |
| 370 for (intptr_t i = 0; i < dil_klass->constructors().length(); i++) { |
| 371 Constructor* dil_constructor = dil_klass->constructors()[i]; |
| 372 ActiveMemberScope active_member_scope(&active_class_, dil_constructor); |
| 373 ActiveFunctionScope active_function_scope(&active_class_, |
| 374 dil_constructor->function()); |
| 375 |
| 376 const dart::String& name = H.DartConstructorName(dil_constructor); |
| 377 Function& function = dart::Function::ZoneHandle( |
| 378 Z, dart::Function::New(name, RawFunction::kConstructor, |
| 379 false, // is_static |
| 380 dil_constructor->IsConst(), |
| 381 false, // is_abstract |
| 382 dil_constructor->IsExternal(), |
| 383 false, // is_native |
| 384 klass, pos)); |
| 385 klass.AddFunction(function); |
| 386 function.set_dil_function(reinterpret_cast<intptr_t>(dil_constructor)); |
| 387 function.set_result_type(T.ReceiverType(klass)); |
| 388 SetupFunctionParameters(H, T, klass, function, dil_constructor->function(), |
| 389 true, // is_method |
| 390 false); // is_closure |
| 391 } |
| 392 |
| 393 for (intptr_t i = 0; i < dil_klass->procedures().length(); i++) { |
| 394 Procedure* dil_procedure = dil_klass->procedures()[i]; |
| 395 ActiveMemberScope active_member_scope(&active_class_, dil_procedure); |
| 396 ReadProcedure(library, klass, dil_procedure, dil_klass); |
| 397 } |
| 398 |
| 399 if (bootstrapping_ && !klass.is_marked_for_parsing()) { |
| 400 klass.set_is_marked_for_parsing(); |
| 401 GrowableObjectArray::Handle(Z, I->object_store()->pending_classes()) |
| 402 .Add(klass, Heap::kOld); |
| 403 } |
| 404 } |
| 405 |
| 406 void DilReader::ReadProcedure(const dart::Library& library, |
| 407 const dart::Class& owner, |
| 408 Procedure* dil_procedure, Class* dil_klass) { |
| 409 ActiveClassScope active_class_scope(&active_class_, dil_klass, &owner); |
| 410 ActiveMemberScope active_member_scope(&active_class_, dil_procedure); |
| 411 ActiveFunctionScope active_function_scope(&active_class_, |
| 412 dil_procedure->function()); |
| 413 |
| 414 const dart::String& name = H.DartProcedureName(dil_procedure); |
| 415 TokenPosition pos(0); |
| 416 bool is_method = dil_klass != NULL && !dil_procedure->IsStatic(); |
| 417 bool is_abstract = dil_procedure->IsAbstract(); |
| 418 bool is_external = dil_procedure->IsExternal(); |
| 419 dart::String* native_name = NULL; |
| 420 if (is_external) { |
| 421 // Maybe it has a native implementation, which is not external as far as |
| 422 // the VM is concerned because it does have an implementation. Check for |
| 423 // an ExternalName annotation and extract the string from it. |
| 424 for (int i = 0; i < dil_procedure->annotations().length(); ++i) { |
| 425 Expression* annotation = dil_procedure->annotations()[i]; |
| 426 if (!annotation->IsConstructorInvocation()) continue; |
| 427 ConstructorInvocation* invocation = |
| 428 ConstructorInvocation::Cast(annotation); |
| 429 Class* annotation_class = Class::Cast(invocation->target()->parent()); |
| 430 String* class_name = annotation_class->name(); |
| 431 // Just compare by name, do not generate the annotation class. |
| 432 int length = sizeof("ExternalName") - 1; |
| 433 if (class_name->size() != length) continue; |
| 434 if (memcmp(class_name->buffer(), "ExternalName", length) != 0) continue; |
| 435 String* library_name = annotation_class->parent()->name(); |
| 436 length = sizeof("dart._internal") - 1; |
| 437 if (library_name->size() != length) continue; |
| 438 if (memcmp(library_name->buffer(), "dart._internal", length) != 0) { |
| 439 continue; |
| 440 } |
| 441 |
| 442 is_external = false; |
| 443 ASSERT(invocation->arguments()->positional().length() == 1 && |
| 444 invocation->arguments()->named().length() == 0); |
| 445 StringLiteral* literal = |
| 446 StringLiteral::Cast(invocation->arguments()->positional()[0]); |
| 447 native_name = &H.DartSymbol(literal->value()); |
| 448 break; |
| 449 } |
| 450 } |
| 451 dart::Function& function = dart::Function::ZoneHandle( |
| 452 Z, Function::New(name, GetFunctionType(dil_procedure), |
| 453 !is_method, // is_static |
| 454 false, // is_const |
| 455 is_abstract, is_external, |
| 456 native_name != NULL, // is_native |
| 457 owner, pos)); |
| 458 owner.AddFunction(function); |
| 459 function.set_dil_function(reinterpret_cast<intptr_t>(dil_procedure)); |
| 460 function.set_is_debuggable(false); |
| 461 if (native_name != NULL) { |
| 462 function.set_native_name(*native_name); |
| 463 } |
| 464 |
| 465 SetupFunctionParameters(H, T, owner, function, dil_procedure->function(), |
| 466 is_method, |
| 467 false); // is_closure |
| 468 |
| 469 if (dil_klass == NULL) { |
| 470 library.AddObject(function, name); |
| 471 ASSERT(!Object::Handle(library.LookupObjectAllowPrivate( |
| 472 H.DartProcedureName(dil_procedure))) |
| 473 .IsNull()); |
| 474 } |
| 475 } |
| 476 |
| 477 void DilReader::GenerateFieldAccessors(const dart::Class& klass, |
| 478 const dart::Field& field, |
| 479 Field* dil_field) { |
| 480 TokenPosition pos(0); |
| 481 |
| 482 if (dil_field->IsStatic() && dil_field->initializer() != NULL) { |
| 483 // Static fields with initializers either have the static value set to the |
| 484 // initializer value if it is simple enough or else set to an uninitialized |
| 485 // sentinel. |
| 486 SimpleExpressionConverter converter(H.thread(), Z); |
| 487 if (converter.IsSimple(dil_field->initializer())) { |
| 488 // We do not need a getter. |
| 489 field.SetStaticValue(converter.SimpleValue(), true); |
| 490 return; |
| 491 } |
| 492 // We do need a getter that evaluates the initializer if necessary. |
| 493 field.SetStaticValue(Object::sentinel(), true); |
| 494 } |
| 495 |
| 496 const dart::String& getter_name = H.DartGetterName(dil_field->name()); |
| 497 Function& getter = Function::ZoneHandle( |
| 498 Z, |
| 499 Function::New( |
| 500 getter_name, |
| 501 dil_field->IsStatic() ? RawFunction::kImplicitStaticFinalGetter |
| 502 : RawFunction::kImplicitGetter, |
| 503 dil_field->IsStatic(), |
| 504 // The functions created by the parser have is_const for static fields |
| 505 // that are const (not just final) and they have is_const for |
| 506 // non-static |
| 507 // fields that are final. |
| 508 dil_field->IsStatic() ? dil_field->IsConst() : dil_field->IsFinal(), |
| 509 false, // is_abstract |
| 510 false, // is_external |
| 511 false, // is_native |
| 512 klass, pos)); |
| 513 klass.AddFunction(getter); |
| 514 if (klass.IsTopLevel()) { |
| 515 dart::Library& library = dart::Library::Handle(Z, klass.library()); |
| 516 library.AddObject(getter, getter_name); |
| 517 } |
| 518 getter.set_dil_function(reinterpret_cast<intptr_t>(dil_field)); |
| 519 getter.set_result_type(AbstractType::Handle(Z, field.type())); |
| 520 getter.set_is_debuggable(false); |
| 521 SetupFieldAccessorFunction(klass, getter); |
| 522 |
| 523 if (!dil_field->IsStatic() && !dil_field->IsFinal()) { |
| 524 // Only static fields can be const. |
| 525 ASSERT(!dil_field->IsConst()); |
| 526 const dart::String& setter_name = H.DartSetterName(dil_field->name()); |
| 527 Function& setter = Function::ZoneHandle( |
| 528 Z, Function::New(setter_name, RawFunction::kImplicitSetter, |
| 529 false, // is_static |
| 530 false, // is_const |
| 531 false, // is_abstract |
| 532 false, // is_external |
| 533 false, // is_native |
| 534 klass, pos)); |
| 535 klass.AddFunction(setter); |
| 536 setter.set_dil_function(reinterpret_cast<intptr_t>(dil_field)); |
| 537 setter.set_result_type(Object::void_type()); |
| 538 setter.set_is_debuggable(false); |
| 539 SetupFieldAccessorFunction(klass, setter); |
| 540 } |
| 541 } |
| 542 |
| 543 void DilReader::SetupFunctionParameters(TranslationHelper translation_helper_, |
| 544 DartTypeTranslator type_translator_, |
| 545 const dart::Class& klass, |
| 546 const dart::Function& function, |
| 547 FunctionNode* node, bool is_method, |
| 548 bool is_closure) { |
| 549 ASSERT(!(is_method && is_closure)); |
| 550 bool is_factory = function.IsFactory(); |
| 551 intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0; |
| 552 |
| 553 function.set_num_fixed_parameters(extra_parameters + |
| 554 node->required_parameter_count()); |
| 555 if (node->named_parameters().length() > 0) { |
| 556 function.SetNumOptionalParameters(node->named_parameters().length(), false); |
| 557 } else { |
| 558 function.SetNumOptionalParameters(node->positional_parameters().length() - |
| 559 node->required_parameter_count(), |
| 560 true); |
| 561 } |
| 562 intptr_t num_parameters = extra_parameters + |
| 563 node->positional_parameters().length() + |
| 564 node->named_parameters().length(); |
| 565 function.set_parameter_types( |
| 566 Array::Handle(Array::New(num_parameters, Heap::kOld))); |
| 567 function.set_parameter_names( |
| 568 Array::Handle(Array::New(num_parameters, Heap::kOld))); |
| 569 intptr_t pos = 0; |
| 570 if (is_method) { |
| 571 ASSERT(!klass.IsNull()); |
| 572 function.SetParameterTypeAt(pos, H.GetCanonicalType(klass)); |
| 573 function.SetParameterNameAt(pos, Symbols::This()); |
| 574 pos++; |
| 575 } else if (is_closure) { |
| 576 function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
| 577 function.SetParameterNameAt(pos, Symbols::ClosureParameter()); |
| 578 pos++; |
| 579 } else if (is_factory) { |
| 580 function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
| 581 function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter()); |
| 582 pos++; |
| 583 } |
| 584 for (intptr_t i = 0; i < node->positional_parameters().length(); i++, pos++) { |
| 585 VariableDeclaration* dil_variable = node->positional_parameters()[i]; |
| 586 const AbstractType& type = T.TranslateType(dil_variable->type()); |
| 587 function.SetParameterTypeAt( |
| 588 pos, type.IsMalformed() ? Type::dynamic_type() : type); |
| 589 function.SetParameterNameAt(pos, H.DartSymbol(dil_variable->name())); |
| 590 } |
| 591 for (intptr_t i = 0; i < node->named_parameters().length(); i++, pos++) { |
| 592 VariableDeclaration* named_expression = node->named_parameters()[i]; |
| 593 const AbstractType& type = T.TranslateType(named_expression->type()); |
| 594 function.SetParameterTypeAt( |
| 595 pos, type.IsMalformed() ? Type::dynamic_type() : type); |
| 596 function.SetParameterNameAt(pos, H.DartSymbol(named_expression->name())); |
| 597 } |
| 598 |
| 599 const AbstractType& return_type = T.TranslateType(node->return_type()); |
| 600 function.set_result_type(return_type.IsMalformed() ? Type::dynamic_type() |
| 601 : return_type); |
| 602 } |
| 603 |
| 604 void DilReader::SetupFieldAccessorFunction(const dart::Class& klass, |
| 605 const dart::Function& function) { |
| 606 bool is_setter = function.IsImplicitSetterFunction(); |
| 607 bool is_method = !function.IsStaticFunction(); |
| 608 intptr_t num_parameters = (is_method ? 1 : 0) + (is_setter ? 1 : 0); |
| 609 |
| 610 function.SetNumOptionalParameters(0, false); |
| 611 function.set_num_fixed_parameters(num_parameters); |
| 612 function.set_parameter_types( |
| 613 Array::Handle(Array::New(num_parameters, Heap::kOld))); |
| 614 function.set_parameter_names( |
| 615 Array::Handle(Array::New(num_parameters, Heap::kOld))); |
| 616 |
| 617 intptr_t pos = 0; |
| 618 if (is_method) { |
| 619 function.SetParameterTypeAt(pos, T.ReceiverType(klass)); |
| 620 function.SetParameterNameAt(pos, Symbols::This()); |
| 621 pos++; |
| 622 } |
| 623 if (is_setter) { |
| 624 function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
| 625 function.SetParameterNameAt(pos, Symbols::Value()); |
| 626 pos++; |
| 627 } |
| 628 } |
| 629 |
| 630 dart::Library& DilReader::LookupLibrary(Library* library) { |
| 631 dart::Library* handle = NULL; |
| 632 if (!libraries_.Lookup(library, &handle)) { |
| 633 const dart::String& url = H.DartSymbol(library->import_uri()); |
| 634 handle = |
| 635 &dart::Library::Handle(Z, dart::Library::LookupLibrary(thread_, url)); |
| 636 if (handle->IsNull()) { |
| 637 *handle = dart::Library::New(url); |
| 638 handle->Register(thread_); |
| 639 } |
| 640 ASSERT(!handle->IsNull()); |
| 641 libraries_.Insert(library, handle); |
| 642 } |
| 643 return *handle; |
| 644 } |
| 645 |
| 646 dart::Class& DilReader::LookupClass(Class* klass) { |
| 647 dart::Class* handle = NULL; |
| 648 if (!classes_.Lookup(klass, &handle)) { |
| 649 dart::Library& library = LookupLibrary(klass->parent()); |
| 650 const dart::String& name = H.DartClassName(klass); |
| 651 handle = &dart::Class::Handle(Z, library.LookupClass(name)); |
| 652 if (handle->IsNull()) { |
| 653 // The class needs to have a script because all the functions in the class |
| 654 // will inherit it. The predicate Function::IsOptimizable uses the |
| 655 // absence of a script to detect test functions that should not be |
| 656 // optimized. Use a dummy script. |
| 657 // |
| 658 // TODO(kmillikin): We shouldn't need a dummy script per class. At the |
| 659 // least we could have a singleton. At best, we'd change IsOptimizable to |
| 660 // detect test functions some other way (like simply not setting the |
| 661 // optimizable bit on those functions in the first place). |
| 662 TokenPosition pos(0); |
| 663 Script& script = |
| 664 Script::Handle(Z, Script::New(H.DartString(""), H.DartString(""), |
| 665 RawScript::kScriptTag)); |
| 666 handle = |
| 667 &dart::Class::Handle(Z, dart::Class::New(library, name, script, pos)); |
| 668 library.AddClass(*handle); |
| 669 } else if (handle->script() == Script::null()) { |
| 670 // When bootstrapping we can encounter classes that do not yet have a |
| 671 // dummy script. |
| 672 TokenPosition pos(0); |
| 673 Script& script = |
| 674 Script::Handle(Z, Script::New(H.DartString(""), H.DartString(""), |
| 675 RawScript::kScriptTag)); |
| 676 handle->set_script(script); |
| 677 } |
| 678 // Insert the class in the cache before calling ReadPreliminaryClass so |
| 679 // we do not risk allocating the class again by calling LookupClass |
| 680 // recursively from ReadPreliminaryClass for the same class. |
| 681 classes_.Insert(klass, handle); |
| 682 if (!handle->is_type_finalized()) { |
| 683 ReadPreliminaryClass(handle, klass); |
| 684 } |
| 685 } |
| 686 return *handle; |
| 687 } |
| 688 |
| 689 RawFunction::Kind DilReader::GetFunctionType(Procedure* dil_procedure) { |
| 690 // TODO(kustermann): Are these correct? |
| 691 intptr_t lookuptable[] = { |
| 692 RawFunction::kRegularFunction, // Procedure::kMethod |
| 693 RawFunction::kGetterFunction, // Procedure::kGetter |
| 694 RawFunction::kSetterFunction, // Procedure::kSetter |
| 695 RawFunction::kRegularFunction, // Procedure::kOperator |
| 696 RawFunction::kConstructor, // Procedure::kFactory |
| 697 }; |
| 698 intptr_t kind = static_cast<int>(dil_procedure->kind()); |
| 699 if (kind == Procedure::kIncompleteProcedure) { |
| 700 // TODO(kustermann): Is this correct? |
| 701 return RawFunction::kSignatureFunction; |
| 702 } else { |
| 703 ASSERT(0 <= kind && kind <= Procedure::kFactory); |
| 704 return static_cast<RawFunction::Kind>(lookuptable[kind]); |
| 705 } |
| 706 } |
| 707 |
| 708 } // namespace dil |
| 709 } // namespace dart |
OLD | NEW |