| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 } | 79 } |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 void HValue::InferRepresentation(HInferRepresentation* h_infer) { | 83 void HValue::InferRepresentation(HInferRepresentation* h_infer) { |
| 84 ASSERT(CheckFlag(kFlexibleRepresentation)); | 84 ASSERT(CheckFlag(kFlexibleRepresentation)); |
| 85 Representation new_rep = RepresentationFromInputs(); | 85 Representation new_rep = RepresentationFromInputs(); |
| 86 UpdateRepresentation(new_rep, h_infer, "inputs"); | 86 UpdateRepresentation(new_rep, h_infer, "inputs"); |
| 87 new_rep = RepresentationFromUses(); | 87 new_rep = RepresentationFromUses(); |
| 88 UpdateRepresentation(new_rep, h_infer, "uses"); | 88 UpdateRepresentation(new_rep, h_infer, "uses"); |
| 89 new_rep = RepresentationFromUseRequirements(); |
| 90 if (new_rep.fits_into(Representation::Integer32())) { |
| 91 UpdateRepresentation(new_rep, h_infer, "use requirements"); |
| 92 } |
| 89 } | 93 } |
| 90 | 94 |
| 91 | 95 |
| 92 Representation HValue::RepresentationFromUses() { | 96 Representation HValue::RepresentationFromUses() { |
| 93 if (HasNoUses()) return Representation::None(); | 97 if (HasNoUses()) return Representation::None(); |
| 94 | 98 |
| 95 // Array of use counts for each representation. | 99 // Array of use counts for each representation. |
| 96 int use_count[Representation::kNumRepresentations] = { 0 }; | 100 int use_count[Representation::kNumRepresentations] = { 0 }; |
| 97 | 101 |
| 98 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 102 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| (...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1142 stream->Add(" + %d) >> %d)", offset(), scale()); | 1146 stream->Add(" + %d) >> %d)", offset(), scale()); |
| 1143 } | 1147 } |
| 1144 if (skip_check()) { | 1148 if (skip_check()) { |
| 1145 stream->Add(" [DISABLED]"); | 1149 stream->Add(" [DISABLED]"); |
| 1146 } | 1150 } |
| 1147 } | 1151 } |
| 1148 | 1152 |
| 1149 | 1153 |
| 1150 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) { | 1154 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) { |
| 1151 ASSERT(CheckFlag(kFlexibleRepresentation)); | 1155 ASSERT(CheckFlag(kFlexibleRepresentation)); |
| 1152 Representation r; | |
| 1153 HValue* actual_index = index()->ActualValue(); | 1156 HValue* actual_index = index()->ActualValue(); |
| 1154 HValue* actual_length = length()->ActualValue(); | 1157 HValue* actual_length = length()->ActualValue(); |
| 1155 Representation index_rep = actual_index->representation(); | 1158 Representation index_rep = actual_index->representation(); |
| 1156 if (!actual_length->representation().IsSmiOrTagged()) { | 1159 Representation length_rep = actual_length->representation(); |
| 1157 r = Representation::Integer32(); | 1160 if (index_rep.IsTagged()) index_rep = Representation::Smi(); |
| 1158 } else if ((index_rep.IsTagged() && actual_index->type().IsSmi()) || | 1161 if (length_rep.IsTagged()) length_rep = Representation::Smi(); |
| 1159 index_rep.IsSmi()) { | 1162 Representation r = index_rep.generalize(length_rep); |
| 1160 // If the index is smi, allow the length to be smi, since it is usually | 1163 if (r.is_more_general_than(Representation::Integer32())) { |
| 1161 // already smi from loading it out of the length field of a JSArray. This | |
| 1162 // allows for direct comparison without untagging. | |
| 1163 r = Representation::Smi(); | |
| 1164 } else { | |
| 1165 r = Representation::Integer32(); | 1164 r = Representation::Integer32(); |
| 1166 } | 1165 } |
| 1167 UpdateRepresentation(r, h_infer, "boundscheck"); | 1166 UpdateRepresentation(r, h_infer, "boundscheck"); |
| 1168 } | 1167 } |
| 1169 | 1168 |
| 1170 | 1169 |
| 1171 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal( | 1170 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal( |
| 1172 NumericRelation relation, | 1171 NumericRelation relation, |
| 1173 HValue* related_value, | 1172 HValue* related_value, |
| 1174 int offset, | 1173 int offset, |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1282 ToBooleanStub::UNDEFINED | | 1281 ToBooleanStub::UNDEFINED | |
| 1283 ToBooleanStub::NULL_TYPE | | 1282 ToBooleanStub::NULL_TYPE | |
| 1284 ToBooleanStub::SPEC_OBJECT | | 1283 ToBooleanStub::SPEC_OBJECT | |
| 1285 ToBooleanStub::STRING | | 1284 ToBooleanStub::STRING | |
| 1286 ToBooleanStub::SYMBOL); | 1285 ToBooleanStub::SYMBOL); |
| 1287 if (expected_input_types_.ContainsAnyOf(tagged_types)) { | 1286 if (expected_input_types_.ContainsAnyOf(tagged_types)) { |
| 1288 return Representation::Tagged(); | 1287 return Representation::Tagged(); |
| 1289 } else if (expected_input_types_.Contains(ToBooleanStub::HEAP_NUMBER)) { | 1288 } else if (expected_input_types_.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 1290 return Representation::Double(); | 1289 return Representation::Double(); |
| 1291 } else if (expected_input_types_.Contains(ToBooleanStub::SMI)) { | 1290 } else if (expected_input_types_.Contains(ToBooleanStub::SMI)) { |
| 1292 return Representation::Integer32(); | 1291 return Representation::Smi(); |
| 1293 } else { | 1292 } else { |
| 1294 return Representation::None(); | 1293 return Representation::None(); |
| 1295 } | 1294 } |
| 1296 } | 1295 } |
| 1297 | 1296 |
| 1298 | 1297 |
| 1299 void HCompareMap::PrintDataTo(StringStream* stream) { | 1298 void HCompareMap::PrintDataTo(StringStream* stream) { |
| 1300 value()->PrintNameTo(stream); | 1299 value()->PrintNameTo(stream); |
| 1301 stream->Add(" (%p)", *map()); | 1300 stream->Add(" (%p)", *map()); |
| 1302 HControlInstruction::PrintDataTo(stream); | 1301 HControlInstruction::PrintDataTo(stream); |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1506 void HChange::PrintDataTo(StringStream* stream) { | 1505 void HChange::PrintDataTo(StringStream* stream) { |
| 1507 HUnaryOperation::PrintDataTo(stream); | 1506 HUnaryOperation::PrintDataTo(stream); |
| 1508 stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic()); | 1507 stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic()); |
| 1509 | 1508 |
| 1510 if (CanTruncateToInt32()) stream->Add(" truncating-int32"); | 1509 if (CanTruncateToInt32()) stream->Add(" truncating-int32"); |
| 1511 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); | 1510 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?"); |
| 1512 if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan"); | 1511 if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan"); |
| 1513 } | 1512 } |
| 1514 | 1513 |
| 1515 | 1514 |
| 1515 static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* dividend) { |
| 1516 // A value with an integer representation does not need to be transformed. |
| 1517 if (dividend->representation().IsInteger32()) { |
| 1518 return dividend; |
| 1519 } |
| 1520 // A change from an integer32 can be replaced by the integer32 value. |
| 1521 if (dividend->IsChange() && |
| 1522 HChange::cast(dividend)->from().IsInteger32()) { |
| 1523 return HChange::cast(dividend)->value(); |
| 1524 } |
| 1525 return NULL; |
| 1526 } |
| 1527 |
| 1528 |
| 1516 HValue* HUnaryMathOperation::Canonicalize() { | 1529 HValue* HUnaryMathOperation::Canonicalize() { |
| 1517 if (op() == kMathFloor) { | 1530 if (op() == kMathFloor) { |
| 1531 HValue* val = value(); |
| 1532 if (val->IsChange()) val = HChange::cast(val)->value(); |
| 1533 |
| 1518 // If the input is integer32 then we replace the floor instruction | 1534 // If the input is integer32 then we replace the floor instruction |
| 1519 // with its input. This happens before the representation changes are | 1535 // with its input. |
| 1520 // introduced. | 1536 if (val->representation().IsInteger32()) return val; |
| 1521 | |
| 1522 // TODO(2205): The above comment is lying. All of this happens | |
| 1523 // *after* representation changes are introduced. We should check | |
| 1524 // for value->IsChange() and react accordingly if yes. | |
| 1525 | |
| 1526 if (value()->representation().IsInteger32()) return value(); | |
| 1527 | 1537 |
| 1528 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_IA32) || \ | 1538 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_IA32) || \ |
| 1529 defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_A64) | 1539 defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_A64) |
| 1530 if (value()->IsDiv() && (value()->UseCount() == 1)) { | 1540 if (value()->IsDiv() && (value()->UseCount() == 1)) { |
| 1531 // TODO(2038): Implement this optimization for non ARM architectures. | 1541 // TODO(2038): Implement this optimization for non ARM architectures. |
| 1532 HDiv* hdiv = HDiv::cast(value()); | 1542 HDiv* hdiv = HDiv::cast(value()); |
| 1533 HValue* left = hdiv->left(); | 1543 HValue* left = hdiv->left(); |
| 1534 HValue* right = hdiv->right(); | 1544 HValue* right = hdiv->right(); |
| 1535 // Try to simplify left and right values of the division. | 1545 // Try to simplify left and right values of the division. |
| 1536 HValue* new_left = | 1546 HValue* new_left = SimplifiedDividendForMathFloorOfDiv(left); |
| 1537 LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(left); | 1547 if (new_left == NULL && |
| 1548 hdiv->observed_input_representation(1).IsSmiOrInteger32()) { |
| 1549 new_left = new(block()->zone()) |
| 1550 HChange(left, Representation::Integer32(), false, false); |
| 1551 HChange::cast(new_left)->InsertBefore(this); |
| 1552 } |
| 1538 HValue* new_right = | 1553 HValue* new_right = |
| 1539 LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right); | 1554 LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right); |
| 1555 if (new_right == NULL && |
| 1556 #ifdef V8_TARGET_ARCH_ARM |
| 1557 CpuFeatures::IsSupported(SUDIV) && |
| 1558 #endif |
| 1559 hdiv->observed_input_representation(2).IsSmiOrInteger32()) { |
| 1560 new_right = new(block()->zone()) |
| 1561 HChange(right, Representation::Integer32(), false, false); |
| 1562 HChange::cast(new_right)->InsertBefore(this); |
| 1563 } |
| 1540 | 1564 |
| 1541 // Return if left or right are not optimizable. | 1565 // Return if left or right are not optimizable. |
| 1542 if ((new_left == NULL) || (new_right == NULL)) return this; | 1566 if ((new_left == NULL) || (new_right == NULL)) return this; |
| 1543 | 1567 |
| 1544 // Insert the new values in the graph. | 1568 // Insert the new values in the graph. |
| 1545 if (new_left->IsInstruction() && | 1569 if (new_left->IsInstruction() && |
| 1546 !HInstruction::cast(new_left)->IsLinked()) { | 1570 !HInstruction::cast(new_left)->IsLinked()) { |
| 1547 HInstruction::cast(new_left)->InsertBefore(this); | 1571 HInstruction::cast(new_left)->InsertBefore(this); |
| 1548 } | 1572 } |
| 1549 if (new_right->IsInstruction() && | 1573 if (new_right->IsInstruction() && |
| 1550 !HInstruction::cast(new_right)->IsLinked()) { | 1574 !HInstruction::cast(new_right)->IsLinked()) { |
| 1551 HInstruction::cast(new_right)->InsertBefore(this); | 1575 HInstruction::cast(new_right)->InsertBefore(this); |
| 1552 } | 1576 } |
| 1553 HMathFloorOfDiv* instr = new(block()->zone()) HMathFloorOfDiv(context(), | 1577 HMathFloorOfDiv* instr = new(block()->zone()) |
| 1554 new_left, | 1578 HMathFloorOfDiv(context(), new_left, new_right); |
| 1555 new_right); | |
| 1556 // Replace this HMathFloor instruction by the new HMathFloorOfDiv. | 1579 // Replace this HMathFloor instruction by the new HMathFloorOfDiv. |
| 1557 instr->InsertBefore(this); | 1580 instr->InsertBefore(this); |
| 1558 ReplaceAllUsesWith(instr); | 1581 ReplaceAllUsesWith(instr); |
| 1559 Kill(); | 1582 Kill(); |
| 1560 // We know the division had no other uses than this HMathFloor. Delete it. | 1583 // We know the division had no other uses than this HMathFloor. Delete it. |
| 1561 // Also delete the arguments of the division if they are not used any | 1584 // Dead code elimination will deal with |left| and |right| if |
| 1562 // more. | 1585 // appropriate. |
| 1563 hdiv->DeleteAndReplaceWith(NULL); | 1586 hdiv->DeleteAndReplaceWith(NULL); |
| 1564 ASSERT(left->IsChange() || left->IsConstant()); | |
| 1565 ASSERT(right->IsChange() || right->IsConstant()); | |
| 1566 if (left->HasNoUses()) left->DeleteAndReplaceWith(NULL); | |
| 1567 if (right->HasNoUses()) right->DeleteAndReplaceWith(NULL); | |
| 1568 | 1587 |
| 1569 // Return NULL to remove this instruction from the graph. | 1588 // Return NULL to remove this instruction from the graph. |
| 1570 return NULL; | 1589 return NULL; |
| 1571 } | 1590 } |
| 1572 #endif // V8_TARGET_ARCH_ARM | 1591 #endif |
| 1573 } | 1592 } |
| 1574 return this; | 1593 return this; |
| 1575 } | 1594 } |
| 1576 | 1595 |
| 1577 | 1596 |
| 1578 HValue* HCheckInstanceType::Canonicalize() { | 1597 HValue* HCheckInstanceType::Canonicalize() { |
| 1579 if (check_ == IS_STRING && | 1598 if (check_ == IS_STRING && |
| 1580 !value()->type().IsUninitialized() && | 1599 !value()->type().IsUninitialized() && |
| 1581 value()->type().IsString()) { | 1600 value()->type().IsString()) { |
| 1582 return NULL; | 1601 return NULL; |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2299 | 2318 |
| 2300 void HBinaryOperation::InferRepresentation(HInferRepresentation* h_infer) { | 2319 void HBinaryOperation::InferRepresentation(HInferRepresentation* h_infer) { |
| 2301 ASSERT(CheckFlag(kFlexibleRepresentation)); | 2320 ASSERT(CheckFlag(kFlexibleRepresentation)); |
| 2302 Representation new_rep = RepresentationFromInputs(); | 2321 Representation new_rep = RepresentationFromInputs(); |
| 2303 UpdateRepresentation(new_rep, h_infer, "inputs"); | 2322 UpdateRepresentation(new_rep, h_infer, "inputs"); |
| 2304 // When the operation has information about its own output type, don't look | 2323 // When the operation has information about its own output type, don't look |
| 2305 // at uses. | 2324 // at uses. |
| 2306 if (!observed_output_representation_.IsNone()) return; | 2325 if (!observed_output_representation_.IsNone()) return; |
| 2307 new_rep = RepresentationFromUses(); | 2326 new_rep = RepresentationFromUses(); |
| 2308 UpdateRepresentation(new_rep, h_infer, "uses"); | 2327 UpdateRepresentation(new_rep, h_infer, "uses"); |
| 2328 new_rep = RepresentationFromUseRequirements(); |
| 2329 if (new_rep.fits_into(Representation::Integer32())) { |
| 2330 UpdateRepresentation(new_rep, h_infer, "use requirements"); |
| 2331 } |
| 2309 } | 2332 } |
| 2310 | 2333 |
| 2311 | 2334 |
| 2312 bool HBinaryOperation::IgnoreObservedOutputRepresentation( | 2335 bool HBinaryOperation::IgnoreObservedOutputRepresentation( |
| 2313 Representation current_rep) { | 2336 Representation current_rep) { |
| 2314 return observed_output_representation_.IsDouble() && | 2337 return observed_output_representation_.IsDouble() && |
| 2315 current_rep.IsInteger32() && | 2338 current_rep.IsInteger32() && |
| 2316 // Mul in Integer32 mode would be too precise. | 2339 // Mul in Integer32 mode would be too precise. |
| 2317 !this->IsMul() && | 2340 !this->IsMul() && |
| 2318 CheckUsesForFlag(kTruncatingToInt32); | 2341 CheckUsesForFlag(kTruncatingToInt32); |
| (...skipping 1336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3655 | 3678 |
| 3656 Representation HPhi::RepresentationFromInputs() { | 3679 Representation HPhi::RepresentationFromInputs() { |
| 3657 Representation r = Representation::None(); | 3680 Representation r = Representation::None(); |
| 3658 for (int i = 0; i < OperandCount(); ++i) { | 3681 for (int i = 0; i < OperandCount(); ++i) { |
| 3659 r = r.generalize(OperandAt(i)->KnownOptimalRepresentation()); | 3682 r = r.generalize(OperandAt(i)->KnownOptimalRepresentation()); |
| 3660 } | 3683 } |
| 3661 return r; | 3684 return r; |
| 3662 } | 3685 } |
| 3663 | 3686 |
| 3664 | 3687 |
| 3665 Representation HPhi::RepresentationFromUseRequirements() { | 3688 // Returns a representation if all uses agree on the same representation. |
| 3666 Representation all_uses_require = Representation::None(); | 3689 // Integer32 is also returned when some uses are Smi but others are Integer32. |
| 3667 bool all_uses_require_the_same = true; | 3690 Representation HValue::RepresentationFromUseRequirements() { |
| 3691 Representation rep = Representation::None(); |
| 3668 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 3692 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 3669 // We check for observed_input_representation elsewhere. | 3693 // We check for observed_input_representation elsewhere. |
| 3670 Representation use_rep = | 3694 Representation use_rep = |
| 3671 it.value()->RequiredInputRepresentation(it.index()); | 3695 it.value()->RequiredInputRepresentation(it.index()); |
| 3672 // No useful info from this use -> look at the next one. | 3696 if (rep.IsNone()) { |
| 3673 if (use_rep.IsNone()) { | 3697 rep = use_rep; |
| 3674 continue; | 3698 continue; |
| 3675 } | 3699 } |
| 3676 if (use_rep.Equals(all_uses_require)) { | 3700 if (use_rep.IsNone() || rep.Equals(use_rep)) continue; |
| 3701 if (rep.generalize(use_rep).IsInteger32()) { |
| 3702 rep = Representation::Integer32(); |
| 3677 continue; | 3703 continue; |
| 3678 } | 3704 } |
| 3679 // This use's representation contradicts what we've seen so far. | 3705 return Representation::None(); |
| 3680 if (!all_uses_require.IsNone()) { | |
| 3681 ASSERT(!use_rep.Equals(all_uses_require)); | |
| 3682 all_uses_require_the_same = false; | |
| 3683 break; | |
| 3684 } | |
| 3685 // Otherwise, initialize observed representation. | |
| 3686 all_uses_require = use_rep; | |
| 3687 } | 3706 } |
| 3688 if (all_uses_require_the_same) { | 3707 return rep; |
| 3689 return all_uses_require; | |
| 3690 } | |
| 3691 | |
| 3692 return Representation::None(); | |
| 3693 } | 3708 } |
| 3694 | 3709 |
| 3695 | 3710 |
| 3696 // Node-specific verification code is only included in debug mode. | 3711 // Node-specific verification code is only included in debug mode. |
| 3697 #ifdef DEBUG | 3712 #ifdef DEBUG |
| 3698 | 3713 |
| 3699 void HPhi::Verify() { | 3714 void HPhi::Verify() { |
| 3700 ASSERT(OperandCount() == block()->predecessors()->length()); | 3715 ASSERT(OperandCount() == block()->predecessors()->length()); |
| 3701 for (int i = 0; i < OperandCount(); ++i) { | 3716 for (int i = 0; i < OperandCount(); ++i) { |
| 3702 HValue* value = OperandAt(i); | 3717 HValue* value = OperandAt(i); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3857 case kBackingStore: | 3872 case kBackingStore: |
| 3858 if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString()); | 3873 if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString()); |
| 3859 stream->Add("[backing-store]"); | 3874 stream->Add("[backing-store]"); |
| 3860 break; | 3875 break; |
| 3861 } | 3876 } |
| 3862 | 3877 |
| 3863 stream->Add("@%d", offset()); | 3878 stream->Add("@%d", offset()); |
| 3864 } | 3879 } |
| 3865 | 3880 |
| 3866 } } // namespace v8::internal | 3881 } } // namespace v8::internal |
| OLD | NEW |