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" |
11 #include "src/code-stubs.h" | 11 #include "src/code-stubs.h" |
12 #include "src/codegen.h" | 12 #include "src/codegen.h" |
13 #include "src/ic/handler-compiler.h" | 13 #include "src/ic/handler-compiler.h" |
| 14 #include "src/ic/ic.h" |
14 #include "src/isolate.h" | 15 #include "src/isolate.h" |
15 #include "src/jsregexp.h" | 16 #include "src/jsregexp.h" |
16 #include "src/regexp-macro-assembler.h" | 17 #include "src/regexp-macro-assembler.h" |
17 #include "src/runtime.h" | 18 #include "src/runtime.h" |
18 | 19 |
19 namespace v8 { | 20 namespace v8 { |
20 namespace internal { | 21 namespace internal { |
21 | 22 |
22 | 23 |
23 static void InitializeArrayConstructorDescriptor( | 24 static void InitializeArrayConstructorDescriptor( |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); | 560 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); |
560 __ and_(r0, r2, Operand(r3)); | 561 __ and_(r0, r2, Operand(r3)); |
561 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); | 562 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); |
562 __ eor(r0, r0, Operand(1 << Map::kIsUndetectable)); | 563 __ eor(r0, r0, Operand(1 << Map::kIsUndetectable)); |
563 __ Ret(); | 564 __ Ret(); |
564 } | 565 } |
565 | 566 |
566 | 567 |
567 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, | 568 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, |
568 Register scratch, | 569 Register scratch, |
569 CompareIC::State expected, | 570 CompareICState::State expected, |
570 Label* fail) { | 571 Label* fail) { |
571 Label ok; | 572 Label ok; |
572 if (expected == CompareIC::SMI) { | 573 if (expected == CompareICState::SMI) { |
573 __ JumpIfNotSmi(input, fail); | 574 __ JumpIfNotSmi(input, fail); |
574 } else if (expected == CompareIC::NUMBER) { | 575 } else if (expected == CompareICState::NUMBER) { |
575 __ JumpIfSmi(input, &ok); | 576 __ JumpIfSmi(input, &ok); |
576 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, | 577 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, |
577 DONT_DO_SMI_CHECK); | 578 DONT_DO_SMI_CHECK); |
578 } | 579 } |
579 // We could be strict about internalized/non-internalized here, but as long as | 580 // We could be strict about internalized/non-internalized here, but as long as |
580 // hydrogen doesn't care, the stub doesn't have to care either. | 581 // hydrogen doesn't care, the stub doesn't have to care either. |
581 __ bind(&ok); | 582 __ bind(&ok); |
582 } | 583 } |
583 | 584 |
584 | 585 |
(...skipping 2023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2608 // Verify that r4 contains an AllocationSite | 2609 // Verify that r4 contains an AllocationSite |
2609 __ ldr(r5, FieldMemOperand(r4, HeapObject::kMapOffset)); | 2610 __ ldr(r5, FieldMemOperand(r4, HeapObject::kMapOffset)); |
2610 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); | 2611 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); |
2611 __ b(ne, &miss); | 2612 __ b(ne, &miss); |
2612 | 2613 |
2613 __ mov(r2, r4); | 2614 __ mov(r2, r4); |
2614 ArrayConstructorStub stub(masm->isolate(), arg_count()); | 2615 ArrayConstructorStub stub(masm->isolate(), arg_count()); |
2615 __ TailCallStub(&stub); | 2616 __ TailCallStub(&stub); |
2616 | 2617 |
2617 __ bind(&miss); | 2618 __ bind(&miss); |
2618 GenerateMiss(masm, IC::kCallIC_Customization_Miss); | 2619 GenerateMiss(masm); |
2619 | 2620 |
2620 // The slow case, we need this no matter what to complete a call after a miss. | 2621 // The slow case, we need this no matter what to complete a call after a miss. |
2621 CallFunctionNoFeedback(masm, | 2622 CallFunctionNoFeedback(masm, |
2622 arg_count(), | 2623 arg_count(), |
2623 true, | 2624 true, |
2624 CallAsMethod()); | 2625 CallAsMethod()); |
2625 | 2626 |
2626 // Unreachable. | 2627 // Unreachable. |
2627 __ stop("Unexpected code address"); | 2628 __ stop("Unexpected code address"); |
2628 } | 2629 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2683 __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); | 2684 __ CompareObjectType(r4, r5, r5, JS_FUNCTION_TYPE); |
2684 __ b(ne, &miss); | 2685 __ b(ne, &miss); |
2685 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | 2686 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); |
2686 __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex); | 2687 __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex); |
2687 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); | 2688 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); |
2688 __ jmp(&slow_start); | 2689 __ jmp(&slow_start); |
2689 } | 2690 } |
2690 | 2691 |
2691 // We are here because tracing is on or we are going monomorphic. | 2692 // We are here because tracing is on or we are going monomorphic. |
2692 __ bind(&miss); | 2693 __ bind(&miss); |
2693 GenerateMiss(masm, IC::kCallIC_Miss); | 2694 GenerateMiss(masm); |
2694 | 2695 |
2695 // the slow case | 2696 // the slow case |
2696 __ bind(&slow_start); | 2697 __ bind(&slow_start); |
2697 // Check that the function is really a JavaScript function. | 2698 // Check that the function is really a JavaScript function. |
2698 // r1: pushed function (to be verified) | 2699 // r1: pushed function (to be verified) |
2699 __ JumpIfSmi(r1, &non_function); | 2700 __ JumpIfSmi(r1, &non_function); |
2700 | 2701 |
2701 // Goto slow case if we do not have a function. | 2702 // Goto slow case if we do not have a function. |
2702 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); | 2703 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); |
2703 __ b(ne, &slow); | 2704 __ b(ne, &slow); |
2704 __ jmp(&have_js_function); | 2705 __ jmp(&have_js_function); |
2705 } | 2706 } |
2706 | 2707 |
2707 | 2708 |
2708 void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) { | 2709 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
2709 // Get the receiver of the function from the stack; 1 ~ return address. | 2710 // Get the receiver of the function from the stack; 1 ~ return address. |
2710 __ ldr(r4, MemOperand(sp, (arg_count() + 1) * kPointerSize)); | 2711 __ ldr(r4, MemOperand(sp, (arg_count() + 1) * kPointerSize)); |
2711 | 2712 |
2712 { | 2713 { |
2713 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 2714 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
2714 | 2715 |
2715 // Push the receiver and the function and feedback info. | 2716 // Push the receiver and the function and feedback info. |
2716 __ Push(r4, r1, r2, r3); | 2717 __ Push(r4, r1, r2, r3); |
2717 | 2718 |
2718 // Call the entry. | 2719 // Call the entry. |
| 2720 IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss |
| 2721 : IC::kCallIC_Customization_Miss; |
| 2722 |
2719 ExternalReference miss = ExternalReference(IC_Utility(id), | 2723 ExternalReference miss = ExternalReference(IC_Utility(id), |
2720 masm->isolate()); | 2724 masm->isolate()); |
2721 __ CallExternalReference(miss, 4); | 2725 __ CallExternalReference(miss, 4); |
2722 | 2726 |
2723 // Move result to edi and exit the internal frame. | 2727 // Move result to edi and exit the internal frame. |
2724 __ mov(r1, r0); | 2728 __ mov(r1, r0); |
2725 } | 2729 } |
2726 } | 2730 } |
2727 | 2731 |
2728 | 2732 |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3272 } | 3276 } |
3273 | 3277 |
3274 // Tail call into the stub that handles binary operations with allocation | 3278 // Tail call into the stub that handles binary operations with allocation |
3275 // sites. | 3279 // sites. |
3276 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 3280 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
3277 __ TailCallStub(&stub); | 3281 __ TailCallStub(&stub); |
3278 } | 3282 } |
3279 | 3283 |
3280 | 3284 |
3281 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 3285 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3282 DCHECK(state() == CompareIC::SMI); | 3286 DCHECK(state() == CompareICState::SMI); |
3283 Label miss; | 3287 Label miss; |
3284 __ orr(r2, r1, r0); | 3288 __ orr(r2, r1, r0); |
3285 __ JumpIfNotSmi(r2, &miss); | 3289 __ JumpIfNotSmi(r2, &miss); |
3286 | 3290 |
3287 if (GetCondition() == eq) { | 3291 if (GetCondition() == eq) { |
3288 // For equality we do not care about the sign of the result. | 3292 // For equality we do not care about the sign of the result. |
3289 __ sub(r0, r0, r1, SetCC); | 3293 __ sub(r0, r0, r1, SetCC); |
3290 } else { | 3294 } else { |
3291 // Untag before subtracting to avoid handling overflow. | 3295 // Untag before subtracting to avoid handling overflow. |
3292 __ SmiUntag(r1); | 3296 __ SmiUntag(r1); |
3293 __ sub(r0, r1, Operand::SmiUntag(r0)); | 3297 __ sub(r0, r1, Operand::SmiUntag(r0)); |
3294 } | 3298 } |
3295 __ Ret(); | 3299 __ Ret(); |
3296 | 3300 |
3297 __ bind(&miss); | 3301 __ bind(&miss); |
3298 GenerateMiss(masm); | 3302 GenerateMiss(masm); |
3299 } | 3303 } |
3300 | 3304 |
3301 | 3305 |
3302 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { | 3306 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
3303 DCHECK(state() == CompareIC::NUMBER); | 3307 DCHECK(state() == CompareICState::NUMBER); |
3304 | 3308 |
3305 Label generic_stub; | 3309 Label generic_stub; |
3306 Label unordered, maybe_undefined1, maybe_undefined2; | 3310 Label unordered, maybe_undefined1, maybe_undefined2; |
3307 Label miss; | 3311 Label miss; |
3308 | 3312 |
3309 if (left() == CompareIC::SMI) { | 3313 if (left() == CompareICState::SMI) { |
3310 __ JumpIfNotSmi(r1, &miss); | 3314 __ JumpIfNotSmi(r1, &miss); |
3311 } | 3315 } |
3312 if (right() == CompareIC::SMI) { | 3316 if (right() == CompareICState::SMI) { |
3313 __ JumpIfNotSmi(r0, &miss); | 3317 __ JumpIfNotSmi(r0, &miss); |
3314 } | 3318 } |
3315 | 3319 |
3316 // Inlining the double comparison and falling back to the general compare | 3320 // Inlining the double comparison and falling back to the general compare |
3317 // stub if NaN is involved. | 3321 // stub if NaN is involved. |
3318 // Load left and right operand. | 3322 // Load left and right operand. |
3319 Label done, left, left_smi, right_smi; | 3323 Label done, left, left_smi, right_smi; |
3320 __ JumpIfSmi(r0, &right_smi); | 3324 __ JumpIfSmi(r0, &right_smi); |
3321 __ CheckMap(r0, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, | 3325 __ CheckMap(r0, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, |
3322 DONT_DO_SMI_CHECK); | 3326 DONT_DO_SMI_CHECK); |
(...skipping 21 matching lines...) Expand all Loading... |
3344 __ b(vs, &unordered); | 3348 __ b(vs, &unordered); |
3345 | 3349 |
3346 // Return a result of -1, 0, or 1, based on status bits. | 3350 // Return a result of -1, 0, or 1, based on status bits. |
3347 __ mov(r0, Operand(EQUAL), LeaveCC, eq); | 3351 __ mov(r0, Operand(EQUAL), LeaveCC, eq); |
3348 __ mov(r0, Operand(LESS), LeaveCC, lt); | 3352 __ mov(r0, Operand(LESS), LeaveCC, lt); |
3349 __ mov(r0, Operand(GREATER), LeaveCC, gt); | 3353 __ mov(r0, Operand(GREATER), LeaveCC, gt); |
3350 __ Ret(); | 3354 __ Ret(); |
3351 | 3355 |
3352 __ bind(&unordered); | 3356 __ bind(&unordered); |
3353 __ bind(&generic_stub); | 3357 __ bind(&generic_stub); |
3354 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3358 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3355 CompareIC::GENERIC); | 3359 CompareICState::GENERIC, CompareICState::GENERIC); |
3356 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3360 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
3357 | 3361 |
3358 __ bind(&maybe_undefined1); | 3362 __ bind(&maybe_undefined1); |
3359 if (Token::IsOrderedRelationalCompareOp(op())) { | 3363 if (Token::IsOrderedRelationalCompareOp(op())) { |
3360 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); | 3364 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); |
3361 __ b(ne, &miss); | 3365 __ b(ne, &miss); |
3362 __ JumpIfSmi(r1, &unordered); | 3366 __ JumpIfSmi(r1, &unordered); |
3363 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); | 3367 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); |
3364 __ b(ne, &maybe_undefined2); | 3368 __ b(ne, &maybe_undefined2); |
3365 __ jmp(&unordered); | 3369 __ jmp(&unordered); |
3366 } | 3370 } |
3367 | 3371 |
3368 __ bind(&maybe_undefined2); | 3372 __ bind(&maybe_undefined2); |
3369 if (Token::IsOrderedRelationalCompareOp(op())) { | 3373 if (Token::IsOrderedRelationalCompareOp(op())) { |
3370 __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); | 3374 __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); |
3371 __ b(eq, &unordered); | 3375 __ b(eq, &unordered); |
3372 } | 3376 } |
3373 | 3377 |
3374 __ bind(&miss); | 3378 __ bind(&miss); |
3375 GenerateMiss(masm); | 3379 GenerateMiss(masm); |
3376 } | 3380 } |
3377 | 3381 |
3378 | 3382 |
3379 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3383 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3380 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3384 DCHECK(state() == CompareICState::INTERNALIZED_STRING); |
3381 Label miss; | 3385 Label miss; |
3382 | 3386 |
3383 // Registers containing left and right operands respectively. | 3387 // Registers containing left and right operands respectively. |
3384 Register left = r1; | 3388 Register left = r1; |
3385 Register right = r0; | 3389 Register right = r0; |
3386 Register tmp1 = r2; | 3390 Register tmp1 = r2; |
3387 Register tmp2 = r3; | 3391 Register tmp2 = r3; |
3388 | 3392 |
3389 // Check that both operands are heap objects. | 3393 // Check that both operands are heap objects. |
3390 __ JumpIfEitherSmi(left, right, &miss); | 3394 __ JumpIfEitherSmi(left, right, &miss); |
(...skipping 17 matching lines...) Expand all Loading... |
3408 STATIC_ASSERT(kSmiTag == 0); | 3412 STATIC_ASSERT(kSmiTag == 0); |
3409 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); | 3413 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); |
3410 __ Ret(); | 3414 __ Ret(); |
3411 | 3415 |
3412 __ bind(&miss); | 3416 __ bind(&miss); |
3413 GenerateMiss(masm); | 3417 GenerateMiss(masm); |
3414 } | 3418 } |
3415 | 3419 |
3416 | 3420 |
3417 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { | 3421 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
3418 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3422 DCHECK(state() == CompareICState::UNIQUE_NAME); |
3419 DCHECK(GetCondition() == eq); | 3423 DCHECK(GetCondition() == eq); |
3420 Label miss; | 3424 Label miss; |
3421 | 3425 |
3422 // Registers containing left and right operands respectively. | 3426 // Registers containing left and right operands respectively. |
3423 Register left = r1; | 3427 Register left = r1; |
3424 Register right = r0; | 3428 Register right = r0; |
3425 Register tmp1 = r2; | 3429 Register tmp1 = r2; |
3426 Register tmp2 = r3; | 3430 Register tmp2 = r3; |
3427 | 3431 |
3428 // Check that both operands are heap objects. | 3432 // Check that both operands are heap objects. |
(...skipping 18 matching lines...) Expand all Loading... |
3447 STATIC_ASSERT(kSmiTag == 0); | 3451 STATIC_ASSERT(kSmiTag == 0); |
3448 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); | 3452 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); |
3449 __ Ret(); | 3453 __ Ret(); |
3450 | 3454 |
3451 __ bind(&miss); | 3455 __ bind(&miss); |
3452 GenerateMiss(masm); | 3456 GenerateMiss(masm); |
3453 } | 3457 } |
3454 | 3458 |
3455 | 3459 |
3456 void CompareICStub::GenerateStrings(MacroAssembler* masm) { | 3460 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
3457 DCHECK(state() == CompareIC::STRING); | 3461 DCHECK(state() == CompareICState::STRING); |
3458 Label miss; | 3462 Label miss; |
3459 | 3463 |
3460 bool equality = Token::IsEqualityOp(op()); | 3464 bool equality = Token::IsEqualityOp(op()); |
3461 | 3465 |
3462 // Registers containing left and right operands respectively. | 3466 // Registers containing left and right operands respectively. |
3463 Register left = r1; | 3467 Register left = r1; |
3464 Register right = r0; | 3468 Register right = r0; |
3465 Register tmp1 = r2; | 3469 Register tmp1 = r2; |
3466 Register tmp2 = r3; | 3470 Register tmp2 = r3; |
3467 Register tmp3 = r4; | 3471 Register tmp3 = r4; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3526 } else { | 3530 } else { |
3527 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3531 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3528 } | 3532 } |
3529 | 3533 |
3530 __ bind(&miss); | 3534 __ bind(&miss); |
3531 GenerateMiss(masm); | 3535 GenerateMiss(masm); |
3532 } | 3536 } |
3533 | 3537 |
3534 | 3538 |
3535 void CompareICStub::GenerateObjects(MacroAssembler* masm) { | 3539 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
3536 DCHECK(state() == CompareIC::OBJECT); | 3540 DCHECK(state() == CompareICState::OBJECT); |
3537 Label miss; | 3541 Label miss; |
3538 __ and_(r2, r1, Operand(r0)); | 3542 __ and_(r2, r1, Operand(r0)); |
3539 __ JumpIfSmi(r2, &miss); | 3543 __ JumpIfSmi(r2, &miss); |
3540 | 3544 |
3541 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); | 3545 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); |
3542 __ b(ne, &miss); | 3546 __ b(ne, &miss); |
3543 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); | 3547 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); |
3544 __ b(ne, &miss); | 3548 __ b(ne, &miss); |
3545 | 3549 |
3546 DCHECK(GetCondition() == eq); | 3550 DCHECK(GetCondition() == eq); |
(...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4648 MemOperand(fp, 6 * kPointerSize), | 4652 MemOperand(fp, 6 * kPointerSize), |
4649 NULL); | 4653 NULL); |
4650 } | 4654 } |
4651 | 4655 |
4652 | 4656 |
4653 #undef __ | 4657 #undef __ |
4654 | 4658 |
4655 } } // namespace v8::internal | 4659 } } // namespace v8::internal |
4656 | 4660 |
4657 #endif // V8_TARGET_ARCH_ARM | 4661 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |