Chromium Code Reviews| 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/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 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 && ic_data.HasReceiverClassId(kSmiCid) | 524 && ic_data.HasReceiverClassId(kSmiCid) |
| 525 && ic_data.HasReceiverClassId(kMintCid); | 525 && ic_data.HasReceiverClassId(kMintCid); |
| 526 } | 526 } |
| 527 | 527 |
| 528 | 528 |
| 529 static bool HasOnlyTwoSmis(const ICData& ic_data) { | 529 static bool HasOnlyTwoSmis(const ICData& ic_data) { |
| 530 return (ic_data.NumberOfChecks() == 1) && | 530 return (ic_data.NumberOfChecks() == 1) && |
| 531 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); | 531 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); |
| 532 } | 532 } |
| 533 | 533 |
| 534 static bool HasOnlyTwoFloat32x4s(const ICData& ic_data) { | |
| 535 return (ic_data.NumberOfChecks() == 1) && | |
| 536 ICDataHasReceiverArgumentClassIds(ic_data, kFloat32x4Cid, kFloat32x4Cid); | |
| 537 } | |
| 538 | |
| 534 | 539 |
| 535 // Returns false if the ICData contains anything other than the 4 combinations | 540 // Returns false if the ICData contains anything other than the 4 combinations |
| 536 // of Mint and Smi for the receiver and argument classes. | 541 // of Mint and Smi for the receiver and argument classes. |
| 537 static bool HasTwoMintOrSmi(const ICData& ic_data) { | 542 static bool HasTwoMintOrSmi(const ICData& ic_data) { |
| 538 GrowableArray<intptr_t> class_ids(2); | 543 GrowableArray<intptr_t> class_ids(2); |
| 539 class_ids.Add(kSmiCid); | 544 class_ids.Add(kSmiCid); |
| 540 class_ids.Add(kMintCid); | 545 class_ids.Add(kMintCid); |
| 541 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); | 546 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); |
| 542 } | 547 } |
| 543 | 548 |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 958 ? kMintCid | 963 ? kMintCid |
| 959 : kSmiCid; | 964 : kSmiCid; |
| 960 } else if (HasTwoMintOrSmi(ic_data) && | 965 } else if (HasTwoMintOrSmi(ic_data) && |
| 961 FlowGraphCompiler::SupportsUnboxedMints()) { | 966 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 962 // Don't generate mint code if the IC data is marked because of an | 967 // Don't generate mint code if the IC data is marked because of an |
| 963 // overflow. | 968 // overflow. |
| 964 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false; | 969 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false; |
| 965 operands_type = kMintCid; | 970 operands_type = kMintCid; |
| 966 } else if (ShouldSpecializeForDouble(ic_data)) { | 971 } else if (ShouldSpecializeForDouble(ic_data)) { |
| 967 operands_type = kDoubleCid; | 972 operands_type = kDoubleCid; |
| 973 } else if (HasOnlyTwoFloat32x4s(ic_data)) { | |
| 974 operands_type = kFloat32x4Cid; | |
| 968 } else { | 975 } else { |
| 969 return false; | 976 return false; |
| 970 } | 977 } |
| 971 break; | 978 break; |
| 972 case Token::kMUL: | 979 case Token::kMUL: |
| 973 if (HasOnlyTwoSmis(ic_data)) { | 980 if (HasOnlyTwoSmis(ic_data)) { |
| 974 // Don't generate smi code if the IC data is marked because of an | 981 // Don't generate smi code if the IC data is marked because of an |
| 975 // overflow. | 982 // overflow. |
| 976 // TODO(fschneider): Add unboxed mint multiplication. | 983 // TODO(fschneider): Add unboxed mint multiplication. |
| 977 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; | 984 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; |
| 978 operands_type = kSmiCid; | 985 operands_type = kSmiCid; |
| 979 } else if (ShouldSpecializeForDouble(ic_data)) { | 986 } else if (ShouldSpecializeForDouble(ic_data)) { |
| 980 operands_type = kDoubleCid; | 987 operands_type = kDoubleCid; |
| 988 } else if (HasOnlyTwoFloat32x4s(ic_data)) { | |
| 989 operands_type = kFloat32x4Cid; | |
| 981 } else { | 990 } else { |
| 982 return false; | 991 return false; |
| 983 } | 992 } |
| 984 break; | 993 break; |
| 985 case Token::kDIV: | 994 case Token::kDIV: |
| 986 if (ShouldSpecializeForDouble(ic_data)) { | 995 if (ShouldSpecializeForDouble(ic_data)) { |
| 987 operands_type = kDoubleCid; | 996 operands_type = kDoubleCid; |
| 997 } else if (HasOnlyTwoFloat32x4s(ic_data)) { | |
| 998 operands_type = kFloat32x4Cid; | |
| 988 } else { | 999 } else { |
| 989 return false; | 1000 return false; |
| 990 } | 1001 } |
| 991 break; | 1002 break; |
| 992 case Token::kMOD: | 1003 case Token::kMOD: |
| 993 if (HasOnlyTwoSmis(ic_data)) { | 1004 if (HasOnlyTwoSmis(ic_data)) { |
| 994 operands_type = kSmiCid; | 1005 operands_type = kSmiCid; |
| 995 } else { | 1006 } else { |
| 996 return false; | 1007 return false; |
| 997 } | 1008 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1064 ShiftMintOpInstr* shift_op = | 1075 ShiftMintOpInstr* shift_op = |
| 1065 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), | 1076 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), |
| 1066 call); | 1077 call); |
| 1067 ReplaceCall(call, shift_op); | 1078 ReplaceCall(call, shift_op); |
| 1068 } else { | 1079 } else { |
| 1069 BinaryMintOpInstr* bin_op = | 1080 BinaryMintOpInstr* bin_op = |
| 1070 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), | 1081 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), |
| 1071 call); | 1082 call); |
| 1072 ReplaceCall(call, bin_op); | 1083 ReplaceCall(call, bin_op); |
| 1073 } | 1084 } |
| 1085 } else if (operands_type == kFloat32x4Cid) { | |
| 1086 CheckClassInstr* check_class; | |
| 1087 // Type check left. | |
| 1088 ICData& lvalue_check = ICData::ZoneHandle(); | |
| 1089 lvalue_check = call->ic_data()->AsUnaryClassChecksForArgNr(0); | |
| 1090 check_class = new CheckClassInstr(new Value(left), call->deopt_id(), | |
| 1091 lvalue_check); | |
| 1092 InsertBefore(call, check_class, call->env(), Definition::kEffect); | |
|
Vyacheslav Egorov (Google)
2013/04/15 13:49:21
AddCheckClass(left->definition(),
ca
Cutch
2013/04/15 14:07:06
Done.
| |
| 1093 // Type check right. | |
| 1094 ICData& rvalue_check = ICData::ZoneHandle(); | |
| 1095 rvalue_check = call->ic_data()->AsUnaryClassChecksForArgNr(1); | |
| 1096 check_class = new CheckClassInstr(new Value(right), call->deopt_id(), | |
| 1097 rvalue_check); | |
| 1098 InsertBefore(call, check_class, call->env(), Definition::kEffect); | |
|
Vyacheslav Egorov (Google)
2013/04/15 13:49:21
AddCheckClass(right->definition(),
c
Cutch
2013/04/15 14:07:06
Done.
| |
| 1099 // Replace call. | |
| 1100 BinaryFloat32x4OpInstr* float32x4_bin_op = | |
| 1101 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right), | |
| 1102 call); | |
| 1103 ReplaceCall(call, float32x4_bin_op); | |
| 1074 } else if (op_kind == Token::kMOD) { | 1104 } else if (op_kind == Token::kMOD) { |
| 1075 // TODO(vegorov): implement fast path code for modulo. | 1105 // TODO(vegorov): implement fast path code for modulo. |
| 1076 ASSERT(operands_type == kSmiCid); | 1106 ASSERT(operands_type == kSmiCid); |
| 1077 if (!right->IsConstant()) return false; | 1107 if (!right->IsConstant()) return false; |
| 1078 const Object& obj = right->AsConstant()->value(); | 1108 const Object& obj = right->AsConstant()->value(); |
| 1079 if (!obj.IsSmi()) return false; | 1109 if (!obj.IsSmi()) return false; |
| 1080 const intptr_t value = Smi::Cast(obj).Value(); | 1110 const intptr_t value = Smi::Cast(obj).Value(); |
| 1081 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false; | 1111 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false; |
| 1082 | 1112 |
| 1083 // Insert smi check and attach a copy of the original environment | 1113 // Insert smi check and attach a copy of the original environment |
| (...skipping 3308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4392 const Object& right = instr->right()->definition()->constant_value(); | 4422 const Object& right = instr->right()->definition()->constant_value(); |
| 4393 if (IsNonConstant(left) || IsNonConstant(right)) { | 4423 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 4394 SetValue(instr, non_constant_); | 4424 SetValue(instr, non_constant_); |
| 4395 } else if (IsConstant(left) && IsConstant(right)) { | 4425 } else if (IsConstant(left) && IsConstant(right)) { |
| 4396 // TODO(kmillikin): Handle binary operation. | 4426 // TODO(kmillikin): Handle binary operation. |
| 4397 SetValue(instr, non_constant_); | 4427 SetValue(instr, non_constant_); |
| 4398 } | 4428 } |
| 4399 } | 4429 } |
| 4400 | 4430 |
| 4401 | 4431 |
| 4432 void ConstantPropagator::VisitBinaryFloat32x4Op( | |
| 4433 BinaryFloat32x4OpInstr* instr) { | |
| 4434 const Object& left = instr->left()->definition()->constant_value(); | |
| 4435 const Object& right = instr->right()->definition()->constant_value(); | |
| 4436 if (IsNonConstant(left) || IsNonConstant(right)) { | |
| 4437 SetValue(instr, non_constant_); | |
| 4438 } else if (IsConstant(left) && IsConstant(right)) { | |
| 4439 // TODO(kmillikin): Handle binary operation. | |
| 4440 SetValue(instr, non_constant_); | |
| 4441 } | |
| 4442 } | |
| 4443 | |
| 4444 | |
| 4402 void ConstantPropagator::VisitMathSqrt(MathSqrtInstr* instr) { | 4445 void ConstantPropagator::VisitMathSqrt(MathSqrtInstr* instr) { |
| 4403 const Object& value = instr->value()->definition()->constant_value(); | 4446 const Object& value = instr->value()->definition()->constant_value(); |
| 4404 if (IsNonConstant(value)) { | 4447 if (IsNonConstant(value)) { |
| 4405 SetValue(instr, non_constant_); | 4448 SetValue(instr, non_constant_); |
| 4406 } else if (IsConstant(value)) { | 4449 } else if (IsConstant(value)) { |
| 4407 // TODO(kmillikin): Handle sqrt. | 4450 // TODO(kmillikin): Handle sqrt. |
| 4408 SetValue(instr, non_constant_); | 4451 SetValue(instr, non_constant_); |
| 4409 } | 4452 } |
| 4410 } | 4453 } |
| 4411 | 4454 |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5016 if (changed) { | 5059 if (changed) { |
| 5017 // We may have changed the block order and the dominator tree. | 5060 // We may have changed the block order and the dominator tree. |
| 5018 flow_graph->DiscoverBlocks(); | 5061 flow_graph->DiscoverBlocks(); |
| 5019 GrowableArray<BitVector*> dominance_frontier; | 5062 GrowableArray<BitVector*> dominance_frontier; |
| 5020 flow_graph->ComputeDominators(&dominance_frontier); | 5063 flow_graph->ComputeDominators(&dominance_frontier); |
| 5021 } | 5064 } |
| 5022 } | 5065 } |
| 5023 | 5066 |
| 5024 | 5067 |
| 5025 } // namespace dart | 5068 } // namespace dart |
| OLD | NEW |