| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset)); | 571 __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset)); |
| 572 __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset)); | 572 __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset)); |
| 573 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); | 573 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); |
| 574 __ and_(r0, r2, Operand(r3)); | 574 __ and_(r0, r2, Operand(r3)); |
| 575 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); | 575 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); |
| 576 __ eor(r0, r0, Operand(1 << Map::kIsUndetectable)); | 576 __ eor(r0, r0, Operand(1 << Map::kIsUndetectable)); |
| 577 __ Ret(); | 577 __ Ret(); |
| 578 } | 578 } |
| 579 | 579 |
| 580 | 580 |
| 581 static void ICCompareStub_CheckInputType(MacroAssembler* masm, | 581 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, |
| 582 Register input, | |
| 583 Register scratch, | 582 Register scratch, |
| 584 CompareIC::State expected, | 583 CompareIC::State expected, |
| 585 Label* fail) { | 584 Label* fail) { |
| 586 Label ok; | 585 Label ok; |
| 587 if (expected == CompareIC::SMI) { | 586 if (expected == CompareIC::SMI) { |
| 588 __ JumpIfNotSmi(input, fail); | 587 __ JumpIfNotSmi(input, fail); |
| 589 } else if (expected == CompareIC::NUMBER) { | 588 } else if (expected == CompareIC::NUMBER) { |
| 590 __ JumpIfSmi(input, &ok); | 589 __ JumpIfSmi(input, &ok); |
| 591 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, | 590 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, |
| 592 DONT_DO_SMI_CHECK); | 591 DONT_DO_SMI_CHECK); |
| 593 } | 592 } |
| 594 // We could be strict about internalized/non-internalized here, but as long as | 593 // We could be strict about internalized/non-internalized here, but as long as |
| 595 // hydrogen doesn't care, the stub doesn't have to care either. | 594 // hydrogen doesn't care, the stub doesn't have to care either. |
| 596 __ bind(&ok); | 595 __ bind(&ok); |
| 597 } | 596 } |
| 598 | 597 |
| 599 | 598 |
| 600 // On entry r1 and r2 are the values to be compared. | 599 // On entry r1 and r2 are the values to be compared. |
| 601 // On exit r0 is 0, positive or negative to indicate the result of | 600 // On exit r0 is 0, positive or negative to indicate the result of |
| 602 // the comparison. | 601 // the comparison. |
| 603 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 602 void CompareICStub::GenerateGeneric(MacroAssembler* masm) { |
| 604 Register lhs = r1; | 603 Register lhs = r1; |
| 605 Register rhs = r0; | 604 Register rhs = r0; |
| 606 Condition cc = GetCondition(); | 605 Condition cc = GetCondition(); |
| 607 | 606 |
| 608 Label miss; | 607 Label miss; |
| 609 ICCompareStub_CheckInputType(masm, lhs, r2, left(), &miss); | 608 CompareICStub_CheckInputType(masm, lhs, r2, left(), &miss); |
| 610 ICCompareStub_CheckInputType(masm, rhs, r3, right(), &miss); | 609 CompareICStub_CheckInputType(masm, rhs, r3, right(), &miss); |
| 611 | 610 |
| 612 Label slow; // Call builtin. | 611 Label slow; // Call builtin. |
| 613 Label not_smis, both_loaded_as_doubles, lhs_not_nan; | 612 Label not_smis, both_loaded_as_doubles, lhs_not_nan; |
| 614 | 613 |
| 615 Label not_two_smis, smi_done; | 614 Label not_two_smis, smi_done; |
| 616 __ orr(r2, r1, r0); | 615 __ orr(r2, r1, r0); |
| 617 __ JumpIfNotSmi(r2, ¬_two_smis); | 616 __ JumpIfNotSmi(r2, ¬_two_smis); |
| 618 __ mov(r1, Operand(r1, ASR, 1)); | 617 __ mov(r1, Operand(r1, ASR, 1)); |
| 619 __ sub(r0, r1, Operand(r0, ASR, 1)); | 618 __ sub(r0, r1, Operand(r0, ASR, 1)); |
| 620 __ Ret(); | 619 __ Ret(); |
| (...skipping 2725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3346 __ Assert(eq, kExpectedAllocationSite); | 3345 __ Assert(eq, kExpectedAllocationSite); |
| 3347 } | 3346 } |
| 3348 | 3347 |
| 3349 // Tail call into the stub that handles binary operations with allocation | 3348 // Tail call into the stub that handles binary operations with allocation |
| 3350 // sites. | 3349 // sites. |
| 3351 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3350 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
| 3352 __ TailCallStub(&stub); | 3351 __ TailCallStub(&stub); |
| 3353 } | 3352 } |
| 3354 | 3353 |
| 3355 | 3354 |
| 3356 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 3355 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
| 3357 DCHECK(state() == CompareIC::SMI); | 3356 DCHECK(state() == CompareIC::SMI); |
| 3358 Label miss; | 3357 Label miss; |
| 3359 __ orr(r2, r1, r0); | 3358 __ orr(r2, r1, r0); |
| 3360 __ JumpIfNotSmi(r2, &miss); | 3359 __ JumpIfNotSmi(r2, &miss); |
| 3361 | 3360 |
| 3362 if (GetCondition() == eq) { | 3361 if (GetCondition() == eq) { |
| 3363 // For equality we do not care about the sign of the result. | 3362 // For equality we do not care about the sign of the result. |
| 3364 __ sub(r0, r0, r1, SetCC); | 3363 __ sub(r0, r0, r1, SetCC); |
| 3365 } else { | 3364 } else { |
| 3366 // Untag before subtracting to avoid handling overflow. | 3365 // Untag before subtracting to avoid handling overflow. |
| 3367 __ SmiUntag(r1); | 3366 __ SmiUntag(r1); |
| 3368 __ sub(r0, r1, Operand::SmiUntag(r0)); | 3367 __ sub(r0, r1, Operand::SmiUntag(r0)); |
| 3369 } | 3368 } |
| 3370 __ Ret(); | 3369 __ Ret(); |
| 3371 | 3370 |
| 3372 __ bind(&miss); | 3371 __ bind(&miss); |
| 3373 GenerateMiss(masm); | 3372 GenerateMiss(masm); |
| 3374 } | 3373 } |
| 3375 | 3374 |
| 3376 | 3375 |
| 3377 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { | 3376 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
| 3378 DCHECK(state() == CompareIC::NUMBER); | 3377 DCHECK(state() == CompareIC::NUMBER); |
| 3379 | 3378 |
| 3380 Label generic_stub; | 3379 Label generic_stub; |
| 3381 Label unordered, maybe_undefined1, maybe_undefined2; | 3380 Label unordered, maybe_undefined1, maybe_undefined2; |
| 3382 Label miss; | 3381 Label miss; |
| 3383 | 3382 |
| 3384 if (left() == CompareIC::SMI) { | 3383 if (left() == CompareIC::SMI) { |
| 3385 __ JumpIfNotSmi(r1, &miss); | 3384 __ JumpIfNotSmi(r1, &miss); |
| 3386 } | 3385 } |
| 3387 if (right() == CompareIC::SMI) { | 3386 if (right() == CompareIC::SMI) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3419 __ b(vs, &unordered); | 3418 __ b(vs, &unordered); |
| 3420 | 3419 |
| 3421 // Return a result of -1, 0, or 1, based on status bits. | 3420 // Return a result of -1, 0, or 1, based on status bits. |
| 3422 __ mov(r0, Operand(EQUAL), LeaveCC, eq); | 3421 __ mov(r0, Operand(EQUAL), LeaveCC, eq); |
| 3423 __ mov(r0, Operand(LESS), LeaveCC, lt); | 3422 __ mov(r0, Operand(LESS), LeaveCC, lt); |
| 3424 __ mov(r0, Operand(GREATER), LeaveCC, gt); | 3423 __ mov(r0, Operand(GREATER), LeaveCC, gt); |
| 3425 __ Ret(); | 3424 __ Ret(); |
| 3426 | 3425 |
| 3427 __ bind(&unordered); | 3426 __ bind(&unordered); |
| 3428 __ bind(&generic_stub); | 3427 __ bind(&generic_stub); |
| 3429 ICCompareStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3428 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, |
| 3430 CompareIC::GENERIC); | 3429 CompareIC::GENERIC); |
| 3431 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3430 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 3432 | 3431 |
| 3433 __ bind(&maybe_undefined1); | 3432 __ bind(&maybe_undefined1); |
| 3434 if (Token::IsOrderedRelationalCompareOp(op())) { | 3433 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3435 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); | 3434 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); |
| 3436 __ b(ne, &miss); | 3435 __ b(ne, &miss); |
| 3437 __ JumpIfSmi(r1, &unordered); | 3436 __ JumpIfSmi(r1, &unordered); |
| 3438 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); | 3437 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); |
| 3439 __ b(ne, &maybe_undefined2); | 3438 __ b(ne, &maybe_undefined2); |
| 3440 __ jmp(&unordered); | 3439 __ jmp(&unordered); |
| 3441 } | 3440 } |
| 3442 | 3441 |
| 3443 __ bind(&maybe_undefined2); | 3442 __ bind(&maybe_undefined2); |
| 3444 if (Token::IsOrderedRelationalCompareOp(op())) { | 3443 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3445 __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); | 3444 __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); |
| 3446 __ b(eq, &unordered); | 3445 __ b(eq, &unordered); |
| 3447 } | 3446 } |
| 3448 | 3447 |
| 3449 __ bind(&miss); | 3448 __ bind(&miss); |
| 3450 GenerateMiss(masm); | 3449 GenerateMiss(masm); |
| 3451 } | 3450 } |
| 3452 | 3451 |
| 3453 | 3452 |
| 3454 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3453 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
| 3455 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3454 DCHECK(state() == CompareIC::INTERNALIZED_STRING); |
| 3456 Label miss; | 3455 Label miss; |
| 3457 | 3456 |
| 3458 // Registers containing left and right operands respectively. | 3457 // Registers containing left and right operands respectively. |
| 3459 Register left = r1; | 3458 Register left = r1; |
| 3460 Register right = r0; | 3459 Register right = r0; |
| 3461 Register tmp1 = r2; | 3460 Register tmp1 = r2; |
| 3462 Register tmp2 = r3; | 3461 Register tmp2 = r3; |
| 3463 | 3462 |
| 3464 // Check that both operands are heap objects. | 3463 // Check that both operands are heap objects. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3482 STATIC_ASSERT(EQUAL == 0); | 3481 STATIC_ASSERT(EQUAL == 0); |
| 3483 STATIC_ASSERT(kSmiTag == 0); | 3482 STATIC_ASSERT(kSmiTag == 0); |
| 3484 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); | 3483 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); |
| 3485 __ Ret(); | 3484 __ Ret(); |
| 3486 | 3485 |
| 3487 __ bind(&miss); | 3486 __ bind(&miss); |
| 3488 GenerateMiss(masm); | 3487 GenerateMiss(masm); |
| 3489 } | 3488 } |
| 3490 | 3489 |
| 3491 | 3490 |
| 3492 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { | 3491 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
| 3493 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3492 DCHECK(state() == CompareIC::UNIQUE_NAME); |
| 3494 DCHECK(GetCondition() == eq); | 3493 DCHECK(GetCondition() == eq); |
| 3495 Label miss; | 3494 Label miss; |
| 3496 | 3495 |
| 3497 // Registers containing left and right operands respectively. | 3496 // Registers containing left and right operands respectively. |
| 3498 Register left = r1; | 3497 Register left = r1; |
| 3499 Register right = r0; | 3498 Register right = r0; |
| 3500 Register tmp1 = r2; | 3499 Register tmp1 = r2; |
| 3501 Register tmp2 = r3; | 3500 Register tmp2 = r3; |
| 3502 | 3501 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3521 STATIC_ASSERT(EQUAL == 0); | 3520 STATIC_ASSERT(EQUAL == 0); |
| 3522 STATIC_ASSERT(kSmiTag == 0); | 3521 STATIC_ASSERT(kSmiTag == 0); |
| 3523 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); | 3522 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); |
| 3524 __ Ret(); | 3523 __ Ret(); |
| 3525 | 3524 |
| 3526 __ bind(&miss); | 3525 __ bind(&miss); |
| 3527 GenerateMiss(masm); | 3526 GenerateMiss(masm); |
| 3528 } | 3527 } |
| 3529 | 3528 |
| 3530 | 3529 |
| 3531 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { | 3530 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
| 3532 DCHECK(state() == CompareIC::STRING); | 3531 DCHECK(state() == CompareIC::STRING); |
| 3533 Label miss; | 3532 Label miss; |
| 3534 | 3533 |
| 3535 bool equality = Token::IsEqualityOp(op()); | 3534 bool equality = Token::IsEqualityOp(op()); |
| 3536 | 3535 |
| 3537 // Registers containing left and right operands respectively. | 3536 // Registers containing left and right operands respectively. |
| 3538 Register left = r1; | 3537 Register left = r1; |
| 3539 Register right = r0; | 3538 Register right = r0; |
| 3540 Register tmp1 = r2; | 3539 Register tmp1 = r2; |
| 3541 Register tmp2 = r3; | 3540 Register tmp2 = r3; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3600 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3599 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
| 3601 } else { | 3600 } else { |
| 3602 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3601 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 3603 } | 3602 } |
| 3604 | 3603 |
| 3605 __ bind(&miss); | 3604 __ bind(&miss); |
| 3606 GenerateMiss(masm); | 3605 GenerateMiss(masm); |
| 3607 } | 3606 } |
| 3608 | 3607 |
| 3609 | 3608 |
| 3610 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 3609 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
| 3611 DCHECK(state() == CompareIC::OBJECT); | 3610 DCHECK(state() == CompareIC::OBJECT); |
| 3612 Label miss; | 3611 Label miss; |
| 3613 __ and_(r2, r1, Operand(r0)); | 3612 __ and_(r2, r1, Operand(r0)); |
| 3614 __ JumpIfSmi(r2, &miss); | 3613 __ JumpIfSmi(r2, &miss); |
| 3615 | 3614 |
| 3616 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); | 3615 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); |
| 3617 __ b(ne, &miss); | 3616 __ b(ne, &miss); |
| 3618 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); | 3617 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); |
| 3619 __ b(ne, &miss); | 3618 __ b(ne, &miss); |
| 3620 | 3619 |
| 3621 DCHECK(GetCondition() == eq); | 3620 DCHECK(GetCondition() == eq); |
| 3622 __ sub(r0, r0, Operand(r1)); | 3621 __ sub(r0, r0, Operand(r1)); |
| 3623 __ Ret(); | 3622 __ Ret(); |
| 3624 | 3623 |
| 3625 __ bind(&miss); | 3624 __ bind(&miss); |
| 3626 GenerateMiss(masm); | 3625 GenerateMiss(masm); |
| 3627 } | 3626 } |
| 3628 | 3627 |
| 3629 | 3628 |
| 3630 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { | 3629 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { |
| 3631 Label miss; | 3630 Label miss; |
| 3632 __ and_(r2, r1, Operand(r0)); | 3631 __ and_(r2, r1, Operand(r0)); |
| 3633 __ JumpIfSmi(r2, &miss); | 3632 __ JumpIfSmi(r2, &miss); |
| 3634 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 3633 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 3635 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3634 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 3636 __ cmp(r2, Operand(known_map_)); | 3635 __ cmp(r2, Operand(known_map_)); |
| 3637 __ b(ne, &miss); | 3636 __ b(ne, &miss); |
| 3638 __ cmp(r3, Operand(known_map_)); | 3637 __ cmp(r3, Operand(known_map_)); |
| 3639 __ b(ne, &miss); | 3638 __ b(ne, &miss); |
| 3640 | 3639 |
| 3641 __ sub(r0, r0, Operand(r1)); | 3640 __ sub(r0, r0, Operand(r1)); |
| 3642 __ Ret(); | 3641 __ Ret(); |
| 3643 | 3642 |
| 3644 __ bind(&miss); | 3643 __ bind(&miss); |
| 3645 GenerateMiss(masm); | 3644 GenerateMiss(masm); |
| 3646 } | 3645 } |
| 3647 | 3646 |
| 3648 | 3647 |
| 3649 | 3648 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
| 3650 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | |
| 3651 { | 3649 { |
| 3652 // Call the runtime system in a fresh internal frame. | 3650 // Call the runtime system in a fresh internal frame. |
| 3653 ExternalReference miss = | 3651 ExternalReference miss = |
| 3654 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); | 3652 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); |
| 3655 | 3653 |
| 3656 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 3654 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 3657 __ Push(r1, r0); | 3655 __ Push(r1, r0); |
| 3658 __ Push(lr, r1, r0); | 3656 __ Push(lr, r1, r0); |
| 3659 __ mov(ip, Operand(Smi::FromInt(op()))); | 3657 __ mov(ip, Operand(Smi::FromInt(op()))); |
| 3660 __ push(ip); | 3658 __ push(ip); |
| (...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4723 MemOperand(fp, 6 * kPointerSize), | 4721 MemOperand(fp, 6 * kPointerSize), |
| 4724 NULL); | 4722 NULL); |
| 4725 } | 4723 } |
| 4726 | 4724 |
| 4727 | 4725 |
| 4728 #undef __ | 4726 #undef __ |
| 4729 | 4727 |
| 4730 } } // namespace v8::internal | 4728 } } // namespace v8::internal |
| 4731 | 4729 |
| 4732 #endif // V8_TARGET_ARCH_ARM | 4730 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |