// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "vm/kernel_reader.h" #include #include "vm/dart_api_impl.h" #include "vm/longjump.h" #include "vm/object_store.h" #include "vm/parser.h" #include "vm/symbols.h" #if !defined(DART_PRECOMPILED_RUNTIME) namespace dart { namespace kernel { #define Z (zone_) #define I (isolate_) #define T (type_translator_) #define H (translation_helper_) class SimpleExpressionConverter : public ExpressionVisitor { public: explicit SimpleExpressionConverter(Thread* thread) : translation_helper_(thread), zone_(translation_helper_.zone()), is_simple_(false), simple_value_(NULL) {} virtual void VisitDefaultExpression(Expression* node) { is_simple_ = false; } virtual void VisitIntLiteral(IntLiteral* node) { is_simple_ = true; simple_value_ = &Integer::ZoneHandle(Z, Integer::New(node->value(), Heap::kOld)); *simple_value_ = H.Canonicalize(*simple_value_); } virtual void VisitBigintLiteral(BigintLiteral* node) { is_simple_ = true; simple_value_ = &Integer::ZoneHandle( Z, Integer::New(H.DartString(node->value(), Heap::kOld))); *simple_value_ = H.Canonicalize(*simple_value_); } virtual void VisitDoubleLiteral(DoubleLiteral* node) { is_simple_ = true; simple_value_ = &Double::ZoneHandle( Z, Double::New(H.DartString(node->value()), Heap::kOld)); *simple_value_ = H.Canonicalize(*simple_value_); } virtual void VisitBoolLiteral(BoolLiteral* node) { is_simple_ = true; simple_value_ = &Bool::Handle(Z, Bool::Get(node->value()).raw()); } virtual void VisitNullLiteral(NullLiteral* node) { is_simple_ = true; simple_value_ = &dart::Instance::ZoneHandle(Z, dart::Instance::null()); } virtual void VisitStringLiteral(StringLiteral* node) { is_simple_ = true; simple_value_ = &H.DartSymbol(node->value()); } bool IsSimple(Expression* expression) { expression->AcceptExpressionVisitor(this); return is_simple_; } const dart::Instance& SimpleValue() { return *simple_value_; } dart::Zone* zone() const { return zone_; } private: TranslationHelper translation_helper_; dart::Zone* zone_; bool is_simple_; dart::Instance* simple_value_; }; RawArray* KernelReader::MakeFunctionsArray() { const intptr_t len = functions_.length(); const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld)); for (intptr_t i = 0; i < len; i++) { res.SetAt(i, *functions_[i]); } return res.raw(); } RawLibrary* BuildingTranslationHelper::LookupLibraryByKernelLibrary( CanonicalName* library) { return reader_->LookupLibrary(library).raw(); } RawClass* BuildingTranslationHelper::LookupClassByKernelClass( CanonicalName* klass) { return reader_->LookupClass(klass).raw(); } KernelReader::KernelReader(Program* program) : program_(program), thread_(dart::Thread::Current()), zone_(thread_->zone()), isolate_(thread_->isolate()), scripts_(Array::ZoneHandle(zone_)), translation_helper_(this, thread_), type_translator_(&translation_helper_, &active_class_, /*finalize=*/false) { intptr_t source_file_count = program_->source_table().size(); scripts_ = Array::New(source_file_count, Heap::kOld); } Object& KernelReader::ReadProgram() { LongJumpScope jump; if (setjmp(*jump.Set()) == 0) { intptr_t length = program_->libraries().length(); for (intptr_t i = 0; i < length; i++) { Library* kernel_library = program_->libraries()[i]; ReadLibrary(kernel_library); } for (intptr_t i = 0; i < length; i++) { dart::Library& library = LookupLibrary(program_->libraries()[i]->canonical_name()); if (!library.Loaded()) library.SetLoaded(); } if (ClassFinalizer::ProcessPendingClasses(/*from_kernel=*/true)) { CanonicalName* main = program_->main_method(); dart::Library& library = LookupLibrary(main->EnclosingName()); // Sanity check that we can find the main entrypoint. Object& main_obj = Object::Handle( Z, library.LookupObjectAllowPrivate(H.DartSymbol("main"))); ASSERT(!main_obj.IsNull()); return library; } } // Either class finalization failed or we caught a compile error. // In both cases sticky error would be set. Error& error = Error::Handle(Z); error = thread_->sticky_error(); thread_->clear_sticky_error(); return error; } void KernelReader::ReadLibrary(Library* kernel_library) { dart::Library& library = LookupLibrary(kernel_library->canonical_name()); if (library.Loaded()) return; library.SetName(H.DartSymbol(kernel_library->name())); // The bootstrapper will take care of creating the native wrapper classes, but // we will add the synthetic constructors to them here. if (library.name() == Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).raw()) { ASSERT(library.LoadInProgress()); } else { library.SetLoadInProgress(); } // Setup toplevel class (which contains library fields/procedures). Script& script = ScriptAt(kernel_library->source_uri_index(), kernel_library->import_uri()); dart::Class& toplevel_class = dart::Class::Handle( Z, dart::Class::New(library, Symbols::TopLevel(), script, TokenPosition::kNoSource)); toplevel_class.set_is_cycle_free(); library.set_toplevel_class(toplevel_class); fields_.Clear(); functions_.Clear(); ActiveClassScope active_class_scope(&active_class_, NULL, &toplevel_class); // Load toplevel fields. for (intptr_t i = 0; i < kernel_library->fields().length(); i++) { Field* kernel_field = kernel_library->fields()[i]; ActiveMemberScope active_member_scope(&active_class_, kernel_field); const dart::String& name = H.DartFieldName(kernel_field->name()); const Object& script_class = ClassForScriptAt(toplevel_class, kernel_field->source_uri_index()); dart::Field& field = dart::Field::Handle( Z, dart::Field::NewTopLevel(name, kernel_field->IsFinal(), kernel_field->IsConst(), script_class, kernel_field->position())); field.set_kernel_field(kernel_field); const AbstractType& type = T.TranslateType(kernel_field->type()); field.SetFieldType(type); field.set_has_initializer(kernel_field->initializer() != NULL); GenerateFieldAccessors(toplevel_class, field, kernel_field); fields_.Add(&field); library.AddObject(field, name); } toplevel_class.AddFields(fields_); // Load toplevel procedures. for (intptr_t i = 0; i < kernel_library->procedures().length(); i++) { Procedure* kernel_procedure = kernel_library->procedures()[i]; ReadProcedure(library, toplevel_class, kernel_procedure); } toplevel_class.SetFunctions(Array::Handle(MakeFunctionsArray())); const GrowableObjectArray& classes = GrowableObjectArray::Handle(I->object_store()->pending_classes()); // Load all classes. for (intptr_t i = 0; i < kernel_library->classes().length(); i++) { Class* kernel_klass = kernel_library->classes()[i]; classes.Add(ReadClass(library, toplevel_class, kernel_klass), Heap::kOld); } classes.Add(toplevel_class, Heap::kOld); } void KernelReader::ReadPreliminaryClass(dart::Class* klass, Class* kernel_klass) { ASSERT(kernel_klass->IsNormalClass()); NormalClass* kernel_normal_class = NormalClass::Cast(kernel_klass); ActiveClassScope active_class_scope(&active_class_, kernel_klass, klass); // First setup the type parameters, so if any of the following code uses it // (in a recursive way) we're fine. TypeArguments& type_parameters = TypeArguments::Handle(Z, TypeArguments::null()); intptr_t num_type_parameters = kernel_klass->type_parameters().length(); if (num_type_parameters > 0) { dart::TypeParameter& parameter = dart::TypeParameter::Handle(Z); Type& null_bound = Type::Handle(Z, Type::null()); // Step a) Create array of [TypeParameter] objects (without bound). type_parameters = TypeArguments::New(num_type_parameters); for (intptr_t i = 0; i < num_type_parameters; i++) { parameter = dart::TypeParameter::New( *klass, Function::Handle(Z), i, 0, H.DartSymbol(kernel_klass->type_parameters()[i]->name()), null_bound, TokenPosition::kNoSource); type_parameters.SetTypeAt(i, parameter); } klass->set_type_parameters(type_parameters); // Step b) Fill in the bounds of all [TypeParameter]s. for (intptr_t i = 0; i < num_type_parameters; i++) { TypeParameter* kernel_parameter = kernel_klass->type_parameters()[i]; // TODO(github.com/dart-lang/kernel/issues/42): This should be handled // by the frontend. if (kernel_parameter->bound()->IsDynamicType()) { parameter ^= type_parameters.TypeAt(i); parameter.set_bound(Type::Handle(Z, I->object_store()->object_type())); } else { AbstractType& bound = T.TranslateTypeWithoutFinalization(kernel_parameter->bound()); if (bound.IsMalformedOrMalbounded()) { bound = I->object_store()->object_type(); } parameter ^= type_parameters.TypeAt(i); parameter.set_bound(bound); } } } // Set super type. Some classes (e.g., Object) do not have one. if (kernel_normal_class->super_class() != NULL) { AbstractType& super_type = T.TranslateTypeWithoutFinalization(kernel_normal_class->super_class()); if (super_type.IsMalformed()) H.ReportError("Malformed super type"); klass->set_super_type(super_type); } // Build implemented interface types intptr_t interface_count = kernel_klass->implemented_classes().length(); const dart::Array& interfaces = dart::Array::Handle(Z, dart::Array::New(interface_count, Heap::kOld)); for (intptr_t i = 0; i < interface_count; i++) { InterfaceType* kernel_interface_type = kernel_klass->implemented_classes()[i]; const AbstractType& type = T.TranslateTypeWithoutFinalization(kernel_interface_type); if (type.IsMalformed()) H.ReportError("Malformed interface type."); interfaces.SetAt(i, type); } klass->set_interfaces(interfaces); if (kernel_klass->is_abstract()) klass->set_is_abstract(); } dart::Class& KernelReader::ReadClass(const dart::Library& library, const dart::Class& toplevel_class, Class* kernel_klass) { dart::Class& klass = LookupClass(kernel_klass->canonical_name()); // The class needs to have a script because all the functions in the class // will inherit it. The predicate Function::IsOptimizable uses the absence of // a script to detect test functions that should not be optimized. if (klass.script() == Script::null()) { klass.set_script(ScriptAt(kernel_klass->source_uri_index())); } if (klass.token_pos() == TokenPosition::kNoSource) { klass.set_token_pos(kernel_klass->position()); } if (!klass.is_cycle_free()) { ReadPreliminaryClass(&klass, kernel_klass); } ActiveClassScope active_class_scope(&active_class_, kernel_klass, &klass); fields_.Clear(); functions_.Clear(); if (library.raw() == dart::Library::InternalLibrary() && klass.Name() == Symbols::ClassID().raw()) { // If this is a dart:internal.ClassID class ignore field declarations // contained in the Kernel file and instead inject our own const // fields. klass.InjectCIDFields(); } else { for (intptr_t i = 0; i < kernel_klass->fields().length(); i++) { Field* kernel_field = kernel_klass->fields()[i]; ActiveMemberScope active_member_scope(&active_class_, kernel_field); const dart::String& name = H.DartFieldName(kernel_field->name()); const AbstractType& type = T.TranslateTypeWithoutFinalization(kernel_field->type()); const Object& script_class = ClassForScriptAt(klass, kernel_field->source_uri_index()); dart::Field& field = dart::Field::Handle( Z, dart::Field::New(name, kernel_field->IsStatic(), // In the VM all const fields are implicitly final // whereas in Kernel they are not final because they // are not explicitly declared that way. kernel_field->IsFinal() || kernel_field->IsConst(), kernel_field->IsConst(), false, // is_reflectable script_class, type, kernel_field->position())); field.set_kernel_field(kernel_field); field.set_has_initializer(kernel_field->initializer() != NULL); GenerateFieldAccessors(klass, field, kernel_field); fields_.Add(&field); } klass.AddFields(fields_); } for (intptr_t i = 0; i < kernel_klass->constructors().length(); i++) { Constructor* kernel_constructor = kernel_klass->constructors()[i]; ActiveMemberScope active_member_scope(&active_class_, kernel_constructor); ActiveFunctionScope active_function_scope(&active_class_, kernel_constructor->function()); const dart::String& name = H.DartConstructorName(kernel_constructor->canonical_name()); Function& function = dart::Function::ZoneHandle( Z, dart::Function::New(name, RawFunction::kConstructor, false, // is_static kernel_constructor->IsConst(), false, // is_abstract kernel_constructor->IsExternal(), false, // is_native klass, kernel_constructor->position())); function.set_end_token_pos(kernel_constructor->end_position()); functions_.Add(&function); function.set_kernel_function(kernel_constructor); function.set_result_type(T.ReceiverType(klass)); SetupFunctionParameters(H, T, klass, function, kernel_constructor->function(), true, // is_method false); // is_closure if (FLAG_enable_mirrors) { library.AddFunctionMetadata(function, TokenPosition::kNoSource, kernel_constructor); } } for (intptr_t i = 0; i < kernel_klass->procedures().length(); i++) { Procedure* kernel_procedure = kernel_klass->procedures()[i]; ActiveMemberScope active_member_scope(&active_class_, kernel_procedure); ReadProcedure(library, klass, kernel_procedure, kernel_klass); } klass.SetFunctions(Array::Handle(MakeFunctionsArray())); if (!klass.is_marked_for_parsing()) { klass.set_is_marked_for_parsing(); } if (FLAG_enable_mirrors) { library.AddClassMetadata(klass, toplevel_class, TokenPosition::kNoSource, kernel_klass); } return klass; } void KernelReader::ReadProcedure(const dart::Library& library, const dart::Class& owner, Procedure* kernel_procedure, Class* kernel_klass) { ActiveClassScope active_class_scope(&active_class_, kernel_klass, &owner); ActiveMemberScope active_member_scope(&active_class_, kernel_procedure); ActiveFunctionScope active_function_scope(&active_class_, kernel_procedure->function()); const dart::String& name = H.DartProcedureName(kernel_procedure->canonical_name()); bool is_method = kernel_klass != NULL && !kernel_procedure->IsStatic(); bool is_abstract = kernel_procedure->IsAbstract(); bool is_external = kernel_procedure->IsExternal(); dart::String* native_name = NULL; if (is_external) { // Maybe it has a native implementation, which is not external as far as // the VM is concerned because it does have an implementation. Check for // an ExternalName annotation and extract the string from it. for (int i = 0; i < kernel_procedure->annotations().length(); ++i) { Expression* annotation = kernel_procedure->annotations()[i]; if (!annotation->IsConstructorInvocation()) continue; ConstructorInvocation* invocation = ConstructorInvocation::Cast(annotation); CanonicalName* annotation_class = invocation->target()->EnclosingName(); ASSERT(annotation_class->IsClass()); String* class_name = annotation_class->name(); // Just compare by name, do not generate the annotation class. int length = sizeof("ExternalName") - 1; if (class_name->size() != length) continue; if (memcmp(class_name->buffer(), "ExternalName", length) != 0) continue; ASSERT(annotation_class->parent()->IsLibrary()); String* library_name = annotation_class->parent()->name(); length = sizeof("dart:_internal") - 1; if (library_name->size() != length) continue; if (memcmp(library_name->buffer(), "dart:_internal", length) != 0) { continue; } is_external = false; ASSERT(invocation->arguments()->positional().length() == 1 && invocation->arguments()->named().length() == 0); StringLiteral* literal = StringLiteral::Cast(invocation->arguments()->positional()[0]); native_name = &H.DartSymbol(literal->value()); break; } } const Object& script_class = ClassForScriptAt(owner, kernel_procedure->source_uri_index()); dart::Function& function = dart::Function::ZoneHandle( Z, Function::New(name, GetFunctionType(kernel_procedure), !is_method, // is_static false, // is_const is_abstract, is_external, native_name != NULL, // is_native script_class, kernel_procedure->position())); function.set_end_token_pos(kernel_procedure->end_position()); functions_.Add(&function); function.set_kernel_function(kernel_procedure); function.set_is_debuggable( kernel_procedure->function()->dart_async_marker() == FunctionNode::kSync); switch (kernel_procedure->function()->dart_async_marker()) { case FunctionNode::kSyncStar: function.set_modifier(RawFunction::kSyncGen); break; case FunctionNode::kAsync: function.set_modifier(RawFunction::kAsync); function.set_is_inlinable(!FLAG_causal_async_stacks); break; case FunctionNode::kAsyncStar: function.set_modifier(RawFunction::kAsyncGen); function.set_is_inlinable(!FLAG_causal_async_stacks); break; default: // no special modifier break; } ASSERT(kernel_procedure->function()->async_marker() == FunctionNode::kSync); if (native_name != NULL) { function.set_native_name(*native_name); } SetupFunctionParameters(H, T, owner, function, kernel_procedure->function(), is_method, false); // is_closure if (kernel_klass == NULL) { library.AddObject(function, name); ASSERT(!Object::Handle( Z, library.LookupObjectAllowPrivate( H.DartProcedureName(kernel_procedure->canonical_name()))) .IsNull()); } if (FLAG_enable_mirrors) { library.AddFunctionMetadata(function, TokenPosition::kNoSource, kernel_procedure); } } const Object& KernelReader::ClassForScriptAt(const dart::Class& klass, intptr_t source_uri_index) { Script& correct_script = ScriptAt(source_uri_index); if (klass.script() != correct_script.raw()) { // TODO(jensj): We could probably cache this so we don't create // new PatchClasses all the time return PatchClass::ZoneHandle(Z, PatchClass::New(klass, correct_script)); } return klass; } static int LowestFirst(const intptr_t* a, const intptr_t* b) { return *a - *b; } /** * If index exists as sublist in list, sort the sublist from lowest to highest, * then copy it, as Smis and without duplicates, * to a new Array in Heap::kOld which is returned. * Note that the source list is both sorted and de-duplicated as well, but will * possibly contain duplicate and unsorted data at the end. * Otherwise (when sublist doesn't exist in list) return new empty array. */ static RawArray* AsSortedDuplicateFreeArray( intptr_t index, MallocGrowableArray*>* list) { if ((index < list->length()) && (list->At(index)->length() > 0)) { MallocGrowableArray* source = list->At(index); source->Sort(LowestFirst); intptr_t size = source->length(); intptr_t last = 0; for (intptr_t current = 1; current < size; ++current) { if (source->At(last) != source->At(current)) { (*source)[++last] = source->At(current); } } Array& array_object = Array::Handle(); array_object ^= Array::New(last + 1, Heap::kOld); Smi& smi_value = Smi::Handle(); for (intptr_t i = 0; i <= last; ++i) { smi_value = Smi::New(source->At(i)); array_object.SetAt(i, smi_value); } return array_object.raw(); } else { return Array::New(0); } } Script& KernelReader::ScriptAt(intptr_t source_uri_index, String* import_uri) { Script& script = Script::ZoneHandle(Z); script ^= scripts_.At(source_uri_index); if (script.IsNull()) { // Create script with correct uri(s). String* uri = program_->source_uri_table().strings()[source_uri_index]; dart::String& uri_string = H.DartString(uri, Heap::kOld); dart::String& import_uri_string = import_uri == NULL ? uri_string : H.DartString(import_uri, Heap::kOld); dart::String& source_code = H.DartString( program_->source_table().SourceFor(source_uri_index), Heap::kOld); script = Script::New(import_uri_string, uri_string, source_code, RawScript::kKernelTag); scripts_.SetAt(source_uri_index, script); // Create line_starts array for the script. intptr_t* line_starts = program_->source_table().LineStartsFor(source_uri_index); intptr_t line_count = program_->source_table().LineCountFor(source_uri_index); Array& array_object = Array::Handle(Z, Array::New(line_count, Heap::kOld)); Smi& value = Smi::Handle(Z); for (intptr_t i = 0; i < line_count; ++i) { value = Smi::New(line_starts[i]); array_object.SetAt(i, value); } script.set_line_starts(array_object); // Create tokens_seen array for the script. array_object ^= AsSortedDuplicateFreeArray( source_uri_index, &program_->valid_token_positions); script.set_debug_positions(array_object); // Create yield_positions array for the script. array_object ^= AsSortedDuplicateFreeArray( source_uri_index, &program_->yield_token_positions); script.set_yield_positions(array_object); } return script; } void KernelReader::GenerateFieldAccessors(const dart::Class& klass, const dart::Field& field, Field* kernel_field) { if (kernel_field->IsStatic() && kernel_field->initializer() == NULL) { // Static fields without an initializer are implicitly initialized to null. // We do not need a getter. field.SetStaticValue(Instance::Handle(Z), true); return; } if (kernel_field->initializer() != NULL) { SimpleExpressionConverter converter(H.thread()); const bool has_simple_initializer = converter.IsSimple(kernel_field->initializer()); if (kernel_field->IsStatic()) { // Static fields with initializers either have the static value set to the // initializer value if it is simple enough or else set to an // uninitialized sentinel. if (has_simple_initializer) { // We do not need a getter. field.SetStaticValue(converter.SimpleValue(), true); return; } // We do need a getter that evaluates the initializer if necessary. field.SetStaticValue(Object::sentinel(), true); } else if (has_simple_initializer) { // Note: optimizer relies on DoubleInitialized bit in its field-unboxing // heuristics. See JitOptimizer::VisitStoreInstanceField for more details. field.RecordStore(converter.SimpleValue()); if (!converter.SimpleValue().IsNull() && converter.SimpleValue().IsDouble()) { field.set_is_double_initialized(true); } } } const dart::String& getter_name = H.DartGetterName(kernel_field->canonical_name()); const Object& script_class = ClassForScriptAt(klass, kernel_field->source_uri_index()); Function& getter = Function::ZoneHandle( Z, Function::New( getter_name, kernel_field->IsStatic() ? RawFunction::kImplicitStaticFinalGetter : RawFunction::kImplicitGetter, kernel_field->IsStatic(), // The functions created by the parser have is_const for static fields // that are const (not just final) and they have is_const for // non-static // fields that are final. kernel_field->IsStatic() ? kernel_field->IsConst() : kernel_field->IsFinal(), false, // is_abstract false, // is_external false, // is_native script_class, kernel_field->position())); functions_.Add(&getter); getter.set_end_token_pos(kernel_field->end_position()); getter.set_kernel_function(kernel_field); getter.set_result_type(AbstractType::Handle(Z, field.type())); getter.set_is_debuggable(false); SetupFieldAccessorFunction(klass, getter); if (!kernel_field->IsStatic() && !kernel_field->IsFinal()) { // Only static fields can be const. ASSERT(!kernel_field->IsConst()); const dart::String& setter_name = H.DartSetterName(kernel_field->canonical_name()); Function& setter = Function::ZoneHandle( Z, Function::New(setter_name, RawFunction::kImplicitSetter, false, // is_static false, // is_const false, // is_abstract false, // is_external false, // is_native script_class, kernel_field->position())); functions_.Add(&setter); setter.set_end_token_pos(kernel_field->end_position()); setter.set_kernel_function(kernel_field); setter.set_result_type(Object::void_type()); setter.set_is_debuggable(false); SetupFieldAccessorFunction(klass, setter); } } void KernelReader::SetupFunctionParameters(TranslationHelper translation_helper, DartTypeTranslator type_translator, const dart::Class& klass, const dart::Function& function, FunctionNode* node, bool is_method, bool is_closure) { dart::Zone* zone = translation_helper.zone(); ASSERT(!(is_method && is_closure)); bool is_factory = function.IsFactory(); intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0; function.set_num_fixed_parameters(extra_parameters + node->required_parameter_count()); if (node->named_parameters().length() > 0) { function.SetNumOptionalParameters(node->named_parameters().length(), false); } else { function.SetNumOptionalParameters(node->positional_parameters().length() - node->required_parameter_count(), true); } intptr_t num_parameters = extra_parameters + node->positional_parameters().length() + node->named_parameters().length(); function.set_parameter_types( Array::Handle(zone, Array::New(num_parameters, Heap::kOld))); function.set_parameter_names( Array::Handle(zone, Array::New(num_parameters, Heap::kOld))); intptr_t pos = 0; if (is_method) { ASSERT(!klass.IsNull()); function.SetParameterTypeAt(pos, translation_helper.GetCanonicalType(klass)); function.SetParameterNameAt(pos, Symbols::This()); pos++; } else if (is_closure) { function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); function.SetParameterNameAt(pos, Symbols::ClosureParameter()); pos++; } else if (is_factory) { function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter()); pos++; } for (intptr_t i = 0; i < node->positional_parameters().length(); i++, pos++) { VariableDeclaration* kernel_variable = node->positional_parameters()[i]; const AbstractType& type = type_translator.TranslateTypeWithoutFinalization( kernel_variable->type()); function.SetParameterTypeAt( pos, type.IsMalformed() ? Type::dynamic_type() : type); function.SetParameterNameAt( pos, translation_helper.DartSymbol(kernel_variable->name())); } for (intptr_t i = 0; i < node->named_parameters().length(); i++, pos++) { VariableDeclaration* named_expression = node->named_parameters()[i]; const AbstractType& type = type_translator.TranslateTypeWithoutFinalization( named_expression->type()); function.SetParameterTypeAt( pos, type.IsMalformed() ? Type::dynamic_type() : type); function.SetParameterNameAt( pos, translation_helper.DartSymbol(named_expression->name())); } // The result type for generative constructors has already been set. if (!function.IsGenerativeConstructor()) { const AbstractType& return_type = type_translator.TranslateTypeWithoutFinalization(node->return_type()); function.set_result_type(return_type.IsMalformed() ? Type::dynamic_type() : return_type); } } void KernelReader::SetupFieldAccessorFunction(const dart::Class& klass, const dart::Function& function) { bool is_setter = function.IsImplicitSetterFunction(); bool is_method = !function.IsStaticFunction(); intptr_t num_parameters = (is_method ? 1 : 0) + (is_setter ? 1 : 0); function.SetNumOptionalParameters(0, false); function.set_num_fixed_parameters(num_parameters); function.set_parameter_types( Array::Handle(Z, Array::New(num_parameters, Heap::kOld))); function.set_parameter_names( Array::Handle(Z, Array::New(num_parameters, Heap::kOld))); intptr_t pos = 0; if (is_method) { function.SetParameterTypeAt(pos, T.ReceiverType(klass)); function.SetParameterNameAt(pos, Symbols::This()); pos++; } if (is_setter) { function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); function.SetParameterNameAt(pos, Symbols::Value()); pos++; } } dart::Library& KernelReader::LookupLibrary(CanonicalName* library) { dart::Library* handle = NULL; if (!libraries_.Lookup(library, &handle)) { const dart::String& url = H.DartSymbol(library->name()); handle = &dart::Library::Handle(Z, dart::Library::LookupLibrary(thread_, url)); if (handle->IsNull()) { *handle = dart::Library::New(url); handle->Register(thread_); } ASSERT(!handle->IsNull()); libraries_.Insert(library, handle); } return *handle; } dart::Class& KernelReader::LookupClass(CanonicalName* klass) { dart::Class* handle = NULL; if (!classes_.Lookup(klass, &handle)) { dart::Library& library = LookupLibrary(klass->parent()); const dart::String& name = H.DartClassName(klass); handle = &dart::Class::Handle(Z, library.LookupClass(name)); if (handle->IsNull()) { *handle = dart::Class::New(library, name, Script::Handle(Z), TokenPosition::kNoSource); library.AddClass(*handle); } // Insert the class in the cache before calling ReadPreliminaryClass so // we do not risk allocating the class again by calling LookupClass // recursively from ReadPreliminaryClass for the same class. classes_.Insert(klass, handle); } return *handle; } RawFunction::Kind KernelReader::GetFunctionType(Procedure* kernel_procedure) { intptr_t lookuptable[] = { RawFunction::kRegularFunction, // Procedure::kMethod RawFunction::kGetterFunction, // Procedure::kGetter RawFunction::kSetterFunction, // Procedure::kSetter RawFunction::kRegularFunction, // Procedure::kOperator RawFunction::kConstructor, // Procedure::kFactory }; intptr_t kind = static_cast(kernel_procedure->kind()); if (kind == Procedure::kIncompleteProcedure) { return RawFunction::kSignatureFunction; } else { ASSERT(0 <= kind && kind <= Procedure::kFactory); return static_cast(lookuptable[kind]); } } ParsedFunction* ParseStaticFieldInitializer(Zone* zone, const dart::Field& field) { Thread* thread = Thread::Current(); kernel::Field* kernel_field = kernel::Field::Cast( reinterpret_cast(field.kernel_field())); dart::String& init_name = dart::String::Handle(zone, field.name()); init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name); // Create a static initializer. const Object& owner = Object::Handle(field.RawOwner()); const Function& initializer_fun = Function::ZoneHandle( zone, dart::Function::New(init_name, RawFunction::kImplicitStaticFinalGetter, true, // is_static false, // is_const false, // is_abstract false, // is_external false, // is_native owner, TokenPosition::kNoSource)); initializer_fun.set_kernel_function(kernel_field); initializer_fun.set_result_type(AbstractType::Handle(zone, field.type())); initializer_fun.set_is_debuggable(false); initializer_fun.set_is_reflectable(false); initializer_fun.set_is_inlinable(false); return new (zone) ParsedFunction(thread, initializer_fun); } } // namespace kernel } // namespace dart #endif // !defined(DART_PRECOMPILED_RUNTIME)