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/object_store.h" | 13 #include "vm/object_store.h" |
14 #include "vm/reusable_handles.h" | 14 #include "vm/reusable_handles.h" |
| 15 #include "vm/safepoint.h" |
15 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
16 #include "vm/symbols.h" | 17 #include "vm/symbols.h" |
17 #include "vm/tags.h" | 18 #include "vm/tags.h" |
18 | 19 |
19 | 20 |
20 namespace dart { | 21 namespace dart { |
21 | 22 |
22 DEFINE_FLAG(bool, trace_natives, false, | 23 DEFINE_FLAG(bool, trace_natives, false, |
23 "Trace invocation of natives (debug mode only)"); | 24 "Trace invocation of natives (debug mode only)"); |
24 | 25 |
25 | 26 |
26 NativeFunction NativeEntry::ResolveNative(const Library& library, | 27 NativeFunction NativeEntry::ResolveNative(const Library& library, |
27 const String& function_name, | 28 const String& function_name, |
28 int number_of_arguments, | 29 int number_of_arguments, |
29 bool* auto_setup_scope) { | 30 bool* auto_setup_scope) { |
30 // Now resolve the native function to the corresponding native entrypoint. | 31 // Now resolve the native function to the corresponding native entrypoint. |
31 if (library.native_entry_resolver() == 0) { | 32 if (library.native_entry_resolver() == 0) { |
32 // Native methods are not allowed in the library to which this | 33 // Native methods are not allowed in the library to which this |
33 // class belongs in. | 34 // class belongs in. |
34 return NULL; | 35 return NULL; |
35 } | 36 } |
36 Dart_EnterScope(); // Enter a new Dart API scope as we invoke API entries. | 37 Dart_NativeFunction native_function = NULL; |
37 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); | 38 { |
38 Dart_NativeFunction native_function = | 39 Thread* T = Thread::Current(); |
39 resolver(Api::NewHandle(Thread::Current(), function_name.raw()), | 40 TransitionVMToNative transition(T); |
40 number_of_arguments, auto_setup_scope); | 41 Dart_EnterScope(); // Enter a new Dart API scope as we invoke API entries. |
41 Dart_ExitScope(); // Exit the Dart API scope. | 42 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); |
| 43 native_function = resolver(Api::NewHandle(T, function_name.raw()), |
| 44 number_of_arguments, auto_setup_scope); |
| 45 Dart_ExitScope(); // Exit the Dart API scope. |
| 46 } |
42 return reinterpret_cast<NativeFunction>(native_function); | 47 return reinterpret_cast<NativeFunction>(native_function); |
43 } | 48 } |
44 | 49 |
45 | 50 |
46 const uint8_t* NativeEntry::ResolveSymbolInLibrary(const Library& library, | 51 const uint8_t* NativeEntry::ResolveSymbolInLibrary(const Library& library, |
47 uword pc) { | 52 uword pc) { |
48 Dart_NativeEntrySymbol symbol_resolver = | 53 Dart_NativeEntrySymbol symbol_resolver = |
49 library.native_entry_symbol_resolver(); | 54 library.native_entry_symbol_resolver(); |
50 if (symbol_resolver == 0) { | 55 if (symbol_resolver == 0) { |
51 // Cannot reverse lookup native entries. | 56 // Cannot reverse lookup native entries. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 | 92 |
88 | 93 |
89 void NativeEntry::NativeCallWrapper(Dart_NativeArguments args, | 94 void NativeEntry::NativeCallWrapper(Dart_NativeArguments args, |
90 Dart_NativeFunction func) { | 95 Dart_NativeFunction func) { |
91 CHECK_STACK_ALIGNMENT; | 96 CHECK_STACK_ALIGNMENT; |
92 VERIFY_ON_TRANSITION; | 97 VERIFY_ON_TRANSITION; |
93 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 98 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
94 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 99 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
95 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 100 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
96 Thread* thread = arguments->thread(); | 101 Thread* thread = arguments->thread(); |
97 Isolate* isolate = thread->isolate(); | 102 if (!arguments->IsNativeAutoSetupScope()) { |
| 103 TransitionGeneratedToNative transition(thread); |
| 104 func(args); |
| 105 } else { |
| 106 Isolate* isolate = thread->isolate(); |
| 107 ApiState* state = isolate->api_state(); |
| 108 ASSERT(state != NULL); |
| 109 ApiLocalScope* current_top_scope = thread->api_top_scope(); |
| 110 ApiLocalScope* scope = thread->api_reusable_scope(); |
| 111 TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func)); |
| 112 TransitionGeneratedToNative transition(thread); |
| 113 if (scope == NULL) { |
| 114 scope = new ApiLocalScope(current_top_scope, |
| 115 thread->top_exit_frame_info()); |
| 116 ASSERT(scope != NULL); |
| 117 } else { |
| 118 scope->Reinit(thread, |
| 119 current_top_scope, |
| 120 thread->top_exit_frame_info()); |
| 121 thread->set_api_reusable_scope(NULL); |
| 122 } |
| 123 thread->set_api_top_scope(scope); // New scope is now the top scope. |
98 | 124 |
99 ApiState* state = isolate->api_state(); | 125 func(args); |
100 ASSERT(state != NULL); | 126 |
101 ApiLocalScope* current_top_scope = thread->api_top_scope(); | 127 ASSERT(current_top_scope == scope->previous()); |
102 ApiLocalScope* scope = thread->api_reusable_scope(); | 128 thread->set_api_top_scope(current_top_scope); // Reset top scope to prev. |
103 TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func)); | 129 if (thread->api_reusable_scope() == NULL) { |
104 if (scope == NULL) { | 130 scope->Reset(thread); // Reset the old scope which we just exited. |
105 scope = new ApiLocalScope(current_top_scope, | 131 thread->set_api_reusable_scope(scope); |
106 thread->top_exit_frame_info()); | 132 } else { |
107 ASSERT(scope != NULL); | 133 ASSERT(thread->api_reusable_scope() != scope); |
108 } else { | 134 delete scope; |
109 scope->Reinit(thread, | 135 } |
110 current_top_scope, | 136 DEOPTIMIZE_ALOT; |
111 thread->top_exit_frame_info()); | 137 VERIFY_ON_TRANSITION; |
112 thread->set_api_reusable_scope(NULL); | |
113 } | 138 } |
114 thread->set_api_top_scope(scope); // New scope is now the top scope. | |
115 | |
116 func(args); | |
117 | |
118 ASSERT(current_top_scope == scope->previous()); | |
119 thread->set_api_top_scope(current_top_scope); // Reset top scope to previous. | |
120 if (thread->api_reusable_scope() == NULL) { | |
121 scope->Reset(thread); // Reset the old scope which we just exited. | |
122 thread->set_api_reusable_scope(scope); | |
123 } else { | |
124 ASSERT(thread->api_reusable_scope() != scope); | |
125 delete scope; | |
126 } | |
127 DEOPTIMIZE_ALOT; | |
128 VERIFY_ON_TRANSITION; | |
129 } | 139 } |
130 | 140 |
131 | 141 |
132 static NativeFunction ResolveNativeFunction(Zone* zone, | 142 static NativeFunction ResolveNativeFunction(Zone* zone, |
133 const Function& func, | 143 const Function& func, |
134 bool* is_bootstrap_native) { | 144 bool* is_bootstrap_native) { |
135 const Class& cls = Class::Handle(zone, func.Owner()); | 145 const Class& cls = Class::Handle(zone, func.Owner()); |
136 const Library& library = Library::Handle(zone, cls.library()); | 146 const Library& library = Library::Handle(zone, cls.library()); |
137 | 147 |
138 *is_bootstrap_native = | 148 *is_bootstrap_native = |
(...skipping 22 matching lines...) Expand all Loading... |
161 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { | 171 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { |
162 CHECK_STACK_ALIGNMENT; | 172 CHECK_STACK_ALIGNMENT; |
163 VERIFY_ON_TRANSITION; | 173 VERIFY_ON_TRANSITION; |
164 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 174 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
165 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 175 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
166 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 176 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
167 TRACE_NATIVE_CALL("%s", "LinkNative"); | 177 TRACE_NATIVE_CALL("%s", "LinkNative"); |
168 | 178 |
169 NativeFunction target_function = NULL; | 179 NativeFunction target_function = NULL; |
170 bool call_through_wrapper = false; | 180 bool call_through_wrapper = false; |
171 #ifdef USING_SIMULATOR | |
172 bool is_native_auto_setup_scope = false; | |
173 #endif | |
174 | 181 |
175 { | 182 { |
| 183 TransitionGeneratedToVM transition(arguments->thread()); |
176 StackZone zone(arguments->thread()); | 184 StackZone zone(arguments->thread()); |
177 | 185 |
178 DartFrameIterator iterator; | 186 DartFrameIterator iterator; |
179 StackFrame* caller_frame = iterator.NextFrame(); | 187 StackFrame* caller_frame = iterator.NextFrame(); |
180 | 188 |
181 const Code& code = Code::Handle(caller_frame->LookupDartCode()); | 189 const Code& code = Code::Handle(caller_frame->LookupDartCode()); |
182 const Function& func = Function::Handle(code.function()); | 190 const Function& func = Function::Handle(code.function()); |
183 #ifdef USING_SIMULATOR | |
184 is_native_auto_setup_scope = func.IsNativeAutoSetupScope(); | |
185 #endif | |
186 | 191 |
187 if (FLAG_trace_natives) { | 192 if (FLAG_trace_natives) { |
188 OS::Print("Resolving native target for %s\n", func.ToCString()); | 193 OS::Print("Resolving native target for %s\n", func.ToCString()); |
189 } | 194 } |
190 | 195 |
191 bool is_bootstrap_native = false; | 196 bool is_bootstrap_native = false; |
192 target_function = ResolveNativeFunction( | 197 target_function = ResolveNativeFunction( |
193 arguments->thread()->zone(), func, &is_bootstrap_native); | 198 arguments->thread()->zone(), func, &is_bootstrap_native); |
194 ASSERT(target_function != NULL); | 199 ASSERT(target_function != NULL); |
195 | 200 |
(...skipping 13 matching lines...) Expand all Loading... |
209 Simulator::RedirectExternalReference( | 214 Simulator::RedirectExternalReference( |
210 reinterpret_cast<uword>(LinkNativeCall), | 215 reinterpret_cast<uword>(LinkNativeCall), |
211 Simulator::kBootstrapNativeCall, | 216 Simulator::kBootstrapNativeCall, |
212 NativeEntry::kNumArguments))); | 217 NativeEntry::kNumArguments))); |
213 #endif | 218 #endif |
214 ASSERT(current_trampoline.raw() == | 219 ASSERT(current_trampoline.raw() == |
215 StubCode::CallBootstrapCFunction_entry()->code()); | 220 StubCode::CallBootstrapCFunction_entry()->code()); |
216 } | 221 } |
217 #endif | 222 #endif |
218 | 223 |
219 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(func); | 224 call_through_wrapper = !is_bootstrap_native; |
220 const bool is_leaf_call = | |
221 (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0; | |
222 | |
223 call_through_wrapper = !is_bootstrap_native && !is_leaf_call; | |
224 | |
225 const Code& trampoline = Code::Handle(call_through_wrapper ? | 225 const Code& trampoline = Code::Handle(call_through_wrapper ? |
226 StubCode::CallNativeCFunction_entry()->code() : | 226 StubCode::CallNativeCFunction_entry()->code() : |
227 StubCode::CallBootstrapCFunction_entry()->code()); | 227 StubCode::CallBootstrapCFunction_entry()->code()); |
228 | 228 |
229 NativeFunction patch_target_function = target_function; | 229 NativeFunction patch_target_function = target_function; |
230 #if defined(USING_SIMULATOR) | 230 #if defined(USING_SIMULATOR) |
231 if (!call_through_wrapper || !is_native_auto_setup_scope) { | 231 if (!call_through_wrapper) { |
232 patch_target_function = reinterpret_cast<NativeFunction>( | 232 patch_target_function = reinterpret_cast<NativeFunction>( |
233 Simulator::RedirectExternalReference( | 233 Simulator::RedirectExternalReference( |
234 reinterpret_cast<uword>(patch_target_function), | 234 reinterpret_cast<uword>(patch_target_function), |
235 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)); | 235 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)); |
236 } | 236 } |
237 #endif | 237 #endif |
238 | 238 |
239 CodePatcher::PatchNativeCallAt( | 239 CodePatcher::PatchNativeCallAt( |
240 caller_frame->pc(), code, patch_target_function, trampoline); | 240 caller_frame->pc(), code, patch_target_function, trampoline); |
241 | 241 |
242 if (FLAG_trace_natives) { | 242 if (FLAG_trace_natives) { |
243 OS::Print(" -> %p (%s, %s)\n", | 243 OS::Print(" -> %p (%s)\n", |
244 target_function, | 244 target_function, |
245 is_bootstrap_native ? "bootstrap" : "non-bootstrap", | 245 is_bootstrap_native ? "bootstrap" : "non-bootstrap"); |
246 is_leaf_call ? "leaf" : "non-leaf"); | |
247 } | 246 } |
248 } | 247 } |
249 VERIFY_ON_TRANSITION; | 248 VERIFY_ON_TRANSITION; |
250 | 249 |
251 // Tail-call resolved target. | 250 // Tail-call resolved target. |
252 if (call_through_wrapper) { | 251 if (call_through_wrapper) { |
253 NativeEntry::NativeCallWrapper( | 252 NativeEntry::NativeCallWrapper( |
254 args, reinterpret_cast<Dart_NativeFunction>(target_function)); | 253 args, reinterpret_cast<Dart_NativeFunction>(target_function)); |
255 } else { | 254 } else { |
256 target_function(arguments); | 255 target_function(arguments); |
257 } | 256 } |
258 } | 257 } |
259 | 258 |
260 | 259 |
261 } // namespace dart | 260 } // namespace dart |
OLD | NEW |