Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Side by Side Diff: src/x64/macro-assembler-x64.cc

Issue 114085: X64: Implement CEntryStub and JSEntryTrampoline. (Closed)
Patch Set: Addressed review comments Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "bootstrapper.h" 30 #include "bootstrapper.h"
31 #include "codegen-inl.h" 31 #include "codegen-inl.h"
32 #include "assembler-x64.h"
32 #include "macro-assembler-x64.h" 33 #include "macro-assembler-x64.h"
34 #include "debug.h"
33 35
34 namespace v8 { 36 namespace v8 {
35 namespace internal { 37 namespace internal {
36 38
37 MacroAssembler::MacroAssembler(void* buffer, int size) 39 MacroAssembler::MacroAssembler(void* buffer, int size)
38 : Assembler(buffer, size), 40 : Assembler(buffer, size),
39 unresolved_(0), 41 unresolved_(0),
40 generating_stub_(false), 42 generating_stub_(false),
41 allow_stub_calls_(true), 43 allow_stub_calls_(true),
42 code_object_(Heap::undefined_value()) { 44 code_object_(Heap::undefined_value()) {
43 } 45 }
44 46
45 47
48 void MacroAssembler::Check(Condition cc, const char* message) {
William Hesse 2009/06/10 08:09:09 We want this to be inline if the debug check is in
49 #ifdef DEBUG
50 // Not implemented yet.
51 #endif
52 }
53
54
46 void MacroAssembler::TailCallRuntime(ExternalReference const& a, int b) { 55 void MacroAssembler::TailCallRuntime(ExternalReference const& a, int b) {
47 UNIMPLEMENTED(); 56 UNIMPLEMENTED();
48 } 57 }
49 58
50 59
51 void MacroAssembler::Set(Register dst, int64_t x) { 60 void MacroAssembler::Set(Register dst, int64_t x) {
52 if (is_int32(x)) { 61 if (is_int32(x)) {
53 movq(dst, Immediate(x)); 62 movq(dst, Immediate(x));
54 } else if (is_uint32(x)) { 63 } else if (is_uint32(x)) {
55 movl(dst, Immediate(x)); 64 movl(dst, Immediate(x));
(...skipping 12 matching lines...) Expand all
68 movq(kScratchRegister, x, RelocInfo::NONE); 77 movq(kScratchRegister, x, RelocInfo::NONE);
69 } 78 }
70 movq(dst, kScratchRegister); 79 movq(dst, kScratchRegister);
71 } 80 }
72 81
73 82
74 void MacroAssembler::PushTryHandler(CodeLocation try_location, 83 void MacroAssembler::PushTryHandler(CodeLocation try_location,
75 HandlerType type) { 84 HandlerType type) {
76 // The pc (return address) is already on TOS. 85 // The pc (return address) is already on TOS.
77 // This code pushes state, code, frame pointer and parameter pointer. 86 // This code pushes state, code, frame pointer and parameter pointer.
78 // Check that they are expected next on the stack, int that order. 87 // Check that they are expected next on the stack, in that order.
79 ASSERT_EQ(StackHandlerConstants::kStateOffset, 88 ASSERT_EQ(StackHandlerConstants::kStateOffset,
80 StackHandlerConstants::kPCOffset - kPointerSize); 89 StackHandlerConstants::kPCOffset - kPointerSize);
81 ASSERT_EQ(StackHandlerConstants::kCodeOffset, 90 ASSERT_EQ(StackHandlerConstants::kCodeOffset,
82 StackHandlerConstants::kStateOffset - kPointerSize); 91 StackHandlerConstants::kStateOffset - kPointerSize);
83 ASSERT_EQ(StackHandlerConstants::kFPOffset, 92 ASSERT_EQ(StackHandlerConstants::kFPOffset,
84 StackHandlerConstants::kCodeOffset - kPointerSize); 93 StackHandlerConstants::kCodeOffset - kPointerSize);
85 ASSERT_EQ(StackHandlerConstants::kPPOffset,
86 StackHandlerConstants::kFPOffset - kPointerSize);
87 94
88 if (try_location == IN_JAVASCRIPT) { 95 if (try_location == IN_JAVASCRIPT) {
89 if (type == TRY_CATCH_HANDLER) { 96 if (type == TRY_CATCH_HANDLER) {
90 push(Immediate(StackHandler::TRY_CATCH)); 97 push(Immediate(StackHandler::TRY_CATCH));
91 } else { 98 } else {
92 push(Immediate(StackHandler::TRY_FINALLY)); 99 push(Immediate(StackHandler::TRY_FINALLY));
93 } 100 }
94 push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent))); 101 push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent)));
95 push(rbp); 102 push(rbp);
96 push(rdi);
97 } else { 103 } else {
98 ASSERT(try_location == IN_JS_ENTRY); 104 ASSERT(try_location == IN_JS_ENTRY);
99 // The parameter pointer is meaningless here and ebp does not 105 // The parameter pointer is meaningless here and ebp does not
100 // point to a JS frame. So we save NULL for both pp and ebp. We 106 // point to a JS frame. So we save NULL for both pp and ebp. We
101 // expect the code throwing an exception to check ebp before 107 // expect the code throwing an exception to check ebp before
102 // dereferencing it to restore the context. 108 // dereferencing it to restore the context.
103 push(Immediate(StackHandler::ENTRY)); 109 push(Immediate(StackHandler::ENTRY));
104 push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent))); 110 push(Immediate(Smi::FromInt(StackHandler::kCodeNotPresent)));
105 push(Immediate(0)); // NULL frame pointer 111 push(Immediate(0)); // NULL frame pointer
106 push(Immediate(0)); // NULL parameter pointer
107 } 112 }
108 movq(kScratchRegister, ExternalReference(Top::k_handler_address)); 113 movq(kScratchRegister, ExternalReference(Top::k_handler_address));
109 // Cached TOS. 114 // Cached TOS.
110 movq(rax, Operand(kScratchRegister, 0)); 115 movq(rax, Operand(kScratchRegister, 0));
111 // Link this handler. 116 // Link this handler.
112 movq(Operand(kScratchRegister, 0), rsp); 117 movq(Operand(kScratchRegister, 0), rsp);
113 } 118 }
114 119
115 120
121 #ifdef ENABLE_DEBUGGER_SUPPORT
122
123 void MacroAssembler::PushRegistersFromMemory(RegList regs) {
124 ASSERT((regs & ~kJSCallerSaved) == 0);
125 // Push the content of the memory location to the stack.
126 for (int i = 0; i < kNumJSCallerSaved; i++) {
127 int r = JSCallerSavedCode(i);
128 if ((regs & (1 << r)) != 0) {
129 ExternalReference reg_addr =
130 ExternalReference(Debug_Address::Register(i));
131 movq(kScratchRegister, reg_addr);
132 push(Operand(kScratchRegister, 0));
133 }
134 }
135 }
136
137 void MacroAssembler::SaveRegistersToMemory(RegList regs) {
138 ASSERT((regs & ~kJSCallerSaved) == 0);
139 // Copy the content of registers to memory location.
140 for (int i = 0; i < kNumJSCallerSaved; i++) {
141 int r = JSCallerSavedCode(i);
142 if ((regs & (1 << r)) != 0) {
143 Register reg = { r };
144 ExternalReference reg_addr =
145 ExternalReference(Debug_Address::Register(i));
146 movq(kScratchRegister, reg_addr);
147 movq(Operand(kScratchRegister, 0), reg);
148 }
149 }
150 }
151
152
153 void MacroAssembler::RestoreRegistersFromMemory(RegList regs) {
154 ASSERT((regs & ~kJSCallerSaved) == 0);
155 // Copy the content of memory location to registers.
156 for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
157 int r = JSCallerSavedCode(i);
158 if ((regs & (1 << r)) != 0) {
159 Register reg = { r };
160 ExternalReference reg_addr =
161 ExternalReference(Debug_Address::Register(i));
162 movq(kScratchRegister, reg_addr);
163 movq(reg, Operand(kScratchRegister, 0));
164 }
165 }
166 }
167
168
169 void MacroAssembler::PopRegistersToMemory(RegList regs) {
170 ASSERT((regs & ~kJSCallerSaved) == 0);
171 // Pop the content from the stack to the memory location.
172 for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
173 int r = JSCallerSavedCode(i);
174 if ((regs & (1 << r)) != 0) {
175 ExternalReference reg_addr =
176 ExternalReference(Debug_Address::Register(i));
177 movq(kScratchRegister, reg_addr);
178 pop(Operand(kScratchRegister, 0));
179 }
180 }
181 }
182
183
184 void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
185 Register scratch,
186 RegList regs) {
187 ASSERT(!scratch.is(kScratchRegister));
188 ASSERT(!base.is(kScratchRegister));
189 ASSERT(!base.is(scratch));
190 ASSERT((regs & ~kJSCallerSaved) == 0);
191 // Copy the content of the stack to the memory location and adjust base.
192 for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
193 int r = JSCallerSavedCode(i);
194 if ((regs & (1 << r)) != 0) {
195 movq(scratch, Operand(base, 0));
196 ExternalReference reg_addr =
197 ExternalReference(Debug_Address::Register(i));
198 movq(kScratchRegister, reg_addr);
199 movq(Operand(kScratchRegister, 0), scratch);
200 lea(base, Operand(base, kPointerSize));
201 }
202 }
203 }
204
205 #endif // ENABLE_DEBUGGER_SUPPORT
206
207
208
209
210 void MacroAssembler::InvokeFunction(Register fun,
211 const ParameterCount& actual,
212 InvokeFlag flag) {
213 UNIMPLEMENTED();
214 }
215
216
217 void MacroAssembler::EnterFrame(StackFrame::Type type) {
218 push(rbp);
219 movq(rbp, rsp);
220 push(rsi); // Context.
221 push(Immediate(Smi::FromInt(type)));
222 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
223 push(kScratchRegister);
224 if (FLAG_debug_code) {
225 movq(kScratchRegister,
226 Factory::undefined_value(),
227 RelocInfo::EMBEDDED_OBJECT);
228 cmp(Operand(rsp, 0), kScratchRegister);
229 Check(not_equal, "code object not properly patched");
230 }
231 }
232
233
234 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
235 if (FLAG_debug_code) {
236 movq(kScratchRegister, Immediate(Smi::FromInt(type)));
237 cmp(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
238 Check(equal, "stack frame types must match");
239 }
240 movq(rsp, rbp);
241 pop(rbp);
242 }
243
244
245
246 void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
247 ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
248
249 // Setup the frame structure on the stack.
250 ASSERT(ExitFrameConstants::kPPDisplacement == +2 * kPointerSize);
251 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
252 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
253 push(rbp);
254 movq(rbp, rsp);
255
256 // Reserve room for entry stack pointer and push the debug marker.
257 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
258 push(Immediate(0)); // saved entry sp, patched before call
259 push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0));
260
261 // Save the frame pointer and the context in top.
262 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
263 ExternalReference context_address(Top::k_context_address);
264 movq(kScratchRegister, rax);
265 movq(rax, rbp);
266 store_rax(c_entry_fp_address);
267 movq(rax, rsi);
268 store_rax(context_address);
269 movq(rax, kScratchRegister);
270
271 // Setup argc and argv in callee-saved registers.
272 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
273 movq(rdi, rax);
274 lea(rsi, Operand(rbp, rax, kTimesPointerSize, offset));
275
276 #ifdef ENABLE_DEBUGGER_SUPPORT
277 // Save the state of all registers to the stack from the memory
278 // location. This is needed to allow nested break points.
279 if (type == StackFrame::EXIT_DEBUG) {
280 // TODO(1243899): This should be symmetric to
281 // CopyRegistersFromStackToMemory() but it isn't! esp is assumed
282 // correct here, but computed for the other call. Very error
283 // prone! FIX THIS. Actually there are deeper problems with
284 // register saving than this asymmetry (see the bug report
285 // associated with this issue).
286 PushRegistersFromMemory(kJSCallerSaved);
287 }
288 #endif
289
290 // Reserve space for two arguments: argc and argv.
291 sub(rsp, Immediate(2 * kPointerSize));
292
293 // Get the required frame alignment for the OS.
294 static const int kFrameAlignment = OS::ActivationFrameAlignment();
295 if (kFrameAlignment > 0) {
296 ASSERT(IsPowerOf2(kFrameAlignment));
297 movq(r10, Immediate(-kFrameAlignment));
298 and_(rsp, r10);
299 }
300
301 // Patch the saved entry sp.
302 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
303 }
304
305
306 void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
307 #ifdef ENABLE_DEBUGGER_SUPPORT
308 // Restore the memory copy of the registers by digging them out from
309 // the stack. This is needed to allow nested break points.
310 if (type == StackFrame::EXIT_DEBUG) {
311 // It's okay to clobber register ebx below because we don't need
312 // the function pointer after this.
313 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
314 int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
315 lea(rbx, Operand(rbp, kOffset));
316 CopyRegistersFromStackToMemory(rbx, rcx, kJSCallerSaved);
317 }
318 #endif
319
320 // Get the return address from the stack and restore the frame pointer.
321 movq(rcx, Operand(rbp, 1 * kPointerSize));
322 movq(rbp, Operand(rbp, 0 * kPointerSize));
323
324 // Pop the arguments and the receiver from the caller stack.
325 lea(rsp, Operand(rsi, 1 * kPointerSize));
326
327 // Restore current context from top and clear it in debug mode.
328 ExternalReference context_address(Top::k_context_address);
329 movq(kScratchRegister, context_address);
330 movq(rsi, Operand(kScratchRegister, 0));
331 #ifdef DEBUG
332 movq(Operand(kScratchRegister, 0), Immediate(0));
333 #endif
334
335 // Push the return address to get ready to return.
336 push(rcx);
337
338 // Clear the top frame.
339 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
340 movq(kScratchRegister, c_entry_fp_address);
341 movq(Operand(kScratchRegister, 0), Immediate(0));
342 }
343
344
116 } } // namespace v8::internal 345 } } // namespace v8::internal
OLDNEW
« src/x64/assembler-x64.cc ('K') | « src/x64/frames-x64.h ('k') | src/x64/simulator-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698