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 |