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 |