| 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 |