Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: src/hydrogen.cc

Issue 57123002: Reland 21774: Generate KeyedLoadGeneric with Hydrogen (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Turn off by default Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698