Chromium Code Reviews| 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 |