OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_PPC | 5 #if V8_TARGET_ARCH_PPC |
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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 | 84 |
85 | 85 |
86 void InternalArrayNArgumentsConstructorStub::InitializeDescriptor( | 86 void InternalArrayNArgumentsConstructorStub::InitializeDescriptor( |
87 CodeStubDescriptor* descriptor) { | 87 CodeStubDescriptor* descriptor) { |
88 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1); | 88 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1); |
89 } | 89 } |
90 | 90 |
91 | 91 |
92 #define __ ACCESS_MASM(masm) | 92 #define __ ACCESS_MASM(masm) |
93 | 93 |
94 | |
95 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, | 94 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, |
96 Condition cond, Strength strength); | 95 Condition cond); |
97 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs, | 96 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs, |
98 Register rhs, Label* lhs_not_nan, | 97 Register rhs, Label* lhs_not_nan, |
99 Label* slow, bool strict); | 98 Label* slow, bool strict); |
100 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs, | 99 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs, |
101 Register rhs); | 100 Register rhs); |
102 | 101 |
103 | 102 |
104 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm, | 103 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm, |
105 ExternalReference miss) { | 104 ExternalReference miss) { |
106 // Update the static counter each time a new code stub is generated. | 105 // Update the static counter each time a new code stub is generated. |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 __ pop(scratch); | 240 __ pop(scratch); |
242 | 241 |
243 __ Ret(); | 242 __ Ret(); |
244 } | 243 } |
245 | 244 |
246 | 245 |
247 // Handle the case where the lhs and rhs are the same object. | 246 // Handle the case where the lhs and rhs are the same object. |
248 // Equality is almost reflexive (everything but NaN), so this is a test | 247 // Equality is almost reflexive (everything but NaN), so this is a test |
249 // for "identity and not NaN". | 248 // for "identity and not NaN". |
250 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, | 249 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, |
251 Condition cond, Strength strength) { | 250 Condition cond) { |
252 Label not_identical; | 251 Label not_identical; |
253 Label heap_number, return_equal; | 252 Label heap_number, return_equal; |
254 __ cmp(r3, r4); | 253 __ cmp(r3, r4); |
255 __ bne(¬_identical); | 254 __ bne(¬_identical); |
256 | 255 |
257 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), | 256 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
258 // so we do the second best thing - test it ourselves. | 257 // so we do the second best thing - test it ourselves. |
259 // They are both equal and they are not both Smis so both of them are not | 258 // They are both equal and they are not both Smis so both of them are not |
260 // Smis. If it's not a heap number, then return equal. | 259 // Smis. If it's not a heap number, then return equal. |
261 if (cond == lt || cond == gt) { | 260 if (cond == lt || cond == gt) { |
262 // Call runtime on identical JSObjects. | 261 // Call runtime on identical JSObjects. |
263 __ CompareObjectType(r3, r7, r7, FIRST_JS_RECEIVER_TYPE); | 262 __ CompareObjectType(r3, r7, r7, FIRST_JS_RECEIVER_TYPE); |
264 __ bge(slow); | 263 __ bge(slow); |
265 // Call runtime on identical symbols since we need to throw a TypeError. | 264 // Call runtime on identical symbols since we need to throw a TypeError. |
266 __ cmpi(r7, Operand(SYMBOL_TYPE)); | 265 __ cmpi(r7, Operand(SYMBOL_TYPE)); |
267 __ beq(slow); | 266 __ beq(slow); |
268 // Call runtime on identical SIMD values since we must throw a TypeError. | 267 // Call runtime on identical SIMD values since we must throw a TypeError. |
269 __ cmpi(r7, Operand(SIMD128_VALUE_TYPE)); | 268 __ cmpi(r7, Operand(SIMD128_VALUE_TYPE)); |
270 __ beq(slow); | 269 __ beq(slow); |
271 if (is_strong(strength)) { | |
272 // Call the runtime on anything that is converted in the semantics, since | |
273 // we need to throw a TypeError. Smis have already been ruled out. | |
274 __ cmpi(r7, Operand(HEAP_NUMBER_TYPE)); | |
275 __ beq(&return_equal); | |
276 __ andi(r0, r7, Operand(kIsNotStringMask)); | |
277 __ bne(slow, cr0); | |
278 } | |
279 } else { | 270 } else { |
280 __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE); | 271 __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE); |
281 __ beq(&heap_number); | 272 __ beq(&heap_number); |
282 // Comparing JS objects with <=, >= is complicated. | 273 // Comparing JS objects with <=, >= is complicated. |
283 if (cond != eq) { | 274 if (cond != eq) { |
284 __ cmpi(r7, Operand(FIRST_JS_RECEIVER_TYPE)); | 275 __ cmpi(r7, Operand(FIRST_JS_RECEIVER_TYPE)); |
285 __ bge(slow); | 276 __ bge(slow); |
286 // Call runtime on identical symbols since we need to throw a TypeError. | 277 // Call runtime on identical symbols since we need to throw a TypeError. |
287 __ cmpi(r7, Operand(SYMBOL_TYPE)); | 278 __ cmpi(r7, Operand(SYMBOL_TYPE)); |
288 __ beq(slow); | 279 __ beq(slow); |
289 // Call runtime on identical SIMD values since we must throw a TypeError. | 280 // Call runtime on identical SIMD values since we must throw a TypeError. |
290 __ cmpi(r7, Operand(SIMD128_VALUE_TYPE)); | 281 __ cmpi(r7, Operand(SIMD128_VALUE_TYPE)); |
291 __ beq(slow); | 282 __ beq(slow); |
292 if (is_strong(strength)) { | |
293 // Call the runtime on anything that is converted in the semantics, | |
294 // since we need to throw a TypeError. Smis and heap numbers have | |
295 // already been ruled out. | |
296 __ andi(r0, r7, Operand(kIsNotStringMask)); | |
297 __ bne(slow, cr0); | |
298 } | |
299 // Normally here we fall through to return_equal, but undefined is | 283 // Normally here we fall through to return_equal, but undefined is |
300 // special: (undefined == undefined) == true, but | 284 // special: (undefined == undefined) == true, but |
301 // (undefined <= undefined) == false! See ECMAScript 11.8.5. | 285 // (undefined <= undefined) == false! See ECMAScript 11.8.5. |
302 if (cond == le || cond == ge) { | 286 if (cond == le || cond == ge) { |
303 __ cmpi(r7, Operand(ODDBALL_TYPE)); | 287 __ cmpi(r7, Operand(ODDBALL_TYPE)); |
304 __ bne(&return_equal); | 288 __ bne(&return_equal); |
305 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | 289 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
306 __ cmp(r3, r5); | 290 __ cmp(r3, r5); |
307 __ bne(&return_equal); | 291 __ bne(&return_equal); |
308 if (cond == le) { | 292 if (cond == le) { |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 __ SmiUntag(r3); | 586 __ SmiUntag(r3); |
603 __ sub(r3, r4, r3); | 587 __ sub(r3, r4, r3); |
604 __ Ret(); | 588 __ Ret(); |
605 __ bind(¬_two_smis); | 589 __ bind(¬_two_smis); |
606 | 590 |
607 // NOTICE! This code is only reached after a smi-fast-case check, so | 591 // NOTICE! This code is only reached after a smi-fast-case check, so |
608 // it is certain that at least one operand isn't a smi. | 592 // it is certain that at least one operand isn't a smi. |
609 | 593 |
610 // Handle the case where the objects are identical. Either returns the answer | 594 // Handle the case where the objects are identical. Either returns the answer |
611 // or goes to slow. Only falls through if the objects were not identical. | 595 // or goes to slow. Only falls through if the objects were not identical. |
612 EmitIdenticalObjectComparison(masm, &slow, cc, strength()); | 596 EmitIdenticalObjectComparison(masm, &slow, cc); |
613 | 597 |
614 // If either is a Smi (we know that not both are), then they can only | 598 // If either is a Smi (we know that not both are), then they can only |
615 // be strictly equal if the other is a HeapNumber. | 599 // be strictly equal if the other is a HeapNumber. |
616 STATIC_ASSERT(kSmiTag == 0); | 600 STATIC_ASSERT(kSmiTag == 0); |
617 DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); | 601 DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); |
618 __ and_(r5, lhs, rhs); | 602 __ and_(r5, lhs, rhs); |
619 __ JumpIfNotSmi(r5, ¬_smis); | 603 __ JumpIfNotSmi(r5, ¬_smis); |
620 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: | 604 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: |
621 // 1) Return the answer. | 605 // 1) Return the answer. |
622 // 2) Go to slow. | 606 // 2) Go to slow. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 ncr = GREATER; | 708 ncr = GREATER; |
725 } else { | 709 } else { |
726 DCHECK(cc == gt || cc == ge); // remaining cases | 710 DCHECK(cc == gt || cc == ge); // remaining cases |
727 ncr = LESS; | 711 ncr = LESS; |
728 } | 712 } |
729 __ LoadSmiLiteral(r3, Smi::FromInt(ncr)); | 713 __ LoadSmiLiteral(r3, Smi::FromInt(ncr)); |
730 __ push(r3); | 714 __ push(r3); |
731 | 715 |
732 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 716 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
733 // tagged as a small integer. | 717 // tagged as a small integer. |
734 __ TailCallRuntime(is_strong(strength()) ? Runtime::kCompare_Strong | 718 __ TailCallRuntime(Runtime::kCompare); |
735 : Runtime::kCompare); | |
736 } | 719 } |
737 | 720 |
738 __ bind(&miss); | 721 __ bind(&miss); |
739 GenerateMiss(masm); | 722 GenerateMiss(masm); |
740 } | 723 } |
741 | 724 |
742 | 725 |
743 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 726 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
744 // We don't allow a GC during a store buffer overflow so there is no need to | 727 // We don't allow a GC during a store buffer overflow so there is no need to |
745 // store the registers in any particular way, but we do have to store and | 728 // store the registers in any particular way, but we do have to store and |
(...skipping 2272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3018 __ TailCallStub(&stub); | 3001 __ TailCallStub(&stub); |
3019 } | 3002 } |
3020 | 3003 |
3021 | 3004 |
3022 void CompareICStub::GenerateBooleans(MacroAssembler* masm) { | 3005 void CompareICStub::GenerateBooleans(MacroAssembler* masm) { |
3023 DCHECK_EQ(CompareICState::BOOLEAN, state()); | 3006 DCHECK_EQ(CompareICState::BOOLEAN, state()); |
3024 Label miss; | 3007 Label miss; |
3025 | 3008 |
3026 __ CheckMap(r4, r5, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); | 3009 __ CheckMap(r4, r5, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); |
3027 __ CheckMap(r3, r6, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); | 3010 __ CheckMap(r3, r6, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); |
3028 if (op() != Token::EQ_STRICT && is_strong(strength())) { | 3011 if (!Token::IsEqualityOp(op())) { |
3029 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | 3012 __ LoadP(r4, FieldMemOperand(r4, Oddball::kToNumberOffset)); |
3030 } else { | 3013 __ AssertSmi(r4); |
3031 if (!Token::IsEqualityOp(op())) { | 3014 __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset)); |
3032 __ LoadP(r4, FieldMemOperand(r4, Oddball::kToNumberOffset)); | 3015 __ AssertSmi(r3); |
3033 __ AssertSmi(r4); | |
3034 __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset)); | |
3035 __ AssertSmi(r3); | |
3036 } | |
3037 __ sub(r3, r4, r3); | |
3038 __ Ret(); | |
3039 } | 3016 } |
| 3017 __ sub(r3, r4, r3); |
| 3018 __ Ret(); |
3040 | 3019 |
3041 __ bind(&miss); | 3020 __ bind(&miss); |
3042 GenerateMiss(masm); | 3021 GenerateMiss(masm); |
3043 } | 3022 } |
3044 | 3023 |
3045 | 3024 |
3046 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 3025 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3047 DCHECK(state() == CompareICState::SMI); | 3026 DCHECK(state() == CompareICState::SMI); |
3048 Label miss; | 3027 Label miss; |
3049 __ orx(r5, r4, r3); | 3028 __ orx(r5, r4, r3); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3127 __ bind(&equal); | 3106 __ bind(&equal); |
3128 __ li(r3, Operand(EQUAL)); | 3107 __ li(r3, Operand(EQUAL)); |
3129 __ Ret(); | 3108 __ Ret(); |
3130 __ bind(&less_than); | 3109 __ bind(&less_than); |
3131 __ li(r3, Operand(LESS)); | 3110 __ li(r3, Operand(LESS)); |
3132 __ Ret(); | 3111 __ Ret(); |
3133 } | 3112 } |
3134 | 3113 |
3135 __ bind(&unordered); | 3114 __ bind(&unordered); |
3136 __ bind(&generic_stub); | 3115 __ bind(&generic_stub); |
3137 CompareICStub stub(isolate(), op(), strength(), CompareICState::GENERIC, | 3116 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3138 CompareICState::GENERIC, CompareICState::GENERIC); | 3117 CompareICState::GENERIC, CompareICState::GENERIC); |
3139 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3118 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
3140 | 3119 |
3141 __ bind(&maybe_undefined1); | 3120 __ bind(&maybe_undefined1); |
3142 if (Token::IsOrderedRelationalCompareOp(op())) { | 3121 if (Token::IsOrderedRelationalCompareOp(op())) { |
3143 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); | 3122 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); |
3144 __ bne(&miss); | 3123 __ bne(&miss); |
3145 __ JumpIfSmi(r4, &unordered); | 3124 __ JumpIfSmi(r4, &unordered); |
3146 __ CompareObjectType(r4, r5, r5, HEAP_NUMBER_TYPE); | 3125 __ CompareObjectType(r4, r5, r5, HEAP_NUMBER_TYPE); |
3147 __ bne(&maybe_undefined2); | 3126 __ bne(&maybe_undefined2); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3350 __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset)); | 3329 __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset)); |
3351 __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset)); | 3330 __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset)); |
3352 __ cmp(r5, r7); | 3331 __ cmp(r5, r7); |
3353 __ bne(&miss); | 3332 __ bne(&miss); |
3354 __ cmp(r6, r7); | 3333 __ cmp(r6, r7); |
3355 __ bne(&miss); | 3334 __ bne(&miss); |
3356 | 3335 |
3357 if (Token::IsEqualityOp(op())) { | 3336 if (Token::IsEqualityOp(op())) { |
3358 __ sub(r3, r3, r4); | 3337 __ sub(r3, r3, r4); |
3359 __ Ret(); | 3338 __ Ret(); |
3360 } else if (is_strong(strength())) { | |
3361 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | |
3362 } else { | 3339 } else { |
3363 if (op() == Token::LT || op() == Token::LTE) { | 3340 if (op() == Token::LT || op() == Token::LTE) { |
3364 __ LoadSmiLiteral(r5, Smi::FromInt(GREATER)); | 3341 __ LoadSmiLiteral(r5, Smi::FromInt(GREATER)); |
3365 } else { | 3342 } else { |
3366 __ LoadSmiLiteral(r5, Smi::FromInt(LESS)); | 3343 __ LoadSmiLiteral(r5, Smi::FromInt(LESS)); |
3367 } | 3344 } |
3368 __ Push(r4, r3, r5); | 3345 __ Push(r4, r3, r5); |
3369 __ TailCallRuntime(Runtime::kCompare); | 3346 __ TailCallRuntime(Runtime::kCompare); |
3370 } | 3347 } |
3371 | 3348 |
(...skipping 2384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5756 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, | 5733 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
5757 kStackUnwindSpace, NULL, return_value_operand, NULL); | 5734 kStackUnwindSpace, NULL, return_value_operand, NULL); |
5758 } | 5735 } |
5759 | 5736 |
5760 | 5737 |
5761 #undef __ | 5738 #undef __ |
5762 } // namespace internal | 5739 } // namespace internal |
5763 } // namespace v8 | 5740 } // namespace v8 |
5764 | 5741 |
5765 #endif // V8_TARGET_ARCH_PPC | 5742 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |