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