Flutter Engine
The Flutter Engine
resolver.cc
Go to the documentation of this file.
1// Copyright (c) 2011, 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/resolver.h"
6
7#include "vm/dart_entry.h"
8#include "vm/flags.h"
9#include "vm/isolate.h"
10#include "vm/log.h"
11#include "vm/object.h"
12#include "vm/object_store.h"
13#include "vm/symbols.h"
14
15namespace dart {
16
17DEFINE_FLAG(bool, trace_resolving, false, "Trace resolving.");
18
20 Zone* zone,
21 const Class& receiver_class,
22 const String& function_name,
23 bool allow_add,
24 std::function<FunctionPtr(Class&, const String&)> lookup) {
25#if defined(DART_PRECOMPILED_RUNTIME)
26 // No methods can be added in the precompiled runtime.
27 ASSERT(!allow_add);
28#endif
29
30 if (FLAG_trace_resolving) {
31 THR_Print("ResolveDynamic '%s' for class %s\n", function_name.ToCString(),
32 receiver_class.NameCString(Object::kInternalName));
33 }
34
35 const bool is_dyn_call =
37 const String* const demangled_name =
38 is_dyn_call
40 zone,
43
44 const bool is_getter = Field::IsGetterName(*demangled_name);
45 const String* const method_name_to_extract =
46 is_getter ? &String::Handle(zone, Field::NameFromGetter(*demangled_name))
47 : nullptr;
48
49 Thread* thread = Thread::Current();
51 for (auto& cls = Class::Handle(zone, receiver_class.ptr()); !cls.IsNull();
52 cls = cls.SuperClass()) {
53 if (is_dyn_call) {
54 // If a dyn:* forwarder already exists, return it.
55 function = cls.GetInvocationDispatcher(
56 function_name, Array::null_array(),
57 UntaggedFunction::kDynamicInvocationForwarder,
58 /*create_if_absent=*/false);
59 if (!function.IsNull()) return function.ptr();
60 }
61
62 ASSERT(cls.is_finalized());
63 {
64 SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
65 function = lookup(cls, *demangled_name);
66 }
67#if !defined(DART_PRECOMPILED_RUNTIME)
68 if (allow_add && is_dyn_call && !function.IsNull()) {
69 // In JIT mode, lazily create a dyn:* forwarder if one is required.
70 function = function.GetDynamicInvocationForwarder(function_name);
71 }
72#endif
73 if (!function.IsNull()) return function.ptr();
74
75 // Getter invocation might be an attempted closurization of a method that
76 // does not already have an implicit closure function or method extractor.
77 if (is_getter) {
78 SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
79 function = lookup(cls, *method_name_to_extract);
80 }
81 if (!function.IsNull()) {
82 // Only create method extractors if adding new methods is allowed.
83 if (!allow_add) return Function::null();
84 // Don't create method extractors in the precompiler, as it creates those
85 // based on metadata (see Precompiler::CheckForNewDynamicFunctions).
86 if (FLAG_precompiled_mode) return Function::null();
87 // Use GetMethodExtractor in case a method extractor was created between
88 // the earlier attempted resolution of [*demangled_name] and now.
89 return function.GetMethodExtractor(*demangled_name);
90 }
91 }
92 if (is_getter && receiver_class.IsRecordClass()) {
93 // Only create record field getters if adding new methods is allowed.
94 if (!allow_add) return Function::null();
95 // Don't create record field getters in the precompiler.
96 if (FLAG_precompiled_mode) return Function::null();
97 return receiver_class.GetRecordFieldGetter(*demangled_name);
98 }
99 return Function::null();
100}
101
103 const Class& receiver_class,
104 const String& function_name,
105 const ArgumentsDescriptor& args_desc,
106 bool allow_add,
107 std::function<FunctionPtr(Class&, const String&)> lookup) {
108 Thread* thread = Thread::Current();
109 Zone* zone = thread->zone();
110
113 zone, receiver_class, function_name, allow_add, lookup));
114
115#if defined(DART_PRECOMPILED_RUNTIME)
116 if (!function.IsNull() && function.signature() == FunctionType::null()) {
117 // FfiTrampolines are the only functions that can still be called
118 // dynamically without going through a dynamic invocation forwarder.
120 !function.IsFfiCallbackTrampoline());
121 // The signature for this function was dropped in the precompiler, which
122 // means it is not a possible target for a dynamic call in the program.
123 // That means we're resolving an UnlinkedCall for an InstanceCall to
124 // a known interface. Since there's no overloading in Dart, the type checker
125 // has already checked the validity of the arguments at compile time.
126 return function.ptr();
127 }
128#endif
129
130 if (function.IsNull() || !function.AreValidArguments(args_desc, nullptr)) {
131 // Return a null function to signal to the upper levels to dispatch to
132 // "noSuchMethod" function.
133 if (FLAG_trace_resolving) {
134 String& error_message =
135 String::Handle(zone, Symbols::New(thread, "function not found"));
136 if (!function.IsNull()) {
137 // Obtain more detailed error message.
138 function.AreValidArguments(args_desc, &error_message);
139 }
140 THR_Print("ResolveDynamic error '%s': %s.\n", function_name.ToCString(),
141 error_message.ToCString());
142 }
143 return Function::null();
144 }
145 return function.ptr();
146}
147
149 const Class& receiver_class,
150 const String& function_name,
151 const ArgumentsDescriptor& args_desc,
152 bool allow_add) {
154 receiver_class, function_name, args_desc, allow_add,
156}
157
159 const Class& receiver_class,
160 const String& function_name,
161 const ArgumentsDescriptor& args_desc) {
163 receiver_class, function_name, args_desc, /*allow_add=*/false,
165}
166
168 const Class& receiver_class,
169 const String& function_name) {
171 zone, receiver_class, function_name, /*allow_add=*/false,
172 std::mem_fn(static_cast<FunctionPtr (Class::*)(const String&) const>(
174}
175
177 const Class& receiver_class,
178 const String& function_name) {
180 zone, receiver_class, function_name, /*allow_add=*/false,
181 std::mem_fn(static_cast<FunctionPtr (Class::*)(const String&) const>(
183}
184
186 const Class& receiver_class,
187 const String& function_name,
188 bool allow_add) {
190 zone, receiver_class, function_name, allow_add,
192}
193
194} // namespace dart
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
const char * NameCString(NameVisibility name_visibility) const
Definition: object.cc:3006
FunctionPtr LookupDynamicFunctionAllowPrivate(const String &name) const
Definition: object.cc:6133
bool IsRecordClass() const
Definition: object.h:1583
FunctionPtr GetRecordFieldGetter(const String &getter_name) const
Definition: object.cc:4078
FunctionPtr LookupFunctionReadLocked(const String &name) const
Definition: object.cc:6171
FunctionPtr LookupDynamicFunctionUnsafe(const String &name) const
Definition: object.cc:6129
static bool IsGetterName(const String &function_name)
Definition: object.cc:11831
static StringPtr NameFromGetter(const String &getter_name)
Definition: object.cc:11816
static bool IsDynamicInvocationForwarderName(const String &name)
Definition: object.cc:4190
static StringPtr DemangleDynamicInvocationForwarderName(const String &name)
Definition: object.cc:4198
SafepointRwLock * program_lock()
Definition: isolate.h:537
@ kInternalName
Definition: object.h:622
static ObjectPtr null()
Definition: object.h:433
ObjectPtr ptr() const
Definition: object.h:332
bool IsNull() const
Definition: object.h:363
static Object & Handle()
Definition: object.h:407
static FunctionPtr ResolveDynamicAnyArgs(Zone *zone, const Class &receiver_class, const String &function_name, bool allow_add)
Definition: resolver.cc:185
static FunctionPtr ResolveDynamicFunction(Zone *zone, const Class &receiver_class, const String &function_name)
Definition: resolver.cc:176
static FunctionPtr ResolveFunction(Zone *zone, const Class &receiver_class, const String &function_name)
Definition: resolver.cc:167
static FunctionPtr ResolveDynamicForReceiverClassAllowPrivate(const Class &receiver_class, const String &function_name, const ArgumentsDescriptor &args_desc)
Definition: resolver.cc:158
static FunctionPtr ResolveDynamicForReceiverClass(const Class &receiver_class, const String &function_name, const ArgumentsDescriptor &args_desc, bool allow_add)
Definition: resolver.cc:148
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition: object.cc:24126
static StringPtr New(Thread *thread, const char *cstr)
Definition: symbols.h:723
Zone * zone() const
Definition: thread_state.h:37
static Thread * Current()
Definition: thread.h:362
IsolateGroup * isolate_group() const
Definition: thread.h:541
#define THR_Print(format,...)
Definition: log.h:20
#define ASSERT(E)
Dart_NativeFunction function
Definition: fuchsia.cc:51
Definition: dart_vm.cc:33
static FunctionPtr ResolveDynamicAnyArgsWithCustomLookup(Zone *zone, const Class &receiver_class, const String &function_name, bool allow_add, std::function< FunctionPtr(Class &, const String &)> lookup)
Definition: resolver.cc:19
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
const char *const function_name
static FunctionPtr ResolveDynamicForReceiverClassWithCustomLookup(const Class &receiver_class, const String &function_name, const ArgumentsDescriptor &args_desc, bool allow_add, std::function< FunctionPtr(Class &, const String &)> lookup)
Definition: resolver.cc:102