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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 __ j(not_zero, label); | 1439 __ j(not_zero, label); |
1440 } | 1440 } |
1441 | 1441 |
1442 | 1442 |
1443 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 1443 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
1444 Label check_unequal_objects, done; | 1444 Label check_unequal_objects, done; |
1445 Condition cc = GetCondition(); | 1445 Condition cc = GetCondition(); |
1446 Factory* factory = isolate()->factory(); | 1446 Factory* factory = isolate()->factory(); |
1447 | 1447 |
1448 Label miss; | 1448 Label miss; |
1449 CheckInputType(masm, rdx, left_, &miss); | 1449 CheckInputType(masm, rdx, left(), &miss); |
1450 CheckInputType(masm, rax, right_, &miss); | 1450 CheckInputType(masm, rax, right(), &miss); |
1451 | 1451 |
1452 // Compare two smis. | 1452 // Compare two smis. |
1453 Label non_smi, smi_done; | 1453 Label non_smi, smi_done; |
1454 __ JumpIfNotBothSmi(rax, rdx, &non_smi); | 1454 __ JumpIfNotBothSmi(rax, rdx, &non_smi); |
1455 __ subp(rdx, rax); | 1455 __ subp(rdx, rax); |
1456 __ j(no_overflow, &smi_done); | 1456 __ j(no_overflow, &smi_done); |
1457 __ notp(rdx); // Correct sign in case of overflow. rdx cannot be 0 here. | 1457 __ notp(rdx); // Correct sign in case of overflow. rdx cannot be 0 here. |
1458 __ bind(&smi_done); | 1458 __ bind(&smi_done); |
1459 __ movp(rax, rdx); | 1459 __ movp(rax, rdx); |
1460 __ ret(0); | 1460 __ ret(0); |
(...skipping 1890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3351 } | 3351 } |
3352 | 3352 |
3353 // Tail call into the stub that handles binary operations with allocation | 3353 // Tail call into the stub that handles binary operations with allocation |
3354 // sites. | 3354 // sites. |
3355 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3355 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3356 __ TailCallStub(&stub); | 3356 __ TailCallStub(&stub); |
3357 } | 3357 } |
3358 | 3358 |
3359 | 3359 |
3360 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3360 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
3361 DCHECK(state_ == CompareIC::SMI); | 3361 DCHECK(state() == CompareIC::SMI); |
3362 Label miss; | 3362 Label miss; |
3363 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); | 3363 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); |
3364 | 3364 |
3365 if (GetCondition() == equal) { | 3365 if (GetCondition() == equal) { |
3366 // For equality we do not care about the sign of the result. | 3366 // For equality we do not care about the sign of the result. |
3367 __ subp(rax, rdx); | 3367 __ subp(rax, rdx); |
3368 } else { | 3368 } else { |
3369 Label done; | 3369 Label done; |
3370 __ subp(rdx, rax); | 3370 __ subp(rdx, rax); |
3371 __ j(no_overflow, &done, Label::kNear); | 3371 __ j(no_overflow, &done, Label::kNear); |
3372 // Correct sign of result in case of overflow. | 3372 // Correct sign of result in case of overflow. |
3373 __ notp(rdx); | 3373 __ notp(rdx); |
3374 __ bind(&done); | 3374 __ bind(&done); |
3375 __ movp(rax, rdx); | 3375 __ movp(rax, rdx); |
3376 } | 3376 } |
3377 __ ret(0); | 3377 __ ret(0); |
3378 | 3378 |
3379 __ bind(&miss); | 3379 __ bind(&miss); |
3380 GenerateMiss(masm); | 3380 GenerateMiss(masm); |
3381 } | 3381 } |
3382 | 3382 |
3383 | 3383 |
3384 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3384 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { |
3385 DCHECK(state_ == CompareIC::NUMBER); | 3385 DCHECK(state() == CompareIC::NUMBER); |
3386 | 3386 |
3387 Label generic_stub; | 3387 Label generic_stub; |
3388 Label unordered, maybe_undefined1, maybe_undefined2; | 3388 Label unordered, maybe_undefined1, maybe_undefined2; |
3389 Label miss; | 3389 Label miss; |
3390 | 3390 |
3391 if (left_ == CompareIC::SMI) { | 3391 if (left() == CompareIC::SMI) { |
3392 __ JumpIfNotSmi(rdx, &miss); | 3392 __ JumpIfNotSmi(rdx, &miss); |
3393 } | 3393 } |
3394 if (right_ == CompareIC::SMI) { | 3394 if (right() == CompareIC::SMI) { |
3395 __ JumpIfNotSmi(rax, &miss); | 3395 __ JumpIfNotSmi(rax, &miss); |
3396 } | 3396 } |
3397 | 3397 |
3398 // Load left and right operand. | 3398 // Load left and right operand. |
3399 Label done, left, left_smi, right_smi; | 3399 Label done, left, left_smi, right_smi; |
3400 __ JumpIfSmi(rax, &right_smi, Label::kNear); | 3400 __ JumpIfSmi(rax, &right_smi, Label::kNear); |
3401 __ CompareMap(rax, isolate()->factory()->heap_number_map()); | 3401 __ CompareMap(rax, isolate()->factory()->heap_number_map()); |
3402 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3402 __ j(not_equal, &maybe_undefined1, Label::kNear); |
3403 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); | 3403 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); |
3404 __ jmp(&left, Label::kNear); | 3404 __ jmp(&left, Label::kNear); |
(...skipping 21 matching lines...) Expand all Loading... |
3426 // Return a result of -1, 0, or 1, based on EFLAGS. | 3426 // Return a result of -1, 0, or 1, based on EFLAGS. |
3427 // Performing mov, because xor would destroy the flag register. | 3427 // Performing mov, because xor would destroy the flag register. |
3428 __ movl(rax, Immediate(0)); | 3428 __ movl(rax, Immediate(0)); |
3429 __ movl(rcx, Immediate(0)); | 3429 __ movl(rcx, Immediate(0)); |
3430 __ setcc(above, rax); // Add one to zero if carry clear and not equal. | 3430 __ setcc(above, rax); // Add one to zero if carry clear and not equal. |
3431 __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). | 3431 __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). |
3432 __ ret(0); | 3432 __ ret(0); |
3433 | 3433 |
3434 __ bind(&unordered); | 3434 __ bind(&unordered); |
3435 __ bind(&generic_stub); | 3435 __ bind(&generic_stub); |
3436 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, | 3436 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
3437 CompareIC::GENERIC); | 3437 CompareIC::GENERIC); |
3438 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3438 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3439 | 3439 |
3440 __ bind(&maybe_undefined1); | 3440 __ bind(&maybe_undefined1); |
3441 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3441 if (Token::IsOrderedRelationalCompareOp(op())) { |
3442 __ Cmp(rax, isolate()->factory()->undefined_value()); | 3442 __ Cmp(rax, isolate()->factory()->undefined_value()); |
3443 __ j(not_equal, &miss); | 3443 __ j(not_equal, &miss); |
3444 __ JumpIfSmi(rdx, &unordered); | 3444 __ JumpIfSmi(rdx, &unordered); |
3445 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); | 3445 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); |
3446 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3446 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3447 __ jmp(&unordered); | 3447 __ jmp(&unordered); |
3448 } | 3448 } |
3449 | 3449 |
3450 __ bind(&maybe_undefined2); | 3450 __ bind(&maybe_undefined2); |
3451 if (Token::IsOrderedRelationalCompareOp(op_)) { | 3451 if (Token::IsOrderedRelationalCompareOp(op())) { |
3452 __ Cmp(rdx, isolate()->factory()->undefined_value()); | 3452 __ Cmp(rdx, isolate()->factory()->undefined_value()); |
3453 __ j(equal, &unordered); | 3453 __ j(equal, &unordered); |
3454 } | 3454 } |
3455 | 3455 |
3456 __ bind(&miss); | 3456 __ bind(&miss); |
3457 GenerateMiss(masm); | 3457 GenerateMiss(masm); |
3458 } | 3458 } |
3459 | 3459 |
3460 | 3460 |
3461 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3461 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3462 DCHECK(state_ == CompareIC::INTERNALIZED_STRING); | 3462 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
3463 DCHECK(GetCondition() == equal); | 3463 DCHECK(GetCondition() == equal); |
3464 | 3464 |
3465 // Registers containing left and right operands respectively. | 3465 // Registers containing left and right operands respectively. |
3466 Register left = rdx; | 3466 Register left = rdx; |
3467 Register right = rax; | 3467 Register right = rax; |
3468 Register tmp1 = rcx; | 3468 Register tmp1 = rcx; |
3469 Register tmp2 = rbx; | 3469 Register tmp2 = rbx; |
3470 | 3470 |
3471 // Check that both operands are heap objects. | 3471 // Check that both operands are heap objects. |
3472 Label miss; | 3472 Label miss; |
(...skipping 22 matching lines...) Expand all Loading... |
3495 __ Move(rax, Smi::FromInt(EQUAL)); | 3495 __ Move(rax, Smi::FromInt(EQUAL)); |
3496 __ bind(&done); | 3496 __ bind(&done); |
3497 __ ret(0); | 3497 __ ret(0); |
3498 | 3498 |
3499 __ bind(&miss); | 3499 __ bind(&miss); |
3500 GenerateMiss(masm); | 3500 GenerateMiss(masm); |
3501 } | 3501 } |
3502 | 3502 |
3503 | 3503 |
3504 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3504 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { |
3505 DCHECK(state_ == CompareIC::UNIQUE_NAME); | 3505 DCHECK(state() == CompareIC::UNIQUE_NAME); |
3506 DCHECK(GetCondition() == equal); | 3506 DCHECK(GetCondition() == equal); |
3507 | 3507 |
3508 // Registers containing left and right operands respectively. | 3508 // Registers containing left and right operands respectively. |
3509 Register left = rdx; | 3509 Register left = rdx; |
3510 Register right = rax; | 3510 Register right = rax; |
3511 Register tmp1 = rcx; | 3511 Register tmp1 = rcx; |
3512 Register tmp2 = rbx; | 3512 Register tmp2 = rbx; |
3513 | 3513 |
3514 // Check that both operands are heap objects. | 3514 // Check that both operands are heap objects. |
3515 Label miss; | 3515 Label miss; |
(...skipping 22 matching lines...) Expand all Loading... |
3538 __ Move(rax, Smi::FromInt(EQUAL)); | 3538 __ Move(rax, Smi::FromInt(EQUAL)); |
3539 __ bind(&done); | 3539 __ bind(&done); |
3540 __ ret(0); | 3540 __ ret(0); |
3541 | 3541 |
3542 __ bind(&miss); | 3542 __ bind(&miss); |
3543 GenerateMiss(masm); | 3543 GenerateMiss(masm); |
3544 } | 3544 } |
3545 | 3545 |
3546 | 3546 |
3547 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3547 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { |
3548 DCHECK(state_ == CompareIC::STRING); | 3548 DCHECK(state() == CompareIC::STRING); |
3549 Label miss; | 3549 Label miss; |
3550 | 3550 |
3551 bool equality = Token::IsEqualityOp(op_); | 3551 bool equality = Token::IsEqualityOp(op()); |
3552 | 3552 |
3553 // Registers containing left and right operands respectively. | 3553 // Registers containing left and right operands respectively. |
3554 Register left = rdx; | 3554 Register left = rdx; |
3555 Register right = rax; | 3555 Register right = rax; |
3556 Register tmp1 = rcx; | 3556 Register tmp1 = rcx; |
3557 Register tmp2 = rbx; | 3557 Register tmp2 = rbx; |
3558 Register tmp3 = rdi; | 3558 Register tmp3 = rdi; |
3559 | 3559 |
3560 // Check that both operands are heap objects. | 3560 // Check that both operands are heap objects. |
3561 Condition cond = masm->CheckEitherSmi(left, right, tmp1); | 3561 Condition cond = masm->CheckEitherSmi(left, right, tmp1); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3625 } else { | 3625 } else { |
3626 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3626 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3627 } | 3627 } |
3628 | 3628 |
3629 __ bind(&miss); | 3629 __ bind(&miss); |
3630 GenerateMiss(masm); | 3630 GenerateMiss(masm); |
3631 } | 3631 } |
3632 | 3632 |
3633 | 3633 |
3634 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3634 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { |
3635 DCHECK(state_ == CompareIC::OBJECT); | 3635 DCHECK(state() == CompareIC::OBJECT); |
3636 Label miss; | 3636 Label miss; |
3637 Condition either_smi = masm->CheckEitherSmi(rdx, rax); | 3637 Condition either_smi = masm->CheckEitherSmi(rdx, rax); |
3638 __ j(either_smi, &miss, Label::kNear); | 3638 __ j(either_smi, &miss, Label::kNear); |
3639 | 3639 |
3640 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); | 3640 __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); |
3641 __ j(not_equal, &miss, Label::kNear); | 3641 __ j(not_equal, &miss, Label::kNear); |
3642 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); | 3642 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); |
3643 __ j(not_equal, &miss, Label::kNear); | 3643 __ j(not_equal, &miss, Label::kNear); |
3644 | 3644 |
3645 DCHECK(GetCondition() == equal); | 3645 DCHECK(GetCondition() == equal); |
(...skipping 29 matching lines...) Expand all Loading... |
3675 { | 3675 { |
3676 // Call the runtime system in a fresh internal frame. | 3676 // Call the runtime system in a fresh internal frame. |
3677 ExternalReference miss = | 3677 ExternalReference miss = |
3678 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); | 3678 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); |
3679 | 3679 |
3680 FrameScope scope(masm, StackFrame::INTERNAL); | 3680 FrameScope scope(masm, StackFrame::INTERNAL); |
3681 __ Push(rdx); | 3681 __ Push(rdx); |
3682 __ Push(rax); | 3682 __ Push(rax); |
3683 __ Push(rdx); | 3683 __ Push(rdx); |
3684 __ Push(rax); | 3684 __ Push(rax); |
3685 __ Push(Smi::FromInt(op_)); | 3685 __ Push(Smi::FromInt(op())); |
3686 __ CallExternalReference(miss, 3); | 3686 __ CallExternalReference(miss, 3); |
3687 | 3687 |
3688 // Compute the entry point of the rewritten stub. | 3688 // Compute the entry point of the rewritten stub. |
3689 __ leap(rdi, FieldOperand(rax, Code::kHeaderSize)); | 3689 __ leap(rdi, FieldOperand(rax, Code::kHeaderSize)); |
3690 __ Pop(rax); | 3690 __ Pop(rax); |
3691 __ Pop(rdx); | 3691 __ Pop(rdx); |
3692 } | 3692 } |
3693 | 3693 |
3694 // Do a tail call to the rewritten stub. | 3694 // Do a tail call to the rewritten stub. |
3695 __ jmp(rdi); | 3695 __ jmp(rdi); |
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4748 return_value_operand, | 4748 return_value_operand, |
4749 NULL); | 4749 NULL); |
4750 } | 4750 } |
4751 | 4751 |
4752 | 4752 |
4753 #undef __ | 4753 #undef __ |
4754 | 4754 |
4755 } } // namespace v8::internal | 4755 } } // namespace v8::internal |
4756 | 4756 |
4757 #endif // V8_TARGET_ARCH_X64 | 4757 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |