Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
19// The actual names of named arguments are not checked by the dynamic resolver,
20// but by the method entry code. It is important that the dynamic resolver
21// checks that no named arguments are passed to a method that does not accept
22// them, since the entry code of such a method does not check for named
23// arguments. The dynamic resolver actually checks that a valid number of named
24// arguments is passed in.
25FunctionPtr Resolver::ResolveDynamic(const Instance& receiver,
26 const String& function_name,
27 const ArgumentsDescriptor& args_desc) {
28 // Figure out type of receiver first.
29 const Class& cls = Class::Handle(receiver.clazz());
30 return ResolveDynamicForReceiverClass(cls, function_name, args_desc);
31}
32
34 Zone* zone,
35 const Class& receiver_class,
36 const String& function_name,
37 bool allow_add,
38 std::function<FunctionPtr(Class&, const String&)> lookup) {
39 Class& cls = Class::Handle(zone, receiver_class.ptr());
40 if (FLAG_trace_resolving) {
41 THR_Print("ResolveDynamic '%s' for class %s\n", function_name.ToCString(),
42 String::Handle(zone, cls.Name()).ToCString());
43 }
45
46 const String& demangled = String::Handle(
47 zone,
50 : function_name.ptr());
51
52 const bool is_getter = Field::IsGetterName(demangled);
53 String& demangled_getter_name = String::Handle();
54 if (is_getter) {
55 demangled_getter_name = Field::NameFromGetter(demangled);
56 }
57
58 const bool is_dyn_call = demangled.ptr() != function_name.ptr();
59
60 Thread* thread = Thread::Current();
61 bool need_to_create_method_extractor = false;
62 while (!cls.IsNull()) {
63 if (is_dyn_call) {
64 // Try to find a dyn:* forwarder & return it.
66 function_name, Array::null_array(),
67 UntaggedFunction::kDynamicInvocationForwarder,
68 /*create_if_absent=*/false);
69 }
70 if (!function.IsNull()) return function.ptr();
71
72 ASSERT(cls.is_finalized());
73 {
74 SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
75 function = lookup(cls, demangled);
76 }
77#if !defined(DART_PRECOMPILED_RUNTIME)
78 // In JIT we might need to lazily create a dyn:* forwarder.
79 if (is_dyn_call && !function.IsNull()) {
80 function =
81 function.GetDynamicInvocationForwarder(function_name, allow_add);
82 }
83#endif
84 if (!function.IsNull()) return function.ptr();
85
86 // Getter invocation might actually be a method extraction.
87 if (is_getter) {
88 SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
89 function = lookup(cls, demangled_getter_name);
90 if (!function.IsNull()) {
91 if (allow_add && FLAG_lazy_dispatchers) {
92 need_to_create_method_extractor = true;
93 break;
94 } else {
95 return Function::null();
96 }
97 }
98 }
99 cls = cls.SuperClass();
100 }
101 if (need_to_create_method_extractor) {
102 // We were looking for the getter but found a method with the same
103 // name. Create a method extractor and return it.
104 // Use GetMethodExtractor instead of CreateMethodExtractor to ensure
105 // nobody created method extractor since we last checked under ReadRwLocker.
106 function = function.GetMethodExtractor(demangled);
107 } else if (is_getter && receiver_class.IsRecordClass() && allow_add &&
108 FLAG_lazy_dispatchers) {
109 function = receiver_class.GetRecordFieldGetter(demangled);
110 }
111 return function.ptr();
112}
113
115 const Class& receiver_class,
116 const String& function_name,
117 const ArgumentsDescriptor& args_desc,
118 bool allow_add,
119 std::function<FunctionPtr(Class&, const String&)> lookup) {
120 Thread* thread = Thread::Current();
121 Zone* zone = thread->zone();
122
125 zone, receiver_class, function_name, allow_add, lookup));
126
127#if defined(DART_PRECOMPILED_RUNTIME)
128 if (!function.IsNull() && function.signature() == FunctionType::null()) {
129 // FfiTrampolines are the only functions that can still be called
130 // dynamically without going through a dynamic invocation forwarder.
132 !function.IsFfiCallbackTrampoline());
133 // The signature for this function was dropped in the precompiler, which
134 // means it is not a possible target for a dynamic call in the program.
135 // That means we're resolving an UnlinkedCall for an InstanceCall to
136 // a known interface. Since there's no overloading in Dart, the type checker
137 // has already checked the validity of the arguments at compile time.
138 return function.ptr();
139 }
140#endif
141
142 if (function.IsNull() || !function.AreValidArguments(args_desc, nullptr)) {
143 // Return a null function to signal to the upper levels to dispatch to
144 // "noSuchMethod" function.
145 if (FLAG_trace_resolving) {
146 String& error_message =
147 String::Handle(zone, Symbols::New(thread, "function not found"));
148 if (!function.IsNull()) {
149 // Obtain more detailed error message.
150 function.AreValidArguments(args_desc, &error_message);
151 }
152 THR_Print("ResolveDynamic error '%s': %s.\n", function_name.ToCString(),
153 error_message.ToCString());
154 }
155 return Function::null();
156 }
157 return function.ptr();
158}
159
161 const Class& receiver_class,
162 const String& function_name,
163 const ArgumentsDescriptor& args_desc,
164 bool allow_add) {
166 receiver_class, function_name, args_desc, allow_add,
168}
169
171 const Class& receiver_class,
172 const String& function_name,
173 const ArgumentsDescriptor& args_desc,
174 bool allow_add) {
176 receiver_class, function_name, args_desc, allow_add,
178}
179
181 const Class& receiver_class,
182 const String& function_name) {
184 zone, receiver_class, function_name, /*allow_add=*/false,
185 std::mem_fn(static_cast<FunctionPtr (Class::*)(const String&) const>(
187}
188
190 const Class& receiver_class,
191 const String& function_name) {
193 zone, receiver_class, function_name, /*allow_add=*/false,
194 std::mem_fn(static_cast<FunctionPtr (Class::*)(const String&) const>(
196}
197
199 const Class& receiver_class,
200 const String& function_name,
201 bool allow_add) {
203 zone, receiver_class, function_name, allow_add,
205}
206
208 Zone* zone,
209 const Class& receiver_class,
210 const String& function_name,
211 bool allow_add) {
213 zone, receiver_class, function_name, allow_add,
215}
216
217} // namespace dart
#define RELEASE_ASSERT(cond)
Definition assert.h:327
FunctionPtr LookupDynamicFunctionAllowPrivate(const String &name) const
Definition object.cc:6188
bool IsRecordClass() const
Definition object.h:1585
FunctionPtr GetInvocationDispatcher(const String &target_name, const Array &args_desc, UntaggedFunction::Kind kind, bool create_if_absent) const
Definition object.cc:3897
FunctionPtr GetRecordFieldGetter(const String &getter_name) const
Definition object.cc:4128
FunctionPtr LookupFunctionReadLocked(const String &name) const
Definition object.cc:6226
FunctionPtr LookupDynamicFunctionUnsafe(const String &name) const
Definition object.cc:6184
StringPtr Name() const
Definition object.cc:3038
ClassPtr SuperClass(ClassTable *class_table=nullptr) const
Definition object.cc:3715
bool is_finalized() const
Definition object.h:1725
static bool IsGetterName(const String &function_name)
Definition object.cc:11882
static StringPtr NameFromGetter(const String &getter_name)
Definition object.cc:11867
static bool IsDynamicInvocationForwarderName(const String &name)
Definition object.cc:4240
static StringPtr DemangleDynamicInvocationForwarderName(const String &name)
Definition object.cc:4248
SafepointRwLock * program_lock()
Definition isolate.h:532
static ObjectPtr null()
Definition object.h:433
ObjectPtr ptr() const
Definition object.h:332
virtual const char * ToCString() const
Definition object.h:366
bool IsNull() const
Definition object.h:363
static Object & Handle()
Definition object.h:407
ClassPtr clazz() const
Definition object.h:13192
static FunctionPtr ResolveDynamicFunction(Zone *zone, const Class &receiver_class, const String &function_name)
Definition resolver.cc:189
static FunctionPtr ResolveFunction(Zone *zone, const Class &receiver_class, const String &function_name)
Definition resolver.cc:180
static FunctionPtr ResolveDynamicForReceiverClassAllowPrivate(const Class &receiver_class, const String &function_name, const ArgumentsDescriptor &args_desc, bool allow_add)
Definition resolver.cc:170
static FunctionPtr ResolveDynamicAnyArgs(Zone *zone, const Class &receiver_class, const String &function_name, bool allow_add=true)
Definition resolver.cc:198
static FunctionPtr ResolveDynamicForReceiverClass(const Class &receiver_class, const String &function_name, const ArgumentsDescriptor &args_desc, bool allow_add=true)
Definition resolver.cc:160
static FunctionPtr ResolveDynamicAnyArgsAllowPrivate(Zone *zone, const Class &receiver_class, const String &function_name, bool allow_add)
Definition resolver.cc:207
static FunctionPtr ResolveDynamic(const Instance &receiver, const String &function_name, const ArgumentsDescriptor &args_desc)
Definition resolver.cc:25
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition object.cc:24205
static StringPtr New(Thread *thread, const char *cstr)
Definition symbols.h:722
Zone * zone() const
static Thread * Current()
Definition thread.h:361
IsolateGroup * isolate_group() const
Definition thread.h:540
#define THR_Print(format,...)
Definition log.h:20
#define ASSERT(E)
#define DEFINE_FLAG(type, name, default_value, comment)
Definition flags.h:16
Dart_NativeFunction function
Definition fuchsia.cc:51
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:33
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:114