OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 | 488 |
489 | 489 |
490 void MacroAssembler::Abort(const char* msg) { | 490 void MacroAssembler::Abort(const char* msg) { |
491 // We want to pass the msg string like a smi to avoid GC | 491 // We want to pass the msg string like a smi to avoid GC |
492 // problems, however msg is not guaranteed to be aligned | 492 // problems, however msg is not guaranteed to be aligned |
493 // properly. Instead, we pass an aligned pointer that is | 493 // properly. Instead, we pass an aligned pointer that is |
494 // a proper v8 smi, but also pass the alignment difference | 494 // a proper v8 smi, but also pass the alignment difference |
495 // from the real pointer as a smi. | 495 // from the real pointer as a smi. |
496 intptr_t p1 = reinterpret_cast<intptr_t>(msg); | 496 intptr_t p1 = reinterpret_cast<intptr_t>(msg); |
497 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; | 497 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; |
498 // Note: p0 might not be a valid Smi *value*, but it has a valid Smi tag. | 498 // Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag. |
499 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); | 499 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); |
500 #ifdef DEBUG | 500 #ifdef DEBUG |
501 if (msg != NULL) { | 501 if (msg != NULL) { |
502 RecordComment("Abort message: "); | 502 RecordComment("Abort message: "); |
503 RecordComment(msg); | 503 RecordComment(msg); |
504 } | 504 } |
505 #endif | 505 #endif |
506 push(rax); | 506 push(rax); |
507 movq(kScratchRegister, p0, RelocInfo::NONE); | 507 movq(kScratchRegister, p0, RelocInfo::NONE); |
508 push(kScratchRegister); | 508 push(kScratchRegister); |
(...skipping 2223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2732 // Value is a smi. convert to a double and store. | 2732 // Value is a smi. convert to a double and store. |
2733 // Preserve original value. | 2733 // Preserve original value. |
2734 SmiToInteger32(kScratchRegister, maybe_number); | 2734 SmiToInteger32(kScratchRegister, maybe_number); |
2735 cvtlsi2sd(xmm_scratch, kScratchRegister); | 2735 cvtlsi2sd(xmm_scratch, kScratchRegister); |
2736 movsd(FieldOperand(elements, index, times_8, FixedDoubleArray::kHeaderSize), | 2736 movsd(FieldOperand(elements, index, times_8, FixedDoubleArray::kHeaderSize), |
2737 xmm_scratch); | 2737 xmm_scratch); |
2738 bind(&done); | 2738 bind(&done); |
2739 } | 2739 } |
2740 | 2740 |
2741 | 2741 |
| 2742 void MacroAssembler::CompareMap(Register obj, |
| 2743 Handle<Map> map, |
| 2744 Label* early_success, |
| 2745 CompareMapMode mode) { |
| 2746 Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); |
| 2747 if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { |
| 2748 Map* transitioned_fast_element_map( |
| 2749 map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL)); |
| 2750 ASSERT(transitioned_fast_element_map == NULL || |
| 2751 map->elements_kind() != FAST_ELEMENTS); |
| 2752 if (transitioned_fast_element_map != NULL) { |
| 2753 j(equal, early_success, Label::kNear); |
| 2754 Cmp(FieldOperand(obj, HeapObject::kMapOffset), |
| 2755 Handle<Map>(transitioned_fast_element_map)); |
| 2756 } |
| 2757 |
| 2758 Map* transitioned_double_map( |
| 2759 map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL)); |
| 2760 ASSERT(transitioned_double_map == NULL || |
| 2761 map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); |
| 2762 if (transitioned_double_map != NULL) { |
| 2763 j(equal, early_success, Label::kNear); |
| 2764 Cmp(FieldOperand(obj, HeapObject::kMapOffset), |
| 2765 Handle<Map>(transitioned_double_map)); |
| 2766 } |
| 2767 } |
| 2768 } |
| 2769 |
| 2770 |
2742 void MacroAssembler::CheckMap(Register obj, | 2771 void MacroAssembler::CheckMap(Register obj, |
2743 Handle<Map> map, | 2772 Handle<Map> map, |
2744 Label* fail, | 2773 Label* fail, |
2745 SmiCheckType smi_check_type) { | 2774 SmiCheckType smi_check_type, |
| 2775 CompareMapMode mode) { |
2746 if (smi_check_type == DO_SMI_CHECK) { | 2776 if (smi_check_type == DO_SMI_CHECK) { |
2747 JumpIfSmi(obj, fail); | 2777 JumpIfSmi(obj, fail); |
2748 } | 2778 } |
2749 Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); | 2779 |
| 2780 Label success; |
| 2781 CompareMap(obj, map, &success, mode); |
2750 j(not_equal, fail); | 2782 j(not_equal, fail); |
| 2783 bind(&success); |
2751 } | 2784 } |
2752 | 2785 |
2753 | 2786 |
2754 void MacroAssembler::ClampUint8(Register reg) { | 2787 void MacroAssembler::ClampUint8(Register reg) { |
2755 Label done; | 2788 Label done; |
2756 testl(reg, Immediate(0xFFFFFF00)); | 2789 testl(reg, Immediate(0xFFFFFF00)); |
2757 j(zero, &done, Label::kNear); | 2790 j(zero, &done, Label::kNear); |
2758 setcc(negative, reg); // 1 if negative, 0 if positive. | 2791 setcc(negative, reg); // 1 if negative, 0 if positive. |
2759 decb(reg); // 0 if negative, 255 if positive. | 2792 decb(reg); // 0 if negative, 255 if positive. |
2760 bind(&done); | 2793 bind(&done); |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3191 Move(kScratchRegister, Smi::FromInt(type)); | 3224 Move(kScratchRegister, Smi::FromInt(type)); |
3192 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); | 3225 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); |
3193 Check(equal, "stack frame types must match"); | 3226 Check(equal, "stack frame types must match"); |
3194 } | 3227 } |
3195 movq(rsp, rbp); | 3228 movq(rsp, rbp); |
3196 pop(rbp); | 3229 pop(rbp); |
3197 } | 3230 } |
3198 | 3231 |
3199 | 3232 |
3200 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { | 3233 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { |
3201 // Setup the frame structure on the stack. | 3234 // Set up the frame structure on the stack. |
3202 // All constants are relative to the frame pointer of the exit frame. | 3235 // All constants are relative to the frame pointer of the exit frame. |
3203 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); | 3236 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |
3204 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); | 3237 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); |
3205 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); | 3238 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); |
3206 push(rbp); | 3239 push(rbp); |
3207 movq(rbp, rsp); | 3240 movq(rbp, rsp); |
3208 | 3241 |
3209 // Reserve room for entry stack pointer and push the code object. | 3242 // Reserve room for entry stack pointer and push the code object. |
3210 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 3243 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
3211 push(Immediate(0)); // Saved entry sp, patched before call. | 3244 push(Immediate(0)); // Saved entry sp, patched before call. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3251 } | 3284 } |
3252 | 3285 |
3253 // Patch the saved entry sp. | 3286 // Patch the saved entry sp. |
3254 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); | 3287 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); |
3255 } | 3288 } |
3256 | 3289 |
3257 | 3290 |
3258 void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { | 3291 void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { |
3259 EnterExitFramePrologue(true); | 3292 EnterExitFramePrologue(true); |
3260 | 3293 |
3261 // Setup argv in callee-saved register r15. It is reused in LeaveExitFrame, | 3294 // Set up argv in callee-saved register r15. It is reused in LeaveExitFrame, |
3262 // so it must be retained across the C-call. | 3295 // so it must be retained across the C-call. |
3263 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; | 3296 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
3264 lea(r15, Operand(rbp, r14, times_pointer_size, offset)); | 3297 lea(r15, Operand(rbp, r14, times_pointer_size, offset)); |
3265 | 3298 |
3266 EnterExitFrameEpilogue(arg_stack_space, save_doubles); | 3299 EnterExitFrameEpilogue(arg_stack_space, save_doubles); |
3267 } | 3300 } |
3268 | 3301 |
3269 | 3302 |
3270 void MacroAssembler::EnterApiExitFrame(int arg_stack_space) { | 3303 void MacroAssembler::EnterApiExitFrame(int arg_stack_space) { |
3271 EnterExitFramePrologue(false); | 3304 EnterExitFramePrologue(false); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3379 int token_offset = | 3412 int token_offset = |
3380 Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize; | 3413 Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize; |
3381 movq(scratch, FieldOperand(scratch, token_offset)); | 3414 movq(scratch, FieldOperand(scratch, token_offset)); |
3382 cmpq(scratch, FieldOperand(kScratchRegister, token_offset)); | 3415 cmpq(scratch, FieldOperand(kScratchRegister, token_offset)); |
3383 j(not_equal, miss); | 3416 j(not_equal, miss); |
3384 | 3417 |
3385 bind(&same_contexts); | 3418 bind(&same_contexts); |
3386 } | 3419 } |
3387 | 3420 |
3388 | 3421 |
| 3422 void MacroAssembler::GetNumberHash(Register r0, Register scratch) { |
| 3423 // First of all we assign the hash seed to scratch. |
| 3424 LoadRoot(scratch, Heap::kHashSeedRootIndex); |
| 3425 SmiToInteger32(scratch, scratch); |
| 3426 |
| 3427 // Xor original key with a seed. |
| 3428 xorl(r0, scratch); |
| 3429 |
| 3430 // Compute the hash code from the untagged key. This must be kept in sync |
| 3431 // with ComputeIntegerHash in utils.h. |
| 3432 // |
| 3433 // hash = ~hash + (hash << 15); |
| 3434 movl(scratch, r0); |
| 3435 notl(r0); |
| 3436 shll(scratch, Immediate(15)); |
| 3437 addl(r0, scratch); |
| 3438 // hash = hash ^ (hash >> 12); |
| 3439 movl(scratch, r0); |
| 3440 shrl(scratch, Immediate(12)); |
| 3441 xorl(r0, scratch); |
| 3442 // hash = hash + (hash << 2); |
| 3443 leal(r0, Operand(r0, r0, times_4, 0)); |
| 3444 // hash = hash ^ (hash >> 4); |
| 3445 movl(scratch, r0); |
| 3446 shrl(scratch, Immediate(4)); |
| 3447 xorl(r0, scratch); |
| 3448 // hash = hash * 2057; |
| 3449 imull(r0, r0, Immediate(2057)); |
| 3450 // hash = hash ^ (hash >> 16); |
| 3451 movl(scratch, r0); |
| 3452 shrl(scratch, Immediate(16)); |
| 3453 xorl(r0, scratch); |
| 3454 } |
| 3455 |
| 3456 |
| 3457 |
3389 void MacroAssembler::LoadFromNumberDictionary(Label* miss, | 3458 void MacroAssembler::LoadFromNumberDictionary(Label* miss, |
3390 Register elements, | 3459 Register elements, |
3391 Register key, | 3460 Register key, |
3392 Register r0, | 3461 Register r0, |
3393 Register r1, | 3462 Register r1, |
3394 Register r2, | 3463 Register r2, |
3395 Register result) { | 3464 Register result) { |
3396 // Register use: | 3465 // Register use: |
3397 // | 3466 // |
3398 // elements - holds the slow-case elements of the receiver on entry. | 3467 // elements - holds the slow-case elements of the receiver on entry. |
(...skipping 10 matching lines...) Expand all Loading... |
3409 // | 3478 // |
3410 // r2 - used for the index into the dictionary. | 3479 // r2 - used for the index into the dictionary. |
3411 // | 3480 // |
3412 // result - holds the result on exit if the load succeeded. | 3481 // result - holds the result on exit if the load succeeded. |
3413 // Allowed to be the same as 'key' or 'result'. | 3482 // Allowed to be the same as 'key' or 'result'. |
3414 // Unchanged on bailout so 'key' or 'result' can be used | 3483 // Unchanged on bailout so 'key' or 'result' can be used |
3415 // in further computation. | 3484 // in further computation. |
3416 | 3485 |
3417 Label done; | 3486 Label done; |
3418 | 3487 |
3419 // Compute the hash code from the untagged key. This must be kept in sync | 3488 GetNumberHash(r0, r1); |
3420 // with ComputeIntegerHash in utils.h. | |
3421 // | |
3422 // hash = ~hash + (hash << 15); | |
3423 movl(r1, r0); | |
3424 notl(r0); | |
3425 shll(r1, Immediate(15)); | |
3426 addl(r0, r1); | |
3427 // hash = hash ^ (hash >> 12); | |
3428 movl(r1, r0); | |
3429 shrl(r1, Immediate(12)); | |
3430 xorl(r0, r1); | |
3431 // hash = hash + (hash << 2); | |
3432 leal(r0, Operand(r0, r0, times_4, 0)); | |
3433 // hash = hash ^ (hash >> 4); | |
3434 movl(r1, r0); | |
3435 shrl(r1, Immediate(4)); | |
3436 xorl(r0, r1); | |
3437 // hash = hash * 2057; | |
3438 imull(r0, r0, Immediate(2057)); | |
3439 // hash = hash ^ (hash >> 16); | |
3440 movl(r1, r0); | |
3441 shrl(r1, Immediate(16)); | |
3442 xorl(r0, r1); | |
3443 | 3489 |
3444 // Compute capacity mask. | 3490 // Compute capacity mask. |
3445 SmiToInteger32(r1, | 3491 SmiToInteger32(r1, FieldOperand(elements, |
3446 FieldOperand(elements, NumberDictionary::kCapacityOffset)); | 3492 SeededNumberDictionary::kCapacityOffset)); |
3447 decl(r1); | 3493 decl(r1); |
3448 | 3494 |
3449 // Generate an unrolled loop that performs a few probes before giving up. | 3495 // Generate an unrolled loop that performs a few probes before giving up. |
3450 const int kProbes = 4; | 3496 const int kProbes = 4; |
3451 for (int i = 0; i < kProbes; i++) { | 3497 for (int i = 0; i < kProbes; i++) { |
3452 // Use r2 for index calculations and keep the hash intact in r0. | 3498 // Use r2 for index calculations and keep the hash intact in r0. |
3453 movq(r2, r0); | 3499 movq(r2, r0); |
3454 // Compute the masked index: (hash + i + i * i) & mask. | 3500 // Compute the masked index: (hash + i + i * i) & mask. |
3455 if (i > 0) { | 3501 if (i > 0) { |
3456 addl(r2, Immediate(NumberDictionary::GetProbeOffset(i))); | 3502 addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); |
3457 } | 3503 } |
3458 and_(r2, r1); | 3504 and_(r2, r1); |
3459 | 3505 |
3460 // Scale the index by multiplying by the entry size. | 3506 // Scale the index by multiplying by the entry size. |
3461 ASSERT(NumberDictionary::kEntrySize == 3); | 3507 ASSERT(SeededNumberDictionary::kEntrySize == 3); |
3462 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 | 3508 lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 |
3463 | 3509 |
3464 // Check if the key matches. | 3510 // Check if the key matches. |
3465 cmpq(key, FieldOperand(elements, | 3511 cmpq(key, FieldOperand(elements, |
3466 r2, | 3512 r2, |
3467 times_pointer_size, | 3513 times_pointer_size, |
3468 NumberDictionary::kElementsStartOffset)); | 3514 SeededNumberDictionary::kElementsStartOffset)); |
3469 if (i != (kProbes - 1)) { | 3515 if (i != (kProbes - 1)) { |
3470 j(equal, &done); | 3516 j(equal, &done); |
3471 } else { | 3517 } else { |
3472 j(not_equal, miss); | 3518 j(not_equal, miss); |
3473 } | 3519 } |
3474 } | 3520 } |
3475 | 3521 |
3476 bind(&done); | 3522 bind(&done); |
3477 // Check that the value is a normal propety. | 3523 // Check that the value is a normal propety. |
3478 const int kDetailsOffset = | 3524 const int kDetailsOffset = |
3479 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; | 3525 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
3480 ASSERT_EQ(NORMAL, 0); | 3526 ASSERT_EQ(NORMAL, 0); |
3481 Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), | 3527 Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), |
3482 Smi::FromInt(PropertyDetails::TypeField::kMask)); | 3528 Smi::FromInt(PropertyDetails::TypeField::kMask)); |
3483 j(not_zero, miss); | 3529 j(not_zero, miss); |
3484 | 3530 |
3485 // Get the value at the masked, scaled index. | 3531 // Get the value at the masked, scaled index. |
3486 const int kValueOffset = | 3532 const int kValueOffset = |
3487 NumberDictionary::kElementsStartOffset + kPointerSize; | 3533 SeededNumberDictionary::kElementsStartOffset + kPointerSize; |
3488 movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | 3534 movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); |
3489 } | 3535 } |
3490 | 3536 |
3491 | 3537 |
3492 void MacroAssembler::LoadAllocationTopHelper(Register result, | 3538 void MacroAssembler::LoadAllocationTopHelper(Register result, |
3493 Register scratch, | 3539 Register scratch, |
3494 AllocationFlags flags) { | 3540 AllocationFlags flags) { |
3495 ExternalReference new_space_allocation_top = | 3541 ExternalReference new_space_allocation_top = |
3496 ExternalReference::new_space_allocation_top_address(isolate()); | 3542 ExternalReference::new_space_allocation_top_address(isolate()); |
3497 | 3543 |
(...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4279 | 4325 |
4280 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); | 4326 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); |
4281 addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length); | 4327 addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length); |
4282 | 4328 |
4283 bind(&done); | 4329 bind(&done); |
4284 } | 4330 } |
4285 | 4331 |
4286 } } // namespace v8::internal | 4332 } } // namespace v8::internal |
4287 | 4333 |
4288 #endif // V8_TARGET_ARCH_X64 | 4334 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |