| 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 #if V8_TARGET_ARCH_ARM | 5 #if V8_TARGET_ARCH_ARM |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 | 85 |
| 86 | 86 |
| 87 void InternalArrayNArgumentsConstructorStub::InitializeDescriptor( | 87 void InternalArrayNArgumentsConstructorStub::InitializeDescriptor( |
| 88 CodeStubDescriptor* descriptor) { | 88 CodeStubDescriptor* descriptor) { |
| 89 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1); | 89 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1); |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 #define __ ACCESS_MASM(masm) | 93 #define __ ACCESS_MASM(masm) |
| 94 | 94 |
| 95 | |
| 96 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, | 95 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, |
| 97 Condition cond, Strength strength); | 96 Condition cond); |
| 98 static void EmitSmiNonsmiComparison(MacroAssembler* masm, | 97 static void EmitSmiNonsmiComparison(MacroAssembler* masm, |
| 99 Register lhs, | 98 Register lhs, |
| 100 Register rhs, | 99 Register rhs, |
| 101 Label* lhs_not_nan, | 100 Label* lhs_not_nan, |
| 102 Label* slow, | 101 Label* slow, |
| 103 bool strict); | 102 bool strict); |
| 104 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, | 103 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, |
| 105 Register lhs, | 104 Register lhs, |
| 106 Register rhs); | 105 Register rhs); |
| 107 | 106 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 | 230 |
| 232 __ Pop(scratch_high, scratch_low, scratch); | 231 __ Pop(scratch_high, scratch_low, scratch); |
| 233 __ Ret(); | 232 __ Ret(); |
| 234 } | 233 } |
| 235 | 234 |
| 236 | 235 |
| 237 // Handle the case where the lhs and rhs are the same object. | 236 // Handle the case where the lhs and rhs are the same object. |
| 238 // Equality is almost reflexive (everything but NaN), so this is a test | 237 // Equality is almost reflexive (everything but NaN), so this is a test |
| 239 // for "identity and not NaN". | 238 // for "identity and not NaN". |
| 240 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, | 239 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, |
| 241 Condition cond, Strength strength) { | 240 Condition cond) { |
| 242 Label not_identical; | 241 Label not_identical; |
| 243 Label heap_number, return_equal; | 242 Label heap_number, return_equal; |
| 244 __ cmp(r0, r1); | 243 __ cmp(r0, r1); |
| 245 __ b(ne, ¬_identical); | 244 __ b(ne, ¬_identical); |
| 246 | 245 |
| 247 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), | 246 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
| 248 // so we do the second best thing - test it ourselves. | 247 // so we do the second best thing - test it ourselves. |
| 249 // They are both equal and they are not both Smis so both of them are not | 248 // They are both equal and they are not both Smis so both of them are not |
| 250 // Smis. If it's not a heap number, then return equal. | 249 // Smis. If it's not a heap number, then return equal. |
| 251 if (cond == lt || cond == gt) { | 250 if (cond == lt || cond == gt) { |
| 252 // Call runtime on identical JSObjects. | 251 // Call runtime on identical JSObjects. |
| 253 __ CompareObjectType(r0, r4, r4, FIRST_JS_RECEIVER_TYPE); | 252 __ CompareObjectType(r0, r4, r4, FIRST_JS_RECEIVER_TYPE); |
| 254 __ b(ge, slow); | 253 __ b(ge, slow); |
| 255 // Call runtime on identical symbols since we need to throw a TypeError. | 254 // Call runtime on identical symbols since we need to throw a TypeError. |
| 256 __ cmp(r4, Operand(SYMBOL_TYPE)); | 255 __ cmp(r4, Operand(SYMBOL_TYPE)); |
| 257 __ b(eq, slow); | 256 __ b(eq, slow); |
| 258 // Call runtime on identical SIMD values since we must throw a TypeError. | 257 // Call runtime on identical SIMD values since we must throw a TypeError. |
| 259 __ cmp(r4, Operand(SIMD128_VALUE_TYPE)); | 258 __ cmp(r4, Operand(SIMD128_VALUE_TYPE)); |
| 260 __ b(eq, slow); | 259 __ b(eq, slow); |
| 261 if (is_strong(strength)) { | |
| 262 // Call the runtime on anything that is converted in the semantics, since | |
| 263 // we need to throw a TypeError. Smis have already been ruled out. | |
| 264 __ cmp(r4, Operand(HEAP_NUMBER_TYPE)); | |
| 265 __ b(eq, &return_equal); | |
| 266 __ tst(r4, Operand(kIsNotStringMask)); | |
| 267 __ b(ne, slow); | |
| 268 } | |
| 269 } else { | 260 } else { |
| 270 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); | 261 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); |
| 271 __ b(eq, &heap_number); | 262 __ b(eq, &heap_number); |
| 272 // Comparing JS objects with <=, >= is complicated. | 263 // Comparing JS objects with <=, >= is complicated. |
| 273 if (cond != eq) { | 264 if (cond != eq) { |
| 274 __ cmp(r4, Operand(FIRST_JS_RECEIVER_TYPE)); | 265 __ cmp(r4, Operand(FIRST_JS_RECEIVER_TYPE)); |
| 275 __ b(ge, slow); | 266 __ b(ge, slow); |
| 276 // Call runtime on identical symbols since we need to throw a TypeError. | 267 // Call runtime on identical symbols since we need to throw a TypeError. |
| 277 __ cmp(r4, Operand(SYMBOL_TYPE)); | 268 __ cmp(r4, Operand(SYMBOL_TYPE)); |
| 278 __ b(eq, slow); | 269 __ b(eq, slow); |
| 279 // Call runtime on identical SIMD values since we must throw a TypeError. | 270 // Call runtime on identical SIMD values since we must throw a TypeError. |
| 280 __ cmp(r4, Operand(SIMD128_VALUE_TYPE)); | 271 __ cmp(r4, Operand(SIMD128_VALUE_TYPE)); |
| 281 __ b(eq, slow); | 272 __ b(eq, slow); |
| 282 if (is_strong(strength)) { | |
| 283 // Call the runtime on anything that is converted in the semantics, | |
| 284 // since we need to throw a TypeError. Smis and heap numbers have | |
| 285 // already been ruled out. | |
| 286 __ tst(r4, Operand(kIsNotStringMask)); | |
| 287 __ b(ne, slow); | |
| 288 } | |
| 289 // Normally here we fall through to return_equal, but undefined is | 273 // Normally here we fall through to return_equal, but undefined is |
| 290 // special: (undefined == undefined) == true, but | 274 // special: (undefined == undefined) == true, but |
| 291 // (undefined <= undefined) == false! See ECMAScript 11.8.5. | 275 // (undefined <= undefined) == false! See ECMAScript 11.8.5. |
| 292 if (cond == le || cond == ge) { | 276 if (cond == le || cond == ge) { |
| 293 __ cmp(r4, Operand(ODDBALL_TYPE)); | 277 __ cmp(r4, Operand(ODDBALL_TYPE)); |
| 294 __ b(ne, &return_equal); | 278 __ b(ne, &return_equal); |
| 295 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 279 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
| 296 __ cmp(r0, r2); | 280 __ cmp(r0, r2); |
| 297 __ b(ne, &return_equal); | 281 __ b(ne, &return_equal); |
| 298 if (cond == le) { | 282 if (cond == le) { |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 __ mov(r1, Operand(r1, ASR, 1)); | 568 __ mov(r1, Operand(r1, ASR, 1)); |
| 585 __ sub(r0, r1, Operand(r0, ASR, 1)); | 569 __ sub(r0, r1, Operand(r0, ASR, 1)); |
| 586 __ Ret(); | 570 __ Ret(); |
| 587 __ bind(¬_two_smis); | 571 __ bind(¬_two_smis); |
| 588 | 572 |
| 589 // NOTICE! This code is only reached after a smi-fast-case check, so | 573 // NOTICE! This code is only reached after a smi-fast-case check, so |
| 590 // it is certain that at least one operand isn't a smi. | 574 // it is certain that at least one operand isn't a smi. |
| 591 | 575 |
| 592 // Handle the case where the objects are identical. Either returns the answer | 576 // Handle the case where the objects are identical. Either returns the answer |
| 593 // or goes to slow. Only falls through if the objects were not identical. | 577 // or goes to slow. Only falls through if the objects were not identical. |
| 594 EmitIdenticalObjectComparison(masm, &slow, cc, strength()); | 578 EmitIdenticalObjectComparison(masm, &slow, cc); |
| 595 | 579 |
| 596 // If either is a Smi (we know that not both are), then they can only | 580 // If either is a Smi (we know that not both are), then they can only |
| 597 // be strictly equal if the other is a HeapNumber. | 581 // be strictly equal if the other is a HeapNumber. |
| 598 STATIC_ASSERT(kSmiTag == 0); | 582 STATIC_ASSERT(kSmiTag == 0); |
| 599 DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); | 583 DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); |
| 600 __ and_(r2, lhs, Operand(rhs)); | 584 __ and_(r2, lhs, Operand(rhs)); |
| 601 __ JumpIfNotSmi(r2, ¬_smis); | 585 __ JumpIfNotSmi(r2, ¬_smis); |
| 602 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: | 586 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: |
| 603 // 1) Return the answer. | 587 // 1) Return the answer. |
| 604 // 2) Go to slow. | 588 // 2) Go to slow. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 ncr = GREATER; | 681 ncr = GREATER; |
| 698 } else { | 682 } else { |
| 699 DCHECK(cc == gt || cc == ge); // remaining cases | 683 DCHECK(cc == gt || cc == ge); // remaining cases |
| 700 ncr = LESS; | 684 ncr = LESS; |
| 701 } | 685 } |
| 702 __ mov(r0, Operand(Smi::FromInt(ncr))); | 686 __ mov(r0, Operand(Smi::FromInt(ncr))); |
| 703 __ push(r0); | 687 __ push(r0); |
| 704 | 688 |
| 705 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 689 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
| 706 // tagged as a small integer. | 690 // tagged as a small integer. |
| 707 __ TailCallRuntime(is_strong(strength()) ? Runtime::kCompare_Strong | 691 __ TailCallRuntime(Runtime::kCompare); |
| 708 : Runtime::kCompare); | |
| 709 } | 692 } |
| 710 | 693 |
| 711 __ bind(&miss); | 694 __ bind(&miss); |
| 712 GenerateMiss(masm); | 695 GenerateMiss(masm); |
| 713 } | 696 } |
| 714 | 697 |
| 715 | 698 |
| 716 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 699 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
| 717 // We don't allow a GC during a store buffer overflow so there is no need to | 700 // We don't allow a GC during a store buffer overflow so there is no need to |
| 718 // store the registers in any particular way, but we do have to store and | 701 // store the registers in any particular way, but we do have to store and |
| (...skipping 2206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2925 __ TailCallStub(&stub); | 2908 __ TailCallStub(&stub); |
| 2926 } | 2909 } |
| 2927 | 2910 |
| 2928 | 2911 |
| 2929 void CompareICStub::GenerateBooleans(MacroAssembler* masm) { | 2912 void CompareICStub::GenerateBooleans(MacroAssembler* masm) { |
| 2930 DCHECK_EQ(CompareICState::BOOLEAN, state()); | 2913 DCHECK_EQ(CompareICState::BOOLEAN, state()); |
| 2931 Label miss; | 2914 Label miss; |
| 2932 | 2915 |
| 2933 __ CheckMap(r1, r2, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); | 2916 __ CheckMap(r1, r2, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); |
| 2934 __ CheckMap(r0, r3, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); | 2917 __ CheckMap(r0, r3, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); |
| 2935 if (op() != Token::EQ_STRICT && is_strong(strength())) { | 2918 if (!Token::IsEqualityOp(op())) { |
| 2936 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | 2919 __ ldr(r1, FieldMemOperand(r1, Oddball::kToNumberOffset)); |
| 2937 } else { | 2920 __ AssertSmi(r1); |
| 2938 if (!Token::IsEqualityOp(op())) { | 2921 __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset)); |
| 2939 __ ldr(r1, FieldMemOperand(r1, Oddball::kToNumberOffset)); | 2922 __ AssertSmi(r0); |
| 2940 __ AssertSmi(r1); | |
| 2941 __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset)); | |
| 2942 __ AssertSmi(r0); | |
| 2943 } | |
| 2944 __ sub(r0, r1, r0); | |
| 2945 __ Ret(); | |
| 2946 } | 2923 } |
| 2924 __ sub(r0, r1, r0); |
| 2925 __ Ret(); |
| 2947 | 2926 |
| 2948 __ bind(&miss); | 2927 __ bind(&miss); |
| 2949 GenerateMiss(masm); | 2928 GenerateMiss(masm); |
| 2950 } | 2929 } |
| 2951 | 2930 |
| 2952 | 2931 |
| 2953 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 2932 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
| 2954 DCHECK(state() == CompareICState::SMI); | 2933 DCHECK(state() == CompareICState::SMI); |
| 2955 Label miss; | 2934 Label miss; |
| 2956 __ orr(r2, r1, r0); | 2935 __ orr(r2, r1, r0); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3016 __ b(vs, &unordered); | 2995 __ b(vs, &unordered); |
| 3017 | 2996 |
| 3018 // Return a result of -1, 0, or 1, based on status bits. | 2997 // Return a result of -1, 0, or 1, based on status bits. |
| 3019 __ mov(r0, Operand(EQUAL), LeaveCC, eq); | 2998 __ mov(r0, Operand(EQUAL), LeaveCC, eq); |
| 3020 __ mov(r0, Operand(LESS), LeaveCC, lt); | 2999 __ mov(r0, Operand(LESS), LeaveCC, lt); |
| 3021 __ mov(r0, Operand(GREATER), LeaveCC, gt); | 3000 __ mov(r0, Operand(GREATER), LeaveCC, gt); |
| 3022 __ Ret(); | 3001 __ Ret(); |
| 3023 | 3002 |
| 3024 __ bind(&unordered); | 3003 __ bind(&unordered); |
| 3025 __ bind(&generic_stub); | 3004 __ bind(&generic_stub); |
| 3026 CompareICStub stub(isolate(), op(), strength(), CompareICState::GENERIC, | 3005 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
| 3027 CompareICState::GENERIC, CompareICState::GENERIC); | 3006 CompareICState::GENERIC, CompareICState::GENERIC); |
| 3028 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3007 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 3029 | 3008 |
| 3030 __ bind(&maybe_undefined1); | 3009 __ bind(&maybe_undefined1); |
| 3031 if (Token::IsOrderedRelationalCompareOp(op())) { | 3010 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3032 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); | 3011 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); |
| 3033 __ b(ne, &miss); | 3012 __ b(ne, &miss); |
| 3034 __ JumpIfSmi(r1, &unordered); | 3013 __ JumpIfSmi(r1, &unordered); |
| 3035 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); | 3014 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); |
| 3036 __ b(ne, &maybe_undefined2); | 3015 __ b(ne, &maybe_undefined2); |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3234 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 3213 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 3235 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3214 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 3236 __ cmp(r2, r4); | 3215 __ cmp(r2, r4); |
| 3237 __ b(ne, &miss); | 3216 __ b(ne, &miss); |
| 3238 __ cmp(r3, r4); | 3217 __ cmp(r3, r4); |
| 3239 __ b(ne, &miss); | 3218 __ b(ne, &miss); |
| 3240 | 3219 |
| 3241 if (Token::IsEqualityOp(op())) { | 3220 if (Token::IsEqualityOp(op())) { |
| 3242 __ sub(r0, r0, Operand(r1)); | 3221 __ sub(r0, r0, Operand(r1)); |
| 3243 __ Ret(); | 3222 __ Ret(); |
| 3244 } else if (is_strong(strength())) { | |
| 3245 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | |
| 3246 } else { | 3223 } else { |
| 3247 if (op() == Token::LT || op() == Token::LTE) { | 3224 if (op() == Token::LT || op() == Token::LTE) { |
| 3248 __ mov(r2, Operand(Smi::FromInt(GREATER))); | 3225 __ mov(r2, Operand(Smi::FromInt(GREATER))); |
| 3249 } else { | 3226 } else { |
| 3250 __ mov(r2, Operand(Smi::FromInt(LESS))); | 3227 __ mov(r2, Operand(Smi::FromInt(LESS))); |
| 3251 } | 3228 } |
| 3252 __ Push(r1, r0, r2); | 3229 __ Push(r1, r0, r2); |
| 3253 __ TailCallRuntime(Runtime::kCompare); | 3230 __ TailCallRuntime(Runtime::kCompare); |
| 3254 } | 3231 } |
| 3255 | 3232 |
| (...skipping 2254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5510 kStackUnwindSpace, NULL, return_value_operand, NULL); | 5487 kStackUnwindSpace, NULL, return_value_operand, NULL); |
| 5511 } | 5488 } |
| 5512 | 5489 |
| 5513 | 5490 |
| 5514 #undef __ | 5491 #undef __ |
| 5515 | 5492 |
| 5516 } // namespace internal | 5493 } // namespace internal |
| 5517 } // namespace v8 | 5494 } // namespace v8 |
| 5518 | 5495 |
| 5519 #endif // V8_TARGET_ARCH_ARM | 5496 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |