| OLD | NEW |
| 1 | 1 |
| 2 // Copyright 2012 the V8 project authors. All rights reserved. | 2 // Copyright 2012 the V8 project authors. All rights reserved. |
| 3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
| 4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
| 5 | 5 |
| 6 #include <limits.h> // For LONG_MIN, LONG_MAX. | 6 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 7 | 7 |
| 8 #if V8_TARGET_ARCH_MIPS | 8 #if V8_TARGET_ARCH_MIPS |
| 9 | 9 |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 5410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5421 jmp(&other_color); | 5421 jmp(&other_color); |
| 5422 | 5422 |
| 5423 bind(&word_boundary); | 5423 bind(&word_boundary); |
| 5424 lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize)); | 5424 lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize)); |
| 5425 And(t9, t9, Operand(1)); | 5425 And(t9, t9, Operand(1)); |
| 5426 Branch(has_color, second_bit == 1 ? ne : eq, t9, Operand(zero_reg)); | 5426 Branch(has_color, second_bit == 1 ? ne : eq, t9, Operand(zero_reg)); |
| 5427 bind(&other_color); | 5427 bind(&other_color); |
| 5428 } | 5428 } |
| 5429 | 5429 |
| 5430 | 5430 |
| 5431 // Detect some, but not all, common pointer-free objects. This is used by the | |
| 5432 // incremental write barrier which doesn't care about oddballs (they are always | |
| 5433 // marked black immediately so this code is not hit). | |
| 5434 void MacroAssembler::JumpIfDataObject(Register value, | |
| 5435 Register scratch, | |
| 5436 Label* not_data_object) { | |
| 5437 DCHECK(!AreAliased(value, scratch, t8, no_reg)); | |
| 5438 Label is_data_object; | |
| 5439 lw(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | |
| 5440 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | |
| 5441 Branch(&is_data_object, eq, t8, Operand(scratch)); | |
| 5442 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | |
| 5443 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | |
| 5444 // If it's a string and it's not a cons string then it's an object containing | |
| 5445 // no GC pointers. | |
| 5446 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | |
| 5447 And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); | |
| 5448 Branch(not_data_object, ne, t8, Operand(zero_reg)); | |
| 5449 bind(&is_data_object); | |
| 5450 } | |
| 5451 | |
| 5452 | |
| 5453 void MacroAssembler::GetMarkBits(Register addr_reg, | 5431 void MacroAssembler::GetMarkBits(Register addr_reg, |
| 5454 Register bitmap_reg, | 5432 Register bitmap_reg, |
| 5455 Register mask_reg) { | 5433 Register mask_reg) { |
| 5456 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); | 5434 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); |
| 5457 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); | 5435 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); |
| 5458 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); | 5436 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); |
| 5459 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; | 5437 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; |
| 5460 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); | 5438 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); |
| 5461 sll(t8, t8, kPointerSizeLog2); | 5439 sll(t8, t8, kPointerSizeLog2); |
| 5462 Addu(bitmap_reg, bitmap_reg, t8); | 5440 Addu(bitmap_reg, bitmap_reg, t8); |
| 5463 li(t8, Operand(1)); | 5441 li(t8, Operand(1)); |
| 5464 sllv(mask_reg, t8, mask_reg); | 5442 sllv(mask_reg, t8, mask_reg); |
| 5465 } | 5443 } |
| 5466 | 5444 |
| 5467 | 5445 |
| 5468 void MacroAssembler::EnsureNotWhite( | 5446 void MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch, |
| 5469 Register value, | 5447 Register mask_scratch, Register load_scratch, |
| 5470 Register bitmap_scratch, | 5448 Label* value_is_white) { |
| 5471 Register mask_scratch, | |
| 5472 Register load_scratch, | |
| 5473 Label* value_is_white_and_not_data) { | |
| 5474 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); | 5449 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); |
| 5475 GetMarkBits(value, bitmap_scratch, mask_scratch); | 5450 GetMarkBits(value, bitmap_scratch, mask_scratch); |
| 5476 | 5451 |
| 5477 // If the value is black or grey we don't need to do anything. | 5452 // If the value is black or grey we don't need to do anything. |
| 5478 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 5453 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
| 5479 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); | 5454 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| 5480 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); | 5455 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); |
| 5481 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 5456 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 5482 | 5457 |
| 5483 Label done; | |
| 5484 | |
| 5485 // Since both black and grey have a 1 in the first position and white does | 5458 // Since both black and grey have a 1 in the first position and white does |
| 5486 // not have a 1 there we only need to check one bit. | 5459 // not have a 1 there we only need to check one bit. |
| 5487 lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5460 lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 5488 And(t8, mask_scratch, load_scratch); | 5461 And(t8, mask_scratch, load_scratch); |
| 5489 Branch(&done, ne, t8, Operand(zero_reg)); | 5462 Branch(value_is_white, eq, t8, Operand(zero_reg)); |
| 5490 | |
| 5491 if (emit_debug_code()) { | |
| 5492 // Check for impossible bit pattern. | |
| 5493 Label ok; | |
| 5494 // sll may overflow, making the check conservative. | |
| 5495 sll(t8, mask_scratch, 1); | |
| 5496 And(t8, load_scratch, t8); | |
| 5497 Branch(&ok, eq, t8, Operand(zero_reg)); | |
| 5498 stop("Impossible marking bit pattern"); | |
| 5499 bind(&ok); | |
| 5500 } | |
| 5501 | |
| 5502 // Value is white. We check whether it is data that doesn't need scanning. | |
| 5503 // Currently only checks for HeapNumber and non-cons strings. | |
| 5504 Register map = load_scratch; // Holds map while checking type. | |
| 5505 Register length = load_scratch; // Holds length of object after testing type. | |
| 5506 Label is_data_object; | |
| 5507 | |
| 5508 // Check for heap-number | |
| 5509 lw(map, FieldMemOperand(value, HeapObject::kMapOffset)); | |
| 5510 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | |
| 5511 { | |
| 5512 Label skip; | |
| 5513 Branch(&skip, ne, t8, Operand(map)); | |
| 5514 li(length, HeapNumber::kSize); | |
| 5515 Branch(&is_data_object); | |
| 5516 bind(&skip); | |
| 5517 } | |
| 5518 | |
| 5519 // Check for strings. | |
| 5520 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | |
| 5521 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | |
| 5522 // If it's a string and it's not a cons string then it's an object containing | |
| 5523 // no GC pointers. | |
| 5524 Register instance_type = load_scratch; | |
| 5525 lbu(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); | |
| 5526 And(t8, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask)); | |
| 5527 Branch(value_is_white_and_not_data, ne, t8, Operand(zero_reg)); | |
| 5528 // It's a non-indirect (non-cons and non-slice) string. | |
| 5529 // If it's external, the length is just ExternalString::kSize. | |
| 5530 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). | |
| 5531 // External strings are the only ones with the kExternalStringTag bit | |
| 5532 // set. | |
| 5533 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); | |
| 5534 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); | |
| 5535 And(t8, instance_type, Operand(kExternalStringTag)); | |
| 5536 { | |
| 5537 Label skip; | |
| 5538 Branch(&skip, eq, t8, Operand(zero_reg)); | |
| 5539 li(length, ExternalString::kSize); | |
| 5540 Branch(&is_data_object); | |
| 5541 bind(&skip); | |
| 5542 } | |
| 5543 | |
| 5544 // Sequential string, either Latin1 or UC16. | |
| 5545 // For Latin1 (char-size of 1) we shift the smi tag away to get the length. | |
| 5546 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby | |
| 5547 // getting the length multiplied by 2. | |
| 5548 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4); | |
| 5549 DCHECK(kSmiTag == 0 && kSmiTagSize == 1); | |
| 5550 lw(t9, FieldMemOperand(value, String::kLengthOffset)); | |
| 5551 And(t8, instance_type, Operand(kStringEncodingMask)); | |
| 5552 { | |
| 5553 Label skip; | |
| 5554 Branch(&skip, eq, t8, Operand(zero_reg)); | |
| 5555 srl(t9, t9, 1); | |
| 5556 bind(&skip); | |
| 5557 } | |
| 5558 Addu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); | |
| 5559 And(length, length, Operand(~kObjectAlignmentMask)); | |
| 5560 | |
| 5561 bind(&is_data_object); | |
| 5562 // Value is a data object, and it is white. Mark it black. Since we know | |
| 5563 // that the object is white we can make it black by flipping one bit. | |
| 5564 lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | |
| 5565 Or(t8, t8, Operand(mask_scratch)); | |
| 5566 sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | |
| 5567 | |
| 5568 And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); | |
| 5569 lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | |
| 5570 Addu(t8, t8, Operand(length)); | |
| 5571 sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | |
| 5572 | |
| 5573 bind(&done); | |
| 5574 } | 5463 } |
| 5575 | 5464 |
| 5576 | 5465 |
| 5577 void MacroAssembler::LoadInstanceDescriptors(Register map, | 5466 void MacroAssembler::LoadInstanceDescriptors(Register map, |
| 5578 Register descriptors) { | 5467 Register descriptors) { |
| 5579 lw(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); | 5468 lw(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); |
| 5580 } | 5469 } |
| 5581 | 5470 |
| 5582 | 5471 |
| 5583 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { | 5472 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5864 if (mag.shift > 0) sra(result, result, mag.shift); | 5753 if (mag.shift > 0) sra(result, result, mag.shift); |
| 5865 srl(at, dividend, 31); | 5754 srl(at, dividend, 31); |
| 5866 Addu(result, result, Operand(at)); | 5755 Addu(result, result, Operand(at)); |
| 5867 } | 5756 } |
| 5868 | 5757 |
| 5869 | 5758 |
| 5870 } // namespace internal | 5759 } // namespace internal |
| 5871 } // namespace v8 | 5760 } // namespace v8 |
| 5872 | 5761 |
| 5873 #endif // V8_TARGET_ARCH_MIPS | 5762 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |