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" | |
10 #include "vm/code_patcher.h" | |
9 #include "vm/dart_api_impl.h" | 11 #include "vm/dart_api_impl.h" |
10 #include "vm/dart_api_state.h" | 12 #include "vm/dart_api_state.h" |
11 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
12 #include "vm/reusable_handles.h" | 14 #include "vm/reusable_handles.h" |
15 #include "vm/stack_frame.h" | |
16 #include "vm/symbols.h" | |
13 #include "vm/tags.h" | 17 #include "vm/tags.h" |
14 | 18 |
15 | 19 |
16 namespace dart { | 20 namespace dart { |
17 | 21 |
18 DEFINE_FLAG(bool, trace_natives, false, | 22 DEFINE_FLAG(bool, trace_natives, false, |
19 "Trace invocation of natives (debug mode only)"); | 23 "Trace invocation of natives (debug mode only)"); |
20 | 24 |
21 | 25 |
22 static ExternalLabel native_call_label( | 26 static ExternalLabel native_call_label( |
23 reinterpret_cast<uword>(&NativeEntry::NativeCallWrapper)); | 27 reinterpret_cast<uword>(&NativeEntry::NativeCallWrapper)); |
24 | 28 |
25 | 29 |
30 static ExternalLabel link_native_call_label( | |
31 reinterpret_cast<uword>(&NativeEntry::LinkNativeCall)); | |
32 | |
33 | |
26 NativeFunction NativeEntry::ResolveNative(const Library& library, | 34 NativeFunction NativeEntry::ResolveNative(const Library& library, |
27 const String& function_name, | 35 const String& function_name, |
28 int number_of_arguments, | 36 int number_of_arguments, |
29 bool* auto_setup_scope) { | 37 bool* auto_setup_scope) { |
30 // Now resolve the native function to the corresponding native entrypoint. | 38 // Now resolve the native function to the corresponding native entrypoint. |
31 if (library.native_entry_resolver() == 0) { | 39 if (library.native_entry_resolver() == 0) { |
32 // Native methods are not allowed in the library to which this | 40 // Native methods are not allowed in the library to which this |
33 // class belongs in. | 41 // class belongs in. |
34 return NULL; | 42 return NULL; |
35 } | 43 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 scope->Reset(thread); // Reset the old scope which we just exited. | 124 scope->Reset(thread); // Reset the old scope which we just exited. |
117 state->set_reusable_scope(scope); | 125 state->set_reusable_scope(scope); |
118 } else { | 126 } else { |
119 ASSERT(state->reusable_scope() != scope); | 127 ASSERT(state->reusable_scope() != scope); |
120 delete scope; | 128 delete scope; |
121 } | 129 } |
122 DEOPTIMIZE_ALOT; | 130 DEOPTIMIZE_ALOT; |
123 VERIFY_ON_TRANSITION; | 131 VERIFY_ON_TRANSITION; |
124 } | 132 } |
125 | 133 |
134 | |
135 static bool IsNativeKeyword(const TokenStream::Iterator& it) { | |
136 return Token::IsIdentifier(it.CurrentTokenKind()) && | |
137 (it.CurrentLiteral() == Symbols::Native().raw()); | |
138 } | |
139 | |
140 | |
141 static NativeFunction ResolveNativeFunction(Isolate *isolate, | |
142 const Function& func, | |
143 bool* is_bootstrap_native) { | |
144 const Script& script = Script::Handle(isolate, func.script()); | |
145 const Class& cls = Class::Handle(isolate, func.Owner()); | |
146 const Library& library = Library::Handle(isolate, cls.library()); | |
147 | |
148 *is_bootstrap_native = | |
149 Bootstrap::IsBootstapResolver(library.native_entry_resolver()); | |
150 | |
151 TokenStream::Iterator it(TokenStream::Handle(isolate, script.tokens()), | |
152 func.token_pos()); | |
153 | |
154 const intptr_t end_pos = func.end_token_pos(); | |
155 while (!IsNativeKeyword(it) && it.CurrentPosition() <= end_pos) { | |
156 it.Advance(); | |
157 } | |
158 ASSERT(IsNativeKeyword(it)); | |
159 it.Advance(); | |
160 ASSERT(it.CurrentTokenKind() == Token::kSTRING); | |
161 const String& native_name = String::Handle(it.CurrentLiteral()); | |
162 | |
163 const int num_params = NativeArguments::ParameterCountForResolution(func); | |
164 bool auto_setup_scope = true; | |
165 return NativeEntry::ResolveNative( | |
166 library, native_name, num_params, &auto_setup_scope); | |
167 } | |
168 | |
169 | |
170 const ExternalLabel& NativeEntry::LinkNativeCallLabel() { | |
171 return link_native_call_label; | |
172 } | |
173 | |
174 | |
175 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { | |
176 CHECK_STACK_ALIGNMENT; | |
177 VERIFY_ON_TRANSITION; | |
178 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
179 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | |
180 MSAN_UNPOISON(arguments, sizeof(*arguments)); | |
181 TRACE_NATIVE_CALL("%s", "LinkNative"); | |
182 | |
183 NativeFunction target_function = NULL; | |
184 bool call_through_wrapper = false; | |
185 bool is_native_auto_setup_scope = false; | |
rmacnak
2015/08/20 23:48:06
only used behind USING_SIMULATOR
Florian Schneider
2015/08/21 07:58:17
Done.
| |
186 intptr_t num_parameters = -1; | |
rmacnak
2015/08/20 23:48:06
"
Florian Schneider
2015/08/21 07:58:17
Done.
| |
187 | |
188 { | |
189 StackZone zone(arguments->thread()); | |
190 | |
191 DartFrameIterator iterator; | |
192 StackFrame* caller_frame = iterator.NextFrame(); | |
193 | |
194 const Code& code = Code::Handle(caller_frame->LookupDartCode()); | |
195 const Function& func = Function::Handle(code.function()); | |
196 is_native_auto_setup_scope = func.IsNativeAutoSetupScope(); | |
197 num_parameters = func.NumParameters(); | |
198 | |
199 if (FLAG_trace_natives) { | |
200 OS::Print("Resolving native target for %s\n", func.ToCString()); | |
201 } | |
202 | |
203 bool is_bootstrap_native = false; | |
204 target_function = ResolveNativeFunction( | |
205 arguments->thread()->isolate(), func, &is_bootstrap_native); | |
206 ASSERT(target_function != NULL); | |
207 | |
208 #if defined(DEBUG) | |
209 { | |
210 NativeFunction current_function = NULL; | |
211 uword current_trampoline = | |
212 CodePatcher::GetNativeCallAt(caller_frame->pc(), | |
213 code, | |
214 ¤t_function); | |
215 #if !defined(USING_SIMULATOR) | |
216 ASSERT(current_function == | |
217 reinterpret_cast<NativeFunction>(LinkNativeCall)); | |
218 #else | |
219 ASSERT(current_function == | |
220 reinterpret_cast<NativeFunction>( | |
221 Simulator::RedirectExternalReference( | |
222 reinterpret_cast<uword>(LinkNativeCall), | |
223 Simulator::kBootstrapNativeCall, | |
224 func.NumParameters()))); | |
225 #endif | |
226 ASSERT(current_trampoline == | |
227 StubCode::CallBootstrapCFunction_entry()->EntryPoint()); | |
228 } | |
229 #endif | |
230 | |
231 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(func); | |
232 const bool is_leaf_call = | |
233 (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0; | |
234 | |
235 call_through_wrapper = !is_bootstrap_native && !is_leaf_call; | |
236 | |
237 const Code& trampoline = Code::Handle(call_through_wrapper ? | |
238 StubCode::CallNativeCFunction_entry()->code() : | |
239 StubCode::CallBootstrapCFunction_entry()->code()); | |
240 | |
241 NativeFunction patch_target_function = target_function; | |
242 #if defined(USING_SIMULATOR) | |
243 if (!call_through_wrapper || !is_native_auto_setup_scope) { | |
244 patch_target_function = reinterpret_cast<NativeFunction>( | |
245 Simulator::RedirectExternalReference( | |
246 reinterpret_cast<uword>(patch_target_function), | |
247 Simulator::kBootstrapNativeCall, num_parameters)); | |
248 } | |
249 #endif | |
250 | |
251 CodePatcher::PatchNativeCallAt( | |
252 caller_frame->pc(), code, patch_target_function, trampoline); | |
253 | |
254 if (FLAG_trace_natives) { | |
255 OS::Print(" -> %p (%s, %s)\n", | |
256 target_function, | |
257 is_bootstrap_native ? "bootstrap" : "non-bootstrap", | |
258 is_leaf_call ? "leaf" : "non-leaf"); | |
259 } | |
260 } | |
261 VERIFY_ON_TRANSITION; | |
262 | |
263 // Tail-call resolved target. | |
264 if (call_through_wrapper) { | |
265 NativeEntry::NativeCallWrapper( | |
266 args, reinterpret_cast<Dart_NativeFunction>(target_function)); | |
267 } else { | |
268 target_function(arguments); | |
269 } | |
270 } | |
271 | |
272 | |
126 } // namespace dart | 273 } // namespace dart |
OLD | NEW |