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 |