OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/native_entry.h" | 5 #include "vm/native_entry.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 | 8 |
9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
11 #include "vm/dart_api_impl.h" | 11 #include "vm/dart_api_impl.h" |
12 #include "vm/dart_api_state.h" | 12 #include "vm/dart_api_state.h" |
13 #include "vm/native_symbol.h" | 13 #include "vm/native_symbol.h" |
14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
15 #include "vm/reusable_handles.h" | 15 #include "vm/reusable_handles.h" |
16 #include "vm/safepoint.h" | 16 #include "vm/safepoint.h" |
17 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
18 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
19 #include "vm/tags.h" | 19 #include "vm/tags.h" |
20 | 20 |
21 | |
22 namespace dart { | 21 namespace dart { |
23 | 22 |
24 DEFINE_FLAG(bool, | 23 DEFINE_FLAG(bool, |
25 trace_natives, | 24 trace_natives, |
26 false, | 25 false, |
27 "Trace invocation of natives (debug mode only)"); | 26 "Trace invocation of natives (debug mode only)"); |
28 | 27 |
29 | |
30 void DartNativeThrowArgumentException(const Instance& instance) { | 28 void DartNativeThrowArgumentException(const Instance& instance) { |
31 const Array& __args__ = Array::Handle(Array::New(1)); | 29 const Array& __args__ = Array::Handle(Array::New(1)); |
32 __args__.SetAt(0, instance); | 30 __args__.SetAt(0, instance); |
33 Exceptions::ThrowByType(Exceptions::kArgument, __args__); | 31 Exceptions::ThrowByType(Exceptions::kArgument, __args__); |
34 } | 32 } |
35 | 33 |
36 | |
37 NativeFunction NativeEntry::ResolveNative(const Library& library, | 34 NativeFunction NativeEntry::ResolveNative(const Library& library, |
38 const String& function_name, | 35 const String& function_name, |
39 int number_of_arguments, | 36 int number_of_arguments, |
40 bool* auto_setup_scope) { | 37 bool* auto_setup_scope) { |
41 // Now resolve the native function to the corresponding native entrypoint. | 38 // Now resolve the native function to the corresponding native entrypoint. |
42 if (library.native_entry_resolver() == 0) { | 39 if (library.native_entry_resolver() == 0) { |
43 // Native methods are not allowed in the library to which this | 40 // Native methods are not allowed in the library to which this |
44 // class belongs in. | 41 // class belongs in. |
45 return NULL; | 42 return NULL; |
46 } | 43 } |
47 Dart_NativeFunction native_function = NULL; | 44 Dart_NativeFunction native_function = NULL; |
48 { | 45 { |
49 Thread* T = Thread::Current(); | 46 Thread* T = Thread::Current(); |
50 TransitionVMToNative transition(T); | 47 TransitionVMToNative transition(T); |
51 Dart_EnterScope(); // Enter a new Dart API scope as we invoke API entries. | 48 Dart_EnterScope(); // Enter a new Dart API scope as we invoke API entries. |
52 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); | 49 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); |
53 native_function = resolver(Api::NewHandle(T, function_name.raw()), | 50 native_function = resolver(Api::NewHandle(T, function_name.raw()), |
54 number_of_arguments, auto_setup_scope); | 51 number_of_arguments, auto_setup_scope); |
55 Dart_ExitScope(); // Exit the Dart API scope. | 52 Dart_ExitScope(); // Exit the Dart API scope. |
56 } | 53 } |
57 return reinterpret_cast<NativeFunction>(native_function); | 54 return reinterpret_cast<NativeFunction>(native_function); |
58 } | 55 } |
59 | 56 |
60 | |
61 const uint8_t* NativeEntry::ResolveSymbolInLibrary(const Library& library, | 57 const uint8_t* NativeEntry::ResolveSymbolInLibrary(const Library& library, |
62 uword pc) { | 58 uword pc) { |
63 Dart_NativeEntrySymbol symbol_resolver = | 59 Dart_NativeEntrySymbol symbol_resolver = |
64 library.native_entry_symbol_resolver(); | 60 library.native_entry_symbol_resolver(); |
65 if (symbol_resolver == 0) { | 61 if (symbol_resolver == 0) { |
66 // Cannot reverse lookup native entries. | 62 // Cannot reverse lookup native entries. |
67 return NULL; | 63 return NULL; |
68 } | 64 } |
69 return symbol_resolver(reinterpret_cast<Dart_NativeFunction>(pc)); | 65 return symbol_resolver(reinterpret_cast<Dart_NativeFunction>(pc)); |
70 } | 66 } |
71 | 67 |
72 | |
73 const uint8_t* NativeEntry::ResolveSymbol(uword pc) { | 68 const uint8_t* NativeEntry::ResolveSymbol(uword pc) { |
74 Thread* thread = Thread::Current(); | 69 Thread* thread = Thread::Current(); |
75 REUSABLE_GROWABLE_OBJECT_ARRAY_HANDLESCOPE(thread); | 70 REUSABLE_GROWABLE_OBJECT_ARRAY_HANDLESCOPE(thread); |
76 GrowableObjectArray& libs = reused_growable_object_array_handle.Handle(); | 71 GrowableObjectArray& libs = reused_growable_object_array_handle.Handle(); |
77 libs ^= thread->isolate()->object_store()->libraries(); | 72 libs ^= thread->isolate()->object_store()->libraries(); |
78 ASSERT(!libs.IsNull()); | 73 ASSERT(!libs.IsNull()); |
79 intptr_t num_libs = libs.Length(); | 74 intptr_t num_libs = libs.Length(); |
80 for (intptr_t i = 0; i < num_libs; i++) { | 75 for (intptr_t i = 0; i < num_libs; i++) { |
81 REUSABLE_LIBRARY_HANDLESCOPE(thread); | 76 REUSABLE_LIBRARY_HANDLESCOPE(thread); |
82 Library& lib = reused_library_handle.Handle(); | 77 Library& lib = reused_library_handle.Handle(); |
83 lib ^= libs.At(i); | 78 lib ^= libs.At(i); |
84 ASSERT(!lib.IsNull()); | 79 ASSERT(!lib.IsNull()); |
85 const uint8_t* r = ResolveSymbolInLibrary(lib, pc); | 80 const uint8_t* r = ResolveSymbolInLibrary(lib, pc); |
86 if (r != NULL) { | 81 if (r != NULL) { |
87 return r; | 82 return r; |
88 } | 83 } |
89 } | 84 } |
90 return NULL; | 85 return NULL; |
91 } | 86 } |
92 | 87 |
93 | |
94 bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) { | 88 bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) { |
95 RawObject* retval = arguments->ReturnValue(); | 89 RawObject* retval = arguments->ReturnValue(); |
96 return (retval->IsHeapObject() && | 90 return (retval->IsHeapObject() && |
97 RawObject::IsErrorClassId(retval->GetClassId())); | 91 RawObject::IsErrorClassId(retval->GetClassId())); |
98 } | 92 } |
99 | 93 |
100 | |
101 void NativeEntry::PropagateErrors(NativeArguments* arguments) { | 94 void NativeEntry::PropagateErrors(NativeArguments* arguments) { |
102 Thread* thread = arguments->thread(); | 95 Thread* thread = arguments->thread(); |
103 thread->UnwindScopes(thread->top_exit_frame_info()); | 96 thread->UnwindScopes(thread->top_exit_frame_info()); |
104 | 97 |
105 // The thread->zone() is different here than before we unwound. | 98 // The thread->zone() is different here than before we unwound. |
106 const Object& error = | 99 const Object& error = |
107 Object::Handle(thread->zone(), arguments->ReturnValue()); | 100 Object::Handle(thread->zone(), arguments->ReturnValue()); |
108 Exceptions::PropagateError(Error::Cast(error)); | 101 Exceptions::PropagateError(Error::Cast(error)); |
109 UNREACHABLE(); | 102 UNREACHABLE(); |
110 } | 103 } |
111 | 104 |
112 | |
113 uword NativeEntry::NoScopeNativeCallWrapperEntry() { | 105 uword NativeEntry::NoScopeNativeCallWrapperEntry() { |
114 uword entry = reinterpret_cast<uword>(NativeEntry::NoScopeNativeCallWrapper); | 106 uword entry = reinterpret_cast<uword>(NativeEntry::NoScopeNativeCallWrapper); |
115 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) | 107 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) |
116 // DBC does not use redirections unlike other simulators. | 108 // DBC does not use redirections unlike other simulators. |
117 entry = Simulator::RedirectExternalReference( | 109 entry = Simulator::RedirectExternalReference( |
118 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); | 110 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); |
119 #endif | 111 #endif |
120 return entry; | 112 return entry; |
121 } | 113 } |
122 | 114 |
123 | |
124 void NativeEntry::NoScopeNativeCallWrapper(Dart_NativeArguments args, | 115 void NativeEntry::NoScopeNativeCallWrapper(Dart_NativeArguments args, |
125 Dart_NativeFunction func) { | 116 Dart_NativeFunction func) { |
126 CHECK_STACK_ALIGNMENT; | 117 CHECK_STACK_ALIGNMENT; |
127 NoScopeNativeCallWrapperNoStackCheck(args, func); | 118 NoScopeNativeCallWrapperNoStackCheck(args, func); |
128 } | 119 } |
129 | 120 |
130 | |
131 void NativeEntry::NoScopeNativeCallWrapperNoStackCheck( | 121 void NativeEntry::NoScopeNativeCallWrapperNoStackCheck( |
132 Dart_NativeArguments args, | 122 Dart_NativeArguments args, |
133 Dart_NativeFunction func) { | 123 Dart_NativeFunction func) { |
134 VERIFY_ON_TRANSITION; | 124 VERIFY_ON_TRANSITION; |
135 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 125 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
136 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 126 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
137 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 127 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
138 Thread* thread = arguments->thread(); | 128 Thread* thread = arguments->thread(); |
139 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 129 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
140 { | 130 { |
141 TransitionGeneratedToNative transition(thread); | 131 TransitionGeneratedToNative transition(thread); |
142 func(args); | 132 func(args); |
143 if (ReturnValueIsError(arguments)) { | 133 if (ReturnValueIsError(arguments)) { |
144 PropagateErrors(arguments); | 134 PropagateErrors(arguments); |
145 } | 135 } |
146 } | 136 } |
147 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 137 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
148 VERIFY_ON_TRANSITION; | 138 VERIFY_ON_TRANSITION; |
149 } | 139 } |
150 | 140 |
151 | |
152 uword NativeEntry::AutoScopeNativeCallWrapperEntry() { | 141 uword NativeEntry::AutoScopeNativeCallWrapperEntry() { |
153 uword entry = | 142 uword entry = |
154 reinterpret_cast<uword>(NativeEntry::AutoScopeNativeCallWrapper); | 143 reinterpret_cast<uword>(NativeEntry::AutoScopeNativeCallWrapper); |
155 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) | 144 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) |
156 // DBC does not use redirections unlike other simulators. | 145 // DBC does not use redirections unlike other simulators. |
157 entry = Simulator::RedirectExternalReference( | 146 entry = Simulator::RedirectExternalReference( |
158 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); | 147 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); |
159 #endif | 148 #endif |
160 return entry; | 149 return entry; |
161 } | 150 } |
162 | 151 |
163 | |
164 void NativeEntry::AutoScopeNativeCallWrapper(Dart_NativeArguments args, | 152 void NativeEntry::AutoScopeNativeCallWrapper(Dart_NativeArguments args, |
165 Dart_NativeFunction func) { | 153 Dart_NativeFunction func) { |
166 CHECK_STACK_ALIGNMENT; | 154 CHECK_STACK_ALIGNMENT; |
167 AutoScopeNativeCallWrapperNoStackCheck(args, func); | 155 AutoScopeNativeCallWrapperNoStackCheck(args, func); |
168 } | 156 } |
169 | 157 |
170 | |
171 void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck( | 158 void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck( |
172 Dart_NativeArguments args, | 159 Dart_NativeArguments args, |
173 Dart_NativeFunction func) { | 160 Dart_NativeFunction func) { |
174 VERIFY_ON_TRANSITION; | 161 VERIFY_ON_TRANSITION; |
175 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 162 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
176 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 163 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
177 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 164 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
178 Thread* thread = arguments->thread(); | 165 Thread* thread = arguments->thread(); |
179 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 166 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
180 { | 167 { |
(...skipping 27 matching lines...) Expand all Loading... |
208 } else { | 195 } else { |
209 ASSERT(thread->api_reusable_scope() != scope); | 196 ASSERT(thread->api_reusable_scope() != scope); |
210 delete scope; | 197 delete scope; |
211 } | 198 } |
212 DEOPTIMIZE_ALOT; | 199 DEOPTIMIZE_ALOT; |
213 } | 200 } |
214 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 201 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
215 VERIFY_ON_TRANSITION; | 202 VERIFY_ON_TRANSITION; |
216 } | 203 } |
217 | 204 |
218 | |
219 // DBC does not support lazy native call linking. | 205 // DBC does not support lazy native call linking. |
220 #if !defined(TARGET_ARCH_DBC) | 206 #if !defined(TARGET_ARCH_DBC) |
221 static NativeFunction ResolveNativeFunction(Zone* zone, | 207 static NativeFunction ResolveNativeFunction(Zone* zone, |
222 const Function& func, | 208 const Function& func, |
223 bool* is_bootstrap_native, | 209 bool* is_bootstrap_native, |
224 bool* is_auto_scope) { | 210 bool* is_auto_scope) { |
225 const Class& cls = Class::Handle(zone, func.Owner()); | 211 const Class& cls = Class::Handle(zone, func.Owner()); |
226 const Library& library = Library::Handle(zone, cls.library()); | 212 const Library& library = Library::Handle(zone, cls.library()); |
227 | 213 |
228 *is_bootstrap_native = | 214 *is_bootstrap_native = |
229 Bootstrap::IsBootstapResolver(library.native_entry_resolver()); | 215 Bootstrap::IsBootstapResolver(library.native_entry_resolver()); |
230 | 216 |
231 const String& native_name = String::Handle(zone, func.native_name()); | 217 const String& native_name = String::Handle(zone, func.native_name()); |
232 ASSERT(!native_name.IsNull()); | 218 ASSERT(!native_name.IsNull()); |
233 | 219 |
234 const int num_params = NativeArguments::ParameterCountForResolution(func); | 220 const int num_params = NativeArguments::ParameterCountForResolution(func); |
235 return NativeEntry::ResolveNative(library, native_name, num_params, | 221 return NativeEntry::ResolveNative(library, native_name, num_params, |
236 is_auto_scope); | 222 is_auto_scope); |
237 } | 223 } |
238 | 224 |
239 | |
240 uword NativeEntry::LinkNativeCallEntry() { | 225 uword NativeEntry::LinkNativeCallEntry() { |
241 uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall); | 226 uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall); |
242 #if defined(USING_SIMULATOR) | 227 #if defined(USING_SIMULATOR) |
243 entry = Simulator::RedirectExternalReference( | 228 entry = Simulator::RedirectExternalReference( |
244 entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments); | 229 entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments); |
245 #endif | 230 #endif |
246 return entry; | 231 return entry; |
247 } | 232 } |
248 | 233 |
249 | |
250 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { | 234 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { |
251 CHECK_STACK_ALIGNMENT; | 235 CHECK_STACK_ALIGNMENT; |
252 VERIFY_ON_TRANSITION; | 236 VERIFY_ON_TRANSITION; |
253 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 237 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
254 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 238 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
255 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 239 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
256 TRACE_NATIVE_CALL("%s", "LinkNative"); | 240 TRACE_NATIVE_CALL("%s", "LinkNative"); |
257 | 241 |
258 NativeFunction target_function = NULL; | 242 NativeFunction target_function = NULL; |
259 bool is_bootstrap_native = false; | 243 bool is_bootstrap_native = false; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 args, reinterpret_cast<Dart_NativeFunction>(target_function)); | 321 args, reinterpret_cast<Dart_NativeFunction>(target_function)); |
338 } else { | 322 } else { |
339 // Because this call is within a compilation unit, Clang doesn't respect | 323 // Because this call is within a compilation unit, Clang doesn't respect |
340 // the ABI alignment here. | 324 // the ABI alignment here. |
341 NativeEntry::NoScopeNativeCallWrapperNoStackCheck( | 325 NativeEntry::NoScopeNativeCallWrapperNoStackCheck( |
342 args, reinterpret_cast<Dart_NativeFunction>(target_function)); | 326 args, reinterpret_cast<Dart_NativeFunction>(target_function)); |
343 } | 327 } |
344 } | 328 } |
345 #endif // !defined(TARGET_ARCH_DBC) | 329 #endif // !defined(TARGET_ARCH_DBC) |
346 | 330 |
347 | |
348 } // namespace dart | 331 } // namespace dart |
OLD | NEW |