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

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

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month 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/code_generator.h ('k') | runtime/vm/code_generator_test.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/code_generator.h" 5 #include "vm/code_generator.h"
6 6
7 #include "vm/assembler.h" 7 #include "vm/assembler.h"
8 #include "vm/ast.h" 8 #include "vm/ast.h"
9 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 10 matching lines...) Expand all
21 #include "vm/resolver.h" 21 #include "vm/resolver.h"
22 #include "vm/runtime_entry.h" 22 #include "vm/runtime_entry.h"
23 #include "vm/service_isolate.h" 23 #include "vm/service_isolate.h"
24 #include "vm/stack_frame.h" 24 #include "vm/stack_frame.h"
25 #include "vm/symbols.h" 25 #include "vm/symbols.h"
26 #include "vm/thread_registry.h" 26 #include "vm/thread_registry.h"
27 #include "vm/verifier.h" 27 #include "vm/verifier.h"
28 28
29 namespace dart { 29 namespace dart {
30 30
31 DEFINE_FLAG(int, max_subtype_cache_entries, 100, 31 DEFINE_FLAG(
32 int,
33 max_subtype_cache_entries,
34 100,
32 "Maximum number of subtype cache entries (number of checks cached)."); 35 "Maximum number of subtype cache entries (number of checks cached).");
33 DEFINE_FLAG(int, regexp_optimization_counter_threshold, 1000, 36 DEFINE_FLAG(
37 int,
38 regexp_optimization_counter_threshold,
39 1000,
34 "RegExp's usage-counter value before it is optimized, -1 means never"); 40 "RegExp's usage-counter value before it is optimized, -1 means never");
35 DEFINE_FLAG(int, reoptimization_counter_threshold, 4000, 41 DEFINE_FLAG(int,
36 "Counter threshold before a function gets reoptimized."); 42 reoptimization_counter_threshold,
43 4000,
44 "Counter threshold before a function gets reoptimized.");
37 DEFINE_FLAG(bool, trace_deoptimization, false, "Trace deoptimization"); 45 DEFINE_FLAG(bool, trace_deoptimization, false, "Trace deoptimization");
38 DEFINE_FLAG(bool, trace_deoptimization_verbose, false, 46 DEFINE_FLAG(bool,
39 "Trace deoptimization verbose"); 47 trace_deoptimization_verbose,
48 false,
49 "Trace deoptimization verbose");
40 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling"); 50 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling");
41 DEFINE_FLAG(bool, trace_ic_miss_in_optimized, false, 51 DEFINE_FLAG(bool,
42 "Trace IC miss in optimized code"); 52 trace_ic_miss_in_optimized,
43 DEFINE_FLAG(bool, trace_optimized_ic_calls, false, 53 false,
44 "Trace IC calls in optimized code."); 54 "Trace IC miss in optimized code");
55 DEFINE_FLAG(bool,
56 trace_optimized_ic_calls,
57 false,
58 "Trace IC calls in optimized code.");
45 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code."); 59 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code.");
46 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls"); 60 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
47 DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks."); 61 DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks.");
48 62
49 DECLARE_FLAG(int, max_deoptimization_counter_threshold); 63 DECLARE_FLAG(int, max_deoptimization_counter_threshold);
50 DECLARE_FLAG(bool, enable_inlining_annotations); 64 DECLARE_FLAG(bool, enable_inlining_annotations);
51 DECLARE_FLAG(bool, trace_compiler); 65 DECLARE_FLAG(bool, trace_compiler);
52 DECLARE_FLAG(bool, trace_optimizing_compiler); 66 DECLARE_FLAG(bool, trace_optimizing_compiler);
53 DECLARE_FLAG(int, max_polymorphic_checks); 67 DECLARE_FLAG(int, max_polymorphic_checks);
54 68
55 DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement."); 69 DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement.");
56 70
57 DEFINE_FLAG(int, stacktrace_every, 0, 71 DEFINE_FLAG(int,
72 stacktrace_every,
73 0,
58 "Compute debugger stacktrace on every N stack overflow checks"); 74 "Compute debugger stacktrace on every N stack overflow checks");
59 DEFINE_FLAG(charp, stacktrace_filter, NULL, 75 DEFINE_FLAG(charp,
76 stacktrace_filter,
77 NULL,
60 "Compute stacktrace in named function on stack overflow checks"); 78 "Compute stacktrace in named function on stack overflow checks");
61 DEFINE_FLAG(charp, deoptimize_filter, NULL, 79 DEFINE_FLAG(charp,
80 deoptimize_filter,
81 NULL,
62 "Deoptimize in named function on stack overflow checks"); 82 "Deoptimize in named function on stack overflow checks");
63 83
64 DECLARE_FLAG(int, reload_every); 84 DECLARE_FLAG(int, reload_every);
65 DECLARE_FLAG(bool, reload_every_optimized); 85 DECLARE_FLAG(bool, reload_every_optimized);
66 DECLARE_FLAG(bool, reload_every_back_off); 86 DECLARE_FLAG(bool, reload_every_back_off);
67 87
68 #ifdef DEBUG 88 #ifdef DEBUG
69 DEFINE_FLAG(charp, gc_at_instance_allocation, NULL, 89 DEFINE_FLAG(charp,
90 gc_at_instance_allocation,
91 NULL,
70 "Perform a GC before allocation of instances of " 92 "Perform a GC before allocation of instances of "
71 "the specified class"); 93 "the specified class");
72 #endif 94 #endif
73 95
74 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) { 96 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) {
75 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); 97 const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
76 const String& function_name = String::Handle(function.name()); 98 const String& function_name = String::Handle(function.name());
77 const String& class_name = 99 const String& class_name =
78 String::Handle(Class::Handle(function.Owner()).Name()); 100 String::Handle(Class::Handle(function.Owner()).Name());
79 OS::PrintErr("> Entering '%s.%s'\n", 101 OS::PrintErr("> Entering '%s.%s'\n", class_name.ToCString(),
80 class_name.ToCString(), function_name.ToCString()); 102 function_name.ToCString());
81 } 103 }
82 104
83 105
84 DEFINE_RUNTIME_ENTRY(TraceFunctionExit, 1) { 106 DEFINE_RUNTIME_ENTRY(TraceFunctionExit, 1) {
85 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); 107 const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
86 const String& function_name = String::Handle(function.name()); 108 const String& function_name = String::Handle(function.name());
87 const String& class_name = 109 const String& class_name =
88 String::Handle(Class::Handle(function.Owner()).Name()); 110 String::Handle(Class::Handle(function.Owner()).Name());
89 OS::PrintErr("< Exiting '%s.%s'\n", 111 OS::PrintErr("< Exiting '%s.%s'\n", class_name.ToCString(),
90 class_name.ToCString(), function_name.ToCString()); 112 function_name.ToCString());
91 } 113 }
92 114
93 115
94 DEFINE_RUNTIME_ENTRY(RangeError, 2) { 116 DEFINE_RUNTIME_ENTRY(RangeError, 2) {
95 const Instance& length = Instance::CheckedHandle(arguments.ArgAt(0)); 117 const Instance& length = Instance::CheckedHandle(arguments.ArgAt(0));
96 const Instance& index = Instance::CheckedHandle(arguments.ArgAt(1)); 118 const Instance& index = Instance::CheckedHandle(arguments.ArgAt(1));
97 if (!length.IsInteger()) { 119 if (!length.IsInteger()) {
98 // Throw: new ArgumentError.value(length, "length", "is not an integer"); 120 // Throw: new ArgumentError.value(length, "length", "is not an integer");
99 const Array& args = Array::Handle(Array::New(3)); 121 const Array& args = Array::Handle(Array::New(3));
100 args.SetAt(0, length); 122 args.SetAt(0, length);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 const TypeArguments& instantiator = 240 const TypeArguments& instantiator =
219 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); 241 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1));
220 ASSERT(!type.IsNull() && !type.IsInstantiated()); 242 ASSERT(!type.IsNull() && !type.IsInstantiated());
221 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); 243 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
222 Error& bound_error = Error::Handle(zone); 244 Error& bound_error = Error::Handle(zone);
223 type = 245 type =
224 type.InstantiateFrom(instantiator, &bound_error, NULL, NULL, Heap::kOld); 246 type.InstantiateFrom(instantiator, &bound_error, NULL, NULL, Heap::kOld);
225 if (!bound_error.IsNull()) { 247 if (!bound_error.IsNull()) {
226 // Throw a dynamic type error. 248 // Throw a dynamic type error.
227 const TokenPosition location = GetCallerLocation(); 249 const TokenPosition location = GetCallerLocation();
228 String& bound_error_message = String::Handle( 250 String& bound_error_message =
229 zone, String::New(bound_error.ToErrorCString())); 251 String::Handle(zone, String::New(bound_error.ToErrorCString()));
230 Exceptions::CreateAndThrowTypeError( 252 Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone),
231 location, AbstractType::Handle(zone), AbstractType::Handle(zone), 253 AbstractType::Handle(zone),
232 Symbols::Empty(), bound_error_message); 254 Symbols::Empty(), bound_error_message);
233 UNREACHABLE(); 255 UNREACHABLE();
234 } 256 }
235 if (type.IsTypeRef()) { 257 if (type.IsTypeRef()) {
236 type = TypeRef::Cast(type).type(); 258 type = TypeRef::Cast(type).type();
237 ASSERT(!type.IsTypeRef()); 259 ASSERT(!type.IsTypeRef());
238 ASSERT(type.IsCanonical()); 260 ASSERT(type.IsCanonical());
239 } 261 }
240 ASSERT(!type.IsNull() && type.IsInstantiated()); 262 ASSERT(!type.IsNull() && type.IsInstantiated());
241 arguments.SetReturn(type); 263 arguments.SetReturn(type);
242 } 264 }
243 265
244 266
245 // Instantiate type arguments. 267 // Instantiate type arguments.
246 // Arg0: uninstantiated type arguments. 268 // Arg0: uninstantiated type arguments.
247 // Arg1: instantiator type arguments. 269 // Arg1: instantiator type arguments.
248 // Return value: instantiated type arguments. 270 // Return value: instantiated type arguments.
249 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { 271 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) {
250 TypeArguments& type_arguments = 272 TypeArguments& type_arguments =
251 TypeArguments::CheckedHandle(zone, arguments.ArgAt(0)); 273 TypeArguments::CheckedHandle(zone, arguments.ArgAt(0));
252 const TypeArguments& instantiator = 274 const TypeArguments& instantiator =
253 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); 275 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1));
254 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated()); 276 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated());
255 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); 277 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
256 // Code inlined in the caller should have optimized the case where the 278 // Code inlined in the caller should have optimized the case where the
257 // instantiator can be reused as type argument vector. 279 // instantiator can be reused as type argument vector.
258 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity()); 280 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
259 if (isolate->type_checks()) { 281 if (isolate->type_checks()) {
260 Error& bound_error = Error::Handle(zone); 282 Error& bound_error = Error::Handle(zone);
261 type_arguments = 283 type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
262 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, 284 instantiator, &bound_error);
263 &bound_error);
264 if (!bound_error.IsNull()) { 285 if (!bound_error.IsNull()) {
265 // Throw a dynamic type error. 286 // Throw a dynamic type error.
266 const TokenPosition location = GetCallerLocation(); 287 const TokenPosition location = GetCallerLocation();
267 String& bound_error_message = String::Handle( 288 String& bound_error_message =
268 zone, String::New(bound_error.ToErrorCString())); 289 String::Handle(zone, String::New(bound_error.ToErrorCString()));
269 Exceptions::CreateAndThrowTypeError( 290 Exceptions::CreateAndThrowTypeError(
270 location, AbstractType::Handle(zone), AbstractType::Handle(zone), 291 location, AbstractType::Handle(zone), AbstractType::Handle(zone),
271 Symbols::Empty(), bound_error_message); 292 Symbols::Empty(), bound_error_message);
272 UNREACHABLE(); 293 UNREACHABLE();
273 } 294 }
274 } else { 295 } else {
275 type_arguments = 296 type_arguments =
276 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL); 297 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL);
277 } 298 }
278 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); 299 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
(...skipping 22 matching lines...) Expand all
301 Object& inst = Object::Handle(zone); 322 Object& inst = Object::Handle(zone);
302 for (int i = 0; i < ctx.num_variables(); i++) { 323 for (int i = 0; i < ctx.num_variables(); i++) {
303 inst = ctx.At(i); 324 inst = ctx.At(i);
304 cloned_ctx.SetAt(i, inst); 325 cloned_ctx.SetAt(i, inst);
305 } 326 }
306 arguments.SetReturn(cloned_ctx); 327 arguments.SetReturn(cloned_ctx);
307 } 328 }
308 329
309 330
310 // Helper routine for tracing a type check. 331 // Helper routine for tracing a type check.
311 static void PrintTypeCheck( 332 static void PrintTypeCheck(const char* message,
312 const char* message, 333 const Instance& instance,
313 const Instance& instance, 334 const AbstractType& type,
314 const AbstractType& type, 335 const TypeArguments& instantiator_type_arguments,
315 const TypeArguments& instantiator_type_arguments, 336 const Bool& result) {
316 const Bool& result) {
317 DartFrameIterator iterator; 337 DartFrameIterator iterator;
318 StackFrame* caller_frame = iterator.NextFrame(); 338 StackFrame* caller_frame = iterator.NextFrame();
319 ASSERT(caller_frame != NULL); 339 ASSERT(caller_frame != NULL);
320 340
321 const AbstractType& instance_type = AbstractType::Handle(instance.GetType()); 341 const AbstractType& instance_type = AbstractType::Handle(instance.GetType());
322 ASSERT(instance_type.IsInstantiated()); 342 ASSERT(instance_type.IsInstantiated());
323 if (type.IsInstantiated()) { 343 if (type.IsInstantiated()) {
324 OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n", 344 OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n", message,
325 message,
326 String::Handle(instance_type.Name()).ToCString(), 345 String::Handle(instance_type.Name()).ToCString(),
327 Class::Handle(instance_type.type_class()).id(), 346 Class::Handle(instance_type.type_class()).id(),
328 (result.raw() == Bool::True().raw()) ? "is" : "is !", 347 (result.raw() == Bool::True().raw()) ? "is" : "is !",
329 String::Handle(type.Name()).ToCString(), 348 String::Handle(type.Name()).ToCString(),
330 Class::Handle(type.type_class()).id(), 349 Class::Handle(type.type_class()).id(), caller_frame->pc());
331 caller_frame->pc());
332 } else { 350 } else {
333 // Instantiate type before printing. 351 // Instantiate type before printing.
334 Error& bound_error = Error::Handle(); 352 Error& bound_error = Error::Handle();
335 const AbstractType& instantiated_type = AbstractType::Handle( 353 const AbstractType& instantiated_type =
336 type.InstantiateFrom(instantiator_type_arguments, &bound_error, 354 AbstractType::Handle(type.InstantiateFrom(
337 NULL, NULL, Heap::kOld)); 355 instantiator_type_arguments, &bound_error, NULL, NULL, Heap::kOld));
338 OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n", 356 OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n",
339 message, 357 message, String::Handle(instance_type.Name()).ToCString(),
340 String::Handle(instance_type.Name()).ToCString(),
341 (result.raw() == Bool::True().raw()) ? "is" : "is !", 358 (result.raw() == Bool::True().raw()) ? "is" : "is !",
342 String::Handle(instantiated_type.Name()).ToCString(), 359 String::Handle(instantiated_type.Name()).ToCString(),
343 String::Handle(type.Name()).ToCString(), 360 String::Handle(type.Name()).ToCString(), caller_frame->pc());
344 caller_frame->pc());
345 if (!bound_error.IsNull()) { 361 if (!bound_error.IsNull()) {
346 OS::Print(" bound error: %s\n", bound_error.ToErrorCString()); 362 OS::Print(" bound error: %s\n", bound_error.ToErrorCString());
347 } 363 }
348 } 364 }
349 const Function& function = Function::Handle( 365 const Function& function =
350 caller_frame->LookupDartFunction()); 366 Function::Handle(caller_frame->LookupDartFunction());
351 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); 367 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString());
352 } 368 }
353 369
354 370
355 // This updates the type test cache, an array containing 4-value elements 371 // This updates the type test cache, an array containing 4-value elements
356 // (instance class (or function if the instance is a closure), instance type 372 // (instance class (or function if the instance is a closure), instance type
357 // arguments, instantiator type arguments and test_result). It can be applied to 373 // arguments, instantiator type arguments and test_result). It can be applied to
358 // classes with type arguments in which case it contains just the result of the 374 // classes with type arguments in which case it contains just the result of the
359 // class subtype test, not including the evaluation of type arguments. 375 // class subtype test, not including the evaluation of type arguments.
360 // This operation is currently very slow (lookup of code is not efficient yet). 376 // This operation is currently very slow (lookup of code is not efficient yet).
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 #if defined(DEBUG) 415 #if defined(DEBUG)
400 ASSERT(instance_type_arguments.IsNull() || 416 ASSERT(instance_type_arguments.IsNull() ||
401 instance_type_arguments.IsCanonical()); 417 instance_type_arguments.IsCanonical());
402 ASSERT(instantiator_type_arguments.IsNull() || 418 ASSERT(instantiator_type_arguments.IsNull() ||
403 instantiator_type_arguments.IsCanonical()); 419 instantiator_type_arguments.IsCanonical());
404 Object& last_instance_class_id_or_function = Object::Handle(); 420 Object& last_instance_class_id_or_function = Object::Handle();
405 TypeArguments& last_instance_type_arguments = TypeArguments::Handle(); 421 TypeArguments& last_instance_type_arguments = TypeArguments::Handle();
406 TypeArguments& last_instantiator_type_arguments = TypeArguments::Handle(); 422 TypeArguments& last_instantiator_type_arguments = TypeArguments::Handle();
407 Bool& last_result = Bool::Handle(); 423 Bool& last_result = Bool::Handle();
408 for (intptr_t i = 0; i < len; ++i) { 424 for (intptr_t i = 0; i < len; ++i) {
409 new_cache.GetCheck( 425 new_cache.GetCheck(i, &last_instance_class_id_or_function,
410 i, 426 &last_instance_type_arguments,
411 &last_instance_class_id_or_function, 427 &last_instantiator_type_arguments, &last_result);
412 &last_instance_type_arguments,
413 &last_instantiator_type_arguments,
414 &last_result);
415 if ((last_instance_class_id_or_function.raw() == 428 if ((last_instance_class_id_or_function.raw() ==
416 instance_class_id_or_function.raw()) && 429 instance_class_id_or_function.raw()) &&
417 (last_instance_type_arguments.raw() == instance_type_arguments.raw()) && 430 (last_instance_type_arguments.raw() == instance_type_arguments.raw()) &&
418 (last_instantiator_type_arguments.raw() == 431 (last_instantiator_type_arguments.raw() ==
419 instantiator_type_arguments.raw())) { 432 instantiator_type_arguments.raw())) {
420 OS::PrintErr(" Error in test cache %p ix: %" Pd ",", new_cache.raw(), i); 433 OS::PrintErr(" Error in test cache %p ix: %" Pd ",", new_cache.raw(), i);
421 PrintTypeCheck(" duplicate cache entry", instance, type, 434 PrintTypeCheck(" duplicate cache entry", instance, type,
422 instantiator_type_arguments, result); 435 instantiator_type_arguments, result);
423 UNREACHABLE(); 436 UNREACHABLE();
424 return; 437 return;
425 } 438 }
426 } 439 }
427 #endif 440 #endif
428 new_cache.AddCheck(instance_class_id_or_function, 441 new_cache.AddCheck(instance_class_id_or_function, instance_type_arguments,
429 instance_type_arguments, 442 instantiator_type_arguments, result);
430 instantiator_type_arguments,
431 result);
432 if (FLAG_trace_type_checks) { 443 if (FLAG_trace_type_checks) {
433 AbstractType& test_type = AbstractType::Handle(type.raw()); 444 AbstractType& test_type = AbstractType::Handle(type.raw());
434 if (!test_type.IsInstantiated()) { 445 if (!test_type.IsInstantiated()) {
435 Error& bound_error = Error::Handle(); 446 Error& bound_error = Error::Handle();
436 test_type = type.InstantiateFrom(instantiator_type_arguments, 447 test_type = type.InstantiateFrom(instantiator_type_arguments,
437 &bound_error, 448 &bound_error, NULL, NULL, Heap::kNew);
438 NULL, NULL, Heap::kNew);
439 ASSERT(bound_error.IsNull()); // Malbounded types are not optimized. 449 ASSERT(bound_error.IsNull()); // Malbounded types are not optimized.
440 } 450 }
441 OS::PrintErr(" Updated test cache %p ix: %" Pd " with " 451 OS::PrintErr(
452 " Updated test cache %p ix: %" Pd
453 " with "
442 "(cid-or-fun: %p, type-args: %p, instantiator: %p, result: %s)\n" 454 "(cid-or-fun: %p, type-args: %p, instantiator: %p, result: %s)\n"
443 " instance [class: (%p '%s' cid: %" Pd "), type-args: %p %s]\n" 455 " instance [class: (%p '%s' cid: %" Pd
456 "), type-args: %p %s]\n"
444 " test-type [class: (%p '%s' cid: %" Pd "), in-type-args: %p %s]\n", 457 " test-type [class: (%p '%s' cid: %" Pd "), in-type-args: %p %s]\n",
445 new_cache.raw(), 458 new_cache.raw(), len,
446 len,
447 459
448 instance_class_id_or_function.raw(), 460 instance_class_id_or_function.raw(), instance_type_arguments.raw(),
449 instance_type_arguments.raw(), 461 instantiator_type_arguments.raw(), result.ToCString(),
450 instantiator_type_arguments.raw(),
451 result.ToCString(),
452 462
453 instance_class.raw(), 463 instance_class.raw(), String::Handle(instance_class.Name()).ToCString(),
454 String::Handle(instance_class.Name()).ToCString(), 464 instance_class.id(), instance_type_arguments.raw(),
455 instance_class.id(),
456 instance_type_arguments.raw(),
457 instance_type_arguments.ToCString(), 465 instance_type_arguments.ToCString(),
458 466
459 test_type.type_class(), 467 test_type.type_class(),
460 String::Handle(Class::Handle(test_type.type_class()).Name()). 468 String::Handle(Class::Handle(test_type.type_class()).Name())
461 ToCString(), 469 .ToCString(),
462 Class::Handle(test_type.type_class()).id(), 470 Class::Handle(test_type.type_class()).id(),
463 instantiator_type_arguments.raw(), 471 instantiator_type_arguments.raw(),
464 instantiator_type_arguments.ToCString()); 472 instantiator_type_arguments.ToCString());
465 } 473 }
466 } 474 }
467 475
468 476
469 // Check that the given instance is an instance of the given type. 477 // Check that the given instance is an instance of the given type.
470 // Tested instance may not be null, because the null test is inlined. 478 // Tested instance may not be null, because the null test is inlined.
471 // Arg0: instance being checked. 479 // Arg0: instance being checked.
472 // Arg1: type. 480 // Arg1: type.
473 // Arg2: type arguments of the instantiator of the type. 481 // Arg2: type arguments of the instantiator of the type.
474 // Arg3: SubtypeTestCache. 482 // Arg3: SubtypeTestCache.
475 // Return value: true or false, or may throw a type error in checked mode. 483 // Return value: true or false, or may throw a type error in checked mode.
476 DEFINE_RUNTIME_ENTRY(Instanceof, 4) { 484 DEFINE_RUNTIME_ENTRY(Instanceof, 4) {
477 const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0)); 485 const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0));
478 const AbstractType& type = 486 const AbstractType& type =
479 AbstractType::CheckedHandle(zone, arguments.ArgAt(1)); 487 AbstractType::CheckedHandle(zone, arguments.ArgAt(1));
480 const TypeArguments& instantiator_type_arguments = 488 const TypeArguments& instantiator_type_arguments =
481 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); 489 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2));
482 const SubtypeTestCache& cache = 490 const SubtypeTestCache& cache =
483 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(3)); 491 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(3));
484 ASSERT(type.IsFinalized()); 492 ASSERT(type.IsFinalized());
485 ASSERT(!type.IsMalformed()); // Already checked in code generator. 493 ASSERT(!type.IsMalformed()); // Already checked in code generator.
486 ASSERT(!type.IsMalbounded()); // Already checked in code generator. 494 ASSERT(!type.IsMalbounded()); // Already checked in code generator.
487 ASSERT(!type.IsDynamicType()); // No need to check assignment. 495 ASSERT(!type.IsDynamicType()); // No need to check assignment.
488 Error& bound_error = Error::Handle(zone); 496 Error& bound_error = Error::Handle(zone);
489 const Bool& result = 497 const Bool& result = Bool::Get(
490 Bool::Get(instance.IsInstanceOf(type, 498 instance.IsInstanceOf(type, instantiator_type_arguments, &bound_error));
491 instantiator_type_arguments,
492 &bound_error));
493 if (FLAG_trace_type_checks) { 499 if (FLAG_trace_type_checks) {
494 PrintTypeCheck("InstanceOf", 500 PrintTypeCheck("InstanceOf", instance, type, instantiator_type_arguments,
495 instance, type, instantiator_type_arguments, result); 501 result);
496 } 502 }
497 if (!result.value() && !bound_error.IsNull()) { 503 if (!result.value() && !bound_error.IsNull()) {
498 // Throw a dynamic type error only if the instanceof test fails. 504 // Throw a dynamic type error only if the instanceof test fails.
499 const TokenPosition location = GetCallerLocation(); 505 const TokenPosition location = GetCallerLocation();
500 String& bound_error_message = String::Handle( 506 String& bound_error_message =
501 zone, String::New(bound_error.ToErrorCString())); 507 String::Handle(zone, String::New(bound_error.ToErrorCString()));
502 Exceptions::CreateAndThrowTypeError( 508 Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone),
503 location, AbstractType::Handle(zone), AbstractType::Handle(zone), 509 AbstractType::Handle(zone),
504 Symbols::Empty(), bound_error_message); 510 Symbols::Empty(), bound_error_message);
505 UNREACHABLE(); 511 UNREACHABLE();
506 } 512 }
507 UpdateTypeTestCache( 513 UpdateTypeTestCache(instance, type, instantiator_type_arguments, result,
508 instance, type, instantiator_type_arguments, result, cache); 514 cache);
509 arguments.SetReturn(result); 515 arguments.SetReturn(result);
510 } 516 }
511 517
512 518
513 // Check that the type of the given instance is a subtype of the given type and 519 // Check that the type of the given instance is a subtype of the given type and
514 // can therefore be assigned. 520 // can therefore be assigned.
515 // Arg0: instance being assigned. 521 // Arg0: instance being assigned.
516 // Arg1: type being assigned to. 522 // Arg1: type being assigned to.
517 // Arg2: type arguments of the instantiator of the type being assigned to. 523 // Arg2: type arguments of the instantiator of the type being assigned to.
518 // Arg3: name of variable being assigned to. 524 // Arg3: name of variable being assigned to.
519 // Arg4: SubtypeTestCache. 525 // Arg4: SubtypeTestCache.
520 // Return value: instance if a subtype, otherwise throw a TypeError. 526 // Return value: instance if a subtype, otherwise throw a TypeError.
521 DEFINE_RUNTIME_ENTRY(TypeCheck, 5) { 527 DEFINE_RUNTIME_ENTRY(TypeCheck, 5) {
522 const Instance& src_instance = 528 const Instance& src_instance =
523 Instance::CheckedHandle(zone, arguments.ArgAt(0)); 529 Instance::CheckedHandle(zone, arguments.ArgAt(0));
524 AbstractType& dst_type = 530 AbstractType& dst_type =
525 AbstractType::CheckedHandle(zone, arguments.ArgAt(1)); 531 AbstractType::CheckedHandle(zone, arguments.ArgAt(1));
526 const TypeArguments& instantiator_type_arguments = 532 const TypeArguments& instantiator_type_arguments =
527 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); 533 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2));
528 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(3)); 534 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(3));
529 const SubtypeTestCache& cache = 535 const SubtypeTestCache& cache =
530 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(4)); 536 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(4));
531 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. 537 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator.
532 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator. 538 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator.
533 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. 539 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment.
534 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. 540 ASSERT(!src_instance.IsNull()); // Already checked in inlined code.
535 541
536 Error& bound_error = Error::Handle(zone); 542 Error& bound_error = Error::Handle(zone);
537 const bool is_instance_of = src_instance.IsInstanceOf( 543 const bool is_instance_of = src_instance.IsInstanceOf(
538 dst_type, instantiator_type_arguments, &bound_error); 544 dst_type, instantiator_type_arguments, &bound_error);
539 545
540 if (FLAG_trace_type_checks) { 546 if (FLAG_trace_type_checks) {
541 PrintTypeCheck("TypeCheck", 547 PrintTypeCheck("TypeCheck", src_instance, dst_type,
542 src_instance, dst_type, instantiator_type_arguments, 548 instantiator_type_arguments, Bool::Get(is_instance_of));
543 Bool::Get(is_instance_of));
544 } 549 }
545 if (!is_instance_of) { 550 if (!is_instance_of) {
546 // Throw a dynamic type error. 551 // Throw a dynamic type error.
547 const TokenPosition location = GetCallerLocation(); 552 const TokenPosition location = GetCallerLocation();
548 const AbstractType& src_type = 553 const AbstractType& src_type =
549 AbstractType::Handle(zone, src_instance.GetType()); 554 AbstractType::Handle(zone, src_instance.GetType());
550 if (!dst_type.IsInstantiated()) { 555 if (!dst_type.IsInstantiated()) {
551 // Instantiate dst_type before reporting the error. 556 // Instantiate dst_type before reporting the error.
552 dst_type = dst_type.InstantiateFrom(instantiator_type_arguments, NULL, 557 dst_type = dst_type.InstantiateFrom(instantiator_type_arguments, NULL,
553 NULL, NULL, Heap::kNew); 558 NULL, NULL, Heap::kNew);
554 // Note that instantiated dst_type may be malbounded. 559 // Note that instantiated dst_type may be malbounded.
555 } 560 }
556 String& bound_error_message = String::Handle(zone); 561 String& bound_error_message = String::Handle(zone);
557 if (!bound_error.IsNull()) { 562 if (!bound_error.IsNull()) {
558 ASSERT(isolate->type_checks()); 563 ASSERT(isolate->type_checks());
559 bound_error_message = String::New(bound_error.ToErrorCString()); 564 bound_error_message = String::New(bound_error.ToErrorCString());
560 } 565 }
561 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, 566 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name,
562 dst_name, bound_error_message); 567 bound_error_message);
563 UNREACHABLE(); 568 UNREACHABLE();
564 } 569 }
565 UpdateTypeTestCache( 570 UpdateTypeTestCache(src_instance, dst_type, instantiator_type_arguments,
566 src_instance, dst_type, instantiator_type_arguments, Bool::True(), cache); 571 Bool::True(), cache);
567 arguments.SetReturn(src_instance); 572 arguments.SetReturn(src_instance);
568 } 573 }
569 574
570 575
571 // Report that the type of the given object is not bool in conditional context. 576 // Report that the type of the given object is not bool in conditional context.
572 // Throw assertion error if the object is null. (cf. Boolean Conversion 577 // Throw assertion error if the object is null. (cf. Boolean Conversion
573 // in language Spec.) 578 // in language Spec.)
574 // Arg0: bad object. 579 // Arg0: bad object.
575 // Return value: none, throws TypeError or AssertionError. 580 // Return value: none, throws TypeError or AssertionError.
576 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) { 581 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) {
577 const TokenPosition location = GetCallerLocation(); 582 const TokenPosition location = GetCallerLocation();
578 const Instance& src_instance = 583 const Instance& src_instance =
579 Instance::CheckedHandle(zone, arguments.ArgAt(0)); 584 Instance::CheckedHandle(zone, arguments.ArgAt(0));
580 585
581 if (src_instance.IsNull()) { 586 if (src_instance.IsNull()) {
582 const Array& args = Array::Handle(zone, Array::New(4)); 587 const Array& args = Array::Handle(zone, Array::New(4));
583 args.SetAt(0, String::Handle(zone, 588 args.SetAt(
584 String::New("Failed assertion: boolean expression must not be null"))); 589 0, String::Handle(
590 zone,
591 String::New(
592 "Failed assertion: boolean expression must not be null")));
585 593
586 // No source code for this assertion, set url to null. 594 // No source code for this assertion, set url to null.
587 args.SetAt(1, String::Handle(zone, String::null())); 595 args.SetAt(1, String::Handle(zone, String::null()));
588 args.SetAt(2, Smi::Handle(zone, Smi::New(0))); 596 args.SetAt(2, Smi::Handle(zone, Smi::New(0)));
589 args.SetAt(3, Smi::Handle(zone, Smi::New(0))); 597 args.SetAt(3, Smi::Handle(zone, Smi::New(0)));
590 598
591 Exceptions::ThrowByType(Exceptions::kAssertion, args); 599 Exceptions::ThrowByType(Exceptions::kAssertion, args);
592 UNREACHABLE(); 600 UNREACHABLE();
593 } 601 }
594 602
(...skipping 15 matching lines...) Expand all
610 // Arg2: type of destination being assigned to. 618 // Arg2: type of destination being assigned to.
611 // Return value: none, throws an exception. 619 // Return value: none, throws an exception.
612 DEFINE_RUNTIME_ENTRY(BadTypeError, 3) { 620 DEFINE_RUNTIME_ENTRY(BadTypeError, 3) {
613 const TokenPosition location = GetCallerLocation(); 621 const TokenPosition location = GetCallerLocation();
614 const Instance& src_value = Instance::CheckedHandle(zone, arguments.ArgAt(0)); 622 const Instance& src_value = Instance::CheckedHandle(zone, arguments.ArgAt(0));
615 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(1)); 623 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(1));
616 const AbstractType& dst_type = 624 const AbstractType& dst_type =
617 AbstractType::CheckedHandle(zone, arguments.ArgAt(2)); 625 AbstractType::CheckedHandle(zone, arguments.ArgAt(2));
618 const AbstractType& src_type = 626 const AbstractType& src_type =
619 AbstractType::Handle(zone, src_value.GetType()); 627 AbstractType::Handle(zone, src_value.GetType());
620 Exceptions::CreateAndThrowTypeError( 628 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name,
621 location, src_type, dst_type, dst_name, String::Handle(zone)); 629 String::Handle(zone));
622 UNREACHABLE(); 630 UNREACHABLE();
623 } 631 }
624 632
625 633
626 DEFINE_RUNTIME_ENTRY(Throw, 1) { 634 DEFINE_RUNTIME_ENTRY(Throw, 1) {
627 const Instance& exception = 635 const Instance& exception = Instance::CheckedHandle(zone, arguments.ArgAt(0));
628 Instance::CheckedHandle(zone, arguments.ArgAt(0));
629 Exceptions::Throw(thread, exception); 636 Exceptions::Throw(thread, exception);
630 } 637 }
631 638
632 639
633 DEFINE_RUNTIME_ENTRY(ReThrow, 2) { 640 DEFINE_RUNTIME_ENTRY(ReThrow, 2) {
634 const Instance& exception = 641 const Instance& exception = Instance::CheckedHandle(zone, arguments.ArgAt(0));
635 Instance::CheckedHandle(zone, arguments.ArgAt(0));
636 const Instance& stacktrace = 642 const Instance& stacktrace =
637 Instance::CheckedHandle(zone, arguments.ArgAt(1)); 643 Instance::CheckedHandle(zone, arguments.ArgAt(1));
638 Exceptions::ReThrow(thread, exception, stacktrace); 644 Exceptions::ReThrow(thread, exception, stacktrace);
639 } 645 }
640 646
641 647
642 // Patches static call in optimized code with the target's entry point. 648 // Patches static call in optimized code with the target's entry point.
643 // Compiles target if necessary. 649 // Compiles target if necessary.
644 DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) { 650 DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) {
645 DartFrameIterator iterator; 651 DartFrameIterator iterator;
646 StackFrame* caller_frame = iterator.NextFrame(); 652 StackFrame* caller_frame = iterator.NextFrame();
647 ASSERT(caller_frame != NULL); 653 ASSERT(caller_frame != NULL);
648 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); 654 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
649 ASSERT(!caller_code.IsNull()); 655 ASSERT(!caller_code.IsNull());
650 ASSERT(caller_code.is_optimized()); 656 ASSERT(caller_code.is_optimized());
651 const Function& target_function = Function::Handle( 657 const Function& target_function = Function::Handle(
652 zone, caller_code.GetStaticCallTargetFunctionAt(caller_frame->pc())); 658 zone, caller_code.GetStaticCallTargetFunctionAt(caller_frame->pc()));
653 if (!target_function.HasCode()) { 659 if (!target_function.HasCode()) {
654 const Error& error = 660 const Error& error =
655 Error::Handle(zone, Compiler::CompileFunction(thread, target_function)); 661 Error::Handle(zone, Compiler::CompileFunction(thread, target_function));
656 if (!error.IsNull()) { 662 if (!error.IsNull()) {
657 Exceptions::PropagateError(error); 663 Exceptions::PropagateError(error);
658 } 664 }
659 } 665 }
660 const Code& target_code = Code::Handle(zone, target_function.CurrentCode()); 666 const Code& target_code = Code::Handle(zone, target_function.CurrentCode());
661 // Before patching verify that we are not repeatedly patching to the same 667 // Before patching verify that we are not repeatedly patching to the same
662 // target. 668 // target.
663 ASSERT(target_code.raw() != 669 ASSERT(target_code.raw() !=
664 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); 670 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code));
665 CodePatcher::PatchStaticCallAt(caller_frame->pc(), 671 CodePatcher::PatchStaticCallAt(caller_frame->pc(), caller_code, target_code);
666 caller_code,
667 target_code);
668 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); 672 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
669 if (FLAG_trace_patching) { 673 if (FLAG_trace_patching) {
670 THR_Print("PatchStaticCall: patching caller pc %#" Px "" 674 THR_Print("PatchStaticCall: patching caller pc %#" Px
671 " to '%s' new entry point %#" Px " (%s)\n", 675 ""
672 caller_frame->pc(), 676 " to '%s' new entry point %#" Px " (%s)\n",
673 target_function.ToFullyQualifiedCString(), 677 caller_frame->pc(), target_function.ToFullyQualifiedCString(),
674 target_code.UncheckedEntryPoint(), 678 target_code.UncheckedEntryPoint(),
675 target_code.is_optimized() ? "optimized" : "unoptimized"); 679 target_code.is_optimized() ? "optimized" : "unoptimized");
676 } 680 }
677 arguments.SetReturn(target_code); 681 arguments.SetReturn(target_code);
678 } 682 }
679 683
680 684
681 // Result of an invoke may be an unhandled exception, in which case we 685 // Result of an invoke may be an unhandled exception, in which case we
682 // rethrow it. 686 // rethrow it.
683 static void CheckResultError(const Object& result) { 687 static void CheckResultError(const Object& result) {
684 if (result.IsError()) { 688 if (result.IsError()) {
685 Exceptions::PropagateError(Error::Cast(result)); 689 Exceptions::PropagateError(Error::Cast(result));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 static bool ResolveCallThroughGetter(const Instance& receiver, 749 static bool ResolveCallThroughGetter(const Instance& receiver,
746 const Class& receiver_class, 750 const Class& receiver_class,
747 const String& target_name, 751 const String& target_name,
748 const Array& arguments_descriptor, 752 const Array& arguments_descriptor,
749 Function* result) { 753 Function* result) {
750 // 1. Check if there is a getter with the same name. 754 // 1. Check if there is a getter with the same name.
751 const String& getter_name = String::Handle(Field::GetterName(target_name)); 755 const String& getter_name = String::Handle(Field::GetterName(target_name));
752 const int kNumArguments = 1; 756 const int kNumArguments = 1;
753 ArgumentsDescriptor args_desc( 757 ArgumentsDescriptor args_desc(
754 Array::Handle(ArgumentsDescriptor::New(kNumArguments))); 758 Array::Handle(ArgumentsDescriptor::New(kNumArguments)));
755 const Function& getter = Function::Handle( 759 const Function& getter =
756 Resolver::ResolveDynamicForReceiverClass(receiver_class, 760 Function::Handle(Resolver::ResolveDynamicForReceiverClass(
757 getter_name, 761 receiver_class, getter_name, args_desc));
758 args_desc));
759 if (getter.IsNull() || getter.IsMethodExtractor()) { 762 if (getter.IsNull() || getter.IsMethodExtractor()) {
760 return false; 763 return false;
761 } 764 }
762 const Function& target_function = 765 const Function& target_function =
763 Function::Handle(receiver_class.GetInvocationDispatcher( 766 Function::Handle(receiver_class.GetInvocationDispatcher(
764 target_name, 767 target_name, arguments_descriptor,
765 arguments_descriptor, 768 RawFunction::kInvokeFieldDispatcher, FLAG_lazy_dispatchers));
766 RawFunction::kInvokeFieldDispatcher,
767 FLAG_lazy_dispatchers));
768 ASSERT(!target_function.IsNull() || !FLAG_lazy_dispatchers); 769 ASSERT(!target_function.IsNull() || !FLAG_lazy_dispatchers);
769 if (FLAG_trace_ic) { 770 if (FLAG_trace_ic) {
770 OS::PrintErr("InvokeField IC miss: adding <%s> id:%" Pd " -> <%s>\n", 771 OS::PrintErr(
771 Class::Handle(receiver.clazz()).ToCString(), 772 "InvokeField IC miss: adding <%s> id:%" Pd " -> <%s>\n",
772 receiver.GetClassId(), 773 Class::Handle(receiver.clazz()).ToCString(), receiver.GetClassId(),
773 target_function.IsNull() ? "null" : target_function.ToCString()); 774 target_function.IsNull() ? "null" : target_function.ToCString());
774 } 775 }
775 *result = target_function.raw(); 776 *result = target_function.raw();
776 return true; 777 return true;
777 } 778 }
778 779
779 780
780 // Handle other invocations (implicit closures, noSuchMethod). 781 // Handle other invocations (implicit closures, noSuchMethod).
781 RawFunction* InlineCacheMissHelper( 782 RawFunction* InlineCacheMissHelper(const Instance& receiver,
782 const Instance& receiver, 783 const Array& args_descriptor,
783 const Array& args_descriptor, 784 const String& target_name) {
784 const String& target_name) {
785 const Class& receiver_class = Class::Handle(receiver.clazz()); 785 const Class& receiver_class = Class::Handle(receiver.clazz());
786 786
787 Function& result = Function::Handle(); 787 Function& result = Function::Handle();
788 if (!ResolveCallThroughGetter(receiver, 788 if (!ResolveCallThroughGetter(receiver, receiver_class, target_name,
789 receiver_class, 789 args_descriptor, &result)) {
790 target_name,
791 args_descriptor,
792 &result)) {
793 ArgumentsDescriptor desc(args_descriptor); 790 ArgumentsDescriptor desc(args_descriptor);
794 const Function& target_function = 791 const Function& target_function =
795 Function::Handle(receiver_class.GetInvocationDispatcher( 792 Function::Handle(receiver_class.GetInvocationDispatcher(
796 target_name, 793 target_name, args_descriptor, RawFunction::kNoSuchMethodDispatcher,
797 args_descriptor,
798 RawFunction::kNoSuchMethodDispatcher,
799 FLAG_lazy_dispatchers)); 794 FLAG_lazy_dispatchers));
800 if (FLAG_trace_ic) { 795 if (FLAG_trace_ic) {
801 OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n", 796 OS::PrintErr(
802 Class::Handle(receiver.clazz()).ToCString(), 797 "NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n",
803 receiver.GetClassId(), 798 Class::Handle(receiver.clazz()).ToCString(), receiver.GetClassId(),
804 target_function.IsNull() ? "null" : target_function.ToCString()); 799 target_function.IsNull() ? "null" : target_function.ToCString());
805 } 800 }
806 result = target_function.raw(); 801 result = target_function.raw();
807 } 802 }
808 // May be null if --no-lazy-dispatchers, in which case dispatch will be 803 // May be null if --no-lazy-dispatchers, in which case dispatch will be
809 // handled by InvokeNoSuchMethodDispatcher. 804 // handled by InvokeNoSuchMethodDispatcher.
810 ASSERT(!result.IsNull() || !FLAG_lazy_dispatchers); 805 ASSERT(!result.IsNull() || !FLAG_lazy_dispatchers);
811 return result.raw(); 806 return result.raw();
812 } 807 }
813 808
814 809
815 // Perform the subtype and return constant function based on the result. 810 // Perform the subtype and return constant function based on the result.
816 static RawFunction* ComputeTypeCheckTarget(const Instance& receiver, 811 static RawFunction* ComputeTypeCheckTarget(const Instance& receiver,
817 const AbstractType& type, 812 const AbstractType& type,
818 const ArgumentsDescriptor& desc) { 813 const ArgumentsDescriptor& desc) {
819 const TypeArguments& checked_type_arguments = TypeArguments::Handle(); 814 const TypeArguments& checked_type_arguments = TypeArguments::Handle();
820 Error& error = Error::Handle(); 815 Error& error = Error::Handle();
821 bool result = receiver.IsInstanceOf(type, checked_type_arguments, &error); 816 bool result = receiver.IsInstanceOf(type, checked_type_arguments, &error);
822 ASSERT(error.IsNull()); 817 ASSERT(error.IsNull());
823 ObjectStore* store = Isolate::Current()->object_store(); 818 ObjectStore* store = Isolate::Current()->object_store();
824 const Function& target 819 const Function& target =
825 = Function::Handle(result 820 Function::Handle(result ? store->simple_instance_of_true_function()
826 ? store->simple_instance_of_true_function() 821 : store->simple_instance_of_false_function());
827 : store->simple_instance_of_false_function());
828 ASSERT(!target.IsNull()); 822 ASSERT(!target.IsNull());
829 return target.raw(); 823 return target.raw();
830 } 824 }
831 825
832 826
833 static RawFunction* InlineCacheMissHandler( 827 static RawFunction* InlineCacheMissHandler(
834 const GrowableArray<const Instance*>& args, 828 const GrowableArray<const Instance*>& args,
835 const ICData& ic_data) { 829 const ICData& ic_data) {
836 const Instance& receiver = *args[0]; 830 const Instance& receiver = *args[0];
837 ArgumentsDescriptor 831 ArgumentsDescriptor arguments_descriptor(
838 arguments_descriptor(Array::Handle(ic_data.arguments_descriptor())); 832 Array::Handle(ic_data.arguments_descriptor()));
839 String& function_name = String::Handle(ic_data.target_name()); 833 String& function_name = String::Handle(ic_data.target_name());
840 ASSERT(function_name.IsSymbol()); 834 ASSERT(function_name.IsSymbol());
841 835
842 Function& target_function = Function::Handle( 836 Function& target_function = Function::Handle(
843 Resolver::ResolveDynamic(receiver, function_name, arguments_descriptor)); 837 Resolver::ResolveDynamic(receiver, function_name, arguments_descriptor));
844 838
845 ObjectStore* store = Isolate::Current()->object_store(); 839 ObjectStore* store = Isolate::Current()->object_store();
846 if (target_function.raw() == store->simple_instance_of_function()) { 840 if (target_function.raw() == store->simple_instance_of_function()) {
847 // Replace the target function with constant function. 841 // Replace the target function with constant function.
848 const AbstractType& type = AbstractType::Cast(*args[1]); 842 const AbstractType& type = AbstractType::Cast(*args[1]);
849 target_function 843 target_function =
850 = ComputeTypeCheckTarget(receiver, type, arguments_descriptor); 844 ComputeTypeCheckTarget(receiver, type, arguments_descriptor);
851 } 845 }
852 if (target_function.IsNull()) { 846 if (target_function.IsNull()) {
853 if (FLAG_trace_ic) { 847 if (FLAG_trace_ic) {
854 OS::PrintErr("InlineCacheMissHandler NULL function for %s receiver: %s\n", 848 OS::PrintErr("InlineCacheMissHandler NULL function for %s receiver: %s\n",
855 String::Handle(ic_data.target_name()).ToCString(), 849 String::Handle(ic_data.target_name()).ToCString(),
856 receiver.ToCString()); 850 receiver.ToCString());
857 } 851 }
858 const Array& args_descriptor = 852 const Array& args_descriptor =
859 Array::Handle(ic_data.arguments_descriptor()); 853 Array::Handle(ic_data.arguments_descriptor());
860 const String& target_name = String::Handle(ic_data.target_name()); 854 const String& target_name = String::Handle(ic_data.target_name());
861 target_function = InlineCacheMissHelper(receiver, 855 target_function =
862 args_descriptor, 856 InlineCacheMissHelper(receiver, args_descriptor, target_name);
863 target_name);
864 } 857 }
865 if (target_function.IsNull()) { 858 if (target_function.IsNull()) {
866 ASSERT(!FLAG_lazy_dispatchers); 859 ASSERT(!FLAG_lazy_dispatchers);
867 return target_function.raw(); 860 return target_function.raw();
868 } 861 }
869 if (args.length() == 1) { 862 if (args.length() == 1) {
870 ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function); 863 ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function);
871 } else { 864 } else {
872 GrowableArray<intptr_t> class_ids(args.length()); 865 GrowableArray<intptr_t> class_ids(args.length());
873 ASSERT(ic_data.NumArgsTested() == args.length()); 866 ASSERT(ic_data.NumArgsTested() == args.length());
874 for (intptr_t i = 0; i < args.length(); i++) { 867 for (intptr_t i = 0; i < args.length(); i++) {
875 class_ids.Add(args[i]->GetClassId()); 868 class_ids.Add(args[i]->GetClassId());
876 } 869 }
877 ic_data.AddCheck(class_ids, target_function); 870 ic_data.AddCheck(class_ids, target_function);
878 } 871 }
879 if (FLAG_trace_ic_miss_in_optimized || FLAG_trace_ic) { 872 if (FLAG_trace_ic_miss_in_optimized || FLAG_trace_ic) {
880 DartFrameIterator iterator; 873 DartFrameIterator iterator;
881 StackFrame* caller_frame = iterator.NextFrame(); 874 StackFrame* caller_frame = iterator.NextFrame();
882 ASSERT(caller_frame != NULL); 875 ASSERT(caller_frame != NULL);
883 if (FLAG_trace_ic_miss_in_optimized) { 876 if (FLAG_trace_ic_miss_in_optimized) {
884 const Code& caller = Code::Handle(Code::LookupCode(caller_frame->pc())); 877 const Code& caller = Code::Handle(Code::LookupCode(caller_frame->pc()));
885 if (caller.is_optimized()) { 878 if (caller.is_optimized()) {
886 OS::PrintErr("IC miss in optimized code; call %s -> %s\n", 879 OS::PrintErr("IC miss in optimized code; call %s -> %s\n",
887 Function::Handle(caller.function()).ToCString(), 880 Function::Handle(caller.function()).ToCString(),
888 target_function.ToCString()); 881 target_function.ToCString());
889 } 882 }
890 } 883 }
891 if (FLAG_trace_ic) { 884 if (FLAG_trace_ic) {
892 OS::PrintErr("InlineCacheMissHandler %" Pd " call at %#" Px "' " 885 OS::PrintErr("InlineCacheMissHandler %" Pd " call at %#" Px
886 "' "
893 "adding <%s> id:%" Pd " -> <%s>\n", 887 "adding <%s> id:%" Pd " -> <%s>\n",
894 args.length(), 888 args.length(), caller_frame->pc(),
895 caller_frame->pc(), 889 Class::Handle(receiver.clazz()).ToCString(),
896 Class::Handle(receiver.clazz()).ToCString(), 890 receiver.GetClassId(), target_function.ToCString());
897 receiver.GetClassId(),
898 target_function.ToCString());
899 } 891 }
900 } 892 }
901 return target_function.raw(); 893 return target_function.raw();
902 } 894 }
903 895
904 896
905 // Handles inline cache misses by updating the IC data array of the call site. 897 // Handles inline cache misses by updating the IC data array of the call site.
906 // Arg0: Receiver object. 898 // Arg0: Receiver object.
907 // Arg1: IC data object. 899 // Arg1: IC data object.
908 // Returns: target function with compiled code or null. 900 // Returns: target function with compiled code or null.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 // seen before. Compile the target if necessary and update the ICData. 955 // seen before. Compile the target if necessary and update the ICData.
964 // Arg0: argument. 956 // Arg0: argument.
965 // Arg1: IC data object. 957 // Arg1: IC data object.
966 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) { 958 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) {
967 const Instance& arg = Instance::CheckedHandle(arguments.ArgAt(0)); 959 const Instance& arg = Instance::CheckedHandle(arguments.ArgAt(0));
968 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); 960 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
969 // IC data for static call is prepopulated with the statically known target. 961 // IC data for static call is prepopulated with the statically known target.
970 ASSERT(ic_data.NumberOfChecks() == 1); 962 ASSERT(ic_data.NumberOfChecks() == 1);
971 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); 963 const Function& target = Function::Handle(ic_data.GetTargetAt(0));
972 if (!target.HasCode()) { 964 if (!target.HasCode()) {
973 const Error& error = Error::Handle(Compiler::CompileFunction(thread, 965 const Error& error =
974 target)); 966 Error::Handle(Compiler::CompileFunction(thread, target));
975 if (!error.IsNull()) { 967 if (!error.IsNull()) {
976 Exceptions::PropagateError(error); 968 Exceptions::PropagateError(error);
977 } 969 }
978 } 970 }
979 ASSERT(!target.IsNull() && target.HasCode()); 971 ASSERT(!target.IsNull() && target.HasCode());
980 ic_data.AddReceiverCheck(arg.GetClassId(), target, 1); 972 ic_data.AddReceiverCheck(arg.GetClassId(), target, 1);
981 if (FLAG_trace_ic) { 973 if (FLAG_trace_ic) {
982 DartFrameIterator iterator; 974 DartFrameIterator iterator;
983 StackFrame* caller_frame = iterator.NextFrame(); 975 StackFrame* caller_frame = iterator.NextFrame();
984 ASSERT(caller_frame != NULL); 976 ASSERT(caller_frame != NULL);
985 OS::PrintErr("StaticCallMissHandler at %#" Px 977 OS::PrintErr("StaticCallMissHandler at %#" Px " target %s (%" Pd ")\n",
986 " target %s (%" Pd ")\n",
987 caller_frame->pc(), target.ToCString(), arg.GetClassId()); 978 caller_frame->pc(), target.ToCString(), arg.GetClassId());
988 } 979 }
989 arguments.SetReturn(target); 980 arguments.SetReturn(target);
990 } 981 }
991 982
992 983
993 // Handles a static call in unoptimized code that has two argument types not 984 // Handles a static call in unoptimized code that has two argument types not
994 // seen before. Compile the target if necessary and update the ICData. 985 // seen before. Compile the target if necessary and update the ICData.
995 // Arg0: argument 0. 986 // Arg0: argument 0.
996 // Arg1: argument 1. 987 // Arg1: argument 1.
997 // Arg2: IC data object. 988 // Arg2: IC data object.
998 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) { 989 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) {
999 const Instance& arg0 = Instance::CheckedHandle(arguments.ArgAt(0)); 990 const Instance& arg0 = Instance::CheckedHandle(arguments.ArgAt(0));
1000 const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1)); 991 const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1));
1001 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2)); 992 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2));
1002 // IC data for static call is prepopulated with the statically known target. 993 // IC data for static call is prepopulated with the statically known target.
1003 ASSERT(ic_data.NumberOfChecks() > 0); 994 ASSERT(ic_data.NumberOfChecks() > 0);
1004 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); 995 const Function& target = Function::Handle(ic_data.GetTargetAt(0));
1005 if (!target.HasCode()) { 996 if (!target.HasCode()) {
1006 const Error& error = Error::Handle(Compiler::CompileFunction(thread, 997 const Error& error =
1007 target)); 998 Error::Handle(Compiler::CompileFunction(thread, target));
1008 if (!error.IsNull()) { 999 if (!error.IsNull()) {
1009 Exceptions::PropagateError(error); 1000 Exceptions::PropagateError(error);
1010 } 1001 }
1011 } 1002 }
1012 ASSERT(!target.IsNull() && target.HasCode()); 1003 ASSERT(!target.IsNull() && target.HasCode());
1013 GrowableArray<intptr_t> cids(2); 1004 GrowableArray<intptr_t> cids(2);
1014 cids.Add(arg0.GetClassId()); 1005 cids.Add(arg0.GetClassId());
1015 cids.Add(arg1.GetClassId()); 1006 cids.Add(arg1.GetClassId());
1016 ic_data.AddCheck(cids, target); 1007 ic_data.AddCheck(cids, target);
1017 if (FLAG_trace_ic) { 1008 if (FLAG_trace_ic) {
1018 DartFrameIterator iterator; 1009 DartFrameIterator iterator;
1019 StackFrame* caller_frame = iterator.NextFrame(); 1010 StackFrame* caller_frame = iterator.NextFrame();
1020 ASSERT(caller_frame != NULL); 1011 ASSERT(caller_frame != NULL);
1021 OS::PrintErr("StaticCallMissHandler at %#" Px 1012 OS::PrintErr("StaticCallMissHandler at %#" Px " target %s (%" Pd ", %" Pd
1022 " target %s (%" Pd ", %" Pd ")\n", 1013 ")\n",
1023 caller_frame->pc(), target.ToCString(), cids[0], cids[1]); 1014 caller_frame->pc(), target.ToCString(), cids[0], cids[1]);
1024 } 1015 }
1025 arguments.SetReturn(target); 1016 arguments.SetReturn(target);
1026 } 1017 }
1027 1018
1028 1019
1029 #if !defined(TARGET_ARCH_DBC) 1020 #if !defined(TARGET_ARCH_DBC)
1030 static bool IsSingleTarget(Isolate* isolate, 1021 static bool IsSingleTarget(Isolate* isolate,
1031 Zone* zone, 1022 Zone* zone,
1032 intptr_t lower_cid, 1023 intptr_t lower_cid,
1033 intptr_t upper_cid, 1024 intptr_t upper_cid,
1034 const Function& target, 1025 const Function& target,
1035 const String& name) { 1026 const String& name) {
1036 Class& cls = Class::Handle(zone); 1027 Class& cls = Class::Handle(zone);
1037 ClassTable* table = isolate->class_table(); 1028 ClassTable* table = isolate->class_table();
1038 Function& other_target = Function::Handle(zone); 1029 Function& other_target = Function::Handle(zone);
1039 for (intptr_t cid = lower_cid; cid <= upper_cid; cid++) { 1030 for (intptr_t cid = lower_cid; cid <= upper_cid; cid++) {
1040 if (!table->HasValidClassAt(cid)) continue; 1031 if (!table->HasValidClassAt(cid)) continue;
1041 cls = table->At(cid); 1032 cls = table->At(cid);
1042 if (cls.is_abstract()) continue; 1033 if (cls.is_abstract()) continue;
1043 if (!cls.is_allocated()) continue; 1034 if (!cls.is_allocated()) continue;
1044 other_target = Resolver::ResolveDynamicAnyArgs(zone, cls, name, 1035 other_target =
1045 false /* allow_add */); 1036 Resolver::ResolveDynamicAnyArgs(zone, cls, name, false /* allow_add */);
1046 if (other_target.raw() != target.raw()) { 1037 if (other_target.raw() != target.raw()) {
1047 return false; 1038 return false;
1048 } 1039 }
1049 } 1040 }
1050 return true; 1041 return true;
1051 } 1042 }
1052 #endif 1043 #endif
1053 1044
1054 1045
1055 // Handle a miss of a single target cache. 1046 // Handle a miss of a single target cache.
1056 // Arg0: Receiver. 1047 // Arg0: Receiver.
1057 // Returns: the ICData used to continue with a polymorphic call. 1048 // Returns: the ICData used to continue with a polymorphic call.
1058 DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 1) { 1049 DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 1) {
1059 #if defined(TARGET_ARCH_DBC) 1050 #if defined(TARGET_ARCH_DBC)
1060 // DBC does not use switchable calls. 1051 // DBC does not use switchable calls.
1061 UNREACHABLE(); 1052 UNREACHABLE();
1062 #else 1053 #else
1063 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); 1054 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
1064 1055
1065 DartFrameIterator iterator; 1056 DartFrameIterator iterator;
1066 StackFrame* caller_frame = iterator.NextFrame(); 1057 StackFrame* caller_frame = iterator.NextFrame();
1067 ASSERT(caller_frame->IsDartFrame()); 1058 ASSERT(caller_frame->IsDartFrame());
1068 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); 1059 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
1069 const Function& caller_function = 1060 const Function& caller_function =
1070 Function::Handle(zone, caller_frame->LookupDartFunction()); 1061 Function::Handle(zone, caller_frame->LookupDartFunction());
1071 1062
1072 SingleTargetCache& cache = SingleTargetCache::Handle(zone); 1063 SingleTargetCache& cache = SingleTargetCache::Handle(zone);
1073 cache ^= CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), 1064 cache ^=
1074 caller_code); 1065 CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code);
1075 Code& old_target_code = Code::Handle(zone, cache.target()); 1066 Code& old_target_code = Code::Handle(zone, cache.target());
1076 Function& old_target = Function::Handle(zone); 1067 Function& old_target = Function::Handle(zone);
1077 old_target ^= old_target_code.owner(); 1068 old_target ^= old_target_code.owner();
1078 1069
1079 // We lost the original ICData when we patched to the monomorphic case. 1070 // We lost the original ICData when we patched to the monomorphic case.
1080 const String& name = String::Handle(zone, old_target.name()); 1071 const String& name = String::Handle(zone, old_target.name());
1081 ASSERT(!old_target.HasOptionalParameters()); 1072 ASSERT(!old_target.HasOptionalParameters());
1082 const Array& descriptor = Array::Handle(zone, 1073 const Array& descriptor = Array::Handle(
1083 ArgumentsDescriptor::New(old_target.num_fixed_parameters())); 1074 zone, ArgumentsDescriptor::New(old_target.num_fixed_parameters()));
1084 const ICData& ic_data = 1075 const ICData& ic_data =
1085 ICData::Handle(zone, ICData::New(caller_function, 1076 ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
1086 name, 1077 Thread::kNoDeoptId, 1, /* args_tested */
1087 descriptor,
1088 Thread::kNoDeoptId,
1089 1, /* args_tested */
1090 false /* static_call */)); 1078 false /* static_call */));
1091 1079
1092 // Maybe add the new target. 1080 // Maybe add the new target.
1093 Class& cls = Class::Handle(zone, receiver.clazz()); 1081 Class& cls = Class::Handle(zone, receiver.clazz());
1094 ArgumentsDescriptor args_desc(descriptor); 1082 ArgumentsDescriptor args_desc(descriptor);
1095 Function& target_function = Function::Handle(zone, 1083 Function& target_function = Function::Handle(
1096 Resolver::ResolveDynamicForReceiverClass(cls, 1084 zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
1097 name,
1098 args_desc));
1099 if (target_function.IsNull()) { 1085 if (target_function.IsNull()) {
1100 target_function = InlineCacheMissHelper(receiver, descriptor, name); 1086 target_function = InlineCacheMissHelper(receiver, descriptor, name);
1101 } 1087 }
1102 if (target_function.IsNull()) { 1088 if (target_function.IsNull()) {
1103 ASSERT(!FLAG_lazy_dispatchers); 1089 ASSERT(!FLAG_lazy_dispatchers);
1104 } else { 1090 } else {
1105 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); 1091 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
1106 } 1092 }
1107 1093
1108 if (old_target.raw() == target_function.raw()) { 1094 if (old_target.raw() == target_function.raw()) {
(...skipping 18 matching lines...) Expand all
1127 // IC call stub. 1113 // IC call stub.
1128 arguments.SetReturn(ic_data); 1114 arguments.SetReturn(ic_data);
1129 return; 1115 return;
1130 } 1116 }
1131 } 1117 }
1132 1118
1133 // Call site is not single target, switch to call using ICData. 1119 // Call site is not single target, switch to call using ICData.
1134 const Code& stub = 1120 const Code& stub =
1135 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code()); 1121 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code());
1136 ASSERT(!Isolate::Current()->compilation_allowed()); 1122 ASSERT(!Isolate::Current()->compilation_allowed());
1137 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), 1123 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data,
1138 caller_code,
1139 ic_data,
1140 stub); 1124 stub);
1141 1125
1142 // Return the ICData. The single target stub will jump to continue in the 1126 // Return the ICData. The single target stub will jump to continue in the
1143 // IC call stub. 1127 // IC call stub.
1144 arguments.SetReturn(ic_data); 1128 arguments.SetReturn(ic_data);
1145 #endif 1129 #endif
1146 } 1130 }
1147 1131
1148 1132
1149 DEFINE_RUNTIME_ENTRY(UnlinkedCall, 2) { 1133 DEFINE_RUNTIME_ENTRY(UnlinkedCall, 2) {
1150 #if defined(TARGET_ARCH_DBC) 1134 #if defined(TARGET_ARCH_DBC)
1151 // DBC does not use switchable calls. 1135 // DBC does not use switchable calls.
1152 UNREACHABLE(); 1136 UNREACHABLE();
1153 #else 1137 #else
1154 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); 1138 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
1155 const UnlinkedCall& unlinked = 1139 const UnlinkedCall& unlinked =
1156 UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(1)); 1140 UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(1));
1157 1141
1158 DartFrameIterator iterator; 1142 DartFrameIterator iterator;
1159 StackFrame* caller_frame = iterator.NextFrame(); 1143 StackFrame* caller_frame = iterator.NextFrame();
1160 ASSERT(caller_frame->IsDartFrame()); 1144 ASSERT(caller_frame->IsDartFrame());
1161 const Code& caller_code = 1145 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
1162 Code::Handle(zone, caller_frame->LookupDartCode());
1163 const Function& caller_function = 1146 const Function& caller_function =
1164 Function::Handle(zone, caller_frame->LookupDartFunction()); 1147 Function::Handle(zone, caller_frame->LookupDartFunction());
1165 1148
1166 const String& name = String::Handle(zone, unlinked.target_name()); 1149 const String& name = String::Handle(zone, unlinked.target_name());
1167 const Array& descriptor = Array::Handle(zone, unlinked.args_descriptor()); 1150 const Array& descriptor = Array::Handle(zone, unlinked.args_descriptor());
1168 const ICData& ic_data = 1151 const ICData& ic_data =
1169 ICData::Handle(zone, ICData::New(caller_function, 1152 ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
1170 name, 1153 Thread::kNoDeoptId, 1, /* args_tested */
1171 descriptor,
1172 Thread::kNoDeoptId,
1173 1, /* args_tested */
1174 false /* static_call */)); 1154 false /* static_call */));
1175 1155
1176 Class& cls = Class::Handle(zone, receiver.clazz()); 1156 Class& cls = Class::Handle(zone, receiver.clazz());
1177 ArgumentsDescriptor args_desc(descriptor); 1157 ArgumentsDescriptor args_desc(descriptor);
1178 Function& target_function = Function::Handle(zone, 1158 Function& target_function = Function::Handle(
1179 Resolver::ResolveDynamicForReceiverClass(cls, 1159 zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
1180 name,
1181 args_desc));
1182 if (target_function.IsNull()) { 1160 if (target_function.IsNull()) {
1183 target_function = InlineCacheMissHelper(receiver, descriptor, name); 1161 target_function = InlineCacheMissHelper(receiver, descriptor, name);
1184 } 1162 }
1185 if (target_function.IsNull()) { 1163 if (target_function.IsNull()) {
1186 ASSERT(!FLAG_lazy_dispatchers); 1164 ASSERT(!FLAG_lazy_dispatchers);
1187 } else { 1165 } else {
1188 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); 1166 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
1189 } 1167 }
1190 1168
1191 if (!target_function.IsNull() && 1169 if (!target_function.IsNull() && !target_function.HasOptionalParameters()) {
1192 !target_function.HasOptionalParameters()) {
1193 // Patch to monomorphic call. 1170 // Patch to monomorphic call.
1194 ASSERT(target_function.HasCode()); 1171 ASSERT(target_function.HasCode());
1195 const Code& target_code = 1172 const Code& target_code = Code::Handle(zone, target_function.CurrentCode());
1196 Code::Handle(zone, target_function.CurrentCode());
1197 const Smi& expected_cid = 1173 const Smi& expected_cid =
1198 Smi::Handle(zone, Smi::New(receiver.GetClassId())); 1174 Smi::Handle(zone, Smi::New(receiver.GetClassId()));
1199 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, 1175 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code,
1200 expected_cid, target_code); 1176 expected_cid, target_code);
1201 1177
1202 // Return the ICData. The miss stub will jump to continue in the IC call 1178 // Return the ICData. The miss stub will jump to continue in the IC call
1203 // stub. 1179 // stub.
1204 arguments.SetReturn(ic_data); 1180 arguments.SetReturn(ic_data);
1205 return; 1181 return;
1206 } 1182 }
1207 1183
1208 // Patch to call through stub. 1184 // Patch to call through stub.
1209 const Code& stub = 1185 const Code& stub =
1210 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code()); 1186 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code());
1211 ASSERT(!Isolate::Current()->compilation_allowed()); 1187 ASSERT(!Isolate::Current()->compilation_allowed());
1212 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), 1188 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data,
1213 caller_code,
1214 ic_data,
1215 stub); 1189 stub);
1216 1190
1217 // Return the ICData. The miss stub will jump to continue in the IC lookup 1191 // Return the ICData. The miss stub will jump to continue in the IC lookup
1218 // stub. 1192 // stub.
1219 arguments.SetReturn(ic_data); 1193 arguments.SetReturn(ic_data);
1220 #endif // !DBC 1194 #endif // !DBC
1221 } 1195 }
1222 1196
1223 1197
1224 // Handle a miss of a megamorphic cache. 1198 // Handle a miss of a megamorphic cache.
1225 // Arg0: Receiver. 1199 // Arg0: Receiver.
1226 // Returns: the ICData used to continue with a polymorphic call. 1200 // Returns: the ICData used to continue with a polymorphic call.
1227 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) { 1201 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 1) {
1228 #if defined(TARGET_ARCH_DBC) 1202 #if defined(TARGET_ARCH_DBC)
1229 // DBC does not use switchable calls. 1203 // DBC does not use switchable calls.
1230 UNREACHABLE(); 1204 UNREACHABLE();
1231 #else 1205 #else
1232 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0)); 1206 const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
1233 1207
1234 DartFrameIterator iterator; 1208 DartFrameIterator iterator;
1235 StackFrame* caller_frame = iterator.NextFrame(); 1209 StackFrame* caller_frame = iterator.NextFrame();
1236 ASSERT(caller_frame->IsDartFrame()); 1210 ASSERT(caller_frame->IsDartFrame());
1237 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); 1211 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
1238 const Function& caller_function = 1212 const Function& caller_function =
1239 Function::Handle(zone, caller_frame->LookupDartFunction()); 1213 Function::Handle(zone, caller_frame->LookupDartFunction());
1240 1214
1241 Smi& old_expected_cid = Smi::Handle(zone); 1215 Smi& old_expected_cid = Smi::Handle(zone);
1242 old_expected_cid ^= CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), 1216 old_expected_cid ^=
1243 caller_code); 1217 CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code);
1244 const Code& old_target_code = 1218 const Code& old_target_code = Code::Handle(
1245 Code::Handle(CodePatcher::GetSwitchableCallTargetAt(caller_frame->pc(), 1219 CodePatcher::GetSwitchableCallTargetAt(caller_frame->pc(), caller_code));
1246 caller_code));
1247 Function& old_target = Function::Handle(zone); 1220 Function& old_target = Function::Handle(zone);
1248 old_target ^= old_target_code.owner(); 1221 old_target ^= old_target_code.owner();
1249 1222
1250 // We lost the original ICData when we patched to the monomorphic case. 1223 // We lost the original ICData when we patched to the monomorphic case.
1251 const String& name = String::Handle(zone, old_target.name()); 1224 const String& name = String::Handle(zone, old_target.name());
1252 ASSERT(!old_target.HasOptionalParameters()); 1225 ASSERT(!old_target.HasOptionalParameters());
1253 const Array& descriptor = Array::Handle(zone, 1226 const Array& descriptor = Array::Handle(
1254 ArgumentsDescriptor::New(old_target.num_fixed_parameters())); 1227 zone, ArgumentsDescriptor::New(old_target.num_fixed_parameters()));
1255 const ICData& ic_data = 1228 const ICData& ic_data =
1256 ICData::Handle(zone, ICData::New(caller_function, 1229 ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
1257 name, 1230 Thread::kNoDeoptId, 1, /* args_tested */
1258 descriptor,
1259 Thread::kNoDeoptId,
1260 1, /* args_tested */
1261 false /* static_call */)); 1231 false /* static_call */));
1262 1232
1263 // Add the first target. 1233 // Add the first target.
1264 ic_data.AddReceiverCheck(old_expected_cid.Value(), old_target); 1234 ic_data.AddReceiverCheck(old_expected_cid.Value(), old_target);
1265 1235
1266 // Maybe add the new target. 1236 // Maybe add the new target.
1267 Class& cls = Class::Handle(zone, receiver.clazz()); 1237 Class& cls = Class::Handle(zone, receiver.clazz());
1268 ArgumentsDescriptor args_desc(descriptor); 1238 ArgumentsDescriptor args_desc(descriptor);
1269 Function& target_function = Function::Handle(zone, 1239 Function& target_function = Function::Handle(
1270 Resolver::ResolveDynamicForReceiverClass(cls, 1240 zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
1271 name,
1272 args_desc));
1273 if (target_function.IsNull()) { 1241 if (target_function.IsNull()) {
1274 target_function = InlineCacheMissHelper(receiver, descriptor, name); 1242 target_function = InlineCacheMissHelper(receiver, descriptor, name);
1275 } 1243 }
1276 if (target_function.IsNull()) { 1244 if (target_function.IsNull()) {
1277 ASSERT(!FLAG_lazy_dispatchers); 1245 ASSERT(!FLAG_lazy_dispatchers);
1278 } else { 1246 } else {
1279 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); 1247 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
1280 } 1248 }
1281 1249
1282 if (old_target.raw() == target_function.raw()) { 1250 if (old_target.raw() == target_function.raw()) {
1283 intptr_t lower, upper; 1251 intptr_t lower, upper;
1284 if (old_expected_cid.Value() < receiver.GetClassId()) { 1252 if (old_expected_cid.Value() < receiver.GetClassId()) {
1285 lower = old_expected_cid.Value(); 1253 lower = old_expected_cid.Value();
1286 upper = receiver.GetClassId(); 1254 upper = receiver.GetClassId();
1287 } else { 1255 } else {
1288 lower = receiver.GetClassId(); 1256 lower = receiver.GetClassId();
1289 upper = old_expected_cid.Value(); 1257 upper = old_expected_cid.Value();
1290 } 1258 }
1291 1259
1292 if (IsSingleTarget(isolate, zone, lower, upper, target_function, name)) { 1260 if (IsSingleTarget(isolate, zone, lower, upper, target_function, name)) {
1293 const SingleTargetCache& cache = 1261 const SingleTargetCache& cache =
1294 SingleTargetCache::Handle(SingleTargetCache::New()); 1262 SingleTargetCache::Handle(SingleTargetCache::New());
1295 const Code& code = Code::Handle(target_function.CurrentCode()); 1263 const Code& code = Code::Handle(target_function.CurrentCode());
1296 cache.set_target(code); 1264 cache.set_target(code);
1297 cache.set_entry_point(code.UncheckedEntryPoint()); 1265 cache.set_entry_point(code.UncheckedEntryPoint());
1298 cache.set_lower_limit(lower); 1266 cache.set_lower_limit(lower);
1299 cache.set_upper_limit(upper); 1267 cache.set_upper_limit(upper);
1300 const Code& stub = Code::Handle(zone, 1268 const Code& stub =
1301 StubCode::SingleTargetCall_entry()->code()); 1269 Code::Handle(zone, StubCode::SingleTargetCall_entry()->code());
1302 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), 1270 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, cache,
1303 caller_code,
1304 cache,
1305 stub); 1271 stub);
1306 // Return the ICData. The miss stub will jump to continue in the IC call 1272 // Return the ICData. The miss stub will jump to continue in the IC call
1307 // stub. 1273 // stub.
1308 arguments.SetReturn(ic_data); 1274 arguments.SetReturn(ic_data);
1309 return; 1275 return;
1310 } 1276 }
1311 } 1277 }
1312 1278
1313 // Patch to call through stub. 1279 // Patch to call through stub.
1314 const Code& stub = 1280 const Code& stub =
1315 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code()); 1281 Code::Handle(zone, StubCode::ICCallThroughCode_entry()->code());
1316 ASSERT(!Isolate::Current()->compilation_allowed()); 1282 ASSERT(!Isolate::Current()->compilation_allowed());
1317 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), 1283 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, ic_data,
1318 caller_code,
1319 ic_data,
1320 stub); 1284 stub);
1321 1285
1322 // Return the ICData. The miss stub will jump to continue in the IC lookup 1286 // Return the ICData. The miss stub will jump to continue in the IC lookup
1323 // stub. 1287 // stub.
1324 arguments.SetReturn(ic_data); 1288 arguments.SetReturn(ic_data);
1325 #endif // !defined(TARGET_ARCH_DBC) 1289 #endif // !defined(TARGET_ARCH_DBC)
1326 } 1290 }
1327 1291
1328 1292
1329 // Handle a miss of a megamorphic cache. 1293 // Handle a miss of a megamorphic cache.
(...skipping 17 matching lines...) Expand all
1347 name = MegamorphicCache::Cast(ic_data_or_cache).target_name(); 1311 name = MegamorphicCache::Cast(ic_data_or_cache).target_name();
1348 } 1312 }
1349 Class& cls = Class::Handle(zone, receiver.clazz()); 1313 Class& cls = Class::Handle(zone, receiver.clazz());
1350 ASSERT(!cls.IsNull()); 1314 ASSERT(!cls.IsNull());
1351 if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) { 1315 if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) {
1352 OS::PrintErr("Megamorphic IC miss, class=%s, function=%s\n", 1316 OS::PrintErr("Megamorphic IC miss, class=%s, function=%s\n",
1353 cls.ToCString(), name.ToCString()); 1317 cls.ToCString(), name.ToCString());
1354 } 1318 }
1355 1319
1356 ArgumentsDescriptor args_desc(descriptor); 1320 ArgumentsDescriptor args_desc(descriptor);
1357 Function& target_function = Function::Handle(zone, 1321 Function& target_function = Function::Handle(
1358 Resolver::ResolveDynamicForReceiverClass(cls, 1322 zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
1359 name,
1360 args_desc));
1361 if (target_function.IsNull()) { 1323 if (target_function.IsNull()) {
1362 target_function = InlineCacheMissHelper(receiver, descriptor, name); 1324 target_function = InlineCacheMissHelper(receiver, descriptor, name);
1363 } 1325 }
1364 if (target_function.IsNull()) { 1326 if (target_function.IsNull()) {
1365 ASSERT(!FLAG_lazy_dispatchers); 1327 ASSERT(!FLAG_lazy_dispatchers);
1366 arguments.SetReturn(target_function); 1328 arguments.SetReturn(target_function);
1367 return; 1329 return;
1368 } 1330 }
1369 1331
1370 if (ic_data_or_cache.IsICData()) { 1332 if (ic_data_or_cache.IsICData()) {
1371 const ICData& ic_data = ICData::Cast(ic_data_or_cache); 1333 const ICData& ic_data = ICData::Cast(ic_data_or_cache);
1372 1334
1373 if ((ic_data.NumberOfChecks() == 0) && 1335 if ((ic_data.NumberOfChecks() == 0) &&
1374 !target_function.HasOptionalParameters() && 1336 !target_function.HasOptionalParameters() &&
1375 !Isolate::Current()->compilation_allowed()) { 1337 !Isolate::Current()->compilation_allowed()) {
1376 // This call site is unlinked: transition to a monomorphic direct call. 1338 // This call site is unlinked: transition to a monomorphic direct call.
1377 // Note we cannot do this if the target has optional parameters because 1339 // Note we cannot do this if the target has optional parameters because
1378 // the monomorphic direct call does not load the arguments descriptor. 1340 // the monomorphic direct call does not load the arguments descriptor.
1379 // We cannot do this if we are still in the middle of precompiling because 1341 // We cannot do this if we are still in the middle of precompiling because
1380 // the monomorphic case hides an live instance selector from the 1342 // the monomorphic case hides an live instance selector from the
1381 // treeshaker. 1343 // treeshaker.
1382 1344
1383 if (!target_function.HasCode()) { 1345 if (!target_function.HasCode()) {
1384 const Error& error = 1346 const Error& error =
1385 Error::Handle(Compiler::CompileFunction(thread, target_function)); 1347 Error::Handle(Compiler::CompileFunction(thread, target_function));
1386 if (!error.IsNull()) { 1348 if (!error.IsNull()) {
1387 Exceptions::PropagateError(error); 1349 Exceptions::PropagateError(error);
1388 } 1350 }
1389 } 1351 }
1390 1352
1391 DartFrameIterator iterator; 1353 DartFrameIterator iterator;
1392 StackFrame* miss_function_frame = iterator.NextFrame(); 1354 StackFrame* miss_function_frame = iterator.NextFrame();
1393 ASSERT(miss_function_frame->IsDartFrame()); 1355 ASSERT(miss_function_frame->IsDartFrame());
1394 StackFrame* caller_frame = iterator.NextFrame(); 1356 StackFrame* caller_frame = iterator.NextFrame();
1395 ASSERT(caller_frame->IsDartFrame()); 1357 ASSERT(caller_frame->IsDartFrame());
1396 const Code& caller_code = 1358 const Code& caller_code =
1397 Code::Handle(zone, caller_frame->LookupDartCode()); 1359 Code::Handle(zone, caller_frame->LookupDartCode());
1398 const Code& target_code = 1360 const Code& target_code =
1399 Code::Handle(zone, target_function.CurrentCode()); 1361 Code::Handle(zone, target_function.CurrentCode());
1400 const Smi& expected_cid = 1362 const Smi& expected_cid =
1401 Smi::Handle(zone, Smi::New(receiver.GetClassId())); 1363 Smi::Handle(zone, Smi::New(receiver.GetClassId()));
1402 1364
1403 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code, 1365 CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), caller_code,
1404 expected_cid, target_code); 1366 expected_cid, target_code);
1405 } else { 1367 } else {
1406 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); 1368 ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
1407 if (ic_data.NumberOfChecks() > FLAG_max_polymorphic_checks) { 1369 if (ic_data.NumberOfChecks() > FLAG_max_polymorphic_checks) {
1408 // Switch to megamorphic call. 1370 // Switch to megamorphic call.
1409 const MegamorphicCache& cache = MegamorphicCache::Handle(zone, 1371 const MegamorphicCache& cache = MegamorphicCache::Handle(
1410 MegamorphicCacheTable::Lookup(isolate, name, descriptor)); 1372 zone, MegamorphicCacheTable::Lookup(isolate, name, descriptor));
1411 DartFrameIterator iterator; 1373 DartFrameIterator iterator;
1412 StackFrame* miss_function_frame = iterator.NextFrame(); 1374 StackFrame* miss_function_frame = iterator.NextFrame();
1413 ASSERT(miss_function_frame->IsDartFrame()); 1375 ASSERT(miss_function_frame->IsDartFrame());
1414 StackFrame* caller_frame = iterator.NextFrame(); 1376 StackFrame* caller_frame = iterator.NextFrame();
1415 ASSERT(caller_frame->IsDartFrame()); 1377 ASSERT(caller_frame->IsDartFrame());
1416 const Code& caller_code = 1378 const Code& caller_code =
1417 Code::Handle(zone, caller_frame->LookupDartCode()); 1379 Code::Handle(zone, caller_frame->LookupDartCode());
1418 const Code& stub = 1380 const Code& stub =
1419 Code::Handle(zone, StubCode::MegamorphicCall_entry()->code()); 1381 Code::Handle(zone, StubCode::MegamorphicCall_entry()->code());
1420 1382
(...skipping 29 matching lines...) Expand all
1450 if (ic_data_or_cache.IsICData()) { 1412 if (ic_data_or_cache.IsICData()) {
1451 target_name = ICData::Cast(ic_data_or_cache).target_name(); 1413 target_name = ICData::Cast(ic_data_or_cache).target_name();
1452 } else { 1414 } else {
1453 ASSERT(ic_data_or_cache.IsMegamorphicCache()); 1415 ASSERT(ic_data_or_cache.IsMegamorphicCache());
1454 target_name = MegamorphicCache::Cast(ic_data_or_cache).target_name(); 1416 target_name = MegamorphicCache::Cast(ic_data_or_cache).target_name();
1455 } 1417 }
1456 1418
1457 Class& cls = Class::Handle(zone, receiver.clazz()); 1419 Class& cls = Class::Handle(zone, receiver.clazz());
1458 Function& function = Function::Handle(zone); 1420 Function& function = Function::Handle(zone);
1459 1421
1460 // Dart distinguishes getters and regular methods and allows their calls 1422 // Dart distinguishes getters and regular methods and allows their calls
1461 // to mix with conversions, and its selectors are independent of arity. So do 1423 // to mix with conversions, and its selectors are independent of arity. So do
1462 // a zigzagged lookup to see if this call failed because of an arity mismatch, 1424 // a zigzagged lookup to see if this call failed because of an arity mismatch,
1463 // need for conversion, or there really is no such method. 1425 // need for conversion, or there really is no such method.
1464 1426
1465 #define NO_SUCH_METHOD() \ 1427 #define NO_SUCH_METHOD() \
1466 const Object& result = Object::Handle(zone, \ 1428 const Object& result = Object::Handle( \
1467 DartEntry::InvokeNoSuchMethod(receiver, \ 1429 zone, DartEntry::InvokeNoSuchMethod( \
1468 target_name, \ 1430 receiver, target_name, orig_arguments, orig_arguments_desc)); \
1469 orig_arguments, \
1470 orig_arguments_desc)); \
1471 CheckResultError(result); \ 1431 CheckResultError(result); \
1472 arguments.SetReturn(result); \ 1432 arguments.SetReturn(result);
1473 1433
1474 #define CLOSURIZE(some_function) \ 1434 #define CLOSURIZE(some_function) \
1475 const Function& closure_function = \ 1435 const Function& closure_function = \
1476 Function::Handle(zone, some_function.ImplicitClosureFunction()); \ 1436 Function::Handle(zone, some_function.ImplicitClosureFunction()); \
1477 const Object& result = \ 1437 const Object& result = Object::Handle( \
1478 Object::Handle(zone, closure_function.ImplicitInstanceClosure(receiver));\ 1438 zone, closure_function.ImplicitInstanceClosure(receiver)); \
1479 arguments.SetReturn(result); \ 1439 arguments.SetReturn(result);
1480 1440
1481 const bool is_getter = Field::IsGetterName(target_name); 1441 const bool is_getter = Field::IsGetterName(target_name);
1482 if (is_getter) { 1442 if (is_getter) {
1483 // o.foo (o.get:foo) failed, closurize o.foo() if it exists. Or, 1443 // o.foo (o.get:foo) failed, closurize o.foo() if it exists. Or,
1484 // o#foo (o.get:#foo) failed, closurizee o.foo or o.foo(), whichever is 1444 // o#foo (o.get:#foo) failed, closurizee o.foo or o.foo(), whichever is
1485 // encountered first on the inheritance chain. Or, 1445 // encountered first on the inheritance chain. Or,
1486 // o#foo= (o.get:#set:foo) failed, closurize o.foo= if it exists. 1446 // o#foo= (o.get:#set:foo) failed, closurize o.foo= if it exists.
1487 String& field_name = 1447 String& field_name =
1488 String::Handle(zone, Field::NameFromGetter(target_name)); 1448 String::Handle(zone, Field::NameFromGetter(target_name));
1489 1449
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1529 1489
1530 // Fall through for noSuchMethod 1490 // Fall through for noSuchMethod
1531 } else { 1491 } else {
1532 // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong 1492 // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong
1533 // number of arguments, or try (o.foo).call(...) 1493 // number of arguments, or try (o.foo).call(...)
1534 1494
1535 if ((target_name.raw() == Symbols::Call().raw()) && receiver.IsClosure()) { 1495 if ((target_name.raw() == Symbols::Call().raw()) && receiver.IsClosure()) {
1536 // Special case: closures are implemented with a call getter instead of a 1496 // Special case: closures are implemented with a call getter instead of a
1537 // call method and with lazy dispatchers the field-invocation-dispatcher 1497 // call method and with lazy dispatchers the field-invocation-dispatcher
1538 // would perform the closure call. 1498 // would perform the closure call.
1539 const Object& result = 1499 const Object& result = Object::Handle(
1540 Object::Handle(zone, DartEntry::InvokeClosure(orig_arguments, 1500 zone, DartEntry::InvokeClosure(orig_arguments, orig_arguments_desc));
1541 orig_arguments_desc));
1542 CheckResultError(result); 1501 CheckResultError(result);
1543 arguments.SetReturn(result); 1502 arguments.SetReturn(result);
1544 return; 1503 return;
1545 } 1504 }
1546 1505
1547 const String& getter_name = 1506 const String& getter_name =
1548 String::Handle(zone, Field::GetterName(target_name)); 1507 String::Handle(zone, Field::GetterName(target_name));
1549 while (!cls.IsNull()) { 1508 while (!cls.IsNull()) {
1550 function ^= cls.LookupDynamicFunction(target_name); 1509 function ^= cls.LookupDynamicFunction(target_name);
1551 if (!function.IsNull()) { 1510 if (!function.IsNull()) {
1552 ArgumentsDescriptor args_desc(orig_arguments_desc); 1511 ArgumentsDescriptor args_desc(orig_arguments_desc);
1553 ASSERT(!function.AreValidArguments(args_desc, NULL)); 1512 ASSERT(!function.AreValidArguments(args_desc, NULL));
1554 break; // mismatch, invoke noSuchMethod 1513 break; // mismatch, invoke noSuchMethod
1555 } 1514 }
1556 function ^= cls.LookupDynamicFunction(getter_name); 1515 function ^= cls.LookupDynamicFunction(getter_name);
1557 if (!function.IsNull()) { 1516 if (!function.IsNull()) {
1558 const Array& getter_arguments = Array::Handle(Array::New(1)); 1517 const Array& getter_arguments = Array::Handle(Array::New(1));
1559 getter_arguments.SetAt(0, receiver); 1518 getter_arguments.SetAt(0, receiver);
1560 const Object& getter_result = 1519 const Object& getter_result = Object::Handle(
1561 Object::Handle(zone, DartEntry::InvokeFunction(function, 1520 zone, DartEntry::InvokeFunction(function, getter_arguments));
1562 getter_arguments));
1563 CheckResultError(getter_result); 1521 CheckResultError(getter_result);
1564 ASSERT(getter_result.IsNull() || getter_result.IsInstance()); 1522 ASSERT(getter_result.IsNull() || getter_result.IsInstance());
1565 1523
1566 orig_arguments.SetAt(0, getter_result); 1524 orig_arguments.SetAt(0, getter_result);
1567 const Object& call_result = 1525 const Object& call_result = Object::Handle(
1568 Object::Handle(zone, DartEntry::InvokeClosure(orig_arguments, 1526 zone,
1569 orig_arguments_desc)); 1527 DartEntry::InvokeClosure(orig_arguments, orig_arguments_desc));
1570 CheckResultError(call_result); 1528 CheckResultError(call_result);
1571 arguments.SetReturn(call_result); 1529 arguments.SetReturn(call_result);
1572 return; 1530 return;
1573 } 1531 }
1574 cls = cls.SuperClass(); 1532 cls = cls.SuperClass();
1575 } 1533 }
1576 } 1534 }
1577 1535
1578 NO_SUCH_METHOD(); 1536 NO_SUCH_METHOD();
1579 1537
1580 #undef NO_SUCH_METHOD 1538 #undef NO_SUCH_METHOD
1581 #undef CLOSURIZE 1539 #undef CLOSURIZE
1582 } 1540 }
1583 1541
1584 1542
1585
1586 // Invoke appropriate noSuchMethod function. 1543 // Invoke appropriate noSuchMethod function.
1587 // Arg0: receiver (closure object) 1544 // Arg0: receiver (closure object)
1588 // Arg1: arguments descriptor array. 1545 // Arg1: arguments descriptor array.
1589 // Arg2: arguments array. 1546 // Arg2: arguments array.
1590 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) { 1547 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) {
1591 const Closure& receiver = Closure::CheckedHandle(arguments.ArgAt(0)); 1548 const Closure& receiver = Closure::CheckedHandle(arguments.ArgAt(0));
1592 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(1)); 1549 const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(1));
1593 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(2)); 1550 const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(2));
1594 1551
1595 // For closure the function name is always 'call'. Replace it with the 1552 // For closure the function name is always 'call'. Replace it with the
1596 // name of the closurized function so that exception contains more 1553 // name of the closurized function so that exception contains more
1597 // relevant information. 1554 // relevant information.
1598 const Function& function = Function::Handle(receiver.function()); 1555 const Function& function = Function::Handle(receiver.function());
1599 const String& original_function_name = 1556 const String& original_function_name =
1600 String::Handle(function.QualifiedUserVisibleName()); 1557 String::Handle(function.QualifiedUserVisibleName());
1601 const Object& result = Object::Handle( 1558 const Object& result = Object::Handle(DartEntry::InvokeNoSuchMethod(
1602 DartEntry::InvokeNoSuchMethod(receiver, 1559 receiver, original_function_name, orig_arguments, orig_arguments_desc));
1603 original_function_name,
1604 orig_arguments,
1605 orig_arguments_desc));
1606 CheckResultError(result); 1560 CheckResultError(result);
1607 arguments.SetReturn(result); 1561 arguments.SetReturn(result);
1608 } 1562 }
1609 1563
1610 1564
1611 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { 1565 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) {
1612 #if defined(USING_SIMULATOR) 1566 #if defined(USING_SIMULATOR)
1613 uword stack_pos = Simulator::Current()->get_sp(); 1567 uword stack_pos = Simulator::Current()->get_sp();
1614 #else 1568 #else
1615 uword stack_pos = Thread::GetCurrentStackPointer(); 1569 uword stack_pos = Thread::GetCurrentStackPointer();
(...skipping 15 matching lines...) Expand all
1631 UNREACHABLE(); 1585 UNREACHABLE();
1632 } 1586 }
1633 1587
1634 // The following code is used to stress test deoptimization and 1588 // The following code is used to stress test deoptimization and
1635 // debugger stack tracing. 1589 // debugger stack tracing.
1636 bool do_deopt = false; 1590 bool do_deopt = false;
1637 bool do_stacktrace = false; 1591 bool do_stacktrace = false;
1638 bool do_reload = false; 1592 bool do_reload = false;
1639 const intptr_t isolate_reload_every = 1593 const intptr_t isolate_reload_every =
1640 isolate->reload_every_n_stack_overflow_checks(); 1594 isolate->reload_every_n_stack_overflow_checks();
1641 if ((FLAG_deoptimize_every > 0) || 1595 if ((FLAG_deoptimize_every > 0) || (FLAG_stacktrace_every > 0) ||
1642 (FLAG_stacktrace_every > 0) ||
1643 (isolate_reload_every > 0)) { 1596 (isolate_reload_every > 0)) {
1644 // TODO(turnidge): To make --deoptimize_every and 1597 // TODO(turnidge): To make --deoptimize_every and
1645 // --stacktrace-every faster we could move this increment/test to 1598 // --stacktrace-every faster we could move this increment/test to
1646 // the generated code. 1599 // the generated code.
1647 int32_t count = thread->IncrementAndGetStackOverflowCount(); 1600 int32_t count = thread->IncrementAndGetStackOverflowCount();
1648 if (FLAG_deoptimize_every > 0 && 1601 if (FLAG_deoptimize_every > 0 && (count % FLAG_deoptimize_every) == 0) {
1649 (count % FLAG_deoptimize_every) == 0) {
1650 do_deopt = true; 1602 do_deopt = true;
1651 } 1603 }
1652 if (FLAG_stacktrace_every > 0 && 1604 if (FLAG_stacktrace_every > 0 && (count % FLAG_stacktrace_every) == 0) {
1653 (count % FLAG_stacktrace_every) == 0) {
1654 do_stacktrace = true; 1605 do_stacktrace = true;
1655 } 1606 }
1656 if ((isolate_reload_every > 0) && 1607 if ((isolate_reload_every > 0) && (count % isolate_reload_every) == 0) {
1657 (count % isolate_reload_every) == 0) {
1658 do_reload = isolate->CanReload(); 1608 do_reload = isolate->CanReload();
1659 } 1609 }
1660 } 1610 }
1661 if ((FLAG_deoptimize_filter != NULL) || 1611 if ((FLAG_deoptimize_filter != NULL) || (FLAG_stacktrace_filter != NULL) ||
1662 (FLAG_stacktrace_filter != NULL) || 1612 FLAG_reload_every_optimized) {
1663 FLAG_reload_every_optimized) {
1664 DartFrameIterator iterator; 1613 DartFrameIterator iterator;
1665 StackFrame* frame = iterator.NextFrame(); 1614 StackFrame* frame = iterator.NextFrame();
1666 ASSERT(frame != NULL); 1615 ASSERT(frame != NULL);
1667 const Code& code = Code::Handle(frame->LookupDartCode()); 1616 const Code& code = Code::Handle(frame->LookupDartCode());
1668 ASSERT(!code.IsNull()); 1617 ASSERT(!code.IsNull());
1669 const Function& function = Function::Handle(code.function()); 1618 const Function& function = Function::Handle(code.function());
1670 ASSERT(!function.IsNull()); 1619 ASSERT(!function.IsNull());
1671 const char* function_name = function.ToFullyQualifiedCString(); 1620 const char* function_name = function.ToFullyQualifiedCString();
1672 ASSERT(function_name != NULL); 1621 ASSERT(function_name != NULL);
1673 if (!code.is_optimized() && FLAG_reload_every_optimized) { 1622 if (!code.is_optimized() && FLAG_reload_every_optimized) {
1674 // Don't do the reload if we aren't inside optimized code. 1623 // Don't do the reload if we aren't inside optimized code.
1675 do_reload = false; 1624 do_reload = false;
1676 } 1625 }
1677 if (code.is_optimized() && 1626 if (code.is_optimized() && FLAG_deoptimize_filter != NULL &&
1678 FLAG_deoptimize_filter != NULL &&
1679 strstr(function_name, FLAG_deoptimize_filter) != NULL) { 1627 strstr(function_name, FLAG_deoptimize_filter) != NULL) {
1680 OS::PrintErr("*** Forcing deoptimization (%s)\n", 1628 OS::PrintErr("*** Forcing deoptimization (%s)\n",
1681 function.ToFullyQualifiedCString()); 1629 function.ToFullyQualifiedCString());
1682 do_deopt = true; 1630 do_deopt = true;
1683 } 1631 }
1684 if (FLAG_stacktrace_filter != NULL && 1632 if (FLAG_stacktrace_filter != NULL &&
1685 strstr(function_name, FLAG_stacktrace_filter) != NULL) { 1633 strstr(function_name, FLAG_stacktrace_filter) != NULL) {
1686 OS::PrintErr("*** Computing stacktrace (%s)\n", 1634 OS::PrintErr("*** Computing stacktrace (%s)\n",
1687 function.ToFullyQualifiedCString()); 1635 function.ToFullyQualifiedCString());
1688 do_stacktrace = true; 1636 do_stacktrace = true;
(...skipping 29 matching lines...) Expand all
1718 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); 1666 DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
1719 intptr_t num_frames = stack->Length(); 1667 intptr_t num_frames = stack->Length();
1720 for (intptr_t i = 0; i < num_frames; i++) { 1668 for (intptr_t i = 0; i < num_frames; i++) {
1721 ActivationFrame* frame = stack->FrameAt(i); 1669 ActivationFrame* frame = stack->FrameAt(i);
1722 #ifndef DART_PRECOMPILED_RUNTIME 1670 #ifndef DART_PRECOMPILED_RUNTIME
1723 // Ensure that we have unoptimized code. 1671 // Ensure that we have unoptimized code.
1724 frame->function().EnsureHasCompiledUnoptimizedCode(); 1672 frame->function().EnsureHasCompiledUnoptimizedCode();
1725 #endif 1673 #endif
1726 // Variable locations and number are unknown when precompiling. 1674 // Variable locations and number are unknown when precompiling.
1727 const int num_vars = 1675 const int num_vars =
1728 FLAG_precompiled_runtime ? 0 : frame->NumLocalVariables(); 1676 FLAG_precompiled_runtime ? 0 : frame->NumLocalVariables();
1729 TokenPosition unused = TokenPosition::kNoSource; 1677 TokenPosition unused = TokenPosition::kNoSource;
1730 for (intptr_t v = 0; v < num_vars; v++) { 1678 for (intptr_t v = 0; v < num_vars; v++) {
1731 frame->VariableAt(v, &var_name, &unused, &unused, &unused, &var_value); 1679 frame->VariableAt(v, &var_name, &unused, &unused, &unused, &var_value);
1732 } 1680 }
1733 } 1681 }
1734 FLAG_stacktrace_every = saved_stacktrace_every; 1682 FLAG_stacktrace_every = saved_stacktrace_every;
1735 } 1683 }
1736 1684
1737 const Error& error = Error::Handle(thread->HandleInterrupts()); 1685 const Error& error = Error::Handle(thread->HandleInterrupts());
1738 if (!error.IsNull()) { 1686 if (!error.IsNull()) {
(...skipping 29 matching lines...) Expand all
1768 } 1716 }
1769 1717
1770 // The unoptimized code is on the stack and should never be detached from 1718 // The unoptimized code is on the stack and should never be detached from
1771 // the function at this point. 1719 // the function at this point.
1772 ASSERT(function.unoptimized_code() != Object::null()); 1720 ASSERT(function.unoptimized_code() != Object::null());
1773 intptr_t osr_id = 1721 intptr_t osr_id =
1774 Code::Handle(function.unoptimized_code()).GetDeoptIdForOsr(frame->pc()); 1722 Code::Handle(function.unoptimized_code()).GetDeoptIdForOsr(frame->pc());
1775 ASSERT(osr_id != Compiler::kNoOSRDeoptId); 1723 ASSERT(osr_id != Compiler::kNoOSRDeoptId);
1776 if (FLAG_trace_osr) { 1724 if (FLAG_trace_osr) {
1777 OS::Print("Attempting OSR for %s at id=%" Pd ", count=%" Pd "\n", 1725 OS::Print("Attempting OSR for %s at id=%" Pd ", count=%" Pd "\n",
1778 function.ToFullyQualifiedCString(), 1726 function.ToFullyQualifiedCString(), osr_id,
1779 osr_id,
1780 function.usage_counter()); 1727 function.usage_counter());
1781 } 1728 }
1782 1729
1783 const Code& original_code = Code::Handle(function.CurrentCode()); 1730 const Code& original_code = Code::Handle(function.CurrentCode());
1784 // Since the code is referenced from the frame and the ZoneHandle, 1731 // Since the code is referenced from the frame and the ZoneHandle,
1785 // it cannot have been removed from the function. 1732 // it cannot have been removed from the function.
1786 ASSERT(!original_code.IsNull()); 1733 ASSERT(!original_code.IsNull());
1787 const Error& error = Error::Handle(Compiler::CompileOptimizedFunction( 1734 const Error& error = Error::Handle(
1788 thread, function, osr_id)); 1735 Compiler::CompileOptimizedFunction(thread, function, osr_id));
1789 if (!error.IsNull()) { 1736 if (!error.IsNull()) {
1790 Exceptions::PropagateError(error); 1737 Exceptions::PropagateError(error);
1791 } 1738 }
1792 1739
1793 const Code& optimized_code = Code::Handle(function.CurrentCode()); 1740 const Code& optimized_code = Code::Handle(function.CurrentCode());
1794 // The current code will not be changed in the case that the compiler 1741 // The current code will not be changed in the case that the compiler
1795 // bailed out during OSR compilation. 1742 // bailed out during OSR compilation.
1796 if (optimized_code.raw() != original_code.raw()) { 1743 if (optimized_code.raw() != original_code.raw()) {
1797 // The OSR code does not work for calling the function, so restore the 1744 // The OSR code does not work for calling the function, so restore the
1798 // unoptimized code. Patch the stack frame to return into the OSR 1745 // unoptimized code. Patch the stack frame to return into the OSR
1799 // code. 1746 // code.
1800 uword optimized_entry = 1747 uword optimized_entry =
1801 Instructions::UncheckedEntryPoint(optimized_code.instructions()); 1748 Instructions::UncheckedEntryPoint(optimized_code.instructions());
1802 function.AttachCode(original_code); 1749 function.AttachCode(original_code);
1803 frame->set_pc(optimized_entry); 1750 frame->set_pc(optimized_entry);
1804 frame->set_pc_marker(optimized_code.raw()); 1751 frame->set_pc_marker(optimized_code.raw());
1805 } 1752 }
1806 } 1753 }
1807 } 1754 }
1808 1755
1809 1756
1810 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { 1757 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) {
1811 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); 1758 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0));
1812 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); 1759 const Function& function = Function::CheckedHandle(arguments.ArgAt(1));
1813 DartFrameIterator iterator; 1760 DartFrameIterator iterator;
1814 StackFrame* frame = iterator.NextFrame(); 1761 StackFrame* frame = iterator.NextFrame();
1815 ASSERT(frame != NULL); 1762 ASSERT(frame != NULL);
1816 OS::PrintErr("IC call @%#" Px ": ICData: %p cnt:%" Pd " nchecks: %" Pd 1763 OS::PrintErr("IC call @%#" Px ": ICData: %p cnt:%" Pd " nchecks: %" Pd
1817 " %s\n", 1764 " %s\n",
1818 frame->pc(), 1765 frame->pc(), ic_data.raw(), function.usage_counter(),
1819 ic_data.raw(), 1766 ic_data.NumberOfChecks(), function.ToFullyQualifiedCString());
1820 function.usage_counter(),
1821 ic_data.NumberOfChecks(),
1822 function.ToFullyQualifiedCString());
1823 } 1767 }
1824 1768
1825 1769
1826 // This is called from function that needs to be optimized. 1770 // This is called from function that needs to be optimized.
1827 // The requesting function can be already optimized (reoptimization). 1771 // The requesting function can be already optimized (reoptimization).
1828 // Returns the Code object where to continue execution. 1772 // Returns the Code object where to continue execution.
1829 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { 1773 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) {
1830 #if !defined(DART_PRECOMPILED_RUNTIME) 1774 #if !defined(DART_PRECOMPILED_RUNTIME)
1831 const Function& function = Function::CheckedHandle(zone, 1775 const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
1832 arguments.ArgAt(0));
1833 ASSERT(!function.IsNull()); 1776 ASSERT(!function.IsNull());
1834 ASSERT(function.HasCode()); 1777 ASSERT(function.HasCode());
1835 1778
1836 if (Compiler::CanOptimizeFunction(thread, function)) { 1779 if (Compiler::CanOptimizeFunction(thread, function)) {
1837 if (FLAG_background_compilation) { 1780 if (FLAG_background_compilation) {
1838 Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField()); 1781 Field& field = Field::Handle(zone, isolate->GetDeoptimizingBoxedField());
1839 while (!field.IsNull()) { 1782 while (!field.IsNull()) {
1840 if (FLAG_trace_optimization || FLAG_trace_field_guards) { 1783 if (FLAG_trace_optimization || FLAG_trace_field_guards) {
1841 THR_Print("Lazy disabling unboxing of %s\n", field.ToCString()); 1784 THR_Print("Lazy disabling unboxing of %s\n", field.ToCString());
1842 } 1785 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 // Since function's current code is always unpatched, the entry frame always 1850 // Since function's current code is always unpatched, the entry frame always
1908 // calls to unpatched code. 1851 // calls to unpatched code.
1909 UNREACHABLE(); 1852 UNREACHABLE();
1910 } 1853 }
1911 ASSERT(frame->IsDartFrame()); 1854 ASSERT(frame->IsDartFrame());
1912 const Code& caller_code = Code::Handle(zone, frame->LookupDartCode()); 1855 const Code& caller_code = Code::Handle(zone, frame->LookupDartCode());
1913 ASSERT(caller_code.is_optimized()); 1856 ASSERT(caller_code.is_optimized());
1914 const Function& target_function = Function::Handle( 1857 const Function& target_function = Function::Handle(
1915 zone, caller_code.GetStaticCallTargetFunctionAt(frame->pc())); 1858 zone, caller_code.GetStaticCallTargetFunctionAt(frame->pc()));
1916 if (!target_function.HasCode()) { 1859 if (!target_function.HasCode()) {
1917 const Error& error = Error::Handle( 1860 const Error& error =
1918 zone, Compiler::CompileFunction(thread, target_function)); 1861 Error::Handle(zone, Compiler::CompileFunction(thread, target_function));
1919 if (!error.IsNull()) { 1862 if (!error.IsNull()) {
1920 Exceptions::PropagateError(error); 1863 Exceptions::PropagateError(error);
1921 } 1864 }
1922 } 1865 }
1923 ASSERT(target_function.HasCode()); 1866 ASSERT(target_function.HasCode());
1924 1867
1925 const Code& current_target_code = Code::Handle( 1868 const Code& current_target_code =
1926 zone, target_function.CurrentCode()); 1869 Code::Handle(zone, target_function.CurrentCode());
1927 CodePatcher::PatchStaticCallAt(frame->pc(), 1870 CodePatcher::PatchStaticCallAt(frame->pc(), caller_code, current_target_code);
1928 caller_code,
1929 current_target_code);
1930 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code); 1871 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code);
1931 if (FLAG_trace_patching) { 1872 if (FLAG_trace_patching) {
1932 OS::PrintErr("FixCallersTarget: caller %#" Px " " 1873 OS::PrintErr("FixCallersTarget: caller %#" Px
1874 " "
1933 "target '%s' -> %#" Px "\n", 1875 "target '%s' -> %#" Px "\n",
1934 frame->pc(), 1876 frame->pc(), target_function.ToFullyQualifiedCString(),
1935 target_function.ToFullyQualifiedCString(),
1936 current_target_code.UncheckedEntryPoint()); 1877 current_target_code.UncheckedEntryPoint());
1937 } 1878 }
1938 ASSERT(!current_target_code.IsDisabled()); 1879 ASSERT(!current_target_code.IsDisabled());
1939 arguments.SetReturn(current_target_code); 1880 arguments.SetReturn(current_target_code);
1940 } 1881 }
1941 1882
1942 1883
1943 // The caller tried to allocate an instance via an invalidated allocation 1884 // The caller tried to allocate an instance via an invalidated allocation
1944 // stub. 1885 // stub.
1945 DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) { 1886 DEFINE_RUNTIME_ENTRY(FixAllocationStubTarget, 0) {
(...skipping 14 matching lines...) Expand all
1960 ASSERT(!caller_code.IsNull()); 1901 ASSERT(!caller_code.IsNull());
1961 const Code& stub = Code::Handle( 1902 const Code& stub = Code::Handle(
1962 CodePatcher::GetStaticCallTargetAt(frame->pc(), caller_code)); 1903 CodePatcher::GetStaticCallTargetAt(frame->pc(), caller_code));
1963 Class& alloc_class = Class::ZoneHandle(zone); 1904 Class& alloc_class = Class::ZoneHandle(zone);
1964 alloc_class ^= stub.owner(); 1905 alloc_class ^= stub.owner();
1965 Code& alloc_stub = Code::Handle(zone, alloc_class.allocation_stub()); 1906 Code& alloc_stub = Code::Handle(zone, alloc_class.allocation_stub());
1966 if (alloc_stub.IsNull()) { 1907 if (alloc_stub.IsNull()) {
1967 alloc_stub = StubCode::GetAllocationStubForClass(alloc_class); 1908 alloc_stub = StubCode::GetAllocationStubForClass(alloc_class);
1968 ASSERT(!alloc_stub.IsDisabled()); 1909 ASSERT(!alloc_stub.IsDisabled());
1969 } 1910 }
1970 CodePatcher::PatchStaticCallAt(frame->pc(), 1911 CodePatcher::PatchStaticCallAt(frame->pc(), caller_code, alloc_stub);
1971 caller_code,
1972 alloc_stub);
1973 caller_code.SetStubCallTargetCodeAt(frame->pc(), alloc_stub); 1912 caller_code.SetStubCallTargetCodeAt(frame->pc(), alloc_stub);
1974 if (FLAG_trace_patching) { 1913 if (FLAG_trace_patching) {
1975 OS::PrintErr("FixAllocationStubTarget: caller %#" Px " alloc-class %s " 1914 OS::PrintErr("FixAllocationStubTarget: caller %#" Px
1976 " -> %#" Px "\n", 1915 " alloc-class %s "
1977 frame->pc(), 1916 " -> %#" Px "\n",
1978 alloc_class.ToCString(), 1917 frame->pc(), alloc_class.ToCString(),
1979 alloc_stub.UncheckedEntryPoint()); 1918 alloc_stub.UncheckedEntryPoint());
1980 } 1919 }
1981 arguments.SetReturn(alloc_stub); 1920 arguments.SetReturn(alloc_stub);
1982 #else 1921 #else
1983 UNREACHABLE(); 1922 UNREACHABLE();
1984 #endif 1923 #endif
1985 } 1924 }
1986 1925
1987 1926
1988 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason) { 1927 const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason) {
1989 switch (deopt_reason) { 1928 switch (deopt_reason) {
1990 #define DEOPT_REASON_TO_TEXT(name) case ICData::kDeopt##name: return #name; 1929 #define DEOPT_REASON_TO_TEXT(name) \
1991 DEOPT_REASONS(DEOPT_REASON_TO_TEXT) 1930 case ICData::kDeopt##name: \
1931 return #name;
1932 DEOPT_REASONS(DEOPT_REASON_TO_TEXT)
1992 #undef DEOPT_REASON_TO_TEXT 1933 #undef DEOPT_REASON_TO_TEXT
1993 default: 1934 default:
1994 UNREACHABLE(); 1935 UNREACHABLE();
1995 return ""; 1936 return "";
1996 } 1937 }
1997 } 1938 }
1998 1939
1999 1940
2000 void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) { 1941 void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) {
2001 ASSERT(optimized_code.is_optimized()); 1942 ASSERT(optimized_code.is_optimized());
(...skipping 14 matching lines...) Expand all
2016 } 1957 }
2017 1958
2018 #if defined(TARGET_ARCH_DBC) 1959 #if defined(TARGET_ARCH_DBC)
2019 const Instructions& instrs = 1960 const Instructions& instrs =
2020 Instructions::Handle(zone, optimized_code.instructions()); 1961 Instructions::Handle(zone, optimized_code.instructions());
2021 { 1962 {
2022 WritableInstructionsScope writable(instrs.PayloadStart(), instrs.size()); 1963 WritableInstructionsScope writable(instrs.PayloadStart(), instrs.size());
2023 CodePatcher::InsertDeoptimizationCallAt(frame->pc()); 1964 CodePatcher::InsertDeoptimizationCallAt(frame->pc());
2024 if (FLAG_trace_patching) { 1965 if (FLAG_trace_patching) {
2025 const String& name = String::Handle(function.name()); 1966 const String& name = String::Handle(function.name());
2026 OS::PrintErr( 1967 OS::PrintErr("InsertDeoptimizationCallAt: 0x%" Px " for %s\n",
2027 "InsertDeoptimizationCallAt: 0x%" Px " for %s\n", 1968 frame->pc(), name.ToCString());
2028 frame->pc(), name.ToCString());
2029 } 1969 }
2030 const ExceptionHandlers& handlers = 1970 const ExceptionHandlers& handlers =
2031 ExceptionHandlers::Handle(zone, optimized_code.exception_handlers()); 1971 ExceptionHandlers::Handle(zone, optimized_code.exception_handlers());
2032 RawExceptionHandlers::HandlerInfo info; 1972 RawExceptionHandlers::HandlerInfo info;
2033 for (intptr_t i = 0; i < handlers.num_entries(); ++i) { 1973 for (intptr_t i = 0; i < handlers.num_entries(); ++i) {
2034 handlers.GetHandlerInfo(i, &info); 1974 handlers.GetHandlerInfo(i, &info);
2035 const uword patch_pc = instrs.PayloadStart() + info.handler_pc_offset; 1975 const uword patch_pc = instrs.PayloadStart() + info.handler_pc_offset;
2036 CodePatcher::InsertDeoptimizationCallAt(patch_pc); 1976 CodePatcher::InsertDeoptimizationCallAt(patch_pc);
2037 if (FLAG_trace_patching) { 1977 if (FLAG_trace_patching) {
2038 OS::PrintErr(" at handler 0x%" Px "\n", patch_pc); 1978 OS::PrintErr(" at handler 0x%" Px "\n", patch_pc);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2119 *cpu_registers = cpu_registers_copy; 2059 *cpu_registers = cpu_registers_copy;
2120 } 2060 }
2121 #endif 2061 #endif
2122 2062
2123 2063
2124 // Copies saved registers and caller's frame into temporary buffers. 2064 // Copies saved registers and caller's frame into temporary buffers.
2125 // Returns the stack size of unoptimized frame. 2065 // Returns the stack size of unoptimized frame.
2126 // The calling code must be optimized, but its function may not have 2066 // The calling code must be optimized, but its function may not have
2127 // have optimized code if the code is OSR code, or if the code was invalidated 2067 // have optimized code if the code is OSR code, or if the code was invalidated
2128 // through class loading/finalization or field guard. 2068 // through class loading/finalization or field guard.
2129 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, 2069 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t,
2070 DeoptimizeCopyFrame,
2130 2, 2071 2,
2131 uword saved_registers_address, 2072 uword saved_registers_address,
2132 uword is_lazy_deopt) { 2073 uword is_lazy_deopt) {
2133 #if !defined(DART_PRECOMPILED_RUNTIME) 2074 #if !defined(DART_PRECOMPILED_RUNTIME)
2134 Thread* thread = Thread::Current(); 2075 Thread* thread = Thread::Current();
2135 Isolate* isolate = thread->isolate(); 2076 Isolate* isolate = thread->isolate();
2136 StackZone zone(thread); 2077 StackZone zone(thread);
2137 HANDLESCOPE(thread); 2078 HANDLESCOPE(thread);
2138 2079
2139 // All registers have been saved below last-fp as if they were locals. 2080 // All registers have been saved below last-fp as if they were locals.
2140 const uword last_fp = saved_registers_address 2081 const uword last_fp = saved_registers_address +
2141 + (kNumberOfSavedCpuRegisters * kWordSize) 2082 (kNumberOfSavedCpuRegisters * kWordSize) +
2142 + (kNumberOfSavedFpuRegisters * kFpuRegisterSize) 2083 (kNumberOfSavedFpuRegisters * kFpuRegisterSize) -
2143 - ((kFirstLocalSlotFromFp + 1) * kWordSize); 2084 ((kFirstLocalSlotFromFp + 1) * kWordSize);
2144 2085
2145 // Get optimized code and frame that need to be deoptimized. 2086 // Get optimized code and frame that need to be deoptimized.
2146 DartFrameIterator iterator(last_fp); 2087 DartFrameIterator iterator(last_fp);
2147 2088
2148 StackFrame* caller_frame = iterator.NextFrame(); 2089 StackFrame* caller_frame = iterator.NextFrame();
2149 ASSERT(caller_frame != NULL); 2090 ASSERT(caller_frame != NULL);
2150 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); 2091 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
2151 ASSERT(optimized_code.is_optimized()); 2092 ASSERT(optimized_code.is_optimized());
2152 const Function& top_function = 2093 const Function& top_function =
2153 Function::Handle(thread->zone(), optimized_code.function()); 2094 Function::Handle(thread->zone(), optimized_code.function());
2154 const bool deoptimizing_code = top_function.HasOptimizedCode(); 2095 const bool deoptimizing_code = top_function.HasOptimizedCode();
2155 if (FLAG_trace_deoptimization) { 2096 if (FLAG_trace_deoptimization) {
2156 const Function& function = Function::Handle(optimized_code.function()); 2097 const Function& function = Function::Handle(optimized_code.function());
2157 THR_Print("== Deoptimizing code for '%s', %s, %s\n", 2098 THR_Print("== Deoptimizing code for '%s', %s, %s\n",
2158 function.ToFullyQualifiedCString(), 2099 function.ToFullyQualifiedCString(),
2159 deoptimizing_code ? "code & frame" : "frame", 2100 deoptimizing_code ? "code & frame" : "frame",
2160 is_lazy_deopt ? "lazy-deopt" : ""); 2101 is_lazy_deopt ? "lazy-deopt" : "");
2161 } 2102 }
2162 2103
2163 #if !defined(TARGET_ARCH_DBC) 2104 #if !defined(TARGET_ARCH_DBC)
2164 if (is_lazy_deopt) { 2105 if (is_lazy_deopt) {
2165 uword deopt_pc = isolate->FindPendingDeopt(caller_frame->fp()); 2106 uword deopt_pc = isolate->FindPendingDeopt(caller_frame->fp());
2166 if (FLAG_trace_deoptimization) { 2107 if (FLAG_trace_deoptimization) {
2167 THR_Print("Lazy deopt fp=%" Pp " pc=%" Pp "\n", 2108 THR_Print("Lazy deopt fp=%" Pp " pc=%" Pp "\n", caller_frame->fp(),
2168 caller_frame->fp(), deopt_pc); 2109 deopt_pc);
2169 } 2110 }
2170 2111
2171 // N.B.: Update frame before updating pending deopt table. The profiler 2112 // N.B.: Update frame before updating pending deopt table. The profiler
2172 // may attempt a stack walk in between. 2113 // may attempt a stack walk in between.
2173 caller_frame->set_pc(deopt_pc); 2114 caller_frame->set_pc(deopt_pc);
2174 ASSERT(caller_frame->pc() == deopt_pc); 2115 ASSERT(caller_frame->pc() == deopt_pc);
2175 ASSERT(optimized_code.ContainsInstructionAt(caller_frame->pc())); 2116 ASSERT(optimized_code.ContainsInstructionAt(caller_frame->pc()));
2176 isolate->ClearPendingDeoptsAtOrBelow(caller_frame->fp()); 2117 isolate->ClearPendingDeoptsAtOrBelow(caller_frame->fp());
2177 } else { 2118 } else {
2178 if (FLAG_trace_deoptimization) { 2119 if (FLAG_trace_deoptimization) {
2179 THR_Print("Eager deopt fp=%" Pp " pc=%" Pp "\n", 2120 THR_Print("Eager deopt fp=%" Pp " pc=%" Pp "\n", caller_frame->fp(),
2180 caller_frame->fp(), caller_frame->pc()); 2121 caller_frame->pc());
2181 } 2122 }
2182 } 2123 }
2183 #endif // !DBC 2124 #endif // !DBC
2184 2125
2185 // Copy the saved registers from the stack. 2126 // Copy the saved registers from the stack.
2186 fpu_register_t* fpu_registers; 2127 fpu_register_t* fpu_registers;
2187 intptr_t* cpu_registers; 2128 intptr_t* cpu_registers;
2188 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); 2129 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers);
2189 2130
2190 // Create the DeoptContext. 2131 // Create the DeoptContext.
2191 DeoptContext* deopt_context = 2132 DeoptContext* deopt_context = new DeoptContext(
2192 new DeoptContext(caller_frame, 2133 caller_frame, optimized_code, DeoptContext::kDestIsOriginalFrame,
2193 optimized_code, 2134 fpu_registers, cpu_registers, is_lazy_deopt != 0, deoptimizing_code);
2194 DeoptContext::kDestIsOriginalFrame,
2195 fpu_registers,
2196 cpu_registers,
2197 is_lazy_deopt != 0,
2198 deoptimizing_code);
2199 isolate->set_deopt_context(deopt_context); 2135 isolate->set_deopt_context(deopt_context);
2200 2136
2201 // Stack size (FP - SP) in bytes. 2137 // Stack size (FP - SP) in bytes.
2202 return deopt_context->DestStackAdjustment() * kWordSize; 2138 return deopt_context->DestStackAdjustment() * kWordSize;
2203 #else 2139 #else
2204 UNREACHABLE(); 2140 UNREACHABLE();
2205 return 0; 2141 return 0;
2206 #endif // !DART_PRECOMPILED_RUNTIME 2142 #endif // !DART_PRECOMPILED_RUNTIME
2207 } 2143 }
2208 END_LEAF_RUNTIME_ENTRY 2144 END_LEAF_RUNTIME_ENTRY
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2345 const intptr_t elm_size = old_data.ElementSizeInBytes(); 2281 const intptr_t elm_size = old_data.ElementSizeInBytes();
2346 const TypedData& new_data = 2282 const TypedData& new_data =
2347 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); 2283 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld));
2348 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); 2284 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size);
2349 typed_data_cell.SetAt(0, new_data); 2285 typed_data_cell.SetAt(0, new_data);
2350 arguments.SetReturn(new_data); 2286 arguments.SetReturn(new_data);
2351 } 2287 }
2352 2288
2353 2289
2354 } // namespace dart 2290 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/code_generator.h ('k') | runtime/vm/code_generator_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698