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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
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 2068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2079 } | 2079 } |
2080 | 2080 |
2081 | 2081 |
2082 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { | 2082 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { |
2083 // Set the entry point and jump to the C entry runtime stub. | 2083 // Set the entry point and jump to the C entry runtime stub. |
2084 mov(ebx, Immediate(ext)); | 2084 mov(ebx, Immediate(ext)); |
2085 CEntryStub ces(isolate(), 1); | 2085 CEntryStub ces(isolate(), 1); |
2086 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); | 2086 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); |
2087 } | 2087 } |
2088 | 2088 |
| 2089 void MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count, |
| 2090 Register caller_args_count_reg, |
| 2091 Register scratch0, Register scratch1, |
| 2092 ReturnAddressState ra_state) { |
| 2093 #if DEBUG |
| 2094 if (callee_args_count.is_reg()) { |
| 2095 DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0, |
| 2096 scratch1)); |
| 2097 } else { |
| 2098 DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1)); |
| 2099 } |
| 2100 #endif |
| 2101 |
| 2102 // Calculate the destination address where we will put the return address |
| 2103 // after we drop current frame. |
| 2104 Register new_sp_reg = scratch0; |
| 2105 if (callee_args_count.is_reg()) { |
| 2106 sub(caller_args_count_reg, callee_args_count.reg()); |
| 2107 lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size, |
| 2108 StandardFrameConstants::kCallerPCOffset)); |
| 2109 } else { |
| 2110 lea(new_sp_reg, Operand(ebp, caller_args_count_reg, times_pointer_size, |
| 2111 StandardFrameConstants::kCallerPCOffset - |
| 2112 callee_args_count.immediate() * kPointerSize)); |
| 2113 } |
| 2114 |
| 2115 if (FLAG_debug_code) { |
| 2116 cmp(esp, new_sp_reg); |
| 2117 Check(below, kStackAccessBelowStackPointer); |
| 2118 } |
| 2119 |
| 2120 // Copy return address from caller's frame to current frame's return address |
| 2121 // to avoid its trashing and let the following loop copy it to the right |
| 2122 // place. |
| 2123 Register tmp_reg = scratch1; |
| 2124 if (ra_state == ReturnAddressState::kOnStack) { |
| 2125 mov(tmp_reg, Operand(ebp, StandardFrameConstants::kCallerPCOffset)); |
| 2126 mov(Operand(esp, 0), tmp_reg); |
| 2127 } else { |
| 2128 DCHECK(ReturnAddressState::kNotOnStack == ra_state); |
| 2129 Push(Operand(ebp, StandardFrameConstants::kCallerPCOffset)); |
| 2130 } |
| 2131 |
| 2132 // Restore caller's frame pointer now as it could be overwritten by |
| 2133 // the copying loop. |
| 2134 mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2135 |
| 2136 // +2 here is to copy both receiver and return address. |
| 2137 Register count_reg = caller_args_count_reg; |
| 2138 if (callee_args_count.is_reg()) { |
| 2139 lea(count_reg, Operand(callee_args_count.reg(), 2)); |
| 2140 } else { |
| 2141 mov(count_reg, Immediate(callee_args_count.immediate() + 2)); |
| 2142 // TODO(ishell): Unroll copying loop for small immediate values. |
| 2143 } |
| 2144 |
| 2145 // Now copy callee arguments to the caller frame going backwards to avoid |
| 2146 // callee arguments corruption (source and destination areas could overlap). |
| 2147 Label loop, entry; |
| 2148 jmp(&entry, Label::kNear); |
| 2149 bind(&loop); |
| 2150 dec(count_reg); |
| 2151 mov(tmp_reg, Operand(esp, count_reg, times_pointer_size, 0)); |
| 2152 mov(Operand(new_sp_reg, count_reg, times_pointer_size, 0), tmp_reg); |
| 2153 bind(&entry); |
| 2154 cmp(count_reg, Immediate(0)); |
| 2155 j(not_equal, &loop, Label::kNear); |
| 2156 |
| 2157 // Leave current frame. |
| 2158 mov(esp, new_sp_reg); |
| 2159 } |
2089 | 2160 |
2090 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 2161 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
2091 const ParameterCount& actual, | 2162 const ParameterCount& actual, |
2092 Label* done, | 2163 Label* done, |
2093 bool* definitely_mismatches, | 2164 bool* definitely_mismatches, |
2094 InvokeFlag flag, | 2165 InvokeFlag flag, |
2095 Label::Distance done_near, | 2166 Label::Distance done_near, |
2096 const CallWrapper& call_wrapper) { | 2167 const CallWrapper& call_wrapper) { |
2097 bool definitely_matches = false; | 2168 bool definitely_matches = false; |
2098 *definitely_mismatches = false; | 2169 *definitely_mismatches = false; |
(...skipping 1131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3230 mov(eax, dividend); | 3301 mov(eax, dividend); |
3231 shr(eax, 31); | 3302 shr(eax, 31); |
3232 add(edx, eax); | 3303 add(edx, eax); |
3233 } | 3304 } |
3234 | 3305 |
3235 | 3306 |
3236 } // namespace internal | 3307 } // namespace internal |
3237 } // namespace v8 | 3308 } // namespace v8 |
3238 | 3309 |
3239 #endif // V8_TARGET_ARCH_IA32 | 3310 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |