| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_macros.h" | 7 #include "vm/assembler_macros.h" |
| 8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
| 9 #include "vm/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
| 10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 "Maximum number of subtype cache entries (number of checks cached)."); | 55 "Maximum number of subtype cache entries (number of checks cached)."); |
| 56 | 56 |
| 57 | 57 |
| 58 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) { | 58 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) { |
| 59 ASSERT(arguments.ArgCount() == | 59 ASSERT(arguments.ArgCount() == |
| 60 kTraceFunctionEntryRuntimeEntry.argument_count()); | 60 kTraceFunctionEntryRuntimeEntry.argument_count()); |
| 61 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); | 61 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); |
| 62 const String& function_name = String::Handle(function.name()); | 62 const String& function_name = String::Handle(function.name()); |
| 63 const String& class_name = | 63 const String& class_name = |
| 64 String::Handle(Class::Handle(function.Owner()).Name()); | 64 String::Handle(Class::Handle(function.Owner()).Name()); |
| 65 OS::Print("> Entering '%s.%s'\n", | 65 OS::PrintErr("> Entering '%s.%s'\n", |
| 66 class_name.ToCString(), function_name.ToCString()); | 66 class_name.ToCString(), function_name.ToCString()); |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 DEFINE_RUNTIME_ENTRY(TraceFunctionExit, 1) { | 70 DEFINE_RUNTIME_ENTRY(TraceFunctionExit, 1) { |
| 71 ASSERT(arguments.ArgCount() == | 71 ASSERT(arguments.ArgCount() == |
| 72 kTraceFunctionExitRuntimeEntry.argument_count()); | 72 kTraceFunctionExitRuntimeEntry.argument_count()); |
| 73 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); | 73 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); |
| 74 const String& function_name = String::Handle(function.name()); | 74 const String& function_name = String::Handle(function.name()); |
| 75 const String& class_name = | 75 const String& class_name = |
| 76 String::Handle(Class::Handle(function.Owner()).Name()); | 76 String::Handle(Class::Handle(function.Owner()).Name()); |
| 77 OS::Print("< Exiting '%s.%s'\n", | 77 OS::PrintErr("< Exiting '%s.%s'\n", |
| 78 class_name.ToCString(), function_name.ToCString()); | 78 class_name.ToCString(), function_name.ToCString()); |
| 79 } | 79 } |
| 80 | 80 |
| 81 | 81 |
| 82 // Allocation of a fixed length array of given element type. | 82 // Allocation of a fixed length array of given element type. |
| 83 // This runtime entry is never called for allocating a List of a generic type, | 83 // This runtime entry is never called for allocating a List of a generic type, |
| 84 // because a prior run time call instantiates the element type if necessary. | 84 // because a prior run time call instantiates the element type if necessary. |
| 85 // Arg0: array length. | 85 // Arg0: array length. |
| 86 // Arg1: array type arguments, i.e. vector of 1 type, the element type. | 86 // Arg1: array type arguments, i.e. vector of 1 type, the element type. |
| 87 // Return value: newly allocated array of length arg0. | 87 // Return value: newly allocated array of length arg0. |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 const AbstractType& type, | 356 const AbstractType& type, |
| 357 const AbstractTypeArguments& instantiator_type_arguments, | 357 const AbstractTypeArguments& instantiator_type_arguments, |
| 358 const Bool& result) { | 358 const Bool& result) { |
| 359 DartFrameIterator iterator; | 359 DartFrameIterator iterator; |
| 360 StackFrame* caller_frame = iterator.NextFrame(); | 360 StackFrame* caller_frame = iterator.NextFrame(); |
| 361 ASSERT(caller_frame != NULL); | 361 ASSERT(caller_frame != NULL); |
| 362 | 362 |
| 363 const Type& instance_type = Type::Handle(instance.GetType()); | 363 const Type& instance_type = Type::Handle(instance.GetType()); |
| 364 ASSERT(instance_type.IsInstantiated()); | 364 ASSERT(instance_type.IsInstantiated()); |
| 365 if (type.IsInstantiated()) { | 365 if (type.IsInstantiated()) { |
| 366 OS::Print("%s: '%s' %"Pd" %s '%s' %"Pd" (pc: %#"Px").\n", | 366 OS::PrintErr("%s: '%s' %"Pd" %s '%s' %"Pd" (pc: %#"Px").\n", |
| 367 message, | 367 message, |
| 368 String::Handle(instance_type.Name()).ToCString(), | 368 String::Handle(instance_type.Name()).ToCString(), |
| 369 Class::Handle(instance_type.type_class()).id(), | 369 Class::Handle(instance_type.type_class()).id(), |
| 370 (result.raw() == Bool::True().raw()) ? "is" : "is !", | 370 (result.raw() == Bool::True().raw()) ? "is" : "is !", |
| 371 String::Handle(type.Name()).ToCString(), | 371 String::Handle(type.Name()).ToCString(), |
| 372 Class::Handle(type.type_class()).id(), | 372 Class::Handle(type.type_class()).id(), |
| 373 caller_frame->pc()); | 373 caller_frame->pc()); |
| 374 } else { | 374 } else { |
| 375 // Instantiate type before printing. | 375 // Instantiate type before printing. |
| 376 const AbstractType& instantiated_type = | 376 const AbstractType& instantiated_type = |
| 377 AbstractType::Handle(type.InstantiateFrom(instantiator_type_arguments)); | 377 AbstractType::Handle(type.InstantiateFrom(instantiator_type_arguments)); |
| 378 OS::Print("%s: '%s' %s '%s' instantiated from '%s' (pc: %#"Px").\n", | 378 OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#"Px").\n", |
| 379 message, | 379 message, |
| 380 String::Handle(instance_type.Name()).ToCString(), | 380 String::Handle(instance_type.Name()).ToCString(), |
| 381 (result.raw() == Bool::True().raw()) ? "is" : "is !", | 381 (result.raw() == Bool::True().raw()) ? "is" : "is !", |
| 382 String::Handle(instantiated_type.Name()).ToCString(), | 382 String::Handle(instantiated_type.Name()).ToCString(), |
| 383 String::Handle(type.Name()).ToCString(), | 383 String::Handle(type.Name()).ToCString(), |
| 384 caller_frame->pc()); | 384 caller_frame->pc()); |
| 385 } | 385 } |
| 386 const Function& function = Function::Handle( | 386 const Function& function = Function::Handle( |
| 387 caller_frame->LookupDartFunction()); | 387 caller_frame->LookupDartFunction()); |
| 388 OS::Print(" -> Function %s\n", function.ToFullyQualifiedCString()); | 388 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); |
| 389 } | 389 } |
| 390 | 390 |
| 391 | 391 |
| 392 // Converts InstantiatedTypeArguments to TypeArguments and stores it | 392 // Converts InstantiatedTypeArguments to TypeArguments and stores it |
| 393 // into the instance. The assembly code can handle only type arguments of | 393 // into the instance. The assembly code can handle only type arguments of |
| 394 // class TypeArguments. Because of the overhead, do it only when needed. | 394 // class TypeArguments. Because of the overhead, do it only when needed. |
| 395 // Return true if type arguments have been replaced, false otherwise. | 395 // Return true if type arguments have been replaced, false otherwise. |
| 396 static bool OptimizeTypeArguments(const Instance& instance) { | 396 static bool OptimizeTypeArguments(const Instance& instance) { |
| 397 const Class& type_class = Class::ZoneHandle(instance.clazz()); | 397 const Class& type_class = Class::ZoneHandle(instance.clazz()); |
| 398 if (!type_class.HasTypeArguments()) { | 398 if (!type_class.HasTypeArguments()) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 i, | 485 i, |
| 486 &last_instance_class_id, | 486 &last_instance_class_id, |
| 487 &last_instance_type_arguments, | 487 &last_instance_type_arguments, |
| 488 &last_instantiator_type_arguments, | 488 &last_instantiator_type_arguments, |
| 489 &last_result); | 489 &last_result); |
| 490 if ((last_instance_class_id == instance_class.id()) && | 490 if ((last_instance_class_id == instance_class.id()) && |
| 491 (last_instance_type_arguments.raw() == instance_type_arguments.raw()) && | 491 (last_instance_type_arguments.raw() == instance_type_arguments.raw()) && |
| 492 (last_instantiator_type_arguments.raw() == | 492 (last_instantiator_type_arguments.raw() == |
| 493 instantiator_type_arguments.raw())) { | 493 instantiator_type_arguments.raw())) { |
| 494 if (FLAG_trace_type_checks) { | 494 if (FLAG_trace_type_checks) { |
| 495 OS::Print("%"Pd" ", i); | 495 OS::PrintErr("%"Pd" ", i); |
| 496 if (type_arguments_replaced) { | 496 if (type_arguments_replaced) { |
| 497 PrintTypeCheck("Duplicate cache entry (canonical.)", instance, type, | 497 PrintTypeCheck("Duplicate cache entry (canonical.)", instance, type, |
| 498 instantiator_type_arguments, result); | 498 instantiator_type_arguments, result); |
| 499 } else { | 499 } else { |
| 500 PrintTypeCheck("WARNING Duplicate cache entry", instance, type, | 500 PrintTypeCheck("WARNING Duplicate cache entry", instance, type, |
| 501 instantiator_type_arguments, result); | 501 instantiator_type_arguments, result); |
| 502 } | 502 } |
| 503 } | 503 } |
| 504 // Can occur if we have canonicalized arguments. | 504 // Can occur if we have canonicalized arguments. |
| 505 // TODO(srdjan): Investigate why this assert can fail. | 505 // TODO(srdjan): Investigate why this assert can fail. |
| 506 // ASSERT(type_arguments_replaced); | 506 // ASSERT(type_arguments_replaced); |
| 507 return; | 507 return; |
| 508 } | 508 } |
| 509 } | 509 } |
| 510 if (!instantiator_type_arguments.IsInstantiatedTypeArguments()) { | 510 if (!instantiator_type_arguments.IsInstantiatedTypeArguments()) { |
| 511 new_cache.AddCheck(instance_class.id(), | 511 new_cache.AddCheck(instance_class.id(), |
| 512 instance_type_arguments, | 512 instance_type_arguments, |
| 513 instantiator_type_arguments, | 513 instantiator_type_arguments, |
| 514 result); | 514 result); |
| 515 } | 515 } |
| 516 if (FLAG_trace_type_checks) { | 516 if (FLAG_trace_type_checks) { |
| 517 AbstractType& test_type = AbstractType::Handle(type.raw()); | 517 AbstractType& test_type = AbstractType::Handle(type.raw()); |
| 518 if (!test_type.IsInstantiated()) { | 518 if (!test_type.IsInstantiated()) { |
| 519 test_type = type.InstantiateFrom(instantiator_type_arguments); | 519 test_type = type.InstantiateFrom(instantiator_type_arguments); |
| 520 } | 520 } |
| 521 OS::Print(" Updated test cache %p ix: %"Pd" with (%"Pd", %p, %p, %s)\n" | 521 OS::PrintErr(" Updated test cache %p ix: %"Pd" with (%"Pd", %p, %p, %s)\n" |
| 522 " [%p %s %"Pd", %p %s]\n" | 522 " [%p %s %"Pd", %p %s]\n" |
| 523 " [%p %s %"Pd", %p %s] %s\n", | 523 " [%p %s %"Pd", %p %s] %s\n", |
| 524 new_cache.raw(), | 524 new_cache.raw(), |
| 525 len, | 525 len, |
| 526 instance_class.id(), | 526 instance_class.id(), |
| 527 | 527 |
| 528 instance_type_arguments.raw(), | 528 instance_type_arguments.raw(), |
| 529 instantiator_type_arguments.raw(), | 529 instantiator_type_arguments.raw(), |
| 530 result.ToCString(), | 530 result.ToCString(), |
| 531 | 531 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 } | 759 } |
| 760 } | 760 } |
| 761 const Code& target_code = Code::Handle(target_function.CurrentCode()); | 761 const Code& target_code = Code::Handle(target_function.CurrentCode()); |
| 762 // Before patching verify that we are not repeatedly patching to the same | 762 // Before patching verify that we are not repeatedly patching to the same |
| 763 // target. | 763 // target. |
| 764 ASSERT(target_code.EntryPoint() != | 764 ASSERT(target_code.EntryPoint() != |
| 765 CodePatcher::GetStaticCallTargetAt(caller_frame->pc())); | 765 CodePatcher::GetStaticCallTargetAt(caller_frame->pc())); |
| 766 CodePatcher::PatchStaticCallAt(caller_frame->pc(), target_code.EntryPoint()); | 766 CodePatcher::PatchStaticCallAt(caller_frame->pc(), target_code.EntryPoint()); |
| 767 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); | 767 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); |
| 768 if (FLAG_trace_patching) { | 768 if (FLAG_trace_patching) { |
| 769 OS::Print("PatchStaticCall: patching from %#"Px" to '%s' %#"Px"\n", | 769 OS::PrintErr("PatchStaticCall: patching from %#"Px" to '%s' %#"Px"\n", |
| 770 caller_frame->pc(), | 770 caller_frame->pc(), |
| 771 target_function.ToFullyQualifiedCString(), | 771 target_function.ToFullyQualifiedCString(), |
| 772 target_code.EntryPoint()); | 772 target_code.EntryPoint()); |
| 773 } | 773 } |
| 774 arguments.SetReturn(target_code); | 774 arguments.SetReturn(target_code); |
| 775 } | 775 } |
| 776 | 776 |
| 777 | 777 |
| 778 // Resolves and compiles the target function of an instance call, updates | 778 // Resolves and compiles the target function of an instance call, updates |
| 779 // function cache of the receiver's class and returns the compiled code or null. | 779 // function cache of the receiver's class and returns the compiled code or null. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 const Array& arg_descriptor_array) { | 867 const Array& arg_descriptor_array) { |
| 868 const Instance& receiver = *args[0]; | 868 const Instance& receiver = *args[0]; |
| 869 const Code& target_code = | 869 const Code& target_code = |
| 870 Code::Handle(ResolveCompileInstanceCallTarget(receiver, | 870 Code::Handle(ResolveCompileInstanceCallTarget(receiver, |
| 871 ic_data, | 871 ic_data, |
| 872 arg_descriptor_array)); | 872 arg_descriptor_array)); |
| 873 if (target_code.IsNull()) { | 873 if (target_code.IsNull()) { |
| 874 // Let the megamorphic stub handle special cases: NoSuchMethod, | 874 // Let the megamorphic stub handle special cases: NoSuchMethod, |
| 875 // closure calls. | 875 // closure calls. |
| 876 if (FLAG_trace_ic) { | 876 if (FLAG_trace_ic) { |
| 877 OS::Print("InlineCacheMissHandler NULL code for receiver: %s\n", | 877 OS::PrintErr("InlineCacheMissHandler NULL code for receiver: %s\n", |
| 878 receiver.ToCString()); | 878 receiver.ToCString()); |
| 879 } | 879 } |
| 880 return Function::null(); | 880 return Function::null(); |
| 881 } | 881 } |
| 882 const Function& target_function = | 882 const Function& target_function = |
| 883 Function::Handle(target_code.function()); | 883 Function::Handle(target_code.function()); |
| 884 ASSERT(!target_function.IsNull()); | 884 ASSERT(!target_function.IsNull()); |
| 885 if (args.length() == 1) { | 885 if (args.length() == 1) { |
| 886 ic_data.AddReceiverCheck(Class::Handle(args[0]->clazz()).id(), | 886 ic_data.AddReceiverCheck(Class::Handle(args[0]->clazz()).id(), |
| 887 target_function); | 887 target_function); |
| 888 } else { | 888 } else { |
| 889 GrowableArray<intptr_t> class_ids(args.length()); | 889 GrowableArray<intptr_t> class_ids(args.length()); |
| 890 ASSERT(ic_data.num_args_tested() == args.length()); | 890 ASSERT(ic_data.num_args_tested() == args.length()); |
| 891 for (intptr_t i = 0; i < args.length(); i++) { | 891 for (intptr_t i = 0; i < args.length(); i++) { |
| 892 class_ids.Add(Class::Handle(args[i]->clazz()).id()); | 892 class_ids.Add(Class::Handle(args[i]->clazz()).id()); |
| 893 } | 893 } |
| 894 ic_data.AddCheck(class_ids, target_function); | 894 ic_data.AddCheck(class_ids, target_function); |
| 895 } | 895 } |
| 896 if (FLAG_trace_ic_miss_in_optimized || FLAG_trace_ic) { | 896 if (FLAG_trace_ic_miss_in_optimized || FLAG_trace_ic) { |
| 897 DartFrameIterator iterator; | 897 DartFrameIterator iterator; |
| 898 StackFrame* caller_frame = iterator.NextFrame(); | 898 StackFrame* caller_frame = iterator.NextFrame(); |
| 899 ASSERT(caller_frame != NULL); | 899 ASSERT(caller_frame != NULL); |
| 900 if (FLAG_trace_ic_miss_in_optimized) { | 900 if (FLAG_trace_ic_miss_in_optimized) { |
| 901 const Code& caller = Code::Handle(Code::LookupCode(caller_frame->pc())); | 901 const Code& caller = Code::Handle(Code::LookupCode(caller_frame->pc())); |
| 902 if (caller.is_optimized()) { | 902 if (caller.is_optimized()) { |
| 903 OS::Print("IC miss in optimized code; call %s -> %s\n", | 903 OS::PrintErr("IC miss in optimized code; call %s -> %s\n", |
| 904 Function::Handle(caller.function()).ToCString(), | 904 Function::Handle(caller.function()).ToCString(), |
| 905 target_function.ToCString()); | 905 target_function.ToCString()); |
| 906 } | 906 } |
| 907 } | 907 } |
| 908 if (FLAG_trace_ic) { | 908 if (FLAG_trace_ic) { |
| 909 OS::Print("InlineCacheMissHandler %d call at %#"Px"' " | 909 OS::PrintErr("InlineCacheMissHandler %d call at %#"Px"' " |
| 910 "adding <%s> id:%"Pd" -> <%s>\n", | 910 "adding <%s> id:%"Pd" -> <%s>\n", |
| 911 args.length(), | 911 args.length(), |
| 912 caller_frame->pc(), | 912 caller_frame->pc(), |
| 913 Class::Handle(receiver.clazz()).ToCString(), | 913 Class::Handle(receiver.clazz()).ToCString(), |
| 914 Class::Handle(receiver.clazz()).id(), | 914 Class::Handle(receiver.clazz()).id(), |
| 915 target_function.ToCString()); | 915 target_function.ToCString()); |
| 916 } | 916 } |
| 917 } | 917 } |
| 918 return target_function.raw(); | 918 return target_function.raw(); |
| 919 } | 919 } |
| 920 | 920 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 const String& name = String::Handle(ic_data.target_name()); | 1008 const String& name = String::Handle(ic_data.target_name()); |
| 1009 const MegamorphicCache& cache = MegamorphicCache::Handle( | 1009 const MegamorphicCache& cache = MegamorphicCache::Handle( |
| 1010 isolate->megamorphic_cache_table()->Lookup(name, descriptor)); | 1010 isolate->megamorphic_cache_table()->Lookup(name, descriptor)); |
| 1011 Class& cls = Class::Handle(receiver.clazz()); | 1011 Class& cls = Class::Handle(receiver.clazz()); |
| 1012 // For lookups treat null as an instance of class Object. | 1012 // For lookups treat null as an instance of class Object. |
| 1013 if (cls.IsNullClass()) { | 1013 if (cls.IsNullClass()) { |
| 1014 cls = isolate->object_store()->object_class(); | 1014 cls = isolate->object_store()->object_class(); |
| 1015 } | 1015 } |
| 1016 ASSERT(!cls.IsNull()); | 1016 ASSERT(!cls.IsNull()); |
| 1017 if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) { | 1017 if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) { |
| 1018 OS::Print("Megamorphic IC miss, class=%s, function=%s\n", | 1018 OS::PrintErr("Megamorphic IC miss, class=%s, function=%s\n", |
| 1019 cls.ToCString(), name.ToCString()); | 1019 cls.ToCString(), name.ToCString()); |
| 1020 } | 1020 } |
| 1021 | 1021 |
| 1022 intptr_t arg_count = | 1022 intptr_t arg_count = |
| 1023 Smi::Cast(Object::Handle(descriptor.At(0))).Value(); | 1023 Smi::Cast(Object::Handle(descriptor.At(0))).Value(); |
| 1024 intptr_t named_arg_count = | 1024 intptr_t named_arg_count = |
| 1025 arg_count - Smi::Cast(Object::Handle(descriptor.At(1))).Value(); | 1025 arg_count - Smi::Cast(Object::Handle(descriptor.At(1))).Value(); |
| 1026 const Function& target = Function::Handle( | 1026 const Function& target = Function::Handle( |
| 1027 Resolver::ResolveDynamicForReceiverClass(cls, | 1027 Resolver::ResolveDynamicForReceiverClass(cls, |
| 1028 name, | 1028 name, |
| 1029 arg_count, | 1029 arg_count, |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 } | 1298 } |
| 1299 } | 1299 } |
| 1300 | 1300 |
| 1301 | 1301 |
| 1302 static void PrintCaller(const char* msg) { | 1302 static void PrintCaller(const char* msg) { |
| 1303 DartFrameIterator iterator; | 1303 DartFrameIterator iterator; |
| 1304 StackFrame* top_frame = iterator.NextFrame(); | 1304 StackFrame* top_frame = iterator.NextFrame(); |
| 1305 ASSERT(top_frame != NULL); | 1305 ASSERT(top_frame != NULL); |
| 1306 const Function& top_function = Function::Handle( | 1306 const Function& top_function = Function::Handle( |
| 1307 top_frame->LookupDartFunction()); | 1307 top_frame->LookupDartFunction()); |
| 1308 OS::Print("Failed: '%s' %s @ %#"Px"\n", | 1308 OS::PrintErr("Failed: '%s' %s @ %#"Px"\n", |
| 1309 msg, top_function.ToFullyQualifiedCString(), top_frame->pc()); | 1309 msg, top_function.ToFullyQualifiedCString(), top_frame->pc()); |
| 1310 StackFrame* caller_frame = iterator.NextFrame(); | 1310 StackFrame* caller_frame = iterator.NextFrame(); |
| 1311 if (caller_frame != NULL) { | 1311 if (caller_frame != NULL) { |
| 1312 const Function& caller_function = Function::Handle( | 1312 const Function& caller_function = Function::Handle( |
| 1313 caller_frame->LookupDartFunction()); | 1313 caller_frame->LookupDartFunction()); |
| 1314 const Code& code = Code::Handle(caller_frame->LookupDartCode()); | 1314 const Code& code = Code::Handle(caller_frame->LookupDartCode()); |
| 1315 OS::Print(" -> caller: %s (%s)\n", | 1315 OS::PrintErr(" -> caller: %s (%s)\n", |
| 1316 caller_function.ToFullyQualifiedCString(), | 1316 caller_function.ToFullyQualifiedCString(), |
| 1317 code.is_optimized() ? "optimized" : "unoptimized"); | 1317 code.is_optimized() ? "optimized" : "unoptimized"); |
| 1318 } | 1318 } |
| 1319 } | 1319 } |
| 1320 | 1320 |
| 1321 | 1321 |
| 1322 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { | 1322 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { |
| 1323 ASSERT(arguments.ArgCount() == | 1323 ASSERT(arguments.ArgCount() == |
| 1324 kTraceICCallRuntimeEntry.argument_count()); | 1324 kTraceICCallRuntimeEntry.argument_count()); |
| 1325 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); | 1325 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); |
| 1326 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); | 1326 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); |
| 1327 DartFrameIterator iterator; | 1327 DartFrameIterator iterator; |
| 1328 StackFrame* frame = iterator.NextFrame(); | 1328 StackFrame* frame = iterator.NextFrame(); |
| 1329 ASSERT(frame != NULL); | 1329 ASSERT(frame != NULL); |
| 1330 OS::Print("IC call @%#"Px": ICData: %p cnt:%"Pd" nchecks: %"Pd" %s %s\n", | 1330 OS::PrintErr("IC call @%#"Px": ICData: %p cnt:%"Pd" nchecks: %"Pd" %s %s\n", |
| 1331 frame->pc(), | 1331 frame->pc(), |
| 1332 ic_data.raw(), | 1332 ic_data.raw(), |
| 1333 function.usage_counter(), | 1333 function.usage_counter(), |
| 1334 ic_data.NumberOfChecks(), | 1334 ic_data.NumberOfChecks(), |
| 1335 ic_data.is_closure_call() ? "closure" : "", | 1335 ic_data.is_closure_call() ? "closure" : "", |
| 1336 function.ToFullyQualifiedCString()); | 1336 function.ToFullyQualifiedCString()); |
| 1337 } | 1337 } |
| 1338 | 1338 |
| 1339 | 1339 |
| 1340 // This is called from function that needs to be optimized. | 1340 // This is called from function that needs to be optimized. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1376 if (!error.IsNull()) { | 1376 if (!error.IsNull()) { |
| 1377 Exceptions::PropagateError(error); | 1377 Exceptions::PropagateError(error); |
| 1378 } | 1378 } |
| 1379 const Code& optimized_code = Code::Handle(function.CurrentCode()); | 1379 const Code& optimized_code = Code::Handle(function.CurrentCode()); |
| 1380 ASSERT(!optimized_code.IsNull()); | 1380 ASSERT(!optimized_code.IsNull()); |
| 1381 // Set usage counter for reoptimization. | 1381 // Set usage counter for reoptimization. |
| 1382 function.set_usage_counter( | 1382 function.set_usage_counter( |
| 1383 function.usage_counter() - FLAG_reoptimization_counter_threshold); | 1383 function.usage_counter() - FLAG_reoptimization_counter_threshold); |
| 1384 } else { | 1384 } else { |
| 1385 if (FLAG_trace_failed_optimization_attempts) { | 1385 if (FLAG_trace_failed_optimization_attempts) { |
| 1386 PrintCaller("Not Optimizable"); | 1386 OS::PrintErr("Not Optimizable: %s\n", function.ToFullyQualifiedCString()); |
| 1387 } | 1387 } |
| 1388 // TODO(5442338): Abort as this should not happen. | 1388 // TODO(5442338): Abort as this should not happen. |
| 1389 function.set_usage_counter(kLowInvocationCount); | 1389 function.set_usage_counter(kLowInvocationCount); |
| 1390 } | 1390 } |
| 1391 arguments.SetReturn(Code::Handle(function.CurrentCode())); | 1391 arguments.SetReturn(Code::Handle(function.CurrentCode())); |
| 1392 } | 1392 } |
| 1393 | 1393 |
| 1394 | 1394 |
| 1395 // The caller must be a static call in a Dart frame, or an entry frame. | 1395 // The caller must be a static call in a Dart frame, or an entry frame. |
| 1396 // Patch static call to point to valid code's entry point. | 1396 // Patch static call to point to valid code's entry point. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1410 UNREACHABLE(); | 1410 UNREACHABLE(); |
| 1411 } | 1411 } |
| 1412 ASSERT(frame->IsDartFrame()); | 1412 ASSERT(frame->IsDartFrame()); |
| 1413 const Code& caller_code = Code::Handle(frame->LookupDartCode()); | 1413 const Code& caller_code = Code::Handle(frame->LookupDartCode()); |
| 1414 const Function& target_function = Function::Handle( | 1414 const Function& target_function = Function::Handle( |
| 1415 caller_code.GetStaticCallTargetFunctionAt(frame->pc())); | 1415 caller_code.GetStaticCallTargetFunctionAt(frame->pc())); |
| 1416 const Code& target_code = Code::Handle(target_function.CurrentCode()); | 1416 const Code& target_code = Code::Handle(target_function.CurrentCode()); |
| 1417 CodePatcher::PatchStaticCallAt(frame->pc(), target_code.EntryPoint()); | 1417 CodePatcher::PatchStaticCallAt(frame->pc(), target_code.EntryPoint()); |
| 1418 caller_code.SetStaticCallTargetCodeAt(frame->pc(), target_code); | 1418 caller_code.SetStaticCallTargetCodeAt(frame->pc(), target_code); |
| 1419 if (FLAG_trace_patching) { | 1419 if (FLAG_trace_patching) { |
| 1420 OS::Print("FixCallersTarget: patching from %#"Px" to '%s' %#"Px"\n", | 1420 OS::PrintErr("FixCallersTarget: patching from %#"Px" to '%s' %#"Px"\n", |
| 1421 frame->pc(), | 1421 frame->pc(), |
| 1422 Function::Handle(target_code.function()).ToFullyQualifiedCString(), | 1422 Function::Handle(target_code.function()).ToFullyQualifiedCString(), |
| 1423 target_code.EntryPoint()); | 1423 target_code.EntryPoint()); |
| 1424 } | 1424 } |
| 1425 arguments.SetReturn(target_code); | 1425 arguments.SetReturn(target_code); |
| 1426 } | 1426 } |
| 1427 | 1427 |
| 1428 | 1428 |
| 1429 const char* DeoptReasonToText(intptr_t deopt_id) { | 1429 const char* DeoptReasonToText(intptr_t deopt_id) { |
| 1430 switch (deopt_id) { | 1430 switch (deopt_id) { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1601 | 1601 |
| 1602 DeoptInfo& deopt_info = DeoptInfo::Handle(); | 1602 DeoptInfo& deopt_info = DeoptInfo::Handle(); |
| 1603 DeoptReasonId deopt_reason = kDeoptUnknown; | 1603 DeoptReasonId deopt_reason = kDeoptUnknown; |
| 1604 GetDeoptInfoAtPc(optimized_code, caller_frame->pc(), &deopt_info, | 1604 GetDeoptInfoAtPc(optimized_code, caller_frame->pc(), &deopt_info, |
| 1605 &deopt_reason); | 1605 &deopt_reason); |
| 1606 ASSERT(!deopt_info.IsNull()); | 1606 ASSERT(!deopt_info.IsNull()); |
| 1607 | 1607 |
| 1608 CopyFrame(optimized_code, *caller_frame); | 1608 CopyFrame(optimized_code, *caller_frame); |
| 1609 if (FLAG_trace_deoptimization) { | 1609 if (FLAG_trace_deoptimization) { |
| 1610 Function& function = Function::Handle(optimized_code.function()); | 1610 Function& function = Function::Handle(optimized_code.function()); |
| 1611 OS::Print("Deoptimizing (reason %d '%s') at pc %#"Px" '%s' (count %d)\n", | 1611 OS::PrintErr("Deoptimizing (reason %d '%s') at pc %#"Px" '%s' (count %d)\n", |
| 1612 deopt_reason, | 1612 deopt_reason, |
| 1613 DeoptReasonToText(deopt_reason), | 1613 DeoptReasonToText(deopt_reason), |
| 1614 caller_frame->pc(), | 1614 caller_frame->pc(), |
| 1615 function.ToFullyQualifiedCString(), | 1615 function.ToFullyQualifiedCString(), |
| 1616 function.deoptimization_counter()); | 1616 function.deoptimization_counter()); |
| 1617 } | 1617 } |
| 1618 | 1618 |
| 1619 // Compute the stack size of the unoptimized frame. For functions with | 1619 // Compute the stack size of the unoptimized frame. For functions with |
| 1620 // optional arguments the deoptimization info does not describe the | 1620 // optional arguments the deoptimization info does not describe the |
| 1621 // incoming arguments. | 1621 // incoming arguments. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1653 DeoptimizationContext deopt_context(start, | 1653 DeoptimizationContext deopt_context(start, |
| 1654 to_frame_size, | 1654 to_frame_size, |
| 1655 Array::Handle(code.object_table()), | 1655 Array::Handle(code.object_table()), |
| 1656 num_args, | 1656 num_args, |
| 1657 deopt_reason); | 1657 deopt_reason); |
| 1658 for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { | 1658 for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { |
| 1659 deopt_instructions[to_index]->Execute(&deopt_context, to_index); | 1659 deopt_instructions[to_index]->Execute(&deopt_context, to_index); |
| 1660 } | 1660 } |
| 1661 if (FLAG_trace_deoptimization_verbose) { | 1661 if (FLAG_trace_deoptimization_verbose) { |
| 1662 for (intptr_t i = 0; i < len; i++) { | 1662 for (intptr_t i = 0; i < len; i++) { |
| 1663 OS::Print("*%"Pd". [%p] %#014"Px" [%s]\n", | 1663 OS::PrintErr("*%"Pd". [%p] %#014"Px" [%s]\n", |
| 1664 i, | 1664 i, |
| 1665 &start[i], | 1665 &start[i], |
| 1666 start[i], | 1666 start[i], |
| 1667 deopt_instructions[i]->ToCString()); | 1667 deopt_instructions[i]->ToCString()); |
| 1668 } | 1668 } |
| 1669 } | 1669 } |
| 1670 return deopt_context.GetCallerFp(); | 1670 return deopt_context.GetCallerFp(); |
| 1671 } | 1671 } |
| 1672 | 1672 |
| 1673 | 1673 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1719 DeferredDouble* deferred_double = Isolate::Current()->DetachDeferredDoubles(); | 1719 DeferredDouble* deferred_double = Isolate::Current()->DetachDeferredDoubles(); |
| 1720 | 1720 |
| 1721 while (deferred_double != NULL) { | 1721 while (deferred_double != NULL) { |
| 1722 DeferredDouble* current = deferred_double; | 1722 DeferredDouble* current = deferred_double; |
| 1723 deferred_double = deferred_double->next(); | 1723 deferred_double = deferred_double->next(); |
| 1724 | 1724 |
| 1725 RawDouble** slot = current->slot(); | 1725 RawDouble** slot = current->slot(); |
| 1726 *slot = Double::New(current->value()); | 1726 *slot = Double::New(current->value()); |
| 1727 | 1727 |
| 1728 if (FLAG_trace_deoptimization_verbose) { | 1728 if (FLAG_trace_deoptimization_verbose) { |
| 1729 OS::Print("materializing double at %"Px": %g\n", | 1729 OS::PrintErr("materializing double at %"Px": %g\n", |
| 1730 reinterpret_cast<uword>(current->slot()), | 1730 reinterpret_cast<uword>(current->slot()), |
| 1731 current->value()); | 1731 current->value()); |
| 1732 } | 1732 } |
| 1733 | 1733 |
| 1734 delete current; | 1734 delete current; |
| 1735 } | 1735 } |
| 1736 | 1736 |
| 1737 DeferredMint* deferred_mint = Isolate::Current()->DetachDeferredMints(); | 1737 DeferredMint* deferred_mint = Isolate::Current()->DetachDeferredMints(); |
| 1738 | 1738 |
| 1739 while (deferred_mint != NULL) { | 1739 while (deferred_mint != NULL) { |
| 1740 DeferredMint* current = deferred_mint; | 1740 DeferredMint* current = deferred_mint; |
| 1741 deferred_mint = deferred_mint->next(); | 1741 deferred_mint = deferred_mint->next(); |
| 1742 | 1742 |
| 1743 RawMint** slot = current->slot(); | 1743 RawMint** slot = current->slot(); |
| 1744 ASSERT(!Smi::IsValid64(current->value())); | 1744 ASSERT(!Smi::IsValid64(current->value())); |
| 1745 *slot = Mint::New(current->value()); | 1745 *slot = Mint::New(current->value()); |
| 1746 | 1746 |
| 1747 if (FLAG_trace_deoptimization_verbose) { | 1747 if (FLAG_trace_deoptimization_verbose) { |
| 1748 OS::Print("materializing mint at %"Px": %"Pd64"\n", | 1748 OS::PrintErr("materializing mint at %"Px": %"Pd64"\n", |
| 1749 reinterpret_cast<uword>(current->slot()), | 1749 reinterpret_cast<uword>(current->slot()), |
| 1750 current->value()); | 1750 current->value()); |
| 1751 } | 1751 } |
| 1752 | 1752 |
| 1753 delete current; | 1753 delete current; |
| 1754 } | 1754 } |
| 1755 // Since this is the only step where GC can occur during deoptimization, | 1755 // Since this is the only step where GC can occur during deoptimization, |
| 1756 // use it to report the source line where deoptimization occured. | 1756 // use it to report the source line where deoptimization occured. |
| 1757 if (FLAG_trace_deoptimization) { | 1757 if (FLAG_trace_deoptimization) { |
| 1758 DartFrameIterator iterator; | 1758 DartFrameIterator iterator; |
| 1759 StackFrame* top_frame = iterator.NextFrame(); | 1759 StackFrame* top_frame = iterator.NextFrame(); |
| 1760 ASSERT(top_frame != NULL); | 1760 ASSERT(top_frame != NULL); |
| 1761 const Code& code = Code::Handle(top_frame->LookupDartCode()); | 1761 const Code& code = Code::Handle(top_frame->LookupDartCode()); |
| 1762 const Function& top_function = Function::Handle(code.function()); | 1762 const Function& top_function = Function::Handle(code.function()); |
| 1763 const Script& script = Script::Handle(top_function.script()); | 1763 const Script& script = Script::Handle(top_function.script()); |
| 1764 const intptr_t token_pos = code.GetTokenIndexOfPC(top_frame->pc()); | 1764 const intptr_t token_pos = code.GetTokenIndexOfPC(top_frame->pc()); |
| 1765 intptr_t line, column; | 1765 intptr_t line, column; |
| 1766 script.GetTokenLocation(token_pos, &line, &column); | 1766 script.GetTokenLocation(token_pos, &line, &column); |
| 1767 String& line_string = String::Handle(script.GetLine(line)); | 1767 String& line_string = String::Handle(script.GetLine(line)); |
| 1768 OS::Print(" Function: %s\n", top_function.ToFullyQualifiedCString()); | 1768 OS::PrintErr(" Function: %s\n", top_function.ToFullyQualifiedCString()); |
| 1769 OS::Print(" Line %"Pd": '%s'\n", line, line_string.ToCString()); | 1769 OS::PrintErr(" Line %"Pd": '%s'\n", line, line_string.ToCString()); |
| 1770 } | 1770 } |
| 1771 } | 1771 } |
| 1772 | 1772 |
| 1773 | 1773 |
| 1774 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, | 1774 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, |
| 1775 BigintCompare, | 1775 BigintCompare, |
| 1776 RawBigint* left, | 1776 RawBigint* left, |
| 1777 RawBigint* right) { | 1777 RawBigint* right) { |
| 1778 Isolate* isolate = Isolate::Current(); | 1778 Isolate* isolate = Isolate::Current(); |
| 1779 StackZone zone(isolate); | 1779 StackZone zone(isolate); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1794 return; | 1794 return; |
| 1795 } | 1795 } |
| 1796 HeapTrace* heap_trace = Isolate::Current()->heap()->trace(); | 1796 HeapTrace* heap_trace = Isolate::Current()->heap()->trace(); |
| 1797 heap_trace->TraceStoreIntoObject(RawObject::ToAddr(object), | 1797 heap_trace->TraceStoreIntoObject(RawObject::ToAddr(object), |
| 1798 field_addr, | 1798 field_addr, |
| 1799 RawObject::ToAddr(value)); | 1799 RawObject::ToAddr(value)); |
| 1800 } | 1800 } |
| 1801 END_LEAF_RUNTIME_ENTRY | 1801 END_LEAF_RUNTIME_ENTRY |
| 1802 | 1802 |
| 1803 } // namespace dart | 1803 } // namespace dart |
| OLD | NEW |