Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1034)

Side by Side Diff: runtime/vm/jit_optimizer.cc

Issue 1841073003: VM: Fix receiver type propagation in presence of try-catch. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: addressed comments, added test Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698