| 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 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DEFINE_FLAG(bool, trace_natives, false, | 24 DEFINE_FLAG(bool, |
| 25 trace_natives, |
| 26 false, |
| 25 "Trace invocation of natives (debug mode only)"); | 27 "Trace invocation of natives (debug mode only)"); |
| 26 | 28 |
| 27 | 29 |
| 28 void DartNativeThrowArgumentException(const Instance& instance) { | 30 void DartNativeThrowArgumentException(const Instance& instance) { |
| 29 const Array& __args__ = Array::Handle(Array::New(1)); | 31 const Array& __args__ = Array::Handle(Array::New(1)); |
| 30 __args__.SetAt(0, instance); | 32 __args__.SetAt(0, instance); |
| 31 Exceptions::ThrowByType(Exceptions::kArgument, __args__); | 33 Exceptions::ThrowByType(Exceptions::kArgument, __args__); |
| 32 } | 34 } |
| 33 | 35 |
| 34 | 36 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 } | 144 } |
| 143 } else { | 145 } else { |
| 144 Isolate* isolate = thread->isolate(); | 146 Isolate* isolate = thread->isolate(); |
| 145 ApiState* state = isolate->api_state(); | 147 ApiState* state = isolate->api_state(); |
| 146 ASSERT(state != NULL); | 148 ASSERT(state != NULL); |
| 147 ApiLocalScope* current_top_scope = thread->api_top_scope(); | 149 ApiLocalScope* current_top_scope = thread->api_top_scope(); |
| 148 ApiLocalScope* scope = thread->api_reusable_scope(); | 150 ApiLocalScope* scope = thread->api_reusable_scope(); |
| 149 TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func)); | 151 TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func)); |
| 150 TransitionGeneratedToNative transition(thread); | 152 TransitionGeneratedToNative transition(thread); |
| 151 if (scope == NULL) { | 153 if (scope == NULL) { |
| 152 scope = new ApiLocalScope(current_top_scope, | 154 scope = |
| 153 thread->top_exit_frame_info()); | 155 new ApiLocalScope(current_top_scope, thread->top_exit_frame_info()); |
| 154 ASSERT(scope != NULL); | 156 ASSERT(scope != NULL); |
| 155 } else { | 157 } else { |
| 156 scope->Reinit(thread, | 158 scope->Reinit(thread, current_top_scope, thread->top_exit_frame_info()); |
| 157 current_top_scope, | |
| 158 thread->top_exit_frame_info()); | |
| 159 thread->set_api_reusable_scope(NULL); | 159 thread->set_api_reusable_scope(NULL); |
| 160 } | 160 } |
| 161 thread->set_api_top_scope(scope); // New scope is now the top scope. | 161 thread->set_api_top_scope(scope); // New scope is now the top scope. |
| 162 | 162 |
| 163 func(args); | 163 func(args); |
| 164 if (ReturnValueIsError(arguments)) { | 164 if (ReturnValueIsError(arguments)) { |
| 165 PropagateErrors(arguments); | 165 PropagateErrors(arguments); |
| 166 } | 166 } |
| 167 | 167 |
| 168 ASSERT(current_top_scope == scope->previous()); | 168 ASSERT(current_top_scope == scope->previous()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 190 const Library& library = Library::Handle(zone, cls.library()); | 190 const Library& library = Library::Handle(zone, cls.library()); |
| 191 | 191 |
| 192 *is_bootstrap_native = | 192 *is_bootstrap_native = |
| 193 Bootstrap::IsBootstapResolver(library.native_entry_resolver()); | 193 Bootstrap::IsBootstapResolver(library.native_entry_resolver()); |
| 194 | 194 |
| 195 const String& native_name = String::Handle(zone, func.native_name()); | 195 const String& native_name = String::Handle(zone, func.native_name()); |
| 196 ASSERT(!native_name.IsNull()); | 196 ASSERT(!native_name.IsNull()); |
| 197 | 197 |
| 198 const int num_params = NativeArguments::ParameterCountForResolution(func); | 198 const int num_params = NativeArguments::ParameterCountForResolution(func); |
| 199 bool auto_setup_scope = true; | 199 bool auto_setup_scope = true; |
| 200 return NativeEntry::ResolveNative( | 200 return NativeEntry::ResolveNative(library, native_name, num_params, |
| 201 library, native_name, num_params, &auto_setup_scope); | 201 &auto_setup_scope); |
| 202 } | 202 } |
| 203 | 203 |
| 204 | 204 |
| 205 uword NativeEntry::LinkNativeCallEntry() { | 205 uword NativeEntry::LinkNativeCallEntry() { |
| 206 uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall); | 206 uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall); |
| 207 #if defined(USING_SIMULATOR) | 207 #if defined(USING_SIMULATOR) |
| 208 entry = Simulator::RedirectExternalReference( | 208 entry = Simulator::RedirectExternalReference( |
| 209 entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments); | 209 entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments); |
| 210 #endif | 210 #endif |
| 211 return entry; | 211 return entry; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 231 StackFrame* caller_frame = iterator.NextFrame(); | 231 StackFrame* caller_frame = iterator.NextFrame(); |
| 232 | 232 |
| 233 const Code& code = Code::Handle(caller_frame->LookupDartCode()); | 233 const Code& code = Code::Handle(caller_frame->LookupDartCode()); |
| 234 const Function& func = Function::Handle(code.function()); | 234 const Function& func = Function::Handle(code.function()); |
| 235 | 235 |
| 236 if (FLAG_trace_natives) { | 236 if (FLAG_trace_natives) { |
| 237 OS::Print("Resolving native target for %s\n", func.ToCString()); | 237 OS::Print("Resolving native target for %s\n", func.ToCString()); |
| 238 } | 238 } |
| 239 | 239 |
| 240 bool is_bootstrap_native = false; | 240 bool is_bootstrap_native = false; |
| 241 target_function = ResolveNativeFunction( | 241 target_function = ResolveNativeFunction(arguments->thread()->zone(), func, |
| 242 arguments->thread()->zone(), func, &is_bootstrap_native); | 242 &is_bootstrap_native); |
| 243 ASSERT(target_function != NULL); | 243 ASSERT(target_function != NULL); |
| 244 | 244 |
| 245 #if defined(DEBUG) | 245 #if defined(DEBUG) |
| 246 { | 246 { |
| 247 NativeFunction current_function = NULL; | 247 NativeFunction current_function = NULL; |
| 248 const Code& current_trampoline = Code::Handle( | 248 const Code& current_trampoline = |
| 249 CodePatcher::GetNativeCallAt(caller_frame->pc(), | 249 Code::Handle(CodePatcher::GetNativeCallAt(caller_frame->pc(), code, |
| 250 code, | 250 ¤t_function)); |
| 251 ¤t_function)); | |
| 252 #if !defined(USING_SIMULATOR) | 251 #if !defined(USING_SIMULATOR) |
| 253 ASSERT(current_function == | 252 ASSERT(current_function == |
| 254 reinterpret_cast<NativeFunction>(LinkNativeCall)); | 253 reinterpret_cast<NativeFunction>(LinkNativeCall)); |
| 255 #else | 254 #else |
| 256 ASSERT(current_function == | 255 ASSERT( |
| 257 reinterpret_cast<NativeFunction>( | 256 current_function == |
| 258 Simulator::RedirectExternalReference( | 257 reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference( |
| 259 reinterpret_cast<uword>(LinkNativeCall), | 258 reinterpret_cast<uword>(LinkNativeCall), |
| 260 Simulator::kBootstrapNativeCall, | 259 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments))); |
| 261 NativeEntry::kNumArguments))); | |
| 262 #endif | 260 #endif |
| 263 ASSERT(current_trampoline.raw() == | 261 ASSERT(current_trampoline.raw() == |
| 264 StubCode::CallBootstrapCFunction_entry()->code()); | 262 StubCode::CallBootstrapCFunction_entry()->code()); |
| 265 } | 263 } |
| 266 #endif | 264 #endif |
| 267 | 265 |
| 268 call_through_wrapper = !is_bootstrap_native; | 266 call_through_wrapper = !is_bootstrap_native; |
| 269 const Code& trampoline = | 267 const Code& trampoline = |
| 270 Code::Handle(call_through_wrapper ? | 268 Code::Handle(call_through_wrapper |
| 271 StubCode::CallNativeCFunction_entry()->code() : | 269 ? StubCode::CallNativeCFunction_entry()->code() |
| 272 StubCode::CallBootstrapCFunction_entry()->code()); | 270 : StubCode::CallBootstrapCFunction_entry()->code()); |
| 273 | 271 |
| 274 NativeFunction patch_target_function = target_function; | 272 NativeFunction patch_target_function = target_function; |
| 275 #if defined(USING_SIMULATOR) | 273 #if defined(USING_SIMULATOR) |
| 276 if (!call_through_wrapper) { | 274 if (!call_through_wrapper) { |
| 277 patch_target_function = reinterpret_cast<NativeFunction>( | 275 patch_target_function = |
| 278 Simulator::RedirectExternalReference( | 276 reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference( |
| 279 reinterpret_cast<uword>(patch_target_function), | 277 reinterpret_cast<uword>(patch_target_function), |
| 280 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)); | 278 Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)); |
| 281 } | 279 } |
| 282 #endif | 280 #endif |
| 283 | 281 |
| 284 CodePatcher::PatchNativeCallAt( | 282 CodePatcher::PatchNativeCallAt(caller_frame->pc(), code, |
| 285 caller_frame->pc(), code, patch_target_function, trampoline); | 283 patch_target_function, trampoline); |
| 286 | 284 |
| 287 if (FLAG_trace_natives) { | 285 if (FLAG_trace_natives) { |
| 288 OS::Print(" -> %p (%s)\n", | 286 OS::Print(" -> %p (%s)\n", target_function, |
| 289 target_function, | |
| 290 is_bootstrap_native ? "bootstrap" : "non-bootstrap"); | 287 is_bootstrap_native ? "bootstrap" : "non-bootstrap"); |
| 291 } | 288 } |
| 292 } | 289 } |
| 293 VERIFY_ON_TRANSITION; | 290 VERIFY_ON_TRANSITION; |
| 294 | 291 |
| 295 // Tail-call resolved target. | 292 // Tail-call resolved target. |
| 296 if (call_through_wrapper) { | 293 if (call_through_wrapper) { |
| 297 // Because this call is within a compilation unit, Clang doesn't respect | 294 // Because this call is within a compilation unit, Clang doesn't respect |
| 298 // the ABI alignment here. | 295 // the ABI alignment here. |
| 299 NativeEntry::NativeCallWrapperNoStackCheck( | 296 NativeEntry::NativeCallWrapperNoStackCheck( |
| 300 args, reinterpret_cast<Dart_NativeFunction>(target_function)); | 297 args, reinterpret_cast<Dart_NativeFunction>(target_function)); |
| 301 } else { | 298 } else { |
| 302 target_function(arguments); | 299 target_function(arguments); |
| 303 } | 300 } |
| 304 } | 301 } |
| 305 #endif // !defined(TARGET_ARCH_DBC) | 302 #endif // !defined(TARGET_ARCH_DBC) |
| 306 | 303 |
| 307 | 304 |
| 308 } // namespace dart | 305 } // namespace dart |
| OLD | NEW |