| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 Label done; | 485 Label done; |
| 486 | 486 |
| 487 if (smi_check == INLINE_SMI_CHECK) { | 487 if (smi_check == INLINE_SMI_CHECK) { |
| 488 ASSERT_EQ(0, kSmiTag); | 488 ASSERT_EQ(0, kSmiTag); |
| 489 tst(value, Operand(kSmiTagMask)); | 489 tst(value, Operand(kSmiTagMask)); |
| 490 b(eq, &done); | 490 b(eq, &done); |
| 491 } | 491 } |
| 492 | 492 |
| 493 CheckPageFlag(value, | 493 CheckPageFlag(value, |
| 494 value, // Used as scratch. | 494 value, // Used as scratch. |
| 495 MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING, | 495 MemoryChunk::kPointersToHereAreInterestingMask, |
| 496 eq, | 496 eq, |
| 497 &done); | 497 &done); |
| 498 CheckPageFlag(object, | 498 CheckPageFlag(object, |
| 499 value, // Used as scratch. | 499 value, // Used as scratch. |
| 500 MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING, | 500 MemoryChunk::kPointersFromHereAreInterestingMask, |
| 501 eq, | 501 eq, |
| 502 &done); | 502 &done); |
| 503 | 503 |
| 504 // Record the actual write. | 504 // Record the actual write. |
| 505 if (lr_status == kLRHasNotBeenSaved) { | 505 if (lr_status == kLRHasNotBeenSaved) { |
| 506 push(lr); | 506 push(lr); |
| 507 } | 507 } |
| 508 RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode); | 508 RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode); |
| 509 CallStub(&stub); | 509 CallStub(&stub); |
| 510 if (lr_status == kLRHasNotBeenSaved) { | 510 if (lr_status == kLRHasNotBeenSaved) { |
| (...skipping 2682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3193 // Get the address of the constant. | 3193 // Get the address of the constant. |
| 3194 and_(result, result, Operand(kLdrOffsetMask)); | 3194 and_(result, result, Operand(kLdrOffsetMask)); |
| 3195 add(result, ldr_location, Operand(result)); | 3195 add(result, ldr_location, Operand(result)); |
| 3196 add(result, result, Operand(kPCRegOffset)); | 3196 add(result, result, Operand(kPCRegOffset)); |
| 3197 } | 3197 } |
| 3198 | 3198 |
| 3199 | 3199 |
| 3200 void MacroAssembler::CheckPageFlag( | 3200 void MacroAssembler::CheckPageFlag( |
| 3201 Register object, | 3201 Register object, |
| 3202 Register scratch, | 3202 Register scratch, |
| 3203 MemoryChunk::MemoryChunkFlags flag, | 3203 int mask, |
| 3204 Condition cc, | 3204 Condition cc, |
| 3205 Label* condition_met) { | 3205 Label* condition_met) { |
| 3206 and_(scratch, object, Operand(~Page::kPageAlignmentMask)); | 3206 and_(scratch, object, Operand(~Page::kPageAlignmentMask)); |
| 3207 ldr(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset)); | 3207 ldr(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset)); |
| 3208 tst(scratch, Operand(1 << flag)); | 3208 tst(scratch, Operand(mask)); |
| 3209 b(cc, condition_met); | 3209 b(cc, condition_met); |
| 3210 } | 3210 } |
| 3211 | 3211 |
| 3212 | 3212 |
| 3213 void MacroAssembler::JumpIfBlack(Register object, | 3213 void MacroAssembler::JumpIfBlack(Register object, |
| 3214 Register scratch0, | 3214 Register scratch0, |
| 3215 Register scratch1, | 3215 Register scratch1, |
| 3216 Label* on_black) { | 3216 Label* on_black) { |
| 3217 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. | 3217 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. |
| 3218 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 3218 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3276 and_(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); | 3276 and_(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); |
| 3277 Ubfx(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); | 3277 Ubfx(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); |
| 3278 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; | 3278 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; |
| 3279 Ubfx(ip, addr_reg, kLowBits, kPageSizeBits - kLowBits); | 3279 Ubfx(ip, addr_reg, kLowBits, kPageSizeBits - kLowBits); |
| 3280 add(bitmap_reg, bitmap_reg, Operand(ip, LSL, kPointerSizeLog2)); | 3280 add(bitmap_reg, bitmap_reg, Operand(ip, LSL, kPointerSizeLog2)); |
| 3281 mov(ip, Operand(1)); | 3281 mov(ip, Operand(1)); |
| 3282 mov(mask_reg, Operand(ip, LSL, mask_reg)); | 3282 mov(mask_reg, Operand(ip, LSL, mask_reg)); |
| 3283 } | 3283 } |
| 3284 | 3284 |
| 3285 | 3285 |
| 3286 void MacroAssembler::EnsureNotWhite( |
| 3287 Register value, |
| 3288 Register bitmap_scratch, |
| 3289 Register mask_scratch, |
| 3290 Register load_scratch, |
| 3291 Label* value_is_white_and_not_data) { |
| 3292 ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, ip)); |
| 3293 GetMarkBits(value, bitmap_scratch, mask_scratch); |
| 3294 |
| 3295 // If the value is black or grey we don't need to do anything. |
| 3296 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
| 3297 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| 3298 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); |
| 3299 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 3300 |
| 3301 Label done; |
| 3302 |
| 3303 // Since both black and grey have a 1 in the first position and white does |
| 3304 // not have a 1 there we only need to check one bit. |
| 3305 ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 3306 tst(mask_scratch, load_scratch); |
| 3307 b(ne, &done); |
| 3308 |
| 3309 if (FLAG_debug_code) { |
| 3310 // Check for impossible bit pattern. |
| 3311 Label ok; |
| 3312 // LSL may overflow, making the check conservative. |
| 3313 tst(load_scratch, Operand(mask_scratch, LSL, 1)); |
| 3314 b(eq, &ok); |
| 3315 stop("Impossible marking bit pattern"); |
| 3316 bind(&ok); |
| 3317 } |
| 3318 |
| 3319 // Value is white. We check whether it is data that doesn't need scanning. |
| 3320 // Currently only checks for HeapNumber and non-cons strings. |
| 3321 Register map = load_scratch; // Holds map while checking type. |
| 3322 Register length = load_scratch; // Holds length of object after testing type. |
| 3323 Label is_data_object; |
| 3324 |
| 3325 // Check for heap-number |
| 3326 ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); |
| 3327 CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
| 3328 mov(length, Operand(HeapNumber::kSize), LeaveCC, eq); |
| 3329 b(eq, &is_data_object); |
| 3330 |
| 3331 // Check for strings. |
| 3332 ASSERT(kConsStringTag == 1 && kIsConsStringMask == 1); |
| 3333 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); |
| 3334 // If it's a string and it's not a cons string then it's an object containing |
| 3335 // no GC pointers. |
| 3336 Register instance_type = load_scratch; |
| 3337 ldrb(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 3338 tst(instance_type, Operand(kIsConsStringMask | kIsNotStringMask)); |
| 3339 b(ne, value_is_white_and_not_data); |
| 3340 // It's a non-cons string. |
| 3341 // If it's external, the length is just ExternalString::kSize. |
| 3342 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). |
| 3343 // External strings are the only ones with the kExternalStringTag bit |
| 3344 // set. |
| 3345 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); |
| 3346 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); |
| 3347 tst(instance_type, Operand(kExternalStringTag)); |
| 3348 mov(length, Operand(ExternalString::kSize), LeaveCC, ne); |
| 3349 b(ne, &is_data_object); |
| 3350 |
| 3351 // Sequential string, either ASCII or UC16. |
| 3352 // For ASCII (char-size of 1) we shift the smi tag away to get the length. |
| 3353 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby |
| 3354 // getting the length multiplied by 2. |
| 3355 ASSERT(kAsciiStringTag == 4 && kStringEncodingMask == 4); |
| 3356 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 3357 ldr(ip, FieldMemOperand(value, String::kLengthOffset)); |
| 3358 tst(instance_type, Operand(kStringEncodingMask)); |
| 3359 mov(ip, Operand(ip, LSR, 1), LeaveCC, ne); |
| 3360 add(length, ip, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); |
| 3361 and_(length, length, Operand(~kObjectAlignmentMask)); |
| 3362 |
| 3363 bind(&is_data_object); |
| 3364 // Value is a data object, and it is white. Mark it black. Since we know |
| 3365 // that the object is white we can make it black by flipping one bit. |
| 3366 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 3367 orr(ip, ip, Operand(mask_scratch)); |
| 3368 str(ip, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 3369 |
| 3370 and_(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); |
| 3371 ldr(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); |
| 3372 add(ip, ip, Operand(length)); |
| 3373 str(ip, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); |
| 3374 |
| 3375 bind(&done); |
| 3376 } |
| 3377 |
| 3378 |
| 3286 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { | 3379 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { |
| 3287 Usat(output_reg, 8, Operand(input_reg)); | 3380 Usat(output_reg, 8, Operand(input_reg)); |
| 3288 } | 3381 } |
| 3289 | 3382 |
| 3290 | 3383 |
| 3291 void MacroAssembler::ClampDoubleToUint8(Register result_reg, | 3384 void MacroAssembler::ClampDoubleToUint8(Register result_reg, |
| 3292 DoubleRegister input_reg, | 3385 DoubleRegister input_reg, |
| 3293 DoubleRegister temp_double_reg) { | 3386 DoubleRegister temp_double_reg) { |
| 3294 Label above_zero; | 3387 Label above_zero; |
| 3295 Label done; | 3388 Label done; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3378 void CodePatcher::EmitCondition(Condition cond) { | 3471 void CodePatcher::EmitCondition(Condition cond) { |
| 3379 Instr instr = Assembler::instr_at(masm_.pc_); | 3472 Instr instr = Assembler::instr_at(masm_.pc_); |
| 3380 instr = (instr & ~kCondMask) | cond; | 3473 instr = (instr & ~kCondMask) | cond; |
| 3381 masm_.emit(instr); | 3474 masm_.emit(instr); |
| 3382 } | 3475 } |
| 3383 | 3476 |
| 3384 | 3477 |
| 3385 } } // namespace v8::internal | 3478 } } // namespace v8::internal |
| 3386 | 3479 |
| 3387 #endif // V8_TARGET_ARCH_ARM | 3480 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |