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

Side by Side Diff: src/x64/codegen-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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 masm_(new MacroAssembler(NULL, buffer_size)), 43 masm_(new MacroAssembler(NULL, buffer_size)),
44 scope_(NULL), 44 scope_(NULL),
45 frame_(NULL), 45 frame_(NULL),
46 allocator_(NULL), 46 allocator_(NULL),
47 state_(NULL), 47 state_(NULL),
48 loop_nesting_(0), 48 loop_nesting_(0),
49 function_return_is_shadowed_(false), 49 function_return_is_shadowed_(false),
50 in_spilled_code_(false) { 50 in_spilled_code_(false) {
51 } 51 }
52 52
53 #define __ masm-> 53 #define __ ACCESS_MASM(masm)
54
54 55
55 56
56 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) { 57 void CodeGenerator::DeclareGlobals(Handle<FixedArray> a) {
57 UNIMPLEMENTED(); 58 UNIMPLEMENTED();
58 } 59 }
59 60
60 void CodeGenerator::GenCode(FunctionLiteral* a) { 61 void CodeGenerator::GenCode(FunctionLiteral* a) {
61 masm_->int3(); // UNIMPLEMENTED 62 masm_->int3(); // UNIMPLEMENTED
62 } 63 }
63 64
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 222
222 void CodeGenerator::VisitCompareOperation(CompareOperation* a) { 223 void CodeGenerator::VisitCompareOperation(CompareOperation* a) {
223 UNIMPLEMENTED(); 224 UNIMPLEMENTED();
224 } 225 }
225 226
226 void CodeGenerator::VisitThisFunction(ThisFunction* a) { 227 void CodeGenerator::VisitThisFunction(ThisFunction* a) {
227 UNIMPLEMENTED(); 228 UNIMPLEMENTED();
228 } 229 }
229 230
230 231
232 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
233 // Check that stack should contain frame pointer, code pointer, state and
234 // return address in that order.
235 ASSERT_EQ(StackHandlerConstants::kFPOffset + kPointerSize,
236 StackHandlerConstants::kCodeOffset);
237 ASSERT_EQ(StackHandlerConstants::kCodeOffset + kPointerSize,
238 StackHandlerConstants::kStateOffset);
239 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize,
240 StackHandlerConstants::kPCOffset);
241
242 ExternalReference handler_address(Top::k_handler_address);
243 __ movq(kScratchRegister, handler_address);
244 __ movq(rdx, Operand(kScratchRegister, 0));
245 // get next in chain
246 __ movq(rcx, Operand(rdx, StackHandlerConstants::kAddressDisplacement));
247 __ movq(Operand(kScratchRegister, 0), rcx);
248 __ movq(rsp, rdx);
249 __ pop(rbp); // pop frame pointer
250 __ pop(rdx); // remove code pointer
251 __ pop(rdx); // remove state
252
253 // Before returning we restore the context from the frame pointer if not NULL.
254 // The frame pointer is NULL in the exception handler of a JS entry frame.
255 __ xor_(rsi, rsi); // tentatively set context pointer to NULL
256 Label skip;
257 __ cmp(rbp, Immediate(0));
258 __ j(equal, &skip);
259 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
260 __ bind(&skip);
261
262 __ ret(0);
263 }
264
265
266
267 void CEntryStub::GenerateCore(MacroAssembler* masm,
268 Label* throw_normal_exception,
269 Label* throw_out_of_memory_exception,
270 StackFrame::Type frame_type,
271 bool do_gc,
272 bool always_allocate_scope) {
273 // rax: result parameter for PerformGC, if any
274 // rbx: pointer to C function (C callee-saved)
275 // rbp: frame pointer (restored after C call)
276 // rsp: stack pointer (restored after C call)
277 // rdi: number of arguments including receiver (C callee-saved)
278 // rsi: pointer to the first argument (C callee-saved)
279
280 if (do_gc) {
281 __ movq(Operand(rsp, 0), rax); // Result.
282 __ movq(kScratchRegister,
283 FUNCTION_ADDR(Runtime::PerformGC),
284 RelocInfo::RUNTIME_ENTRY);
285 __ call(kScratchRegister);
286 }
287
288 ExternalReference scope_depth =
289 ExternalReference::heap_always_allocate_scope_depth();
290 if (always_allocate_scope) {
291 __ movq(kScratchRegister, scope_depth);
292 __ inc(Operand(kScratchRegister, 0));
293 }
294
295 // Call C function.
296 __ movq(Operand(rsp, 0 * kPointerSize), rdi); // argc.
297 __ movq(Operand(rsp, 1 * kPointerSize), rsi); // argv.
298 __ call(rbx);
299 // Result is in rax - do not destroy this register!
300
301 if (always_allocate_scope) {
302 __ movq(kScratchRegister, scope_depth);
303 __ dec(Operand(kScratchRegister, 0));
304 }
305
306 // Check for failure result.
307 Label failure_returned;
308 ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
309 __ lea(rcx, Operand(rax, 1));
310 // Lower 2 bits of rcx are 0 iff rax has failure tag.
311 __ testl(rcx, Immediate(kFailureTagMask));
312 __ j(zero, &failure_returned);
313
314 // Exit the JavaScript to C++ exit frame.
315 __ LeaveExitFrame(frame_type);
316 __ ret(0);
317
318 // Handling of failure.
319 __ bind(&failure_returned);
320
321 Label retry;
322 // If the returned exception is RETRY_AFTER_GC continue at retry label
323 ASSERT(Failure::RETRY_AFTER_GC == 0);
324 __ testq(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
325 __ j(zero, &retry);
326
327 Label continue_exception;
328 // If the returned failure is EXCEPTION then promote Top::pending_exception().
329 __ movq(kScratchRegister, Failure::Exception(), RelocInfo::NONE);
330 __ cmp(rax, kScratchRegister);
331 __ j(not_equal, &continue_exception);
332
333 // Retrieve the pending exception and clear the variable.
334 ExternalReference pending_exception_address(Top::k_pending_exception_address);
335 __ movq(kScratchRegister, pending_exception_address);
336 __ movq(rax, Operand(kScratchRegister, 0));
337 __ movq(rdx, ExternalReference::the_hole_value_location());
338 __ movq(rdx, Operand(rdx, 0));
339 __ movq(Operand(kScratchRegister, 0), rdx);
340
341 __ bind(&continue_exception);
342 // Special handling of out of memory exception.
343 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE);
344 __ cmp(rax, kScratchRegister);
345 __ j(equal, throw_out_of_memory_exception);
346
347 // Handle normal exception.
348 __ jmp(throw_normal_exception);
349
350 // Retry.
351 __ bind(&retry);
352 }
353
354
355 void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
356 // Fetch top stack handler.
357 ExternalReference handler_address(Top::k_handler_address);
358 __ movq(kScratchRegister, handler_address);
359 __ movq(rdx, Operand(kScratchRegister, 0));
360
361 // Unwind the handlers until the ENTRY handler is found.
362 Label loop, done;
363 __ bind(&loop);
364 // Load the type of the current stack handler.
365 const int kStateOffset = StackHandlerConstants::kAddressDisplacement +
366 StackHandlerConstants::kStateOffset;
367 __ cmp(Operand(rdx, kStateOffset), Immediate(StackHandler::ENTRY));
368 __ j(equal, &done);
369 // Fetch the next handler in the list.
370 const int kNextOffset = StackHandlerConstants::kAddressDisplacement +
371 StackHandlerConstants::kNextOffset;
372 __ movq(rdx, Operand(rdx, kNextOffset));
373 __ jmp(&loop);
374 __ bind(&done);
375
376 // Set the top handler address to next handler past the current ENTRY handler.
377 __ movq(rax, Operand(rdx, kNextOffset));
378 __ store_rax(handler_address);
379
380 // Set external caught exception to false.
381 __ movq(rax, Immediate(false));
382 ExternalReference external_caught(Top::k_external_caught_exception_address);
383 __ store_rax(external_caught);
384
385 // Set pending exception and rax to out of memory exception.
386 __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
387 ExternalReference pending_exception(Top::k_pending_exception_address);
388 __ store_rax(pending_exception);
389
390 // Restore the stack to the address of the ENTRY handler
391 __ movq(rsp, rdx);
392
393 // Clear the context pointer;
394 __ xor_(rsi, rsi);
395
396 // Restore registers from handler.
397 __ pop(rbp); // FP
398 __ pop(rdx); // Code
399 __ pop(rdx); // State
400
401 __ ret(0);
402 }
403
404
231 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { 405 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
232 masm->int3(); // TODO(X64): UNIMPLEMENTED. 406 // rax: number of arguments including receiver
233 } 407 // rbx: pointer to C function (C callee-saved)
234 408 // rbp: frame pointer (restored after C call)
235 409 // rsp: stack pointer (restored after C call)
410 // rsi: current context (C callee-saved)
411 // rdi: caller's parameter pointer pp (C callee-saved)
412
413 // NOTE: Invocations of builtins may return failure objects
414 // instead of a proper result. The builtin entry handles
415 // this by performing a garbage collection and retrying the
416 // builtin once.
417
418 StackFrame::Type frame_type = is_debug_break ?
419 StackFrame::EXIT_DEBUG :
420 StackFrame::EXIT;
421
422 // Enter the exit frame that transitions from JavaScript to C++.
423 __ EnterExitFrame(frame_type);
424
425 // rax: result parameter for PerformGC, if any (setup below)
426 // rbx: pointer to builtin function (C callee-saved)
427 // rbp: frame pointer (restored after C call)
428 // rsp: stack pointer (restored after C call)
429 // rdi: number of arguments including receiver (C callee-saved)
430 // rsi: argv pointer (C callee-saved)
431
432 Label throw_out_of_memory_exception;
433 Label throw_normal_exception;
434
435 // Call into the runtime system. Collect garbage before the call if
436 // running with --gc-greedy set.
437 if (FLAG_gc_greedy) {
438 Failure* failure = Failure::RetryAfterGC(0);
439 __ movq(rax, failure, RelocInfo::NONE);
440 }
441 GenerateCore(masm, &throw_normal_exception,
442 &throw_out_of_memory_exception,
443 frame_type,
444 FLAG_gc_greedy,
445 false);
446
447 // Do space-specific GC and retry runtime call.
448 GenerateCore(masm,
449 &throw_normal_exception,
450 &throw_out_of_memory_exception,
451 frame_type,
452 true,
453 false);
454
455 // Do full GC and retry runtime call one final time.
456 Failure* failure = Failure::InternalError();
457 __ movq(rax, failure, RelocInfo::NONE);
458 GenerateCore(masm,
459 &throw_normal_exception,
460 &throw_out_of_memory_exception,
461 frame_type,
462 true,
463 true);
464
465 __ bind(&throw_out_of_memory_exception);
466 GenerateThrowOutOfMemory(masm);
467 // control flow for generated will not return.
468
469 __ bind(&throw_normal_exception);
470 GenerateThrowTOS(masm);
471 }
472
473
236 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { 474 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
237 Label invoke, exit; 475 Label invoke, exit;
238 476
239 // Setup frame. 477 // Setup frame.
240 __ push(rbp); 478 __ push(rbp);
241 __ movq(rbp, rsp); 479 __ movq(rbp, rsp);
242 480
243 // Save callee-saved registers (X64 calling conventions). 481 // Save callee-saved registers (X64 calling conventions).
244 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 482 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
245 // Push something that is not an arguments adaptor. 483 // Push something that is not an arguments adaptor.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 557
320 // Restore frame pointer and return. 558 // Restore frame pointer and return.
321 __ pop(rbp); 559 __ pop(rbp);
322 __ ret(0); 560 __ ret(0);
323 } 561 }
324 562
325 563
326 #undef __ 564 #undef __
327 565
328 } } // namespace v8::internal 566 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698