| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
| 8 | 8 |
| 9 #include "src/base/division-by-constant.h" | 9 #include "src/base/division-by-constant.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 5841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5852 Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg)); | 5852 Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg)); |
| 5853 // Shift left 1 by adding. | 5853 // Shift left 1 by adding. |
| 5854 Daddu(mask_scratch, mask_scratch, Operand(mask_scratch)); | 5854 Daddu(mask_scratch, mask_scratch, Operand(mask_scratch)); |
| 5855 And(t8, t9, Operand(mask_scratch)); | 5855 And(t8, t9, Operand(mask_scratch)); |
| 5856 Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg)); | 5856 Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg)); |
| 5857 | 5857 |
| 5858 bind(&other_color); | 5858 bind(&other_color); |
| 5859 } | 5859 } |
| 5860 | 5860 |
| 5861 | 5861 |
| 5862 // Detect some, but not all, common pointer-free objects. This is used by the | |
| 5863 // incremental write barrier which doesn't care about oddballs (they are always | |
| 5864 // marked black immediately so this code is not hit). | |
| 5865 void MacroAssembler::JumpIfDataObject(Register value, | |
| 5866 Register scratch, | |
| 5867 Label* not_data_object) { | |
| 5868 DCHECK(!AreAliased(value, scratch, t8, no_reg)); | |
| 5869 Label is_data_object; | |
| 5870 ld(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | |
| 5871 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | |
| 5872 Branch(&is_data_object, eq, t8, Operand(scratch)); | |
| 5873 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | |
| 5874 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | |
| 5875 // If it's a string and it's not a cons string then it's an object containing | |
| 5876 // no GC pointers. | |
| 5877 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | |
| 5878 And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); | |
| 5879 Branch(not_data_object, ne, t8, Operand(zero_reg)); | |
| 5880 bind(&is_data_object); | |
| 5881 } | |
| 5882 | |
| 5883 | |
| 5884 void MacroAssembler::GetMarkBits(Register addr_reg, | 5862 void MacroAssembler::GetMarkBits(Register addr_reg, |
| 5885 Register bitmap_reg, | 5863 Register bitmap_reg, |
| 5886 Register mask_reg) { | 5864 Register mask_reg) { |
| 5887 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); | 5865 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); |
| 5888 // addr_reg is divided into fields: | 5866 // addr_reg is divided into fields: |
| 5889 // |63 page base 20|19 high 8|7 shift 3|2 0| | 5867 // |63 page base 20|19 high 8|7 shift 3|2 0| |
| 5890 // 'high' gives the index of the cell holding color bits for the object. | 5868 // 'high' gives the index of the cell holding color bits for the object. |
| 5891 // 'shift' gives the offset in the cell for this object's color. | 5869 // 'shift' gives the offset in the cell for this object's color. |
| 5892 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); | 5870 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); |
| 5893 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); | 5871 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); |
| 5894 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; | 5872 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; |
| 5895 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); | 5873 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); |
| 5896 dsll(t8, t8, Bitmap::kBytesPerCellLog2); | 5874 dsll(t8, t8, Bitmap::kBytesPerCellLog2); |
| 5897 Daddu(bitmap_reg, bitmap_reg, t8); | 5875 Daddu(bitmap_reg, bitmap_reg, t8); |
| 5898 li(t8, Operand(1)); | 5876 li(t8, Operand(1)); |
| 5899 dsllv(mask_reg, t8, mask_reg); | 5877 dsllv(mask_reg, t8, mask_reg); |
| 5900 } | 5878 } |
| 5901 | 5879 |
| 5902 | 5880 |
| 5903 void MacroAssembler::EnsureNotWhite( | 5881 void MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch, |
| 5904 Register value, | 5882 Register mask_scratch, Register load_scratch, |
| 5905 Register bitmap_scratch, | 5883 Label* value_is_white) { |
| 5906 Register mask_scratch, | |
| 5907 Register load_scratch, | |
| 5908 Label* value_is_white_and_not_data) { | |
| 5909 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); | 5884 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); |
| 5910 GetMarkBits(value, bitmap_scratch, mask_scratch); | 5885 GetMarkBits(value, bitmap_scratch, mask_scratch); |
| 5911 | 5886 |
| 5912 // If the value is black or grey we don't need to do anything. | 5887 // If the value is black or grey we don't need to do anything. |
| 5913 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 5888 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
| 5914 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); | 5889 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| 5915 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); | 5890 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); |
| 5916 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 5891 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 5917 | 5892 |
| 5918 Label done; | |
| 5919 | |
| 5920 // Since both black and grey have a 1 in the first position and white does | 5893 // Since both black and grey have a 1 in the first position and white does |
| 5921 // not have a 1 there we only need to check one bit. | 5894 // not have a 1 there we only need to check one bit. |
| 5922 // Note that we are using a 4-byte aligned 8-byte load. | 5895 // Note that we are using a 4-byte aligned 8-byte load. |
| 5923 if (emit_debug_code()) { | 5896 if (emit_debug_code()) { |
| 5924 LoadWordPair(load_scratch, | 5897 LoadWordPair(load_scratch, |
| 5925 MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5898 MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 5926 } else { | 5899 } else { |
| 5927 lwu(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5900 lwu(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 5928 } | 5901 } |
| 5929 And(t8, mask_scratch, load_scratch); | 5902 And(t8, mask_scratch, load_scratch); |
| 5930 Branch(&done, ne, t8, Operand(zero_reg)); | 5903 Branch(value_is_white, eq, t8, Operand(zero_reg)); |
| 5931 | |
| 5932 if (emit_debug_code()) { | |
| 5933 // Check for impossible bit pattern. | |
| 5934 Label ok; | |
| 5935 // sll may overflow, making the check conservative. | |
| 5936 dsll(t8, mask_scratch, 1); | |
| 5937 And(t8, load_scratch, t8); | |
| 5938 Branch(&ok, eq, t8, Operand(zero_reg)); | |
| 5939 stop("Impossible marking bit pattern"); | |
| 5940 bind(&ok); | |
| 5941 } | |
| 5942 | |
| 5943 // Value is white. We check whether it is data that doesn't need scanning. | |
| 5944 // Currently only checks for HeapNumber and non-cons strings. | |
| 5945 Register map = load_scratch; // Holds map while checking type. | |
| 5946 Register length = load_scratch; // Holds length of object after testing type. | |
| 5947 Label is_data_object; | |
| 5948 | |
| 5949 // Check for heap-number | |
| 5950 ld(map, FieldMemOperand(value, HeapObject::kMapOffset)); | |
| 5951 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | |
| 5952 { | |
| 5953 Label skip; | |
| 5954 Branch(&skip, ne, t8, Operand(map)); | |
| 5955 li(length, HeapNumber::kSize); | |
| 5956 Branch(&is_data_object); | |
| 5957 bind(&skip); | |
| 5958 } | |
| 5959 | |
| 5960 // Check for strings. | |
| 5961 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | |
| 5962 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | |
| 5963 // If it's a string and it's not a cons string then it's an object containing | |
| 5964 // no GC pointers. | |
| 5965 Register instance_type = load_scratch; | |
| 5966 lbu(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); | |
| 5967 And(t8, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask)); | |
| 5968 Branch(value_is_white_and_not_data, ne, t8, Operand(zero_reg)); | |
| 5969 // It's a non-indirect (non-cons and non-slice) string. | |
| 5970 // If it's external, the length is just ExternalString::kSize. | |
| 5971 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). | |
| 5972 // External strings are the only ones with the kExternalStringTag bit | |
| 5973 // set. | |
| 5974 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); | |
| 5975 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); | |
| 5976 And(t8, instance_type, Operand(kExternalStringTag)); | |
| 5977 { | |
| 5978 Label skip; | |
| 5979 Branch(&skip, eq, t8, Operand(zero_reg)); | |
| 5980 li(length, ExternalString::kSize); | |
| 5981 Branch(&is_data_object); | |
| 5982 bind(&skip); | |
| 5983 } | |
| 5984 | |
| 5985 // Sequential string, either Latin1 or UC16. | |
| 5986 // For Latin1 (char-size of 1) we shift the smi tag away to get the length. | |
| 5987 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby | |
| 5988 // getting the length multiplied by 2. | |
| 5989 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4); | |
| 5990 DCHECK(kSmiTag == 0 && kSmiTagSize == 1); | |
| 5991 lw(t9, UntagSmiFieldMemOperand(value, String::kLengthOffset)); | |
| 5992 And(t8, instance_type, Operand(kStringEncodingMask)); | |
| 5993 { | |
| 5994 Label skip; | |
| 5995 Branch(&skip, ne, t8, Operand(zero_reg)); | |
| 5996 // Adjust length for UC16. | |
| 5997 dsll(t9, t9, 1); | |
| 5998 bind(&skip); | |
| 5999 } | |
| 6000 Daddu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); | |
| 6001 DCHECK(!length.is(t8)); | |
| 6002 And(length, length, Operand(~kObjectAlignmentMask)); | |
| 6003 | |
| 6004 bind(&is_data_object); | |
| 6005 // Value is a data object, and it is white. Mark it black. Since we know | |
| 6006 // that the object is white we can make it black by flipping one bit. | |
| 6007 lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | |
| 6008 Or(t8, t8, Operand(mask_scratch)); | |
| 6009 sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | |
| 6010 | |
| 6011 And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); | |
| 6012 lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | |
| 6013 Addu(t8, t8, Operand(length)); | |
| 6014 sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | |
| 6015 | |
| 6016 bind(&done); | |
| 6017 } | 5904 } |
| 6018 | 5905 |
| 6019 | 5906 |
| 6020 void MacroAssembler::LoadInstanceDescriptors(Register map, | 5907 void MacroAssembler::LoadInstanceDescriptors(Register map, |
| 6021 Register descriptors) { | 5908 Register descriptors) { |
| 6022 ld(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); | 5909 ld(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); |
| 6023 } | 5910 } |
| 6024 | 5911 |
| 6025 | 5912 |
| 6026 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { | 5913 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6321 if (mag.shift > 0) sra(result, result, mag.shift); | 6208 if (mag.shift > 0) sra(result, result, mag.shift); |
| 6322 srl(at, dividend, 31); | 6209 srl(at, dividend, 31); |
| 6323 Addu(result, result, Operand(at)); | 6210 Addu(result, result, Operand(at)); |
| 6324 } | 6211 } |
| 6325 | 6212 |
| 6326 | 6213 |
| 6327 } // namespace internal | 6214 } // namespace internal |
| 6328 } // namespace v8 | 6215 } // namespace v8 |
| 6329 | 6216 |
| 6330 #endif // V8_TARGET_ARCH_MIPS64 | 6217 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |