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/jit_optimizer.h" | 5 #include "vm/jit_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 1265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1276 } else { | 1276 } else { |
1277 return field.raw(); | 1277 return field.raw(); |
1278 } | 1278 } |
1279 } | 1279 } |
1280 cls = cls.SuperClass(); | 1280 cls = cls.SuperClass(); |
1281 } | 1281 } |
1282 return Field::null(); | 1282 return Field::null(); |
1283 } | 1283 } |
1284 | 1284 |
1285 | 1285 |
1286 // Use CHA to determine if the call needs a class check: if the callee's | |
1287 // receiver is the same as the caller's receiver and there are no overriden | |
1288 // callee functions, then no class check is needed. | |
1289 bool JitOptimizer::InstanceCallNeedsClassCheck( | |
1290 InstanceCallInstr* call, RawFunction::Kind kind) const { | |
1291 if (!FLAG_use_cha_deopt && !isolate()->all_classes_finalized()) { | |
1292 // Even if class or function are private, lazy class finalization | |
1293 // may later add overriding methods. | |
1294 return true; | |
1295 } | |
1296 Definition* callee_receiver = call->ArgumentAt(0); | |
1297 ASSERT(callee_receiver != NULL); | |
1298 const Function& function = flow_graph_->function(); | |
1299 if (function.IsDynamicFunction() && | |
1300 callee_receiver->IsParameter() && | |
1301 (callee_receiver->AsParameter()->index() == 0)) { | |
1302 const String& name = (kind == RawFunction::kMethodExtractor) | |
1303 ? String::Handle(Z, Field::NameFromGetter(call->function_name())) | |
1304 : call->function_name(); | |
1305 const Class& cls = Class::Handle(Z, function.Owner()); | |
1306 if (!thread()->cha()->HasOverride(cls, name)) { | |
1307 if (FLAG_trace_cha) { | |
1308 THR_Print(" **(CHA) Instance call needs no check, " | |
1309 "no overrides of '%s' '%s'\n", | |
1310 name.ToCString(), cls.ToCString()); | |
1311 } | |
1312 thread()->cha()->AddToLeafClasses(cls); | |
1313 return false; | |
1314 } | |
1315 } | |
1316 return true; | |
1317 } | |
1318 | |
1319 | |
1320 bool JitOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { | 1286 bool JitOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { |
1321 ASSERT(call->HasICData()); | 1287 ASSERT(call->HasICData()); |
1322 const ICData& ic_data = *call->ic_data(); | 1288 const ICData& ic_data = *call->ic_data(); |
1323 ASSERT(ic_data.HasOneTarget()); | 1289 ASSERT(ic_data.HasOneTarget()); |
1324 GrowableArray<intptr_t> class_ids; | 1290 GrowableArray<intptr_t> class_ids; |
1325 ic_data.GetClassIdsAt(0, &class_ids); | 1291 ic_data.GetClassIdsAt(0, &class_ids); |
1326 ASSERT(class_ids.length() == 1); | 1292 ASSERT(class_ids.length() == 1); |
1327 // Inline implicit instance getter. | 1293 // Inline implicit instance getter. |
1328 const String& field_name = | 1294 const String& field_name = |
1329 String::Handle(Z, Field::NameFromGetter(call->function_name())); | 1295 String::Handle(Z, Field::NameFromGetter(call->function_name())); |
1330 const Field& field = | 1296 const Field& field = |
1331 Field::ZoneHandle(Z, GetField(class_ids[0], field_name)); | 1297 Field::ZoneHandle(Z, GetField(class_ids[0], field_name)); |
1332 ASSERT(!field.IsNull()); | 1298 ASSERT(!field.IsNull()); |
1333 | 1299 |
1334 if (InstanceCallNeedsClassCheck(call, RawFunction::kImplicitGetter)) { | 1300 if (flow_graph()->InstanceCallNeedsClassCheck( |
| 1301 call, RawFunction::kImplicitGetter)) { |
1335 AddReceiverCheck(call); | 1302 AddReceiverCheck(call); |
1336 } | 1303 } |
1337 LoadFieldInstr* load = new(Z) LoadFieldInstr( | 1304 LoadFieldInstr* load = new(Z) LoadFieldInstr( |
1338 new(Z) Value(call->ArgumentAt(0)), | 1305 new(Z) Value(call->ArgumentAt(0)), |
1339 &field, | 1306 &field, |
1340 AbstractType::ZoneHandle(Z, field.type()), | 1307 AbstractType::ZoneHandle(Z, field.type()), |
1341 call->token_pos()); | 1308 call->token_pos()); |
1342 load->set_is_immutable(field.is_final()); | 1309 load->set_is_immutable(field.is_final()); |
1343 if (field.guarded_cid() != kIllegalCid) { | 1310 if (field.guarded_cid() != kIllegalCid) { |
1344 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { | 1311 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { |
(...skipping 1375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2720 return; | 2687 return; |
2721 } | 2688 } |
2722 | 2689 |
2723 const ICData& unary_checks = | 2690 const ICData& unary_checks = |
2724 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); | 2691 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); |
2725 | 2692 |
2726 const intptr_t max_checks = (op_kind == Token::kEQ) | 2693 const intptr_t max_checks = (op_kind == Token::kEQ) |
2727 ? FLAG_max_equality_polymorphic_checks | 2694 ? FLAG_max_equality_polymorphic_checks |
2728 : FLAG_max_polymorphic_checks; | 2695 : FLAG_max_polymorphic_checks; |
2729 if ((unary_checks.NumberOfChecks() > max_checks) && | 2696 if ((unary_checks.NumberOfChecks() > max_checks) && |
2730 InstanceCallNeedsClassCheck(instr, RawFunction::kRegularFunction)) { | 2697 flow_graph()->InstanceCallNeedsClassCheck( |
| 2698 instr, RawFunction::kRegularFunction)) { |
2731 // Too many checks, it will be megamorphic which needs unary checks. | 2699 // Too many checks, it will be megamorphic which needs unary checks. |
2732 instr->set_ic_data(&unary_checks); | 2700 instr->set_ic_data(&unary_checks); |
2733 return; | 2701 return; |
2734 } | 2702 } |
2735 | 2703 |
2736 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { | 2704 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { |
2737 return; | 2705 return; |
2738 } | 2706 } |
2739 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { | 2707 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { |
2740 return; | 2708 return; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2775 // we don't have one target. | 2743 // we don't have one target. |
2776 const Function& target = | 2744 const Function& target = |
2777 Function::Handle(Z, unary_checks.GetTargetAt(0)); | 2745 Function::Handle(Z, unary_checks.GetTargetAt(0)); |
2778 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); | 2746 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); |
2779 has_one_target = !polymorphic_target; | 2747 has_one_target = !polymorphic_target; |
2780 } | 2748 } |
2781 | 2749 |
2782 if (has_one_target) { | 2750 if (has_one_target) { |
2783 RawFunction::Kind function_kind = | 2751 RawFunction::Kind function_kind = |
2784 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); | 2752 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); |
2785 if (!InstanceCallNeedsClassCheck(instr, function_kind)) { | 2753 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { |
2786 PolymorphicInstanceCallInstr* call = | 2754 PolymorphicInstanceCallInstr* call = |
2787 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2755 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
2788 /* call_with_checks = */ false); | 2756 /* call_with_checks = */ false); |
2789 instr->ReplaceWith(call, current_iterator()); | 2757 instr->ReplaceWith(call, current_iterator()); |
2790 return; | 2758 return; |
2791 } | 2759 } |
2792 } | 2760 } |
2793 | 2761 |
2794 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { | 2762 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { |
2795 bool call_with_checks; | 2763 bool call_with_checks; |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3107 // Non-implicit setter are inlined like normal method calls. | 3075 // Non-implicit setter are inlined like normal method calls. |
3108 return false; | 3076 return false; |
3109 } | 3077 } |
3110 // Inline implicit instance setter. | 3078 // Inline implicit instance setter. |
3111 const String& field_name = | 3079 const String& field_name = |
3112 String::Handle(Z, Field::NameFromSetter(instr->function_name())); | 3080 String::Handle(Z, Field::NameFromSetter(instr->function_name())); |
3113 const Field& field = | 3081 const Field& field = |
3114 Field::ZoneHandle(Z, GetField(class_id, field_name)); | 3082 Field::ZoneHandle(Z, GetField(class_id, field_name)); |
3115 ASSERT(!field.IsNull()); | 3083 ASSERT(!field.IsNull()); |
3116 | 3084 |
3117 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) { | 3085 if (flow_graph()->InstanceCallNeedsClassCheck( |
| 3086 instr, RawFunction::kImplicitSetter)) { |
3118 AddReceiverCheck(instr); | 3087 AddReceiverCheck(instr); |
3119 } | 3088 } |
3120 if (field.guarded_cid() != kDynamicCid) { | 3089 if (field.guarded_cid() != kDynamicCid) { |
3121 InsertBefore(instr, | 3090 InsertBefore(instr, |
3122 new(Z) GuardFieldClassInstr( | 3091 new(Z) GuardFieldClassInstr( |
3123 new(Z) Value(instr->ArgumentAt(1)), | 3092 new(Z) Value(instr->ArgumentAt(1)), |
3124 field, | 3093 field, |
3125 instr->deopt_id()), | 3094 instr->deopt_id()), |
3126 instr->env(), | 3095 instr->env(), |
3127 FlowGraph::kEffect); | 3096 FlowGraph::kEffect); |
(...skipping 23 matching lines...) Expand all Loading... |
3151 | 3120 |
3152 // Discard the environment from the original instruction because the store | 3121 // Discard the environment from the original instruction because the store |
3153 // can't deoptimize. | 3122 // can't deoptimize. |
3154 instr->RemoveEnvironment(); | 3123 instr->RemoveEnvironment(); |
3155 ReplaceCall(instr, store); | 3124 ReplaceCall(instr, store); |
3156 return true; | 3125 return true; |
3157 } | 3126 } |
3158 | 3127 |
3159 | 3128 |
3160 } // namespace dart | 3129 } // namespace dart |
OLD | NEW |