OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 4218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4229 Ldrb(scratch1, FieldMemOperand(current, Map::kBitField2Offset)); | 4229 Ldrb(scratch1, FieldMemOperand(current, Map::kBitField2Offset)); |
4230 DecodeField<Map::ElementsKindBits>(scratch1); | 4230 DecodeField<Map::ElementsKindBits>(scratch1); |
4231 CompareAndBranch(scratch1, DICTIONARY_ELEMENTS, eq, found); | 4231 CompareAndBranch(scratch1, DICTIONARY_ELEMENTS, eq, found); |
4232 Ldr(current, FieldMemOperand(current, Map::kPrototypeOffset)); | 4232 Ldr(current, FieldMemOperand(current, Map::kPrototypeOffset)); |
4233 CompareAndBranch(current, Heap::kNullValueRootIndex, ne, &loop_again); | 4233 CompareAndBranch(current, Heap::kNullValueRootIndex, ne, &loop_again); |
4234 | 4234 |
4235 Bind(&end); | 4235 Bind(&end); |
4236 } | 4236 } |
4237 | 4237 |
4238 | 4238 |
4239 void MacroAssembler::EnsureNotWhite( | 4239 void MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch, |
4240 Register value, | 4240 Register shift_scratch, Register load_scratch, |
4241 Register bitmap_scratch, | 4241 Register length_scratch, |
4242 Register shift_scratch, | 4242 Label* value_is_white) { |
4243 Register load_scratch, | |
4244 Register length_scratch, | |
4245 Label* value_is_white_and_not_data) { | |
4246 DCHECK(!AreAliased( | 4243 DCHECK(!AreAliased( |
4247 value, bitmap_scratch, shift_scratch, load_scratch, length_scratch)); | 4244 value, bitmap_scratch, shift_scratch, load_scratch, length_scratch)); |
4248 | 4245 |
4249 // These bit sequences are backwards. The first character in the string | 4246 // These bit sequences are backwards. The first character in the string |
4250 // represents the least significant bit. | 4247 // represents the least significant bit. |
4251 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 4248 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
4252 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); | 4249 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
4253 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); | 4250 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); |
4254 | 4251 |
4255 GetMarkBits(value, bitmap_scratch, shift_scratch); | 4252 GetMarkBits(value, bitmap_scratch, shift_scratch); |
4256 Ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 4253 Ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
4257 Lsr(load_scratch, load_scratch, shift_scratch); | 4254 Lsr(load_scratch, load_scratch, shift_scratch); |
4258 | 4255 |
4259 AssertHasValidColor(load_scratch); | 4256 AssertHasValidColor(load_scratch); |
4260 | 4257 |
4261 // If the value is black or grey we don't need to do anything. | 4258 // If the value is black or grey we don't need to do anything. |
4262 // Since both black and grey have a 1 in the first position and white does | 4259 // Since both black and grey have a 1 in the first position and white does |
4263 // not have a 1 there we only need to check one bit. | 4260 // not have a 1 there we only need to check one bit. |
4264 Label done; | 4261 Tbz(load_scratch, 0, value_is_white); |
4265 Tbnz(load_scratch, 0, &done); | |
4266 | |
4267 // Value is white. We check whether it is data that doesn't need scanning. | |
4268 Register map = load_scratch; // Holds map while checking type. | |
4269 Label is_data_object; | |
4270 | |
4271 // Check for heap-number. | |
4272 Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); | |
4273 Mov(length_scratch, HeapNumber::kSize); | |
4274 JumpIfRoot(map, Heap::kHeapNumberMapRootIndex, &is_data_object); | |
4275 | |
4276 // Check for strings. | |
4277 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | |
4278 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | |
4279 // If it's a string and it's not a cons string then it's an object containing | |
4280 // no GC pointers. | |
4281 Register instance_type = load_scratch; | |
4282 Ldrb(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); | |
4283 TestAndBranchIfAnySet(instance_type, | |
4284 kIsIndirectStringMask | kIsNotStringMask, | |
4285 value_is_white_and_not_data); | |
4286 | |
4287 // It's a non-indirect (non-cons and non-slice) string. | |
4288 // If it's external, the length is just ExternalString::kSize. | |
4289 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). | |
4290 // External strings are the only ones with the kExternalStringTag bit | |
4291 // set. | |
4292 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); | |
4293 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); | |
4294 Mov(length_scratch, ExternalString::kSize); | |
4295 TestAndBranchIfAnySet(instance_type, kExternalStringTag, &is_data_object); | |
4296 | |
4297 // Sequential string, either Latin1 or UC16. | |
4298 // For Latin1 (char-size of 1) we shift the smi tag away to get the length. | |
4299 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby | |
4300 // getting the length multiplied by 2. | |
4301 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4); | |
4302 Ldrsw(length_scratch, UntagSmiFieldMemOperand(value, | |
4303 String::kLengthOffset)); | |
4304 Tst(instance_type, kStringEncodingMask); | |
4305 Cset(load_scratch, eq); | |
4306 Lsl(length_scratch, length_scratch, load_scratch); | |
4307 Add(length_scratch, | |
4308 length_scratch, | |
4309 SeqString::kHeaderSize + kObjectAlignmentMask); | |
4310 Bic(length_scratch, length_scratch, kObjectAlignmentMask); | |
4311 | |
4312 Bind(&is_data_object); | |
4313 // Value is a data object, and it is white. Mark it black. Since we know | |
4314 // that the object is white we can make it black by flipping one bit. | |
4315 Register mask = shift_scratch; | |
4316 Mov(load_scratch, 1); | |
4317 Lsl(mask, load_scratch, shift_scratch); | |
4318 | |
4319 Ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | |
4320 Orr(load_scratch, load_scratch, mask); | |
4321 Str(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | |
4322 | |
4323 Bic(bitmap_scratch, bitmap_scratch, Page::kPageAlignmentMask); | |
4324 Ldr(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | |
4325 Add(load_scratch, load_scratch, length_scratch); | |
4326 Str(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | |
4327 | |
4328 Bind(&done); | |
4329 } | 4262 } |
4330 | 4263 |
4331 | 4264 |
4332 void MacroAssembler::Assert(Condition cond, BailoutReason reason) { | 4265 void MacroAssembler::Assert(Condition cond, BailoutReason reason) { |
4333 if (emit_debug_code()) { | 4266 if (emit_debug_code()) { |
4334 Check(cond, reason); | 4267 Check(cond, reason); |
4335 } | 4268 } |
4336 } | 4269 } |
4337 | 4270 |
4338 | 4271 |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4926 } | 4859 } |
4927 | 4860 |
4928 | 4861 |
4929 #undef __ | 4862 #undef __ |
4930 | 4863 |
4931 | 4864 |
4932 } // namespace internal | 4865 } // namespace internal |
4933 } // namespace v8 | 4866 } // namespace v8 |
4934 | 4867 |
4935 #endif // V8_TARGET_ARCH_ARM64 | 4868 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |