| 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 <assert.h> // For assert | 5 #include <assert.h> // For assert |
| 6 #include <limits.h> // For LONG_MIN, LONG_MAX. | 6 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #if V8_TARGET_ARCH_PPC | 10 #if V8_TARGET_ARCH_PPC |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) { | 606 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) { |
| 607 // General purpose registers are pushed last on the stack. | 607 // General purpose registers are pushed last on the stack. |
| 608 int doubles_size = DoubleRegister::NumAllocatableRegisters() * kDoubleSize; | 608 int doubles_size = DoubleRegister::NumAllocatableRegisters() * kDoubleSize; |
| 609 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize; | 609 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize; |
| 610 return MemOperand(sp, doubles_size + register_offset); | 610 return MemOperand(sp, doubles_size + register_offset); |
| 611 } | 611 } |
| 612 | 612 |
| 613 | 613 |
| 614 void MacroAssembler::CanonicalizeNaN(const DoubleRegister dst, | 614 void MacroAssembler::CanonicalizeNaN(const DoubleRegister dst, |
| 615 const DoubleRegister src) { | 615 const DoubleRegister src) { |
| 616 Label done; | 616 // Turn potential sNaN into qNaN. |
| 617 | 617 fadd(dst, src, kDoubleRegZero); |
| 618 // Test for NaN | |
| 619 fcmpu(src, src); | |
| 620 | |
| 621 if (dst.is(src)) { | |
| 622 bordered(&done); | |
| 623 } else { | |
| 624 Label is_nan; | |
| 625 bunordered(&is_nan); | |
| 626 fmr(dst, src); | |
| 627 b(&done); | |
| 628 bind(&is_nan); | |
| 629 } | |
| 630 | |
| 631 // Replace with canonical NaN. | |
| 632 double nan_value = FixedDoubleArray::canonical_not_the_hole_nan_as_double(); | |
| 633 LoadDoubleLiteral(dst, nan_value, r0); | |
| 634 | |
| 635 bind(&done); | |
| 636 } | 618 } |
| 637 | 619 |
| 638 | 620 |
| 639 void MacroAssembler::ConvertIntToDouble(Register src, | 621 void MacroAssembler::ConvertIntToDouble(Register src, |
| 640 DoubleRegister double_dst) { | 622 DoubleRegister double_dst) { |
| 641 MovIntToDouble(double_dst, src, r0); | 623 MovIntToDouble(double_dst, src, r0); |
| 642 fcfid(double_dst, double_dst); | 624 fcfid(double_dst, double_dst); |
| 643 } | 625 } |
| 644 | 626 |
| 645 | 627 |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 // If we are using the simulator then we should always align to the expected | 890 // If we are using the simulator then we should always align to the expected |
| 909 // alignment. As the simulator is used to generate snapshots we do not know | 891 // alignment. As the simulator is used to generate snapshots we do not know |
| 910 // if the target platform will need alignment, so this is controlled from a | 892 // if the target platform will need alignment, so this is controlled from a |
| 911 // flag. | 893 // flag. |
| 912 return FLAG_sim_stack_alignment; | 894 return FLAG_sim_stack_alignment; |
| 913 #endif | 895 #endif |
| 914 } | 896 } |
| 915 | 897 |
| 916 | 898 |
| 917 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, | 899 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, |
| 918 bool restore_context) { | 900 bool restore_context, |
| 901 bool argument_count_is_length) { |
| 919 #if V8_OOL_CONSTANT_POOL | 902 #if V8_OOL_CONSTANT_POOL |
| 920 ConstantPoolUnavailableScope constant_pool_unavailable(this); | 903 ConstantPoolUnavailableScope constant_pool_unavailable(this); |
| 921 #endif | 904 #endif |
| 922 // Optionally restore all double registers. | 905 // Optionally restore all double registers. |
| 923 if (save_doubles) { | 906 if (save_doubles) { |
| 924 // Calculate the stack location of the saved doubles and restore them. | 907 // Calculate the stack location of the saved doubles and restore them. |
| 925 const int kNumRegs = DoubleRegister::kNumVolatileRegisters; | 908 const int kNumRegs = DoubleRegister::kNumVolatileRegisters; |
| 926 const int offset = | 909 const int offset = |
| 927 (ExitFrameConstants::kFrameSize + kNumRegs * kDoubleSize); | 910 (ExitFrameConstants::kFrameSize + kNumRegs * kDoubleSize); |
| 928 addi(r6, fp, Operand(-offset)); | 911 addi(r6, fp, Operand(-offset)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 941 } | 924 } |
| 942 #ifdef DEBUG | 925 #ifdef DEBUG |
| 943 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 926 mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); |
| 944 StoreP(r6, MemOperand(ip)); | 927 StoreP(r6, MemOperand(ip)); |
| 945 #endif | 928 #endif |
| 946 | 929 |
| 947 // Tear down the exit frame, pop the arguments, and return. | 930 // Tear down the exit frame, pop the arguments, and return. |
| 948 LeaveFrame(StackFrame::EXIT); | 931 LeaveFrame(StackFrame::EXIT); |
| 949 | 932 |
| 950 if (argument_count.is_valid()) { | 933 if (argument_count.is_valid()) { |
| 951 ShiftLeftImm(argument_count, argument_count, Operand(kPointerSizeLog2)); | 934 if (!argument_count_is_length) { |
| 935 ShiftLeftImm(argument_count, argument_count, Operand(kPointerSizeLog2)); |
| 936 } |
| 952 add(sp, sp, argument_count); | 937 add(sp, sp, argument_count); |
| 953 } | 938 } |
| 954 } | 939 } |
| 955 | 940 |
| 956 | 941 |
| 957 void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) { | 942 void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) { |
| 958 Move(dst, d1); | 943 Move(dst, d1); |
| 959 } | 944 } |
| 960 | 945 |
| 961 | 946 |
| (...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1735 } | 1720 } |
| 1736 } | 1721 } |
| 1737 | 1722 |
| 1738 | 1723 |
| 1739 void MacroAssembler::UndoAllocationInNewSpace(Register object, | 1724 void MacroAssembler::UndoAllocationInNewSpace(Register object, |
| 1740 Register scratch) { | 1725 Register scratch) { |
| 1741 ExternalReference new_space_allocation_top = | 1726 ExternalReference new_space_allocation_top = |
| 1742 ExternalReference::new_space_allocation_top_address(isolate()); | 1727 ExternalReference::new_space_allocation_top_address(isolate()); |
| 1743 | 1728 |
| 1744 // Make sure the object has no tag before resetting top. | 1729 // Make sure the object has no tag before resetting top. |
| 1745 mov(r0, Operand(~kHeapObjectTagMask)); | 1730 ClearRightImm(object, object, Operand(kHeapObjectTagSize)); |
| 1746 and_(object, object, r0); | |
| 1747 // was.. and_(object, object, Operand(~kHeapObjectTagMask)); | |
| 1748 #ifdef DEBUG | 1731 #ifdef DEBUG |
| 1749 // Check that the object un-allocated is below the current top. | 1732 // Check that the object un-allocated is below the current top. |
| 1750 mov(scratch, Operand(new_space_allocation_top)); | 1733 mov(scratch, Operand(new_space_allocation_top)); |
| 1751 LoadP(scratch, MemOperand(scratch)); | 1734 LoadP(scratch, MemOperand(scratch)); |
| 1752 cmp(object, scratch); | 1735 cmp(object, scratch); |
| 1753 Check(lt, kUndoAllocationOfNonAllocatedMemory); | 1736 Check(lt, kUndoAllocationOfNonAllocatedMemory); |
| 1754 #endif | 1737 #endif |
| 1755 // Write the address of the object to un-allocate as the current top. | 1738 // Write the address of the object to un-allocate as the current top. |
| 1756 mov(scratch, Operand(new_space_allocation_top)); | 1739 mov(scratch, Operand(new_space_allocation_top)); |
| 1757 StoreP(object, MemOperand(scratch)); | 1740 StoreP(object, MemOperand(scratch)); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1935 Label smi_value, store; | 1918 Label smi_value, store; |
| 1936 | 1919 |
| 1937 // Handle smi values specially. | 1920 // Handle smi values specially. |
| 1938 JumpIfSmi(value_reg, &smi_value); | 1921 JumpIfSmi(value_reg, &smi_value); |
| 1939 | 1922 |
| 1940 // Ensure that the object is a heap number | 1923 // Ensure that the object is a heap number |
| 1941 CheckMap(value_reg, scratch1, isolate()->factory()->heap_number_map(), fail, | 1924 CheckMap(value_reg, scratch1, isolate()->factory()->heap_number_map(), fail, |
| 1942 DONT_DO_SMI_CHECK); | 1925 DONT_DO_SMI_CHECK); |
| 1943 | 1926 |
| 1944 lfd(double_scratch, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 1927 lfd(double_scratch, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
| 1945 // Force a canonical NaN. | 1928 // Double value, turn potential sNaN into qNaN. |
| 1946 CanonicalizeNaN(double_scratch); | 1929 CanonicalizeNaN(double_scratch); |
| 1947 b(&store); | 1930 b(&store); |
| 1948 | 1931 |
| 1949 bind(&smi_value); | 1932 bind(&smi_value); |
| 1950 SmiToDouble(double_scratch, value_reg); | 1933 SmiToDouble(double_scratch, value_reg); |
| 1951 | 1934 |
| 1952 bind(&store); | 1935 bind(&store); |
| 1953 SmiToDoubleArrayOffset(scratch1, key_reg); | 1936 SmiToDoubleArrayOffset(scratch1, key_reg); |
| 1954 add(scratch1, elements_reg, scratch1); | 1937 add(scratch1, elements_reg, scratch1); |
| 1955 stfd(double_scratch, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - | 1938 stfd(double_scratch, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - |
| 1956 elements_offset)); | 1939 elements_offset)); |
| 1957 } | 1940 } |
| 1958 | 1941 |
| 1959 | 1942 |
| 1960 void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left, | 1943 void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left, |
| 1961 Register right, | 1944 Register right, |
| 1962 Register overflow_dst, | 1945 Register overflow_dst, |
| 1963 Register scratch) { | 1946 Register scratch) { |
| 1964 DCHECK(!dst.is(overflow_dst)); | 1947 DCHECK(!dst.is(overflow_dst)); |
| 1965 DCHECK(!dst.is(scratch)); | 1948 DCHECK(!dst.is(scratch)); |
| 1966 DCHECK(!overflow_dst.is(scratch)); | 1949 DCHECK(!overflow_dst.is(scratch)); |
| 1967 DCHECK(!overflow_dst.is(left)); | 1950 DCHECK(!overflow_dst.is(left)); |
| 1968 DCHECK(!overflow_dst.is(right)); | 1951 DCHECK(!overflow_dst.is(right)); |
| 1969 | 1952 |
| 1953 bool left_is_right = left.is(right); |
| 1954 RCBit xorRC = left_is_right ? SetRC : LeaveRC; |
| 1955 |
| 1970 // C = A+B; C overflows if A/B have same sign and C has diff sign than A | 1956 // C = A+B; C overflows if A/B have same sign and C has diff sign than A |
| 1971 if (dst.is(left)) { | 1957 if (dst.is(left)) { |
| 1972 mr(scratch, left); // Preserve left. | 1958 mr(scratch, left); // Preserve left. |
| 1973 add(dst, left, right); // Left is overwritten. | 1959 add(dst, left, right); // Left is overwritten. |
| 1974 xor_(scratch, dst, scratch); // Original left. | 1960 xor_(overflow_dst, dst, scratch, xorRC); // Original left. |
| 1975 xor_(overflow_dst, dst, right); | 1961 if (!left_is_right) xor_(scratch, dst, right); |
| 1976 } else if (dst.is(right)) { | 1962 } else if (dst.is(right)) { |
| 1977 mr(scratch, right); // Preserve right. | 1963 mr(scratch, right); // Preserve right. |
| 1978 add(dst, left, right); // Right is overwritten. | 1964 add(dst, left, right); // Right is overwritten. |
| 1979 xor_(scratch, dst, scratch); // Original right. | 1965 xor_(overflow_dst, dst, left, xorRC); |
| 1980 xor_(overflow_dst, dst, left); | 1966 if (!left_is_right) xor_(scratch, dst, scratch); // Original right. |
| 1981 } else { | 1967 } else { |
| 1982 add(dst, left, right); | 1968 add(dst, left, right); |
| 1983 xor_(overflow_dst, dst, left); | 1969 xor_(overflow_dst, dst, left, xorRC); |
| 1984 xor_(scratch, dst, right); | 1970 if (!left_is_right) xor_(scratch, dst, right); |
| 1985 } | 1971 } |
| 1986 and_(overflow_dst, scratch, overflow_dst, SetRC); | 1972 if (!left_is_right) and_(overflow_dst, scratch, overflow_dst, SetRC); |
| 1987 } | 1973 } |
| 1988 | 1974 |
| 1989 | 1975 |
| 1990 void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left, | 1976 void MacroAssembler::AddAndCheckForOverflow(Register dst, Register left, |
| 1991 intptr_t right, | 1977 intptr_t right, |
| 1992 Register overflow_dst, | 1978 Register overflow_dst, |
| 1993 Register scratch) { | 1979 Register scratch) { |
| 1994 Register original_left = left; | 1980 Register original_left = left; |
| 1995 DCHECK(!dst.is(overflow_dst)); | 1981 DCHECK(!dst.is(overflow_dst)); |
| 1996 DCHECK(!dst.is(scratch)); | 1982 DCHECK(!dst.is(scratch)); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2078 if (smi_check_type == DO_SMI_CHECK) { | 2064 if (smi_check_type == DO_SMI_CHECK) { |
| 2079 JumpIfSmi(obj, fail); | 2065 JumpIfSmi(obj, fail); |
| 2080 } | 2066 } |
| 2081 LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); | 2067 LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 2082 LoadRoot(r0, index); | 2068 LoadRoot(r0, index); |
| 2083 cmp(scratch, r0); | 2069 cmp(scratch, r0); |
| 2084 bne(fail); | 2070 bne(fail); |
| 2085 } | 2071 } |
| 2086 | 2072 |
| 2087 | 2073 |
| 2088 void MacroAssembler::DispatchMap(Register obj, Register scratch, | 2074 void MacroAssembler::DispatchWeakMap(Register obj, Register scratch1, |
| 2089 Handle<Map> map, Handle<Code> success, | 2075 Register scratch2, Handle<WeakCell> cell, |
| 2090 SmiCheckType smi_check_type) { | 2076 Handle<Code> success, |
| 2077 SmiCheckType smi_check_type) { |
| 2091 Label fail; | 2078 Label fail; |
| 2092 if (smi_check_type == DO_SMI_CHECK) { | 2079 if (smi_check_type == DO_SMI_CHECK) { |
| 2093 JumpIfSmi(obj, &fail); | 2080 JumpIfSmi(obj, &fail); |
| 2094 } | 2081 } |
| 2095 LoadP(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); | 2082 LoadP(scratch1, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 2096 mov(r0, Operand(map)); | 2083 CmpWeakValue(scratch1, cell, scratch2); |
| 2097 cmp(scratch, r0); | 2084 Jump(success, RelocInfo::CODE_TARGET, eq); |
| 2098 bne(&fail); | |
| 2099 Jump(success, RelocInfo::CODE_TARGET, al); | |
| 2100 bind(&fail); | 2085 bind(&fail); |
| 2101 } | 2086 } |
| 2102 | 2087 |
| 2103 | 2088 |
| 2089 void MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell, |
| 2090 Register scratch, CRegister cr) { |
| 2091 mov(scratch, Operand(cell)); |
| 2092 LoadP(scratch, FieldMemOperand(scratch, WeakCell::kValueOffset)); |
| 2093 cmp(value, scratch, cr); |
| 2094 } |
| 2095 |
| 2096 |
| 2097 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) { |
| 2098 mov(value, Operand(cell)); |
| 2099 LoadP(value, FieldMemOperand(value, WeakCell::kValueOffset)); |
| 2100 } |
| 2101 |
| 2102 |
| 2103 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell, |
| 2104 Label* miss) { |
| 2105 GetWeakValue(value, cell); |
| 2106 JumpIfSmi(value, miss); |
| 2107 } |
| 2108 |
| 2109 |
| 2104 void MacroAssembler::TryGetFunctionPrototype(Register function, Register result, | 2110 void MacroAssembler::TryGetFunctionPrototype(Register function, Register result, |
| 2105 Register scratch, Label* miss, | 2111 Register scratch, Label* miss, |
| 2106 bool miss_on_bound_function) { | 2112 bool miss_on_bound_function) { |
| 2107 Label non_instance; | 2113 Label non_instance; |
| 2108 if (miss_on_bound_function) { | 2114 if (miss_on_bound_function) { |
| 2109 // Check that the receiver isn't a smi. | 2115 // Check that the receiver isn't a smi. |
| 2110 JumpIfSmi(function, miss); | 2116 JumpIfSmi(function, miss); |
| 2111 | 2117 |
| 2112 // Check that the function really is a function. Load map into result reg. | 2118 // Check that the function really is a function. Load map into result reg. |
| 2113 CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE); | 2119 CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2170 DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. | 2176 DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. |
| 2171 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, cond); | 2177 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, cond); |
| 2172 } | 2178 } |
| 2173 | 2179 |
| 2174 | 2180 |
| 2175 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) { | 2181 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) { |
| 2176 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); | 2182 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); |
| 2177 } | 2183 } |
| 2178 | 2184 |
| 2179 | 2185 |
| 2180 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | |
| 2181 return ref0.address() - ref1.address(); | |
| 2182 } | |
| 2183 | |
| 2184 | |
| 2185 void MacroAssembler::CallApiFunctionAndReturn( | |
| 2186 Register function_address, ExternalReference thunk_ref, int stack_space, | |
| 2187 MemOperand return_value_operand, MemOperand* context_restore_operand) { | |
| 2188 ExternalReference next_address = | |
| 2189 ExternalReference::handle_scope_next_address(isolate()); | |
| 2190 const int kNextOffset = 0; | |
| 2191 const int kLimitOffset = AddressOffset( | |
| 2192 ExternalReference::handle_scope_limit_address(isolate()), next_address); | |
| 2193 const int kLevelOffset = AddressOffset( | |
| 2194 ExternalReference::handle_scope_level_address(isolate()), next_address); | |
| 2195 | |
| 2196 DCHECK(function_address.is(r4) || function_address.is(r5)); | |
| 2197 Register scratch = r6; | |
| 2198 | |
| 2199 Label profiler_disabled; | |
| 2200 Label end_profiler_check; | |
| 2201 mov(scratch, Operand(ExternalReference::is_profiling_address(isolate()))); | |
| 2202 lbz(scratch, MemOperand(scratch, 0)); | |
| 2203 cmpi(scratch, Operand::Zero()); | |
| 2204 beq(&profiler_disabled); | |
| 2205 | |
| 2206 // Additional parameter is the address of the actual callback. | |
| 2207 mov(scratch, Operand(thunk_ref)); | |
| 2208 jmp(&end_profiler_check); | |
| 2209 | |
| 2210 bind(&profiler_disabled); | |
| 2211 mr(scratch, function_address); | |
| 2212 bind(&end_profiler_check); | |
| 2213 | |
| 2214 // Allocate HandleScope in callee-save registers. | |
| 2215 // r17 - next_address | |
| 2216 // r14 - next_address->kNextOffset | |
| 2217 // r15 - next_address->kLimitOffset | |
| 2218 // r16 - next_address->kLevelOffset | |
| 2219 mov(r17, Operand(next_address)); | |
| 2220 LoadP(r14, MemOperand(r17, kNextOffset)); | |
| 2221 LoadP(r15, MemOperand(r17, kLimitOffset)); | |
| 2222 lwz(r16, MemOperand(r17, kLevelOffset)); | |
| 2223 addi(r16, r16, Operand(1)); | |
| 2224 stw(r16, MemOperand(r17, kLevelOffset)); | |
| 2225 | |
| 2226 if (FLAG_log_timer_events) { | |
| 2227 FrameScope frame(this, StackFrame::MANUAL); | |
| 2228 PushSafepointRegisters(); | |
| 2229 PrepareCallCFunction(1, r3); | |
| 2230 mov(r3, Operand(ExternalReference::isolate_address(isolate()))); | |
| 2231 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); | |
| 2232 PopSafepointRegisters(); | |
| 2233 } | |
| 2234 | |
| 2235 // Native call returns to the DirectCEntry stub which redirects to the | |
| 2236 // return address pushed on stack (could have moved after GC). | |
| 2237 // DirectCEntry stub itself is generated early and never moves. | |
| 2238 DirectCEntryStub stub(isolate()); | |
| 2239 stub.GenerateCall(this, scratch); | |
| 2240 | |
| 2241 if (FLAG_log_timer_events) { | |
| 2242 FrameScope frame(this, StackFrame::MANUAL); | |
| 2243 PushSafepointRegisters(); | |
| 2244 PrepareCallCFunction(1, r3); | |
| 2245 mov(r3, Operand(ExternalReference::isolate_address(isolate()))); | |
| 2246 CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1); | |
| 2247 PopSafepointRegisters(); | |
| 2248 } | |
| 2249 | |
| 2250 Label promote_scheduled_exception; | |
| 2251 Label exception_handled; | |
| 2252 Label delete_allocated_handles; | |
| 2253 Label leave_exit_frame; | |
| 2254 Label return_value_loaded; | |
| 2255 | |
| 2256 // load value from ReturnValue | |
| 2257 LoadP(r3, return_value_operand); | |
| 2258 bind(&return_value_loaded); | |
| 2259 // No more valid handles (the result handle was the last one). Restore | |
| 2260 // previous handle scope. | |
| 2261 StoreP(r14, MemOperand(r17, kNextOffset)); | |
| 2262 if (emit_debug_code()) { | |
| 2263 lwz(r4, MemOperand(r17, kLevelOffset)); | |
| 2264 cmp(r4, r16); | |
| 2265 Check(eq, kUnexpectedLevelAfterReturnFromApiCall); | |
| 2266 } | |
| 2267 subi(r16, r16, Operand(1)); | |
| 2268 stw(r16, MemOperand(r17, kLevelOffset)); | |
| 2269 LoadP(r0, MemOperand(r17, kLimitOffset)); | |
| 2270 cmp(r15, r0); | |
| 2271 bne(&delete_allocated_handles); | |
| 2272 | |
| 2273 // Check if the function scheduled an exception. | |
| 2274 bind(&leave_exit_frame); | |
| 2275 LoadRoot(r14, Heap::kTheHoleValueRootIndex); | |
| 2276 mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate()))); | |
| 2277 LoadP(r15, MemOperand(r15)); | |
| 2278 cmp(r14, r15); | |
| 2279 bne(&promote_scheduled_exception); | |
| 2280 bind(&exception_handled); | |
| 2281 | |
| 2282 bool restore_context = context_restore_operand != NULL; | |
| 2283 if (restore_context) { | |
| 2284 LoadP(cp, *context_restore_operand); | |
| 2285 } | |
| 2286 // LeaveExitFrame expects unwind space to be in a register. | |
| 2287 mov(r14, Operand(stack_space)); | |
| 2288 LeaveExitFrame(false, r14, !restore_context); | |
| 2289 blr(); | |
| 2290 | |
| 2291 bind(&promote_scheduled_exception); | |
| 2292 { | |
| 2293 FrameScope frame(this, StackFrame::INTERNAL); | |
| 2294 CallExternalReference( | |
| 2295 ExternalReference(Runtime::kPromoteScheduledException, isolate()), 0); | |
| 2296 } | |
| 2297 jmp(&exception_handled); | |
| 2298 | |
| 2299 // HandleScope limit has changed. Delete allocated extensions. | |
| 2300 bind(&delete_allocated_handles); | |
| 2301 StoreP(r15, MemOperand(r17, kLimitOffset)); | |
| 2302 mr(r14, r3); | |
| 2303 PrepareCallCFunction(1, r15); | |
| 2304 mov(r3, Operand(ExternalReference::isolate_address(isolate()))); | |
| 2305 CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate()), | |
| 2306 1); | |
| 2307 mr(r3, r14); | |
| 2308 b(&leave_exit_frame); | |
| 2309 } | |
| 2310 | |
| 2311 | |
| 2312 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { | 2186 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { |
| 2313 return has_frame_ || !stub->SometimesSetsUpAFrame(); | 2187 return has_frame_ || !stub->SometimesSetsUpAFrame(); |
| 2314 } | 2188 } |
| 2315 | 2189 |
| 2316 | 2190 |
| 2317 void MacroAssembler::IndexFromHash(Register hash, Register index) { | 2191 void MacroAssembler::IndexFromHash(Register hash, Register index) { |
| 2318 // If the hash field contains an array index pick it out. The assert checks | 2192 // If the hash field contains an array index pick it out. The assert checks |
| 2319 // that the constants for the maximum number of digits for an array index | 2193 // that the constants for the maximum number of digits for an array index |
| 2320 // cached in the hash field and the number of bits reserved for it does not | 2194 // cached in the hash field and the number of bits reserved for it does not |
| 2321 // conflict. | 2195 // conflict. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2345 Label done; | 2219 Label done; |
| 2346 DCHECK(!double_input.is(double_scratch)); | 2220 DCHECK(!double_input.is(double_scratch)); |
| 2347 | 2221 |
| 2348 ConvertDoubleToInt64(double_input, | 2222 ConvertDoubleToInt64(double_input, |
| 2349 #if !V8_TARGET_ARCH_PPC64 | 2223 #if !V8_TARGET_ARCH_PPC64 |
| 2350 scratch, | 2224 scratch, |
| 2351 #endif | 2225 #endif |
| 2352 result, double_scratch); | 2226 result, double_scratch); |
| 2353 | 2227 |
| 2354 #if V8_TARGET_ARCH_PPC64 | 2228 #if V8_TARGET_ARCH_PPC64 |
| 2355 TestIfInt32(result, scratch, r0); | 2229 TestIfInt32(result, r0); |
| 2356 #else | 2230 #else |
| 2357 TestIfInt32(scratch, result, r0); | 2231 TestIfInt32(scratch, result, r0); |
| 2358 #endif | 2232 #endif |
| 2359 bne(&done); | 2233 bne(&done); |
| 2360 | 2234 |
| 2361 // convert back and compare | 2235 // convert back and compare |
| 2362 fcfid(double_scratch, double_scratch); | 2236 fcfid(double_scratch, double_scratch); |
| 2363 fcmpu(double_scratch, double_input); | 2237 fcmpu(double_scratch, double_input); |
| 2364 bind(&done); | 2238 bind(&done); |
| 2365 } | 2239 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2382 | 2256 |
| 2383 // Convert (rounding to -Inf) | 2257 // Convert (rounding to -Inf) |
| 2384 ConvertDoubleToInt64(double_input, | 2258 ConvertDoubleToInt64(double_input, |
| 2385 #if !V8_TARGET_ARCH_PPC64 | 2259 #if !V8_TARGET_ARCH_PPC64 |
| 2386 scratch, | 2260 scratch, |
| 2387 #endif | 2261 #endif |
| 2388 result, double_scratch, kRoundToMinusInf); | 2262 result, double_scratch, kRoundToMinusInf); |
| 2389 | 2263 |
| 2390 // Test for overflow | 2264 // Test for overflow |
| 2391 #if V8_TARGET_ARCH_PPC64 | 2265 #if V8_TARGET_ARCH_PPC64 |
| 2392 TestIfInt32(result, scratch, r0); | 2266 TestIfInt32(result, r0); |
| 2393 #else | 2267 #else |
| 2394 TestIfInt32(scratch, result, r0); | 2268 TestIfInt32(scratch, result, r0); |
| 2395 #endif | 2269 #endif |
| 2396 bne(&exception); | 2270 bne(&exception); |
| 2397 | 2271 |
| 2398 // Test for exactness | 2272 // Test for exactness |
| 2399 fcfid(double_scratch, double_scratch); | 2273 fcfid(double_scratch, double_scratch); |
| 2400 fcmpu(double_scratch, double_input); | 2274 fcmpu(double_scratch, double_input); |
| 2401 beq(exact); | 2275 beq(exact); |
| 2402 b(done); | 2276 b(done); |
| 2403 | 2277 |
| 2404 bind(&exception); | 2278 bind(&exception); |
| 2405 } | 2279 } |
| 2406 | 2280 |
| 2407 | 2281 |
| 2408 void MacroAssembler::TryInlineTruncateDoubleToI(Register result, | 2282 void MacroAssembler::TryInlineTruncateDoubleToI(Register result, |
| 2409 DoubleRegister double_input, | 2283 DoubleRegister double_input, |
| 2410 Label* done) { | 2284 Label* done) { |
| 2411 DoubleRegister double_scratch = kScratchDoubleReg; | 2285 DoubleRegister double_scratch = kScratchDoubleReg; |
| 2286 #if !V8_TARGET_ARCH_PPC64 |
| 2412 Register scratch = ip; | 2287 Register scratch = ip; |
| 2288 #endif |
| 2413 | 2289 |
| 2414 ConvertDoubleToInt64(double_input, | 2290 ConvertDoubleToInt64(double_input, |
| 2415 #if !V8_TARGET_ARCH_PPC64 | 2291 #if !V8_TARGET_ARCH_PPC64 |
| 2416 scratch, | 2292 scratch, |
| 2417 #endif | 2293 #endif |
| 2418 result, double_scratch); | 2294 result, double_scratch); |
| 2419 | 2295 |
| 2420 // Test for overflow | 2296 // Test for overflow |
| 2421 #if V8_TARGET_ARCH_PPC64 | 2297 #if V8_TARGET_ARCH_PPC64 |
| 2422 TestIfInt32(result, scratch, r0); | 2298 TestIfInt32(result, r0); |
| 2423 #else | 2299 #else |
| 2424 TestIfInt32(scratch, result, r0); | 2300 TestIfInt32(scratch, result, r0); |
| 2425 #endif | 2301 #endif |
| 2426 beq(done); | 2302 beq(done); |
| 2427 } | 2303 } |
| 2428 | 2304 |
| 2429 | 2305 |
| 2430 void MacroAssembler::TruncateDoubleToI(Register result, | 2306 void MacroAssembler::TruncateDoubleToI(Register result, |
| 2431 DoubleRegister double_input) { | 2307 DoubleRegister double_input) { |
| 2432 Label done; | 2308 Label done; |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2726 Register map_in_out, Register scratch, Label* no_map_match) { | 2602 Register map_in_out, Register scratch, Label* no_map_match) { |
| 2727 // Load the global or builtins object from the current context. | 2603 // Load the global or builtins object from the current context. |
| 2728 LoadP(scratch, | 2604 LoadP(scratch, |
| 2729 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 2605 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 2730 LoadP(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); | 2606 LoadP(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
| 2731 | 2607 |
| 2732 // Check that the function's map is the same as the expected cached map. | 2608 // Check that the function's map is the same as the expected cached map. |
| 2733 LoadP(scratch, | 2609 LoadP(scratch, |
| 2734 MemOperand(scratch, Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX))); | 2610 MemOperand(scratch, Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX))); |
| 2735 size_t offset = expected_kind * kPointerSize + FixedArrayBase::kHeaderSize; | 2611 size_t offset = expected_kind * kPointerSize + FixedArrayBase::kHeaderSize; |
| 2736 LoadP(scratch, FieldMemOperand(scratch, offset)); | 2612 LoadP(ip, FieldMemOperand(scratch, offset)); |
| 2737 cmp(map_in_out, scratch); | 2613 cmp(map_in_out, ip); |
| 2738 bne(no_map_match); | 2614 bne(no_map_match); |
| 2739 | 2615 |
| 2740 // Use the transitioned cached map. | 2616 // Use the transitioned cached map. |
| 2741 offset = transitioned_kind * kPointerSize + FixedArrayBase::kHeaderSize; | 2617 offset = transitioned_kind * kPointerSize + FixedArrayBase::kHeaderSize; |
| 2742 LoadP(map_in_out, FieldMemOperand(scratch, offset)); | 2618 LoadP(map_in_out, FieldMemOperand(scratch, offset)); |
| 2743 } | 2619 } |
| 2744 | 2620 |
| 2745 | 2621 |
| 2746 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 2622 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 2747 // Load the global or builtins object from the current context. | 2623 // Load the global or builtins object from the current context. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2813 DCHECK(!src.is(overflow)); | 2689 DCHECK(!src.is(overflow)); |
| 2814 SmiTag(dst, src); | 2690 SmiTag(dst, src); |
| 2815 xor_(overflow, dst, src, SetRC); // Overflow if (value ^ 2 * value) < 0. | 2691 xor_(overflow, dst, src, SetRC); // Overflow if (value ^ 2 * value) < 0. |
| 2816 } | 2692 } |
| 2817 } | 2693 } |
| 2818 #endif | 2694 #endif |
| 2819 | 2695 |
| 2820 void MacroAssembler::JumpIfNotBothSmi(Register reg1, Register reg2, | 2696 void MacroAssembler::JumpIfNotBothSmi(Register reg1, Register reg2, |
| 2821 Label* on_not_both_smi) { | 2697 Label* on_not_both_smi) { |
| 2822 STATIC_ASSERT(kSmiTag == 0); | 2698 STATIC_ASSERT(kSmiTag == 0); |
| 2823 DCHECK_EQ(1, static_cast<int>(kSmiTagMask)); | |
| 2824 orx(r0, reg1, reg2, LeaveRC); | 2699 orx(r0, reg1, reg2, LeaveRC); |
| 2825 JumpIfNotSmi(r0, on_not_both_smi); | 2700 JumpIfNotSmi(r0, on_not_both_smi); |
| 2826 } | 2701 } |
| 2827 | 2702 |
| 2828 | 2703 |
| 2829 void MacroAssembler::UntagAndJumpIfSmi(Register dst, Register src, | 2704 void MacroAssembler::UntagAndJumpIfSmi(Register dst, Register src, |
| 2830 Label* smi_case) { | 2705 Label* smi_case) { |
| 2831 STATIC_ASSERT(kSmiTag == 0); | 2706 STATIC_ASSERT(kSmiTag == 0); |
| 2832 STATIC_ASSERT(kSmiTagSize == 1); | 2707 TestBitRange(src, kSmiTagSize - 1, 0, r0); |
| 2833 TestBit(src, 0, r0); | |
| 2834 SmiUntag(dst, src); | 2708 SmiUntag(dst, src); |
| 2835 beq(smi_case, cr0); | 2709 beq(smi_case, cr0); |
| 2836 } | 2710 } |
| 2837 | 2711 |
| 2838 | 2712 |
| 2839 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst, Register src, | 2713 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst, Register src, |
| 2840 Label* non_smi_case) { | 2714 Label* non_smi_case) { |
| 2841 STATIC_ASSERT(kSmiTag == 0); | 2715 STATIC_ASSERT(kSmiTag == 0); |
| 2842 STATIC_ASSERT(kSmiTagSize == 1); | 2716 TestBitRange(src, kSmiTagSize - 1, 0, r0); |
| 2843 TestBit(src, 0, r0); | |
| 2844 SmiUntag(dst, src); | 2717 SmiUntag(dst, src); |
| 2845 bne(non_smi_case, cr0); | 2718 bne(non_smi_case, cr0); |
| 2846 } | 2719 } |
| 2847 | 2720 |
| 2848 | 2721 |
| 2849 void MacroAssembler::JumpIfEitherSmi(Register reg1, Register reg2, | 2722 void MacroAssembler::JumpIfEitherSmi(Register reg1, Register reg2, |
| 2850 Label* on_either_smi) { | 2723 Label* on_either_smi) { |
| 2851 STATIC_ASSERT(kSmiTag == 0); | 2724 STATIC_ASSERT(kSmiTag == 0); |
| 2852 JumpIfSmi(reg1, on_either_smi); | 2725 JumpIfSmi(reg1, on_either_smi); |
| 2853 JumpIfSmi(reg2, on_either_smi); | 2726 JumpIfSmi(reg2, on_either_smi); |
| (...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3686 | 3559 |
| 3687 if (cc == ne) { | 3560 if (cc == ne) { |
| 3688 bne(condition_met, cr0); | 3561 bne(condition_met, cr0); |
| 3689 } | 3562 } |
| 3690 if (cc == eq) { | 3563 if (cc == eq) { |
| 3691 beq(condition_met, cr0); | 3564 beq(condition_met, cr0); |
| 3692 } | 3565 } |
| 3693 } | 3566 } |
| 3694 | 3567 |
| 3695 | 3568 |
| 3696 void MacroAssembler::CheckMapDeprecated(Handle<Map> map, Register scratch, | |
| 3697 Label* if_deprecated) { | |
| 3698 if (map->CanBeDeprecated()) { | |
| 3699 mov(scratch, Operand(map)); | |
| 3700 lwz(scratch, FieldMemOperand(scratch, Map::kBitField3Offset)); | |
| 3701 ExtractBitMask(scratch, scratch, Map::Deprecated::kMask, SetRC); | |
| 3702 bne(if_deprecated, cr0); | |
| 3703 } | |
| 3704 } | |
| 3705 | |
| 3706 | |
| 3707 void MacroAssembler::JumpIfBlack(Register object, Register scratch0, | 3569 void MacroAssembler::JumpIfBlack(Register object, Register scratch0, |
| 3708 Register scratch1, Label* on_black) { | 3570 Register scratch1, Label* on_black) { |
| 3709 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. | 3571 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. |
| 3710 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); | 3572 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| 3711 } | 3573 } |
| 3712 | 3574 |
| 3713 | 3575 |
| 3714 void MacroAssembler::HasColor(Register object, Register bitmap_scratch, | 3576 void MacroAssembler::HasColor(Register object, Register bitmap_scratch, |
| 3715 Register mask_scratch, Label* has_color, | 3577 Register mask_scratch, Label* has_color, |
| 3716 int first_bit, int second_bit) { | 3578 int first_bit, int second_bit) { |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3889 | 3751 |
| 3890 bind(&done); | 3752 bind(&done); |
| 3891 } | 3753 } |
| 3892 | 3754 |
| 3893 | 3755 |
| 3894 // Saturate a value into 8-bit unsigned integer | 3756 // Saturate a value into 8-bit unsigned integer |
| 3895 // if input_value < 0, output_value is 0 | 3757 // if input_value < 0, output_value is 0 |
| 3896 // if input_value > 255, output_value is 255 | 3758 // if input_value > 255, output_value is 255 |
| 3897 // otherwise output_value is the input_value | 3759 // otherwise output_value is the input_value |
| 3898 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { | 3760 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { |
| 3899 Label done, negative_label, overflow_label; | |
| 3900 int satval = (1 << 8) - 1; | 3761 int satval = (1 << 8) - 1; |
| 3901 | 3762 |
| 3902 cmpi(input_reg, Operand::Zero()); | 3763 if (CpuFeatures::IsSupported(ISELECT)) { |
| 3903 blt(&negative_label); | 3764 // set to 0 if negative |
| 3765 cmpi(input_reg, Operand::Zero()); |
| 3766 isel(lt, output_reg, r0, input_reg); |
| 3904 | 3767 |
| 3905 cmpi(input_reg, Operand(satval)); | 3768 // set to satval if > satval |
| 3906 bgt(&overflow_label); | 3769 li(r0, Operand(satval)); |
| 3907 if (!output_reg.is(input_reg)) { | 3770 cmpi(output_reg, Operand(satval)); |
| 3908 mr(output_reg, input_reg); | 3771 isel(lt, output_reg, output_reg, r0); |
| 3772 } else { |
| 3773 Label done, negative_label, overflow_label; |
| 3774 cmpi(input_reg, Operand::Zero()); |
| 3775 blt(&negative_label); |
| 3776 |
| 3777 cmpi(input_reg, Operand(satval)); |
| 3778 bgt(&overflow_label); |
| 3779 if (!output_reg.is(input_reg)) { |
| 3780 mr(output_reg, input_reg); |
| 3781 } |
| 3782 b(&done); |
| 3783 |
| 3784 bind(&negative_label); |
| 3785 li(output_reg, Operand::Zero()); // set to 0 if negative |
| 3786 b(&done); |
| 3787 |
| 3788 bind(&overflow_label); // set to satval if > satval |
| 3789 li(output_reg, Operand(satval)); |
| 3790 |
| 3791 bind(&done); |
| 3909 } | 3792 } |
| 3910 b(&done); | |
| 3911 | |
| 3912 bind(&negative_label); | |
| 3913 li(output_reg, Operand::Zero()); // set to 0 if negative | |
| 3914 b(&done); | |
| 3915 | |
| 3916 | |
| 3917 bind(&overflow_label); // set to satval if > satval | |
| 3918 li(output_reg, Operand(satval)); | |
| 3919 | |
| 3920 bind(&done); | |
| 3921 } | 3793 } |
| 3922 | 3794 |
| 3923 | 3795 |
| 3924 void MacroAssembler::SetRoundingMode(FPRoundingMode RN) { mtfsfi(7, RN); } | 3796 void MacroAssembler::SetRoundingMode(FPRoundingMode RN) { mtfsfi(7, RN); } |
| 3925 | 3797 |
| 3926 | 3798 |
| 3927 void MacroAssembler::ResetRoundingMode() { | 3799 void MacroAssembler::ResetRoundingMode() { |
| 3928 mtfsfi(7, kRoundToNearest); // reset (default is kRoundToNearest) | 3800 mtfsfi(7, kRoundToNearest); // reset (default is kRoundToNearest) |
| 3929 } | 3801 } |
| 3930 | 3802 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3975 | 3847 |
| 3976 | 3848 |
| 3977 void MacroAssembler::EnumLength(Register dst, Register map) { | 3849 void MacroAssembler::EnumLength(Register dst, Register map) { |
| 3978 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); | 3850 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); |
| 3979 lwz(dst, FieldMemOperand(map, Map::kBitField3Offset)); | 3851 lwz(dst, FieldMemOperand(map, Map::kBitField3Offset)); |
| 3980 ExtractBitMask(dst, dst, Map::EnumLengthBits::kMask); | 3852 ExtractBitMask(dst, dst, Map::EnumLengthBits::kMask); |
| 3981 SmiTag(dst); | 3853 SmiTag(dst); |
| 3982 } | 3854 } |
| 3983 | 3855 |
| 3984 | 3856 |
| 3857 void MacroAssembler::LoadAccessor(Register dst, Register holder, |
| 3858 int accessor_index, |
| 3859 AccessorComponent accessor) { |
| 3860 LoadP(dst, FieldMemOperand(holder, HeapObject::kMapOffset)); |
| 3861 LoadInstanceDescriptors(dst, dst); |
| 3862 LoadP(dst, |
| 3863 FieldMemOperand(dst, DescriptorArray::GetValueOffset(accessor_index))); |
| 3864 const int getterOffset = AccessorPair::kGetterOffset; |
| 3865 const int setterOffset = AccessorPair::kSetterOffset; |
| 3866 int offset = ((accessor == ACCESSOR_GETTER) ? getterOffset : setterOffset); |
| 3867 LoadP(dst, FieldMemOperand(dst, offset)); |
| 3868 } |
| 3869 |
| 3870 |
| 3985 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { | 3871 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { |
| 3986 Register empty_fixed_array_value = r9; | 3872 Register empty_fixed_array_value = r9; |
| 3987 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | 3873 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); |
| 3988 Label next, start; | 3874 Label next, start; |
| 3989 mr(r5, r3); | 3875 mr(r5, r3); |
| 3990 | 3876 |
| 3991 // Check if the enum length field is properly initialized, indicating that | 3877 // Check if the enum length field is properly initialized, indicating that |
| 3992 // there is an enum cache. | 3878 // there is an enum cache. |
| 3993 LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset)); | 3879 LoadP(r4, FieldMemOperand(r5, HeapObject::kMapOffset)); |
| 3994 | 3880 |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4415 And(dst, src, Operand(smi), rc); | 4301 And(dst, src, Operand(smi), rc); |
| 4416 #endif | 4302 #endif |
| 4417 } | 4303 } |
| 4418 | 4304 |
| 4419 | 4305 |
| 4420 // Load a "pointer" sized value from the memory location | 4306 // Load a "pointer" sized value from the memory location |
| 4421 void MacroAssembler::LoadP(Register dst, const MemOperand& mem, | 4307 void MacroAssembler::LoadP(Register dst, const MemOperand& mem, |
| 4422 Register scratch) { | 4308 Register scratch) { |
| 4423 int offset = mem.offset(); | 4309 int offset = mem.offset(); |
| 4424 | 4310 |
| 4425 if (!scratch.is(no_reg) && !is_int16(offset)) { | 4311 if (!is_int16(offset)) { |
| 4426 /* cannot use d-form */ | 4312 /* cannot use d-form */ |
| 4427 LoadIntLiteral(scratch, offset); | 4313 DCHECK(!scratch.is(no_reg)); |
| 4314 mov(scratch, Operand(offset)); |
| 4428 #if V8_TARGET_ARCH_PPC64 | 4315 #if V8_TARGET_ARCH_PPC64 |
| 4429 ldx(dst, MemOperand(mem.ra(), scratch)); | 4316 ldx(dst, MemOperand(mem.ra(), scratch)); |
| 4430 #else | 4317 #else |
| 4431 lwzx(dst, MemOperand(mem.ra(), scratch)); | 4318 lwzx(dst, MemOperand(mem.ra(), scratch)); |
| 4432 #endif | 4319 #endif |
| 4433 } else { | 4320 } else { |
| 4434 #if V8_TARGET_ARCH_PPC64 | 4321 #if V8_TARGET_ARCH_PPC64 |
| 4435 int misaligned = (offset & 3); | 4322 int misaligned = (offset & 3); |
| 4436 if (misaligned) { | 4323 if (misaligned) { |
| 4437 // adjust base to conform to offset alignment requirements | 4324 // adjust base to conform to offset alignment requirements |
| 4438 // Todo: enhance to use scratch if dst is unsuitable | 4325 // Todo: enhance to use scratch if dst is unsuitable |
| 4439 DCHECK(!dst.is(r0)); | 4326 DCHECK(!dst.is(r0)); |
| 4440 addi(dst, mem.ra(), Operand((offset & 3) - 4)); | 4327 addi(dst, mem.ra(), Operand((offset & 3) - 4)); |
| 4441 ld(dst, MemOperand(dst, (offset & ~3) + 4)); | 4328 ld(dst, MemOperand(dst, (offset & ~3) + 4)); |
| 4442 } else { | 4329 } else { |
| 4443 ld(dst, mem); | 4330 ld(dst, mem); |
| 4444 } | 4331 } |
| 4445 #else | 4332 #else |
| 4446 lwz(dst, mem); | 4333 lwz(dst, mem); |
| 4447 #endif | 4334 #endif |
| 4448 } | 4335 } |
| 4449 } | 4336 } |
| 4450 | 4337 |
| 4451 | 4338 |
| 4452 // Store a "pointer" sized value to the memory location | 4339 // Store a "pointer" sized value to the memory location |
| 4453 void MacroAssembler::StoreP(Register src, const MemOperand& mem, | 4340 void MacroAssembler::StoreP(Register src, const MemOperand& mem, |
| 4454 Register scratch) { | 4341 Register scratch) { |
| 4455 int offset = mem.offset(); | 4342 int offset = mem.offset(); |
| 4456 | 4343 |
| 4457 if (!scratch.is(no_reg) && !is_int16(offset)) { | 4344 if (!is_int16(offset)) { |
| 4458 /* cannot use d-form */ | 4345 /* cannot use d-form */ |
| 4459 LoadIntLiteral(scratch, offset); | 4346 DCHECK(!scratch.is(no_reg)); |
| 4347 mov(scratch, Operand(offset)); |
| 4460 #if V8_TARGET_ARCH_PPC64 | 4348 #if V8_TARGET_ARCH_PPC64 |
| 4461 stdx(src, MemOperand(mem.ra(), scratch)); | 4349 stdx(src, MemOperand(mem.ra(), scratch)); |
| 4462 #else | 4350 #else |
| 4463 stwx(src, MemOperand(mem.ra(), scratch)); | 4351 stwx(src, MemOperand(mem.ra(), scratch)); |
| 4464 #endif | 4352 #endif |
| 4465 } else { | 4353 } else { |
| 4466 #if V8_TARGET_ARCH_PPC64 | 4354 #if V8_TARGET_ARCH_PPC64 |
| 4467 int misaligned = (offset & 3); | 4355 int misaligned = (offset & 3); |
| 4468 if (misaligned) { | 4356 if (misaligned) { |
| 4469 // adjust base to conform to offset alignment requirements | 4357 // adjust base to conform to offset alignment requirements |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4482 #else | 4370 #else |
| 4483 stw(src, mem); | 4371 stw(src, mem); |
| 4484 #endif | 4372 #endif |
| 4485 } | 4373 } |
| 4486 } | 4374 } |
| 4487 | 4375 |
| 4488 void MacroAssembler::LoadWordArith(Register dst, const MemOperand& mem, | 4376 void MacroAssembler::LoadWordArith(Register dst, const MemOperand& mem, |
| 4489 Register scratch) { | 4377 Register scratch) { |
| 4490 int offset = mem.offset(); | 4378 int offset = mem.offset(); |
| 4491 | 4379 |
| 4492 if (!scratch.is(no_reg) && !is_int16(offset)) { | 4380 if (!is_int16(offset)) { |
| 4493 /* cannot use d-form */ | 4381 DCHECK(!scratch.is(no_reg)); |
| 4494 LoadIntLiteral(scratch, offset); | 4382 mov(scratch, Operand(offset)); |
| 4495 #if V8_TARGET_ARCH_PPC64 | 4383 lwax(dst, MemOperand(mem.ra(), scratch)); |
| 4496 // lwax(dst, MemOperand(mem.ra(), scratch)); | |
| 4497 DCHECK(0); // lwax not yet implemented | |
| 4498 #else | |
| 4499 lwzx(dst, MemOperand(mem.ra(), scratch)); | |
| 4500 #endif | |
| 4501 } else { | 4384 } else { |
| 4502 #if V8_TARGET_ARCH_PPC64 | 4385 #if V8_TARGET_ARCH_PPC64 |
| 4503 int misaligned = (offset & 3); | 4386 int misaligned = (offset & 3); |
| 4504 if (misaligned) { | 4387 if (misaligned) { |
| 4505 // adjust base to conform to offset alignment requirements | 4388 // adjust base to conform to offset alignment requirements |
| 4506 // Todo: enhance to use scratch if dst is unsuitable | 4389 // Todo: enhance to use scratch if dst is unsuitable |
| 4507 DCHECK(!dst.is(r0)); | 4390 DCHECK(!dst.is(r0)); |
| 4508 addi(dst, mem.ra(), Operand((offset & 3) - 4)); | 4391 addi(dst, mem.ra(), Operand((offset & 3) - 4)); |
| 4509 lwa(dst, MemOperand(dst, (offset & ~3) + 4)); | 4392 lwa(dst, MemOperand(dst, (offset & ~3) + 4)); |
| 4510 } else { | 4393 } else { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4542 | 4425 |
| 4543 if (!is_int16(offset)) { | 4426 if (!is_int16(offset)) { |
| 4544 LoadIntLiteral(scratch, offset); | 4427 LoadIntLiteral(scratch, offset); |
| 4545 stwx(src, MemOperand(base, scratch)); | 4428 stwx(src, MemOperand(base, scratch)); |
| 4546 } else { | 4429 } else { |
| 4547 stw(src, mem); | 4430 stw(src, mem); |
| 4548 } | 4431 } |
| 4549 } | 4432 } |
| 4550 | 4433 |
| 4551 | 4434 |
| 4435 void MacroAssembler::LoadHalfWordArith(Register dst, const MemOperand& mem, |
| 4436 Register scratch) { |
| 4437 int offset = mem.offset(); |
| 4438 |
| 4439 if (!is_int16(offset)) { |
| 4440 DCHECK(!scratch.is(no_reg)); |
| 4441 mov(scratch, Operand(offset)); |
| 4442 lhax(dst, MemOperand(mem.ra(), scratch)); |
| 4443 } else { |
| 4444 lha(dst, mem); |
| 4445 } |
| 4446 } |
| 4447 |
| 4448 |
| 4552 // Variable length depending on whether offset fits into immediate field | 4449 // Variable length depending on whether offset fits into immediate field |
| 4553 // MemOperand currently only supports d-form | 4450 // MemOperand currently only supports d-form |
| 4554 void MacroAssembler::LoadHalfWord(Register dst, const MemOperand& mem, | 4451 void MacroAssembler::LoadHalfWord(Register dst, const MemOperand& mem, |
| 4555 Register scratch) { | 4452 Register scratch) { |
| 4556 Register base = mem.ra(); | 4453 Register base = mem.ra(); |
| 4557 int offset = mem.offset(); | 4454 int offset = mem.offset(); |
| 4558 | 4455 |
| 4559 if (!is_int16(offset)) { | 4456 if (!is_int16(offset)) { |
| 4560 LoadIntLiteral(scratch, offset); | 4457 LoadIntLiteral(scratch, offset); |
| 4561 lhzx(dst, MemOperand(base, scratch)); | 4458 lhzx(dst, MemOperand(base, scratch)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4615 | 4512 |
| 4616 void MacroAssembler::LoadRepresentation(Register dst, const MemOperand& mem, | 4513 void MacroAssembler::LoadRepresentation(Register dst, const MemOperand& mem, |
| 4617 Representation r, Register scratch) { | 4514 Representation r, Register scratch) { |
| 4618 DCHECK(!r.IsDouble()); | 4515 DCHECK(!r.IsDouble()); |
| 4619 if (r.IsInteger8()) { | 4516 if (r.IsInteger8()) { |
| 4620 LoadByte(dst, mem, scratch); | 4517 LoadByte(dst, mem, scratch); |
| 4621 extsb(dst, dst); | 4518 extsb(dst, dst); |
| 4622 } else if (r.IsUInteger8()) { | 4519 } else if (r.IsUInteger8()) { |
| 4623 LoadByte(dst, mem, scratch); | 4520 LoadByte(dst, mem, scratch); |
| 4624 } else if (r.IsInteger16()) { | 4521 } else if (r.IsInteger16()) { |
| 4625 LoadHalfWord(dst, mem, scratch); | 4522 LoadHalfWordArith(dst, mem, scratch); |
| 4626 extsh(dst, dst); | |
| 4627 } else if (r.IsUInteger16()) { | 4523 } else if (r.IsUInteger16()) { |
| 4628 LoadHalfWord(dst, mem, scratch); | 4524 LoadHalfWord(dst, mem, scratch); |
| 4629 #if V8_TARGET_ARCH_PPC64 | 4525 #if V8_TARGET_ARCH_PPC64 |
| 4630 } else if (r.IsInteger32()) { | 4526 } else if (r.IsInteger32()) { |
| 4631 LoadWord(dst, mem, scratch); | 4527 LoadWordArith(dst, mem, scratch); |
| 4632 #endif | 4528 #endif |
| 4633 } else { | 4529 } else { |
| 4634 LoadP(dst, mem, scratch); | 4530 LoadP(dst, mem, scratch); |
| 4635 } | 4531 } |
| 4636 } | 4532 } |
| 4637 | 4533 |
| 4638 | 4534 |
| 4639 void MacroAssembler::StoreRepresentation(Register src, const MemOperand& mem, | 4535 void MacroAssembler::StoreRepresentation(Register src, const MemOperand& mem, |
| 4640 Representation r, Register scratch) { | 4536 Representation r, Register scratch) { |
| 4641 DCHECK(!r.IsDouble()); | 4537 DCHECK(!r.IsDouble()); |
| 4642 if (r.IsInteger8() || r.IsUInteger8()) { | 4538 if (r.IsInteger8() || r.IsUInteger8()) { |
| 4643 StoreByte(src, mem, scratch); | 4539 StoreByte(src, mem, scratch); |
| 4644 } else if (r.IsInteger16() || r.IsUInteger16()) { | 4540 } else if (r.IsInteger16() || r.IsUInteger16()) { |
| 4645 StoreHalfWord(src, mem, scratch); | 4541 StoreHalfWord(src, mem, scratch); |
| 4646 #if V8_TARGET_ARCH_PPC64 | 4542 #if V8_TARGET_ARCH_PPC64 |
| 4647 } else if (r.IsInteger32()) { | 4543 } else if (r.IsInteger32()) { |
| 4648 StoreWord(src, mem, scratch); | 4544 StoreWord(src, mem, scratch); |
| 4649 #endif | 4545 #endif |
| 4650 } else { | 4546 } else { |
| 4651 if (r.IsHeapObject()) { | 4547 if (r.IsHeapObject()) { |
| 4652 AssertNotSmi(src); | 4548 AssertNotSmi(src); |
| 4653 } else if (r.IsSmi()) { | 4549 } else if (r.IsSmi()) { |
| 4654 AssertSmi(src); | 4550 AssertSmi(src); |
| 4655 } | 4551 } |
| 4656 StoreP(src, mem, scratch); | 4552 StoreP(src, mem, scratch); |
| 4657 } | 4553 } |
| 4658 } | 4554 } |
| 4659 | 4555 |
| 4660 | 4556 |
| 4557 void MacroAssembler::LoadDouble(DoubleRegister dst, const MemOperand& mem, |
| 4558 Register scratch) { |
| 4559 Register base = mem.ra(); |
| 4560 int offset = mem.offset(); |
| 4561 |
| 4562 if (!is_int16(offset)) { |
| 4563 mov(scratch, Operand(offset)); |
| 4564 lfdx(dst, MemOperand(base, scratch)); |
| 4565 } else { |
| 4566 lfd(dst, mem); |
| 4567 } |
| 4568 } |
| 4569 |
| 4570 |
| 4571 void MacroAssembler::StoreDouble(DoubleRegister src, const MemOperand& mem, |
| 4572 Register scratch) { |
| 4573 Register base = mem.ra(); |
| 4574 int offset = mem.offset(); |
| 4575 |
| 4576 if (!is_int16(offset)) { |
| 4577 mov(scratch, Operand(offset)); |
| 4578 stfdx(src, MemOperand(base, scratch)); |
| 4579 } else { |
| 4580 stfd(src, mem); |
| 4581 } |
| 4582 } |
| 4583 |
| 4584 |
| 4661 void MacroAssembler::TestJSArrayForAllocationMemento(Register receiver_reg, | 4585 void MacroAssembler::TestJSArrayForAllocationMemento(Register receiver_reg, |
| 4662 Register scratch_reg, | 4586 Register scratch_reg, |
| 4663 Label* no_memento_found) { | 4587 Label* no_memento_found) { |
| 4664 ExternalReference new_space_start = | 4588 ExternalReference new_space_start = |
| 4665 ExternalReference::new_space_start(isolate()); | 4589 ExternalReference::new_space_start(isolate()); |
| 4666 ExternalReference new_space_allocation_top = | 4590 ExternalReference new_space_allocation_top = |
| 4667 ExternalReference::new_space_allocation_top_address(isolate()); | 4591 ExternalReference::new_space_allocation_top_address(isolate()); |
| 4668 addi(scratch_reg, receiver_reg, | 4592 addi(scratch_reg, receiver_reg, |
| 4669 Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag)); | 4593 Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag)); |
| 4670 Cmpi(scratch_reg, Operand(new_space_start), r0); | 4594 Cmpi(scratch_reg, Operand(new_space_start), r0); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4810 } | 4734 } |
| 4811 if (mag.shift > 0) srawi(result, result, mag.shift); | 4735 if (mag.shift > 0) srawi(result, result, mag.shift); |
| 4812 ExtractBit(r0, dividend, 31); | 4736 ExtractBit(r0, dividend, 31); |
| 4813 add(result, result, r0); | 4737 add(result, result, r0); |
| 4814 } | 4738 } |
| 4815 | 4739 |
| 4816 } // namespace internal | 4740 } // namespace internal |
| 4817 } // namespace v8 | 4741 } // namespace v8 |
| 4818 | 4742 |
| 4819 #endif // V8_TARGET_ARCH_PPC | 4743 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |