OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |