| 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 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 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 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 Register map) { | 694 Register map) { |
| 695 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | 695 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); |
| 696 CmpInstanceType(map, type); | 696 CmpInstanceType(map, type); |
| 697 } | 697 } |
| 698 | 698 |
| 699 | 699 |
| 700 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { | 700 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { |
| 701 cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type)); | 701 cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type)); |
| 702 } | 702 } |
| 703 | 703 |
| 704 | |
| 705 void MacroAssembler::CheckFastElements(Register map, | |
| 706 Label* fail, | |
| 707 Label::Distance distance) { | |
| 708 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
| 709 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
| 710 STATIC_ASSERT(FAST_ELEMENTS == 2); | |
| 711 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
| 712 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
| 713 Immediate(Map::kMaximumBitField2FastHoleyElementValue)); | |
| 714 j(above, fail, distance); | |
| 715 } | |
| 716 | |
| 717 | |
| 718 void MacroAssembler::CheckFastObjectElements(Register map, | 704 void MacroAssembler::CheckFastObjectElements(Register map, |
| 719 Label* fail, | 705 Label* fail, |
| 720 Label::Distance distance) { | 706 Label::Distance distance) { |
| 721 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | 707 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); |
| 722 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | 708 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
| 723 STATIC_ASSERT(FAST_ELEMENTS == 2); | 709 STATIC_ASSERT(FAST_ELEMENTS == 2); |
| 724 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | 710 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); |
| 725 cmpb(FieldOperand(map, Map::kBitField2Offset), | 711 cmpb(FieldOperand(map, Map::kBitField2Offset), |
| 726 Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); | 712 Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); |
| 727 j(below_equal, fail, distance); | 713 j(below_equal, fail, distance); |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1348 xor_(r0, scratch); | 1334 xor_(r0, scratch); |
| 1349 // hash = hash * 2057; | 1335 // hash = hash * 2057; |
| 1350 imul(r0, r0, 2057); | 1336 imul(r0, r0, 2057); |
| 1351 // hash = hash ^ (hash >> 16); | 1337 // hash = hash ^ (hash >> 16); |
| 1352 mov(scratch, r0); | 1338 mov(scratch, r0); |
| 1353 shr(scratch, 16); | 1339 shr(scratch, 16); |
| 1354 xor_(r0, scratch); | 1340 xor_(r0, scratch); |
| 1355 and_(r0, 0x3fffffff); | 1341 and_(r0, 0x3fffffff); |
| 1356 } | 1342 } |
| 1357 | 1343 |
| 1358 | |
| 1359 | |
| 1360 void MacroAssembler::LoadFromNumberDictionary(Label* miss, | |
| 1361 Register elements, | |
| 1362 Register key, | |
| 1363 Register r0, | |
| 1364 Register r1, | |
| 1365 Register r2, | |
| 1366 Register result) { | |
| 1367 // Register use: | |
| 1368 // | |
| 1369 // elements - holds the slow-case elements of the receiver and is unchanged. | |
| 1370 // | |
| 1371 // key - holds the smi key on entry and is unchanged. | |
| 1372 // | |
| 1373 // Scratch registers: | |
| 1374 // | |
| 1375 // r0 - holds the untagged key on entry and holds the hash once computed. | |
| 1376 // | |
| 1377 // r1 - used to hold the capacity mask of the dictionary | |
| 1378 // | |
| 1379 // r2 - used for the index into the dictionary. | |
| 1380 // | |
| 1381 // result - holds the result on exit if the load succeeds and we fall through. | |
| 1382 | |
| 1383 Label done; | |
| 1384 | |
| 1385 GetNumberHash(r0, r1); | |
| 1386 | |
| 1387 // Compute capacity mask. | |
| 1388 mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset)); | |
| 1389 shr(r1, kSmiTagSize); // convert smi to int | |
| 1390 dec(r1); | |
| 1391 | |
| 1392 // Generate an unrolled loop that performs a few probes before giving up. | |
| 1393 for (int i = 0; i < kNumberDictionaryProbes; i++) { | |
| 1394 // Use r2 for index calculations and keep the hash intact in r0. | |
| 1395 mov(r2, r0); | |
| 1396 // Compute the masked index: (hash + i + i * i) & mask. | |
| 1397 if (i > 0) { | |
| 1398 add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); | |
| 1399 } | |
| 1400 and_(r2, r1); | |
| 1401 | |
| 1402 // Scale the index by multiplying by the entry size. | |
| 1403 DCHECK(SeededNumberDictionary::kEntrySize == 3); | |
| 1404 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 | |
| 1405 | |
| 1406 // Check if the key matches. | |
| 1407 cmp(key, FieldOperand(elements, | |
| 1408 r2, | |
| 1409 times_pointer_size, | |
| 1410 SeededNumberDictionary::kElementsStartOffset)); | |
| 1411 if (i != (kNumberDictionaryProbes - 1)) { | |
| 1412 j(equal, &done); | |
| 1413 } else { | |
| 1414 j(not_equal, miss); | |
| 1415 } | |
| 1416 } | |
| 1417 | |
| 1418 bind(&done); | |
| 1419 // Check that the value is a field property. | |
| 1420 const int kDetailsOffset = | |
| 1421 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; | |
| 1422 DCHECK_EQ(DATA, 0); | |
| 1423 test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), | |
| 1424 Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); | |
| 1425 j(not_zero, miss); | |
| 1426 | |
| 1427 // Get the value at the masked, scaled index. | |
| 1428 const int kValueOffset = | |
| 1429 SeededNumberDictionary::kElementsStartOffset + kPointerSize; | |
| 1430 mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | |
| 1431 } | |
| 1432 | |
| 1433 | |
| 1434 void MacroAssembler::LoadAllocationTopHelper(Register result, | 1344 void MacroAssembler::LoadAllocationTopHelper(Register result, |
| 1435 Register scratch, | 1345 Register scratch, |
| 1436 AllocationFlags flags) { | 1346 AllocationFlags flags) { |
| 1437 ExternalReference allocation_top = | 1347 ExternalReference allocation_top = |
| 1438 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 1348 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 1439 | 1349 |
| 1440 // Just return if allocation top is already known. | 1350 // Just return if allocation top is already known. |
| 1441 if ((flags & RESULT_CONTAINS_TOP) != 0) { | 1351 if ((flags & RESULT_CONTAINS_TOP) != 0) { |
| 1442 // No use of scratch if allocation top is provided. | 1352 // No use of scratch if allocation top is provided. |
| 1443 DCHECK(scratch.is(no_reg)); | 1353 DCHECK(scratch.is(no_reg)); |
| (...skipping 1860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3304 mov(eax, dividend); | 3214 mov(eax, dividend); |
| 3305 shr(eax, 31); | 3215 shr(eax, 31); |
| 3306 add(edx, eax); | 3216 add(edx, eax); |
| 3307 } | 3217 } |
| 3308 | 3218 |
| 3309 | 3219 |
| 3310 } // namespace internal | 3220 } // namespace internal |
| 3311 } // namespace v8 | 3221 } // namespace v8 |
| 3312 | 3222 |
| 3313 #endif // V8_TARGET_ARCH_X87 | 3223 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |