OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 <assert.h> // For assert | 5 #include <assert.h> // For assert |
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_PPC | 8 #if V8_TARGET_ARCH_PPC |
9 | 9 |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 3185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3196 b(&other_color); | 3196 b(&other_color); |
3197 | 3197 |
3198 bind(&word_boundary); | 3198 bind(&word_boundary); |
3199 lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kIntSize)); | 3199 lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kIntSize)); |
3200 andi(r0, ip, Operand(1)); | 3200 andi(r0, ip, Operand(1)); |
3201 b(second_bit == 1 ? ne : eq, has_color, cr0); | 3201 b(second_bit == 1 ? ne : eq, has_color, cr0); |
3202 bind(&other_color); | 3202 bind(&other_color); |
3203 } | 3203 } |
3204 | 3204 |
3205 | 3205 |
3206 // Detect some, but not all, common pointer-free objects. This is used by the | |
3207 // incremental write barrier which doesn't care about oddballs (they are always | |
3208 // marked black immediately so this code is not hit). | |
3209 void MacroAssembler::JumpIfDataObject(Register value, Register scratch, | |
3210 Label* not_data_object) { | |
3211 Label is_data_object; | |
3212 LoadP(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | |
3213 CompareRoot(scratch, Heap::kHeapNumberMapRootIndex); | |
3214 beq(&is_data_object); | |
3215 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | |
3216 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | |
3217 // If it's a string and it's not a cons string then it's an object containing | |
3218 // no GC pointers. | |
3219 lbz(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | |
3220 STATIC_ASSERT((kIsIndirectStringMask | kIsNotStringMask) == 0x81); | |
3221 andi(scratch, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); | |
3222 bne(not_data_object, cr0); | |
3223 bind(&is_data_object); | |
3224 } | |
3225 | |
3226 | |
3227 void MacroAssembler::GetMarkBits(Register addr_reg, Register bitmap_reg, | 3206 void MacroAssembler::GetMarkBits(Register addr_reg, Register bitmap_reg, |
3228 Register mask_reg) { | 3207 Register mask_reg) { |
3229 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); | 3208 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); |
3230 DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0); | 3209 DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0); |
3231 lis(r0, Operand((~Page::kPageAlignmentMask >> 16))); | 3210 lis(r0, Operand((~Page::kPageAlignmentMask >> 16))); |
3232 and_(bitmap_reg, addr_reg, r0); | 3211 and_(bitmap_reg, addr_reg, r0); |
3233 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; | 3212 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; |
3234 ExtractBitRange(mask_reg, addr_reg, kLowBits - 1, kPointerSizeLog2); | 3213 ExtractBitRange(mask_reg, addr_reg, kLowBits - 1, kPointerSizeLog2); |
3235 ExtractBitRange(ip, addr_reg, kPageSizeBits - 1, kLowBits); | 3214 ExtractBitRange(ip, addr_reg, kPageSizeBits - 1, kLowBits); |
3236 ShiftLeftImm(ip, ip, Operand(Bitmap::kBytesPerCellLog2)); | 3215 ShiftLeftImm(ip, ip, Operand(Bitmap::kBytesPerCellLog2)); |
3237 add(bitmap_reg, bitmap_reg, ip); | 3216 add(bitmap_reg, bitmap_reg, ip); |
3238 li(ip, Operand(1)); | 3217 li(ip, Operand(1)); |
3239 slw(mask_reg, ip, mask_reg); | 3218 slw(mask_reg, ip, mask_reg); |
3240 } | 3219 } |
3241 | 3220 |
3242 | 3221 |
3243 void MacroAssembler::EnsureNotWhite(Register value, Register bitmap_scratch, | 3222 void MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch, |
3244 Register mask_scratch, | 3223 Register mask_scratch, Register load_scratch, |
3245 Register load_scratch, | 3224 Label* value_is_white) { |
3246 Label* value_is_white_and_not_data) { | |
3247 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ip)); | 3225 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ip)); |
3248 GetMarkBits(value, bitmap_scratch, mask_scratch); | 3226 GetMarkBits(value, bitmap_scratch, mask_scratch); |
3249 | 3227 |
3250 // If the value is black or grey we don't need to do anything. | 3228 // If the value is black or grey we don't need to do anything. |
3251 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 3229 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
3252 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); | 3230 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
3253 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); | 3231 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); |
3254 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 3232 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
3255 | 3233 |
3256 Label done; | |
3257 | |
3258 // Since both black and grey have a 1 in the first position and white does | 3234 // Since both black and grey have a 1 in the first position and white does |
3259 // not have a 1 there we only need to check one bit. | 3235 // not have a 1 there we only need to check one bit. |
3260 lwz(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 3236 lwz(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
3261 and_(r0, mask_scratch, load_scratch, SetRC); | 3237 and_(r0, mask_scratch, load_scratch, SetRC); |
3262 bne(&done, cr0); | 3238 beq(value_is_white, cr0); |
3263 | |
3264 if (emit_debug_code()) { | |
3265 // Check for impossible bit pattern. | |
3266 Label ok; | |
3267 // LSL may overflow, making the check conservative. | |
3268 slwi(r0, mask_scratch, Operand(1)); | |
3269 and_(r0, load_scratch, r0, SetRC); | |
3270 beq(&ok, cr0); | |
3271 stop("Impossible marking bit pattern"); | |
3272 bind(&ok); | |
3273 } | |
3274 | |
3275 // Value is white. We check whether it is data that doesn't need scanning. | |
3276 // Currently only checks for HeapNumber and non-cons strings. | |
3277 Register map = load_scratch; // Holds map while checking type. | |
3278 Register length = load_scratch; // Holds length of object after testing type. | |
3279 Label is_data_object, maybe_string_object, is_string_object, is_encoded; | |
3280 #if V8_TARGET_ARCH_PPC64 | |
3281 Label length_computed; | |
3282 #endif | |
3283 | |
3284 | |
3285 // Check for heap-number | |
3286 LoadP(map, FieldMemOperand(value, HeapObject::kMapOffset)); | |
3287 CompareRoot(map, Heap::kHeapNumberMapRootIndex); | |
3288 bne(&maybe_string_object); | |
3289 li(length, Operand(HeapNumber::kSize)); | |
3290 b(&is_data_object); | |
3291 bind(&maybe_string_object); | |
3292 | |
3293 // Check for strings. | |
3294 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | |
3295 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | |
3296 // If it's a string and it's not a cons string then it's an object containing | |
3297 // no GC pointers. | |
3298 Register instance_type = load_scratch; | |
3299 lbz(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); | |
3300 andi(r0, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask)); | |
3301 bne(value_is_white_and_not_data, cr0); | |
3302 // It's a non-indirect (non-cons and non-slice) string. | |
3303 // If it's external, the length is just ExternalString::kSize. | |
3304 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). | |
3305 // External strings are the only ones with the kExternalStringTag bit | |
3306 // set. | |
3307 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); | |
3308 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); | |
3309 andi(r0, instance_type, Operand(kExternalStringTag)); | |
3310 beq(&is_string_object, cr0); | |
3311 li(length, Operand(ExternalString::kSize)); | |
3312 b(&is_data_object); | |
3313 bind(&is_string_object); | |
3314 | |
3315 // Sequential string, either Latin1 or UC16. | |
3316 // For Latin1 (char-size of 1) we untag the smi to get the length. | |
3317 // For UC16 (char-size of 2): | |
3318 // - (32-bit) we just leave the smi tag in place, thereby getting | |
3319 // the length multiplied by 2. | |
3320 // - (64-bit) we compute the offset in the 2-byte array | |
3321 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4); | |
3322 LoadP(ip, FieldMemOperand(value, String::kLengthOffset)); | |
3323 andi(r0, instance_type, Operand(kStringEncodingMask)); | |
3324 beq(&is_encoded, cr0); | |
3325 SmiUntag(ip); | |
3326 #if V8_TARGET_ARCH_PPC64 | |
3327 b(&length_computed); | |
3328 #endif | |
3329 bind(&is_encoded); | |
3330 #if V8_TARGET_ARCH_PPC64 | |
3331 SmiToShortArrayOffset(ip, ip); | |
3332 bind(&length_computed); | |
3333 #else | |
3334 DCHECK(kSmiShift == 1); | |
3335 #endif | |
3336 addi(length, ip, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); | |
3337 li(r0, Operand(~kObjectAlignmentMask)); | |
3338 and_(length, length, r0); | |
3339 | |
3340 bind(&is_data_object); | |
3341 // Value is a data object, and it is white. Mark it black. Since we know | |
3342 // that the object is white we can make it black by flipping one bit. | |
3343 lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | |
3344 orx(ip, ip, mask_scratch); | |
3345 stw(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | |
3346 | |
3347 mov(ip, Operand(~Page::kPageAlignmentMask)); | |
3348 and_(bitmap_scratch, bitmap_scratch, ip); | |
3349 lwz(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | |
3350 add(ip, ip, length); | |
3351 stw(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | |
3352 | |
3353 bind(&done); | |
3354 } | 3239 } |
3355 | 3240 |
3356 | 3241 |
3357 // Saturate a value into 8-bit unsigned integer | 3242 // Saturate a value into 8-bit unsigned integer |
3358 // if input_value < 0, output_value is 0 | 3243 // if input_value < 0, output_value is 0 |
3359 // if input_value > 255, output_value is 255 | 3244 // if input_value > 255, output_value is 255 |
3360 // otherwise output_value is the input_value | 3245 // otherwise output_value is the input_value |
3361 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { | 3246 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { |
3362 int satval = (1 << 8) - 1; | 3247 int satval = (1 << 8) - 1; |
3363 | 3248 |
(...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4404 } | 4289 } |
4405 if (mag.shift > 0) srawi(result, result, mag.shift); | 4290 if (mag.shift > 0) srawi(result, result, mag.shift); |
4406 ExtractBit(r0, dividend, 31); | 4291 ExtractBit(r0, dividend, 31); |
4407 add(result, result, r0); | 4292 add(result, result, r0); |
4408 } | 4293 } |
4409 | 4294 |
4410 } // namespace internal | 4295 } // namespace internal |
4411 } // namespace v8 | 4296 } // namespace v8 |
4412 | 4297 |
4413 #endif // V8_TARGET_ARCH_PPC | 4298 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |