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" |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 ASSERT(!lib.IsNull()); | 84 ASSERT(!lib.IsNull()); |
85 const uint8_t* r = ResolveSymbolInLibrary(lib, pc); | 85 const uint8_t* r = ResolveSymbolInLibrary(lib, pc); |
86 if (r != NULL) { | 86 if (r != NULL) { |
87 return r; | 87 return r; |
88 } | 88 } |
89 } | 89 } |
90 return NULL; | 90 return NULL; |
91 } | 91 } |
92 | 92 |
93 | 93 |
94 uword NativeEntry::NativeCallWrapperEntry() { | |
95 uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper); | |
96 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) | |
97 // DBC does not use redirections unlike other simulators. | |
98 entry = Simulator::RedirectExternalReference( | |
99 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); | |
100 #endif | |
101 return entry; | |
102 } | |
103 | |
104 | |
105 bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) { | 94 bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) { |
106 RawObject* retval = arguments->ReturnValue(); | 95 RawObject* retval = arguments->ReturnValue(); |
107 return (retval->IsHeapObject() && | 96 return (retval->IsHeapObject() && |
108 RawObject::IsErrorClassId(retval->GetClassId())); | 97 RawObject::IsErrorClassId(retval->GetClassId())); |
109 } | 98 } |
110 | 99 |
111 | 100 |
112 void NativeEntry::PropagateErrors(NativeArguments* arguments) { | 101 void NativeEntry::PropagateErrors(NativeArguments* arguments) { |
113 Thread* thread = arguments->thread(); | 102 Thread* thread = arguments->thread(); |
114 thread->UnwindScopes(thread->top_exit_frame_info()); | 103 thread->UnwindScopes(thread->top_exit_frame_info()); |
115 | 104 |
116 // The thread->zone() is different here than before we unwound. | 105 // The thread->zone() is different here than before we unwound. |
117 const Object& error = | 106 const Object& error = |
118 Object::Handle(thread->zone(), arguments->ReturnValue()); | 107 Object::Handle(thread->zone(), arguments->ReturnValue()); |
119 Exceptions::PropagateError(Error::Cast(error)); | 108 Exceptions::PropagateError(Error::Cast(error)); |
120 UNREACHABLE(); | 109 UNREACHABLE(); |
121 } | 110 } |
122 | 111 |
123 | 112 |
124 void NativeEntry::NativeCallWrapper(Dart_NativeArguments args, | 113 uword NativeEntry::NoScopeNativeCallWrapperEntry() { |
125 Dart_NativeFunction func) { | 114 uword entry = reinterpret_cast<uword>(NativeEntry::NoScopeNativeCallWrapper); |
126 CHECK_STACK_ALIGNMENT; | 115 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) |
127 NativeCallWrapperNoStackCheck(args, func); | 116 // DBC does not use redirections unlike other simulators. |
| 117 entry = Simulator::RedirectExternalReference( |
| 118 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); |
| 119 #endif |
| 120 return entry; |
128 } | 121 } |
129 | 122 |
130 | 123 |
131 void NativeEntry::NativeCallWrapperNoStackCheck(Dart_NativeArguments args, | 124 void NativeEntry::NoScopeNativeCallWrapper(Dart_NativeArguments args, |
132 Dart_NativeFunction func) { | 125 Dart_NativeFunction func) { |
| 126 CHECK_STACK_ALIGNMENT; |
| 127 NoScopeNativeCallWrapperNoStackCheck(args, func); |
| 128 } |
| 129 |
| 130 |
| 131 void NativeEntry::NoScopeNativeCallWrapperNoStackCheck( |
| 132 Dart_NativeArguments args, |
| 133 Dart_NativeFunction func) { |
133 VERIFY_ON_TRANSITION; | 134 VERIFY_ON_TRANSITION; |
134 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 135 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
135 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 136 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
136 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 137 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
137 Thread* thread = arguments->thread(); | 138 Thread* thread = arguments->thread(); |
138 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 139 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
139 if (!arguments->IsNativeAutoSetupScope()) { | 140 { |
140 TransitionGeneratedToNative transition(thread); | 141 TransitionGeneratedToNative transition(thread); |
141 func(args); | 142 func(args); |
142 if (ReturnValueIsError(arguments)) { | 143 if (ReturnValueIsError(arguments)) { |
143 PropagateErrors(arguments); | 144 PropagateErrors(arguments); |
144 } | 145 } |
145 } else { | 146 } |
| 147 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
| 148 VERIFY_ON_TRANSITION; |
| 149 } |
| 150 |
| 151 |
| 152 uword NativeEntry::AutoScopeNativeCallWrapperEntry() { |
| 153 uword entry = |
| 154 reinterpret_cast<uword>(NativeEntry::AutoScopeNativeCallWrapper); |
| 155 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) |
| 156 // DBC does not use redirections unlike other simulators. |
| 157 entry = Simulator::RedirectExternalReference( |
| 158 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); |
| 159 #endif |
| 160 return entry; |
| 161 } |
| 162 |
| 163 |
| 164 void NativeEntry::AutoScopeNativeCallWrapper(Dart_NativeArguments args, |
| 165 Dart_NativeFunction func) { |
| 166 CHECK_STACK_ALIGNMENT; |
| 167 AutoScopeNativeCallWrapperNoStackCheck(args, func); |
| 168 } |
| 169 |
| 170 |
| 171 void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck( |
| 172 Dart_NativeArguments args, |
| 173 Dart_NativeFunction func) { |
| 174 VERIFY_ON_TRANSITION; |
| 175 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
| 176 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
| 177 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
| 178 Thread* thread = arguments->thread(); |
| 179 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
| 180 { |
146 Isolate* isolate = thread->isolate(); | 181 Isolate* isolate = thread->isolate(); |
147 ApiState* state = isolate->api_state(); | 182 ApiState* state = isolate->api_state(); |
148 ASSERT(state != NULL); | 183 ASSERT(state != NULL); |
149 ApiLocalScope* current_top_scope = thread->api_top_scope(); | 184 ApiLocalScope* current_top_scope = thread->api_top_scope(); |
150 ApiLocalScope* scope = thread->api_reusable_scope(); | 185 ApiLocalScope* scope = thread->api_reusable_scope(); |
151 TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func)); | 186 TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func)); |
152 TransitionGeneratedToNative transition(thread); | 187 TransitionGeneratedToNative transition(thread); |
153 if (scope == NULL) { | 188 if (scope == NULL) { |
154 scope = | 189 scope = |
155 new ApiLocalScope(current_top_scope, thread->top_exit_frame_info()); | 190 new ApiLocalScope(current_top_scope, thread->top_exit_frame_info()); |
(...skipping 22 matching lines...) Expand all Loading... |
178 } | 213 } |
179 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 214 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
180 VERIFY_ON_TRANSITION; | 215 VERIFY_ON_TRANSITION; |
181 } | 216 } |
182 | 217 |
183 | 218 |
184 // DBC does not support lazy native call linking. | 219 // DBC does not support lazy native call linking. |
185 #if !defined(TARGET_ARCH_DBC) | 220 #if !defined(TARGET_ARCH_DBC) |
186 static NativeFunction ResolveNativeFunction(Zone* zone, | 221 static NativeFunction ResolveNativeFunction(Zone* zone, |
187 const Function& func, | 222 const Function& func, |
188 bool* is_bootstrap_native) { | 223 bool* is_bootstrap_native, |
| 224 bool* is_auto_scope) { |
189 const Class& cls = Class::Handle(zone, func.Owner()); | 225 const Class& cls = Class::Handle(zone, func.Owner()); |
190 const Library& library = Library::Handle(zone, cls.library()); | 226 const Library& library = Library::Handle(zone, cls.library()); |
191 | 227 |
192 *is_bootstrap_native = | 228 *is_bootstrap_native = |
193 Bootstrap::IsBootstapResolver(library.native_entry_resolver()); | 229 Bootstrap::IsBootstapResolver(library.native_entry_resolver()); |
194 | 230 |
195 const String& native_name = String::Handle(zone, func.native_name()); | 231 const String& native_name = String::Handle(zone, func.native_name()); |
196 ASSERT(!native_name.IsNull()); | 232 ASSERT(!native_name.IsNull()); |
197 | 233 |
198 const int num_params = NativeArguments::ParameterCountForResolution(func); | 234 const int num_params = NativeArguments::ParameterCountForResolution(func); |
199 bool auto_setup_scope = true; | |
200 return NativeEntry::ResolveNative(library, native_name, num_params, | 235 return NativeEntry::ResolveNative(library, native_name, num_params, |
201 &auto_setup_scope); | 236 is_auto_scope); |
202 } | 237 } |
203 | 238 |
204 | 239 |
205 uword NativeEntry::LinkNativeCallEntry() { | 240 uword NativeEntry::LinkNativeCallEntry() { |
206 uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall); | 241 uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall); |
207 #if defined(USING_SIMULATOR) | 242 #if defined(USING_SIMULATOR) |
208 entry = Simulator::RedirectExternalReference( | 243 entry = Simulator::RedirectExternalReference( |
209 entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments); | 244 entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments); |
210 #endif | 245 #endif |
211 return entry; | 246 return entry; |
212 } | 247 } |
213 | 248 |
214 | 249 |
215 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { | 250 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { |
216 CHECK_STACK_ALIGNMENT; | 251 CHECK_STACK_ALIGNMENT; |
217 VERIFY_ON_TRANSITION; | 252 VERIFY_ON_TRANSITION; |
218 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 253 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
219 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 254 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
220 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 255 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
221 TRACE_NATIVE_CALL("%s", "LinkNative"); | 256 TRACE_NATIVE_CALL("%s", "LinkNative"); |
222 | 257 |
223 NativeFunction target_function = NULL; | 258 NativeFunction target_function = NULL; |
224 bool call_through_wrapper = false; | 259 bool is_bootstrap_native = false; |
| 260 bool is_auto_scope = true; |
225 | 261 |
226 { | 262 { |
227 TransitionGeneratedToVM transition(arguments->thread()); | 263 TransitionGeneratedToVM transition(arguments->thread()); |
228 StackZone zone(arguments->thread()); | 264 StackZone stack_zone(arguments->thread()); |
| 265 Zone* zone = stack_zone.GetZone(); |
229 | 266 |
230 DartFrameIterator iterator; | 267 DartFrameIterator iterator; |
231 StackFrame* caller_frame = iterator.NextFrame(); | 268 StackFrame* caller_frame = iterator.NextFrame(); |
232 | 269 |
233 const Code& code = Code::Handle(caller_frame->LookupDartCode()); | 270 const Code& code = Code::Handle(zone, caller_frame->LookupDartCode()); |
234 const Function& func = Function::Handle(code.function()); | 271 const Function& func = Function::Handle(zone, code.function()); |
235 | 272 |
236 if (FLAG_trace_natives) { | 273 if (FLAG_trace_natives) { |
237 OS::Print("Resolving native target for %s\n", func.ToCString()); | 274 OS::Print("Resolving native target for %s\n", func.ToCString()); |
238 } | 275 } |
239 | 276 |
240 bool is_bootstrap_native = false; | 277 target_function = |
241 target_function = ResolveNativeFunction(arguments->thread()->zone(), func, | 278 ResolveNativeFunction(arguments->thread()->zone(), func, |
242 &is_bootstrap_native); | 279 &is_bootstrap_native, &is_auto_scope); |
243 ASSERT(target_function != NULL); | 280 ASSERT(target_function != NULL); |
244 | 281 |
245 #if defined(DEBUG) | 282 #if defined(DEBUG) |
246 { | 283 { |
247 NativeFunction current_function = NULL; | 284 NativeFunction current_function = NULL; |
248 const Code& current_trampoline = | 285 const Code& current_trampoline = |
249 Code::Handle(CodePatcher::GetNativeCallAt(caller_frame->pc(), code, | 286 Code::Handle(zone, CodePatcher::GetNativeCallAt( |
250 ¤t_function)); | 287 caller_frame->pc(), code, ¤t_function)); |
251 #if !defined(USING_SIMULATOR) | 288 #if !defined(USING_SIMULATOR) |
252 ASSERT(current_function == | 289 ASSERT(current_function == |
253 reinterpret_cast<NativeFunction>(LinkNativeCall)); | 290 reinterpret_cast<NativeFunction>(LinkNativeCall)); |
254 #else | 291 #else |
255 ASSERT( | 292 ASSERT( |
256 current_function == | 293 current_function == |
257 reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference( | 294 reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference( |
258 reinterpret_cast<uword>(LinkNativeCall), | 295 reinterpret_cast<uword>(LinkNativeCall), |
259 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments))); | 296 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments))); |
260 #endif | 297 #endif |
261 ASSERT(current_trampoline.raw() == | 298 ASSERT(current_trampoline.raw() == |
262 StubCode::CallBootstrapCFunction_entry()->code()); | 299 StubCode::CallBootstrapNative_entry()->code()); |
263 } | 300 } |
264 #endif | 301 #endif |
265 | 302 |
266 call_through_wrapper = !is_bootstrap_native; | |
267 const Code& trampoline = | |
268 Code::Handle(call_through_wrapper | |
269 ? StubCode::CallNativeCFunction_entry()->code() | |
270 : StubCode::CallBootstrapCFunction_entry()->code()); | |
271 | |
272 NativeFunction patch_target_function = target_function; | 303 NativeFunction patch_target_function = target_function; |
| 304 Code& trampoline = Code::Handle(zone); |
| 305 if (is_bootstrap_native) { |
| 306 trampoline = StubCode::CallBootstrapNative_entry()->code(); |
273 #if defined(USING_SIMULATOR) | 307 #if defined(USING_SIMULATOR) |
274 if (!call_through_wrapper) { | |
275 patch_target_function = | 308 patch_target_function = |
276 reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference( | 309 reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference( |
277 reinterpret_cast<uword>(patch_target_function), | 310 reinterpret_cast<uword>(patch_target_function), |
278 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)); | 311 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)); |
| 312 #endif |
| 313 } else if (is_auto_scope) { |
| 314 trampoline = StubCode::CallAutoScopeNative_entry()->code(); |
| 315 } else { |
| 316 trampoline = StubCode::CallNoScopeNative_entry()->code(); |
279 } | 317 } |
280 #endif | |
281 | 318 |
282 CodePatcher::PatchNativeCallAt(caller_frame->pc(), code, | 319 CodePatcher::PatchNativeCallAt(caller_frame->pc(), code, |
283 patch_target_function, trampoline); | 320 patch_target_function, trampoline); |
284 | 321 |
285 if (FLAG_trace_natives) { | 322 if (FLAG_trace_natives) { |
286 OS::Print(" -> %p (%s)\n", target_function, | 323 OS::Print(" -> %p (%s)\n", target_function, |
287 is_bootstrap_native ? "bootstrap" : "non-bootstrap"); | 324 is_bootstrap_native ? "bootstrap" : "non-bootstrap"); |
288 } | 325 } |
289 } | 326 } |
290 VERIFY_ON_TRANSITION; | 327 VERIFY_ON_TRANSITION; |
291 | 328 |
292 // Tail-call resolved target. | 329 // Tail-call resolved target. |
293 if (call_through_wrapper) { | 330 if (is_bootstrap_native) { |
| 331 target_function(arguments); |
| 332 } else if (is_auto_scope) { |
294 // Because this call is within a compilation unit, Clang doesn't respect | 333 // Because this call is within a compilation unit, Clang doesn't respect |
295 // the ABI alignment here. | 334 // the ABI alignment here. |
296 NativeEntry::NativeCallWrapperNoStackCheck( | 335 NativeEntry::AutoScopeNativeCallWrapperNoStackCheck( |
297 args, reinterpret_cast<Dart_NativeFunction>(target_function)); | 336 args, reinterpret_cast<Dart_NativeFunction>(target_function)); |
298 } else { | 337 } else { |
299 target_function(arguments); | 338 // Because this call is within a compilation unit, Clang doesn't respect |
| 339 // the ABI alignment here. |
| 340 NativeEntry::NoScopeNativeCallWrapperNoStackCheck( |
| 341 args, reinterpret_cast<Dart_NativeFunction>(target_function)); |
300 } | 342 } |
301 } | 343 } |
302 #endif // !defined(TARGET_ARCH_DBC) | 344 #endif // !defined(TARGET_ARCH_DBC) |
303 | 345 |
304 | 346 |
305 } // namespace dart | 347 } // namespace dart |
OLD | NEW |