OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 Register object, | 445 Register object, |
446 DwVfpRegister dst, | 446 DwVfpRegister dst, |
447 Register dst1, | 447 Register dst1, |
448 Register dst2, | 448 Register dst2, |
449 Register heap_number_map, | 449 Register heap_number_map, |
450 Register scratch1, | 450 Register scratch1, |
451 Register scratch2, | 451 Register scratch2, |
452 Label* not_number) { | 452 Label* not_number) { |
453 Label is_smi, done; | 453 Label is_smi, done; |
454 | 454 |
455 __ BranchOnSmi(object, &is_smi); | 455 __ JumpIfSmi(object, &is_smi); |
456 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); | 456 __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number); |
457 | 457 |
458 // Handle loading a double from a heap number. | 458 // Handle loading a double from a heap number. |
459 if (CpuFeatures::IsSupported(VFP3)) { | 459 if (CpuFeatures::IsSupported(VFP3)) { |
460 CpuFeatures::Scope scope(VFP3); | 460 CpuFeatures::Scope scope(VFP3); |
461 // Load the double from tagged HeapNumber to double register. | 461 // Load the double from tagged HeapNumber to double register. |
462 __ sub(scratch1, object, Operand(kHeapObjectTag)); | 462 __ sub(scratch1, object, Operand(kHeapObjectTag)); |
463 __ vldr(dst, scratch1, HeapNumber::kValueOffset); | 463 __ vldr(dst, scratch1, HeapNumber::kValueOffset); |
464 } else { | 464 } else { |
465 ASSERT(destination == kCoreRegisters); | 465 ASSERT(destination == kCoreRegisters); |
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
977 __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); | 977 __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); |
978 __ sub(mask, mask, Operand(1)); // Make mask. | 978 __ sub(mask, mask, Operand(1)); // Make mask. |
979 | 979 |
980 // Calculate the entry in the number string cache. The hash value in the | 980 // Calculate the entry in the number string cache. The hash value in the |
981 // number string cache for smis is just the smi value, and the hash for | 981 // number string cache for smis is just the smi value, and the hash for |
982 // doubles is the xor of the upper and lower words. See | 982 // doubles is the xor of the upper and lower words. See |
983 // Heap::GetNumberStringCache. | 983 // Heap::GetNumberStringCache. |
984 Label is_smi; | 984 Label is_smi; |
985 Label load_result_from_cache; | 985 Label load_result_from_cache; |
986 if (!object_is_smi) { | 986 if (!object_is_smi) { |
987 __ BranchOnSmi(object, &is_smi); | 987 __ JumpIfSmi(object, &is_smi); |
988 if (CpuFeatures::IsSupported(VFP3)) { | 988 if (CpuFeatures::IsSupported(VFP3)) { |
989 CpuFeatures::Scope scope(VFP3); | 989 CpuFeatures::Scope scope(VFP3); |
990 __ CheckMap(object, | 990 __ CheckMap(object, |
991 scratch1, | 991 scratch1, |
992 Heap::kHeapNumberMapRootIndex, | 992 Heap::kHeapNumberMapRootIndex, |
993 not_found, | 993 not_found, |
994 true); | 994 true); |
995 | 995 |
996 STATIC_ASSERT(8 == kDoubleSize); | 996 STATIC_ASSERT(8 == kDoubleSize); |
997 __ add(scratch1, | 997 __ add(scratch1, |
998 object, | 998 object, |
999 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); | 999 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); |
1000 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); | 1000 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); |
1001 __ eor(scratch1, scratch1, Operand(scratch2)); | 1001 __ eor(scratch1, scratch1, Operand(scratch2)); |
1002 __ and_(scratch1, scratch1, Operand(mask)); | 1002 __ and_(scratch1, scratch1, Operand(mask)); |
1003 | 1003 |
1004 // Calculate address of entry in string cache: each entry consists | 1004 // Calculate address of entry in string cache: each entry consists |
1005 // of two pointer sized fields. | 1005 // of two pointer sized fields. |
1006 __ add(scratch1, | 1006 __ add(scratch1, |
1007 number_string_cache, | 1007 number_string_cache, |
1008 Operand(scratch1, LSL, kPointerSizeLog2 + 1)); | 1008 Operand(scratch1, LSL, kPointerSizeLog2 + 1)); |
1009 | 1009 |
1010 Register probe = mask; | 1010 Register probe = mask; |
1011 __ ldr(probe, | 1011 __ ldr(probe, |
1012 FieldMemOperand(scratch1, FixedArray::kHeaderSize)); | 1012 FieldMemOperand(scratch1, FixedArray::kHeaderSize)); |
1013 __ BranchOnSmi(probe, not_found); | 1013 __ JumpIfSmi(probe, not_found); |
1014 __ sub(scratch2, object, Operand(kHeapObjectTag)); | 1014 __ sub(scratch2, object, Operand(kHeapObjectTag)); |
1015 __ vldr(d0, scratch2, HeapNumber::kValueOffset); | 1015 __ vldr(d0, scratch2, HeapNumber::kValueOffset); |
1016 __ sub(probe, probe, Operand(kHeapObjectTag)); | 1016 __ sub(probe, probe, Operand(kHeapObjectTag)); |
1017 __ vldr(d1, probe, HeapNumber::kValueOffset); | 1017 __ vldr(d1, probe, HeapNumber::kValueOffset); |
1018 __ VFPCompareAndSetFlags(d0, d1); | 1018 __ VFPCompareAndSetFlags(d0, d1); |
1019 __ b(ne, not_found); // The cache did not contain this value. | 1019 __ b(ne, not_found); // The cache did not contain this value. |
1020 __ b(&load_result_from_cache); | 1020 __ b(&load_result_from_cache); |
1021 } else { | 1021 } else { |
1022 __ b(not_found); | 1022 __ b(not_found); |
1023 } | 1023 } |
(...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2102 } | 2102 } |
2103 HandleBinaryOpSlowCases(masm, ¬_smi, lhs, rhs, Builtins::MUL); | 2103 HandleBinaryOpSlowCases(masm, ¬_smi, lhs, rhs, Builtins::MUL); |
2104 break; | 2104 break; |
2105 } | 2105 } |
2106 | 2106 |
2107 case Token::DIV: | 2107 case Token::DIV: |
2108 case Token::MOD: { | 2108 case Token::MOD: { |
2109 Label not_smi; | 2109 Label not_smi; |
2110 if (ShouldGenerateSmiCode() && specialized_on_rhs_) { | 2110 if (ShouldGenerateSmiCode() && specialized_on_rhs_) { |
2111 Label lhs_is_unsuitable; | 2111 Label lhs_is_unsuitable; |
2112 __ BranchOnNotSmi(lhs, ¬_smi); | 2112 __ JumpIfNotSmi(lhs, ¬_smi); |
2113 if (IsPowerOf2(constant_rhs_)) { | 2113 if (IsPowerOf2(constant_rhs_)) { |
2114 if (op_ == Token::MOD) { | 2114 if (op_ == Token::MOD) { |
2115 __ and_(rhs, | 2115 __ and_(rhs, |
2116 lhs, | 2116 lhs, |
2117 Operand(0x80000000u | ((constant_rhs_ << kSmiTagSize) - 1)), | 2117 Operand(0x80000000u | ((constant_rhs_ << kSmiTagSize) - 1)), |
2118 SetCC); | 2118 SetCC); |
2119 // We now have the answer, but if the input was negative we also | 2119 // We now have the answer, but if the input was negative we also |
2120 // have the sign bit. Our work is done if the result is | 2120 // have the sign bit. Our work is done if the result is |
2121 // positive or zero: | 2121 // positive or zero: |
2122 if (!rhs.is(r0)) { | 2122 if (!rhs.is(r0)) { |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2668 __ TailCallStub(&stub); | 2668 __ TailCallStub(&stub); |
2669 } | 2669 } |
2670 | 2670 |
2671 | 2671 |
2672 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { | 2672 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
2673 Register left = r1; | 2673 Register left = r1; |
2674 Register right = r0; | 2674 Register right = r0; |
2675 Label call_runtime; | 2675 Label call_runtime; |
2676 | 2676 |
2677 // Check if first argument is a string. | 2677 // Check if first argument is a string. |
2678 __ BranchOnSmi(left, &call_runtime); | 2678 __ JumpIfSmi(left, &call_runtime); |
2679 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); | 2679 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); |
2680 __ b(ge, &call_runtime); | 2680 __ b(ge, &call_runtime); |
2681 | 2681 |
2682 // First argument is a a string, test second. | 2682 // First argument is a a string, test second. |
2683 __ BranchOnSmi(right, &call_runtime); | 2683 __ JumpIfSmi(right, &call_runtime); |
2684 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); | 2684 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); |
2685 __ b(ge, &call_runtime); | 2685 __ b(ge, &call_runtime); |
2686 | 2686 |
2687 // First and second argument are strings. | 2687 // First and second argument are strings. |
2688 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); | 2688 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); |
2689 GenerateRegisterArgsPush(masm); | 2689 GenerateRegisterArgsPush(masm); |
2690 __ TailCallStub(&string_add_stub); | 2690 __ TailCallStub(&string_add_stub); |
2691 | 2691 |
2692 // At least one argument is not a string. | 2692 // At least one argument is not a string. |
2693 __ bind(&call_runtime); | 2693 __ bind(&call_runtime); |
(...skipping 22 matching lines...) Expand all Loading... |
2716 | 2716 |
2717 // Code below will scratch result if allocation fails. To keep both arguments | 2717 // Code below will scratch result if allocation fails. To keep both arguments |
2718 // intact for the runtime call result cannot be one of these. | 2718 // intact for the runtime call result cannot be one of these. |
2719 ASSERT(!result.is(r0) && !result.is(r1)); | 2719 ASSERT(!result.is(r0) && !result.is(r1)); |
2720 | 2720 |
2721 if (mode_ == OVERWRITE_LEFT || mode_ == OVERWRITE_RIGHT) { | 2721 if (mode_ == OVERWRITE_LEFT || mode_ == OVERWRITE_RIGHT) { |
2722 Label skip_allocation, allocated; | 2722 Label skip_allocation, allocated; |
2723 Register overwritable_operand = mode_ == OVERWRITE_LEFT ? r1 : r0; | 2723 Register overwritable_operand = mode_ == OVERWRITE_LEFT ? r1 : r0; |
2724 // If the overwritable operand is already an object, we skip the | 2724 // If the overwritable operand is already an object, we skip the |
2725 // allocation of a heap number. | 2725 // allocation of a heap number. |
2726 __ BranchOnNotSmi(overwritable_operand, &skip_allocation); | 2726 __ JumpIfNotSmi(overwritable_operand, &skip_allocation); |
2727 // Allocate a heap number for the result. | 2727 // Allocate a heap number for the result. |
2728 __ AllocateHeapNumber( | 2728 __ AllocateHeapNumber( |
2729 result, scratch1, scratch2, heap_number_map, gc_required); | 2729 result, scratch1, scratch2, heap_number_map, gc_required); |
2730 __ b(&allocated); | 2730 __ b(&allocated); |
2731 __ bind(&skip_allocation); | 2731 __ bind(&skip_allocation); |
2732 // Use object holding the overwritable operand for result. | 2732 // Use object holding the overwritable operand for result. |
2733 __ mov(result, Operand(overwritable_operand)); | 2733 __ mov(result, Operand(overwritable_operand)); |
2734 __ bind(&allocated); | 2734 __ bind(&allocated); |
2735 } else { | 2735 } else { |
2736 ASSERT(mode_ == NO_OVERWRITE); | 2736 ASSERT(mode_ == NO_OVERWRITE); |
2737 __ AllocateHeapNumber( | 2737 __ AllocateHeapNumber( |
2738 result, scratch1, scratch2, heap_number_map, gc_required); | 2738 result, scratch1, scratch2, heap_number_map, gc_required); |
2739 } | 2739 } |
2740 } | 2740 } |
2741 | 2741 |
2742 | 2742 |
2743 void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { | 2743 void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { |
2744 __ Push(r1, r0); | 2744 __ Push(r1, r0); |
2745 } | 2745 } |
2746 | 2746 |
2747 | 2747 |
2748 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { | 2748 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { |
2749 // Argument is a number and is on stack and in r0. | 2749 // Argument is a number and is on stack and in r0. |
2750 Label runtime_call; | 2750 Label runtime_call; |
2751 Label input_not_smi; | 2751 Label input_not_smi; |
2752 Label loaded; | 2752 Label loaded; |
2753 | 2753 |
2754 if (CpuFeatures::IsSupported(VFP3)) { | 2754 if (CpuFeatures::IsSupported(VFP3)) { |
2755 // Load argument and check if it is a smi. | 2755 // Load argument and check if it is a smi. |
2756 __ BranchOnNotSmi(r0, &input_not_smi); | 2756 __ JumpIfNotSmi(r0, &input_not_smi); |
2757 | 2757 |
2758 CpuFeatures::Scope scope(VFP3); | 2758 CpuFeatures::Scope scope(VFP3); |
2759 // Input is a smi. Convert to double and load the low and high words | 2759 // Input is a smi. Convert to double and load the low and high words |
2760 // of the double into r2, r3. | 2760 // of the double into r2, r3. |
2761 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2); | 2761 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2); |
2762 __ b(&loaded); | 2762 __ b(&loaded); |
2763 | 2763 |
2764 __ bind(&input_not_smi); | 2764 __ bind(&input_not_smi); |
2765 // Check if input is a HeapNumber. | 2765 // Check if input is a HeapNumber. |
2766 __ CheckMap(r0, | 2766 __ CheckMap(r0, |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2900 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 2900 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
2901 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 2901 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
2902 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); | 2902 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); |
2903 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. | 2903 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. |
2904 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); | 2904 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); |
2905 __ mov(r0, Operand(r1)); | 2905 __ mov(r0, Operand(r1)); |
2906 } | 2906 } |
2907 } else if (op_ == Token::BIT_NOT) { | 2907 } else if (op_ == Token::BIT_NOT) { |
2908 if (include_smi_code_) { | 2908 if (include_smi_code_) { |
2909 Label non_smi; | 2909 Label non_smi; |
2910 __ BranchOnNotSmi(r0, &non_smi); | 2910 __ JumpIfNotSmi(r0, &non_smi); |
2911 __ mvn(r0, Operand(r0)); | 2911 __ mvn(r0, Operand(r0)); |
2912 // Bit-clear inverted smi-tag. | 2912 // Bit-clear inverted smi-tag. |
2913 __ bic(r0, r0, Operand(kSmiTagMask)); | 2913 __ bic(r0, r0, Operand(kSmiTagMask)); |
2914 __ Ret(); | 2914 __ Ret(); |
2915 __ bind(&non_smi); | 2915 __ bind(&non_smi); |
2916 } else if (FLAG_debug_code) { | 2916 } else if (FLAG_debug_code) { |
2917 __ tst(r0, Operand(kSmiTagMask)); | 2917 __ tst(r0, Operand(kSmiTagMask)); |
2918 __ Assert(ne, "Unexpected smi operand."); | 2918 __ Assert(ne, "Unexpected smi operand."); |
2919 } | 2919 } |
2920 | 2920 |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3429 const int32_t kDeltaToLoadBoolResult = 3 * kPointerSize; | 3429 const int32_t kDeltaToLoadBoolResult = 3 * kPointerSize; |
3430 | 3430 |
3431 Label slow, loop, is_instance, is_not_instance, not_js_object; | 3431 Label slow, loop, is_instance, is_not_instance, not_js_object; |
3432 | 3432 |
3433 if (!HasArgsInRegisters()) { | 3433 if (!HasArgsInRegisters()) { |
3434 __ ldr(object, MemOperand(sp, 1 * kPointerSize)); | 3434 __ ldr(object, MemOperand(sp, 1 * kPointerSize)); |
3435 __ ldr(function, MemOperand(sp, 0)); | 3435 __ ldr(function, MemOperand(sp, 0)); |
3436 } | 3436 } |
3437 | 3437 |
3438 // Check that the left hand is a JS object and load map. | 3438 // Check that the left hand is a JS object and load map. |
3439 __ BranchOnSmi(object, ¬_js_object); | 3439 __ JumpIfSmi(object, ¬_js_object); |
3440 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 3440 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
3441 | 3441 |
3442 // If there is a call site cache don't look in the global cache, but do the | 3442 // If there is a call site cache don't look in the global cache, but do the |
3443 // real lookup and update the call site cache. | 3443 // real lookup and update the call site cache. |
3444 if (!HasCallSiteInlineCheck()) { | 3444 if (!HasCallSiteInlineCheck()) { |
3445 Label miss; | 3445 Label miss; |
3446 __ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex); | 3446 __ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex); |
3447 __ cmp(function, ip); | 3447 __ cmp(function, ip); |
3448 __ b(ne, &miss); | 3448 __ b(ne, &miss); |
3449 __ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex); | 3449 __ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex); |
3450 __ cmp(map, ip); | 3450 __ cmp(map, ip); |
3451 __ b(ne, &miss); | 3451 __ b(ne, &miss); |
3452 __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); | 3452 __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); |
3453 __ Ret(HasArgsInRegisters() ? 0 : 2); | 3453 __ Ret(HasArgsInRegisters() ? 0 : 2); |
3454 | 3454 |
3455 __ bind(&miss); | 3455 __ bind(&miss); |
3456 } | 3456 } |
3457 | 3457 |
3458 // Get the prototype of the function. | 3458 // Get the prototype of the function. |
3459 __ TryGetFunctionPrototype(function, prototype, scratch, &slow); | 3459 __ TryGetFunctionPrototype(function, prototype, scratch, &slow); |
3460 | 3460 |
3461 // Check that the function prototype is a JS object. | 3461 // Check that the function prototype is a JS object. |
3462 __ BranchOnSmi(prototype, &slow); | 3462 __ JumpIfSmi(prototype, &slow); |
3463 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); | 3463 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); |
3464 | 3464 |
3465 // Update the global instanceof or call site inlined cache with the current | 3465 // Update the global instanceof or call site inlined cache with the current |
3466 // map and function. The cached answer will be set when it is known below. | 3466 // map and function. The cached answer will be set when it is known below. |
3467 if (!HasCallSiteInlineCheck()) { | 3467 if (!HasCallSiteInlineCheck()) { |
3468 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); | 3468 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); |
3469 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); | 3469 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); |
3470 } else { | 3470 } else { |
3471 ASSERT(HasArgsInRegisters()); | 3471 ASSERT(HasArgsInRegisters()); |
3472 // Patch the (relocated) inlined map check. | 3472 // Patch the (relocated) inlined map check. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3532 if (!ReturnTrueFalseObject()) { | 3532 if (!ReturnTrueFalseObject()) { |
3533 __ mov(r0, Operand(Smi::FromInt(1))); | 3533 __ mov(r0, Operand(Smi::FromInt(1))); |
3534 } | 3534 } |
3535 } | 3535 } |
3536 __ Ret(HasArgsInRegisters() ? 0 : 2); | 3536 __ Ret(HasArgsInRegisters() ? 0 : 2); |
3537 | 3537 |
3538 Label object_not_null, object_not_null_or_smi; | 3538 Label object_not_null, object_not_null_or_smi; |
3539 __ bind(¬_js_object); | 3539 __ bind(¬_js_object); |
3540 // Before null, smi and string value checks, check that the rhs is a function | 3540 // Before null, smi and string value checks, check that the rhs is a function |
3541 // as for a non-function rhs an exception needs to be thrown. | 3541 // as for a non-function rhs an exception needs to be thrown. |
3542 __ BranchOnSmi(function, &slow); | 3542 __ JumpIfSmi(function, &slow); |
3543 __ CompareObjectType(function, scratch2, scratch, JS_FUNCTION_TYPE); | 3543 __ CompareObjectType(function, scratch2, scratch, JS_FUNCTION_TYPE); |
3544 __ b(ne, &slow); | 3544 __ b(ne, &slow); |
3545 | 3545 |
3546 // Null is not instance of anything. | 3546 // Null is not instance of anything. |
3547 __ cmp(scratch, Operand(Factory::null_value())); | 3547 __ cmp(scratch, Operand(Factory::null_value())); |
3548 __ b(ne, &object_not_null); | 3548 __ b(ne, &object_not_null); |
3549 __ mov(r0, Operand(Smi::FromInt(1))); | 3549 __ mov(r0, Operand(Smi::FromInt(1))); |
3550 __ Ret(HasArgsInRegisters() ? 0 : 2); | 3550 __ Ret(HasArgsInRegisters() ? 0 : 2); |
3551 | 3551 |
3552 __ bind(&object_not_null); | 3552 __ bind(&object_not_null); |
3553 // Smi values are not instances of anything. | 3553 // Smi values are not instances of anything. |
3554 __ BranchOnNotSmi(object, &object_not_null_or_smi); | 3554 __ JumpIfNotSmi(object, &object_not_null_or_smi); |
3555 __ mov(r0, Operand(Smi::FromInt(1))); | 3555 __ mov(r0, Operand(Smi::FromInt(1))); |
3556 __ Ret(HasArgsInRegisters() ? 0 : 2); | 3556 __ Ret(HasArgsInRegisters() ? 0 : 2); |
3557 | 3557 |
3558 __ bind(&object_not_null_or_smi); | 3558 __ bind(&object_not_null_or_smi); |
3559 // String values are not instances of anything. | 3559 // String values are not instances of anything. |
3560 __ IsObjectJSStringType(object, scratch, &slow); | 3560 __ IsObjectJSStringType(object, scratch, &slow); |
3561 __ mov(r0, Operand(Smi::FromInt(1))); | 3561 __ mov(r0, Operand(Smi::FromInt(1))); |
3562 __ Ret(HasArgsInRegisters() ? 0 : 2); | 3562 __ Ret(HasArgsInRegisters() ? 0 : 2); |
3563 | 3563 |
3564 // Slow-case. Tail call builtin. | 3564 // Slow-case. Tail call builtin. |
(...skipping 23 matching lines...) Expand all Loading... |
3588 | 3588 |
3589 | 3589 |
3590 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 3590 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
3591 // The displacement is the offset of the last parameter (if any) | 3591 // The displacement is the offset of the last parameter (if any) |
3592 // relative to the frame pointer. | 3592 // relative to the frame pointer. |
3593 static const int kDisplacement = | 3593 static const int kDisplacement = |
3594 StandardFrameConstants::kCallerSPOffset - kPointerSize; | 3594 StandardFrameConstants::kCallerSPOffset - kPointerSize; |
3595 | 3595 |
3596 // Check that the key is a smi. | 3596 // Check that the key is a smi. |
3597 Label slow; | 3597 Label slow; |
3598 __ BranchOnNotSmi(r1, &slow); | 3598 __ JumpIfNotSmi(r1, &slow); |
3599 | 3599 |
3600 // Check if the calling frame is an arguments adaptor frame. | 3600 // Check if the calling frame is an arguments adaptor frame. |
3601 Label adaptor; | 3601 Label adaptor; |
3602 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3602 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
3603 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 3603 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
3604 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3604 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
3605 __ b(eq, &adaptor); | 3605 __ b(eq, &adaptor); |
3606 | 3606 |
3607 // Check index against formal parameters count limit passed in | 3607 // Check index against formal parameters count limit passed in |
3608 // through register r0. Use unsigned comparison to get negative | 3608 // through register r0. Use unsigned comparison to get negative |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4170 | 4170 |
4171 // If the receiver might be a value (string, number or boolean) check for this | 4171 // If the receiver might be a value (string, number or boolean) check for this |
4172 // and box it if it is. | 4172 // and box it if it is. |
4173 if (ReceiverMightBeValue()) { | 4173 if (ReceiverMightBeValue()) { |
4174 // Get the receiver from the stack. | 4174 // Get the receiver from the stack. |
4175 // function, receiver [, arguments] | 4175 // function, receiver [, arguments] |
4176 Label receiver_is_value, receiver_is_js_object; | 4176 Label receiver_is_value, receiver_is_js_object; |
4177 __ ldr(r1, MemOperand(sp, argc_ * kPointerSize)); | 4177 __ ldr(r1, MemOperand(sp, argc_ * kPointerSize)); |
4178 | 4178 |
4179 // Check if receiver is a smi (which is a number value). | 4179 // Check if receiver is a smi (which is a number value). |
4180 __ BranchOnSmi(r1, &receiver_is_value); | 4180 __ JumpIfSmi(r1, &receiver_is_value); |
4181 | 4181 |
4182 // Check if the receiver is a valid JS object. | 4182 // Check if the receiver is a valid JS object. |
4183 __ CompareObjectType(r1, r2, r2, FIRST_JS_OBJECT_TYPE); | 4183 __ CompareObjectType(r1, r2, r2, FIRST_JS_OBJECT_TYPE); |
4184 __ b(ge, &receiver_is_js_object); | 4184 __ b(ge, &receiver_is_js_object); |
4185 | 4185 |
4186 // Call the runtime to box the value. | 4186 // Call the runtime to box the value. |
4187 __ bind(&receiver_is_value); | 4187 __ bind(&receiver_is_value); |
4188 __ EnterInternalFrame(); | 4188 __ EnterInternalFrame(); |
4189 __ push(r1); | 4189 __ push(r1); |
4190 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); | 4190 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS); |
4191 __ LeaveInternalFrame(); | 4191 __ LeaveInternalFrame(); |
4192 __ str(r0, MemOperand(sp, argc_ * kPointerSize)); | 4192 __ str(r0, MemOperand(sp, argc_ * kPointerSize)); |
4193 | 4193 |
4194 __ bind(&receiver_is_js_object); | 4194 __ bind(&receiver_is_js_object); |
4195 } | 4195 } |
4196 | 4196 |
4197 // Get the function to call from the stack. | 4197 // Get the function to call from the stack. |
4198 // function, receiver [, arguments] | 4198 // function, receiver [, arguments] |
4199 __ ldr(r1, MemOperand(sp, (argc_ + 1) * kPointerSize)); | 4199 __ ldr(r1, MemOperand(sp, (argc_ + 1) * kPointerSize)); |
4200 | 4200 |
4201 // Check that the function is really a JavaScript function. | 4201 // Check that the function is really a JavaScript function. |
4202 // r1: pushed function (to be verified) | 4202 // r1: pushed function (to be verified) |
4203 __ BranchOnSmi(r1, &slow); | 4203 __ JumpIfSmi(r1, &slow); |
4204 // Get the map of the function object. | 4204 // Get the map of the function object. |
4205 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 4205 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
4206 __ b(ne, &slow); | 4206 __ b(ne, &slow); |
4207 | 4207 |
4208 // Fast-case: Invoke the function now. | 4208 // Fast-case: Invoke the function now. |
4209 // r1: pushed function | 4209 // r1: pushed function |
4210 ParameterCount actual(argc_); | 4210 ParameterCount actual(argc_); |
4211 __ InvokeFunction(r1, actual, JUMP_FUNCTION); | 4211 __ InvokeFunction(r1, actual, JUMP_FUNCTION); |
4212 | 4212 |
4213 // Slow-case: Non-function called. | 4213 // Slow-case: Non-function called. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4297 } | 4297 } |
4298 | 4298 |
4299 | 4299 |
4300 // StringCharCodeAtGenerator | 4300 // StringCharCodeAtGenerator |
4301 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 4301 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
4302 Label flat_string; | 4302 Label flat_string; |
4303 Label ascii_string; | 4303 Label ascii_string; |
4304 Label got_char_code; | 4304 Label got_char_code; |
4305 | 4305 |
4306 // If the receiver is a smi trigger the non-string case. | 4306 // If the receiver is a smi trigger the non-string case. |
4307 __ BranchOnSmi(object_, receiver_not_string_); | 4307 __ JumpIfSmi(object_, receiver_not_string_); |
4308 | 4308 |
4309 // Fetch the instance type of the receiver into result register. | 4309 // Fetch the instance type of the receiver into result register. |
4310 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 4310 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
4311 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 4311 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
4312 // If the receiver is not a string trigger the non-string case. | 4312 // If the receiver is not a string trigger the non-string case. |
4313 __ tst(result_, Operand(kIsNotStringMask)); | 4313 __ tst(result_, Operand(kIsNotStringMask)); |
4314 __ b(ne, receiver_not_string_); | 4314 __ b(ne, receiver_not_string_); |
4315 | 4315 |
4316 // If the index is non-smi trigger the non-smi case. | 4316 // If the index is non-smi trigger the non-smi case. |
4317 __ BranchOnNotSmi(index_, &index_not_smi_); | 4317 __ JumpIfNotSmi(index_, &index_not_smi_); |
4318 | 4318 |
4319 // Put smi-tagged index into scratch register. | 4319 // Put smi-tagged index into scratch register. |
4320 __ mov(scratch_, index_); | 4320 __ mov(scratch_, index_); |
4321 __ bind(&got_smi_index_); | 4321 __ bind(&got_smi_index_); |
4322 | 4322 |
4323 // Check for index out of range. | 4323 // Check for index out of range. |
4324 __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset)); | 4324 __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset)); |
4325 __ cmp(ip, Operand(scratch_)); | 4325 __ cmp(ip, Operand(scratch_)); |
4326 __ b(ls, index_out_of_range_); | 4326 __ b(ls, index_out_of_range_); |
4327 | 4327 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4404 // Save the conversion result before the pop instructions below | 4404 // Save the conversion result before the pop instructions below |
4405 // have a chance to overwrite it. | 4405 // have a chance to overwrite it. |
4406 __ Move(scratch_, r0); | 4406 __ Move(scratch_, r0); |
4407 __ pop(index_); | 4407 __ pop(index_); |
4408 __ pop(object_); | 4408 __ pop(object_); |
4409 // Reload the instance type. | 4409 // Reload the instance type. |
4410 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 4410 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
4411 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 4411 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
4412 call_helper.AfterCall(masm); | 4412 call_helper.AfterCall(masm); |
4413 // If index is still not a smi, it must be out of range. | 4413 // If index is still not a smi, it must be out of range. |
4414 __ BranchOnNotSmi(scratch_, index_out_of_range_); | 4414 __ JumpIfNotSmi(scratch_, index_out_of_range_); |
4415 // Otherwise, return to the fast path. | 4415 // Otherwise, return to the fast path. |
4416 __ jmp(&got_smi_index_); | 4416 __ jmp(&got_smi_index_); |
4417 | 4417 |
4418 // Call runtime. We get here when the receiver is a string and the | 4418 // Call runtime. We get here when the receiver is a string and the |
4419 // index is a number, but the code of getting the actual character | 4419 // index is a number, but the code of getting the actual character |
4420 // is too complex (e.g., when the string needs to be flattened). | 4420 // is too complex (e.g., when the string needs to be flattened). |
4421 __ bind(&call_runtime_); | 4421 __ bind(&call_runtime_); |
4422 call_helper.BeforeCall(masm); | 4422 call_helper.BeforeCall(masm); |
4423 __ Push(object_, index_); | 4423 __ Push(object_, index_); |
4424 __ CallRuntime(Runtime::kStringCharCodeAt, 2); | 4424 __ CallRuntime(Runtime::kStringCharCodeAt, 2); |
(...skipping 1195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5620 __ pop(r1); | 5620 __ pop(r1); |
5621 __ Jump(r2); | 5621 __ Jump(r2); |
5622 } | 5622 } |
5623 | 5623 |
5624 | 5624 |
5625 #undef __ | 5625 #undef __ |
5626 | 5626 |
5627 } } // namespace v8::internal | 5627 } } // namespace v8::internal |
5628 | 5628 |
5629 #endif // V8_TARGET_ARCH_ARM | 5629 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |