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 |