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/aot_optimizer.h" | 5 #include "vm/aot_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 1293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 field = cls.LookupInstanceField(field_name); | 1304 field = cls.LookupInstanceField(field_name); |
1305 if (!field.IsNull()) { | 1305 if (!field.IsNull()) { |
1306 return field.raw(); | 1306 return field.raw(); |
1307 } | 1307 } |
1308 cls = cls.SuperClass(); | 1308 cls = cls.SuperClass(); |
1309 } | 1309 } |
1310 return Field::null(); | 1310 return Field::null(); |
1311 } | 1311 } |
1312 | 1312 |
1313 | 1313 |
1314 // Use CHA to determine if the call needs a class check: if the callee's | |
1315 // receiver is the same as the caller's receiver and there are no overriden | |
1316 // callee functions, then no class check is needed. | |
1317 bool AotOptimizer::InstanceCallNeedsClassCheck( | |
1318 InstanceCallInstr* call, RawFunction::Kind kind) const { | |
1319 if (!FLAG_use_cha_deopt && !isolate()->all_classes_finalized()) { | |
1320 // Even if class or function are private, lazy class finalization | |
1321 // may later add overriding methods. | |
1322 return true; | |
1323 } | |
1324 Definition* callee_receiver = call->ArgumentAt(0); | |
1325 ASSERT(callee_receiver != NULL); | |
1326 const Function& function = flow_graph_->function(); | |
1327 if (function.IsDynamicFunction() && | |
1328 callee_receiver->IsParameter() && | |
1329 (callee_receiver->AsParameter()->index() == 0)) { | |
1330 const String& name = (kind == RawFunction::kMethodExtractor) | |
1331 ? String::Handle(Z, Field::NameFromGetter(call->function_name())) | |
1332 : call->function_name(); | |
1333 const Class& cls = Class::Handle(Z, function.Owner()); | |
1334 if (!thread()->cha()->HasOverride(cls, name)) { | |
1335 if (FLAG_trace_cha) { | |
1336 THR_Print(" **(CHA) Instance call needs no check, " | |
1337 "no overrides of '%s' '%s'\n", | |
1338 name.ToCString(), cls.ToCString()); | |
1339 } | |
1340 thread()->cha()->AddToLeafClasses(cls); | |
1341 return false; | |
1342 } | |
1343 } | |
1344 return true; | |
1345 } | |
1346 | |
1347 | |
1348 bool AotOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { | 1314 bool AotOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { |
1349 ASSERT(call->HasICData()); | 1315 ASSERT(call->HasICData()); |
1350 const ICData& ic_data = *call->ic_data(); | 1316 const ICData& ic_data = *call->ic_data(); |
1351 ASSERT(ic_data.HasOneTarget()); | 1317 ASSERT(ic_data.HasOneTarget()); |
1352 GrowableArray<intptr_t> class_ids; | 1318 GrowableArray<intptr_t> class_ids; |
1353 ic_data.GetClassIdsAt(0, &class_ids); | 1319 ic_data.GetClassIdsAt(0, &class_ids); |
1354 ASSERT(class_ids.length() == 1); | 1320 ASSERT(class_ids.length() == 1); |
1355 // Inline implicit instance getter. | 1321 // Inline implicit instance getter. |
1356 const String& field_name = | 1322 const String& field_name = |
1357 String::Handle(Z, Field::NameFromGetter(call->function_name())); | 1323 String::Handle(Z, Field::NameFromGetter(call->function_name())); |
1358 const Field& field = | 1324 const Field& field = |
1359 Field::ZoneHandle(Z, GetField(class_ids[0], field_name)); | 1325 Field::ZoneHandle(Z, GetField(class_ids[0], field_name)); |
1360 ASSERT(!field.IsNull()); | 1326 ASSERT(!field.IsNull()); |
1361 | 1327 |
1362 if (InstanceCallNeedsClassCheck(call, RawFunction::kImplicitGetter)) { | 1328 if (flow_graph()->InstanceCallNeedsClassCheck( |
| 1329 call, RawFunction::kImplicitGetter)) { |
1363 return false; | 1330 return false; |
1364 } | 1331 } |
1365 LoadFieldInstr* load = new(Z) LoadFieldInstr( | 1332 LoadFieldInstr* load = new(Z) LoadFieldInstr( |
1366 new(Z) Value(call->ArgumentAt(0)), | 1333 new(Z) Value(call->ArgumentAt(0)), |
1367 &field, | 1334 &field, |
1368 AbstractType::ZoneHandle(Z, field.type()), | 1335 AbstractType::ZoneHandle(Z, field.type()), |
1369 call->token_pos()); | 1336 call->token_pos()); |
1370 load->set_is_immutable(field.is_final()); | 1337 load->set_is_immutable(field.is_final()); |
1371 | 1338 |
1372 // Discard the environment from the original instruction because the load | 1339 // Discard the environment from the original instruction because the load |
(...skipping 1090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2463 // we don't have one target. | 2430 // we don't have one target. |
2464 const Function& target = | 2431 const Function& target = |
2465 Function::Handle(Z, unary_checks.GetTargetAt(0)); | 2432 Function::Handle(Z, unary_checks.GetTargetAt(0)); |
2466 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); | 2433 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); |
2467 has_one_target = !polymorphic_target; | 2434 has_one_target = !polymorphic_target; |
2468 } | 2435 } |
2469 | 2436 |
2470 if (has_one_target) { | 2437 if (has_one_target) { |
2471 RawFunction::Kind function_kind = | 2438 RawFunction::Kind function_kind = |
2472 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); | 2439 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); |
2473 if (!InstanceCallNeedsClassCheck(instr, function_kind)) { | 2440 if (!flow_graph()->InstanceCallNeedsClassCheck( |
| 2441 instr, function_kind)) { |
2474 PolymorphicInstanceCallInstr* call = | 2442 PolymorphicInstanceCallInstr* call = |
2475 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2443 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
2476 /* with_checks = */ false); | 2444 /* with_checks = */ false); |
2477 instr->ReplaceWith(call, current_iterator()); | 2445 instr->ReplaceWith(call, current_iterator()); |
2478 return; | 2446 return; |
2479 } | 2447 } |
2480 } | 2448 } |
2481 switch (instr->token_kind()) { | 2449 switch (instr->token_kind()) { |
2482 case Token::kEQ: | 2450 case Token::kEQ: |
2483 case Token::kLT: | 2451 case Token::kLT: |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2764 // Non-implicit setter are inlined like normal method calls. | 2732 // Non-implicit setter are inlined like normal method calls. |
2765 return false; | 2733 return false; |
2766 } | 2734 } |
2767 // Inline implicit instance setter. | 2735 // Inline implicit instance setter. |
2768 const String& field_name = | 2736 const String& field_name = |
2769 String::Handle(Z, Field::NameFromSetter(instr->function_name())); | 2737 String::Handle(Z, Field::NameFromSetter(instr->function_name())); |
2770 const Field& field = | 2738 const Field& field = |
2771 Field::ZoneHandle(Z, GetField(class_id, field_name)); | 2739 Field::ZoneHandle(Z, GetField(class_id, field_name)); |
2772 ASSERT(!field.IsNull()); | 2740 ASSERT(!field.IsNull()); |
2773 | 2741 |
2774 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) { | 2742 if (flow_graph()->InstanceCallNeedsClassCheck( |
| 2743 instr, RawFunction::kImplicitSetter)) { |
2775 return false; | 2744 return false; |
2776 } | 2745 } |
2777 | 2746 |
2778 // Field guard was detached. | 2747 // Field guard was detached. |
2779 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( | 2748 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( |
2780 field, | 2749 field, |
2781 new(Z) Value(instr->ArgumentAt(0)), | 2750 new(Z) Value(instr->ArgumentAt(0)), |
2782 new(Z) Value(instr->ArgumentAt(1)), | 2751 new(Z) Value(instr->ArgumentAt(1)), |
2783 kEmitStoreBarrier, | 2752 kEmitStoreBarrier, |
2784 instr->token_pos()); | 2753 instr->token_pos()); |
2785 | 2754 |
2786 // No unboxed stores in precompiled code. | 2755 // No unboxed stores in precompiled code. |
2787 ASSERT(!store->IsUnboxedStore()); | 2756 ASSERT(!store->IsUnboxedStore()); |
2788 | 2757 |
2789 // Discard the environment from the original instruction because the store | 2758 // Discard the environment from the original instruction because the store |
2790 // can't deoptimize. | 2759 // can't deoptimize. |
2791 instr->RemoveEnvironment(); | 2760 instr->RemoveEnvironment(); |
2792 ReplaceCall(instr, store); | 2761 ReplaceCall(instr, store); |
2793 return true; | 2762 return true; |
2794 } | 2763 } |
2795 | 2764 |
2796 | 2765 |
2797 } // namespace dart | 2766 } // namespace dart |
OLD | NEW |