OLD | NEW |
1 // Copyright 2011 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 return result; | 1040 return result; |
1041 } | 1041 } |
1042 | 1042 |
1043 | 1043 |
1044 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 1044 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
1045 return new(zone()) LGoto(instr->FirstSuccessor()->block_id()); | 1045 return new(zone()) LGoto(instr->FirstSuccessor()->block_id()); |
1046 } | 1046 } |
1047 | 1047 |
1048 | 1048 |
1049 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 1049 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
1050 HValue* v = instr->value(); | 1050 HValue* value = instr->value(); |
1051 if (v->EmitAtUses()) { | 1051 if (value->EmitAtUses()) { |
1052 ASSERT(v->IsConstant()); | 1052 ASSERT(value->IsConstant()); |
1053 ASSERT(!v->representation().IsDouble()); | 1053 ASSERT(!value->representation().IsDouble()); |
1054 HBasicBlock* successor = HConstant::cast(v)->ToBoolean() | 1054 HBasicBlock* successor = HConstant::cast(value)->ToBoolean() |
1055 ? instr->FirstSuccessor() | 1055 ? instr->FirstSuccessor() |
1056 : instr->SecondSuccessor(); | 1056 : instr->SecondSuccessor(); |
1057 return new(zone()) LGoto(successor->block_id()); | 1057 return new(zone()) LGoto(successor->block_id()); |
1058 } | 1058 } |
| 1059 |
| 1060 // Untagged integers or doubles, smis and booleans don't require a |
| 1061 // deoptimization environment nor a temp register. |
| 1062 Representation rep = value->representation(); |
| 1063 HType type = value->type(); |
| 1064 if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { |
| 1065 return new(zone()) LBranch(UseRegister(value), NULL); |
| 1066 } |
| 1067 |
1059 ToBooleanStub::Types expected = instr->expected_input_types(); | 1068 ToBooleanStub::Types expected = instr->expected_input_types(); |
1060 // We need a temporary register when we have to access the map *or* we have | 1069 // We need a temporary register when we have to access the map *or* we have |
1061 // no type info yet, in which case we handle all cases (including the ones | 1070 // no type info yet, in which case we handle all cases (including the ones |
1062 // involving maps). | 1071 // involving maps). |
1063 bool needs_temp = expected.NeedsMap() || expected.IsEmpty(); | 1072 bool needs_temp = expected.NeedsMap() || expected.IsEmpty(); |
1064 LOperand* temp = needs_temp ? TempRegister() : NULL; | 1073 LOperand* temp = needs_temp ? TempRegister() : NULL; |
1065 return AssignEnvironment(new(zone()) LBranch(UseRegister(v), temp)); | 1074 return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp)); |
1066 } | 1075 } |
1067 | 1076 |
1068 | 1077 |
1069 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 1078 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
1070 ASSERT(instr->value()->representation().IsTagged()); | 1079 ASSERT(instr->value()->representation().IsTagged()); |
1071 LOperand* value = UseRegisterAtStart(instr->value()); | 1080 LOperand* value = UseRegisterAtStart(instr->value()); |
1072 return new(zone()) LCmpMapAndBranch(value); | 1081 return new(zone()) LCmpMapAndBranch(value); |
1073 } | 1082 } |
1074 | 1083 |
1075 | 1084 |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1381 if (instr->representation().IsInteger32()) { | 1390 if (instr->representation().IsInteger32()) { |
1382 ASSERT(instr->left()->representation().IsInteger32()); | 1391 ASSERT(instr->left()->representation().IsInteger32()); |
1383 ASSERT(instr->right()->representation().IsInteger32()); | 1392 ASSERT(instr->right()->representation().IsInteger32()); |
1384 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 1393 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); |
1385 LOperand* right = UseOrConstant(instr->MostConstantOperand()); | 1394 LOperand* right = UseOrConstant(instr->MostConstantOperand()); |
1386 LOperand* temp = NULL; | 1395 LOperand* temp = NULL; |
1387 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1396 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1388 temp = TempRegister(); | 1397 temp = TempRegister(); |
1389 } | 1398 } |
1390 LMulI* mul = new(zone()) LMulI(left, right, temp); | 1399 LMulI* mul = new(zone()) LMulI(left, right, temp); |
1391 return AssignEnvironment(DefineSameAsFirst(mul)); | 1400 if (instr->CheckFlag(HValue::kCanOverflow) || |
| 1401 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1402 AssignEnvironment(mul); |
| 1403 } |
| 1404 return DefineSameAsFirst(mul); |
1392 } else if (instr->representation().IsDouble()) { | 1405 } else if (instr->representation().IsDouble()) { |
1393 return DoArithmeticD(Token::MUL, instr); | 1406 return DoArithmeticD(Token::MUL, instr); |
1394 } else { | 1407 } else { |
1395 ASSERT(instr->representation().IsTagged()); | 1408 ASSERT(instr->representation().IsTagged()); |
1396 return DoArithmeticT(Token::MUL, instr); | 1409 return DoArithmeticT(Token::MUL, instr); |
1397 } | 1410 } |
1398 } | 1411 } |
1399 | 1412 |
1400 | 1413 |
1401 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1414 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1449 LOperand* left = UseFixedDouble(instr->left(), xmm2); | 1462 LOperand* left = UseFixedDouble(instr->left(), xmm2); |
1450 LOperand* right = exponent_type.IsDouble() ? | 1463 LOperand* right = exponent_type.IsDouble() ? |
1451 UseFixedDouble(instr->right(), xmm1) : | 1464 UseFixedDouble(instr->right(), xmm1) : |
1452 UseFixed(instr->right(), eax); | 1465 UseFixed(instr->right(), eax); |
1453 LPower* result = new(zone()) LPower(left, right); | 1466 LPower* result = new(zone()) LPower(left, right); |
1454 return MarkAsCall(DefineFixedDouble(result, xmm3), instr, | 1467 return MarkAsCall(DefineFixedDouble(result, xmm3), instr, |
1455 CAN_DEOPTIMIZE_EAGERLY); | 1468 CAN_DEOPTIMIZE_EAGERLY); |
1456 } | 1469 } |
1457 | 1470 |
1458 | 1471 |
| 1472 LInstruction* LChunkBuilder::DoRandom(HRandom* instr) { |
| 1473 ASSERT(instr->representation().IsDouble()); |
| 1474 ASSERT(instr->global_object()->representation().IsTagged()); |
| 1475 LOperand* global_object = UseFixed(instr->global_object(), eax); |
| 1476 LRandom* result = new(zone()) LRandom(global_object); |
| 1477 return MarkAsCall(DefineFixedDouble(result, xmm1), instr); |
| 1478 } |
| 1479 |
| 1480 |
1459 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { | 1481 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { |
1460 ASSERT(instr->left()->representation().IsTagged()); | 1482 ASSERT(instr->left()->representation().IsTagged()); |
1461 ASSERT(instr->right()->representation().IsTagged()); | 1483 ASSERT(instr->right()->representation().IsTagged()); |
1462 LOperand* context = UseFixed(instr->context(), esi); | 1484 LOperand* context = UseFixed(instr->context(), esi); |
1463 LOperand* left = UseFixed(instr->left(), edx); | 1485 LOperand* left = UseFixed(instr->left(), edx); |
1464 LOperand* right = UseFixed(instr->right(), eax); | 1486 LOperand* right = UseFixed(instr->right(), eax); |
1465 LCmpT* result = new(zone()) LCmpT(context, left, right); | 1487 LCmpT* result = new(zone()) LCmpT(context, left, right); |
1466 return MarkAsCall(DefineFixed(result, eax), instr); | 1488 return MarkAsCall(DefineFixed(result, eax), instr); |
1467 } | 1489 } |
1468 | 1490 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1581 HHasCachedArrayIndexAndBranch* instr) { | 1603 HHasCachedArrayIndexAndBranch* instr) { |
1582 ASSERT(instr->value()->representation().IsTagged()); | 1604 ASSERT(instr->value()->representation().IsTagged()); |
1583 return new(zone()) LHasCachedArrayIndexAndBranch( | 1605 return new(zone()) LHasCachedArrayIndexAndBranch( |
1584 UseRegisterAtStart(instr->value())); | 1606 UseRegisterAtStart(instr->value())); |
1585 } | 1607 } |
1586 | 1608 |
1587 | 1609 |
1588 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( | 1610 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( |
1589 HClassOfTestAndBranch* instr) { | 1611 HClassOfTestAndBranch* instr) { |
1590 ASSERT(instr->value()->representation().IsTagged()); | 1612 ASSERT(instr->value()->representation().IsTagged()); |
1591 return new(zone()) LClassOfTestAndBranch(UseTempRegister(instr->value()), | 1613 return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()), |
1592 TempRegister(), | 1614 TempRegister(), |
1593 TempRegister()); | 1615 TempRegister()); |
1594 } | 1616 } |
1595 | 1617 |
1596 | 1618 |
1597 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { | 1619 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { |
1598 LOperand* array = UseRegisterAtStart(instr->value()); | 1620 LOperand* array = UseRegisterAtStart(instr->value()); |
1599 return DefineAsRegister(new(zone()) LJSArrayLength(array)); | 1621 return DefineAsRegister(new(zone()) LJSArrayLength(array)); |
1600 } | 1622 } |
1601 | 1623 |
1602 | 1624 |
1603 LInstruction* LChunkBuilder::DoFixedArrayBaseLength( | 1625 LInstruction* LChunkBuilder::DoFixedArrayBaseLength( |
1604 HFixedArrayBaseLength* instr) { | 1626 HFixedArrayBaseLength* instr) { |
1605 LOperand* array = UseRegisterAtStart(instr->value()); | 1627 LOperand* array = UseRegisterAtStart(instr->value()); |
1606 return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array)); | 1628 return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array)); |
1607 } | 1629 } |
1608 | 1630 |
1609 | 1631 |
1610 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { | 1632 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { |
1611 LOperand* object = UseRegisterAtStart(instr->value()); | 1633 LOperand* object = UseRegisterAtStart(instr->value()); |
1612 return DefineAsRegister(new(zone()) LElementsKind(object)); | 1634 return DefineAsRegister(new(zone()) LElementsKind(object)); |
1613 } | 1635 } |
1614 | 1636 |
1615 | 1637 |
1616 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | 1638 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { |
1617 LOperand* object = UseRegister(instr->value()); | 1639 LOperand* object = UseRegister(instr->value()); |
1618 LValueOf* result = new(zone()) LValueOf(object, TempRegister()); | 1640 LValueOf* result = new(zone()) LValueOf(object, TempRegister()); |
1619 return AssignEnvironment(DefineSameAsFirst(result)); | 1641 return DefineSameAsFirst(result); |
1620 } | 1642 } |
1621 | 1643 |
1622 | 1644 |
1623 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1645 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
1624 return AssignEnvironment(new(zone()) LBoundsCheck( | 1646 return AssignEnvironment(new(zone()) LBoundsCheck( |
1625 UseRegisterOrConstantAtStart(instr->index()), | 1647 UseRegisterOrConstantAtStart(instr->index()), |
1626 UseAtStart(instr->length()))); | 1648 UseAtStart(instr->length()))); |
1627 } | 1649 } |
1628 | 1650 |
1629 | 1651 |
(...skipping 23 matching lines...) Expand all Loading... |
1653 return NULL; | 1675 return NULL; |
1654 } | 1676 } |
1655 | 1677 |
1656 | 1678 |
1657 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1679 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
1658 Representation from = instr->from(); | 1680 Representation from = instr->from(); |
1659 Representation to = instr->to(); | 1681 Representation to = instr->to(); |
1660 if (from.IsTagged()) { | 1682 if (from.IsTagged()) { |
1661 if (to.IsDouble()) { | 1683 if (to.IsDouble()) { |
1662 LOperand* value = UseRegister(instr->value()); | 1684 LOperand* value = UseRegister(instr->value()); |
1663 LNumberUntagD* res = new(zone()) LNumberUntagD(value); | 1685 // Temp register only necessary for minus zero check. |
| 1686 LOperand* temp = instr->deoptimize_on_minus_zero() |
| 1687 ? TempRegister() |
| 1688 : NULL; |
| 1689 LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); |
1664 return AssignEnvironment(DefineAsRegister(res)); | 1690 return AssignEnvironment(DefineAsRegister(res)); |
1665 } else { | 1691 } else { |
1666 ASSERT(to.IsInteger32()); | 1692 ASSERT(to.IsInteger32()); |
1667 LOperand* value = UseRegister(instr->value()); | 1693 LOperand* value = UseRegister(instr->value()); |
1668 bool needs_check = !instr->value()->type().IsSmi(); | 1694 bool needs_check = !instr->value()->type().IsSmi(); |
1669 if (needs_check) { | 1695 if (needs_check) { |
1670 bool truncating = instr->CanTruncateToInt32(); | 1696 bool truncating = instr->CanTruncateToInt32(); |
1671 LOperand* xmm_temp = | 1697 LOperand* xmm_temp = |
1672 (truncating && CpuFeatures::IsSupported(SSE3)) | 1698 (truncating && CpuFeatures::IsSupported(SSE3)) |
1673 ? NULL | 1699 ? NULL |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1949 } | 1975 } |
1950 | 1976 |
1951 | 1977 |
1952 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( | 1978 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( |
1953 HLoadKeyedFastElement* instr) { | 1979 HLoadKeyedFastElement* instr) { |
1954 ASSERT(instr->representation().IsTagged()); | 1980 ASSERT(instr->representation().IsTagged()); |
1955 ASSERT(instr->key()->representation().IsInteger32()); | 1981 ASSERT(instr->key()->representation().IsInteger32()); |
1956 LOperand* obj = UseRegisterAtStart(instr->object()); | 1982 LOperand* obj = UseRegisterAtStart(instr->object()); |
1957 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 1983 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
1958 LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key); | 1984 LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key); |
1959 return AssignEnvironment(DefineAsRegister(result)); | 1985 if (instr->RequiresHoleCheck()) AssignEnvironment(result); |
| 1986 return DefineAsRegister(result); |
1960 } | 1987 } |
1961 | 1988 |
1962 | 1989 |
1963 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement( | 1990 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement( |
1964 HLoadKeyedFastDoubleElement* instr) { | 1991 HLoadKeyedFastDoubleElement* instr) { |
1965 ASSERT(instr->representation().IsDouble()); | 1992 ASSERT(instr->representation().IsDouble()); |
1966 ASSERT(instr->key()->representation().IsInteger32()); | 1993 ASSERT(instr->key()->representation().IsInteger32()); |
1967 LOperand* elements = UseRegisterAtStart(instr->elements()); | 1994 LOperand* elements = UseRegisterAtStart(instr->elements()); |
1968 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 1995 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
1969 LLoadKeyedFastDoubleElement* result = | 1996 LLoadKeyedFastDoubleElement* result = |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2374 LOperand* key = UseOrConstantAtStart(instr->key()); | 2401 LOperand* key = UseOrConstantAtStart(instr->key()); |
2375 LOperand* object = UseOrConstantAtStart(instr->object()); | 2402 LOperand* object = UseOrConstantAtStart(instr->object()); |
2376 LIn* result = new(zone()) LIn(context, key, object); | 2403 LIn* result = new(zone()) LIn(context, key, object); |
2377 return MarkAsCall(DefineFixed(result, eax), instr); | 2404 return MarkAsCall(DefineFixed(result, eax), instr); |
2378 } | 2405 } |
2379 | 2406 |
2380 | 2407 |
2381 } } // namespace v8::internal | 2408 } } // namespace v8::internal |
2382 | 2409 |
2383 #endif // V8_TARGET_ARCH_IA32 | 2410 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |