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

Side by Side Diff: src/code-stub-assembler.cc

Issue 1995453002: [stubs] Extend HasProperty stub with dictionary-mode and double-elements objects support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fixes and ArrayIndex-related cleanup in objects.h/.cc Created 4 years, 7 months 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
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/code-stub-assembler.h" 5 #include "src/code-stub-assembler.h"
6 #include "src/code-factory.h" 6 #include "src/code-factory.h"
7 7
8 namespace v8 { 8 namespace v8 {
9 namespace internal { 9 namespace internal {
10 10
(...skipping 28 matching lines...) Expand all
39 } 39 }
40 40
41 Node* CodeStubAssembler::NullConstant() { 41 Node* CodeStubAssembler::NullConstant() {
42 return LoadRoot(Heap::kNullValueRootIndex); 42 return LoadRoot(Heap::kNullValueRootIndex);
43 } 43 }
44 44
45 Node* CodeStubAssembler::UndefinedConstant() { 45 Node* CodeStubAssembler::UndefinedConstant() {
46 return LoadRoot(Heap::kUndefinedValueRootIndex); 46 return LoadRoot(Heap::kUndefinedValueRootIndex);
47 } 47 }
48 48
49 Node* CodeStubAssembler::TheHoleConstant() {
50 return LoadRoot(Heap::kTheHoleValueRootIndex);
51 }
52
53 Node* CodeStubAssembler::HashSeed() {
54 return SmiToWord32(LoadRoot(Heap::kHashSeedRootIndex));
55 }
56
49 Node* CodeStubAssembler::StaleRegisterConstant() { 57 Node* CodeStubAssembler::StaleRegisterConstant() {
50 return LoadRoot(Heap::kStaleRegisterRootIndex); 58 return LoadRoot(Heap::kStaleRegisterRootIndex);
51 } 59 }
52 60
53 Node* CodeStubAssembler::Float64Round(Node* x) { 61 Node* CodeStubAssembler::Float64Round(Node* x) {
54 Node* one = Float64Constant(1.0); 62 Node* one = Float64Constant(1.0);
55 Node* one_half = Float64Constant(0.5); 63 Node* one_half = Float64Constant(0.5);
56 64
57 Variable var_x(this, MachineRepresentation::kFloat64); 65 Variable var_x(this, MachineRepresentation::kFloat64);
58 Label return_x(this); 66 Label return_x(this);
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 } 470 }
463 471
464 Node* CodeStubAssembler::LoadMap(Node* object) { 472 Node* CodeStubAssembler::LoadMap(Node* object) {
465 return LoadObjectField(object, HeapObject::kMapOffset); 473 return LoadObjectField(object, HeapObject::kMapOffset);
466 } 474 }
467 475
468 Node* CodeStubAssembler::LoadInstanceType(Node* object) { 476 Node* CodeStubAssembler::LoadInstanceType(Node* object) {
469 return LoadMapInstanceType(LoadMap(object)); 477 return LoadMapInstanceType(LoadMap(object));
470 } 478 }
471 479
480 Node* CodeStubAssembler::LoadProperties(Node* object) {
481 return LoadObjectField(object, JSObject::kPropertiesOffset);
482 }
483
472 Node* CodeStubAssembler::LoadElements(Node* object) { 484 Node* CodeStubAssembler::LoadElements(Node* object) {
473 return LoadObjectField(object, JSObject::kElementsOffset); 485 return LoadObjectField(object, JSObject::kElementsOffset);
474 } 486 }
475 487
476 Node* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) { 488 Node* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) {
477 return LoadObjectField(array, FixedArrayBase::kLengthOffset); 489 return LoadObjectField(array, FixedArrayBase::kLengthOffset);
478 } 490 }
479 491
480 Node* CodeStubAssembler::LoadMapBitField(Node* map) { 492 Node* CodeStubAssembler::LoadMapBitField(Node* map) {
481 return Load(MachineType::Uint8(), map, 493 return Load(MachineType::Uint8(), map,
(...skipping 16 matching lines...) Expand all
498 } 510 }
499 511
500 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { 512 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) {
501 return LoadObjectField(map, Map::kDescriptorsOffset); 513 return LoadObjectField(map, Map::kDescriptorsOffset);
502 } 514 }
503 515
504 Node* CodeStubAssembler::LoadMapPrototype(Node* map) { 516 Node* CodeStubAssembler::LoadMapPrototype(Node* map) {
505 return LoadObjectField(map, Map::kPrototypeOffset); 517 return LoadObjectField(map, Map::kPrototypeOffset);
506 } 518 }
507 519
508 Node* CodeStubAssembler::LoadNameHash(Node* name) { 520 Node* CodeStubAssembler::LoadNameHashField(Node* name) {
509 return Load(MachineType::Uint32(), name, 521 return Load(MachineType::Uint32(), name,
510 IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag)); 522 IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag));
511 } 523 }
512 524
525 Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) {
526 Node* hash_field = LoadNameHashField(name);
527 if (if_hash_not_computed != nullptr) {
528 GotoIf(WordEqual(
529 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)),
530 Int32Constant(0)),
531 if_hash_not_computed);
532 }
533 return Word32Shr(hash_field, Int32Constant(Name::kHashShift));
534 }
535
536 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) {
537 return Load(MachineType::Uint8(), map,
538 IntPtrConstant(Map::kInstanceSizeOffset - kHeapObjectTag));
539 }
540
513 Node* CodeStubAssembler::AllocateUninitializedFixedArray(Node* length) { 541 Node* CodeStubAssembler::AllocateUninitializedFixedArray(Node* length) {
514 Node* header_size = IntPtrConstant(FixedArray::kHeaderSize); 542 Node* header_size = IntPtrConstant(FixedArray::kHeaderSize);
515 Node* data_size = WordShl(length, IntPtrConstant(kPointerSizeLog2)); 543 Node* data_size = WordShl(length, IntPtrConstant(kPointerSizeLog2));
516 Node* total_size = IntPtrAdd(data_size, header_size); 544 Node* total_size = IntPtrAdd(data_size, header_size);
517 545
518 Node* result = Allocate(total_size, kNone); 546 Node* result = Allocate(total_size, kNone);
519 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kFixedArrayMapRootIndex)); 547 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kFixedArrayMapRootIndex));
520 StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset, 548 StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset,
521 SmiTag(length)); 549 SmiTag(length));
522 550
523 return result; 551 return result;
524 } 552 }
525 553
526 Node* CodeStubAssembler::LoadFixedArrayElementInt32Index( 554 Node* CodeStubAssembler::LoadFixedArrayElementInt32Index(
527 Node* object, Node* index, int additional_offset) { 555 Node* object, Node* index, int additional_offset) {
528 Node* header_size = IntPtrConstant(additional_offset + 556 Node* header_size = IntPtrConstant(additional_offset +
529 FixedArray::kHeaderSize - kHeapObjectTag); 557 FixedArray::kHeaderSize - kHeapObjectTag);
530 index = ChangeInt32ToIntPtr(index); 558 index = ChangeInt32ToIntPtr(index);
531 Node* scaled_index = WordShl(index, IntPtrConstant(kPointerSizeLog2)); 559 Node* scaled_index = WordShl(index, IntPtrConstant(kPointerSizeLog2));
532 Node* offset = IntPtrAdd(scaled_index, header_size); 560 Node* offset = IntPtrAdd(scaled_index, header_size);
533 return Load(MachineType::AnyTagged(), object, offset); 561 return Load(MachineType::AnyTagged(), object, offset);
534 } 562 }
535 563
536 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) {
537 return Load(MachineType::Uint8(), map,
538 IntPtrConstant(Map::kInstanceSizeOffset - kHeapObjectTag));
539 }
540
541 Node* CodeStubAssembler::LoadFixedArrayElementSmiIndex(Node* object, 564 Node* CodeStubAssembler::LoadFixedArrayElementSmiIndex(Node* object,
542 Node* smi_index, 565 Node* smi_index,
543 int additional_offset) { 566 int additional_offset) {
544 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize; 567 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize;
545 Node* header_size = IntPtrConstant(additional_offset + 568 Node* header_size = IntPtrConstant(additional_offset +
546 FixedArray::kHeaderSize - kHeapObjectTag); 569 FixedArray::kHeaderSize - kHeapObjectTag);
547 Node* scaled_index = 570 Node* scaled_index =
548 (kSmiShiftBits > kPointerSizeLog2) 571 (kSmiShiftBits > kPointerSizeLog2)
549 ? WordSar(smi_index, IntPtrConstant(kSmiShiftBits - kPointerSizeLog2)) 572 ? WordSar(smi_index, IntPtrConstant(kSmiShiftBits - kPointerSizeLog2))
550 : WordShl(smi_index, 573 : WordShl(smi_index,
551 IntPtrConstant(kPointerSizeLog2 - kSmiShiftBits)); 574 IntPtrConstant(kPointerSizeLog2 - kSmiShiftBits));
552 Node* offset = IntPtrAdd(scaled_index, header_size); 575 Node* offset = IntPtrAdd(scaled_index, header_size);
553 return Load(MachineType::AnyTagged(), object, offset); 576 return Load(MachineType::AnyTagged(), object, offset);
554 } 577 }
555 578
556 Node* CodeStubAssembler::LoadFixedArrayElementConstantIndex(Node* object, 579 Node* CodeStubAssembler::LoadFixedArrayElementConstantIndex(Node* object,
557 int index) { 580 int index) {
558 Node* offset = IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag + 581 Node* offset = IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag +
559 index * kPointerSize); 582 index * kPointerSize);
560 return Load(MachineType::AnyTagged(), object, offset); 583 return Load(MachineType::AnyTagged(), object, offset);
561 } 584 }
562 585
586 Node* CodeStubAssembler::OffsetOfFixedDoubleArrayElementInt32Index(
587 Node* index, int additional_offset) {
588 Node* header_size = IntPtrConstant(
589 additional_offset + FixedDoubleArray::kHeaderSize - kHeapObjectTag);
590 index = ChangeInt32ToIntPtr(index);
591 Node* scaled_index = WordShl(index, IntPtrConstant(kDoubleSizeLog2));
592 return IntPtrAdd(scaled_index, header_size);
593 }
594
595 Node* CodeStubAssembler::LoadFixedDoubleArrayElementInt32Index(
596 Node* object, Node* index, MachineType machine_type,
597 int additional_offset) {
598 Node* offset =
599 OffsetOfFixedDoubleArrayElementInt32Index(index, additional_offset);
600 return Load(machine_type, object, offset);
601 }
602
563 Node* CodeStubAssembler::LoadNativeContext(Node* context) { 603 Node* CodeStubAssembler::LoadNativeContext(Node* context) {
564 return LoadFixedArrayElementConstantIndex(context, 604 return LoadFixedArrayElementConstantIndex(context,
565 Context::NATIVE_CONTEXT_INDEX); 605 Context::NATIVE_CONTEXT_INDEX);
566 } 606 }
567 607
568 Node* CodeStubAssembler::LoadJSArrayElementsMap(ElementsKind kind, 608 Node* CodeStubAssembler::LoadJSArrayElementsMap(ElementsKind kind,
569 Node* native_context) { 609 Node* native_context) {
570 return LoadFixedArrayElementConstantIndex(native_context, 610 return LoadFixedArrayElementConstantIndex(native_context,
571 Context::ArrayMapIndex(kind)); 611 Context::ArrayMapIndex(kind));
572 } 612 }
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after
1279 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, 1319 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex,
1280 Variable* var_index, Label* if_keyisunique, 1320 Variable* var_index, Label* if_keyisunique,
1281 Label* call_runtime) { 1321 Label* call_runtime) {
1282 DCHECK_EQ(MachineRepresentation::kWord32, var_index->rep()); 1322 DCHECK_EQ(MachineRepresentation::kWord32, var_index->rep());
1283 1323
1284 Label if_keyissmi(this), if_keyisnotsmi(this); 1324 Label if_keyissmi(this), if_keyisnotsmi(this);
1285 Branch(WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi); 1325 Branch(WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi);
1286 Bind(&if_keyissmi); 1326 Bind(&if_keyissmi);
1287 { 1327 {
1288 // Negative smi keys are named properties. Handle in the runtime. 1328 // Negative smi keys are named properties. Handle in the runtime.
1289 Label if_keyispositive(this); 1329 GotoUnless(WordIsPositiveSmi(key), call_runtime);
1290 Branch(WordIsPositiveSmi(key), &if_keyispositive, call_runtime);
1291 Bind(&if_keyispositive);
1292 1330
1293 var_index->Bind(SmiToWord32(key)); 1331 var_index->Bind(SmiToWord32(key));
1294 Goto(if_keyisindex); 1332 Goto(if_keyisindex);
1295 } 1333 }
1296 1334
1297 Bind(&if_keyisnotsmi); 1335 Bind(&if_keyisnotsmi);
1298 1336
1299 Node* key_instance_type = LoadInstanceType(key); 1337 Node* key_instance_type = LoadInstanceType(key);
1300 Label if_keyisnotsymbol(this); 1338 // Symbols are unique.
1301 Branch(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)), 1339 GotoIf(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)),
1302 if_keyisunique, &if_keyisnotsymbol); 1340 if_keyisunique);
1303 Bind(&if_keyisnotsymbol); 1341
1304 { 1342 Label if_keyisinternalized(this);
1305 Label if_keyisinternalized(this); 1343 Node* bits =
1306 Node* bits = 1344 WordAnd(key_instance_type,
1307 WordAnd(key_instance_type, 1345 Int32Constant(kIsNotStringMask | kIsNotInternalizedMask));
1308 Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)); 1346 Branch(Word32Equal(bits, Int32Constant(kStringTag | kInternalizedTag)),
1309 Branch(Word32Equal(bits, Int32Constant(kStringTag | kInternalizedTag)), 1347 &if_keyisinternalized, call_runtime);
1310 &if_keyisinternalized, call_runtime); 1348 Bind(&if_keyisinternalized);
1311 Bind(&if_keyisinternalized); 1349
1312 1350 // Check whether the key is an array index passed in as string. Handle
1313 // Check whether the key is an array index passed in as string. Handle 1351 // uniform with smi keys if so.
1314 // uniform with smi keys if so. 1352 // TODO(verwaest): Also support non-internalized strings.
1315 // TODO(verwaest): Also support non-internalized strings. 1353 Node* hash = LoadNameHashField(key);
1316 Node* hash = LoadNameHash(key); 1354 Node* bit = Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask));
1317 Node* bit = 1355 GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_keyisunique);
1318 Word32And(hash, Int32Constant(internal::Name::kIsNotArrayIndexMask)); 1356 // Key is an index. Check if it is small enough to be encoded in the
1319 Label if_isarrayindex(this); 1357 // hash_field. Handle too big array index in runtime.
1320 Branch(Word32Equal(bit, Int32Constant(0)), &if_isarrayindex, 1358 bit = Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask));
1321 if_keyisunique); 1359 GotoIf(Word32NotEqual(bit, Int32Constant(0)), call_runtime);
1322 Bind(&if_isarrayindex); 1360 var_index->Bind(BitFieldDecode<Name::ArrayIndexValueBits>(hash));
1323 var_index->Bind(BitFieldDecode<internal::Name::ArrayIndexValueBits>(hash)); 1361 Goto(if_keyisindex);
1324 Goto(if_keyisindex); 1362 }
1363
1364 template <typename Dictionary>
1365 void CodeStubAssembler::NameDictionaryLookup(Node* dictionary,
1366 Node* unique_name, Label* if_found,
1367 Label* if_not_found,
1368 Label* call_runtime,
1369 int inlined_probes) {
1370 const int kElementsStartOffset =
1371 Dictionary::kElementsStartIndex * kPointerSize;
1372
1373 Node* capacity = SmiToWord32(LoadFixedArrayElementConstantIndex(
1374 dictionary, Dictionary::kCapacityIndex));
1375 Node* mask = Int32Sub(capacity, Int32Constant(1));
1376 Node* hash = LoadNameHash(unique_name);
1377
1378 // See Dictionary::FirstProbe().
1379 Node* count = Int32Constant(0);
1380 Node* entry = Word32And(hash, mask);
1381
1382 for (int i = 0; i < inlined_probes; i++) {
1383 // See Dictionary::EntryToIndex()
1384 Node* index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize));
1385 Node* current = LoadFixedArrayElementInt32Index(dictionary, index,
1386 kElementsStartOffset);
1387 GotoIf(WordEqual(current, unique_name), if_found);
1388
1389 // See Dictionary::NextProbe().
1390 count = Int32Constant(i + 1);
1391 entry = Word32And(Int32Add(entry, count), mask);
1392 }
1393
1394 Node* undefined = UndefinedConstant();
1395
1396 Variable var_count(this, MachineRepresentation::kWord32);
1397 Variable var_entry(this, MachineType::PointerRepresentation());
Toon Verwaest 2016/05/19 14:50:22 Shouldn't this be kWord32 as well?
Igor Sheludko 2016/05/30 12:11:34 Done.
1398 Variable* loop_vars[] = {&var_count, &var_entry};
1399 Label loop(this, 2, loop_vars);
1400 var_count.Bind(count);
1401 var_entry.Bind(entry);
1402 Goto(&loop);
1403 Bind(&loop);
1404 {
1405 Node* count = var_count.value();
1406 Node* entry = var_entry.value();
1407
1408 // See Dictionary::EntryToIndex()
1409 Node* index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize));
1410 Node* current = LoadFixedArrayElementInt32Index(dictionary, index,
1411 kElementsStartOffset);
1412 GotoIf(WordEqual(current, undefined), if_not_found);
1413 GotoIf(WordEqual(current, unique_name), if_found);
1414
1415 // See Dictionary::NextProbe().
1416 count = Int32Add(count, Int32Constant(1));
1417 entry = Word32And(Int32Add(entry, count), mask);
1418
1419 var_count.Bind(count);
1420 var_entry.Bind(entry);
1421 Goto(&loop);
1422 }
1423 }
1424
1425 Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) {
1426 // See v8::internal::ComputeIntegerHash()
1427 Node* hash = key;
1428 hash = Word32Xor(hash, seed);
1429 hash = Int32Add(Word32Xor(hash, Int32Constant(0xffffffff)),
1430 Word32Shl(hash, Int32Constant(15)));
Toon Verwaest 2016/05/19 14:50:22 What about explicitly sharing these constants with
Igor Sheludko 2016/05/30 12:11:34 I think we can just rely on a respective unit test
1431 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12)));
1432 hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2)));
1433 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4)));
1434 hash = Int32Mul(hash, Int32Constant(2057));
1435 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16)));
1436 return Word32And(hash, Int32Constant(0x3fffffff));
1437 }
1438
1439 template <typename Dictionary>
1440 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, Node* key,
1441 Label* if_found,
1442 Label* if_not_found,
1443 Label* call_runtime) {
1444 const int kElementsStartOffset =
1445 Dictionary::kElementsStartIndex * kPointerSize;
1446
1447 Node* capacity = SmiToWord32(LoadFixedArrayElementConstantIndex(
1448 dictionary, Dictionary::kCapacityIndex));
1449 Node* mask = Int32Sub(capacity, Int32Constant(1));
1450
1451 Node* seed;
1452 if (Dictionary::ShapeT::UsesSeed) {
1453 seed = HashSeed();
1454 } else {
1455 seed = Int32Constant(kZeroHashSeed);
1456 }
1457 Node* hash = ComputeIntegerHash(key, seed);
1458 Node* key_as_float64 = ChangeUint32ToFloat64(key);
1459
1460 // See Dictionary::FirstProbe().
1461 Node* count = Int32Constant(0);
1462 Node* entry = Word32And(hash, mask);
1463
1464 Node* undefined = UndefinedConstant();
1465 Node* the_hole = TheHoleConstant();
1466
1467 Variable var_count(this, MachineRepresentation::kWord32);
1468 Variable var_entry(this, MachineType::PointerRepresentation());
1469 Variable* loop_vars[] = {&var_count, &var_entry};
1470 Label loop(this, 2, loop_vars);
1471 var_count.Bind(count);
1472 var_entry.Bind(entry);
1473 Goto(&loop);
1474 Bind(&loop);
1475 {
1476 Node* count = var_count.value();
1477 Node* entry = var_entry.value();
1478
1479 // See Dictionary::EntryToIndex()
1480 Node* index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize));
1481 Node* current = LoadFixedArrayElementInt32Index(dictionary, index,
1482 kElementsStartOffset);
1483 GotoIf(WordEqual(current, undefined), if_not_found);
1484 Label next_probe(this);
1485 {
1486 Label if_currentissmi(this), if_currentisnotsmi(this);
1487 Branch(WordIsSmi(current), &if_currentissmi, &if_currentisnotsmi);
1488 Bind(&if_currentissmi);
1489 {
1490 Node* current_value = SmiToWord32(current);
1491 Branch(Word32Equal(current_value, key), if_found, &next_probe);
1492 }
1493 Bind(&if_currentisnotsmi);
1494 {
1495 GotoIf(WordEqual(current, the_hole), &next_probe);
1496 // Current must be the Number.
1497 Node* current_value = LoadHeapNumberValue(current);
1498 Branch(Float64Equal(current_value, key_as_float64), if_found,
1499 &next_probe);
1500 }
1501 }
1502
1503 Bind(&next_probe);
1504 // See Dictionary::NextProbe().
1505 count = Int32Add(count, Int32Constant(1));
1506 entry = Word32And(Int32Add(entry, count), mask);
1507
1508 var_count.Bind(count);
1509 var_entry.Bind(entry);
1510 Goto(&loop);
1325 } 1511 }
1326 } 1512 }
1327 1513
1328 void CodeStubAssembler::TryLookupProperty(Node* object, Node* map, 1514 void CodeStubAssembler::TryLookupProperty(Node* object, Node* map,
1329 Node* instance_type, Node* name, 1515 Node* instance_type,
1330 Label* if_found, Label* if_not_found, 1516 Node* unique_name, Label* if_found,
1517 Label* if_not_found,
1331 Label* call_runtime) { 1518 Label* call_runtime) {
1332 { 1519 // Handle non-simple objects in runtime.
1333 Label if_objectissimple(this); 1520 GotoIf(Int32LessThanOrEqual(instance_type,
1334 Branch(Int32LessThanOrEqual(instance_type, 1521 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
1335 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), 1522 call_runtime);
1336 call_runtime, &if_objectissimple); 1523
1337 Bind(&if_objectissimple);
1338 }
1339
1340 // TODO(verwaest): Perform a dictonary lookup on slow-mode receivers.
1341 Node* bit_field3 = LoadMapBitField3(map); 1524 Node* bit_field3 = LoadMapBitField3(map);
1342 Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3); 1525 Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3);
1343 Label if_isfastmap(this); 1526 Label if_isfastmap(this), if_isslowmap(this);
1344 Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, call_runtime); 1527 Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, &if_isslowmap);
1345 Bind(&if_isfastmap); 1528 Bind(&if_isfastmap);
1346 Node* nof = BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3); 1529 {
1347 // Bail out to the runtime for large numbers of own descriptors. The stub only 1530 Node* nof = BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3);
1348 // does linear search, which becomes too expensive in that case. 1531 // Bail out to the runtime for large numbers of own descriptors. The stub
1349 { 1532 // only does linear search, which becomes too expensive in that case.
1350 static const int32_t kMaxLinear = 210;
1351 Label above_max(this), below_max(this);
1352 Branch(Int32LessThanOrEqual(nof, Int32Constant(kMaxLinear)), &below_max,
1353 call_runtime);
1354 Bind(&below_max);
1355 }
1356 Node* descriptors = LoadMapDescriptors(map);
1357
1358 Variable var_descriptor(this, MachineRepresentation::kWord32);
1359 Label loop(this, &var_descriptor);
1360 var_descriptor.Bind(Int32Constant(0));
1361 Goto(&loop);
1362 Bind(&loop);
1363 {
1364 Node* index = var_descriptor.value();
1365 Node* offset = Int32Constant(DescriptorArray::ToKeyIndex(0));
1366 Node* factor = Int32Constant(DescriptorArray::kDescriptorSize);
1367 Label if_notdone(this);
1368 Branch(Word32Equal(index, nof), if_not_found, &if_notdone);
1369 Bind(&if_notdone);
1370 { 1533 {
1534 static const int32_t kMaxLinear = 210;
1535 GotoIf(Int32GreaterThan(nof, Int32Constant(kMaxLinear)), call_runtime);
1536 }
1537 Node* descriptors = LoadMapDescriptors(map);
1538
1539 Variable var_descriptor(this, MachineRepresentation::kWord32);
1540 Label loop(this, &var_descriptor);
1541 var_descriptor.Bind(Int32Constant(0));
1542 Goto(&loop);
1543 Bind(&loop);
1544 {
1545 Node* index = var_descriptor.value();
1546 Node* offset = Int32Constant(DescriptorArray::ToKeyIndex(0));
1547 Node* factor = Int32Constant(DescriptorArray::kDescriptorSize);
1548 GotoIf(Word32Equal(index, nof), if_not_found);
1549
1371 Node* array_index = Int32Add(offset, Int32Mul(index, factor)); 1550 Node* array_index = Int32Add(offset, Int32Mul(index, factor));
1372 Node* current = LoadFixedArrayElementInt32Index(descriptors, array_index); 1551 Node* current = LoadFixedArrayElementInt32Index(descriptors, array_index);
1373 Label if_unequal(this); 1552 GotoIf(WordEqual(current, unique_name), if_found);
1374 Branch(WordEqual(current, name), if_found, &if_unequal);
1375 Bind(&if_unequal);
1376 1553
1377 var_descriptor.Bind(Int32Add(index, Int32Constant(1))); 1554 var_descriptor.Bind(Int32Add(index, Int32Constant(1)));
1378 Goto(&loop); 1555 Goto(&loop);
1379 } 1556 }
1380 } 1557 }
1558 Bind(&if_isslowmap);
1559 {
1560 Node* dictionary = LoadProperties(object);
1561
1562 Label if_isglobal(this), if_isnotglobal(this);
1563 Branch(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)),
1564 &if_isglobal, &if_isnotglobal);
1565
1566 Bind(&if_isnotglobal);
1567 NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found,
1568 if_not_found, call_runtime);
1569
1570 Bind(&if_isglobal);
1571 NameDictionaryLookup<GlobalDictionary>(dictionary, unique_name, if_found,
Toon Verwaest 2016/05/19 14:50:22 JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYP
Igor Sheludko 2016/05/30 12:11:34 Fixed and added unit tests.
1572 if_not_found, call_runtime);
1573 }
1381 } 1574 }
1382 1575
1383 void CodeStubAssembler::TryLookupElement(Node* object, Node* map, 1576 void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
1384 Node* instance_type, Node* index, 1577 Node* instance_type, Node* index,
1385 Label* if_found, Label* if_not_found, 1578 Label* if_found, Label* if_not_found,
1386 Label* call_runtime) { 1579 Label* call_runtime) {
1387 { 1580 // Handle objects with non-simple elements in runtime.
1388 Label if_objectissimple(this); 1581 GotoIf(Int32LessThanOrEqual(instance_type,
1389 Branch(Int32LessThanOrEqual(instance_type, 1582 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
1390 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), 1583 call_runtime);
1391 call_runtime, &if_objectissimple);
1392 Bind(&if_objectissimple);
1393 }
1394 1584
1395 Node* bit_field2 = LoadMapBitField2(map); 1585 Node* bit_field2 = LoadMapBitField2(map);
1396 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2); 1586 Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2);
1397 1587
1398 // TODO(verwaest): Support other elements kinds as well. 1588 // TODO(verwaest): Support other elements kinds as well.
1399 Label if_isobjectorsmi(this); 1589 Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this);
1400 Branch( 1590 // clang-format off
1401 Int32LessThanOrEqual(elements_kind, Int32Constant(FAST_HOLEY_ELEMENTS)), 1591 int32_t values[] = {
1402 &if_isobjectorsmi, call_runtime); 1592 // Handled by {if_isobjectorsmi}.
1593 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS,
1594 FAST_HOLEY_ELEMENTS, FAST_STRING_WRAPPER_ELEMENTS,
1595 // Handled by {if_isdouble}.
1596 FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS,
1597 // Handled by {if_is_dictionary}.
1598 DICTIONARY_ELEMENTS, SLOW_STRING_WRAPPER_ELEMENTS,
1599 };
1600 Label* labels[] = {
1601 &if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi,
1602 &if_isobjectorsmi, &if_isobjectorsmi,
1603 &if_isdouble, &if_isdouble,
1604 &if_isdictionary, &if_isdictionary,
1605 };
1606 // clang-format on
1607 STATIC_ASSERT(arraysize(values) == arraysize(labels));
1608 Switch(elements_kind, call_runtime, values, labels, arraysize(values));
1609
1403 Bind(&if_isobjectorsmi); 1610 Bind(&if_isobjectorsmi);
1404 { 1611 {
1405 Node* elements = LoadElements(object); 1612 Node* elements = LoadElements(object);
1406 Node* length = LoadFixedArrayBaseLength(elements); 1613 Node* length = LoadFixedArrayBaseLength(elements);
1407 1614
1408 Label if_iskeyinrange(this); 1615 GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found);
1409 Branch(Int32LessThan(index, SmiToWord32(length)), &if_iskeyinrange, 1616
1410 if_not_found);
1411
1412 Bind(&if_iskeyinrange);
1413 Node* element = LoadFixedArrayElementInt32Index(elements, index); 1617 Node* element = LoadFixedArrayElementInt32Index(elements, index);
1414 Node* the_hole = LoadRoot(Heap::kTheHoleValueRootIndex); 1618 Node* the_hole = TheHoleConstant();
1415 Branch(WordEqual(element, the_hole), if_not_found, if_found); 1619 Branch(WordEqual(element, the_hole), if_not_found, if_found);
1416 } 1620 }
1621 Bind(&if_isdouble);
1622 {
1623 Node* elements = LoadElements(object);
1624 Node* length = LoadFixedArrayBaseLength(elements);
1625
1626 GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found);
1627
1628 if (kPointerSize == kDoubleSize) {
1629 Node* element = LoadFixedDoubleArrayElementInt32Index(
1630 elements, index, MachineType::Uint64());
1631 Node* the_hole = Int64Constant(kHoleNanInt64);
1632 Branch(Word64Equal(element, the_hole), if_not_found, if_found);
1633 } else {
1634 DCHECK_EQ(4, kPointerSize);
1635 Node* offset = OffsetOfFixedDoubleArrayElementInt32Index(index);
1636 // Since upper and lower parts are the same, don't care about endianness.
1637 STATIC_ASSERT(kHoleNanUpper32 == kHoleNanLower32);
1638 Node* element_lo = Load(MachineType::Int32(), elements, offset);
1639 GotoUnless(Word32Equal(element_lo, Int32Constant(kHoleNanLower32)),
1640 if_found);
1641 Node* element_hi = Load(MachineType::Int32(), elements,
1642 Int32Add(offset, Int32Constant(kPointerSize)));
1643 Branch(Word32Equal(element_hi, Int32Constant(kHoleNanUpper32)),
1644 if_not_found, if_found);
1645 }
1646 }
1647 Bind(&if_isdictionary);
1648 {
1649 Node* elements = LoadElements(object);
1650 NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found,
1651 if_not_found, call_runtime);
1652 }
1417 } 1653 }
1418 1654
1419 Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, 1655 Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
1420 Node* object) { 1656 Node* object) {
1421 Variable var_result(this, MachineRepresentation::kTagged); 1657 Variable var_result(this, MachineRepresentation::kTagged);
1422 Label return_false(this), return_true(this), 1658 Label return_false(this), return_true(this),
1423 return_runtime(this, Label::kDeferred), return_result(this); 1659 return_runtime(this, Label::kDeferred), return_result(this);
1424 1660
1425 // Goto runtime if {object} is a Smi. 1661 // Goto runtime if {object} is a Smi.
1426 GotoIf(WordIsSmi(object), &return_runtime); 1662 GotoIf(WordIsSmi(object), &return_runtime);
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1547 CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object)); 1783 CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object));
1548 } 1784 }
1549 Goto(&return_result); 1785 Goto(&return_result);
1550 1786
1551 Bind(&return_result); 1787 Bind(&return_result);
1552 return var_result.value(); 1788 return var_result.value();
1553 } 1789 }
1554 1790
1555 } // namespace internal 1791 } // namespace internal
1556 } // namespace v8 1792 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698