Chromium Code Reviews| 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 |