| 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 |