OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1067 instr->ReplayEnvironment(current_block_->last_environment()); | 1067 instr->ReplayEnvironment(current_block_->last_environment()); |
1068 | 1068 |
1069 // There are no real uses of a captured object. | 1069 // There are no real uses of a captured object. |
1070 return NULL; | 1070 return NULL; |
1071 } | 1071 } |
1072 | 1072 |
1073 | 1073 |
1074 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1074 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
1075 Representation from = instr->from(); | 1075 Representation from = instr->from(); |
1076 Representation to = instr->to(); | 1076 Representation to = instr->to(); |
1077 | 1077 HValue* val = instr->value(); |
1078 if (from.IsSmi()) { | 1078 if (from.IsSmi()) { |
1079 if (to.IsTagged()) { | 1079 if (to.IsTagged()) { |
1080 LOperand* value = UseRegister(instr->value()); | 1080 LOperand* value = UseRegister(val); |
1081 return DefineSameAsFirst(new(zone()) LDummyUse(value)); | 1081 return DefineSameAsFirst(new(zone()) LDummyUse(value)); |
1082 } | 1082 } |
1083 from = Representation::Tagged(); | 1083 from = Representation::Tagged(); |
1084 } | 1084 } |
1085 | |
1086 if (from.IsTagged()) { | 1085 if (from.IsTagged()) { |
1087 if (to.IsDouble()) { | 1086 if (to.IsDouble()) { |
1088 LOperand* value = UseRegister(instr->value()); | 1087 LOperand* value = UseRegister(val); |
1089 LOperand* temp = TempRegister(); | 1088 LOperand* temp = TempRegister(); |
1090 LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); | 1089 LInstruction* result = |
1091 return AssignEnvironment(DefineAsRegister(res)); | 1090 DefineAsRegister(new(zone()) LNumberUntagD(value, temp)); |
| 1091 if (!val->representation().IsSmi()) result = AssignEnvironment(result); |
| 1092 return result; |
1092 } else if (to.IsSmi()) { | 1093 } else if (to.IsSmi()) { |
1093 LOperand* value = UseRegister(instr->value()); | 1094 LOperand* value = UseRegister(val); |
1094 if (instr->value()->type().IsSmi()) { | 1095 if (val->type().IsSmi()) { |
1095 return DefineSameAsFirst(new(zone()) LDummyUse(value)); | 1096 return DefineSameAsFirst(new(zone()) LDummyUse(value)); |
1096 } | 1097 } |
1097 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); | 1098 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); |
1098 } else { | 1099 } else { |
1099 ASSERT(to.IsInteger32()); | 1100 ASSERT(to.IsInteger32()); |
1100 LInstruction* res = NULL; | 1101 if (val->type().IsSmi() || val->representation().IsSmi()) { |
1101 | 1102 LOperand* value = UseRegisterAtStart(val); |
1102 if (instr->value()->type().IsSmi() || | 1103 return DefineAsRegister(new(zone()) LSmiUntag(value, false)); |
1103 instr->value()->representation().IsSmi()) { | |
1104 LOperand* value = UseRegisterAtStart(instr->value()); | |
1105 res = DefineAsRegister(new(zone()) LSmiUntag(value, false)); | |
1106 } else { | 1104 } else { |
1107 LOperand* value = UseRegister(instr->value()); | 1105 LOperand* value = UseRegister(val); |
1108 LOperand* temp1 = TempRegister(); | 1106 LOperand* temp1 = TempRegister(); |
1109 LOperand* temp2 = instr->CanTruncateToInt32() ? NULL : FixedTemp(d24); | 1107 LOperand* temp2 = instr->CanTruncateToInt32() ? NULL : FixedTemp(d24); |
1110 res = DefineAsRegister(new(zone()) LTaggedToI(value, temp1, temp2)); | 1108 LInstruction* result = |
1111 res = AssignEnvironment(res); | 1109 DefineAsRegister(new(zone()) LTaggedToI(value, temp1, temp2)); |
| 1110 if (!val->representation().IsSmi()) { |
| 1111 // Note: Only deopts in deferred code. |
| 1112 result = AssignEnvironment(result); |
| 1113 } |
| 1114 return result; |
1112 } | 1115 } |
1113 | |
1114 return res; | |
1115 } | 1116 } |
1116 } else if (from.IsDouble()) { | 1117 } else if (from.IsDouble()) { |
1117 if (to.IsTagged()) { | 1118 if (to.IsTagged()) { |
1118 info()->MarkAsDeferredCalling(); | 1119 info()->MarkAsDeferredCalling(); |
1119 LOperand* value = UseRegister(instr->value()); | 1120 LOperand* value = UseRegister(val); |
1120 LOperand* temp1 = TempRegister(); | 1121 LOperand* temp1 = TempRegister(); |
1121 LOperand* temp2 = TempRegister(); | 1122 LOperand* temp2 = TempRegister(); |
1122 | |
1123 LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); | 1123 LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); |
1124 return AssignPointerMap(DefineAsRegister(result)); | 1124 return AssignPointerMap(DefineAsRegister(result)); |
1125 } else { | 1125 } else { |
1126 ASSERT(to.IsSmi() || to.IsInteger32()); | 1126 ASSERT(to.IsSmi() || to.IsInteger32()); |
1127 LOperand* value = UseRegister(instr->value()); | |
1128 | |
1129 if (instr->CanTruncateToInt32()) { | 1127 if (instr->CanTruncateToInt32()) { |
1130 LTruncateDoubleToIntOrSmi* result = | 1128 LOperand* value = UseRegister(val); |
1131 new(zone()) LTruncateDoubleToIntOrSmi(value); | 1129 return DefineAsRegister(new(zone()) LTruncateDoubleToIntOrSmi(value)); |
1132 return DefineAsRegister(result); | |
1133 } else { | 1130 } else { |
| 1131 LOperand* value = UseRegister(val); |
1134 LDoubleToIntOrSmi* result = new(zone()) LDoubleToIntOrSmi(value); | 1132 LDoubleToIntOrSmi* result = new(zone()) LDoubleToIntOrSmi(value); |
1135 return AssignEnvironment(DefineAsRegister(result)); | 1133 return AssignEnvironment(DefineAsRegister(result)); |
1136 } | 1134 } |
1137 } | 1135 } |
1138 } else if (from.IsInteger32()) { | 1136 } else if (from.IsInteger32()) { |
1139 info()->MarkAsDeferredCalling(); | 1137 info()->MarkAsDeferredCalling(); |
1140 if (to.IsTagged()) { | 1138 if (to.IsTagged()) { |
1141 if (instr->value()->CheckFlag(HInstruction::kUint32)) { | 1139 if (val->CheckFlag(HInstruction::kUint32)) { |
1142 LOperand* value = UseRegister(instr->value()); | 1140 LOperand* value = UseRegister(val); |
1143 LNumberTagU* result = new(zone()) LNumberTagU(value, | 1141 LNumberTagU* result = |
1144 TempRegister(), | 1142 new(zone()) LNumberTagU(value, TempRegister(), TempRegister()); |
1145 TempRegister()); | 1143 return AssignPointerMap(DefineAsRegister(result)); |
1146 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | |
1147 } else { | 1144 } else { |
1148 STATIC_ASSERT((kMinInt == Smi::kMinValue) && | 1145 STATIC_ASSERT((kMinInt == Smi::kMinValue) && |
1149 (kMaxInt == Smi::kMaxValue)); | 1146 (kMaxInt == Smi::kMaxValue)); |
1150 LOperand* value = UseRegisterAtStart(instr->value()); | 1147 LOperand* value = UseRegisterAtStart(val); |
1151 return DefineAsRegister(new(zone()) LSmiTag(value)); | 1148 return DefineAsRegister(new(zone()) LSmiTag(value)); |
1152 } | 1149 } |
1153 } else if (to.IsSmi()) { | 1150 } else if (to.IsSmi()) { |
1154 LOperand* value = UseRegisterAtStart(instr->value()); | 1151 LOperand* value = UseRegisterAtStart(val); |
1155 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); | 1152 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); |
1156 if (instr->value()->CheckFlag(HInstruction::kUint32)) { | 1153 if (val->CheckFlag(HInstruction::kUint32)) { |
1157 result = AssignEnvironment(result); | 1154 result = AssignEnvironment(result); |
1158 } | 1155 } |
1159 return result; | 1156 return result; |
1160 } else { | 1157 } else { |
1161 ASSERT(to.IsDouble()); | 1158 ASSERT(to.IsDouble()); |
1162 if (instr->value()->CheckFlag(HInstruction::kUint32)) { | 1159 if (val->CheckFlag(HInstruction::kUint32)) { |
1163 return DefineAsRegister( | 1160 return DefineAsRegister( |
1164 new(zone()) LUint32ToDouble(UseRegisterAtStart(instr->value()))); | 1161 new(zone()) LUint32ToDouble(UseRegisterAtStart(val))); |
1165 } else { | 1162 } else { |
1166 return DefineAsRegister( | 1163 return DefineAsRegister( |
1167 new(zone()) LInteger32ToDouble(UseRegisterAtStart(instr->value()))); | 1164 new(zone()) LInteger32ToDouble(UseRegisterAtStart(val))); |
1168 } | 1165 } |
1169 } | 1166 } |
1170 } | 1167 } |
1171 | |
1172 UNREACHABLE(); | 1168 UNREACHABLE(); |
1173 return NULL; | 1169 return NULL; |
1174 } | 1170 } |
1175 | 1171 |
1176 | 1172 |
1177 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { | 1173 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { |
1178 LOperand* value = UseRegisterAtStart(instr->value()); | 1174 LOperand* value = UseRegisterAtStart(instr->value()); |
1179 return AssignEnvironment(new(zone()) LCheckValue(value)); | 1175 return AssignEnvironment(new(zone()) LCheckValue(value)); |
1180 } | 1176 } |
1181 | 1177 |
1182 | 1178 |
1183 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 1179 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
1184 LOperand* value = UseRegisterAtStart(instr->value()); | 1180 LOperand* value = UseRegisterAtStart(instr->value()); |
1185 LOperand* temp = TempRegister(); | 1181 LOperand* temp = TempRegister(); |
1186 LInstruction* result = new(zone()) LCheckInstanceType(value, temp); | 1182 LInstruction* result = new(zone()) LCheckInstanceType(value, temp); |
1187 return AssignEnvironment(result); | 1183 return AssignEnvironment(result); |
1188 } | 1184 } |
1189 | 1185 |
1190 | 1186 |
1191 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { | 1187 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { |
1192 if (instr->CanOmitMapChecks()) { | 1188 LOperand* value = NULL; |
1193 // LCheckMaps does nothing in this case. | 1189 LOperand* temp = NULL; |
1194 return new(zone()) LCheckMaps(NULL); | 1190 if (!instr->CanOmitMapChecks()) { |
1195 } else { | 1191 value = UseRegisterAtStart(instr->value()); |
1196 LOperand* value = UseRegisterAtStart(instr->value()); | 1192 temp = TempRegister(); |
1197 LOperand* temp = TempRegister(); | 1193 if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); |
1198 | |
1199 if (instr->has_migration_target()) { | |
1200 info()->MarkAsDeferredCalling(); | |
1201 LInstruction* result = new(zone()) LCheckMaps(value, temp); | |
1202 return AssignPointerMap(AssignEnvironment(result)); | |
1203 } else { | |
1204 return AssignEnvironment(new(zone()) LCheckMaps(value, temp)); | |
1205 } | |
1206 } | 1194 } |
| 1195 LInstruction* result = new(zone()) LCheckMaps(value, temp); |
| 1196 if (!instr->CanOmitMapChecks()) { |
| 1197 // Note: Only deopts in deferred code. |
| 1198 result = AssignEnvironment(result); |
| 1199 if (instr->has_migration_target()) return AssignPointerMap(result); |
| 1200 } |
| 1201 return result; |
1207 } | 1202 } |
1208 | 1203 |
1209 | 1204 |
1210 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { | 1205 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { |
1211 LOperand* value = UseRegisterAtStart(instr->value()); | 1206 LOperand* value = UseRegisterAtStart(instr->value()); |
1212 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); | 1207 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); |
1213 } | 1208 } |
1214 | 1209 |
1215 | 1210 |
1216 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { | 1211 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1411 | 1406 |
1412 | 1407 |
1413 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { | 1408 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { |
1414 ASSERT(instr->representation().IsSmiOrInteger32()); | 1409 ASSERT(instr->representation().IsSmiOrInteger32()); |
1415 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1410 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1416 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1411 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1417 LOperand* dividend = UseRegister(instr->left()); | 1412 LOperand* dividend = UseRegister(instr->left()); |
1418 LOperand* divisor = UseRegister(instr->right()); | 1413 LOperand* divisor = UseRegister(instr->right()); |
1419 LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) | 1414 LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) |
1420 ? NULL : TempRegister(); | 1415 ? NULL : TempRegister(); |
1421 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); | 1416 LInstruction* result = |
1422 return AssignEnvironment(DefineAsRegister(div)); | 1417 DefineAsRegister(new(zone()) LDivI(dividend, divisor, temp)); |
| 1418 if (!instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1419 result = AssignEnvironment(result); |
| 1420 } |
| 1421 return result; |
1423 } | 1422 } |
1424 | 1423 |
1425 | 1424 |
1426 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1425 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1427 if (instr->representation().IsSmiOrInteger32()) { | 1426 if (instr->representation().IsSmiOrInteger32()) { |
1428 if (instr->RightIsPowerOf2()) { | 1427 if (instr->RightIsPowerOf2()) { |
1429 return DoDivByPowerOf2I(instr); | 1428 return DoDivByPowerOf2I(instr); |
1430 } else if (instr->right()->IsConstant()) { | 1429 } else if (instr->right()->IsConstant()) { |
1431 return DoDivByConstI(instr); | 1430 return DoDivByConstI(instr); |
1432 } else { | 1431 } else { |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1615 current_block_->UpdateEnvironment(outer); | 1614 current_block_->UpdateEnvironment(outer); |
1616 | 1615 |
1617 return pop; | 1616 return pop; |
1618 } | 1617 } |
1619 | 1618 |
1620 | 1619 |
1621 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { | 1620 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
1622 LOperand* context = UseRegisterAtStart(instr->value()); | 1621 LOperand* context = UseRegisterAtStart(instr->value()); |
1623 LInstruction* result = | 1622 LInstruction* result = |
1624 DefineAsRegister(new(zone()) LLoadContextSlot(context)); | 1623 DefineAsRegister(new(zone()) LLoadContextSlot(context)); |
1625 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; | 1624 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
| 1625 result = AssignEnvironment(result); |
| 1626 } |
| 1627 return result; |
1626 } | 1628 } |
1627 | 1629 |
1628 | 1630 |
1629 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( | 1631 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( |
1630 HLoadFunctionPrototype* instr) { | 1632 HLoadFunctionPrototype* instr) { |
1631 LOperand* function = UseRegister(instr->function()); | 1633 LOperand* function = UseRegister(instr->function()); |
1632 LOperand* temp = TempRegister(); | 1634 LOperand* temp = TempRegister(); |
1633 return AssignEnvironment(DefineAsRegister( | 1635 return AssignEnvironment(DefineAsRegister( |
1634 new(zone()) LLoadFunctionPrototype(function, temp))); | 1636 new(zone()) LLoadFunctionPrototype(function, temp))); |
1635 } | 1637 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1680 ? AssignEnvironment(DefineAsRegister(result)) | 1682 ? AssignEnvironment(DefineAsRegister(result)) |
1681 : DefineAsRegister(result); | 1683 : DefineAsRegister(result); |
1682 } | 1684 } |
1683 } else { | 1685 } else { |
1684 ASSERT((instr->representation().IsInteger32() && | 1686 ASSERT((instr->representation().IsInteger32() && |
1685 !IsDoubleOrFloatElementsKind(instr->elements_kind())) || | 1687 !IsDoubleOrFloatElementsKind(instr->elements_kind())) || |
1686 (instr->representation().IsDouble() && | 1688 (instr->representation().IsDouble() && |
1687 IsDoubleOrFloatElementsKind(instr->elements_kind()))); | 1689 IsDoubleOrFloatElementsKind(instr->elements_kind()))); |
1688 | 1690 |
1689 LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister(); | 1691 LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister(); |
1690 LLoadKeyedExternal* result = | 1692 LInstruction* result = DefineAsRegister( |
1691 new(zone()) LLoadKeyedExternal(elements, key, temp); | 1693 new(zone()) LLoadKeyedExternal(elements, key, temp)); |
1692 // An unsigned int array load might overflow and cause a deopt. Make sure it | 1694 if ((elements_kind == EXTERNAL_UINT32_ELEMENTS || |
1693 // has an environment. | 1695 elements_kind == UINT32_ELEMENTS) && |
1694 if (instr->RequiresHoleCheck() || | 1696 !instr->CheckFlag(HInstruction::kUint32)) { |
1695 elements_kind == EXTERNAL_UINT32_ELEMENTS || | 1697 result = AssignEnvironment(result); |
1696 elements_kind == UINT32_ELEMENTS) { | |
1697 return AssignEnvironment(DefineAsRegister(result)); | |
1698 } else { | |
1699 return DefineAsRegister(result); | |
1700 } | 1698 } |
| 1699 return result; |
1701 } | 1700 } |
1702 } | 1701 } |
1703 | 1702 |
1704 | 1703 |
1705 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1704 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
1706 LOperand* context = UseFixed(instr->context(), cp); | 1705 LOperand* context = UseFixed(instr->context(), cp); |
1707 LOperand* object = UseFixed(instr->object(), x1); | 1706 LOperand* object = UseFixed(instr->object(), x1); |
1708 LOperand* key = UseFixed(instr->key(), x0); | 1707 LOperand* key = UseFixed(instr->key(), x0); |
1709 | 1708 |
1710 LInstruction* result = | 1709 LInstruction* result = |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1878 } | 1877 } |
1879 | 1878 |
1880 | 1879 |
1881 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1880 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
1882 if (instr->representation().IsSmiOrInteger32()) { | 1881 if (instr->representation().IsSmiOrInteger32()) { |
1883 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1882 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1884 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1883 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1885 | 1884 |
1886 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); | 1885 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); |
1887 bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero); | 1886 bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero); |
1888 bool needs_environment = can_overflow || bailout_on_minus_zero; | |
1889 | 1887 |
1890 HValue* least_const = instr->BetterLeftOperand(); | 1888 HValue* least_const = instr->BetterLeftOperand(); |
1891 HValue* most_const = instr->BetterRightOperand(); | 1889 HValue* most_const = instr->BetterRightOperand(); |
1892 | 1890 |
1893 LOperand* left; | |
1894 | |
1895 // LMulConstI can handle a subset of constants: | 1891 // LMulConstI can handle a subset of constants: |
1896 // With support for overflow detection: | 1892 // With support for overflow detection: |
1897 // -1, 0, 1, 2 | 1893 // -1, 0, 1, 2 |
1898 // 2^n, -(2^n) | 1894 // 2^n, -(2^n) |
1899 // Without support for overflow detection: | 1895 // Without support for overflow detection: |
1900 // 2^n + 1, -(2^n - 1) | 1896 // 2^n + 1, -(2^n - 1) |
1901 if (most_const->IsConstant()) { | 1897 if (most_const->IsConstant()) { |
1902 int32_t constant = HConstant::cast(most_const)->Integer32Value(); | 1898 int32_t constant = HConstant::cast(most_const)->Integer32Value(); |
1903 bool small_constant = (constant >= -1) && (constant <= 2); | 1899 bool small_constant = (constant >= -1) && (constant <= 2); |
1904 bool end_range_constant = (constant <= -kMaxInt) || (constant == kMaxInt); | 1900 bool end_range_constant = (constant <= -kMaxInt) || (constant == kMaxInt); |
1905 int32_t constant_abs = Abs(constant); | 1901 int32_t constant_abs = Abs(constant); |
1906 | 1902 |
1907 if (!end_range_constant && | 1903 if (!end_range_constant && |
1908 (small_constant || | 1904 (small_constant || |
1909 (IsPowerOf2(constant_abs)) || | 1905 (IsPowerOf2(constant_abs)) || |
1910 (!can_overflow && (IsPowerOf2(constant_abs + 1) || | 1906 (!can_overflow && (IsPowerOf2(constant_abs + 1) || |
1911 IsPowerOf2(constant_abs - 1))))) { | 1907 IsPowerOf2(constant_abs - 1))))) { |
1912 LConstantOperand* right = UseConstant(most_const); | 1908 LConstantOperand* right = UseConstant(most_const); |
1913 bool need_register = IsPowerOf2(constant_abs) && !small_constant; | 1909 bool need_register = IsPowerOf2(constant_abs) && !small_constant; |
1914 left = need_register ? UseRegister(least_const) | 1910 LOperand* left = need_register ? UseRegister(least_const) |
1915 : UseRegisterAtStart(least_const); | 1911 : UseRegisterAtStart(least_const); |
1916 LMulConstIS* mul = new(zone()) LMulConstIS(left, right); | 1912 LInstruction* result = |
1917 if (needs_environment) AssignEnvironment(mul); | 1913 DefineAsRegister(new(zone()) LMulConstIS(left, right)); |
1918 return DefineAsRegister(mul); | 1914 if ((bailout_on_minus_zero && constant <= 0) || can_overflow) { |
| 1915 result = AssignEnvironment(result); |
| 1916 } |
| 1917 return result; |
1919 } | 1918 } |
1920 } | 1919 } |
1921 | 1920 |
1922 left = UseRegisterAtStart(least_const); | |
1923 // LMulI/S can handle all cases, but it requires that a register is | 1921 // LMulI/S can handle all cases, but it requires that a register is |
1924 // allocated for the second operand. | 1922 // allocated for the second operand. |
1925 LInstruction* result; | 1923 LOperand* left = UseRegisterAtStart(least_const); |
1926 if (instr->representation().IsSmi()) { | 1924 LOperand* right = UseRegisterAtStart(most_const); |
1927 LOperand* right = UseRegisterAtStart(most_const); | 1925 LInstruction* result = instr->representation().IsSmi() |
1928 result = DefineAsRegister(new(zone()) LMulS(left, right)); | 1926 ? DefineAsRegister(new(zone()) LMulS(left, right)) |
1929 } else { | 1927 : DefineAsRegister(new(zone()) LMulI(left, right)); |
1930 LOperand* right = UseRegisterAtStart(most_const); | 1928 if ((bailout_on_minus_zero && least_const != most_const) || can_overflow) { |
1931 result = DefineAsRegister(new(zone()) LMulI(left, right)); | 1929 result = AssignEnvironment(result); |
1932 } | 1930 } |
1933 if (needs_environment) AssignEnvironment(result); | |
1934 return result; | 1931 return result; |
1935 } else if (instr->representation().IsDouble()) { | 1932 } else if (instr->representation().IsDouble()) { |
1936 return DoArithmeticD(Token::MUL, instr); | 1933 return DoArithmeticD(Token::MUL, instr); |
1937 } else { | 1934 } else { |
1938 return DoArithmeticT(Token::MUL, instr); | 1935 return DoArithmeticT(Token::MUL, instr); |
1939 } | 1936 } |
1940 } | 1937 } |
1941 | 1938 |
1942 | 1939 |
1943 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { | 1940 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2153 if (instr->NeedsWriteBarrier()) { | 2150 if (instr->NeedsWriteBarrier()) { |
2154 // TODO(all): Replace these constraints when RecordWriteStub has been | 2151 // TODO(all): Replace these constraints when RecordWriteStub has been |
2155 // rewritten. | 2152 // rewritten. |
2156 context = UseRegisterAndClobber(instr->context()); | 2153 context = UseRegisterAndClobber(instr->context()); |
2157 value = UseRegisterAndClobber(instr->value()); | 2154 value = UseRegisterAndClobber(instr->value()); |
2158 } else { | 2155 } else { |
2159 context = UseRegister(instr->context()); | 2156 context = UseRegister(instr->context()); |
2160 value = UseRegister(instr->value()); | 2157 value = UseRegister(instr->value()); |
2161 } | 2158 } |
2162 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp); | 2159 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp); |
2163 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; | 2160 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
| 2161 result = AssignEnvironment(result); |
| 2162 } |
| 2163 return result; |
2164 } | 2164 } |
2165 | 2165 |
2166 | 2166 |
2167 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { | 2167 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { |
2168 LOperand* value = UseRegister(instr->value()); | 2168 LOperand* value = UseRegister(instr->value()); |
2169 if (instr->RequiresHoleCheck()) { | 2169 if (instr->RequiresHoleCheck()) { |
2170 return AssignEnvironment(new(zone()) LStoreGlobalCell(value, | 2170 return AssignEnvironment(new(zone()) LStoreGlobalCell(value, |
2171 TempRegister(), | 2171 TempRegister(), |
2172 TempRegister())); | 2172 TempRegister())); |
2173 } else { | 2173 } else { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2287 return MarkAsCall(DefineFixed(result, x0), instr); | 2287 return MarkAsCall(DefineFixed(result, x0), instr); |
2288 } | 2288 } |
2289 | 2289 |
2290 | 2290 |
2291 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { | 2291 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
2292 LOperand* string = UseRegisterAndClobber(instr->string()); | 2292 LOperand* string = UseRegisterAndClobber(instr->string()); |
2293 LOperand* index = UseRegisterAndClobber(instr->index()); | 2293 LOperand* index = UseRegisterAndClobber(instr->index()); |
2294 LOperand* context = UseAny(instr->context()); | 2294 LOperand* context = UseAny(instr->context()); |
2295 LStringCharCodeAt* result = | 2295 LStringCharCodeAt* result = |
2296 new(zone()) LStringCharCodeAt(context, string, index); | 2296 new(zone()) LStringCharCodeAt(context, string, index); |
2297 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 2297 return AssignPointerMap(DefineAsRegister(result)); |
2298 } | 2298 } |
2299 | 2299 |
2300 | 2300 |
2301 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { | 2301 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { |
2302 LOperand* char_code = UseRegister(instr->value()); | 2302 LOperand* char_code = UseRegister(instr->value()); |
2303 LOperand* context = UseAny(instr->context()); | 2303 LOperand* context = UseAny(instr->context()); |
2304 LStringCharFromCode* result = | 2304 LStringCharFromCode* result = |
2305 new(zone()) LStringCharFromCode(context, char_code); | 2305 new(zone()) LStringCharFromCode(context, char_code); |
2306 return AssignPointerMap(DefineAsRegister(result)); | 2306 return AssignPointerMap(DefineAsRegister(result)); |
2307 } | 2307 } |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2423 case kMathAbs: { | 2423 case kMathAbs: { |
2424 Representation r = instr->representation(); | 2424 Representation r = instr->representation(); |
2425 if (r.IsTagged()) { | 2425 if (r.IsTagged()) { |
2426 // The tagged case might need to allocate a HeapNumber for the result, | 2426 // The tagged case might need to allocate a HeapNumber for the result, |
2427 // so it is handled by a separate LInstruction. | 2427 // so it is handled by a separate LInstruction. |
2428 LOperand* context = UseFixed(instr->context(), cp); | 2428 LOperand* context = UseFixed(instr->context(), cp); |
2429 LOperand* input = UseRegister(instr->value()); | 2429 LOperand* input = UseRegister(instr->value()); |
2430 LOperand* temp1 = TempRegister(); | 2430 LOperand* temp1 = TempRegister(); |
2431 LOperand* temp2 = TempRegister(); | 2431 LOperand* temp2 = TempRegister(); |
2432 LOperand* temp3 = TempRegister(); | 2432 LOperand* temp3 = TempRegister(); |
2433 LMathAbsTagged* result = | 2433 LInstruction* result = DefineAsRegister( |
2434 new(zone()) LMathAbsTagged(context, input, temp1, temp2, temp3); | 2434 new(zone()) LMathAbsTagged(context, input, temp1, temp2, temp3)); |
2435 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 2435 // Note: Only deopts in deferred code. |
| 2436 return AssignEnvironment(AssignPointerMap(result)); |
2436 } else { | 2437 } else { |
2437 LOperand* input = UseRegisterAtStart(instr->value()); | 2438 LOperand* input = UseRegisterAtStart(instr->value()); |
2438 LMathAbs* result = new(zone()) LMathAbs(input); | 2439 LInstruction* result = DefineAsRegister(new(zone()) LMathAbs(input)); |
2439 if (r.IsDouble()) { | 2440 if (!r.IsDouble()) result = AssignEnvironment(result); |
2440 // The Double case can never fail so it doesn't need an environment. | 2441 return result; |
2441 return DefineAsRegister(result); | |
2442 } else { | |
2443 ASSERT(r.IsInteger32() || r.IsSmi()); | |
2444 // The Integer32 and Smi cases need an environment because they can | |
2445 // deoptimize on minimum representable number. | |
2446 return AssignEnvironment(DefineAsRegister(result)); | |
2447 } | |
2448 } | 2442 } |
2449 } | 2443 } |
2450 case kMathExp: { | 2444 case kMathExp: { |
2451 ASSERT(instr->representation().IsDouble()); | 2445 ASSERT(instr->representation().IsDouble()); |
2452 ASSERT(instr->value()->representation().IsDouble()); | 2446 ASSERT(instr->value()->representation().IsDouble()); |
2453 LOperand* input = UseRegister(instr->value()); | 2447 LOperand* input = UseRegister(instr->value()); |
2454 // TODO(all): Implement TempFPRegister. | 2448 // TODO(all): Implement TempFPRegister. |
2455 LOperand* double_temp1 = FixedTemp(d24); // This was chosen arbitrarily. | 2449 LOperand* double_temp1 = FixedTemp(d24); // This was chosen arbitrarily. |
2456 LOperand* temp1 = TempRegister(); | 2450 LOperand* temp1 = TempRegister(); |
2457 LOperand* temp2 = TempRegister(); | 2451 LOperand* temp2 = TempRegister(); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2570 | 2564 |
2571 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { | 2565 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { |
2572 LOperand* receiver = UseRegister(instr->receiver()); | 2566 LOperand* receiver = UseRegister(instr->receiver()); |
2573 LOperand* function = UseRegister(instr->function()); | 2567 LOperand* function = UseRegister(instr->function()); |
2574 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function); | 2568 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function); |
2575 return AssignEnvironment(DefineAsRegister(result)); | 2569 return AssignEnvironment(DefineAsRegister(result)); |
2576 } | 2570 } |
2577 | 2571 |
2578 | 2572 |
2579 } } // namespace v8::internal | 2573 } } // namespace v8::internal |
OLD | NEW |