OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1321 } | 1321 } |
1322 | 1322 |
1323 | 1323 |
1324 template<> | 1324 template<> |
1325 HValue* CodeStubGraphBuilder<KeyedLoadDictionaryElementStub>::BuildCodeStub() { | 1325 HValue* CodeStubGraphBuilder<KeyedLoadDictionaryElementStub>::BuildCodeStub() { |
1326 HValue* receiver = GetParameter(0); | 1326 HValue* receiver = GetParameter(0); |
1327 HValue* key = GetParameter(1); | 1327 HValue* key = GetParameter(1); |
1328 | 1328 |
1329 Add<HCheckSmi>(key); | 1329 Add<HCheckSmi>(key); |
1330 | 1330 |
1331 return BuildUncheckedDictionaryElementLoad(receiver, key); | 1331 HValue* elements = AddLoadElements(receiver); |
Toon Verwaest
2013/12/04 17:29:26
We need at least a BuildCheckHeapObject(receiver)
danno
2014/06/06 15:43:50
Why is that needed? We already did a map check in
| |
1332 | |
1333 HValue* hash = BuildElementIndexHash(key); | |
1334 | |
1335 return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash); | |
1332 } | 1336 } |
1333 | 1337 |
1334 | 1338 |
1335 Handle<Code> KeyedLoadDictionaryElementStub::GenerateCode(Isolate* isolate) { | 1339 Handle<Code> KeyedLoadDictionaryElementStub::GenerateCode(Isolate* isolate) { |
1336 return DoGenerateCode(isolate, this); | 1340 return DoGenerateCode(isolate, this); |
1337 } | 1341 } |
1338 | 1342 |
1339 | 1343 |
1344 template <> | |
1345 class CodeStubGraphBuilder<KeyedLoadGenericElementStub> | |
1346 : public CodeStubGraphBuilderBase { | |
1347 public: | |
1348 CodeStubGraphBuilder(Isolate* isolate, | |
1349 KeyedLoadGenericElementStub* stub) | |
Toon Verwaest
2013/12/04 17:29:26
nit: Weird indentation
danno
2014/06/06 15:43:50
Done.
| |
1350 : CodeStubGraphBuilderBase(isolate, stub) {} | |
1351 | |
1352 protected: | |
1353 virtual HValue* BuildCodeStub(); | |
1354 | |
1355 void BuildFastElementLoad(HGraphBuilder::IfBuilder* if_builder, | |
1356 HValue* receiver, | |
1357 HValue* key, | |
1358 HValue* instance_type, | |
1359 HValue* bit_field2, | |
1360 ElementsKind next_kind, | |
1361 ElementsKind handle_as_kind); | |
1362 | |
1363 KeyedLoadGenericElementStub* casted_stub() { | |
1364 return static_cast<KeyedLoadGenericElementStub*>(stub()); | |
1365 } | |
1366 }; | |
1367 | |
1368 | |
1369 void CodeStubGraphBuilder<KeyedLoadGenericElementStub>::BuildFastElementLoad( | |
1370 HGraphBuilder::IfBuilder* if_builder, | |
1371 HValue* receiver, | |
1372 HValue* key, | |
1373 HValue* instance_type, | |
1374 HValue* bit_field2, | |
1375 ElementsKind next_kind, | |
1376 ElementsKind handle_as_kind) { | |
Toon Verwaest
2013/12/04 17:29:26
In isolation it's very hard to see what this metho
danno
2014/06/06 15:43:50
Done.
| |
1377 HValue* next_kind_value = | |
1378 Add<HConstant>(next_kind << Map::kElementsKindShift); | |
1379 if_builder->If<HCompareNumericAndBranch>(bit_field2, next_kind_value, | |
1380 Token::LT); | |
1381 if_builder->Then(); | |
1382 | |
1383 IfBuilder js_array_check(this); | |
1384 | |
1385 if (!IsExternalArrayElementsKind(handle_as_kind)) { | |
1386 js_array_check.If<HCompareNumericAndBranch>( | |
1387 instance_type, Add<HConstant>(JS_ARRAY_TYPE), Token::EQ); | |
1388 } | |
1389 | |
1390 js_array_check.Then(); | |
1391 if (!IsExternalArrayElementsKind(handle_as_kind)) { | |
Toon Verwaest
2013/12/04 17:29:26
It's hard to understand what kind of graph is crea
danno
2014/06/06 15:43:50
Done.
| |
1392 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, | |
1393 true, handle_as_kind, | |
1394 false, NEVER_RETURN_HOLE, | |
1395 STANDARD_STORE)); | |
1396 } else { | |
1397 Push(graph()->GetConstant0()); | |
1398 } | |
1399 | |
1400 js_array_check.Else(); | |
1401 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, | |
1402 false, handle_as_kind, | |
1403 false, NEVER_RETURN_HOLE, | |
1404 STANDARD_STORE)); | |
1405 } | |
1406 | |
1407 | |
1408 HValue* CodeStubGraphBuilder<KeyedLoadGenericElementStub>::BuildCodeStub() { | |
1409 HValue* receiver = GetParameter(0); | |
1410 HValue* key = GetParameter(1); | |
1411 | |
1412 // Split into a smi/integer case and unique string case. | |
1413 HIfContinuation index_name_split_continuation(graph()->CreateBasicBlock(), | |
1414 graph()->CreateBasicBlock()); | |
1415 | |
1416 BuildKeyedIndexCheck(key, &index_name_split_continuation); | |
1417 | |
1418 IfBuilder index_name_split(this, &index_name_split_continuation); | |
1419 index_name_split.Then(); | |
1420 { | |
1421 // Key is an index (number) | |
1422 key = Pop(); | |
1423 | |
1424 int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) | | |
1425 (1 << Map::kHasIndexedInterceptor); | |
1426 BuildReceiverCheck(receiver, bit_field_mask); | |
Toon Verwaest
2013/12/04 17:29:26
Can we pull these 2 checks out of the continuation
danno
2014/06/06 15:43:50
No, these can't be moved since they are different
| |
1427 | |
1428 HValue* map = Add<HLoadNamedField>(receiver, HObjectAccess::ForMap()); | |
1429 | |
1430 HValue* instance_type = | |
1431 Add<HLoadNamedField>(map, HObjectAccess::ForMapInstanceType()); | |
1432 | |
1433 HValue* bit_field2 = Add<HLoadNamedField>(map, | |
1434 HObjectAccess::ForMapBitField2()); | |
1435 | |
1436 IfBuilder kind_if(this); | |
1437 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1438 FAST_DOUBLE_ELEMENTS, FAST_HOLEY_ELEMENTS); | |
1439 | |
1440 kind_if.Else(); | |
1441 { | |
1442 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1443 DICTIONARY_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS); | |
1444 } | |
1445 kind_if.Else(); | |
1446 { | |
1447 int non_strict_elements_kind = | |
1448 NON_STRICT_ARGUMENTS_ELEMENTS << Map::kElementsKindShift; | |
1449 HValue* dictionary_limit = Add<HConstant>(non_strict_elements_kind); | |
1450 kind_if.If<HCompareNumericAndBranch>(bit_field2, dictionary_limit, | |
1451 Token::LT); | |
1452 } | |
1453 kind_if.Then(); | |
1454 { | |
1455 HValue* elements = AddLoadElements(receiver); | |
1456 | |
1457 HValue* hash = BuildElementIndexHash(key); | |
1458 | |
1459 Push(BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash)); | |
1460 } | |
1461 // Non-strict elements are not handled. | |
1462 kind_if.Else(); | |
1463 | |
1464 HValue* non_strict_limit = | |
1465 Add<HConstant>(EXTERNAL_BYTE_ELEMENTS << Map::kElementsKindShift); | |
1466 DeoptimizeIf<HCompareNumericAndBranch>( | |
1467 bit_field2, non_strict_limit, Token::LT, | |
1468 "non-strict argument elements in KeyedLoadGenericElementStub"); | |
1469 | |
1470 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1471 EXTERNAL_UNSIGNED_BYTE_ELEMENTS, | |
1472 EXTERNAL_BYTE_ELEMENTS); | |
1473 | |
1474 kind_if.Else(); | |
1475 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1476 EXTERNAL_SHORT_ELEMENTS, | |
1477 EXTERNAL_UNSIGNED_BYTE_ELEMENTS); | |
1478 | |
1479 kind_if.Else(); | |
1480 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1481 EXTERNAL_UNSIGNED_SHORT_ELEMENTS, | |
1482 EXTERNAL_SHORT_ELEMENTS); | |
1483 | |
1484 kind_if.Else(); | |
1485 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1486 EXTERNAL_INT_ELEMENTS, | |
1487 EXTERNAL_UNSIGNED_SHORT_ELEMENTS); | |
1488 | |
1489 kind_if.Else(); | |
1490 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1491 EXTERNAL_UNSIGNED_INT_ELEMENTS, | |
1492 EXTERNAL_INT_ELEMENTS); | |
1493 | |
1494 kind_if.Else(); | |
1495 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1496 EXTERNAL_FLOAT_ELEMENTS, | |
1497 EXTERNAL_UNSIGNED_INT_ELEMENTS); | |
1498 | |
1499 kind_if.Else(); | |
1500 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1501 EXTERNAL_DOUBLE_ELEMENTS, EXTERNAL_FLOAT_ELEMENTS); | |
1502 | |
1503 kind_if.Else(); | |
1504 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1505 EXTERNAL_PIXEL_ELEMENTS, EXTERNAL_DOUBLE_ELEMENTS); | |
1506 | |
1507 kind_if.Else(); | |
1508 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | |
1509 static_cast<ElementsKind>(EXTERNAL_PIXEL_ELEMENTS + 1), | |
1510 EXTERNAL_PIXEL_ELEMENTS); | |
1511 | |
1512 kind_if.ElseDeopt("ElementsKind unhandled in KeyedLoadGenericElementStub"); | |
1513 | |
1514 kind_if.End(); | |
1515 } | |
1516 index_name_split.Else(); | |
1517 { | |
1518 // Key is a unique string. | |
1519 key = Pop(); | |
1520 | |
1521 int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) | | |
1522 (1 << Map::kHasNamedInterceptor); | |
1523 BuildReceiverCheck(receiver, bit_field_mask); | |
1524 | |
1525 HIfContinuation continuation; | |
1526 BuildCheckForDictionaryProperties(receiver, &continuation); | |
1527 IfBuilder if_dict_properties(this, &continuation); | |
1528 if_dict_properties.Then(); | |
1529 { | |
1530 // Key is string, properties are dictionary mode | |
1531 BuildGlobalInstanceTypeCheck(receiver); | |
1532 | |
1533 HValue* properties = Add<HLoadNamedField>( | |
1534 receiver, HObjectAccess::ForPropertiesPointer()); | |
1535 | |
1536 HValue* hash = | |
1537 Add<HLoadNamedField>(key, HObjectAccess::ForNameHashField()); | |
1538 | |
1539 HValue* value = BuildUncheckedDictionaryElementLoad(receiver, | |
1540 properties, | |
1541 key, | |
1542 hash); | |
1543 Push(value); | |
1544 } | |
1545 if_dict_properties.Else(); | |
1546 { | |
1547 // Key is string, properties are fast mode | |
1548 HValue* hash = BuildKeyedLookupCacheHash(receiver, key); | |
1549 | |
1550 ExternalReference cache_keys_ref = | |
1551 ExternalReference::keyed_lookup_cache_keys(isolate()); | |
1552 HValue* cache_keys = Add<HConstant>(cache_keys_ref); | |
1553 | |
1554 HValue* map = Add<HLoadNamedField>(receiver, HObjectAccess::ForMap()); | |
1555 HValue* base_index = AddUncasted<HMul>(hash, Add<HConstant>(2)); | |
1556 base_index->ClearFlag(HValue::kCanOverflow); | |
1557 | |
1558 IfBuilder lookup_if(this); | |
1559 for (int probe = 0; probe < KeyedLookupCache::kEntriesPerBucket; | |
1560 ++probe) { | |
1561 HValue* map_index = AddUncasted<HAdd>(base_index, | |
1562 Add<HConstant>(probe * 2)); | |
1563 map_index->ClearFlag(HValue::kCanOverflow); | |
1564 HValue* key_index = AddUncasted<HAdd>(base_index, | |
1565 Add<HConstant>(probe * 2 + 1)); | |
1566 key_index->ClearFlag(HValue::kCanOverflow); | |
1567 HValue* map_to_check = Add<HLoadKeyed>(cache_keys, | |
1568 map_index, | |
1569 static_cast<HValue*>(NULL), | |
1570 FAST_ELEMENTS, | |
1571 NEVER_RETURN_HOLE, 0); | |
1572 lookup_if.If<HCompareObjectEqAndBranch>(map_to_check, map); | |
1573 lookup_if.And(); | |
1574 HValue* key_to_check = Add<HLoadKeyed>(cache_keys, | |
1575 key_index, | |
1576 static_cast<HValue*>(NULL), | |
1577 FAST_ELEMENTS, | |
1578 NEVER_RETURN_HOLE, 0); | |
1579 lookup_if.If<HCompareObjectEqAndBranch>(key_to_check, key); | |
1580 lookup_if.Then(); | |
1581 { | |
1582 ExternalReference cache_field_offsets_ref = | |
1583 ExternalReference::keyed_lookup_cache_field_offsets(isolate()); | |
1584 HValue* cache_field_offsets = Add<HConstant>(cache_field_offsets_ref); | |
1585 HValue* index = AddUncasted<HAdd>(hash, | |
1586 Add<HConstant>(probe)); | |
1587 index->ClearFlag(HValue::kCanOverflow); | |
1588 HValue* property_index = Add<HLoadKeyed>(cache_field_offsets, | |
1589 index, | |
1590 static_cast<HValue*>(NULL), | |
1591 EXTERNAL_INT_ELEMENTS, | |
1592 NEVER_RETURN_HOLE, 0); | |
1593 Push(property_index); | |
1594 } | |
1595 lookup_if.Else(); | |
1596 } | |
1597 Add<HDeoptimize>("KeyedLoad fall-back", Deoptimizer::EAGER); | |
1598 Push(graph()->GetConstant0()); | |
1599 lookup_if.End(); | |
1600 Push(Add<HLoadFieldByIndex>(receiver, Pop())); | |
1601 } | |
1602 if_dict_properties.End(); | |
1603 } | |
1604 index_name_split.End(); | |
1605 | |
1606 return Pop(); | |
1607 } | |
1608 | |
1609 | |
1610 Handle<Code> KeyedLoadGenericElementStub::GenerateCode(Isolate* isolate) { | |
1611 return DoGenerateCode(isolate, this); | |
1612 } | |
1613 | |
1614 | |
1340 } } // namespace v8::internal | 1615 } } // namespace v8::internal |
OLD | NEW |