| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_PPC | 7 #if V8_TARGET_ARCH_PPC |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 | 150 |
| 151 // Do fast-path convert from double to int. | 151 // Do fast-path convert from double to int. |
| 152 __ ConvertDoubleToInt64(double_scratch, | 152 __ ConvertDoubleToInt64(double_scratch, |
| 153 #if !V8_TARGET_ARCH_PPC64 | 153 #if !V8_TARGET_ARCH_PPC64 |
| 154 scratch, | 154 scratch, |
| 155 #endif | 155 #endif |
| 156 result_reg, d0); | 156 result_reg, d0); |
| 157 | 157 |
| 158 // Test for overflow | 158 // Test for overflow |
| 159 #if V8_TARGET_ARCH_PPC64 | 159 #if V8_TARGET_ARCH_PPC64 |
| 160 __ TestIfInt32(result_reg, scratch, r0); | 160 __ TestIfInt32(result_reg, r0); |
| 161 #else | 161 #else |
| 162 __ TestIfInt32(scratch, result_reg, r0); | 162 __ TestIfInt32(scratch, result_reg, r0); |
| 163 #endif | 163 #endif |
| 164 __ beq(&fastpath_done); | 164 __ beq(&fastpath_done); |
| 165 } | 165 } |
| 166 | 166 |
| 167 __ Push(scratch_high, scratch_low); | 167 __ Push(scratch_high, scratch_low); |
| 168 // Account for saved regs if input is sp. | 168 // Account for saved regs if input is sp. |
| 169 if (input_reg.is(sp)) double_offset += 2 * kPointerSize; | 169 if (input_reg.is(sp)) double_offset += 2 * kPointerSize; |
| 170 | 170 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 __ slwi(r5, r5, Operand(HeapNumber::kNonMantissaBitsInTopWord)); | 321 __ slwi(r5, r5, Operand(HeapNumber::kNonMantissaBitsInTopWord)); |
| 322 // Or with all low-bits of mantissa. | 322 // Or with all low-bits of mantissa. |
| 323 __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); | 323 __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); |
| 324 __ orx(r3, r6, r5); | 324 __ orx(r3, r6, r5); |
| 325 __ cmpi(r3, Operand::Zero()); | 325 __ cmpi(r3, Operand::Zero()); |
| 326 // For equal we already have the right value in r3: Return zero (equal) | 326 // For equal we already have the right value in r3: Return zero (equal) |
| 327 // if all bits in mantissa are zero (it's an Infinity) and non-zero if | 327 // if all bits in mantissa are zero (it's an Infinity) and non-zero if |
| 328 // not (it's a NaN). For <= and >= we need to load r0 with the failing | 328 // not (it's a NaN). For <= and >= we need to load r0 with the failing |
| 329 // value if it's a NaN. | 329 // value if it's a NaN. |
| 330 if (cond != eq) { | 330 if (cond != eq) { |
| 331 Label not_equal; | 331 if (CpuFeatures::IsSupported(ISELECT)) { |
| 332 __ bne(¬_equal); | 332 __ li(r4, Operand((cond == le) ? GREATER : LESS)); |
| 333 // All-zero means Infinity means equal. | 333 __ isel(eq, r3, r3, r4); |
| 334 __ Ret(); | |
| 335 __ bind(¬_equal); | |
| 336 if (cond == le) { | |
| 337 __ li(r3, Operand(GREATER)); // NaN <= NaN should fail. | |
| 338 } else { | 334 } else { |
| 339 __ li(r3, Operand(LESS)); // NaN >= NaN should fail. | 335 Label not_equal; |
| 336 __ bne(¬_equal); |
| 337 // All-zero means Infinity means equal. |
| 338 __ Ret(); |
| 339 __ bind(¬_equal); |
| 340 if (cond == le) { |
| 341 __ li(r3, Operand(GREATER)); // NaN <= NaN should fail. |
| 342 } else { |
| 343 __ li(r3, Operand(LESS)); // NaN >= NaN should fail. |
| 344 } |
| 340 } | 345 } |
| 341 } | 346 } |
| 342 __ Ret(); | 347 __ Ret(); |
| 343 } | 348 } |
| 344 // No fall through here. | 349 // No fall through here. |
| 345 | 350 |
| 346 __ bind(¬_identical); | 351 __ bind(¬_identical); |
| 347 } | 352 } |
| 348 | 353 |
| 349 | 354 |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 // NOTICE! This code is only reached after a smi-fast-case check, so | 569 // NOTICE! This code is only reached after a smi-fast-case check, so |
| 565 // it is certain that at least one operand isn't a smi. | 570 // it is certain that at least one operand isn't a smi. |
| 566 | 571 |
| 567 // Handle the case where the objects are identical. Either returns the answer | 572 // Handle the case where the objects are identical. Either returns the answer |
| 568 // or goes to slow. Only falls through if the objects were not identical. | 573 // or goes to slow. Only falls through if the objects were not identical. |
| 569 EmitIdenticalObjectComparison(masm, &slow, cc); | 574 EmitIdenticalObjectComparison(masm, &slow, cc); |
| 570 | 575 |
| 571 // If either is a Smi (we know that not both are), then they can only | 576 // If either is a Smi (we know that not both are), then they can only |
| 572 // be strictly equal if the other is a HeapNumber. | 577 // be strictly equal if the other is a HeapNumber. |
| 573 STATIC_ASSERT(kSmiTag == 0); | 578 STATIC_ASSERT(kSmiTag == 0); |
| 574 DCHECK_EQ(0, Smi::FromInt(0)); | 579 DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); |
| 575 __ and_(r5, lhs, rhs); | 580 __ and_(r5, lhs, rhs); |
| 576 __ JumpIfNotSmi(r5, ¬_smis); | 581 __ JumpIfNotSmi(r5, ¬_smis); |
| 577 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: | 582 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: |
| 578 // 1) Return the answer. | 583 // 1) Return the answer. |
| 579 // 2) Go to slow. | 584 // 2) Go to slow. |
| 580 // 3) Fall through to both_loaded_as_doubles. | 585 // 3) Fall through to both_loaded_as_doubles. |
| 581 // 4) Jump to lhs_not_nan. | 586 // 4) Jump to lhs_not_nan. |
| 582 // In cases 3 and 4 we have found out we were dealing with a number-number | 587 // In cases 3 and 4 we have found out we were dealing with a number-number |
| 583 // comparison. The double values of the numbers have been loaded | 588 // comparison. The double values of the numbers have been loaded |
| 584 // into d7 and d6. | 589 // into d7 and d6. |
| 585 EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict()); | 590 EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict()); |
| 586 | 591 |
| 587 __ bind(&both_loaded_as_doubles); | 592 __ bind(&both_loaded_as_doubles); |
| 588 // The arguments have been converted to doubles and stored in d6 and d7 | 593 // The arguments have been converted to doubles and stored in d6 and d7 |
| 589 __ bind(&lhs_not_nan); | 594 __ bind(&lhs_not_nan); |
| 590 Label no_nan; | 595 Label no_nan; |
| 591 __ fcmpu(d7, d6); | 596 __ fcmpu(d7, d6); |
| 592 | 597 |
| 593 Label nan, equal, less_than; | 598 Label nan, equal, less_than; |
| 594 __ bunordered(&nan); | 599 __ bunordered(&nan); |
| 595 __ beq(&equal); | 600 if (CpuFeatures::IsSupported(ISELECT)) { |
| 596 __ blt(&less_than); | 601 DCHECK(EQUAL == 0); |
| 597 __ li(r3, Operand(GREATER)); | 602 __ li(r4, Operand(GREATER)); |
| 598 __ Ret(); | 603 __ li(r5, Operand(LESS)); |
| 599 __ bind(&equal); | 604 __ isel(eq, r3, r0, r4); |
| 600 __ li(r3, Operand(EQUAL)); | 605 __ isel(lt, r3, r5, r3); |
| 601 __ Ret(); | 606 __ Ret(); |
| 602 __ bind(&less_than); | 607 } else { |
| 603 __ li(r3, Operand(LESS)); | 608 __ beq(&equal); |
| 604 __ Ret(); | 609 __ blt(&less_than); |
| 610 __ li(r3, Operand(GREATER)); |
| 611 __ Ret(); |
| 612 __ bind(&equal); |
| 613 __ li(r3, Operand(EQUAL)); |
| 614 __ Ret(); |
| 615 __ bind(&less_than); |
| 616 __ li(r3, Operand(LESS)); |
| 617 __ Ret(); |
| 618 } |
| 605 | 619 |
| 606 __ bind(&nan); | 620 __ bind(&nan); |
| 607 // If one of the sides was a NaN then the v flag is set. Load r3 with | 621 // If one of the sides was a NaN then the v flag is set. Load r3 with |
| 608 // whatever it takes to make the comparison fail, since comparisons with NaN | 622 // whatever it takes to make the comparison fail, since comparisons with NaN |
| 609 // always fail. | 623 // always fail. |
| 610 if (cc == lt || cc == le) { | 624 if (cc == lt || cc == le) { |
| 611 __ li(r3, Operand(GREATER)); | 625 __ li(r3, Operand(GREATER)); |
| 612 } else { | 626 } else { |
| 613 __ li(r3, Operand(LESS)); | 627 __ li(r3, Operand(LESS)); |
| 614 } | 628 } |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 __ mr(scratch, exponent); | 869 __ mr(scratch, exponent); |
| 856 } else { | 870 } else { |
| 857 // Exponent has previously been stored into scratch as untagged integer. | 871 // Exponent has previously been stored into scratch as untagged integer. |
| 858 __ mr(exponent, scratch); | 872 __ mr(exponent, scratch); |
| 859 } | 873 } |
| 860 __ fmr(double_scratch, double_base); // Back up base. | 874 __ fmr(double_scratch, double_base); // Back up base. |
| 861 __ li(scratch2, Operand(1)); | 875 __ li(scratch2, Operand(1)); |
| 862 __ ConvertIntToDouble(scratch2, double_result); | 876 __ ConvertIntToDouble(scratch2, double_result); |
| 863 | 877 |
| 864 // Get absolute value of exponent. | 878 // Get absolute value of exponent. |
| 865 Label positive_exponent; | |
| 866 __ cmpi(scratch, Operand::Zero()); | 879 __ cmpi(scratch, Operand::Zero()); |
| 867 __ bge(&positive_exponent); | 880 if (CpuFeatures::IsSupported(ISELECT)) { |
| 868 __ neg(scratch, scratch); | 881 __ neg(scratch2, scratch); |
| 869 __ bind(&positive_exponent); | 882 __ isel(lt, scratch, scratch2, scratch); |
| 883 } else { |
| 884 Label positive_exponent; |
| 885 __ bge(&positive_exponent); |
| 886 __ neg(scratch, scratch); |
| 887 __ bind(&positive_exponent); |
| 888 } |
| 870 | 889 |
| 871 Label while_true, no_carry, loop_end; | 890 Label while_true, no_carry, loop_end; |
| 872 __ bind(&while_true); | 891 __ bind(&while_true); |
| 873 __ andi(scratch2, scratch, Operand(1)); | 892 __ andi(scratch2, scratch, Operand(1)); |
| 874 __ beq(&no_carry, cr0); | 893 __ beq(&no_carry, cr0); |
| 875 __ fmul(double_result, double_result, double_scratch); | 894 __ fmul(double_result, double_result, double_scratch); |
| 876 __ bind(&no_carry); | 895 __ bind(&no_carry); |
| 877 __ ShiftRightArithImm(scratch, scratch, 1, SetRC); | 896 __ ShiftRightArithImm(scratch, scratch, 1, SetRC); |
| 878 __ beq(&loop_end, cr0); | 897 __ beq(&loop_end, cr0); |
| 879 __ fmul(double_scratch, double_scratch, double_scratch); | 898 __ fmul(double_scratch, double_scratch, double_scratch); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 __ Ret(); | 949 __ Ret(); |
| 931 } | 950 } |
| 932 } | 951 } |
| 933 | 952 |
| 934 | 953 |
| 935 bool CEntryStub::NeedsImmovableCode() { return true; } | 954 bool CEntryStub::NeedsImmovableCode() { return true; } |
| 936 | 955 |
| 937 | 956 |
| 938 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 957 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 939 CEntryStub::GenerateAheadOfTime(isolate); | 958 CEntryStub::GenerateAheadOfTime(isolate); |
| 940 // WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); | |
| 941 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 959 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 942 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 960 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
| 943 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | 961 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
| 944 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); | 962 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); |
| 963 CreateWeakCellStub::GenerateAheadOfTime(isolate); |
| 945 BinaryOpICStub::GenerateAheadOfTime(isolate); | 964 BinaryOpICStub::GenerateAheadOfTime(isolate); |
| 946 StoreRegistersStateStub::GenerateAheadOfTime(isolate); | 965 StoreRegistersStateStub::GenerateAheadOfTime(isolate); |
| 947 RestoreRegistersStateStub::GenerateAheadOfTime(isolate); | 966 RestoreRegistersStateStub::GenerateAheadOfTime(isolate); |
| 948 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); | 967 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); |
| 949 } | 968 } |
| 950 | 969 |
| 951 | 970 |
| 952 void StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { | 971 void StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { |
| 953 StoreRegistersStateStub stub(isolate); | 972 StoreRegistersStateStub stub(isolate); |
| 954 stub.GetCode(); | 973 stub.GetCode(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 __ add(r4, r4, sp); | 1012 __ add(r4, r4, sp); |
| 994 __ subi(r4, r4, Operand(kPointerSize)); | 1013 __ subi(r4, r4, Operand(kPointerSize)); |
| 995 | 1014 |
| 996 // Enter the exit frame that transitions from JavaScript to C++. | 1015 // Enter the exit frame that transitions from JavaScript to C++. |
| 997 FrameScope scope(masm, StackFrame::MANUAL); | 1016 FrameScope scope(masm, StackFrame::MANUAL); |
| 998 | 1017 |
| 999 // Need at least one extra slot for return address location. | 1018 // Need at least one extra slot for return address location. |
| 1000 int arg_stack_space = 1; | 1019 int arg_stack_space = 1; |
| 1001 | 1020 |
| 1002 // PPC LINUX ABI: | 1021 // PPC LINUX ABI: |
| 1003 #if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS | 1022 #if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS |
| 1004 // Pass buffer for return value on stack if necessary | 1023 // Pass buffer for return value on stack if necessary |
| 1005 if (result_size() > 1) { | 1024 if (result_size() > 1) { |
| 1006 DCHECK_EQ(2, result_size()); | 1025 DCHECK_EQ(2, result_size()); |
| 1007 arg_stack_space += 2; | 1026 arg_stack_space += 2; |
| 1008 } | 1027 } |
| 1009 #endif | 1028 #endif |
| 1010 | 1029 |
| 1011 __ EnterExitFrame(save_doubles(), arg_stack_space); | 1030 __ EnterExitFrame(save_doubles(), arg_stack_space); |
| 1012 | 1031 |
| 1013 // Store a copy of argc in callee-saved registers for later. | 1032 // Store a copy of argc in callee-saved registers for later. |
| 1014 __ mr(r14, r3); | 1033 __ mr(r14, r3); |
| 1015 | 1034 |
| 1016 // r3, r14: number of arguments including receiver (C callee-saved) | 1035 // r3, r14: number of arguments including receiver (C callee-saved) |
| 1017 // r4: pointer to the first argument | 1036 // r4: pointer to the first argument |
| 1018 // r15: pointer to builtin function (C callee-saved) | 1037 // r15: pointer to builtin function (C callee-saved) |
| 1019 | 1038 |
| 1020 // Result returned in registers or stack, depending on result size and ABI. | 1039 // Result returned in registers or stack, depending on result size and ABI. |
| 1021 | 1040 |
| 1022 Register isolate_reg = r5; | 1041 Register isolate_reg = r5; |
| 1023 #if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS | 1042 #if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS |
| 1024 if (result_size() > 1) { | 1043 if (result_size() > 1) { |
| 1025 // The return value is 16-byte non-scalar value. | 1044 // The return value is 16-byte non-scalar value. |
| 1026 // Use frame storage reserved by calling function to pass return | 1045 // Use frame storage reserved by calling function to pass return |
| 1027 // buffer as implicit first argument. | 1046 // buffer as implicit first argument. |
| 1028 __ mr(r5, r4); | 1047 __ mr(r5, r4); |
| 1029 __ mr(r4, r3); | 1048 __ mr(r4, r3); |
| 1030 __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize)); | 1049 __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize)); |
| 1031 isolate_reg = r6; | 1050 isolate_reg = r6; |
| 1032 } | 1051 } |
| 1033 #endif | 1052 #endif |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1061 __ bind(&here); | 1080 __ bind(&here); |
| 1062 __ mflr(r8); | 1081 __ mflr(r8); |
| 1063 | 1082 |
| 1064 // Constant used below is dependent on size of Call() macro instructions | 1083 // Constant used below is dependent on size of Call() macro instructions |
| 1065 __ addi(r0, r8, Operand(20)); | 1084 __ addi(r0, r8, Operand(20)); |
| 1066 | 1085 |
| 1067 __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); | 1086 __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); |
| 1068 __ Call(target); | 1087 __ Call(target); |
| 1069 } | 1088 } |
| 1070 | 1089 |
| 1071 #if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS | 1090 #if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS |
| 1072 // If return value is on the stack, pop it to registers. | 1091 // If return value is on the stack, pop it to registers. |
| 1073 if (result_size() > 1) { | 1092 if (result_size() > 1) { |
| 1074 __ LoadP(r4, MemOperand(r3, kPointerSize)); | 1093 __ LoadP(r4, MemOperand(r3, kPointerSize)); |
| 1075 __ LoadP(r3, MemOperand(r3)); | 1094 __ LoadP(r3, MemOperand(r3)); |
| 1076 } | 1095 } |
| 1077 #endif | 1096 #endif |
| 1078 | 1097 |
| 1079 // Runtime functions should not return 'the hole'. Allowing it to escape may | 1098 // Runtime functions should not return 'the hole'. Allowing it to escape may |
| 1080 // lead to crashes in the IC code later. | 1099 // lead to crashes in the IC code later. |
| 1081 if (FLAG_debug_code) { | 1100 if (FLAG_debug_code) { |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1492 if (HasArgsInRegisters()) { | 1511 if (HasArgsInRegisters()) { |
| 1493 __ Push(r3, r4); | 1512 __ Push(r3, r4); |
| 1494 } | 1513 } |
| 1495 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 1514 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 1496 } else { | 1515 } else { |
| 1497 { | 1516 { |
| 1498 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 1517 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 1499 __ Push(r3, r4); | 1518 __ Push(r3, r4); |
| 1500 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); | 1519 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); |
| 1501 } | 1520 } |
| 1502 Label true_value, done; | 1521 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1503 __ cmpi(r3, Operand::Zero()); | 1522 __ cmpi(r3, Operand::Zero()); |
| 1504 __ beq(&true_value); | 1523 __ LoadRoot(r3, Heap::kTrueValueRootIndex); |
| 1524 __ LoadRoot(r4, Heap::kFalseValueRootIndex); |
| 1525 __ isel(eq, r3, r3, r4); |
| 1526 } else { |
| 1527 Label true_value, done; |
| 1528 __ cmpi(r3, Operand::Zero()); |
| 1529 __ beq(&true_value); |
| 1505 | 1530 |
| 1506 __ LoadRoot(r3, Heap::kFalseValueRootIndex); | 1531 __ LoadRoot(r3, Heap::kFalseValueRootIndex); |
| 1507 __ b(&done); | 1532 __ b(&done); |
| 1508 | 1533 |
| 1509 __ bind(&true_value); | 1534 __ bind(&true_value); |
| 1510 __ LoadRoot(r3, Heap::kTrueValueRootIndex); | 1535 __ LoadRoot(r3, Heap::kTrueValueRootIndex); |
| 1511 | 1536 |
| 1512 __ bind(&done); | 1537 __ bind(&done); |
| 1538 } |
| 1513 __ Ret(HasArgsInRegisters() ? 0 : 2); | 1539 __ Ret(HasArgsInRegisters() ? 0 : 2); |
| 1514 } | 1540 } |
| 1515 } | 1541 } |
| 1516 | 1542 |
| 1517 | 1543 |
| 1518 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { | 1544 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { |
| 1519 Label miss; | 1545 Label miss; |
| 1520 Register receiver = LoadDescriptor::ReceiverRegister(); | 1546 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 1547 // Ensure that the vector and slot registers won't be clobbered before |
| 1548 // calling the miss handler. |
| 1549 DCHECK(!FLAG_vector_ics || |
| 1550 !AreAliased(r7, r8, VectorLoadICDescriptor::VectorRegister(), |
| 1551 VectorLoadICDescriptor::SlotRegister())); |
| 1521 | 1552 |
| 1522 NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r6, | 1553 NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r7, |
| 1523 r7, &miss); | 1554 r8, &miss); |
| 1524 __ bind(&miss); | 1555 __ bind(&miss); |
| 1525 PropertyAccessCompiler::TailCallBuiltin( | 1556 PropertyAccessCompiler::TailCallBuiltin( |
| 1526 masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); | 1557 masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); |
| 1527 } | 1558 } |
| 1528 | 1559 |
| 1529 | 1560 |
| 1530 void LoadIndexedStringStub::Generate(MacroAssembler* masm) { | 1561 void LoadIndexedStringStub::Generate(MacroAssembler* masm) { |
| 1531 // Return address is in lr. | 1562 // Return address is in lr. |
| 1532 Label miss; | 1563 Label miss; |
| 1533 | 1564 |
| 1534 Register receiver = LoadDescriptor::ReceiverRegister(); | 1565 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 1535 Register index = LoadDescriptor::NameRegister(); | 1566 Register index = LoadDescriptor::NameRegister(); |
| 1536 Register scratch = r6; | 1567 Register scratch = r8; |
| 1537 Register result = r3; | 1568 Register result = r3; |
| 1538 DCHECK(!scratch.is(receiver) && !scratch.is(index)); | 1569 DCHECK(!scratch.is(receiver) && !scratch.is(index)); |
| 1570 DCHECK(!FLAG_vector_ics || |
| 1571 (!scratch.is(VectorLoadICDescriptor::VectorRegister()) && |
| 1572 result.is(VectorLoadICDescriptor::SlotRegister()))); |
| 1539 | 1573 |
| 1574 // StringCharAtGenerator doesn't use the result register until it's passed |
| 1575 // the different miss possibilities. If it did, we would have a conflict |
| 1576 // when FLAG_vector_ics is true. |
| 1540 StringCharAtGenerator char_at_generator(receiver, index, scratch, result, | 1577 StringCharAtGenerator char_at_generator(receiver, index, scratch, result, |
| 1541 &miss, // When not a string. | 1578 &miss, // When not a string. |
| 1542 &miss, // When not a number. | 1579 &miss, // When not a number. |
| 1543 &miss, // When index out of range. | 1580 &miss, // When index out of range. |
| 1544 STRING_INDEX_IS_ARRAY_INDEX, | 1581 STRING_INDEX_IS_ARRAY_INDEX, |
| 1545 RECEIVER_IS_STRING); | 1582 RECEIVER_IS_STRING); |
| 1546 char_at_generator.GenerateFast(masm); | 1583 char_at_generator.GenerateFast(masm); |
| 1547 __ Ret(); | 1584 __ Ret(); |
| 1548 | 1585 |
| 1549 StubRuntimeCallHelper call_helper; | 1586 StubRuntimeCallHelper call_helper; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1666 __ bind(&adaptor_frame); | 1703 __ bind(&adaptor_frame); |
| 1667 __ LoadP(r5, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1704 __ LoadP(r5, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 1668 __ SmiToPtrArrayOffset(r7, r5); | 1705 __ SmiToPtrArrayOffset(r7, r5); |
| 1669 __ add(r6, r6, r7); | 1706 __ add(r6, r6, r7); |
| 1670 __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset)); | 1707 __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 1671 __ StoreP(r6, MemOperand(sp, 1 * kPointerSize)); | 1708 __ StoreP(r6, MemOperand(sp, 1 * kPointerSize)); |
| 1672 | 1709 |
| 1673 // r4 = parameter count (tagged) | 1710 // r4 = parameter count (tagged) |
| 1674 // r5 = argument count (tagged) | 1711 // r5 = argument count (tagged) |
| 1675 // Compute the mapped parameter count = min(r4, r5) in r4. | 1712 // Compute the mapped parameter count = min(r4, r5) in r4. |
| 1676 Label skip; | |
| 1677 __ cmp(r4, r5); | 1713 __ cmp(r4, r5); |
| 1678 __ blt(&skip); | 1714 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1679 __ mr(r4, r5); | 1715 __ isel(lt, r4, r4, r5); |
| 1680 __ bind(&skip); | 1716 } else { |
| 1717 Label skip; |
| 1718 __ blt(&skip); |
| 1719 __ mr(r4, r5); |
| 1720 __ bind(&skip); |
| 1721 } |
| 1681 | 1722 |
| 1682 __ bind(&try_allocate); | 1723 __ bind(&try_allocate); |
| 1683 | 1724 |
| 1684 // Compute the sizes of backing store, parameter map, and arguments object. | 1725 // Compute the sizes of backing store, parameter map, and arguments object. |
| 1685 // 1. Parameter map, has 2 extra words containing context and backing store. | 1726 // 1. Parameter map, has 2 extra words containing context and backing store. |
| 1686 const int kParameterMapHeaderSize = | 1727 const int kParameterMapHeaderSize = |
| 1687 FixedArray::kHeaderSize + 2 * kPointerSize; | 1728 FixedArray::kHeaderSize + 2 * kPointerSize; |
| 1688 // If there are no mapped parameters, we do not need the parameter_map. | 1729 // If there are no mapped parameters, we do not need the parameter_map. |
| 1689 Label skip2, skip3; | |
| 1690 __ CmpSmiLiteral(r4, Smi::FromInt(0), r0); | 1730 __ CmpSmiLiteral(r4, Smi::FromInt(0), r0); |
| 1691 __ bne(&skip2); | 1731 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1692 __ li(r11, Operand::Zero()); | 1732 __ SmiToPtrArrayOffset(r11, r4); |
| 1693 __ b(&skip3); | 1733 __ addi(r11, r11, Operand(kParameterMapHeaderSize)); |
| 1694 __ bind(&skip2); | 1734 __ isel(eq, r11, r0, r11); |
| 1695 __ SmiToPtrArrayOffset(r11, r4); | 1735 } else { |
| 1696 __ addi(r11, r11, Operand(kParameterMapHeaderSize)); | 1736 Label skip2, skip3; |
| 1697 __ bind(&skip3); | 1737 __ bne(&skip2); |
| 1738 __ li(r11, Operand::Zero()); |
| 1739 __ b(&skip3); |
| 1740 __ bind(&skip2); |
| 1741 __ SmiToPtrArrayOffset(r11, r4); |
| 1742 __ addi(r11, r11, Operand(kParameterMapHeaderSize)); |
| 1743 __ bind(&skip3); |
| 1744 } |
| 1698 | 1745 |
| 1699 // 2. Backing store. | 1746 // 2. Backing store. |
| 1700 __ SmiToPtrArrayOffset(r7, r5); | 1747 __ SmiToPtrArrayOffset(r7, r5); |
| 1701 __ add(r11, r11, r7); | 1748 __ add(r11, r11, r7); |
| 1702 __ addi(r11, r11, Operand(FixedArray::kHeaderSize)); | 1749 __ addi(r11, r11, Operand(FixedArray::kHeaderSize)); |
| 1703 | 1750 |
| 1704 // 3. Arguments object. | 1751 // 3. Arguments object. |
| 1705 __ addi(r11, r11, Operand(Heap::kSloppyArgumentsObjectSize)); | 1752 __ addi(r11, r11, Operand(Heap::kSloppyArgumentsObjectSize)); |
| 1706 | 1753 |
| 1707 // Do the allocation of all three objects in one go. | 1754 // Do the allocation of all three objects in one go. |
| 1708 __ Allocate(r11, r3, r6, r7, &runtime, TAG_OBJECT); | 1755 __ Allocate(r11, r3, r6, r7, &runtime, TAG_OBJECT); |
| 1709 | 1756 |
| 1710 // r3 = address of new object(s) (tagged) | 1757 // r3 = address of new object(s) (tagged) |
| 1711 // r5 = argument count (smi-tagged) | 1758 // r5 = argument count (smi-tagged) |
| 1712 // Get the arguments boilerplate from the current native context into r4. | 1759 // Get the arguments boilerplate from the current native context into r4. |
| 1713 const int kNormalOffset = | 1760 const int kNormalOffset = |
| 1714 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); | 1761 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); |
| 1715 const int kAliasedOffset = | 1762 const int kAliasedOffset = |
| 1716 Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX); | 1763 Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX); |
| 1717 | 1764 |
| 1718 __ LoadP(r7, | 1765 __ LoadP(r7, |
| 1719 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1766 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 1720 __ LoadP(r7, FieldMemOperand(r7, GlobalObject::kNativeContextOffset)); | 1767 __ LoadP(r7, FieldMemOperand(r7, GlobalObject::kNativeContextOffset)); |
| 1721 Label skip4, skip5; | |
| 1722 __ cmpi(r4, Operand::Zero()); | 1768 __ cmpi(r4, Operand::Zero()); |
| 1723 __ bne(&skip4); | 1769 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1724 __ LoadP(r7, MemOperand(r7, kNormalOffset)); | 1770 __ LoadP(r11, MemOperand(r7, kNormalOffset)); |
| 1725 __ b(&skip5); | 1771 __ LoadP(r7, MemOperand(r7, kAliasedOffset)); |
| 1726 __ bind(&skip4); | 1772 __ isel(eq, r7, r11, r7); |
| 1727 __ LoadP(r7, MemOperand(r7, kAliasedOffset)); | 1773 } else { |
| 1728 __ bind(&skip5); | 1774 Label skip4, skip5; |
| 1775 __ bne(&skip4); |
| 1776 __ LoadP(r7, MemOperand(r7, kNormalOffset)); |
| 1777 __ b(&skip5); |
| 1778 __ bind(&skip4); |
| 1779 __ LoadP(r7, MemOperand(r7, kAliasedOffset)); |
| 1780 __ bind(&skip5); |
| 1781 } |
| 1729 | 1782 |
| 1730 // r3 = address of new object (tagged) | 1783 // r3 = address of new object (tagged) |
| 1731 // r4 = mapped parameter count (tagged) | 1784 // r4 = mapped parameter count (tagged) |
| 1732 // r5 = argument count (smi-tagged) | 1785 // r5 = argument count (smi-tagged) |
| 1733 // r7 = address of arguments map (tagged) | 1786 // r7 = address of arguments map (tagged) |
| 1734 __ StoreP(r7, FieldMemOperand(r3, JSObject::kMapOffset), r0); | 1787 __ StoreP(r7, FieldMemOperand(r3, JSObject::kMapOffset), r0); |
| 1735 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); | 1788 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); |
| 1736 __ StoreP(r6, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0); | 1789 __ StoreP(r6, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0); |
| 1737 __ StoreP(r6, FieldMemOperand(r3, JSObject::kElementsOffset), r0); | 1790 __ StoreP(r6, FieldMemOperand(r3, JSObject::kElementsOffset), r0); |
| 1738 | 1791 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1755 // If we allocated a parameter map, r7 will point there, otherwise | 1808 // If we allocated a parameter map, r7 will point there, otherwise |
| 1756 // it will point to the backing store. | 1809 // it will point to the backing store. |
| 1757 __ addi(r7, r3, Operand(Heap::kSloppyArgumentsObjectSize)); | 1810 __ addi(r7, r3, Operand(Heap::kSloppyArgumentsObjectSize)); |
| 1758 __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0); | 1811 __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0); |
| 1759 | 1812 |
| 1760 // r3 = address of new object (tagged) | 1813 // r3 = address of new object (tagged) |
| 1761 // r4 = mapped parameter count (tagged) | 1814 // r4 = mapped parameter count (tagged) |
| 1762 // r5 = argument count (tagged) | 1815 // r5 = argument count (tagged) |
| 1763 // r7 = address of parameter map or backing store (tagged) | 1816 // r7 = address of parameter map or backing store (tagged) |
| 1764 // Initialize parameter map. If there are no mapped arguments, we're done. | 1817 // Initialize parameter map. If there are no mapped arguments, we're done. |
| 1765 Label skip_parameter_map, skip6; | 1818 Label skip_parameter_map; |
| 1766 __ CmpSmiLiteral(r4, Smi::FromInt(0), r0); | 1819 __ CmpSmiLiteral(r4, Smi::FromInt(0), r0); |
| 1767 __ bne(&skip6); | 1820 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1768 // Move backing store address to r6, because it is | 1821 __ isel(eq, r6, r7, r6); |
| 1769 // expected there when filling in the unmapped arguments. | 1822 __ beq(&skip_parameter_map); |
| 1770 __ mr(r6, r7); | 1823 } else { |
| 1771 __ b(&skip_parameter_map); | 1824 Label skip6; |
| 1772 __ bind(&skip6); | 1825 __ bne(&skip6); |
| 1826 // Move backing store address to r6, because it is |
| 1827 // expected there when filling in the unmapped arguments. |
| 1828 __ mr(r6, r7); |
| 1829 __ b(&skip_parameter_map); |
| 1830 __ bind(&skip6); |
| 1831 } |
| 1773 | 1832 |
| 1774 __ LoadRoot(r9, Heap::kSloppyArgumentsElementsMapRootIndex); | 1833 __ LoadRoot(r9, Heap::kSloppyArgumentsElementsMapRootIndex); |
| 1775 __ StoreP(r9, FieldMemOperand(r7, FixedArray::kMapOffset), r0); | 1834 __ StoreP(r9, FieldMemOperand(r7, FixedArray::kMapOffset), r0); |
| 1776 __ AddSmiLiteral(r9, r4, Smi::FromInt(2), r0); | 1835 __ AddSmiLiteral(r9, r4, Smi::FromInt(2), r0); |
| 1777 __ StoreP(r9, FieldMemOperand(r7, FixedArray::kLengthOffset), r0); | 1836 __ StoreP(r9, FieldMemOperand(r7, FixedArray::kLengthOffset), r0); |
| 1778 __ StoreP(cp, FieldMemOperand(r7, FixedArray::kHeaderSize + 0 * kPointerSize), | 1837 __ StoreP(cp, FieldMemOperand(r7, FixedArray::kHeaderSize + 0 * kPointerSize), |
| 1779 r0); | 1838 r0); |
| 1780 __ SmiToPtrArrayOffset(r9, r4); | 1839 __ SmiToPtrArrayOffset(r9, r4); |
| 1781 __ add(r9, r7, r9); | 1840 __ add(r9, r7, r9); |
| 1782 __ addi(r9, r9, Operand(kParameterMapHeaderSize)); | 1841 __ addi(r9, r9, Operand(kParameterMapHeaderSize)); |
| (...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2675 GenerateRecordCallTarget(masm); | 2734 GenerateRecordCallTarget(masm); |
| 2676 | 2735 |
| 2677 __ SmiToPtrArrayOffset(r8, r6); | 2736 __ SmiToPtrArrayOffset(r8, r6); |
| 2678 __ add(r8, r5, r8); | 2737 __ add(r8, r5, r8); |
| 2679 if (FLAG_pretenuring_call_new) { | 2738 if (FLAG_pretenuring_call_new) { |
| 2680 // Put the AllocationSite from the feedback vector into r5. | 2739 // Put the AllocationSite from the feedback vector into r5. |
| 2681 // By adding kPointerSize we encode that we know the AllocationSite | 2740 // By adding kPointerSize we encode that we know the AllocationSite |
| 2682 // entry is at the feedback vector slot given by r6 + 1. | 2741 // entry is at the feedback vector slot given by r6 + 1. |
| 2683 __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize + kPointerSize)); | 2742 __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize + kPointerSize)); |
| 2684 } else { | 2743 } else { |
| 2685 Label feedback_register_initialized; | |
| 2686 // Put the AllocationSite from the feedback vector into r5, or undefined. | 2744 // Put the AllocationSite from the feedback vector into r5, or undefined. |
| 2687 __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize)); | 2745 __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize)); |
| 2688 __ LoadP(r8, FieldMemOperand(r5, AllocationSite::kMapOffset)); | 2746 __ LoadP(r8, FieldMemOperand(r5, AllocationSite::kMapOffset)); |
| 2689 __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); | 2747 __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); |
| 2690 __ beq(&feedback_register_initialized); | 2748 if (CpuFeatures::IsSupported(ISELECT)) { |
| 2691 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | 2749 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); |
| 2692 __ bind(&feedback_register_initialized); | 2750 __ isel(eq, r5, r5, r8); |
| 2751 } else { |
| 2752 Label feedback_register_initialized; |
| 2753 __ beq(&feedback_register_initialized); |
| 2754 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
| 2755 __ bind(&feedback_register_initialized); |
| 2756 } |
| 2693 } | 2757 } |
| 2694 | 2758 |
| 2695 __ AssertUndefinedOrAllocationSite(r5, r8); | 2759 __ AssertUndefinedOrAllocationSite(r5, r8); |
| 2696 } | 2760 } |
| 2697 | 2761 |
| 2762 // Pass function as original constructor. |
| 2763 __ mr(r6, r4); |
| 2764 |
| 2698 // Jump to the function-specific construct stub. | 2765 // Jump to the function-specific construct stub. |
| 2699 Register jmp_reg = r7; | 2766 Register jmp_reg = r7; |
| 2700 __ LoadP(jmp_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); | 2767 __ LoadP(jmp_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); |
| 2701 __ LoadP(jmp_reg, | 2768 __ LoadP(jmp_reg, |
| 2702 FieldMemOperand(jmp_reg, SharedFunctionInfo::kConstructStubOffset)); | 2769 FieldMemOperand(jmp_reg, SharedFunctionInfo::kConstructStubOffset)); |
| 2703 __ addi(ip, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); | 2770 __ addi(ip, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 2704 __ JumpToJSEntry(ip); | 2771 __ JumpToJSEntry(ip); |
| 2705 | 2772 |
| 2706 // r3: number of arguments | 2773 // r3: number of arguments |
| 2707 // r4: called object | 2774 // r4: called object |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2729 __ LoadP(vector, | 2796 __ LoadP(vector, |
| 2730 FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); | 2797 FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); |
| 2731 __ LoadP(vector, | 2798 __ LoadP(vector, |
| 2732 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); | 2799 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); |
| 2733 } | 2800 } |
| 2734 | 2801 |
| 2735 | 2802 |
| 2736 void CallIC_ArrayStub::Generate(MacroAssembler* masm) { | 2803 void CallIC_ArrayStub::Generate(MacroAssembler* masm) { |
| 2737 // r4 - function | 2804 // r4 - function |
| 2738 // r6 - slot id | 2805 // r6 - slot id |
| 2806 // r5 - vector |
| 2739 Label miss; | 2807 Label miss; |
| 2740 int argc = arg_count(); | 2808 int argc = arg_count(); |
| 2741 ParameterCount actual(argc); | 2809 ParameterCount actual(argc); |
| 2742 | 2810 |
| 2743 EmitLoadTypeFeedbackVector(masm, r5); | |
| 2744 | |
| 2745 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7); | 2811 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7); |
| 2746 __ cmp(r4, r7); | 2812 __ cmp(r4, r7); |
| 2747 __ bne(&miss); | 2813 __ bne(&miss); |
| 2748 | 2814 |
| 2749 __ mov(r3, Operand(arg_count())); | 2815 __ mov(r3, Operand(arg_count())); |
| 2750 __ SmiToPtrArrayOffset(r7, r6); | 2816 __ SmiToPtrArrayOffset(r7, r6); |
| 2751 __ add(r7, r5, r7); | 2817 __ add(r7, r5, r7); |
| 2752 __ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize)); | 2818 __ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize)); |
| 2753 | 2819 |
| 2754 // Verify that r7 contains an AllocationSite | 2820 // Verify that r7 contains an AllocationSite |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2767 CallFunctionNoFeedback(masm, arg_count(), true, CallAsMethod()); | 2833 CallFunctionNoFeedback(masm, arg_count(), true, CallAsMethod()); |
| 2768 | 2834 |
| 2769 // Unreachable. | 2835 // Unreachable. |
| 2770 __ stop("Unexpected code address"); | 2836 __ stop("Unexpected code address"); |
| 2771 } | 2837 } |
| 2772 | 2838 |
| 2773 | 2839 |
| 2774 void CallICStub::Generate(MacroAssembler* masm) { | 2840 void CallICStub::Generate(MacroAssembler* masm) { |
| 2775 // r4 - function | 2841 // r4 - function |
| 2776 // r6 - slot id (Smi) | 2842 // r6 - slot id (Smi) |
| 2843 // r5 - vector |
| 2844 const int with_types_offset = |
| 2845 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
| 2846 const int generic_offset = |
| 2847 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
| 2777 Label extra_checks_or_miss, slow_start; | 2848 Label extra_checks_or_miss, slow_start; |
| 2778 Label slow, non_function, wrap, cont; | 2849 Label slow, non_function, wrap, cont; |
| 2779 Label have_js_function; | 2850 Label have_js_function; |
| 2780 int argc = arg_count(); | 2851 int argc = arg_count(); |
| 2781 ParameterCount actual(argc); | 2852 ParameterCount actual(argc); |
| 2782 | 2853 |
| 2783 EmitLoadTypeFeedbackVector(masm, r5); | |
| 2784 | |
| 2785 // The checks. First, does r4 match the recorded monomorphic target? | 2854 // The checks. First, does r4 match the recorded monomorphic target? |
| 2786 __ SmiToPtrArrayOffset(r7, r6); | 2855 __ SmiToPtrArrayOffset(r7, r6); |
| 2787 __ add(r7, r5, r7); | 2856 __ add(r7, r5, r7); |
| 2788 __ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize)); | 2857 __ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize)); |
| 2789 __ cmp(r4, r7); | 2858 |
| 2859 // We don't know that we have a weak cell. We might have a private symbol |
| 2860 // or an AllocationSite, but the memory is safe to examine. |
| 2861 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to |
| 2862 // FixedArray. |
| 2863 // WeakCell::kValueOffset - contains a JSFunction or Smi(0) |
| 2864 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not |
| 2865 // computed, meaning that it can't appear to be a pointer. If the low bit is |
| 2866 // 0, then hash is computed, but the 0 bit prevents the field from appearing |
| 2867 // to be a pointer. |
| 2868 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); |
| 2869 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == |
| 2870 WeakCell::kValueOffset && |
| 2871 WeakCell::kValueOffset == Symbol::kHashFieldSlot); |
| 2872 |
| 2873 __ LoadP(r8, FieldMemOperand(r7, WeakCell::kValueOffset)); |
| 2874 __ cmp(r4, r8); |
| 2790 __ bne(&extra_checks_or_miss); | 2875 __ bne(&extra_checks_or_miss); |
| 2791 | 2876 |
| 2877 // The compare above could have been a SMI/SMI comparison. Guard against this |
| 2878 // convincing us that we have a monomorphic JSFunction. |
| 2879 __ JumpIfSmi(r4, &extra_checks_or_miss); |
| 2880 |
| 2792 __ bind(&have_js_function); | 2881 __ bind(&have_js_function); |
| 2793 if (CallAsMethod()) { | 2882 if (CallAsMethod()) { |
| 2794 EmitContinueIfStrictOrNative(masm, &cont); | 2883 EmitContinueIfStrictOrNative(masm, &cont); |
| 2795 // Compute the receiver in sloppy mode. | 2884 // Compute the receiver in sloppy mode. |
| 2796 __ LoadP(r6, MemOperand(sp, argc * kPointerSize), r0); | 2885 __ LoadP(r6, MemOperand(sp, argc * kPointerSize), r0); |
| 2797 | 2886 |
| 2798 __ JumpIfSmi(r6, &wrap); | 2887 __ JumpIfSmi(r6, &wrap); |
| 2799 __ CompareObjectType(r6, r7, r7, FIRST_SPEC_OBJECT_TYPE); | 2888 __ CompareObjectType(r6, r7, r7, FIRST_SPEC_OBJECT_TYPE); |
| 2800 __ blt(&wrap); | 2889 __ blt(&wrap); |
| 2801 | 2890 |
| 2802 __ bind(&cont); | 2891 __ bind(&cont); |
| 2803 } | 2892 } |
| 2804 | 2893 |
| 2805 __ InvokeFunction(r4, actual, JUMP_FUNCTION, NullCallWrapper()); | 2894 __ InvokeFunction(r4, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 2806 | 2895 |
| 2807 __ bind(&slow); | 2896 __ bind(&slow); |
| 2808 EmitSlowCase(masm, argc, &non_function); | 2897 EmitSlowCase(masm, argc, &non_function); |
| 2809 | 2898 |
| 2810 if (CallAsMethod()) { | 2899 if (CallAsMethod()) { |
| 2811 __ bind(&wrap); | 2900 __ bind(&wrap); |
| 2812 EmitWrapCase(masm, argc, &cont); | 2901 EmitWrapCase(masm, argc, &cont); |
| 2813 } | 2902 } |
| 2814 | 2903 |
| 2815 __ bind(&extra_checks_or_miss); | 2904 __ bind(&extra_checks_or_miss); |
| 2816 Label miss; | 2905 Label uninitialized, miss; |
| 2817 | 2906 |
| 2818 __ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex); | 2907 __ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex); |
| 2819 __ beq(&slow_start); | 2908 __ beq(&slow_start); |
| 2909 |
| 2910 // The following cases attempt to handle MISS cases without going to the |
| 2911 // runtime. |
| 2912 if (FLAG_trace_ic) { |
| 2913 __ b(&miss); |
| 2914 } |
| 2915 |
| 2820 __ CompareRoot(r7, Heap::kuninitialized_symbolRootIndex); | 2916 __ CompareRoot(r7, Heap::kuninitialized_symbolRootIndex); |
| 2917 __ beq(&uninitialized); |
| 2918 |
| 2919 // We are going megamorphic. If the feedback is a JSFunction, it is fine |
| 2920 // to handle it here. More complex cases are dealt with in the runtime. |
| 2921 __ AssertNotSmi(r7); |
| 2922 __ CompareObjectType(r7, r8, r8, JS_FUNCTION_TYPE); |
| 2923 __ bne(&miss); |
| 2924 __ SmiToPtrArrayOffset(r7, r6); |
| 2925 __ add(r7, r5, r7); |
| 2926 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); |
| 2927 __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0); |
| 2928 // We have to update statistics for runtime profiling. |
| 2929 __ LoadP(r7, FieldMemOperand(r5, with_types_offset)); |
| 2930 __ SubSmiLiteral(r7, r7, Smi::FromInt(1), r0); |
| 2931 __ StoreP(r7, FieldMemOperand(r5, with_types_offset), r0); |
| 2932 __ LoadP(r7, FieldMemOperand(r5, generic_offset)); |
| 2933 __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0); |
| 2934 __ StoreP(r7, FieldMemOperand(r5, generic_offset), r0); |
| 2935 __ b(&slow_start); |
| 2936 |
| 2937 __ bind(&uninitialized); |
| 2938 |
| 2939 // We are going monomorphic, provided we actually have a JSFunction. |
| 2940 __ JumpIfSmi(r4, &miss); |
| 2941 |
| 2942 // Goto miss case if we do not have a function. |
| 2943 __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE); |
| 2944 __ bne(&miss); |
| 2945 |
| 2946 // Make sure the function is not the Array() function, which requires special |
| 2947 // behavior on MISS. |
| 2948 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7); |
| 2949 __ cmp(r4, r7); |
| 2821 __ beq(&miss); | 2950 __ beq(&miss); |
| 2822 | 2951 |
| 2823 if (!FLAG_trace_ic) { | 2952 // Update stats. |
| 2824 // We are going megamorphic. If the feedback is a JSFunction, it is fine | 2953 __ LoadP(r7, FieldMemOperand(r5, with_types_offset)); |
| 2825 // to handle it here. More complex cases are dealt with in the runtime. | 2954 __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0); |
| 2826 __ AssertNotSmi(r7); | 2955 __ StoreP(r7, FieldMemOperand(r5, with_types_offset), r0); |
| 2827 __ CompareObjectType(r7, r8, r8, JS_FUNCTION_TYPE); | 2956 |
| 2828 __ bne(&miss); | 2957 // Store the function. Use a stub since we need a frame for allocation. |
| 2829 __ SmiToPtrArrayOffset(r7, r6); | 2958 // r5 - vector |
| 2830 __ add(r7, r5, r7); | 2959 // r6 - slot |
| 2831 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); | 2960 // r4 - function |
| 2832 __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0); | 2961 { |
| 2833 // We have to update statistics for runtime profiling. | 2962 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 2834 const int with_types_offset = | 2963 CreateWeakCellStub create_stub(masm->isolate()); |
| 2835 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | 2964 __ Push(r4); |
| 2836 __ LoadP(r7, FieldMemOperand(r5, with_types_offset)); | 2965 __ CallStub(&create_stub); |
| 2837 __ SubSmiLiteral(r7, r7, Smi::FromInt(1), r0); | 2966 __ Pop(r4); |
| 2838 __ StoreP(r7, FieldMemOperand(r5, with_types_offset), r0); | |
| 2839 const int generic_offset = | |
| 2840 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | |
| 2841 __ LoadP(r7, FieldMemOperand(r5, generic_offset)); | |
| 2842 __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0); | |
| 2843 __ StoreP(r7, FieldMemOperand(r5, generic_offset), r0); | |
| 2844 __ jmp(&slow_start); | |
| 2845 } | 2967 } |
| 2846 | 2968 |
| 2847 // We are here because tracing is on or we are going monomorphic. | 2969 __ b(&have_js_function); |
| 2970 |
| 2971 // We are here because tracing is on or we encountered a MISS case we can't |
| 2972 // handle here. |
| 2848 __ bind(&miss); | 2973 __ bind(&miss); |
| 2849 GenerateMiss(masm); | 2974 GenerateMiss(masm); |
| 2850 | 2975 |
| 2851 // the slow case | 2976 // the slow case |
| 2852 __ bind(&slow_start); | 2977 __ bind(&slow_start); |
| 2853 // Check that the function is really a JavaScript function. | 2978 // Check that the function is really a JavaScript function. |
| 2854 // r4: pushed function (to be verified) | 2979 // r4: pushed function (to be verified) |
| 2855 __ JumpIfSmi(r4, &non_function); | 2980 __ JumpIfSmi(r4, &non_function); |
| 2856 | 2981 |
| 2857 // Goto slow case if we do not have a function. | 2982 // Goto slow case if we do not have a function. |
| 2858 __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE); | 2983 __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE); |
| 2859 __ bne(&slow); | 2984 __ bne(&slow); |
| 2860 __ b(&have_js_function); | 2985 __ b(&have_js_function); |
| 2861 } | 2986 } |
| 2862 | 2987 |
| 2863 | 2988 |
| 2864 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 2989 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
| 2865 // Get the receiver of the function from the stack; 1 ~ return address. | 2990 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 2866 __ LoadP(r7, MemOperand(sp, (arg_count() + 1) * kPointerSize), r0); | |
| 2867 | 2991 |
| 2868 { | 2992 // Push the function and feedback info. |
| 2869 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 2993 __ Push(r4, r5, r6); |
| 2870 | 2994 |
| 2871 // Push the receiver and the function and feedback info. | 2995 // Call the entry. |
| 2872 __ Push(r7, r4, r5, r6); | 2996 IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss |
| 2997 : IC::kCallIC_Customization_Miss; |
| 2873 | 2998 |
| 2874 // Call the entry. | 2999 ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate()); |
| 2875 IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss | 3000 __ CallExternalReference(miss, 3); |
| 2876 : IC::kCallIC_Customization_Miss; | |
| 2877 | 3001 |
| 2878 ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate()); | 3002 // Move result to r4 and exit the internal frame. |
| 2879 __ CallExternalReference(miss, 4); | 3003 __ mr(r4, r3); |
| 2880 | |
| 2881 // Move result to r4 and exit the internal frame. | |
| 2882 __ mr(r4, r3); | |
| 2883 } | |
| 2884 } | 3004 } |
| 2885 | 3005 |
| 2886 | 3006 |
| 2887 // StringCharCodeAtGenerator | 3007 // StringCharCodeAtGenerator |
| 2888 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 3008 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
| 2889 // If the receiver is a smi trigger the non-string case. | 3009 // If the receiver is a smi trigger the non-string case. |
| 2890 if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 3010 if (check_mode_ == RECEIVER_IS_UNKNOWN) { |
| 2891 __ JumpIfSmi(object_, receiver_not_string_); | 3011 __ JumpIfSmi(object_, receiver_not_string_); |
| 2892 | 3012 |
| 2893 // Fetch the instance type of the receiver into result register. | 3013 // Fetch the instance type of the receiver into result register. |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3261 __ SmiTag(r6, r6); | 3381 __ SmiTag(r6, r6); |
| 3262 StringCharAtGenerator generator(r3, r6, r5, r3, &runtime, &runtime, &runtime, | 3382 StringCharAtGenerator generator(r3, r6, r5, r3, &runtime, &runtime, &runtime, |
| 3263 STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING); | 3383 STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING); |
| 3264 generator.GenerateFast(masm); | 3384 generator.GenerateFast(masm); |
| 3265 __ Drop(3); | 3385 __ Drop(3); |
| 3266 __ Ret(); | 3386 __ Ret(); |
| 3267 generator.SkipSlow(masm, &runtime); | 3387 generator.SkipSlow(masm, &runtime); |
| 3268 } | 3388 } |
| 3269 | 3389 |
| 3270 | 3390 |
| 3391 void ToNumberStub::Generate(MacroAssembler* masm) { |
| 3392 // The ToNumber stub takes one argument in r3. |
| 3393 Label not_smi; |
| 3394 __ JumpIfNotSmi(r3, ¬_smi); |
| 3395 __ blr(); |
| 3396 __ bind(¬_smi); |
| 3397 |
| 3398 Label not_heap_number; |
| 3399 __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| 3400 __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 3401 // r3: object |
| 3402 // r4: instance type. |
| 3403 __ cmpi(r4, Operand(HEAP_NUMBER_TYPE)); |
| 3404 __ bne(¬_heap_number); |
| 3405 __ blr(); |
| 3406 __ bind(¬_heap_number); |
| 3407 |
| 3408 Label not_string, slow_string; |
| 3409 __ cmpli(r4, Operand(FIRST_NONSTRING_TYPE)); |
| 3410 __ bge(¬_string); |
| 3411 // Check if string has a cached array index. |
| 3412 __ lwz(r5, FieldMemOperand(r3, String::kHashFieldOffset)); |
| 3413 __ And(r0, r5, Operand(String::kContainsCachedArrayIndexMask), SetRC); |
| 3414 __ bne(&slow_string, cr0); |
| 3415 __ IndexFromHash(r5, r3); |
| 3416 __ blr(); |
| 3417 __ bind(&slow_string); |
| 3418 __ push(r3); // Push argument. |
| 3419 __ TailCallRuntime(Runtime::kStringToNumber, 1, 1); |
| 3420 __ bind(¬_string); |
| 3421 |
| 3422 Label not_oddball; |
| 3423 __ cmpi(r4, Operand(ODDBALL_TYPE)); |
| 3424 __ bne(¬_oddball); |
| 3425 __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset)); |
| 3426 __ blr(); |
| 3427 __ bind(¬_oddball); |
| 3428 |
| 3429 __ push(r3); // Push argument. |
| 3430 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); |
| 3431 } |
| 3432 |
| 3433 |
| 3271 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, | 3434 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, |
| 3272 Register left, | 3435 Register left, |
| 3273 Register right, | 3436 Register right, |
| 3274 Register scratch1, | 3437 Register scratch1, |
| 3275 Register scratch2) { | 3438 Register scratch2) { |
| 3276 Register length = scratch1; | 3439 Register length = scratch1; |
| 3277 | 3440 |
| 3278 // Compare lengths. | 3441 // Compare lengths. |
| 3279 Label strings_not_equal, check_zero_length; | 3442 Label strings_not_equal, check_zero_length; |
| 3280 __ LoadP(length, FieldMemOperand(left, String::kLengthOffset)); | 3443 __ LoadP(length, FieldMemOperand(left, String::kLengthOffset)); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3301 | 3464 |
| 3302 // Characters are equal. | 3465 // Characters are equal. |
| 3303 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); | 3466 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); |
| 3304 __ Ret(); | 3467 __ Ret(); |
| 3305 } | 3468 } |
| 3306 | 3469 |
| 3307 | 3470 |
| 3308 void StringHelper::GenerateCompareFlatOneByteStrings( | 3471 void StringHelper::GenerateCompareFlatOneByteStrings( |
| 3309 MacroAssembler* masm, Register left, Register right, Register scratch1, | 3472 MacroAssembler* masm, Register left, Register right, Register scratch1, |
| 3310 Register scratch2, Register scratch3) { | 3473 Register scratch2, Register scratch3) { |
| 3311 Label skip, result_not_equal, compare_lengths; | 3474 Label result_not_equal, compare_lengths; |
| 3312 // Find minimum length and length difference. | 3475 // Find minimum length and length difference. |
| 3313 __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset)); | 3476 __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset)); |
| 3314 __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset)); | 3477 __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset)); |
| 3315 __ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC); | 3478 __ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC); |
| 3316 Register length_delta = scratch3; | 3479 Register length_delta = scratch3; |
| 3317 __ ble(&skip, cr0); | 3480 if (CpuFeatures::IsSupported(ISELECT)) { |
| 3318 __ mr(scratch1, scratch2); | 3481 __ isel(gt, scratch1, scratch2, scratch1, cr0); |
| 3319 __ bind(&skip); | 3482 } else { |
| 3483 Label skip; |
| 3484 __ ble(&skip, cr0); |
| 3485 __ mr(scratch1, scratch2); |
| 3486 __ bind(&skip); |
| 3487 } |
| 3320 Register min_length = scratch1; | 3488 Register min_length = scratch1; |
| 3321 STATIC_ASSERT(kSmiTag == 0); | 3489 STATIC_ASSERT(kSmiTag == 0); |
| 3322 __ cmpi(min_length, Operand::Zero()); | 3490 __ cmpi(min_length, Operand::Zero()); |
| 3323 __ beq(&compare_lengths); | 3491 __ beq(&compare_lengths); |
| 3324 | 3492 |
| 3325 // Compare loop. | 3493 // Compare loop. |
| 3326 GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, | 3494 GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, |
| 3327 &result_not_equal); | 3495 &result_not_equal); |
| 3328 | 3496 |
| 3329 // Compare lengths - strings up to min-length are equal. | 3497 // Compare lengths - strings up to min-length are equal. |
| 3330 __ bind(&compare_lengths); | 3498 __ bind(&compare_lengths); |
| 3331 DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); | 3499 DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); |
| 3332 // Use length_delta as result if it's zero. | 3500 // Use length_delta as result if it's zero. |
| 3333 __ mr(r3, length_delta); | 3501 __ mr(r3, length_delta); |
| 3334 __ cmpi(r3, Operand::Zero()); | 3502 __ cmpi(r3, Operand::Zero()); |
| 3335 __ bind(&result_not_equal); | 3503 __ bind(&result_not_equal); |
| 3336 // Conditionally update the result based either on length_delta or | 3504 // Conditionally update the result based either on length_delta or |
| 3337 // the last comparion performed in the loop above. | 3505 // the last comparion performed in the loop above. |
| 3338 Label less_equal, equal; | 3506 if (CpuFeatures::IsSupported(ISELECT)) { |
| 3339 __ ble(&less_equal); | 3507 __ li(r4, Operand(GREATER)); |
| 3340 __ LoadSmiLiteral(r3, Smi::FromInt(GREATER)); | 3508 __ li(r5, Operand(LESS)); |
| 3341 __ Ret(); | 3509 __ isel(eq, r3, r0, r4); |
| 3342 __ bind(&less_equal); | 3510 __ isel(lt, r3, r5, r3); |
| 3343 __ beq(&equal); | 3511 __ Ret(); |
| 3344 __ LoadSmiLiteral(r3, Smi::FromInt(LESS)); | 3512 } else { |
| 3345 __ bind(&equal); | 3513 Label less_equal, equal; |
| 3346 __ Ret(); | 3514 __ ble(&less_equal); |
| 3515 __ LoadSmiLiteral(r3, Smi::FromInt(GREATER)); |
| 3516 __ Ret(); |
| 3517 __ bind(&less_equal); |
| 3518 __ beq(&equal); |
| 3519 __ LoadSmiLiteral(r3, Smi::FromInt(LESS)); |
| 3520 __ bind(&equal); |
| 3521 __ Ret(); |
| 3522 } |
| 3347 } | 3523 } |
| 3348 | 3524 |
| 3349 | 3525 |
| 3350 void StringHelper::GenerateOneByteCharsCompareLoop( | 3526 void StringHelper::GenerateOneByteCharsCompareLoop( |
| 3351 MacroAssembler* masm, Register left, Register right, Register length, | 3527 MacroAssembler* masm, Register left, Register right, Register length, |
| 3352 Register scratch1, Label* chars_not_equal) { | 3528 Register scratch1, Label* chars_not_equal) { |
| 3353 // Change index to run from -length to -1 by adding length to string | 3529 // Change index to run from -length to -1 by adding length to string |
| 3354 // start. This means that loop ends when index reaches zero, which | 3530 // start. This means that loop ends when index reaches zero, which |
| 3355 // doesn't need an additional compare. | 3531 // doesn't need an additional compare. |
| 3356 __ SmiUntag(length); | 3532 __ SmiUntag(length); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3504 | 3680 |
| 3505 __ bind(&done); | 3681 __ bind(&done); |
| 3506 | 3682 |
| 3507 // Compare operands | 3683 // Compare operands |
| 3508 __ fcmpu(d0, d1); | 3684 __ fcmpu(d0, d1); |
| 3509 | 3685 |
| 3510 // Don't base result on status bits when a NaN is involved. | 3686 // Don't base result on status bits when a NaN is involved. |
| 3511 __ bunordered(&unordered); | 3687 __ bunordered(&unordered); |
| 3512 | 3688 |
| 3513 // Return a result of -1, 0, or 1, based on status bits. | 3689 // Return a result of -1, 0, or 1, based on status bits. |
| 3514 __ beq(&equal); | 3690 if (CpuFeatures::IsSupported(ISELECT)) { |
| 3515 __ blt(&less_than); | 3691 DCHECK(EQUAL == 0); |
| 3516 // assume greater than | 3692 __ li(r4, Operand(GREATER)); |
| 3517 __ li(r3, Operand(GREATER)); | 3693 __ li(r5, Operand(LESS)); |
| 3518 __ Ret(); | 3694 __ isel(eq, r3, r0, r4); |
| 3519 __ bind(&equal); | 3695 __ isel(lt, r3, r5, r3); |
| 3520 __ li(r3, Operand(EQUAL)); | 3696 __ Ret(); |
| 3521 __ Ret(); | 3697 } else { |
| 3522 __ bind(&less_than); | 3698 __ beq(&equal); |
| 3523 __ li(r3, Operand(LESS)); | 3699 __ blt(&less_than); |
| 3524 __ Ret(); | 3700 // assume greater than |
| 3701 __ li(r3, Operand(GREATER)); |
| 3702 __ Ret(); |
| 3703 __ bind(&equal); |
| 3704 __ li(r3, Operand(EQUAL)); |
| 3705 __ Ret(); |
| 3706 __ bind(&less_than); |
| 3707 __ li(r3, Operand(LESS)); |
| 3708 __ Ret(); |
| 3709 } |
| 3525 | 3710 |
| 3526 __ bind(&unordered); | 3711 __ bind(&unordered); |
| 3527 __ bind(&generic_stub); | 3712 __ bind(&generic_stub); |
| 3528 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, | 3713 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
| 3529 CompareICState::GENERIC, CompareICState::GENERIC); | 3714 CompareICState::GENERIC, CompareICState::GENERIC); |
| 3530 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 3715 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 3531 | 3716 |
| 3532 __ bind(&maybe_undefined1); | 3717 __ bind(&maybe_undefined1); |
| 3533 if (Token::IsOrderedRelationalCompareOp(op())) { | 3718 if (Token::IsOrderedRelationalCompareOp(op())) { |
| 3534 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); | 3719 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3728 __ sub(r3, r3, r4); | 3913 __ sub(r3, r3, r4); |
| 3729 __ Ret(); | 3914 __ Ret(); |
| 3730 | 3915 |
| 3731 __ bind(&miss); | 3916 __ bind(&miss); |
| 3732 GenerateMiss(masm); | 3917 GenerateMiss(masm); |
| 3733 } | 3918 } |
| 3734 | 3919 |
| 3735 | 3920 |
| 3736 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { | 3921 void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) { |
| 3737 Label miss; | 3922 Label miss; |
| 3923 Handle<WeakCell> cell = Map::WeakCellForMap(known_map_); |
| 3738 __ and_(r5, r4, r3); | 3924 __ and_(r5, r4, r3); |
| 3739 __ JumpIfSmi(r5, &miss); | 3925 __ JumpIfSmi(r5, &miss); |
| 3926 __ GetWeakValue(r7, cell); |
| 3740 __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset)); | 3927 __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| 3741 __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset)); | 3928 __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset)); |
| 3742 __ Cmpi(r5, Operand(known_map_), r0); | 3929 __ cmp(r5, r7); |
| 3743 __ bne(&miss); | 3930 __ bne(&miss); |
| 3744 __ Cmpi(r6, Operand(known_map_), r0); | 3931 __ cmp(r6, r7); |
| 3745 __ bne(&miss); | 3932 __ bne(&miss); |
| 3746 | 3933 |
| 3747 __ sub(r3, r3, r4); | 3934 __ sub(r3, r3, r4); |
| 3748 __ Ret(); | 3935 __ Ret(); |
| 3749 | 3936 |
| 3750 __ bind(&miss); | 3937 __ bind(&miss); |
| 3751 GenerateMiss(masm); | 3938 GenerateMiss(masm); |
| 3752 } | 3939 } |
| 3753 | 3940 |
| 3754 | 3941 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3818 // Compute the masked index: (hash + i + i * i) & mask. | 4005 // Compute the masked index: (hash + i + i * i) & mask. |
| 3819 Register index = scratch0; | 4006 Register index = scratch0; |
| 3820 // Capacity is smi 2^n. | 4007 // Capacity is smi 2^n. |
| 3821 __ LoadP(index, FieldMemOperand(properties, kCapacityOffset)); | 4008 __ LoadP(index, FieldMemOperand(properties, kCapacityOffset)); |
| 3822 __ subi(index, index, Operand(1)); | 4009 __ subi(index, index, Operand(1)); |
| 3823 __ LoadSmiLiteral( | 4010 __ LoadSmiLiteral( |
| 3824 ip, Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i))); | 4011 ip, Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i))); |
| 3825 __ and_(index, index, ip); | 4012 __ and_(index, index, ip); |
| 3826 | 4013 |
| 3827 // Scale the index by multiplying by the entry size. | 4014 // Scale the index by multiplying by the entry size. |
| 3828 DCHECK(NameDictionary::kEntrySize == 3); | 4015 STATIC_ASSERT(NameDictionary::kEntrySize == 3); |
| 3829 __ ShiftLeftImm(ip, index, Operand(1)); | 4016 __ ShiftLeftImm(ip, index, Operand(1)); |
| 3830 __ add(index, index, ip); // index *= 3. | 4017 __ add(index, index, ip); // index *= 3. |
| 3831 | 4018 |
| 3832 Register entity_name = scratch0; | 4019 Register entity_name = scratch0; |
| 3833 // Having undefined at this place means the name is not contained. | 4020 // Having undefined at this place means the name is not contained. |
| 3834 Register tmp = properties; | 4021 Register tmp = properties; |
| 3835 __ SmiToPtrArrayOffset(ip, index); | 4022 __ SmiToPtrArrayOffset(ip, index); |
| 3836 __ add(tmp, properties, ip); | 4023 __ add(tmp, properties, ip); |
| 3837 __ LoadP(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); | 4024 __ LoadP(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); |
| 3838 | 4025 |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4007 __ mr(index, hash); | 4194 __ mr(index, hash); |
| 4008 } | 4195 } |
| 4009 __ srwi(r0, index, Operand(Name::kHashShift)); | 4196 __ srwi(r0, index, Operand(Name::kHashShift)); |
| 4010 __ and_(index, mask, r0); | 4197 __ and_(index, mask, r0); |
| 4011 | 4198 |
| 4012 // Scale the index by multiplying by the entry size. | 4199 // Scale the index by multiplying by the entry size. |
| 4013 DCHECK(NameDictionary::kEntrySize == 3); | 4200 DCHECK(NameDictionary::kEntrySize == 3); |
| 4014 __ ShiftLeftImm(scratch, index, Operand(1)); | 4201 __ ShiftLeftImm(scratch, index, Operand(1)); |
| 4015 __ add(index, index, scratch); // index *= 3. | 4202 __ add(index, index, scratch); // index *= 3. |
| 4016 | 4203 |
| 4017 DCHECK_EQ(kSmiTagSize, 1); | |
| 4018 __ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2)); | 4204 __ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2)); |
| 4019 __ add(index, dictionary, scratch); | 4205 __ add(index, dictionary, scratch); |
| 4020 __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset)); | 4206 __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset)); |
| 4021 | 4207 |
| 4022 // Having undefined at this place means the name is not contained. | 4208 // Having undefined at this place means the name is not contained. |
| 4023 __ cmp(entry_key, undefined); | 4209 __ cmp(entry_key, undefined); |
| 4024 __ beq(¬_in_dictionary); | 4210 __ beq(¬_in_dictionary); |
| 4025 | 4211 |
| 4026 // Stop if found the property. | 4212 // Stop if found the property. |
| 4027 __ cmp(entry_key, key); | 4213 __ cmp(entry_key, key); |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4328 } | 4514 } |
| 4329 | 4515 |
| 4330 | 4516 |
| 4331 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { | 4517 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { |
| 4332 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); | 4518 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); |
| 4333 VectorKeyedLoadStub stub(isolate()); | 4519 VectorKeyedLoadStub stub(isolate()); |
| 4334 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 4520 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 4335 } | 4521 } |
| 4336 | 4522 |
| 4337 | 4523 |
| 4524 void CallICTrampolineStub::Generate(MacroAssembler* masm) { |
| 4525 EmitLoadTypeFeedbackVector(masm, r5); |
| 4526 CallICStub stub(isolate(), state()); |
| 4527 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 4528 } |
| 4529 |
| 4530 |
| 4531 void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) { |
| 4532 EmitLoadTypeFeedbackVector(masm, r5); |
| 4533 CallIC_ArrayStub stub(isolate(), state()); |
| 4534 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 4535 } |
| 4536 |
| 4537 |
| 4338 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4538 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
| 4339 if (masm->isolate()->function_entry_hook() != NULL) { | 4539 if (masm->isolate()->function_entry_hook() != NULL) { |
| 4340 PredictableCodeSizeScope predictable(masm, | 4540 PredictableCodeSizeScope predictable(masm, |
| 4341 #if V8_TARGET_ARCH_PPC64 | 4541 #if V8_TARGET_ARCH_PPC64 |
| 4342 14 * Assembler::kInstrSize); | 4542 14 * Assembler::kInstrSize); |
| 4343 #else | 4543 #else |
| 4344 11 * Assembler::kInstrSize); | 4544 11 * Assembler::kInstrSize); |
| 4345 #endif | 4545 #endif |
| 4346 ProfileEntryHookStub stub(masm->isolate()); | 4546 ProfileEntryHookStub stub(masm->isolate()); |
| 4347 __ mflr(r0); | 4547 __ mflr(r0); |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4704 Label fast_elements_case; | 4904 Label fast_elements_case; |
| 4705 __ cmpi(r6, Operand(FAST_ELEMENTS)); | 4905 __ cmpi(r6, Operand(FAST_ELEMENTS)); |
| 4706 __ beq(&fast_elements_case); | 4906 __ beq(&fast_elements_case); |
| 4707 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 4907 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
| 4708 | 4908 |
| 4709 __ bind(&fast_elements_case); | 4909 __ bind(&fast_elements_case); |
| 4710 GenerateCase(masm, FAST_ELEMENTS); | 4910 GenerateCase(masm, FAST_ELEMENTS); |
| 4711 } | 4911 } |
| 4712 | 4912 |
| 4713 | 4913 |
| 4714 void CallApiFunctionStub::Generate(MacroAssembler* masm) { | 4914 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
| 4915 return ref0.address() - ref1.address(); |
| 4916 } |
| 4917 |
| 4918 |
| 4919 // Calls an API function. Allocates HandleScope, extracts returned value |
| 4920 // from handle and propagates exceptions. Restores context. stack_space |
| 4921 // - space to be unwound on exit (includes the call JS arguments space and |
| 4922 // the additional space allocated for the fast call). |
| 4923 static void CallApiFunctionAndReturn(MacroAssembler* masm, |
| 4924 Register function_address, |
| 4925 ExternalReference thunk_ref, |
| 4926 int stack_space, |
| 4927 MemOperand* stack_space_operand, |
| 4928 MemOperand return_value_operand, |
| 4929 MemOperand* context_restore_operand) { |
| 4930 Isolate* isolate = masm->isolate(); |
| 4931 ExternalReference next_address = |
| 4932 ExternalReference::handle_scope_next_address(isolate); |
| 4933 const int kNextOffset = 0; |
| 4934 const int kLimitOffset = AddressOffset( |
| 4935 ExternalReference::handle_scope_limit_address(isolate), next_address); |
| 4936 const int kLevelOffset = AddressOffset( |
| 4937 ExternalReference::handle_scope_level_address(isolate), next_address); |
| 4938 |
| 4939 // Additional parameter is the address of the actual callback. |
| 4940 DCHECK(function_address.is(r4) || function_address.is(r5)); |
| 4941 Register scratch = r6; |
| 4942 |
| 4943 __ mov(scratch, Operand(ExternalReference::is_profiling_address(isolate))); |
| 4944 __ lbz(scratch, MemOperand(scratch, 0)); |
| 4945 __ cmpi(scratch, Operand::Zero()); |
| 4946 |
| 4947 if (CpuFeatures::IsSupported(ISELECT)) { |
| 4948 __ mov(scratch, Operand(thunk_ref)); |
| 4949 __ isel(eq, scratch, function_address, scratch); |
| 4950 } else { |
| 4951 Label profiler_disabled; |
| 4952 Label end_profiler_check; |
| 4953 __ beq(&profiler_disabled); |
| 4954 __ mov(scratch, Operand(thunk_ref)); |
| 4955 __ b(&end_profiler_check); |
| 4956 __ bind(&profiler_disabled); |
| 4957 __ mr(scratch, function_address); |
| 4958 __ bind(&end_profiler_check); |
| 4959 } |
| 4960 |
| 4961 // Allocate HandleScope in callee-save registers. |
| 4962 // r17 - next_address |
| 4963 // r14 - next_address->kNextOffset |
| 4964 // r15 - next_address->kLimitOffset |
| 4965 // r16 - next_address->kLevelOffset |
| 4966 __ mov(r17, Operand(next_address)); |
| 4967 __ LoadP(r14, MemOperand(r17, kNextOffset)); |
| 4968 __ LoadP(r15, MemOperand(r17, kLimitOffset)); |
| 4969 __ lwz(r16, MemOperand(r17, kLevelOffset)); |
| 4970 __ addi(r16, r16, Operand(1)); |
| 4971 __ stw(r16, MemOperand(r17, kLevelOffset)); |
| 4972 |
| 4973 if (FLAG_log_timer_events) { |
| 4974 FrameScope frame(masm, StackFrame::MANUAL); |
| 4975 __ PushSafepointRegisters(); |
| 4976 __ PrepareCallCFunction(1, r3); |
| 4977 __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); |
| 4978 __ CallCFunction(ExternalReference::log_enter_external_function(isolate), |
| 4979 1); |
| 4980 __ PopSafepointRegisters(); |
| 4981 } |
| 4982 |
| 4983 // Native call returns to the DirectCEntry stub which redirects to the |
| 4984 // return address pushed on stack (could have moved after GC). |
| 4985 // DirectCEntry stub itself is generated early and never moves. |
| 4986 DirectCEntryStub stub(isolate); |
| 4987 stub.GenerateCall(masm, scratch); |
| 4988 |
| 4989 if (FLAG_log_timer_events) { |
| 4990 FrameScope frame(masm, StackFrame::MANUAL); |
| 4991 __ PushSafepointRegisters(); |
| 4992 __ PrepareCallCFunction(1, r3); |
| 4993 __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); |
| 4994 __ CallCFunction(ExternalReference::log_leave_external_function(isolate), |
| 4995 1); |
| 4996 __ PopSafepointRegisters(); |
| 4997 } |
| 4998 |
| 4999 Label promote_scheduled_exception; |
| 5000 Label exception_handled; |
| 5001 Label delete_allocated_handles; |
| 5002 Label leave_exit_frame; |
| 5003 Label return_value_loaded; |
| 5004 |
| 5005 // load value from ReturnValue |
| 5006 __ LoadP(r3, return_value_operand); |
| 5007 __ bind(&return_value_loaded); |
| 5008 // No more valid handles (the result handle was the last one). Restore |
| 5009 // previous handle scope. |
| 5010 __ StoreP(r14, MemOperand(r17, kNextOffset)); |
| 5011 if (__ emit_debug_code()) { |
| 5012 __ lwz(r4, MemOperand(r17, kLevelOffset)); |
| 5013 __ cmp(r4, r16); |
| 5014 __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall); |
| 5015 } |
| 5016 __ subi(r16, r16, Operand(1)); |
| 5017 __ stw(r16, MemOperand(r17, kLevelOffset)); |
| 5018 __ LoadP(r0, MemOperand(r17, kLimitOffset)); |
| 5019 __ cmp(r15, r0); |
| 5020 __ bne(&delete_allocated_handles); |
| 5021 |
| 5022 // Check if the function scheduled an exception. |
| 5023 __ bind(&leave_exit_frame); |
| 5024 __ LoadRoot(r14, Heap::kTheHoleValueRootIndex); |
| 5025 __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate))); |
| 5026 __ LoadP(r15, MemOperand(r15)); |
| 5027 __ cmp(r14, r15); |
| 5028 __ bne(&promote_scheduled_exception); |
| 5029 __ bind(&exception_handled); |
| 5030 |
| 5031 bool restore_context = context_restore_operand != NULL; |
| 5032 if (restore_context) { |
| 5033 __ LoadP(cp, *context_restore_operand); |
| 5034 } |
| 5035 // LeaveExitFrame expects unwind space to be in a register. |
| 5036 if (stack_space_operand != NULL) { |
| 5037 __ lwz(r14, *stack_space_operand); |
| 5038 } else { |
| 5039 __ mov(r14, Operand(stack_space)); |
| 5040 } |
| 5041 __ LeaveExitFrame(false, r14, !restore_context, stack_space_operand != NULL); |
| 5042 __ blr(); |
| 5043 |
| 5044 __ bind(&promote_scheduled_exception); |
| 5045 { |
| 5046 FrameScope frame(masm, StackFrame::INTERNAL); |
| 5047 __ CallExternalReference( |
| 5048 ExternalReference(Runtime::kPromoteScheduledException, isolate), 0); |
| 5049 } |
| 5050 __ jmp(&exception_handled); |
| 5051 |
| 5052 // HandleScope limit has changed. Delete allocated extensions. |
| 5053 __ bind(&delete_allocated_handles); |
| 5054 __ StoreP(r15, MemOperand(r17, kLimitOffset)); |
| 5055 __ mr(r14, r3); |
| 5056 __ PrepareCallCFunction(1, r15); |
| 5057 __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); |
| 5058 __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate), |
| 5059 1); |
| 5060 __ mr(r3, r14); |
| 5061 __ b(&leave_exit_frame); |
| 5062 } |
| 5063 |
| 5064 |
| 5065 static void CallApiFunctionStubHelper(MacroAssembler* masm, |
| 5066 const ParameterCount& argc, |
| 5067 bool return_first_arg, |
| 5068 bool call_data_undefined) { |
| 4715 // ----------- S t a t e ------------- | 5069 // ----------- S t a t e ------------- |
| 4716 // -- r3 : callee | 5070 // -- r3 : callee |
| 4717 // -- r7 : call_data | 5071 // -- r7 : call_data |
| 4718 // -- r5 : holder | 5072 // -- r5 : holder |
| 4719 // -- r4 : api_function_address | 5073 // -- r4 : api_function_address |
| 5074 // -- r6 : number of arguments if argc is a register |
| 4720 // -- cp : context | 5075 // -- cp : context |
| 4721 // -- | 5076 // -- |
| 4722 // -- sp[0] : last argument | 5077 // -- sp[0] : last argument |
| 4723 // -- ... | 5078 // -- ... |
| 4724 // -- sp[(argc - 1)* 4] : first argument | 5079 // -- sp[(argc - 1)* 4] : first argument |
| 4725 // -- sp[argc * 4] : receiver | 5080 // -- sp[argc * 4] : receiver |
| 4726 // ----------------------------------- | 5081 // ----------------------------------- |
| 4727 | 5082 |
| 4728 Register callee = r3; | 5083 Register callee = r3; |
| 4729 Register call_data = r7; | 5084 Register call_data = r7; |
| 4730 Register holder = r5; | 5085 Register holder = r5; |
| 4731 Register api_function_address = r4; | 5086 Register api_function_address = r4; |
| 4732 Register context = cp; | 5087 Register context = cp; |
| 4733 | 5088 |
| 4734 int argc = this->argc(); | |
| 4735 bool is_store = this->is_store(); | |
| 4736 bool call_data_undefined = this->call_data_undefined(); | |
| 4737 | |
| 4738 typedef FunctionCallbackArguments FCA; | 5089 typedef FunctionCallbackArguments FCA; |
| 4739 | 5090 |
| 4740 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 5091 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
| 4741 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 5092 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
| 4742 STATIC_ASSERT(FCA::kDataIndex == 4); | 5093 STATIC_ASSERT(FCA::kDataIndex == 4); |
| 4743 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 5094 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
| 4744 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 5095 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
| 4745 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 5096 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
| 4746 STATIC_ASSERT(FCA::kHolderIndex == 0); | 5097 STATIC_ASSERT(FCA::kHolderIndex == 0); |
| 4747 STATIC_ASSERT(FCA::kArgsLength == 7); | 5098 STATIC_ASSERT(FCA::kArgsLength == 7); |
| 4748 | 5099 |
| 5100 DCHECK(argc.is_immediate() || r3.is(argc.reg())); |
| 5101 |
| 4749 // context save | 5102 // context save |
| 4750 __ push(context); | 5103 __ push(context); |
| 4751 // load context from callee | 5104 // load context from callee |
| 4752 __ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset)); | 5105 __ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset)); |
| 4753 | 5106 |
| 4754 // callee | 5107 // callee |
| 4755 __ push(callee); | 5108 __ push(callee); |
| 4756 | 5109 |
| 4757 // call data | 5110 // call data |
| 4758 __ push(call_data); | 5111 __ push(call_data); |
| 4759 | 5112 |
| 4760 Register scratch = call_data; | 5113 Register scratch = call_data; |
| 4761 if (!call_data_undefined) { | 5114 if (!call_data_undefined) { |
| 4762 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 5115 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 4763 } | 5116 } |
| 4764 // return value | 5117 // return value |
| 4765 __ push(scratch); | 5118 __ push(scratch); |
| 4766 // return value default | 5119 // return value default |
| 4767 __ push(scratch); | 5120 __ push(scratch); |
| 4768 // isolate | 5121 // isolate |
| 4769 __ mov(scratch, Operand(ExternalReference::isolate_address(isolate()))); | 5122 __ mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate()))); |
| 4770 __ push(scratch); | 5123 __ push(scratch); |
| 4771 // holder | 5124 // holder |
| 4772 __ push(holder); | 5125 __ push(holder); |
| 4773 | 5126 |
| 4774 // Prepare arguments. | 5127 // Prepare arguments. |
| 4775 __ mr(scratch, sp); | 5128 __ mr(scratch, sp); |
| 4776 | 5129 |
| 4777 // Allocate the v8::Arguments structure in the arguments' space since | 5130 // Allocate the v8::Arguments structure in the arguments' space since |
| 4778 // it's not controlled by GC. | 5131 // it's not controlled by GC. |
| 4779 // PPC LINUX ABI: | 5132 // PPC LINUX ABI: |
| 4780 // | 5133 // |
| 4781 // Create 5 extra slots on stack: | 5134 // Create 5 extra slots on stack: |
| 4782 // [0] space for DirectCEntryStub's LR save | 5135 // [0] space for DirectCEntryStub's LR save |
| 4783 // [1-4] FunctionCallbackInfo | 5136 // [1-4] FunctionCallbackInfo |
| 4784 const int kApiStackSpace = 5; | 5137 const int kApiStackSpace = 5; |
| 5138 const int kFunctionCallbackInfoOffset = |
| 5139 (kStackFrameExtraParamSlot + 1) * kPointerSize; |
| 4785 | 5140 |
| 4786 FrameScope frame_scope(masm, StackFrame::MANUAL); | 5141 FrameScope frame_scope(masm, StackFrame::MANUAL); |
| 4787 __ EnterExitFrame(false, kApiStackSpace); | 5142 __ EnterExitFrame(false, kApiStackSpace); |
| 4788 | 5143 |
| 4789 DCHECK(!api_function_address.is(r3) && !scratch.is(r3)); | 5144 DCHECK(!api_function_address.is(r3) && !scratch.is(r3)); |
| 4790 // r3 = FunctionCallbackInfo& | 5145 // r3 = FunctionCallbackInfo& |
| 4791 // Arguments is after the return address. | 5146 // Arguments is after the return address. |
| 4792 __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize)); | 5147 __ addi(r3, sp, Operand(kFunctionCallbackInfoOffset)); |
| 4793 // FunctionCallbackInfo::implicit_args_ | 5148 // FunctionCallbackInfo::implicit_args_ |
| 4794 __ StoreP(scratch, MemOperand(r3, 0 * kPointerSize)); | 5149 __ StoreP(scratch, MemOperand(r3, 0 * kPointerSize)); |
| 4795 // FunctionCallbackInfo::values_ | 5150 if (argc.is_immediate()) { |
| 4796 __ addi(ip, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize)); | 5151 // FunctionCallbackInfo::values_ |
| 4797 __ StoreP(ip, MemOperand(r3, 1 * kPointerSize)); | 5152 __ addi(ip, scratch, |
| 4798 // FunctionCallbackInfo::length_ = argc | 5153 Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize)); |
| 4799 __ li(ip, Operand(argc)); | 5154 __ StoreP(ip, MemOperand(r3, 1 * kPointerSize)); |
| 4800 __ stw(ip, MemOperand(r3, 2 * kPointerSize)); | 5155 // FunctionCallbackInfo::length_ = argc |
| 4801 // FunctionCallbackInfo::is_construct_call = 0 | 5156 __ li(ip, Operand(argc.immediate())); |
| 4802 __ li(ip, Operand::Zero()); | 5157 __ stw(ip, MemOperand(r3, 2 * kPointerSize)); |
| 4803 __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize)); | 5158 // FunctionCallbackInfo::is_construct_call_ = 0 |
| 5159 __ li(ip, Operand::Zero()); |
| 5160 __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize)); |
| 5161 } else { |
| 5162 __ ShiftLeftImm(ip, argc.reg(), Operand(kPointerSizeLog2)); |
| 5163 __ addi(ip, ip, Operand((FCA::kArgsLength - 1) * kPointerSize)); |
| 5164 // FunctionCallbackInfo::values_ |
| 5165 __ add(r0, scratch, ip); |
| 5166 __ StoreP(r0, MemOperand(r3, 1 * kPointerSize)); |
| 5167 // FunctionCallbackInfo::length_ = argc |
| 5168 __ stw(argc.reg(), MemOperand(r3, 2 * kPointerSize)); |
| 5169 // FunctionCallbackInfo::is_construct_call_ |
| 5170 __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize)); |
| 5171 } |
| 4804 | 5172 |
| 4805 const int kStackUnwindSpace = argc + FCA::kArgsLength + 1; | |
| 4806 ExternalReference thunk_ref = | 5173 ExternalReference thunk_ref = |
| 4807 ExternalReference::invoke_function_callback(isolate()); | 5174 ExternalReference::invoke_function_callback(masm->isolate()); |
| 4808 | 5175 |
| 4809 AllowExternalCallThatCantCauseGC scope(masm); | 5176 AllowExternalCallThatCantCauseGC scope(masm); |
| 4810 MemOperand context_restore_operand( | 5177 MemOperand context_restore_operand( |
| 4811 fp, (2 + FCA::kContextSaveIndex) * kPointerSize); | 5178 fp, (2 + FCA::kContextSaveIndex) * kPointerSize); |
| 4812 // Stores return the first js argument | 5179 // Stores return the first js argument |
| 4813 int return_value_offset = 0; | 5180 int return_value_offset = 0; |
| 4814 if (is_store) { | 5181 if (return_first_arg) { |
| 4815 return_value_offset = 2 + FCA::kArgsLength; | 5182 return_value_offset = 2 + FCA::kArgsLength; |
| 4816 } else { | 5183 } else { |
| 4817 return_value_offset = 2 + FCA::kReturnValueOffset; | 5184 return_value_offset = 2 + FCA::kReturnValueOffset; |
| 4818 } | 5185 } |
| 4819 MemOperand return_value_operand(fp, return_value_offset * kPointerSize); | 5186 MemOperand return_value_operand(fp, return_value_offset * kPointerSize); |
| 4820 | 5187 int stack_space = 0; |
| 4821 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, | 5188 MemOperand is_construct_call_operand = |
| 4822 kStackUnwindSpace, return_value_operand, | 5189 MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize + kIntSize); |
| 4823 &context_restore_operand); | 5190 MemOperand* stack_space_operand = &is_construct_call_operand; |
| 5191 if (argc.is_immediate()) { |
| 5192 stack_space = argc.immediate() + FCA::kArgsLength + 1; |
| 5193 stack_space_operand = NULL; |
| 5194 } |
| 5195 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space, |
| 5196 stack_space_operand, return_value_operand, |
| 5197 &context_restore_operand); |
| 4824 } | 5198 } |
| 4825 | 5199 |
| 4826 | 5200 |
| 5201 void CallApiFunctionStub::Generate(MacroAssembler* masm) { |
| 5202 bool call_data_undefined = this->call_data_undefined(); |
| 5203 CallApiFunctionStubHelper(masm, ParameterCount(r6), false, |
| 5204 call_data_undefined); |
| 5205 } |
| 5206 |
| 5207 |
| 5208 void CallApiAccessorStub::Generate(MacroAssembler* masm) { |
| 5209 bool is_store = this->is_store(); |
| 5210 int argc = this->argc(); |
| 5211 bool call_data_undefined = this->call_data_undefined(); |
| 5212 CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store, |
| 5213 call_data_undefined); |
| 5214 } |
| 5215 |
| 5216 |
| 4827 void CallApiGetterStub::Generate(MacroAssembler* masm) { | 5217 void CallApiGetterStub::Generate(MacroAssembler* masm) { |
| 4828 // ----------- S t a t e ------------- | 5218 // ----------- S t a t e ------------- |
| 4829 // -- sp[0] : name | 5219 // -- sp[0] : name |
| 4830 // -- sp[4 - kArgsLength*4] : PropertyCallbackArguments object | 5220 // -- sp[4 - kArgsLength*4] : PropertyCallbackArguments object |
| 4831 // -- ... | 5221 // -- ... |
| 4832 // -- r5 : api_function_address | 5222 // -- r5 : api_function_address |
| 4833 // ----------------------------------- | 5223 // ----------------------------------- |
| 4834 | 5224 |
| 4835 Register api_function_address = ApiGetterDescriptor::function_address(); | 5225 Register api_function_address = ApiGetterDescriptor::function_address(); |
| 4836 DCHECK(api_function_address.is(r5)); | 5226 DCHECK(api_function_address.is(r5)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4871 // Create PropertyAccessorInfo instance on the stack above the exit frame with | 5261 // Create PropertyAccessorInfo instance on the stack above the exit frame with |
| 4872 // r4 (internal::Object** args_) as the data. | 5262 // r4 (internal::Object** args_) as the data. |
| 4873 __ StoreP(r4, MemOperand(sp, kAccessorInfoSlot * kPointerSize)); | 5263 __ StoreP(r4, MemOperand(sp, kAccessorInfoSlot * kPointerSize)); |
| 4874 // r4 = AccessorInfo& | 5264 // r4 = AccessorInfo& |
| 4875 __ addi(r4, sp, Operand(kAccessorInfoSlot * kPointerSize)); | 5265 __ addi(r4, sp, Operand(kAccessorInfoSlot * kPointerSize)); |
| 4876 | 5266 |
| 4877 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; | 5267 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; |
| 4878 | 5268 |
| 4879 ExternalReference thunk_ref = | 5269 ExternalReference thunk_ref = |
| 4880 ExternalReference::invoke_accessor_getter_callback(isolate()); | 5270 ExternalReference::invoke_accessor_getter_callback(isolate()); |
| 4881 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, | 5271 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
| 4882 kStackUnwindSpace, | 5272 kStackUnwindSpace, NULL, |
| 4883 MemOperand(fp, 6 * kPointerSize), NULL); | 5273 MemOperand(fp, 6 * kPointerSize), NULL); |
| 4884 } | 5274 } |
| 4885 | 5275 |
| 4886 | 5276 |
| 4887 #undef __ | 5277 #undef __ |
| 4888 } | 5278 } |
| 4889 } // namespace v8::internal | 5279 } // namespace v8::internal |
| 4890 | 5280 |
| 4891 #endif // V8_TARGET_ARCH_PPC | 5281 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |