Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: runtime/vm/native_entry.cc

Issue 1294113004: VM: Link native calls lazily. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: addressed comments Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/native_entry.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 &current_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
OLDNEW
« no previous file with comments | « runtime/vm/native_entry.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698