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