Flutter Engine
The Flutter Engine
native_entry.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/native_entry.h"
6
7#include "include/dart_api.h"
8
9#include "vm/bootstrap.h"
10#include "vm/code_patcher.h"
11#include "vm/dart_api_impl.h"
12#include "vm/dart_api_state.h"
13#include "vm/heap/safepoint.h"
14#include "vm/native_symbol.h"
15#include "vm/object_store.h"
16#include "vm/reusable_handles.h"
17#include "vm/stack_frame.h"
18#include "vm/symbols.h"
19#include "vm/tags.h"
20
21namespace dart {
22
24 int num_type_args_expected) {
26 "Wrong number of type arguments (%i), expected %i type arguments",
27 num_type_args, num_type_args_expected));
29}
30
32 const Array& __args__ = Array::Handle(Array::New(1));
33 __args__.SetAt(0, instance);
35}
36
38 const String& function_name,
39 int number_of_arguments,
40 bool* auto_setup_scope) {
41 // Now resolve the native function to the corresponding native entrypoint.
42 if (library.native_entry_resolver() == nullptr) {
43 // Native methods are not allowed in the library to which this
44 // class belongs in.
45 return nullptr;
46 }
47 Dart_NativeFunction native_function = nullptr;
48 {
50 Api::Scope api_scope(T);
51 Dart_Handle api_function_name = Api::NewHandle(T, function_name.ptr());
52 {
54 TransitionVMToNative transition(T);
55 native_function =
56 resolver(api_function_name, number_of_arguments, auto_setup_scope);
57 }
58 }
59 return reinterpret_cast<NativeFunction>(native_function);
60}
61
62const uint8_t* NativeEntry::ResolveSymbolInLibrary(const Library& library,
63 uword pc) {
64 Dart_NativeEntrySymbol symbol_resolver =
66 if (symbol_resolver == nullptr) {
67 // Cannot reverse lookup native entries.
68 return nullptr;
69 }
70 return symbol_resolver(reinterpret_cast<Dart_NativeFunction>(pc));
71}
72
74 Thread* thread = Thread::Current();
76 GrowableObjectArray& libs = reused_growable_object_array_handle.Handle();
77 libs = thread->isolate_group()->object_store()->libraries();
78 ASSERT(!libs.IsNull());
79 intptr_t num_libs = libs.Length();
80 for (intptr_t i = 0; i < num_libs; i++) {
82 Library& lib = reused_library_handle.Handle();
83 lib ^= libs.At(i);
84 ASSERT(!lib.IsNull());
85 const uint8_t* r = ResolveSymbolInLibrary(lib, pc);
86 if (r != nullptr) {
87 return r;
88 }
89 }
90 return nullptr;
91}
92
93void NativeEntry::MaybePropagateError(NativeArguments* arguments) {
94 Thread* thread = arguments->thread();
95
96 // We must not access NativeArguments or the result's header under
97 // the kThreadInNative state.
99 ObjectPtr retval = arguments->ReturnValue();
100 if (UNLIKELY(retval->IsHeapObject() &&
101 IsErrorClassId(retval->GetClassId()))) {
102 thread->UnwindScopes(thread->top_exit_frame_info());
103
104 TransitionGeneratedToVM transition(thread);
105
106 // The thread->zone() is different here than before we unwound.
107 const Object& error =
108 Object::Handle(thread->zone(), arguments->ReturnValue());
109 Exceptions::PropagateError(Error::Cast(error));
110 UNREACHABLE();
111 }
112}
113
115 uword entry =
117#if defined(USING_SIMULATOR)
121#endif
122 return entry;
123}
124
126 Dart_NativeFunction func) {
128 if (func == LinkNativeCall) {
129 func(args);
130 return;
131 }
132
133 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
134 // Tell MemorySanitizer 'arguments' is initialized by generated code.
135 MSAN_UNPOISON(arguments, sizeof(*arguments));
136 {
137 Thread* thread = arguments->thread();
138 ASSERT(thread == Thread::Current());
139 TransitionGeneratedToVM transition(thread);
140 StackZone zone(thread);
141 // Be careful holding return_value_unsafe without a handle here.
142 // A return of Object::sentinel means the return value has already
143 // been set.
144 ObjectPtr return_value_unsafe = reinterpret_cast<BootstrapNativeFunction>(
145 reinterpret_cast<void*>(func))(thread, zone.GetZone(), arguments);
146 if (return_value_unsafe != Object::sentinel().ptr()) {
147 ASSERT(return_value_unsafe->IsDartInstance());
148 arguments->SetReturnUnsafe(return_value_unsafe);
149 }
151 }
152}
153
155 uword entry = reinterpret_cast<uword>(NativeEntry::NoScopeNativeCallWrapper);
156#if defined(USING_SIMULATOR)
160#endif
161 return entry;
162}
163
165 Dart_NativeFunction func) {
167 NoScopeNativeCallWrapperNoStackCheck(args, func);
168}
169
170void NativeEntry::NoScopeNativeCallWrapperNoStackCheck(
172 Dart_NativeFunction func) {
173 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
174 // Tell MemorySanitizer 'arguments' is initialized by generated code.
175 MSAN_UNPOISON(arguments, sizeof(*arguments));
176 Thread* thread = arguments->thread();
178 {
179 TransitionGeneratedToNative transition(thread);
180 func(args);
181 }
182 MaybePropagateError(arguments);
184}
185
187 uword entry =
189#if defined(USING_SIMULATOR)
193#endif
194 return entry;
195}
196
198 Dart_NativeFunction func) {
200 AutoScopeNativeCallWrapperNoStackCheck(args, func);
201}
202
203void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck(
205 Dart_NativeFunction func) {
206 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
207 // Tell MemorySanitizer 'arguments' is initialized by generated code.
208 MSAN_UNPOISON(arguments, sizeof(*arguments));
209 Thread* thread = arguments->thread();
211 {
212 Isolate* isolate = thread->isolate();
213 ApiState* state = isolate->group()->api_state();
214 ASSERT(state != nullptr);
215 TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func));
216 thread->EnterApiScope();
217 {
218 TransitionGeneratedToNative transition(thread);
219 func(args);
220 }
221 MaybePropagateError(arguments);
222 thread->ExitApiScope();
224 }
226}
227
229 const Function& func,
230 bool* is_bootstrap_native,
231 bool* is_auto_scope) {
232 const Class& cls = Class::Handle(zone, func.Owner());
233 const Library& library = Library::Handle(zone, cls.library());
234
235 *is_bootstrap_native =
237
238 const String& native_name = String::Handle(zone, func.native_name());
239 ASSERT(!native_name.IsNull());
240
241 const int num_params = NativeArguments::ParameterCountForResolution(func);
243 library, native_name, num_params, is_auto_scope);
244 if (native_function == nullptr) {
245 FATAL("Failed to resolve native function '%s' in '%s'\n",
246 native_name.ToCString(), func.ToQualifiedCString());
247 }
248 return native_function;
249}
250
252 uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall);
253 return entry;
254}
255
258 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
259 // Tell MemorySanitizer 'arguments' is initialized by generated code.
260 MSAN_UNPOISON(arguments, sizeof(*arguments));
261 TRACE_NATIVE_CALL("%s", "LinkNative");
262
263 NativeFunction target_function = nullptr;
264 bool is_bootstrap_native = false;
265 bool is_auto_scope = true;
266
267 {
268 TransitionGeneratedToVM transition(arguments->thread());
269 StackZone stack_zone(arguments->thread());
270 Zone* zone = stack_zone.GetZone();
271
272 DartFrameIterator iterator(arguments->thread(),
274 StackFrame* caller_frame = iterator.NextFrame();
275
276 Code& code = Code::Handle(zone, caller_frame->LookupDartCode());
277 Function& func = Function::Handle(zone, code.function());
278
279 if (FLAG_trace_natives) {
280 THR_Print("Resolving native target for %s\n", func.ToCString());
281 }
282
283 target_function =
284 ResolveNativeFunction(arguments->thread()->zone(), func,
285 &is_bootstrap_native, &is_auto_scope);
286 ASSERT(target_function != nullptr);
287
288#if defined(DEBUG)
289 NativeFunction current_function = nullptr;
290 const Code& current_trampoline =
292 caller_frame->pc(), code, &current_function));
293 // Some other isolate(with code being shared in AOT) might have updated
294 // target function/trampoline already.
295 ASSERT(current_function ==
296 reinterpret_cast<NativeFunction>(LinkNativeCall) ||
297 current_function == target_function);
298 ASSERT(current_trampoline.ptr() == StubCode::CallBootstrapNative().ptr() ||
299 current_function == target_function);
300#endif
301
302 NativeFunction patch_target_function = target_function;
303 Code& trampoline = Code::Handle(zone);
304 if (is_bootstrap_native) {
305 trampoline = StubCode::CallBootstrapNative().ptr();
306 } else if (is_auto_scope) {
307 trampoline = StubCode::CallAutoScopeNative().ptr();
308 } else {
309 trampoline = StubCode::CallNoScopeNative().ptr();
310 }
311 CodePatcher::PatchNativeCallAt(caller_frame->pc(), code,
312 patch_target_function, trampoline);
313
314 if (FLAG_trace_natives) {
315 THR_Print(" -> %p (%s)\n", target_function,
316 is_bootstrap_native ? "bootstrap" : "non-bootstrap");
317 }
318 }
319
320 // Tail-call resolved target.
321 if (is_bootstrap_native) {
323 args, reinterpret_cast<Dart_NativeFunction>(target_function));
324 } else if (is_auto_scope) {
325 // Because this call is within a compilation unit, Clang doesn't respect
326 // the ABI alignment here.
327 NativeEntry::AutoScopeNativeCallWrapperNoStackCheck(
328 args, reinterpret_cast<Dart_NativeFunction>(target_function));
329 } else {
330 // Because this call is within a compilation unit, Clang doesn't respect
331 // the ABI alignment here.
332 NativeEntry::NoScopeNativeCallWrapperNoStackCheck(
333 args, reinterpret_cast<Dart_NativeFunction>(target_function));
334 }
335}
336
337#if !defined(DART_PRECOMPILED_RUNTIME)
338
339// Note: not GC safe. Use with care.
340NativeEntryData::Payload* NativeEntryData::FromTypedArray(TypedDataPtr data) {
341 return reinterpret_cast<Payload*>(data->untag()->data());
342}
343
345 return FromTypedArray(data_.ptr())->kind;
346}
347
349 FromTypedArray(data_.ptr())->kind = value;
350}
351
353 return FromTypedArray(data)->kind;
354}
355
357 return FromTypedArray(data_.ptr())->trampoline;
358}
359
361 FromTypedArray(data_.ptr())->trampoline = value;
362}
363
365 return FromTypedArray(data)->trampoline;
366}
367
369 return FromTypedArray(data_.ptr())->native_function;
370}
371
373 FromTypedArray(data_.ptr())->native_function = value;
374}
375
377 return FromTypedArray(data)->native_function;
378}
379
381 return FromTypedArray(data_.ptr())->argc_tag;
382}
383
385 FromTypedArray(data_.ptr())->argc_tag = value;
386}
387
388intptr_t NativeEntryData::GetArgcTag(TypedDataPtr data) {
389 return FromTypedArray(data)->argc_tag;
390}
391
393 NativeFunctionWrapper trampoline,
394 NativeFunction native_function,
395 intptr_t argc_tag) {
397 TypedData::New(kTypedDataUint8ArrayCid, sizeof(Payload), Heap::kOld));
398 NativeEntryData native_entry(data);
399 native_entry.set_kind(kind);
400 native_entry.set_trampoline(trampoline);
402 native_entry.set_argc_tag(argc_tag);
403 return data.ptr();
404}
405
406#endif // !defined(DART_PRECOMPILED_RUNTIME)
407
408} // namespace dart
#define UNREACHABLE()
Definition: assert.h:248
static Dart_Handle NewHandle(Thread *thread, ObjectPtr raw)
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.h:10959
void SetAt(intptr_t index, const Object &value) const
Definition: object.h:10880
static bool IsBootstrapResolver(Dart_NativeEntryResolver resolver)
LibraryPtr library() const
Definition: object.h:1333
static CodePtr GetNativeCallAt(uword return_address, const Code &caller_code, NativeFunction *target)
static void PatchNativeCallAt(uword return_address, const Code &caller_code, NativeFunction target, const Code &trampoline)
StackFrame * NextFrame()
Definition: stack_frame.h:352
static DART_NORETURN void ThrowByType(ExceptionType type, const Array &arguments)
Definition: exceptions.cc:1052
static DART_NORETURN void ThrowArgumentError(const Instance &arg)
Definition: exceptions.cc:1082
static DART_NORETURN void PropagateError(const Error &error)
Definition: exceptions.cc:1003
StringPtr native_name() const
Definition: object.cc:8506
ClassPtr Owner() const
Definition: object.cc:10841
const char * ToQualifiedCString() const
Definition: object.cc:9776
@ kOld
Definition: heap.h:39
ObjectStore * object_store() const
Definition: isolate.h:510
ApiState * api_state() const
Definition: isolate.h:700
IsolateGroup * group() const
Definition: isolate.h:1037
Dart_NativeEntrySymbol native_entry_symbol_resolver() const
Definition: object.h:5238
Dart_NativeEntryResolver native_entry_resolver() const
Definition: object.h:5229
Thread * thread() const
static intptr_t ParameterCountForResolution(const Function &function)
ObjectPtr ReturnValue() const
void set_native_function(NativeFunction value) const
static MethodRecognizer::Kind GetKind(TypedDataPtr data)
void set_trampoline(NativeFunctionWrapper value) const
static NativeFunction GetNativeFunction(TypedDataPtr data)
NativeFunctionWrapper trampoline() const
void set_kind(MethodRecognizer::Kind value) const
void set_argc_tag(intptr_t value) const
static intptr_t GetArgcTag(TypedDataPtr data)
intptr_t argc_tag() const
static TypedDataPtr New(MethodRecognizer::Kind kind, NativeFunctionWrapper trampoline, NativeFunction native_function, intptr_t argc_tag)
MethodRecognizer::Kind kind() const
NativeFunction native_function() const
static NativeFunctionWrapper GetTrampoline(TypedDataPtr data)
static void AutoScopeNativeCallWrapper(Dart_NativeArguments args, Dart_NativeFunction func)
static void BootstrapNativeCallWrapper(Dart_NativeArguments args, Dart_NativeFunction func)
static const uint8_t * ResolveSymbol(uword pc)
Definition: native_entry.cc:73
static NativeFunction ResolveNative(const Library &library, const String &function_name, int number_of_arguments, bool *auto_setup_scope)
Definition: native_entry.cc:37
static void NoScopeNativeCallWrapper(Dart_NativeArguments args, Dart_NativeFunction func)
static uword NoScopeNativeCallWrapperEntry()
static void LinkNativeCall(Dart_NativeArguments args)
static uword AutoScopeNativeCallWrapperEntry()
static uword LinkNativeCallEntry()
static uword BootstrapNativeCallWrapperEntry()
static constexpr intptr_t kNumCallWrapperArguments
Definition: native_entry.h:99
static const uint8_t * ResolveSymbolInLibrary(const Library &library, uword pc)
Definition: native_entry.cc:62
bool IsDartInstance() const
intptr_t GetClassId() const
Definition: raw_object.h:885
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
static uword RedirectExternalReference(uword function, CallKind call_kind, int argument_count)
uword pc() const
Definition: stack_frame.h:43
CodePtr LookupDartCode() const
Definition: stack_frame.cc:336
Zone * GetZone()
Definition: zone.h:213
static StringPtr NewFormatted(const char *format,...) PRINTF_ATTRIBUTE(1
Definition: object.cc:24004
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition: object.cc:24126
Zone * zone() const
Definition: thread_state.h:37
void UnwindScopes(uword stack_marker)
Definition: thread.cc:1328
static Thread * Current()
Definition: thread.h:362
void EnterApiScope()
Definition: thread.cc:1301
void ExitApiScope()
Definition: thread.cc:1314
uword top_exit_frame_info() const
Definition: thread.h:691
ExecutionState execution_state() const
Definition: thread.h:1040
Isolate * isolate() const
Definition: thread.h:534
@ kThreadInGenerated
Definition: thread.h:1035
IsolateGroup * isolate_group() const
Definition: thread.h:541
static TypedDataPtr New(intptr_t class_id, intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.cc:25587
#define THR_Print(format,...)
Definition: log.h:20
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
Dart_NativeFunction(* Dart_NativeEntryResolver)(Dart_Handle name, int num_of_arguments, bool *auto_setup_scope)
Definition: dart_api.h:3234
const uint8_t *(* Dart_NativeEntrySymbol)(Dart_NativeFunction nf)
Definition: dart_api.h:3255
struct _Dart_NativeArguments * Dart_NativeArguments
Definition: dart_api.h:3019
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
Definition: dart_api.h:3207
#define ASSERT(E)
VkInstance instance
Definition: main.cc:48
#define FATAL(error)
AtkStateType state
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
#define MSAN_UNPOISON(ptr, len)
Definition: dart_vm.cc:33
void(* NativeFunctionWrapper)(Dart_NativeArguments args, Dart_NativeFunction func)
bool IsErrorClassId(intptr_t index)
Definition: class_id.h:321
uintptr_t uword
Definition: globals.h:501
void DartNativeThrowArgumentException(const Instance &instance)
Definition: native_entry.cc:31
ObjectPtr(* BootstrapNativeFunction)(Thread *thread, Zone *zone, NativeArguments *arguments)
Definition: native_entry.h:35
static NativeFunction ResolveNativeFunction(Zone *zone, const Function &func, bool *is_bootstrap_native, bool *is_auto_scope)
void DartNativeThrowTypeArgumentCountException(int num_type_args, int num_type_args_expected)
Definition: native_entry.cc:23
const char *const function_name
static int8_t data[kExtLength]
void(* NativeFunction)(NativeArguments *arguments)
#define CHECK_STACK_ALIGNMENT
#define DEOPTIMIZE_ALOT
#define TRACE_NATIVE_CALL(format, name)
Definition: native_entry.h:30
#define Px
Definition: globals.h:410
#define UNLIKELY(cond)
Definition: globals.h:261
#define T
Definition: precompiler.cc:65
#define REUSABLE_GROWABLE_OBJECT_ARRAY_HANDLESCOPE(thread)
#define REUSABLE_LIBRARY_HANDLESCOPE(thread)