| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 2027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2038 } | 2038 } |
| 2039 | 2039 |
| 2040 | 2040 |
| 2041 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { | 2041 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { |
| 2042 // Set the entry point and jump to the C entry runtime stub. | 2042 // Set the entry point and jump to the C entry runtime stub. |
| 2043 mov(ebx, Immediate(ext)); | 2043 mov(ebx, Immediate(ext)); |
| 2044 CEntryStub ces(isolate(), 1); | 2044 CEntryStub ces(isolate(), 1); |
| 2045 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); | 2045 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); |
| 2046 } | 2046 } |
| 2047 | 2047 |
| 2048 void MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count, | 2048 void MacroAssembler::PrepareForTailCall( |
| 2049 Register caller_args_count_reg, | 2049 const ParameterCount& callee_args_count, Register caller_args_count_reg, |
| 2050 Register scratch0, Register scratch1, | 2050 Register scratch0, Register scratch1, ReturnAddressState ra_state, |
| 2051 ReturnAddressState ra_state) { | 2051 int number_of_temp_values_after_return_address) { |
| 2052 #if DEBUG | 2052 #if DEBUG |
| 2053 if (callee_args_count.is_reg()) { | 2053 if (callee_args_count.is_reg()) { |
| 2054 DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0, | 2054 DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0, |
| 2055 scratch1)); | 2055 scratch1)); |
| 2056 } else { | 2056 } else { |
| 2057 DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1)); | 2057 DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1)); |
| 2058 } | 2058 } |
| 2059 DCHECK(ra_state != ReturnAddressState::kNotOnStack || |
| 2060 number_of_temp_values_after_return_address == 0); |
| 2059 #endif | 2061 #endif |
| 2060 | 2062 |
| 2061 // Calculate the destination address where we will put the return address | 2063 // Calculate the destination address where we will put the return address |
| 2062 // after we drop current frame. | 2064 // after we drop current frame. |
| 2063 Register new_sp_reg = scratch0; | 2065 Register new_sp_reg = scratch0; |
| 2064 if (callee_args_count.is_reg()) { | 2066 if (callee_args_count.is_reg()) { |
| 2065 sub(caller_args_count_reg, callee_args_count.reg()); | 2067 sub(caller_args_count_reg, callee_args_count.reg()); |
| 2066 lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size, | 2068 lea(new_sp_reg, |
| 2067 StandardFrameConstants::kCallerPCOffset)); | 2069 Operand(ebp, caller_args_count_reg, times_pointer_size, |
| 2070 StandardFrameConstants::kCallerPCOffset - |
| 2071 number_of_temp_values_after_return_address * kPointerSize)); |
| 2068 } else { | 2072 } else { |
| 2069 lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size, | 2073 lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size, |
| 2070 StandardFrameConstants::kCallerPCOffset - | 2074 StandardFrameConstants::kCallerPCOffset - |
| 2071 callee_args_count.immediate() * kPointerSize)); | 2075 (callee_args_count.immediate() + |
| 2076 number_of_temp_values_after_return_address) * |
| 2077 kPointerSize)); |
| 2072 } | 2078 } |
| 2073 | 2079 |
| 2074 if (FLAG_debug_code) { | 2080 if (FLAG_debug_code) { |
| 2075 cmp(esp, new_sp_reg); | 2081 cmp(esp, new_sp_reg); |
| 2076 Check(below, kStackAccessBelowStackPointer); | 2082 Check(below, kStackAccessBelowStackPointer); |
| 2077 } | 2083 } |
| 2078 | 2084 |
| 2079 // Copy return address from caller's frame to current frame's return address | 2085 // Copy return address from caller's frame to current frame's return address |
| 2080 // to avoid its trashing and let the following loop copy it to the right | 2086 // to avoid its trashing and let the following loop copy it to the right |
| 2081 // place. | 2087 // place. |
| 2082 Register tmp_reg = scratch1; | 2088 Register tmp_reg = scratch1; |
| 2083 if (ra_state == ReturnAddressState::kOnStack) { | 2089 if (ra_state == ReturnAddressState::kOnStack) { |
| 2084 mov(tmp_reg, Operand(ebp, StandardFrameConstants::kCallerPCOffset)); | 2090 mov(tmp_reg, Operand(ebp, StandardFrameConstants::kCallerPCOffset)); |
| 2085 mov(Operand(esp, 0), tmp_reg); | 2091 mov(Operand(esp, number_of_temp_values_after_return_address * kPointerSize), |
| 2092 tmp_reg); |
| 2086 } else { | 2093 } else { |
| 2087 DCHECK(ReturnAddressState::kNotOnStack == ra_state); | 2094 DCHECK(ReturnAddressState::kNotOnStack == ra_state); |
| 2095 DCHECK_EQ(0, number_of_temp_values_after_return_address); |
| 2088 Push(Operand(ebp, StandardFrameConstants::kCallerPCOffset)); | 2096 Push(Operand(ebp, StandardFrameConstants::kCallerPCOffset)); |
| 2089 } | 2097 } |
| 2090 | 2098 |
| 2091 // Restore caller's frame pointer now as it could be overwritten by | 2099 // Restore caller's frame pointer now as it could be overwritten by |
| 2092 // the copying loop. | 2100 // the copying loop. |
| 2093 mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2101 mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2094 | 2102 |
| 2095 // +2 here is to copy both receiver and return address. | 2103 // +2 here is to copy both receiver and return address. |
| 2096 Register count_reg = caller_args_count_reg; | 2104 Register count_reg = caller_args_count_reg; |
| 2097 if (callee_args_count.is_reg()) { | 2105 if (callee_args_count.is_reg()) { |
| 2098 lea(count_reg, Operand(callee_args_count.reg(), 2)); | 2106 lea(count_reg, Operand(callee_args_count.reg(), |
| 2107 2 + number_of_temp_values_after_return_address)); |
| 2099 } else { | 2108 } else { |
| 2100 mov(count_reg, Immediate(callee_args_count.immediate() + 2)); | 2109 mov(count_reg, Immediate(callee_args_count.immediate() + 2 + |
| 2110 number_of_temp_values_after_return_address)); |
| 2101 // TODO(ishell): Unroll copying loop for small immediate values. | 2111 // TODO(ishell): Unroll copying loop for small immediate values. |
| 2102 } | 2112 } |
| 2103 | 2113 |
| 2104 // Now copy callee arguments to the caller frame going backwards to avoid | 2114 // Now copy callee arguments to the caller frame going backwards to avoid |
| 2105 // callee arguments corruption (source and destination areas could overlap). | 2115 // callee arguments corruption (source and destination areas could overlap). |
| 2106 Label loop, entry; | 2116 Label loop, entry; |
| 2107 jmp(&entry, Label::kNear); | 2117 jmp(&entry, Label::kNear); |
| 2108 bind(&loop); | 2118 bind(&loop); |
| 2109 dec(count_reg); | 2119 dec(count_reg); |
| 2110 mov(tmp_reg, Operand(esp, count_reg, times_pointer_size, 0)); | 2120 mov(tmp_reg, Operand(esp, count_reg, times_pointer_size, 0)); |
| (...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3167 mov(eax, dividend); | 3177 mov(eax, dividend); |
| 3168 shr(eax, 31); | 3178 shr(eax, 31); |
| 3169 add(edx, eax); | 3179 add(edx, eax); |
| 3170 } | 3180 } |
| 3171 | 3181 |
| 3172 | 3182 |
| 3173 } // namespace internal | 3183 } // namespace internal |
| 3174 } // namespace v8 | 3184 } // namespace v8 |
| 3175 | 3185 |
| 3176 #endif // V8_TARGET_ARCH_X87 | 3186 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |