| 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/native_symbol.h" | 13 #include "vm/native_symbol.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/reusable_handles.h" | 15 #include "vm/reusable_handles.h" |
| 16 #include "vm/safepoint.h" | 16 #include "vm/safepoint.h" |
| 17 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
| 18 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 19 #include "vm/tags.h" | 19 #include "vm/tags.h" |
| 20 | 20 |
| 21 | |
| 22 namespace dart { | 21 namespace dart { |
| 23 | 22 |
| 24 DEFINE_FLAG(bool, | 23 DEFINE_FLAG(bool, |
| 25 trace_natives, | 24 trace_natives, |
| 26 false, | 25 false, |
| 27 "Trace invocation of natives (debug mode only)"); | 26 "Trace invocation of natives (debug mode only)"); |
| 28 | 27 |
| 29 | |
| 30 void DartNativeThrowArgumentException(const Instance& instance) { | 28 void DartNativeThrowArgumentException(const Instance& instance) { |
| 31 const Array& __args__ = Array::Handle(Array::New(1)); | 29 const Array& __args__ = Array::Handle(Array::New(1)); |
| 32 __args__.SetAt(0, instance); | 30 __args__.SetAt(0, instance); |
| 33 Exceptions::ThrowByType(Exceptions::kArgument, __args__); | 31 Exceptions::ThrowByType(Exceptions::kArgument, __args__); |
| 34 } | 32 } |
| 35 | 33 |
| 36 | |
| 37 NativeFunction NativeEntry::ResolveNative(const Library& library, | 34 NativeFunction NativeEntry::ResolveNative(const Library& library, |
| 38 const String& function_name, | 35 const String& function_name, |
| 39 int number_of_arguments, | 36 int number_of_arguments, |
| 40 bool* auto_setup_scope) { | 37 bool* auto_setup_scope) { |
| 41 // Now resolve the native function to the corresponding native entrypoint. | 38 // Now resolve the native function to the corresponding native entrypoint. |
| 42 if (library.native_entry_resolver() == 0) { | 39 if (library.native_entry_resolver() == 0) { |
| 43 // Native methods are not allowed in the library to which this | 40 // Native methods are not allowed in the library to which this |
| 44 // class belongs in. | 41 // class belongs in. |
| 45 return NULL; | 42 return NULL; |
| 46 } | 43 } |
| 47 Dart_NativeFunction native_function = NULL; | 44 Dart_NativeFunction native_function = NULL; |
| 48 { | 45 { |
| 49 Thread* T = Thread::Current(); | 46 Thread* T = Thread::Current(); |
| 50 TransitionVMToNative transition(T); | 47 TransitionVMToNative transition(T); |
| 51 Dart_EnterScope(); // Enter a new Dart API scope as we invoke API entries. | 48 Dart_EnterScope(); // Enter a new Dart API scope as we invoke API entries. |
| 52 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); | 49 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); |
| 53 native_function = resolver(Api::NewHandle(T, function_name.raw()), | 50 native_function = resolver(Api::NewHandle(T, function_name.raw()), |
| 54 number_of_arguments, auto_setup_scope); | 51 number_of_arguments, auto_setup_scope); |
| 55 Dart_ExitScope(); // Exit the Dart API scope. | 52 Dart_ExitScope(); // Exit the Dart API scope. |
| 56 } | 53 } |
| 57 return reinterpret_cast<NativeFunction>(native_function); | 54 return reinterpret_cast<NativeFunction>(native_function); |
| 58 } | 55 } |
| 59 | 56 |
| 60 | |
| 61 const uint8_t* NativeEntry::ResolveSymbolInLibrary(const Library& library, | 57 const uint8_t* NativeEntry::ResolveSymbolInLibrary(const Library& library, |
| 62 uword pc) { | 58 uword pc) { |
| 63 Dart_NativeEntrySymbol symbol_resolver = | 59 Dart_NativeEntrySymbol symbol_resolver = |
| 64 library.native_entry_symbol_resolver(); | 60 library.native_entry_symbol_resolver(); |
| 65 if (symbol_resolver == 0) { | 61 if (symbol_resolver == 0) { |
| 66 // Cannot reverse lookup native entries. | 62 // Cannot reverse lookup native entries. |
| 67 return NULL; | 63 return NULL; |
| 68 } | 64 } |
| 69 return symbol_resolver(reinterpret_cast<Dart_NativeFunction>(pc)); | 65 return symbol_resolver(reinterpret_cast<Dart_NativeFunction>(pc)); |
| 70 } | 66 } |
| 71 | 67 |
| 72 | |
| 73 const uint8_t* NativeEntry::ResolveSymbol(uword pc) { | 68 const uint8_t* NativeEntry::ResolveSymbol(uword pc) { |
| 74 Thread* thread = Thread::Current(); | 69 Thread* thread = Thread::Current(); |
| 75 REUSABLE_GROWABLE_OBJECT_ARRAY_HANDLESCOPE(thread); | 70 REUSABLE_GROWABLE_OBJECT_ARRAY_HANDLESCOPE(thread); |
| 76 GrowableObjectArray& libs = reused_growable_object_array_handle.Handle(); | 71 GrowableObjectArray& libs = reused_growable_object_array_handle.Handle(); |
| 77 libs ^= thread->isolate()->object_store()->libraries(); | 72 libs ^= thread->isolate()->object_store()->libraries(); |
| 78 ASSERT(!libs.IsNull()); | 73 ASSERT(!libs.IsNull()); |
| 79 intptr_t num_libs = libs.Length(); | 74 intptr_t num_libs = libs.Length(); |
| 80 for (intptr_t i = 0; i < num_libs; i++) { | 75 for (intptr_t i = 0; i < num_libs; i++) { |
| 81 REUSABLE_LIBRARY_HANDLESCOPE(thread); | 76 REUSABLE_LIBRARY_HANDLESCOPE(thread); |
| 82 Library& lib = reused_library_handle.Handle(); | 77 Library& lib = reused_library_handle.Handle(); |
| 83 lib ^= libs.At(i); | 78 lib ^= libs.At(i); |
| 84 ASSERT(!lib.IsNull()); | 79 ASSERT(!lib.IsNull()); |
| 85 const uint8_t* r = ResolveSymbolInLibrary(lib, pc); | 80 const uint8_t* r = ResolveSymbolInLibrary(lib, pc); |
| 86 if (r != NULL) { | 81 if (r != NULL) { |
| 87 return r; | 82 return r; |
| 88 } | 83 } |
| 89 } | 84 } |
| 90 return NULL; | 85 return NULL; |
| 91 } | 86 } |
| 92 | 87 |
| 93 | |
| 94 bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) { | 88 bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) { |
| 95 RawObject* retval = arguments->ReturnValue(); | 89 RawObject* retval = arguments->ReturnValue(); |
| 96 return (retval->IsHeapObject() && | 90 return (retval->IsHeapObject() && |
| 97 RawObject::IsErrorClassId(retval->GetClassId())); | 91 RawObject::IsErrorClassId(retval->GetClassId())); |
| 98 } | 92 } |
| 99 | 93 |
| 100 | |
| 101 void NativeEntry::PropagateErrors(NativeArguments* arguments) { | 94 void NativeEntry::PropagateErrors(NativeArguments* arguments) { |
| 102 Thread* thread = arguments->thread(); | 95 Thread* thread = arguments->thread(); |
| 103 thread->UnwindScopes(thread->top_exit_frame_info()); | 96 thread->UnwindScopes(thread->top_exit_frame_info()); |
| 104 | 97 |
| 105 // The thread->zone() is different here than before we unwound. | 98 // The thread->zone() is different here than before we unwound. |
| 106 const Object& error = | 99 const Object& error = |
| 107 Object::Handle(thread->zone(), arguments->ReturnValue()); | 100 Object::Handle(thread->zone(), arguments->ReturnValue()); |
| 108 Exceptions::PropagateError(Error::Cast(error)); | 101 Exceptions::PropagateError(Error::Cast(error)); |
| 109 UNREACHABLE(); | 102 UNREACHABLE(); |
| 110 } | 103 } |
| 111 | 104 |
| 112 | |
| 113 uword NativeEntry::NoScopeNativeCallWrapperEntry() { | 105 uword NativeEntry::NoScopeNativeCallWrapperEntry() { |
| 114 uword entry = reinterpret_cast<uword>(NativeEntry::NoScopeNativeCallWrapper); | 106 uword entry = reinterpret_cast<uword>(NativeEntry::NoScopeNativeCallWrapper); |
| 115 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) | 107 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) |
| 116 // DBC does not use redirections unlike other simulators. | 108 // DBC does not use redirections unlike other simulators. |
| 117 entry = Simulator::RedirectExternalReference( | 109 entry = Simulator::RedirectExternalReference( |
| 118 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); | 110 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); |
| 119 #endif | 111 #endif |
| 120 return entry; | 112 return entry; |
| 121 } | 113 } |
| 122 | 114 |
| 123 | |
| 124 void NativeEntry::NoScopeNativeCallWrapper(Dart_NativeArguments args, | 115 void NativeEntry::NoScopeNativeCallWrapper(Dart_NativeArguments args, |
| 125 Dart_NativeFunction func) { | 116 Dart_NativeFunction func) { |
| 126 CHECK_STACK_ALIGNMENT; | 117 CHECK_STACK_ALIGNMENT; |
| 127 NoScopeNativeCallWrapperNoStackCheck(args, func); | 118 NoScopeNativeCallWrapperNoStackCheck(args, func); |
| 128 } | 119 } |
| 129 | 120 |
| 130 | |
| 131 void NativeEntry::NoScopeNativeCallWrapperNoStackCheck( | 121 void NativeEntry::NoScopeNativeCallWrapperNoStackCheck( |
| 132 Dart_NativeArguments args, | 122 Dart_NativeArguments args, |
| 133 Dart_NativeFunction func) { | 123 Dart_NativeFunction func) { |
| 134 VERIFY_ON_TRANSITION; | 124 VERIFY_ON_TRANSITION; |
| 135 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 125 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
| 136 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 126 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
| 137 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 127 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
| 138 Thread* thread = arguments->thread(); | 128 Thread* thread = arguments->thread(); |
| 139 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 129 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
| 140 { | 130 { |
| 141 TransitionGeneratedToNative transition(thread); | 131 TransitionGeneratedToNative transition(thread); |
| 142 func(args); | 132 func(args); |
| 143 if (ReturnValueIsError(arguments)) { | 133 if (ReturnValueIsError(arguments)) { |
| 144 PropagateErrors(arguments); | 134 PropagateErrors(arguments); |
| 145 } | 135 } |
| 146 } | 136 } |
| 147 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 137 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
| 148 VERIFY_ON_TRANSITION; | 138 VERIFY_ON_TRANSITION; |
| 149 } | 139 } |
| 150 | 140 |
| 151 | |
| 152 uword NativeEntry::AutoScopeNativeCallWrapperEntry() { | 141 uword NativeEntry::AutoScopeNativeCallWrapperEntry() { |
| 153 uword entry = | 142 uword entry = |
| 154 reinterpret_cast<uword>(NativeEntry::AutoScopeNativeCallWrapper); | 143 reinterpret_cast<uword>(NativeEntry::AutoScopeNativeCallWrapper); |
| 155 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) | 144 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) |
| 156 // DBC does not use redirections unlike other simulators. | 145 // DBC does not use redirections unlike other simulators. |
| 157 entry = Simulator::RedirectExternalReference( | 146 entry = Simulator::RedirectExternalReference( |
| 158 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); | 147 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); |
| 159 #endif | 148 #endif |
| 160 return entry; | 149 return entry; |
| 161 } | 150 } |
| 162 | 151 |
| 163 | |
| 164 void NativeEntry::AutoScopeNativeCallWrapper(Dart_NativeArguments args, | 152 void NativeEntry::AutoScopeNativeCallWrapper(Dart_NativeArguments args, |
| 165 Dart_NativeFunction func) { | 153 Dart_NativeFunction func) { |
| 166 CHECK_STACK_ALIGNMENT; | 154 CHECK_STACK_ALIGNMENT; |
| 167 AutoScopeNativeCallWrapperNoStackCheck(args, func); | 155 AutoScopeNativeCallWrapperNoStackCheck(args, func); |
| 168 } | 156 } |
| 169 | 157 |
| 170 | |
| 171 void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck( | 158 void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck( |
| 172 Dart_NativeArguments args, | 159 Dart_NativeArguments args, |
| 173 Dart_NativeFunction func) { | 160 Dart_NativeFunction func) { |
| 174 VERIFY_ON_TRANSITION; | 161 VERIFY_ON_TRANSITION; |
| 175 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 162 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
| 176 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 163 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
| 177 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 164 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
| 178 Thread* thread = arguments->thread(); | 165 Thread* thread = arguments->thread(); |
| 179 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 166 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
| 180 { | 167 { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 208 } else { | 195 } else { |
| 209 ASSERT(thread->api_reusable_scope() != scope); | 196 ASSERT(thread->api_reusable_scope() != scope); |
| 210 delete scope; | 197 delete scope; |
| 211 } | 198 } |
| 212 DEOPTIMIZE_ALOT; | 199 DEOPTIMIZE_ALOT; |
| 213 } | 200 } |
| 214 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); | 201 ASSERT(thread->execution_state() == Thread::kThreadInGenerated); |
| 215 VERIFY_ON_TRANSITION; | 202 VERIFY_ON_TRANSITION; |
| 216 } | 203 } |
| 217 | 204 |
| 218 | |
| 219 // DBC does not support lazy native call linking. | 205 // DBC does not support lazy native call linking. |
| 220 #if !defined(TARGET_ARCH_DBC) | 206 #if !defined(TARGET_ARCH_DBC) |
| 221 static NativeFunction ResolveNativeFunction(Zone* zone, | 207 static NativeFunction ResolveNativeFunction(Zone* zone, |
| 222 const Function& func, | 208 const Function& func, |
| 223 bool* is_bootstrap_native, | 209 bool* is_bootstrap_native, |
| 224 bool* is_auto_scope) { | 210 bool* is_auto_scope) { |
| 225 const Class& cls = Class::Handle(zone, func.Owner()); | 211 const Class& cls = Class::Handle(zone, func.Owner()); |
| 226 const Library& library = Library::Handle(zone, cls.library()); | 212 const Library& library = Library::Handle(zone, cls.library()); |
| 227 | 213 |
| 228 *is_bootstrap_native = | 214 *is_bootstrap_native = |
| 229 Bootstrap::IsBootstapResolver(library.native_entry_resolver()); | 215 Bootstrap::IsBootstapResolver(library.native_entry_resolver()); |
| 230 | 216 |
| 231 const String& native_name = String::Handle(zone, func.native_name()); | 217 const String& native_name = String::Handle(zone, func.native_name()); |
| 232 ASSERT(!native_name.IsNull()); | 218 ASSERT(!native_name.IsNull()); |
| 233 | 219 |
| 234 const int num_params = NativeArguments::ParameterCountForResolution(func); | 220 const int num_params = NativeArguments::ParameterCountForResolution(func); |
| 235 return NativeEntry::ResolveNative(library, native_name, num_params, | 221 return NativeEntry::ResolveNative(library, native_name, num_params, |
| 236 is_auto_scope); | 222 is_auto_scope); |
| 237 } | 223 } |
| 238 | 224 |
| 239 | |
| 240 uword NativeEntry::LinkNativeCallEntry() { | 225 uword NativeEntry::LinkNativeCallEntry() { |
| 241 uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall); | 226 uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall); |
| 242 #if defined(USING_SIMULATOR) | 227 #if defined(USING_SIMULATOR) |
| 243 entry = Simulator::RedirectExternalReference( | 228 entry = Simulator::RedirectExternalReference( |
| 244 entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments); | 229 entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments); |
| 245 #endif | 230 #endif |
| 246 return entry; | 231 return entry; |
| 247 } | 232 } |
| 248 | 233 |
| 249 | |
| 250 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { | 234 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) { |
| 251 CHECK_STACK_ALIGNMENT; | 235 CHECK_STACK_ALIGNMENT; |
| 252 VERIFY_ON_TRANSITION; | 236 VERIFY_ON_TRANSITION; |
| 253 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | 237 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
| 254 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ | 238 /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ |
| 255 MSAN_UNPOISON(arguments, sizeof(*arguments)); | 239 MSAN_UNPOISON(arguments, sizeof(*arguments)); |
| 256 TRACE_NATIVE_CALL("%s", "LinkNative"); | 240 TRACE_NATIVE_CALL("%s", "LinkNative"); |
| 257 | 241 |
| 258 NativeFunction target_function = NULL; | 242 NativeFunction target_function = NULL; |
| 259 bool is_bootstrap_native = false; | 243 bool is_bootstrap_native = false; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 args, reinterpret_cast<Dart_NativeFunction>(target_function)); | 321 args, reinterpret_cast<Dart_NativeFunction>(target_function)); |
| 338 } else { | 322 } else { |
| 339 // Because this call is within a compilation unit, Clang doesn't respect | 323 // Because this call is within a compilation unit, Clang doesn't respect |
| 340 // the ABI alignment here. | 324 // the ABI alignment here. |
| 341 NativeEntry::NoScopeNativeCallWrapperNoStackCheck( | 325 NativeEntry::NoScopeNativeCallWrapperNoStackCheck( |
| 342 args, reinterpret_cast<Dart_NativeFunction>(target_function)); | 326 args, reinterpret_cast<Dart_NativeFunction>(target_function)); |
| 343 } | 327 } |
| 344 } | 328 } |
| 345 #endif // !defined(TARGET_ARCH_DBC) | 329 #endif // !defined(TARGET_ARCH_DBC) |
| 346 | 330 |
| 347 | |
| 348 } // namespace dart | 331 } // namespace dart |
| OLD | NEW |