Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 ASSERT(class_ids.length() == 2); | 243 ASSERT(class_ids.length() == 2); |
| 244 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || | 244 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || |
| 245 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { | 245 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { |
| 246 return false; | 246 return false; |
| 247 } | 247 } |
| 248 } | 248 } |
| 249 return true; | 249 return true; |
| 250 } | 250 } |
| 251 | 251 |
| 252 | 252 |
| 253 static bool HasOneSmi(const ICData& ic_data) { | 253 static bool HasOnlyOneSmi(const ICData& ic_data) { |
| 254 return ICDataHasReceiverClassId(ic_data, kSmiCid); | 254 return (ic_data.NumberOfChecks() == 1) |
| 255 && ICDataHasReceiverClassId(ic_data, kSmiCid); | |
| 256 } | |
| 257 | |
| 258 | |
| 259 static bool HasOnlySmiOrMint(const ICData& ic_data) { | |
| 260 if (ic_data.NumberOfChecks() == 1) { | |
| 261 return ICDataHasReceiverClassId(ic_data, kSmiCid) | |
| 262 || ICDataHasReceiverClassId(ic_data, kMintCid); | |
| 263 } | |
| 264 return (ic_data.NumberOfChecks() == 2) | |
| 265 && ICDataHasReceiverClassId(ic_data, kSmiCid) | |
| 266 && ICDataHasReceiverClassId(ic_data, kMintCid); | |
| 255 } | 267 } |
| 256 | 268 |
| 257 | 269 |
| 258 static bool HasOnlyTwoSmi(const ICData& ic_data) { | 270 static bool HasOnlyTwoSmi(const ICData& ic_data) { |
| 259 return (ic_data.NumberOfChecks() == 1) && | 271 return (ic_data.NumberOfChecks() == 1) && |
| 260 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); | 272 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); |
| 261 } | 273 } |
| 262 | 274 |
| 263 | 275 |
| 264 // Returns false if the ICData contains anything other than the 4 combinations | 276 // Returns false if the ICData contains anything other than the 4 combinations |
| 265 // of Mint and Smi for the receiver and argument classes. | 277 // of Mint and Smi for the receiver and argument classes. |
| 266 static bool HasTwoMintOrSmi(const ICData& ic_data) { | 278 static bool HasTwoMintOrSmi(const ICData& ic_data) { |
| 267 GrowableArray<intptr_t> class_ids(2); | 279 GrowableArray<intptr_t> class_ids(2); |
| 268 class_ids.Add(kSmiCid); | 280 class_ids.Add(kSmiCid); |
| 269 class_ids.Add(kMintCid); | 281 class_ids.Add(kMintCid); |
| 270 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); | 282 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); |
| 271 } | 283 } |
| 272 | 284 |
| 273 | 285 |
| 274 static bool HasOneDouble(const ICData& ic_data) { | 286 static bool HasOnlyOneDouble(const ICData& ic_data) { |
| 275 return ICDataHasReceiverClassId(ic_data, kDoubleCid); | 287 return (ic_data.NumberOfChecks() == 1) |
| 288 && ICDataHasReceiverClassId(ic_data, kDoubleCid); | |
| 276 } | 289 } |
| 277 | 290 |
| 278 | 291 |
| 279 static bool ShouldSpecializeForDouble(const ICData& ic_data) { | 292 static bool ShouldSpecializeForDouble(const ICData& ic_data) { |
| 280 // Unboxed double operation can't handle case of two smis. | 293 // Unboxed double operation can't handle case of two smis. |
| 281 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { | 294 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { |
| 282 return false; | 295 return false; |
| 283 } | 296 } |
| 284 | 297 |
| 285 // Check that it have seen only smis and doubles. | 298 // Check that it have seen only smis and doubles. |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 585 BinarySmiOpInstr* bin_op = new BinarySmiOpInstr(op_kind, call, left, right); | 598 BinarySmiOpInstr* bin_op = new BinarySmiOpInstr(op_kind, call, left, right); |
| 586 call->ReplaceWith(bin_op, current_iterator()); | 599 call->ReplaceWith(bin_op, current_iterator()); |
| 587 RemovePushArguments(call); | 600 RemovePushArguments(call); |
| 588 } | 601 } |
| 589 return true; | 602 return true; |
| 590 } | 603 } |
| 591 | 604 |
| 592 | 605 |
| 593 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, | 606 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, |
| 594 Token::Kind op_kind) { | 607 Token::Kind op_kind) { |
| 595 if (call->ic_data()->NumberOfChecks() != 1) { | |
| 596 // TODO(srdjan): Not yet supported. | |
| 597 return false; | |
| 598 } | |
| 599 ASSERT(call->ArgumentCount() == 1); | 608 ASSERT(call->ArgumentCount() == 1); |
| 600 Definition* unary_op = NULL; | 609 Definition* unary_op = NULL; |
| 601 if (HasOneSmi(*call->ic_data())) { | 610 if (HasOnlyOneSmi(*call->ic_data())) { |
| 602 Value* value = call->ArgumentAt(0)->value(); | 611 Value* value = call->ArgumentAt(0)->value(); |
| 603 InsertBefore(call, | 612 InsertBefore(call, |
| 604 new CheckSmiInstr(value->Copy(), call->deopt_id()), | 613 new CheckSmiInstr(value->Copy(), call->deopt_id()), |
| 605 call->env(), | 614 call->env(), |
| 606 Definition::kEffect); | 615 Definition::kEffect); |
| 607 unary_op = new UnarySmiOpInstr(op_kind, | 616 unary_op = new UnarySmiOpInstr(op_kind, |
| 608 (op_kind == Token::kNEGATE) ? call : NULL, | 617 (op_kind == Token::kNEGATE) ? call : NULL, |
| 609 value); | 618 value); |
| 610 } else if (HasOneDouble(*call->ic_data()) && (op_kind == Token::kNEGATE)) { | 619 } else if ((op_kind == Token::kBIT_NOT) && |
| 620 HasOnlySmiOrMint(*call->ic_data()) && | |
| 621 FlowGraphCompiler::SupportsUnboxedMints()) { | |
| 622 Value* value = call->ArgumentAt(0)->value(); | |
| 623 unary_op = new UnboxedMintUnaryOpInstr(op_kind, value, call); | |
| 624 } else if (HasOnlyOneDouble(*call->ic_data()) && | |
| 625 (op_kind == Token::kNEGATE)) { | |
| 611 Value* value = call->ArgumentAt(0)->value(); | 626 Value* value = call->ArgumentAt(0)->value(); |
| 612 AddCheckClass(call, value->Copy()); | 627 AddCheckClass(call, value->Copy()); |
| 613 ConstantInstr* minus_one = | 628 ConstantInstr* minus_one = |
| 614 new ConstantInstr(Double::ZoneHandle(Double::NewCanonical(-1))); | 629 new ConstantInstr(Double::ZoneHandle(Double::NewCanonical(-1))); |
| 615 InsertBefore(call, minus_one, NULL, Definition::kValue); | 630 InsertBefore(call, minus_one, NULL, Definition::kValue); |
| 616 unary_op = new UnboxedDoubleBinaryOpInstr(Token::kMUL, | 631 unary_op = new UnboxedDoubleBinaryOpInstr(Token::kMUL, |
| 617 value, | 632 value, |
| 618 new Value(minus_one), | 633 new Value(minus_one), |
| 619 call); | 634 call); |
| 620 } | 635 } |
| (...skipping 2285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2906 } | 2921 } |
| 2907 | 2922 |
| 2908 | 2923 |
| 2909 void ConstantPropagator::VisitUnboxedMintBinaryOp( | 2924 void ConstantPropagator::VisitUnboxedMintBinaryOp( |
| 2910 UnboxedMintBinaryOpInstr* instr) { | 2925 UnboxedMintBinaryOpInstr* instr) { |
| 2911 // TODO(kmillikin): Handle binary operations. | 2926 // TODO(kmillikin): Handle binary operations. |
| 2912 SetValue(instr, non_constant_); | 2927 SetValue(instr, non_constant_); |
| 2913 } | 2928 } |
| 2914 | 2929 |
| 2915 | 2930 |
| 2931 void ConstantPropagator::VisitUnboxedMintUnaryOp( | |
| 2932 UnboxedMintUnaryOpInstr* instr) { | |
| 2933 // TODO(kmillikin): Handle unary operations. | |
|
Kevin Millikin (Google)
2012/10/04 11:56:06
TODO(fschneider) :)
| |
| 2934 SetValue(instr, non_constant_); | |
| 2935 } | |
| 2936 | |
| 2937 | |
| 2916 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { | 2938 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { |
| 2917 const Object& value = instr->value()->definition()->constant_value(); | 2939 const Object& value = instr->value()->definition()->constant_value(); |
| 2918 if (IsNonConstant(value)) { | 2940 if (IsNonConstant(value)) { |
| 2919 SetValue(instr, non_constant_); | 2941 SetValue(instr, non_constant_); |
| 2920 } else if (IsConstant(value)) { | 2942 } else if (IsConstant(value)) { |
| 2921 // TODO(kmillikin): Handle unary operations. | 2943 // TODO(kmillikin): Handle unary operations. |
| 2922 SetValue(instr, non_constant_); | 2944 SetValue(instr, non_constant_); |
| 2923 } | 2945 } |
| 2924 } | 2946 } |
| 2925 | 2947 |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3149 | 3171 |
| 3150 if (FLAG_trace_constant_propagation) { | 3172 if (FLAG_trace_constant_propagation) { |
| 3151 OS::Print("\n==== After constant propagation ====\n"); | 3173 OS::Print("\n==== After constant propagation ====\n"); |
| 3152 FlowGraphPrinter printer(*graph_); | 3174 FlowGraphPrinter printer(*graph_); |
| 3153 printer.PrintBlocks(); | 3175 printer.PrintBlocks(); |
| 3154 } | 3176 } |
| 3155 } | 3177 } |
| 3156 | 3178 |
| 3157 | 3179 |
| 3158 } // namespace dart | 3180 } // namespace dart |
| OLD | NEW |