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

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

Issue 1175803003: Inline instanceOf and 'as' operations; fix a bug in code emission (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: c Created 5 years, 6 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
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 4070 matching lines...) Expand 10 before | Expand all | Expand 10 after
4081 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); 4081 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
4082 if (FLAG_warn_on_javascript_compatibility && 4082 if (FLAG_warn_on_javascript_compatibility &&
4083 !unary_checks.IssuedJSWarning() && 4083 !unary_checks.IssuedJSWarning() &&
4084 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { 4084 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
4085 // No warning was reported yet for this type check, either because it has 4085 // No warning was reported yet for this type check, either because it has
4086 // not been executed yet, or because no problematic combinations of instance 4086 // not been executed yet, or because no problematic combinations of instance
4087 // type and test type have been encountered so far. A warning may still be 4087 // type and test type have been encountered so far. A warning may still be
4088 // reported, so do not replace the instance call. 4088 // reported, so do not replace the instance call.
4089 return; 4089 return;
4090 } 4090 }
4091 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 4091 if ((unary_checks.NumberOfChecks() > 0) &&
4092 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
4092 ZoneGrowableArray<intptr_t>* results = 4093 ZoneGrowableArray<intptr_t>* results =
4093 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); 4094 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
4094 Bool& as_bool = 4095 Bool& as_bool =
4095 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); 4096 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
4096 if (as_bool.IsNull()) { 4097 if (as_bool.IsNull()) {
4097 if (results->length() == unary_checks.NumberOfChecks() * 2) { 4098 if (results->length() == unary_checks.NumberOfChecks() * 2) {
4098 const bool can_deopt = TryExpandTestCidsResult(results, type); 4099 const bool can_deopt = TryExpandTestCidsResult(results, type);
4099 TestCidsInstr* test_cids = new(Z) TestCidsInstr( 4100 TestCidsInstr* test_cids = new(Z) TestCidsInstr(
4100 call->token_pos(), 4101 call->token_pos(),
4101 negate ? Token::kISNOT : Token::kIS, 4102 negate ? Token::kISNOT : Token::kIS,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
4172 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); 4173 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
4173 if (FLAG_warn_on_javascript_compatibility && 4174 if (FLAG_warn_on_javascript_compatibility &&
4174 !unary_checks.IssuedJSWarning() && 4175 !unary_checks.IssuedJSWarning() &&
4175 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) { 4176 (type.IsIntType() || type.IsDoubleType() || !type.IsInstantiated())) {
4176 // No warning was reported yet for this type check, either because it has 4177 // No warning was reported yet for this type check, either because it has
4177 // not been executed yet, or because no problematic combinations of instance 4178 // not been executed yet, or because no problematic combinations of instance
4178 // type and test type have been encountered so far. A warning may still be 4179 // type and test type have been encountered so far. A warning may still be
4179 // reported, so do not replace the instance call. 4180 // reported, so do not replace the instance call.
4180 return; 4181 return;
4181 } 4182 }
4182 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 4183 if ((unary_checks.NumberOfChecks() > 0) &&
4184 (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
4183 ZoneGrowableArray<intptr_t>* results = 4185 ZoneGrowableArray<intptr_t>* results =
4184 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2); 4186 new(Z) ZoneGrowableArray<intptr_t>(unary_checks.NumberOfChecks() * 2);
4185 const Bool& as_bool = Bool::ZoneHandle(Z, 4187 const Bool& as_bool = Bool::ZoneHandle(Z,
4186 InstanceOfAsBool(unary_checks, type, results)); 4188 InstanceOfAsBool(unary_checks, type, results));
4187 if (as_bool.raw() == Bool::True().raw()) { 4189 if (as_bool.raw() == Bool::True().raw()) {
4188 AddReceiverCheck(call); 4190 AddReceiverCheck(call);
4189 // Remove the original push arguments. 4191 // Remove the original push arguments.
4190 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 4192 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
4191 PushArgumentInstr* push = call->PushArgumentAt(i); 4193 PushArgumentInstr* push = call->PushArgumentAt(i);
4192 push->ReplaceUsesWith(push->value()->definition()); 4194 push->ReplaceUsesWith(push->value()->definition());
(...skipping 13 matching lines...) Expand all
4206 new(Z) Value(left), 4208 new(Z) Value(left),
4207 new(Z) Value(instantiator), 4209 new(Z) Value(instantiator),
4208 new(Z) Value(type_args), 4210 new(Z) Value(type_args),
4209 type, 4211 type,
4210 dst_name, 4212 dst_name,
4211 call->deopt_id()); 4213 call->deopt_id());
4212 ReplaceCall(call, assert_as); 4214 ReplaceCall(call, assert_as);
4213 } 4215 }
4214 4216
4215 4217
4218 // Special optimizations when running in --noopt mode.
4219 void FlowGraphOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) {
4220 // TODO(srdjan): Investigate other attempts, as they are not allowed to
4221 // deoptimize.
4222 const Token::Kind op_kind = instr->token_kind();
4223 if (instr->HasICData() && (instr->ic_data()->NumberOfUsedChecks() > 0)) {
4224 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, false)) {
4225 return;
4226 }
4227 }
4228
4229 // Type test is special as it always gets converted into inlined code.
4230 if (Token::IsTypeTestOperator(op_kind)) {
4231 ReplaceWithInstanceOf(instr);
4232 return;
4233 }
4234 if (Token::IsTypeCastOperator(op_kind)) {
4235 ReplaceWithTypeCast(instr);
4236 return;
4237 }
4238 }
4239
4240
4216 // Tries to optimize instance call by replacing it with a faster instruction 4241 // Tries to optimize instance call by replacing it with a faster instruction
4217 // (e.g, binary op, field load, ..). 4242 // (e.g, binary op, field load, ..).
4218 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { 4243 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
4244 if (Compiler::always_optimize()) {
4245 InstanceCallNoopt(instr);
4246 return;
4247 }
4248
4219 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { 4249 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) {
4220 return; 4250 return;
4221 } 4251 }
4222
4223 const Token::Kind op_kind = instr->token_kind(); 4252 const Token::Kind op_kind = instr->token_kind();
4224 if (Compiler::always_optimize()) {
4225 // TODO(srdjan): Investigate other attempts, as they are not allowed to
4226 // deoptimize.
4227 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, false)) {
4228 return;
4229 }
4230 return;
4231 }
4232 4253
4233 // Type test is special as it always gets converted into inlined code. 4254 // Type test is special as it always gets converted into inlined code.
4234 if (Token::IsTypeTestOperator(op_kind)) { 4255 if (Token::IsTypeTestOperator(op_kind)) {
4235 ReplaceWithInstanceOf(instr); 4256 ReplaceWithInstanceOf(instr);
4236 return; 4257 return;
4237 } 4258 }
4238 4259
4239 if (Token::IsTypeCastOperator(op_kind)) { 4260 if (Token::IsTypeCastOperator(op_kind)) {
4240 ReplaceWithTypeCast(instr); 4261 ReplaceWithTypeCast(instr);
4241 return; 4262 return;
(...skipping 4425 matching lines...) Expand 10 before | Expand all | Expand 10 after
8667 8688
8668 // Insert materializations at environment uses. 8689 // Insert materializations at environment uses.
8669 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 8690 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
8670 CreateMaterializationAt( 8691 CreateMaterializationAt(
8671 exits_collector_.exits()[i], alloc, *slots); 8692 exits_collector_.exits()[i], alloc, *slots);
8672 } 8693 }
8673 } 8694 }
8674 8695
8675 8696
8676 } // namespace dart 8697 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698