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 1210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1221 | 1221 |
1222 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 1222 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
1223 HBasicBlock* header = graph()->CreateBasicBlock(); | 1223 HBasicBlock* header = graph()->CreateBasicBlock(); |
1224 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 1224 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
1225 header->SetInitialEnvironment(entry_env); | 1225 header->SetInitialEnvironment(entry_env); |
1226 header->AttachLoopInformation(); | 1226 header->AttachLoopInformation(); |
1227 return header; | 1227 return header; |
1228 } | 1228 } |
1229 | 1229 |
1230 | 1230 |
1231 HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) { | |
1232 HValue* map = Add<HLoadNamedField>(object, HObjectAccess::ForMap()); | |
1233 | |
1234 HValue* bit_field2 = Add<HLoadNamedField>(map, | |
1235 HObjectAccess::ForMapBitField2()); | |
1236 HValue* unmasked_kind = AddUncasted<HShr>( | |
1237 bit_field2, Add<HConstant>(Map::kElementsKindShift)); | |
Toon Verwaest
2013/12/04 17:29:26
It seems like ElementsKind should really be a BitF
danno
2014/06/06 15:43:51
Done.
| |
1238 int mask = (1 << Map::kElementsKindBitCount) - 1; | |
1239 HValue* mask_value = Add<HConstant>(mask); | |
1240 return AddUncasted<HBitwise>(Token::BIT_AND, unmasked_kind, mask_value); | |
1241 } | |
1242 | |
1243 | |
1231 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 1244 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
1232 if (obj->type().IsHeapObject()) return obj; | 1245 if (obj->type().IsHeapObject()) return obj; |
1233 return Add<HCheckHeapObject>(obj); | 1246 return Add<HCheckHeapObject>(obj); |
1234 } | 1247 } |
1235 | 1248 |
1236 | 1249 |
1237 void HGraphBuilder::FinishExitWithHardDeoptimization( | 1250 void HGraphBuilder::FinishExitWithHardDeoptimization( |
1238 const char* reason, HBasicBlock* continuation) { | 1251 const char* reason, HBasicBlock* continuation) { |
1239 PadEnvironmentForContinuation(current_block(), continuation); | 1252 PadEnvironmentForContinuation(current_block(), continuation); |
1240 Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 1253 Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1410 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, | 1423 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
1411 array_length, elements_length); | 1424 array_length, elements_length); |
1412 | 1425 |
1413 if_builder.End(); | 1426 if_builder.End(); |
1414 } | 1427 } |
1415 | 1428 |
1416 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); | 1429 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); |
1417 } | 1430 } |
1418 | 1431 |
1419 | 1432 |
1433 void HGraphBuilder::BuildReceiverCheck(HValue* receiver, | |
1434 int bit_field_mask) { | |
1435 // Check that the object isn't a smi. | |
1436 Add<HCheckHeapObject>(receiver); | |
1437 | |
1438 // Get the map of the receiver. | |
1439 HValue* map = Add<HLoadNamedField>(receiver, HObjectAccess::ForMap()); | |
1440 | |
1441 if (V8_TARGET_LITTLE_ENDIAN) { | |
1442 // Check the instance type and if an access check is needed, this can be | |
1443 // done with a single load, since both bytes are adjacent in the map. | |
1444 HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField()); | |
1445 HValue* instance_type_and_bit_field = Add<HLoadNamedField>(map, access); | |
1446 | |
1447 HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8)); | |
1448 HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND, | |
1449 instance_type_and_bit_field, | |
1450 mask); | |
1451 HValue* sub_result = AddUncasted<HSub>(and_result, | |
1452 Add<HConstant>(JS_OBJECT_TYPE)); | |
1453 Add<HBoundsCheck>(sub_result, Add<HConstant>(0x100 - JS_OBJECT_TYPE)); | |
1454 } else { | |
1455 HValue* instance_type = | |
1456 Add<HLoadNamedField>(map, HObjectAccess::ForMapInstanceType()); | |
1457 IfBuilder type_check(this); | |
1458 type_check.If<HCompareNumericAndBranch>(instance_type, | |
1459 Add<HConstant>(JS_OBJECT_TYPE), | |
1460 Token::LT); | |
1461 type_check.ThenDeopt("receiver check: not JS_OBJECT_TYPE"); | |
1462 type_check.End(); | |
1463 | |
1464 HValue* bit_field2 = | |
1465 Add<HLoadNamedField>(map, HObjectAccess::ForMapBitField()); | |
Toon Verwaest
2013/12/04 17:29:26
ForMapBitField2 I presume? Is this tested?
Seems t
danno
2014/06/06 15:43:51
Fields swapped, it makes this code much simpler.
| |
1466 HValue* and_result = AddUncasted<HBitwise>( | |
1467 Token::BIT_AND, | |
1468 bit_field2, | |
1469 Add<HConstant>(bit_field_mask)); | |
1470 IfBuilder access_check(this); | |
1471 access_check.If<HCompareNumericAndBranch>(and_result, | |
Toon Verwaest
2013/12/04 17:29:26
Use DeoptimizeIf.
danno
2014/06/06 15:43:51
Done.
| |
1472 graph()->GetConstant0(), | |
1473 Token::NE); | |
1474 access_check.ThenDeopt("receiver check: bit field check failed"); | |
1475 access_check.End(); | |
1476 } | |
1477 } | |
1478 | |
1479 | |
1480 HValue* HGraphBuilder::BuildHashToIndex(HValue *hash) { | |
1481 // The assert checks that the constants for the maximum number of digits | |
1482 // for an array index cached in the hash field and the number of bits | |
1483 // reserved for it does not conflict. | |
1484 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | |
1485 (1 << String::kArrayIndexValueBits)); | |
1486 HValue* index = AddUncasted<HBitwise>( | |
1487 Token::BIT_AND, hash, Add<HConstant>(String::kArrayIndexValueMask)); | |
1488 return AddUncasted<HShr>(index, Add<HConstant>(String::kHashShift)); | |
Toon Verwaest
2013/12/04 17:29:26
A bitfield decoding mechanism would be useful agai
danno
2014/06/06 15:43:51
Done.
| |
1489 } | |
1490 | |
1491 | |
1492 void HGraphBuilder::BuildKeyedIndexCheck(HValue* key, | |
1493 HIfContinuation* join_continuation) { | |
Toon Verwaest
2013/12/04 17:29:26
It took me a while to figure out why the branches
danno
2014/06/06 15:43:51
Done.
| |
1494 // Create a joinable continuation. | |
1495 IfBuilder key_smi_if(this); | |
1496 key_smi_if.If<HIsSmiAndBranch>(key); | |
1497 key_smi_if.Then(); | |
1498 { | |
1499 Push(key); // Nothing to do, just continue to true of continuation. | |
1500 } | |
1501 key_smi_if.Else(); | |
1502 { | |
1503 HValue* map = Add<HLoadNamedField>(key, HObjectAccess::ForMap()); | |
1504 HValue* instance_type = | |
1505 Add<HLoadNamedField>(map, HObjectAccess::ForMapInstanceType()); | |
1506 | |
1507 // Non-unique string, check for a string with a hash code that is actually | |
1508 // an index. | |
1509 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); | |
1510 IfBuilder not_string_or_name_if(this); | |
Toon Verwaest
2013/12/04 17:29:26
I'd swap the condition (use string_or_name rather
danno
2014/06/06 15:43:51
Ordering needs to stay the same due to continuatio
| |
1511 not_string_or_name_if.If<HCompareNumericAndBranch>( | |
1512 instance_type, | |
1513 Add<HConstant>(LAST_UNIQUE_NAME_TYPE), | |
1514 Token::GT); | |
1515 | |
1516 not_string_or_name_if.Then(); | |
1517 { | |
1518 // Non-smi, non-Name, non-String: Try to convert to smi in case of | |
1519 // HeapNumber. | |
1520 Push(AddUncasted<HForceRepresentation>(key, Representation::Smi())); | |
1521 } | |
1522 not_string_or_name_if.Else(); | |
1523 { | |
1524 // String or Name: check explicitly for Name, they can short-circuit | |
1525 // directly to unique non-index key path. | |
1526 IfBuilder name_if(this); | |
1527 name_if.If<HCompareNumericAndBranch>( | |
Toon Verwaest
2013/12/04 17:29:26
And here name_if means that it's not a name. That'
danno
2014/06/06 15:43:51
Ordering needs to stay the same due to continuatio
| |
1528 instance_type, | |
1529 Add<HConstant>(LAST_UNIQUE_NAME_TYPE), | |
1530 Token::NE); | |
1531 | |
1532 name_if.Then(); | |
1533 { | |
1534 // String: check whether the String is an String of an index. If it is, | |
1535 // extract the index value from the hash. | |
1536 HValue* hash = | |
1537 Add<HLoadNamedField>(key, HObjectAccess::ForNameHashField()); | |
1538 HValue* cached_array_bit = AddUncasted<HBitwise>( | |
1539 Token::BIT_AND, | |
1540 hash, | |
1541 Add<HConstant>(Name::kContainsCachedArrayIndexMask)); | |
Toon Verwaest
2013/12/04 17:29:26
Shouldn't kContainsCachedArrayIndex be on String r
danno
2014/06/06 15:43:51
Done.
| |
1542 | |
1543 IfBuilder string_index_if(this); | |
1544 string_index_if.If<HCompareNumericAndBranch>(cached_array_bit, | |
1545 graph()->GetConstant0(), | |
1546 Token::EQ); | |
1547 string_index_if.Then(); | |
1548 { | |
1549 // String with index in hash: extract string and merge to index path. | |
1550 Push(BuildHashToIndex(hash)); | |
Toon Verwaest
2013/12/04 17:29:26
BuildHashToIndex could just be a bitfield decoder.
danno
2014/06/06 15:43:51
Done.
| |
1551 } | |
1552 string_index_if.Else(); | |
1553 { | |
1554 // Key is a non-index String, check for uniqueness/internalization. If | |
1555 // it's not, deopt. | |
1556 HValue* not_internalized_bit = AddUncasted<HBitwise>( | |
1557 Token::BIT_AND, | |
1558 instance_type, | |
1559 Add<HConstant>(static_cast<int>(kIsNotInternalizedMask))); | |
1560 DeoptimizeIf<HCompareNumericAndBranch>( | |
1561 not_internalized_bit, | |
1562 graph()->GetConstant0(), | |
1563 Token::NE, | |
1564 "BuildKeyedIndexCheck: string isn't internalized"); | |
1565 // Key guaranteed to be a unqiue string | |
1566 Push(key); | |
1567 } | |
1568 string_index_if.JoinContinuation(join_continuation); | |
1569 } | |
1570 name_if.Else(); | |
1571 { | |
1572 Push(key); // Key is name | |
1573 } | |
1574 name_if.JoinContinuation(join_continuation); | |
1575 } | |
1576 not_string_or_name_if.JoinContinuation(join_continuation); | |
1577 } | |
1578 key_smi_if.JoinContinuation(join_continuation); | |
1579 } | |
1580 | |
1581 | |
1582 void HGraphBuilder:: BuildGlobalInstanceTypeCheck(HValue* receiver) { | |
1583 // Get the the instance type of the receiver, and make sure that it is | |
1584 // not one of the global object types. | |
Toon Verwaest
2013/12/04 17:29:26
This comment seems to say the opposite of the name
danno
2014/06/06 15:43:51
Done.
| |
1585 HValue* map = Add<HLoadNamedField>(receiver, HObjectAccess::ForMap()); | |
1586 HValue* instance_type = | |
1587 Add<HLoadNamedField>(map, HObjectAccess::ForMapInstanceType()); | |
1588 STATIC_ASSERT(JS_BUILTINS_OBJECT_TYPE == JS_GLOBAL_OBJECT_TYPE + 1); | |
1589 STATIC_ASSERT(JS_GLOBAL_PROXY_TYPE == JS_BUILTINS_OBJECT_TYPE + 1); | |
1590 HValue* smallest_global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE); | |
1591 instance_type = AddUncasted<HSub>(instance_type, smallest_global_type); | |
1592 int globla_type_count = JS_GLOBAL_PROXY_TYPE - JS_GLOBAL_OBJECT_TYPE; | |
Toon Verwaest
2013/12/04 17:29:26
globAL
danno
2014/06/06 15:43:51
Done.
| |
1593 Add<HBoundsCheck>(instance_type, Add<HConstant>(globla_type_count)); | |
1594 } | |
1595 | |
1596 | |
1597 void HGraphBuilder::BuildCheckForDictionaryProperties( | |
1598 HValue* object, | |
1599 HIfContinuation* continuation) { | |
1600 HValue* properties = Add<HLoadNamedField>( | |
1601 object, HObjectAccess::ForPropertiesPointer()); | |
1602 HValue* properties_map = Add<HLoadNamedField>( | |
1603 properties, HObjectAccess::ForMap()); | |
1604 HValue* hash_map = Add<HLoadRoot>(Heap::kHashTableMapRootIndex); | |
1605 IfBuilder builder(this); | |
1606 builder.If<HCompareObjectEqAndBranch>(properties_map, hash_map); | |
1607 builder.CaptureContinuation(continuation); | |
Toon Verwaest
2013/12/04 17:29:26
I wonder if the resulting code may be smaller / fa
danno
2014/06/06 15:43:51
This is a copy of what the hand-written stub did I
| |
1608 } | |
1609 | |
1610 | |
1611 HValue* HGraphBuilder::BuildKeyedLookupCacheHash(HValue* object, | |
1612 HValue* key) { | |
1613 // Load the map of the receiver, compute the keyed lookup cache hash | |
1614 // based on 32 bits of the map pointer and the string hash. | |
1615 HValue* object_map = Add<HLoadNamedField>( | |
1616 object, HObjectAccess::ForMapAsInteger32()); | |
1617 HValue* shifted_map = AddUncasted<HShr>( | |
1618 object_map, Add<HConstant>(KeyedLookupCache::kMapHashShift)); | |
1619 HValue* string_hash = Add<HLoadNamedField>( | |
1620 key, HObjectAccess::ForStringHashField()); | |
1621 HValue* shifted_hash = AddUncasted<HShr>( | |
1622 string_hash, Add<HConstant>(String::kHashShift)); | |
1623 HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map, | |
1624 shifted_hash); | |
1625 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); | |
1626 return AddUncasted<HBitwise>(Token::BIT_AND, xor_result, | |
1627 Add<HConstant>(mask)); | |
1628 } | |
1629 | |
1630 | |
1420 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper( | 1631 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoadHelper( |
1421 HValue* elements, | 1632 HValue* elements, |
1422 HValue* key, | 1633 HValue* key, |
1423 HValue* hash, | 1634 HValue* hash, |
1424 HValue* mask, | 1635 HValue* mask, |
1425 int current_probe) { | 1636 int current_probe) { |
1426 if (current_probe == kNumberDictionaryProbes) { | 1637 if (current_probe == kNumberDictionaryProbes) { |
1427 return NULL; | 1638 return NULL; |
1428 } | 1639 } |
1429 | 1640 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1522 hash = AddUncasted<HMul>(hash, Add<HConstant>(2057)); | 1733 hash = AddUncasted<HMul>(hash, Add<HConstant>(2057)); |
1523 hash->ClearFlag(HValue::kCanOverflow); | 1734 hash->ClearFlag(HValue::kCanOverflow); |
1524 | 1735 |
1525 // hash = hash ^ (hash >> 16); | 1736 // hash = hash ^ (hash >> 16); |
1526 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16)); | 1737 shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16)); |
1527 return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); | 1738 return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash); |
1528 } | 1739 } |
1529 | 1740 |
1530 | 1741 |
1531 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver, | 1742 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver, |
1532 HValue* key) { | 1743 HValue* elements, |
1533 HValue* elements = AddLoadElements(receiver); | 1744 HValue* key, |
1534 | 1745 HValue* hash) { |
1535 HValue* hash = BuildElementIndexHash(key); | |
1536 | |
1537 HValue* capacity = Add<HLoadKeyed>( | 1746 HValue* capacity = Add<HLoadKeyed>( |
1538 elements, | 1747 elements, |
1539 Add<HConstant>(NameDictionary::kCapacityIndex), | 1748 Add<HConstant>(NameDictionary::kCapacityIndex), |
1540 static_cast<HValue*>(NULL), | 1749 static_cast<HValue*>(NULL), |
1541 FAST_SMI_ELEMENTS); | 1750 FAST_SMI_ELEMENTS); |
1542 | 1751 |
1543 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); | 1752 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); |
1544 mask->ChangeRepresentation(Representation::Integer32()); | 1753 mask->ChangeRepresentation(Representation::Integer32()); |
1545 mask->ClearFlag(HValue::kCanOverflow); | 1754 mask->ClearFlag(HValue::kCanOverflow); |
1546 | 1755 |
(...skipping 9261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10808 if (ShouldProduceTraceOutput()) { | 11017 if (ShouldProduceTraceOutput()) { |
10809 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11018 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
10810 } | 11019 } |
10811 | 11020 |
10812 #ifdef DEBUG | 11021 #ifdef DEBUG |
10813 graph_->Verify(false); // No full verify. | 11022 graph_->Verify(false); // No full verify. |
10814 #endif | 11023 #endif |
10815 } | 11024 } |
10816 | 11025 |
10817 } } // namespace v8::internal | 11026 } } // namespace v8::internal |
OLD | NEW |