| 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 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1294 | 1294 |
| 1295 HValue* current_capacity = AddLoadFixedArrayLength(elements); | 1295 HValue* current_capacity = AddLoadFixedArrayLength(elements); |
| 1296 | 1296 |
| 1297 IfBuilder capacity_checker(this); | 1297 IfBuilder capacity_checker(this); |
| 1298 | 1298 |
| 1299 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, | 1299 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, |
| 1300 Token::GTE); | 1300 Token::GTE); |
| 1301 capacity_checker.Then(); | 1301 capacity_checker.Then(); |
| 1302 | 1302 |
| 1303 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); | 1303 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); |
| 1304 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap); | 1304 HValue* max_capacity = AddUncasted<HAdd>(current_capacity, max_gap); |
| 1305 IfBuilder key_checker(this); | 1305 IfBuilder key_checker(this); |
| 1306 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); | 1306 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); |
| 1307 key_checker.Then(); | 1307 key_checker.Then(); |
| 1308 key_checker.ElseDeopt("Key out of capacity range"); | 1308 key_checker.ElseDeopt("Key out of capacity range"); |
| 1309 key_checker.End(); | 1309 key_checker.End(); |
| 1310 | 1310 |
| 1311 HValue* new_capacity = BuildNewElementsCapacity(key); | 1311 HValue* new_capacity = BuildNewElementsCapacity(key); |
| 1312 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1312 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
| 1313 kind, kind, length, | 1313 kind, kind, length, |
| 1314 new_capacity); | 1314 new_capacity); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1411 HValue* hash, | 1411 HValue* hash, |
| 1412 HValue* mask, | 1412 HValue* mask, |
| 1413 int current_probe) { | 1413 int current_probe) { |
| 1414 if (current_probe == kNumberDictionaryProbes) { | 1414 if (current_probe == kNumberDictionaryProbes) { |
| 1415 return NULL; | 1415 return NULL; |
| 1416 } | 1416 } |
| 1417 | 1417 |
| 1418 int32_t offset = SeededNumberDictionary::GetProbeOffset(current_probe); | 1418 int32_t offset = SeededNumberDictionary::GetProbeOffset(current_probe); |
| 1419 HValue* raw_index = (current_probe == 0) | 1419 HValue* raw_index = (current_probe == 0) |
| 1420 ? hash | 1420 ? hash |
| 1421 : Add<HAdd>(hash, Add<HConstant>(offset)); | 1421 : AddUncasted<HAdd>(hash, Add<HConstant>(offset)); |
| 1422 raw_index = Add<HBitwise>(Token::BIT_AND, raw_index, mask); | 1422 raw_index = AddUncasted<HBitwise>(Token::BIT_AND, raw_index, mask); |
| 1423 int32_t entry_size = SeededNumberDictionary::kEntrySize; | 1423 int32_t entry_size = SeededNumberDictionary::kEntrySize; |
| 1424 raw_index = Add<HMul>(raw_index, Add<HConstant>(entry_size)); | 1424 raw_index = AddUncasted<HMul>(raw_index, Add<HConstant>(entry_size)); |
| 1425 raw_index->ClearFlag(HValue::kCanOverflow); | 1425 raw_index->ClearFlag(HValue::kCanOverflow); |
| 1426 | 1426 |
| 1427 int32_t base_offset = SeededNumberDictionary::kElementsStartIndex; | 1427 int32_t base_offset = SeededNumberDictionary::kElementsStartIndex; |
| 1428 HValue* key_index = Add<HAdd>(raw_index, Add<HConstant>(base_offset)); | 1428 HValue* key_index = AddUncasted<HAdd>(raw_index, Add<HConstant>(base_offset)); |
| 1429 key_index->ClearFlag(HValue::kCanOverflow); | 1429 key_index->ClearFlag(HValue::kCanOverflow); |
| 1430 | 1430 |
| 1431 HValue* candidate_key = Add<HLoadKeyed>(elements, key_index, | 1431 HValue* candidate_key = Add<HLoadKeyed>(elements, key_index, |
| 1432 static_cast<HValue*>(NULL), | 1432 static_cast<HValue*>(NULL), |
| 1433 FAST_SMI_ELEMENTS); | 1433 FAST_SMI_ELEMENTS); |
| 1434 | 1434 |
| 1435 IfBuilder key_compare(this); | 1435 IfBuilder key_compare(this); |
| 1436 key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key); | 1436 key_compare.IfNot<HCompareObjectEqAndBranch>(key, candidate_key); |
| 1437 key_compare.Then(); | 1437 key_compare.Then(); |
| 1438 { | 1438 { |
| 1439 // Key at the current probe doesn't match, try at the next probe. | 1439 // Key at the current probe doesn't match, try at the next probe. |
| 1440 HValue* result = BuildUncheckedDictionaryElementLoadHelper( | 1440 HValue* result = BuildUncheckedDictionaryElementLoadHelper( |
| 1441 elements, key, hash, mask, current_probe + 1); | 1441 elements, key, hash, mask, current_probe + 1); |
| 1442 if (result == NULL) { | 1442 if (result == NULL) { |
| 1443 key_compare.Deopt("probes exhausted in keyed load dictionary lookup"); | 1443 key_compare.Deopt("probes exhausted in keyed load dictionary lookup"); |
| 1444 result = graph()->GetConstantUndefined(); | 1444 result = graph()->GetConstantUndefined(); |
| 1445 } else { | 1445 } else { |
| 1446 Push(result); | 1446 Push(result); |
| 1447 } | 1447 } |
| 1448 } | 1448 } |
| 1449 key_compare.Else(); | 1449 key_compare.Else(); |
| 1450 { | 1450 { |
| 1451 // Key at current probe matches. Details must be zero, otherwise the | 1451 // Key at current probe matches. Details must be zero, otherwise the |
| 1452 // dictionary element requires special handling. | 1452 // dictionary element requires special handling. |
| 1453 HValue* details_index = Add<HAdd>(raw_index, | 1453 HValue* details_index = AddUncasted<HAdd>( |
| 1454 Add<HConstant>(base_offset + 2)); | 1454 raw_index, Add<HConstant>(base_offset + 2)); |
| 1455 details_index->ClearFlag(HValue::kCanOverflow); | 1455 details_index->ClearFlag(HValue::kCanOverflow); |
| 1456 | 1456 |
| 1457 HValue* details = Add<HLoadKeyed>(elements, details_index, | 1457 HValue* details = Add<HLoadKeyed>(elements, details_index, |
| 1458 static_cast<HValue*>(NULL), | 1458 static_cast<HValue*>(NULL), |
| 1459 FAST_SMI_ELEMENTS); | 1459 FAST_SMI_ELEMENTS); |
| 1460 IfBuilder details_compare(this); | 1460 IfBuilder details_compare(this); |
| 1461 details_compare.If<HCompareNumericAndBranch>(details, | 1461 details_compare.If<HCompareNumericAndBranch>(details, |
| 1462 graph()->GetConstant0(), | 1462 graph()->GetConstant0(), |
| 1463 Token::NE); | 1463 Token::NE); |
| 1464 details_compare.ThenDeopt("keyed load dictionary element not fast case"); | 1464 details_compare.ThenDeopt("keyed load dictionary element not fast case"); |
| 1465 | 1465 |
| 1466 details_compare.Else(); | 1466 details_compare.Else(); |
| 1467 { | 1467 { |
| 1468 // Key matches and details are zero --> fast case. Load and return the | 1468 // Key matches and details are zero --> fast case. Load and return the |
| 1469 // value. | 1469 // value. |
| 1470 HValue* result_index = Add<HAdd>(raw_index, | 1470 HValue* result_index = AddUncasted<HAdd>( |
| 1471 Add<HConstant>(base_offset + 1)); | 1471 raw_index, Add<HConstant>(base_offset + 1)); |
| 1472 result_index->ClearFlag(HValue::kCanOverflow); | 1472 result_index->ClearFlag(HValue::kCanOverflow); |
| 1473 | 1473 |
| 1474 Push(Add<HLoadKeyed>(elements, result_index, | 1474 Push(Add<HLoadKeyed>(elements, result_index, |
| 1475 static_cast<HValue*>(NULL), | 1475 static_cast<HValue*>(NULL), |
| 1476 FAST_ELEMENTS)); | 1476 FAST_ELEMENTS)); |
| 1477 } | 1477 } |
| 1478 details_compare.End(); | 1478 details_compare.End(); |
| 1479 } | 1479 } |
| 1480 key_compare.End(); | 1480 key_compare.End(); |
| 1481 | 1481 |
| 1482 return Pop(); | 1482 return Pop(); |
| 1483 } | 1483 } |
| 1484 | 1484 |
| 1485 | 1485 |
| 1486 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) { | 1486 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) { |
| 1487 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed()); | 1487 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed()); |
| 1488 HValue* seed = Add<HConstant>(seed_value); | 1488 HValue* seed = Add<HConstant>(seed_value); |
| 1489 HValue* hash = Add<HBitwise>(Token::BIT_XOR, index, seed); | 1489 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed); |
| 1490 | 1490 |
| 1491 // hash = ~hash + (hash << 15); | 1491 // hash = ~hash + (hash << 15); |
| 1492 HValue* shifted_hash = Add<HShl>(hash, Add<HConstant>(15)); | 1492 HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15)); |
| 1493 HValue* not_hash = Add<HBitwise>(Token::BIT_XOR, hash, | 1493 HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, |
| 1494 graph()->GetConstantMinus1()); | 1494 graph()->GetConstantMinus1()); |
| 1495 hash = Add<HAdd>(shifted_hash, not_hash); | 1495 hash = AddUncasted<HAdd>(shifted_hash, not_hash); |
| 1496 | 1496 |
| 1497 // hash = hash ^ (hash >> 12); | 1497 // hash = hash ^ (hash >> 12); |
| 1498 shifted_hash = Add<HShr>(hash, Add<HConstant>(12)); | 1498 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12)); |
| 1499 hash = Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash); | 1499 hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); |
| 1500 | 1500 |
| 1501 // hash = hash + (hash << 2); | 1501 // hash = hash + (hash << 2); |
| 1502 shifted_hash = Add<HShl>(hash, Add<HConstant>(2)); | 1502 shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2)); |
| 1503 hash = Add<HAdd>(hash, shifted_hash); | 1503 hash = AddUncasted<HAdd>(hash, shifted_hash); |
| 1504 | 1504 |
| 1505 // hash = hash ^ (hash >> 4); | 1505 // hash = hash ^ (hash >> 4); |
| 1506 shifted_hash = Add<HShr>(hash, Add<HConstant>(4)); | 1506 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4)); |
| 1507 hash = Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash); | 1507 hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); |
| 1508 | 1508 |
| 1509 // hash = hash * 2057; | 1509 // hash = hash * 2057; |
| 1510 hash = Add<HMul>(hash, Add<HConstant>(2057)); | 1510 hash = AddUncasted<HMul>(hash, Add<HConstant>(2057)); |
| 1511 hash->ClearFlag(HValue::kCanOverflow); | 1511 hash->ClearFlag(HValue::kCanOverflow); |
| 1512 | 1512 |
| 1513 // hash = hash ^ (hash >> 16); | 1513 // hash = hash ^ (hash >> 16); |
| 1514 shifted_hash = Add<HShr>(hash, Add<HConstant>(16)); | 1514 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16)); |
| 1515 return Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash); | 1515 return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); |
| 1516 } | 1516 } |
| 1517 | 1517 |
| 1518 | 1518 |
| 1519 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver, | 1519 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver, |
| 1520 HValue* key) { | 1520 HValue* key) { |
| 1521 HValue* elements = AddLoadElements(receiver); | 1521 HValue* elements = AddLoadElements(receiver); |
| 1522 | 1522 |
| 1523 HValue* hash = BuildElementIndexHash(key); | 1523 HValue* hash = BuildElementIndexHash(key); |
| 1524 | 1524 |
| 1525 HValue* capacity = Add<HLoadKeyed>( | 1525 HValue* capacity = Add<HLoadKeyed>( |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1555 mask->set_type(HType::Smi()); | 1555 mask->set_type(HType::Smi()); |
| 1556 mask = Add<HSar>(mask, graph()->GetConstant1()); | 1556 mask = Add<HSar>(mask, graph()->GetConstant1()); |
| 1557 mask = Add<HSub>(mask, graph()->GetConstant1()); | 1557 mask = Add<HSub>(mask, graph()->GetConstant1()); |
| 1558 | 1558 |
| 1559 // Check whether object is a smi. | 1559 // Check whether object is a smi. |
| 1560 IfBuilder if_objectissmi(this); | 1560 IfBuilder if_objectissmi(this); |
| 1561 if_objectissmi.If<HIsSmiAndBranch>(object); | 1561 if_objectissmi.If<HIsSmiAndBranch>(object); |
| 1562 if_objectissmi.Then(); | 1562 if_objectissmi.Then(); |
| 1563 { | 1563 { |
| 1564 // Compute hash for smi similar to smi_get_hash(). | 1564 // Compute hash for smi similar to smi_get_hash(). |
| 1565 HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask); | 1565 HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask); |
| 1566 | 1566 |
| 1567 // Load the key. | 1567 // Load the key. |
| 1568 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); | 1568 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1()); |
| 1569 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, | 1569 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, |
| 1570 static_cast<HValue*>(NULL), | 1570 static_cast<HValue*>(NULL), |
| 1571 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | 1571 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 1572 | 1572 |
| 1573 // Check if object == key. | 1573 // Check if object == key. |
| 1574 IfBuilder if_objectiskey(this); | 1574 IfBuilder if_objectiskey(this); |
| 1575 if_objectiskey.If<HCompareObjectEqAndBranch>(object, key); | 1575 if_objectiskey.If<HCompareObjectEqAndBranch>(object, key); |
| 1576 if_objectiskey.Then(); | 1576 if_objectiskey.Then(); |
| 1577 { | 1577 { |
| 1578 // Make the key_index available. | 1578 // Make the key_index available. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1589 IfBuilder if_objectisnumber(this); | 1589 IfBuilder if_objectisnumber(this); |
| 1590 if_objectisnumber.If<HCompareMap>( | 1590 if_objectisnumber.If<HCompareMap>( |
| 1591 object, isolate()->factory()->heap_number_map()); | 1591 object, isolate()->factory()->heap_number_map()); |
| 1592 if_objectisnumber.Then(); | 1592 if_objectisnumber.Then(); |
| 1593 { | 1593 { |
| 1594 // Compute hash for heap number similar to double_get_hash(). | 1594 // Compute hash for heap number similar to double_get_hash(). |
| 1595 HValue* low = Add<HLoadNamedField>( | 1595 HValue* low = Add<HLoadNamedField>( |
| 1596 object, HObjectAccess::ForHeapNumberValueLowestBits()); | 1596 object, HObjectAccess::ForHeapNumberValueLowestBits()); |
| 1597 HValue* high = Add<HLoadNamedField>( | 1597 HValue* high = Add<HLoadNamedField>( |
| 1598 object, HObjectAccess::ForHeapNumberValueHighestBits()); | 1598 object, HObjectAccess::ForHeapNumberValueHighestBits()); |
| 1599 HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high); | 1599 HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high); |
| 1600 hash = Add<HBitwise>(Token::BIT_AND, hash, mask); | 1600 hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask); |
| 1601 | 1601 |
| 1602 // Load the key. | 1602 // Load the key. |
| 1603 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); | 1603 HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1()); |
| 1604 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, | 1604 HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, |
| 1605 static_cast<HValue*>(NULL), | 1605 static_cast<HValue*>(NULL), |
| 1606 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | 1606 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 1607 | 1607 |
| 1608 // Check if key is a heap number (the number string cache contains only | 1608 // Check if key is a heap number (the number string cache contains only |
| 1609 // SMIs and heap number, so it is sufficient to do a SMI check here). | 1609 // SMIs and heap number, so it is sufficient to do a SMI check here). |
| 1610 IfBuilder if_keyisnotsmi(this); | 1610 IfBuilder if_keyisnotsmi(this); |
| 1611 if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key); | 1611 if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key); |
| 1612 if_keyisnotsmi.Then(); | 1612 if_keyisnotsmi.Then(); |
| 1613 { | 1613 { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1639 | 1639 |
| 1640 // Check for cache hit. | 1640 // Check for cache hit. |
| 1641 IfBuilder if_found(this, &found); | 1641 IfBuilder if_found(this, &found); |
| 1642 if_found.Then(); | 1642 if_found.Then(); |
| 1643 { | 1643 { |
| 1644 // Count number to string operation in native code. | 1644 // Count number to string operation in native code. |
| 1645 AddIncrementCounter(isolate()->counters()->number_to_string_native()); | 1645 AddIncrementCounter(isolate()->counters()->number_to_string_native()); |
| 1646 | 1646 |
| 1647 // Load the value in case of cache hit. | 1647 // Load the value in case of cache hit. |
| 1648 HValue* key_index = Pop(); | 1648 HValue* key_index = Pop(); |
| 1649 HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1()); | 1649 HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1()); |
| 1650 Push(Add<HLoadKeyed>(number_string_cache, value_index, | 1650 Push(Add<HLoadKeyed>(number_string_cache, value_index, |
| 1651 static_cast<HValue*>(NULL), | 1651 static_cast<HValue*>(NULL), |
| 1652 FAST_ELEMENTS, ALLOW_RETURN_HOLE)); | 1652 FAST_ELEMENTS, ALLOW_RETURN_HOLE)); |
| 1653 } | 1653 } |
| 1654 if_found.Else(); | 1654 if_found.Else(); |
| 1655 { | 1655 { |
| 1656 // Cache miss, fallback to runtime. | 1656 // Cache miss, fallback to runtime. |
| 1657 Add<HPushArgument>(object); | 1657 Add<HPushArgument>(object); |
| 1658 Push(Add<HCallRuntime>( | 1658 Push(Add<HCallRuntime>( |
| 1659 isolate()->factory()->empty_string(), | 1659 isolate()->factory()->empty_string(), |
| 1660 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), | 1660 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), |
| 1661 1)); | 1661 1)); |
| 1662 } | 1662 } |
| 1663 if_found.End(); | 1663 if_found.End(); |
| 1664 | 1664 |
| 1665 return Pop(); | 1665 return Pop(); |
| 1666 } | 1666 } |
| 1667 | 1667 |
| 1668 | 1668 |
| 1669 HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length, | 1669 HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length, |
| 1670 String::Encoding encoding) { | 1670 String::Encoding encoding) { |
| 1671 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0); | 1671 STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0); |
| 1672 HValue* size = length; | 1672 HValue* size = length; |
| 1673 if (encoding == String::TWO_BYTE_ENCODING) { | 1673 if (encoding == String::TWO_BYTE_ENCODING) { |
| 1674 size = Add<HShl>(length, graph()->GetConstant1()); | 1674 size = AddUncasted<HShl>(length, graph()->GetConstant1()); |
| 1675 size->ClearFlag(HValue::kCanOverflow); | 1675 size->ClearFlag(HValue::kCanOverflow); |
| 1676 size->SetFlag(HValue::kUint32); | 1676 size->SetFlag(HValue::kUint32); |
| 1677 } | 1677 } |
| 1678 size = Add<HAdd>(size, Add<HConstant>(static_cast<int32_t>( | 1678 size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>( |
| 1679 SeqString::kHeaderSize + kObjectAlignmentMask))); | 1679 SeqString::kHeaderSize + kObjectAlignmentMask))); |
| 1680 size->ClearFlag(HValue::kCanOverflow); | 1680 size->ClearFlag(HValue::kCanOverflow); |
| 1681 size = Add<HBitwise>( | 1681 size = AddUncasted<HBitwise>( |
| 1682 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( | 1682 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( |
| 1683 ~kObjectAlignmentMask))); | 1683 ~kObjectAlignmentMask))); |
| 1684 return size; | 1684 return size; |
| 1685 } | 1685 } |
| 1686 | 1686 |
| 1687 | 1687 |
| 1688 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, | 1688 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, |
| 1689 HValue* src_offset, | 1689 HValue* src_offset, |
| 1690 String::Encoding src_encoding, | 1690 String::Encoding src_encoding, |
| 1691 HValue* dst, | 1691 HValue* dst, |
| 1692 HValue* dst_offset, | 1692 HValue* dst_offset, |
| 1693 String::Encoding dst_encoding, | 1693 String::Encoding dst_encoding, |
| 1694 HValue* length) { | 1694 HValue* length) { |
| 1695 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || | 1695 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || |
| 1696 src_encoding == String::ONE_BYTE_ENCODING); | 1696 src_encoding == String::ONE_BYTE_ENCODING); |
| 1697 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); | 1697 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); |
| 1698 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1698 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); |
| 1699 { | 1699 { |
| 1700 HValue* src_index = Add<HAdd>(src_offset, index); | 1700 HValue* src_index = AddUncasted<HAdd>(src_offset, index); |
| 1701 HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index); | 1701 HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index); |
| 1702 HValue* dst_index = Add<HAdd>(dst_offset, index); | 1702 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); |
| 1703 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); | 1703 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); |
| 1704 } | 1704 } |
| 1705 loop.EndBody(); | 1705 loop.EndBody(); |
| 1706 } | 1706 } |
| 1707 | 1707 |
| 1708 | 1708 |
| 1709 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, | 1709 HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left, |
| 1710 HValue* right, | 1710 HValue* right, |
| 1711 PretenureFlag pretenure_flag) { | 1711 PretenureFlag pretenure_flag) { |
| 1712 // Determine the string lengths. | 1712 // Determine the string lengths. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1737 { | 1737 { |
| 1738 // Determine the string instance types. | 1738 // Determine the string instance types. |
| 1739 HLoadNamedField* left_instance_type = Add<HLoadNamedField>( | 1739 HLoadNamedField* left_instance_type = Add<HLoadNamedField>( |
| 1740 Add<HLoadNamedField>(left, HObjectAccess::ForMap()), | 1740 Add<HLoadNamedField>(left, HObjectAccess::ForMap()), |
| 1741 HObjectAccess::ForMapInstanceType()); | 1741 HObjectAccess::ForMapInstanceType()); |
| 1742 HLoadNamedField* right_instance_type = Add<HLoadNamedField>( | 1742 HLoadNamedField* right_instance_type = Add<HLoadNamedField>( |
| 1743 Add<HLoadNamedField>(right, HObjectAccess::ForMap()), | 1743 Add<HLoadNamedField>(right, HObjectAccess::ForMap()), |
| 1744 HObjectAccess::ForMapInstanceType()); | 1744 HObjectAccess::ForMapInstanceType()); |
| 1745 | 1745 |
| 1746 // Compute difference of instance types. | 1746 // Compute difference of instance types. |
| 1747 HValue* xored_instance_types = Add<HBitwise>( | 1747 HValue* xored_instance_types = AddUncasted<HBitwise>( |
| 1748 Token::BIT_XOR, left_instance_type, right_instance_type); | 1748 Token::BIT_XOR, left_instance_type, right_instance_type); |
| 1749 | 1749 |
| 1750 // Compute the length of the resulting string. | 1750 // Compute the length of the resulting string. |
| 1751 HValue* length = Add<HAdd>(left_length, right_length); | 1751 HValue* length = AddUncasted<HAdd>(left_length, right_length); |
| 1752 | 1752 |
| 1753 // Check if we should create a cons string. | 1753 // Check if we should create a cons string. |
| 1754 IfBuilder if_createcons(this); | 1754 IfBuilder if_createcons(this); |
| 1755 if_createcons.If<HCompareNumericAndBranch>( | 1755 if_createcons.If<HCompareNumericAndBranch>( |
| 1756 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); | 1756 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); |
| 1757 if_createcons.Then(); | 1757 if_createcons.Then(); |
| 1758 { | 1758 { |
| 1759 // Allocate the cons string object. HAllocate does not care whether we | 1759 // Allocate the cons string object. HAllocate does not care whether we |
| 1760 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use | 1760 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use |
| 1761 // CONS_STRING_TYPE here. Below we decide whether the cons string is | 1761 // CONS_STRING_TYPE here. Below we decide whether the cons string is |
| 1762 // one-byte or two-byte and set the appropriate map. | 1762 // one-byte or two-byte and set the appropriate map. |
| 1763 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), | 1763 HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize), |
| 1764 HType::String(), pretenure_flag, | 1764 HType::String(), pretenure_flag, |
| 1765 CONS_STRING_TYPE); | 1765 CONS_STRING_TYPE); |
| 1766 | 1766 |
| 1767 // Compute the intersection of instance types. | 1767 // Compute the intersection of instance types. |
| 1768 HValue* anded_instance_types = Add<HBitwise>( | 1768 HValue* anded_instance_types = AddUncasted<HBitwise>( |
| 1769 Token::BIT_AND, left_instance_type, right_instance_type); | 1769 Token::BIT_AND, left_instance_type, right_instance_type); |
| 1770 | 1770 |
| 1771 // We create a one-byte cons string if | 1771 // We create a one-byte cons string if |
| 1772 // 1. both strings are one-byte, or | 1772 // 1. both strings are one-byte, or |
| 1773 // 2. at least one of the strings is two-byte, but happens to contain only | 1773 // 2. at least one of the strings is two-byte, but happens to contain only |
| 1774 // one-byte characters. | 1774 // one-byte characters. |
| 1775 // To do this, we check | 1775 // To do this, we check |
| 1776 // 1. if both strings are one-byte, or if the one-byte data hint is set in | 1776 // 1. if both strings are one-byte, or if the one-byte data hint is set in |
| 1777 // both strings, or | 1777 // both strings, or |
| 1778 // 2. if one of the strings has the one-byte data hint set and the other | 1778 // 2. if one of the strings has the one-byte data hint set and the other |
| 1779 // string is one-byte. | 1779 // string is one-byte. |
| 1780 IfBuilder if_onebyte(this); | 1780 IfBuilder if_onebyte(this); |
| 1781 STATIC_ASSERT(kOneByteStringTag != 0); | 1781 STATIC_ASSERT(kOneByteStringTag != 0); |
| 1782 STATIC_ASSERT(kOneByteDataHintMask != 0); | 1782 STATIC_ASSERT(kOneByteDataHintMask != 0); |
| 1783 if_onebyte.If<HCompareNumericAndBranch>( | 1783 if_onebyte.If<HCompareNumericAndBranch>( |
| 1784 Add<HBitwise>( | 1784 AddUncasted<HBitwise>( |
| 1785 Token::BIT_AND, anded_instance_types, | 1785 Token::BIT_AND, anded_instance_types, |
| 1786 Add<HConstant>(static_cast<int32_t>( | 1786 Add<HConstant>(static_cast<int32_t>( |
| 1787 kStringEncodingMask | kOneByteDataHintMask))), | 1787 kStringEncodingMask | kOneByteDataHintMask))), |
| 1788 graph()->GetConstant0(), Token::NE); | 1788 graph()->GetConstant0(), Token::NE); |
| 1789 if_onebyte.Or(); | 1789 if_onebyte.Or(); |
| 1790 STATIC_ASSERT(kOneByteStringTag != 0 && | 1790 STATIC_ASSERT(kOneByteStringTag != 0 && |
| 1791 kOneByteDataHintTag != 0 && | 1791 kOneByteDataHintTag != 0 && |
| 1792 kOneByteDataHintTag != kOneByteStringTag); | 1792 kOneByteDataHintTag != kOneByteStringTag); |
| 1793 if_onebyte.If<HCompareNumericAndBranch>( | 1793 if_onebyte.If<HCompareNumericAndBranch>( |
| 1794 Add<HBitwise>( | 1794 AddUncasted<HBitwise>( |
| 1795 Token::BIT_AND, xored_instance_types, | 1795 Token::BIT_AND, xored_instance_types, |
| 1796 Add<HConstant>(static_cast<int32_t>( | 1796 Add<HConstant>(static_cast<int32_t>( |
| 1797 kOneByteStringTag | kOneByteDataHintTag))), | 1797 kOneByteStringTag | kOneByteDataHintTag))), |
| 1798 Add<HConstant>(static_cast<int32_t>( | 1798 Add<HConstant>(static_cast<int32_t>( |
| 1799 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); | 1799 kOneByteStringTag | kOneByteDataHintTag)), Token::EQ); |
| 1800 if_onebyte.Then(); | 1800 if_onebyte.Then(); |
| 1801 { | 1801 { |
| 1802 // We can safely skip the write barrier for storing the map here. | 1802 // We can safely skip the write barrier for storing the map here. |
| 1803 Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); | 1803 Handle<Map> map = isolate()->factory()->cons_ascii_string_map(); |
| 1804 AddStoreMapConstantNoWriteBarrier(string, map); | 1804 AddStoreMapConstantNoWriteBarrier(string, map); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1818 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left); | 1818 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left); |
| 1819 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(), | 1819 Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(), |
| 1820 right); | 1820 right); |
| 1821 | 1821 |
| 1822 // Cons string is result. | 1822 // Cons string is result. |
| 1823 Push(string); | 1823 Push(string); |
| 1824 } | 1824 } |
| 1825 if_createcons.Else(); | 1825 if_createcons.Else(); |
| 1826 { | 1826 { |
| 1827 // Compute union of instance types. | 1827 // Compute union of instance types. |
| 1828 HValue* ored_instance_types = Add<HBitwise>( | 1828 HValue* ored_instance_types = AddUncasted<HBitwise>( |
| 1829 Token::BIT_OR, left_instance_type, right_instance_type); | 1829 Token::BIT_OR, left_instance_type, right_instance_type); |
| 1830 | 1830 |
| 1831 // Check if both strings have the same encoding and both are | 1831 // Check if both strings have the same encoding and both are |
| 1832 // sequential. | 1832 // sequential. |
| 1833 IfBuilder if_sameencodingandsequential(this); | 1833 IfBuilder if_sameencodingandsequential(this); |
| 1834 if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 1834 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
| 1835 Add<HBitwise>( | 1835 AddUncasted<HBitwise>( |
| 1836 Token::BIT_AND, xored_instance_types, | 1836 Token::BIT_AND, xored_instance_types, |
| 1837 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | 1837 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
| 1838 graph()->GetConstant0(), Token::EQ); | 1838 graph()->GetConstant0(), Token::EQ); |
| 1839 if_sameencodingandsequential.And(); | 1839 if_sameencodingandsequential.And(); |
| 1840 STATIC_ASSERT(kSeqStringTag == 0); | 1840 STATIC_ASSERT(kSeqStringTag == 0); |
| 1841 if_sameencodingandsequential.If<HCompareNumericAndBranch>( | 1841 if_sameencodingandsequential.If<HCompareNumericAndBranch>( |
| 1842 Add<HBitwise>( | 1842 AddUncasted<HBitwise>( |
| 1843 Token::BIT_AND, ored_instance_types, | 1843 Token::BIT_AND, ored_instance_types, |
| 1844 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), | 1844 Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))), |
| 1845 graph()->GetConstant0(), Token::EQ); | 1845 graph()->GetConstant0(), Token::EQ); |
| 1846 if_sameencodingandsequential.Then(); | 1846 if_sameencodingandsequential.Then(); |
| 1847 { | 1847 { |
| 1848 // Check if the result is a one-byte string. | 1848 // Check if the result is a one-byte string. |
| 1849 IfBuilder if_onebyte(this); | 1849 IfBuilder if_onebyte(this); |
| 1850 STATIC_ASSERT(kOneByteStringTag != 0); | 1850 STATIC_ASSERT(kOneByteStringTag != 0); |
| 1851 if_onebyte.If<HCompareNumericAndBranch>( | 1851 if_onebyte.If<HCompareNumericAndBranch>( |
| 1852 Add<HBitwise>( | 1852 AddUncasted<HBitwise>( |
| 1853 Token::BIT_AND, ored_instance_types, | 1853 Token::BIT_AND, ored_instance_types, |
| 1854 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), | 1854 Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))), |
| 1855 graph()->GetConstant0(), Token::NE); | 1855 graph()->GetConstant0(), Token::NE); |
| 1856 if_onebyte.Then(); | 1856 if_onebyte.Then(); |
| 1857 { | 1857 { |
| 1858 // Calculate the number of bytes needed for the characters in the | 1858 // Calculate the number of bytes needed for the characters in the |
| 1859 // string while observing object alignment. | 1859 // string while observing object alignment. |
| 1860 HValue* size = BuildSeqStringSizeFor( | 1860 HValue* size = BuildSeqStringSizeFor( |
| 1861 length, String::ONE_BYTE_ENCODING); | 1861 length, String::ONE_BYTE_ENCODING); |
| 1862 | 1862 |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2165 | 2165 |
| 2166 if (IsFastDoubleElementsKind(kind)) { | 2166 if (IsFastDoubleElementsKind(kind)) { |
| 2167 elements_size = kDoubleSize; | 2167 elements_size = kDoubleSize; |
| 2168 instance_type = FIXED_DOUBLE_ARRAY_TYPE; | 2168 instance_type = FIXED_DOUBLE_ARRAY_TYPE; |
| 2169 } else { | 2169 } else { |
| 2170 elements_size = kPointerSize; | 2170 elements_size = kPointerSize; |
| 2171 instance_type = FIXED_ARRAY_TYPE; | 2171 instance_type = FIXED_ARRAY_TYPE; |
| 2172 } | 2172 } |
| 2173 | 2173 |
| 2174 HConstant* elements_size_value = Add<HConstant>(elements_size); | 2174 HConstant* elements_size_value = Add<HConstant>(elements_size); |
| 2175 HValue* mul = Add<HMul>(capacity, elements_size_value); | 2175 HValue* mul = AddUncasted<HMul>(capacity, elements_size_value); |
| 2176 mul->ClearFlag(HValue::kCanOverflow); | 2176 mul->ClearFlag(HValue::kCanOverflow); |
| 2177 | 2177 |
| 2178 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); | 2178 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); |
| 2179 HValue* total_size = Add<HAdd>(mul, header_size); | 2179 HValue* total_size = AddUncasted<HAdd>(mul, header_size); |
| 2180 total_size->ClearFlag(HValue::kCanOverflow); | 2180 total_size->ClearFlag(HValue::kCanOverflow); |
| 2181 | 2181 |
| 2182 return Add<HAllocate>(total_size, HType::JSArray(), | 2182 return Add<HAllocate>(total_size, HType::JSArray(), |
| 2183 isolate()->heap()->GetPretenureMode(), instance_type); | 2183 isolate()->heap()->GetPretenureMode(), instance_type); |
| 2184 } | 2184 } |
| 2185 | 2185 |
| 2186 | 2186 |
| 2187 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 2187 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
| 2188 ElementsKind kind, | 2188 ElementsKind kind, |
| 2189 HValue* capacity) { | 2189 HValue* capacity) { |
| (...skipping 2307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4497 BreakAndContinueInfo break_info(stmt, 5); | 4497 BreakAndContinueInfo break_info(stmt, 5); |
| 4498 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); | 4498 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); |
| 4499 | 4499 |
| 4500 HBasicBlock* body_exit = | 4500 HBasicBlock* body_exit = |
| 4501 JoinContinue(stmt, current_block(), break_info.continue_block()); | 4501 JoinContinue(stmt, current_block(), break_info.continue_block()); |
| 4502 | 4502 |
| 4503 if (body_exit != NULL) { | 4503 if (body_exit != NULL) { |
| 4504 set_current_block(body_exit); | 4504 set_current_block(body_exit); |
| 4505 | 4505 |
| 4506 HValue* current_index = Pop(); | 4506 HValue* current_index = Pop(); |
| 4507 Push(Add<HAdd>(current_index, graph()->GetConstant1())); | 4507 Push(AddUncasted<HAdd>(current_index, graph()->GetConstant1())); |
| 4508 body_exit = current_block(); | 4508 body_exit = current_block(); |
| 4509 } | 4509 } |
| 4510 | 4510 |
| 4511 HBasicBlock* loop_exit = CreateLoop(stmt, | 4511 HBasicBlock* loop_exit = CreateLoop(stmt, |
| 4512 loop_entry, | 4512 loop_entry, |
| 4513 body_exit, | 4513 body_exit, |
| 4514 loop_successor, | 4514 loop_successor, |
| 4515 break_info.break_block()); | 4515 break_info.break_block()); |
| 4516 | 4516 |
| 4517 set_current_block(loop_exit); | 4517 set_current_block(loop_exit); |
| (...skipping 6115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10633 if (ShouldProduceTraceOutput()) { | 10633 if (ShouldProduceTraceOutput()) { |
| 10634 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10634 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 10635 } | 10635 } |
| 10636 | 10636 |
| 10637 #ifdef DEBUG | 10637 #ifdef DEBUG |
| 10638 graph_->Verify(false); // No full verify. | 10638 graph_->Verify(false); // No full verify. |
| 10639 #endif | 10639 #endif |
| 10640 } | 10640 } |
| 10641 | 10641 |
| 10642 } } // namespace v8::internal | 10642 } } // namespace v8::internal |
| OLD | NEW |