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 #ifdef USING_SIMULATOR |
| 186 bool is_native_auto_setup_scope = false; |
| 187 intptr_t num_parameters = -1; |
| 188 #endif |
| 189 |
| 190 { |
| 191 StackZone zone(arguments->thread()); |
| 192 |
| 193 DartFrameIterator iterator; |
| 194 StackFrame* caller_frame = iterator.NextFrame(); |
| 195 |
| 196 const Code& code = Code::Handle(caller_frame->LookupDartCode()); |
| 197 const Function& func = Function::Handle(code.function()); |
| 198 #ifdef USING_SIMULATOR |
| 199 is_native_auto_setup_scope = func.IsNativeAutoSetupScope(); |
| 200 num_parameters = func.NumParameters(); |
| 201 #endif |
| 202 |
| 203 if (FLAG_trace_natives) { |
| 204 OS::Print("Resolving native target for %s\n", func.ToCString()); |
| 205 } |
| 206 |
| 207 bool is_bootstrap_native = false; |
| 208 target_function = ResolveNativeFunction( |
| 209 arguments->thread()->isolate(), func, &is_bootstrap_native); |
| 210 ASSERT(target_function != NULL); |
| 211 |
| 212 #if defined(DEBUG) |
| 213 { |
| 214 NativeFunction current_function = NULL; |
| 215 uword current_trampoline = |
| 216 CodePatcher::GetNativeCallAt(caller_frame->pc(), |
| 217 code, |
| 218 ¤t_function); |
| 219 #if !defined(USING_SIMULATOR) |
| 220 ASSERT(current_function == |
| 221 reinterpret_cast<NativeFunction>(LinkNativeCall)); |
| 222 #else |
| 223 ASSERT(current_function == |
| 224 reinterpret_cast<NativeFunction>( |
| 225 Simulator::RedirectExternalReference( |
| 226 reinterpret_cast<uword>(LinkNativeCall), |
| 227 Simulator::kBootstrapNativeCall, |
| 228 func.NumParameters()))); |
| 229 #endif |
| 230 ASSERT(current_trampoline == |
| 231 StubCode::CallBootstrapCFunction_entry()->EntryPoint()); |
| 232 } |
| 233 #endif |
| 234 |
| 235 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(func); |
| 236 const bool is_leaf_call = |
| 237 (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0; |
| 238 |
| 239 call_through_wrapper = !is_bootstrap_native && !is_leaf_call; |
| 240 |
| 241 const Code& trampoline = Code::Handle(call_through_wrapper ? |
| 242 StubCode::CallNativeCFunction_entry()->code() : |
| 243 StubCode::CallBootstrapCFunction_entry()->code()); |
| 244 |
| 245 NativeFunction patch_target_function = target_function; |
| 246 #if defined(USING_SIMULATOR) |
| 247 if (!call_through_wrapper || !is_native_auto_setup_scope) { |
| 248 patch_target_function = reinterpret_cast<NativeFunction>( |
| 249 Simulator::RedirectExternalReference( |
| 250 reinterpret_cast<uword>(patch_target_function), |
| 251 Simulator::kBootstrapNativeCall, num_parameters)); |
| 252 } |
| 253 #endif |
| 254 |
| 255 CodePatcher::PatchNativeCallAt( |
| 256 caller_frame->pc(), code, patch_target_function, trampoline); |
| 257 |
| 258 if (FLAG_trace_natives) { |
| 259 OS::Print(" -> %p (%s, %s)\n", |
| 260 target_function, |
| 261 is_bootstrap_native ? "bootstrap" : "non-bootstrap", |
| 262 is_leaf_call ? "leaf" : "non-leaf"); |
| 263 } |
| 264 } |
| 265 VERIFY_ON_TRANSITION; |
| 266 |
| 267 // Tail-call resolved target. |
| 268 if (call_through_wrapper) { |
| 269 NativeEntry::NativeCallWrapper( |
| 270 args, reinterpret_cast<Dart_NativeFunction>(target_function)); |
| 271 } else { |
| 272 target_function(arguments); |
| 273 } |
| 274 } |
| 275 |
| 276 |
126 } // namespace dart | 277 } // namespace dart |
OLD | NEW |