| 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 |