| 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 |