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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 240053010: Return Object* instead of MaybeObject* from runtime calls. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: cmpp Created 6 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « src/stub-cache.cc ('k') | src/x64/regexp-macro-assembler-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 2390 matching lines...) Expand 10 before | Expand all | Expand 10 after
2401 2401
2402 2402
2403 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 2403 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
2404 CEntryStub stub(1, kDontSaveFPRegs); 2404 CEntryStub stub(1, kDontSaveFPRegs);
2405 stub.GetCode(isolate); 2405 stub.GetCode(isolate);
2406 CEntryStub save_doubles(1, kSaveFPRegs); 2406 CEntryStub save_doubles(1, kSaveFPRegs);
2407 save_doubles.GetCode(isolate); 2407 save_doubles.GetCode(isolate);
2408 } 2408 }
2409 2409
2410 2410
2411 void CEntryStub::GenerateCore(MacroAssembler* masm, 2411 void CEntryStub::Generate(MacroAssembler* masm) {
2412 Label* throw_normal_exception, 2412 // rax: number of arguments including receiver
2413 Label* throw_termination_exception, 2413 // rbx: pointer to C function (C callee-saved)
2414 bool do_gc, 2414 // rbp: frame pointer of calling JS frame (restored after C call)
2415 bool always_allocate_scope) { 2415 // rsp: stack pointer (restored after C call)
2416 // rax: result parameter for PerformGC, if any. 2416 // rsi: current context (restored)
2417 // rbx: pointer to C function (C callee-saved). 2417
2418 // rbp: frame pointer (restored after C call). 2418 ProfileEntryHookStub::MaybeCallEntryHook(masm);
2419 // rsp: stack pointer (restored after C call). 2419
2420 // Enter the exit frame that transitions from JavaScript to C++.
2421 #ifdef _WIN64
2422 int arg_stack_space = (result_size_ < 2 ? 2 : 4);
2423 #else
2424 int arg_stack_space = 0;
2425 #endif
2426 __ EnterExitFrame(arg_stack_space, save_doubles_);
2427
2428 // rbx: pointer to builtin function (C callee-saved).
2429 // rbp: frame pointer of exit frame (restored after C call).
2430 // rsp: stack pointer (restored after C call).
2420 // r14: number of arguments including receiver (C callee-saved). 2431 // r14: number of arguments including receiver (C callee-saved).
2421 // r15: pointer to the first argument (C callee-saved). 2432 // r15: argv pointer (C callee-saved).
2422 // This pointer is reused in LeaveExitFrame(), so it is stored in a
2423 // callee-saved register.
2424 2433
2425 // Simple results returned in rax (both AMD64 and Win64 calling conventions). 2434 // Simple results returned in rax (both AMD64 and Win64 calling conventions).
2426 // Complex results must be written to address passed as first argument. 2435 // Complex results must be written to address passed as first argument.
2427 // AMD64 calling convention: a struct of two pointers in rax+rdx 2436 // AMD64 calling convention: a struct of two pointers in rax+rdx
2428 2437
2429 // Check stack alignment. 2438 // Check stack alignment.
2430 if (FLAG_debug_code) { 2439 if (FLAG_debug_code) {
2431 __ CheckStackAlignment(); 2440 __ CheckStackAlignment();
2432 } 2441 }
2433 2442
2434 if (do_gc) {
2435 // Pass failure code returned from last attempt as first argument to
2436 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the
2437 // stack is known to be aligned. This function takes one argument which is
2438 // passed in register.
2439 __ Move(arg_reg_2, ExternalReference::isolate_address(masm->isolate()));
2440 __ movp(arg_reg_1, rax);
2441 __ Move(kScratchRegister,
2442 ExternalReference::perform_gc_function(masm->isolate()));
2443 __ call(kScratchRegister);
2444 }
2445
2446 ExternalReference scope_depth =
2447 ExternalReference::heap_always_allocate_scope_depth(masm->isolate());
2448 if (always_allocate_scope) {
2449 Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
2450 __ incl(scope_depth_operand);
2451 }
2452
2453 // Call C function. 2443 // Call C function.
2454 #ifdef _WIN64 2444 #ifdef _WIN64
2455 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9. 2445 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9.
2456 // Pass argv and argc as two parameters. The arguments object will 2446 // Pass argv and argc as two parameters. The arguments object will
2457 // be created by stubs declared by DECLARE_RUNTIME_FUNCTION(). 2447 // be created by stubs declared by DECLARE_RUNTIME_FUNCTION().
2458 if (result_size_ < 2) { 2448 if (result_size_ < 2) {
2459 // Pass a pointer to the Arguments object as the first argument. 2449 // Pass a pointer to the Arguments object as the first argument.
2460 // Return result in single register (rax). 2450 // Return result in single register (rax).
2461 __ movp(rcx, r14); // argc. 2451 __ movp(rcx, r14); // argc.
2462 __ movp(rdx, r15); // argv. 2452 __ movp(rdx, r15); // argv.
(...skipping 10 matching lines...) Expand all
2473 2463
2474 #else // _WIN64 2464 #else // _WIN64
2475 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. 2465 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9.
2476 __ movp(rdi, r14); // argc. 2466 __ movp(rdi, r14); // argc.
2477 __ movp(rsi, r15); // argv. 2467 __ movp(rsi, r15); // argv.
2478 __ Move(rdx, ExternalReference::isolate_address(masm->isolate())); 2468 __ Move(rdx, ExternalReference::isolate_address(masm->isolate()));
2479 #endif 2469 #endif
2480 __ call(rbx); 2470 __ call(rbx);
2481 // Result is in rax - do not destroy this register! 2471 // Result is in rax - do not destroy this register!
2482 2472
2483 if (always_allocate_scope) {
2484 Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
2485 __ decl(scope_depth_operand);
2486 }
2487
2488 // Check for failure result.
2489 Label failure_returned;
2490 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
2491 #ifdef _WIN64 2473 #ifdef _WIN64
2492 // If return value is on the stack, pop it to registers. 2474 // If return value is on the stack, pop it to registers.
2493 if (result_size_ > 1) { 2475 if (result_size_ > 1) {
2494 ASSERT_EQ(2, result_size_); 2476 ASSERT_EQ(2, result_size_);
2495 // Read result values stored on stack. Result is stored 2477 // Read result values stored on stack. Result is stored
2496 // above the four argument mirror slots and the two 2478 // above the four argument mirror slots and the two
2497 // Arguments object slots. 2479 // Arguments object slots.
2498 __ movq(rax, Operand(rsp, 6 * kRegisterSize)); 2480 __ movq(rax, Operand(rsp, 6 * kRegisterSize));
2499 __ movq(rdx, Operand(rsp, 7 * kRegisterSize)); 2481 __ movq(rdx, Operand(rsp, 7 * kRegisterSize));
2500 } 2482 }
2501 #endif 2483 #endif
2502 __ leap(rcx, Operand(rax, 1)); 2484
2503 // Lower 2 bits of rcx are 0 iff rax has failure tag. 2485 // Runtime functions should not return 'the hole'. Allowing it to escape may
2504 __ testl(rcx, Immediate(kFailureTagMask)); 2486 // lead to crashes in the IC code later.
2505 __ j(zero, &failure_returned); 2487 if (FLAG_debug_code) {
2488 Label okay;
2489 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
2490 __ j(not_equal, &okay, Label::kNear);
2491 __ int3();
2492 __ bind(&okay);
2493 }
2494
2495 // Check result for exception sentinel.
2496 Label exception_returned;
2497 __ CompareRoot(rax, Heap::kExceptionRootIndex);
2498 __ j(equal, &exception_returned);
2499
2500 ExternalReference pending_exception_address(
2501 Isolate::kPendingExceptionAddress, masm->isolate());
2502
2503 // Check that there is no pending exception, otherwise we
2504 // should have returned the exception sentinel.
2505 if (FLAG_debug_code) {
2506 Label okay;
2507 __ LoadRoot(r14, Heap::kTheHoleValueRootIndex);
2508 Operand pending_exception_operand =
2509 masm->ExternalOperand(pending_exception_address);
2510 __ cmpp(r14, pending_exception_operand);
2511 __ j(equal, &okay, Label::kNear);
2512 __ int3();
2513 __ bind(&okay);
2514 }
2506 2515
2507 // Exit the JavaScript to C++ exit frame. 2516 // Exit the JavaScript to C++ exit frame.
2508 __ LeaveExitFrame(save_doubles_); 2517 __ LeaveExitFrame(save_doubles_);
2509 __ ret(0); 2518 __ ret(0);
2510 2519
2511 // Handling of failure. 2520 // Handling of exception.
2512 __ bind(&failure_returned); 2521 __ bind(&exception_returned);
2513
2514 Label retry;
2515 // If the returned exception is RETRY_AFTER_GC continue at retry label
2516 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
2517 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
2518 __ j(zero, &retry, Label::kNear);
2519 2522
2520 // Retrieve the pending exception. 2523 // Retrieve the pending exception.
2521 ExternalReference pending_exception_address(
2522 Isolate::kPendingExceptionAddress, masm->isolate());
2523 Operand pending_exception_operand = 2524 Operand pending_exception_operand =
2524 masm->ExternalOperand(pending_exception_address); 2525 masm->ExternalOperand(pending_exception_address);
2525 __ movp(rax, pending_exception_operand); 2526 __ movp(rax, pending_exception_operand);
2526 2527
2527 // Clear the pending exception. 2528 // Clear the pending exception.
2528 pending_exception_operand =
2529 masm->ExternalOperand(pending_exception_address);
2530 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); 2529 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
2531 __ movp(pending_exception_operand, rdx); 2530 __ movp(pending_exception_operand, rdx);
2532 2531
2533 // Special handling of termination exceptions which are uncatchable 2532 // Special handling of termination exceptions which are uncatchable
2534 // by javascript code. 2533 // by javascript code.
2534 Label throw_termination_exception;
2535 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); 2535 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
2536 __ j(equal, throw_termination_exception); 2536 __ j(equal, &throw_termination_exception);
2537 2537
2538 // Handle normal exception. 2538 // Handle normal exception.
2539 __ jmp(throw_normal_exception); 2539 __ Throw(rax);
2540 2540
2541 // Retry. 2541 __ bind(&throw_termination_exception);
2542 __ bind(&retry); 2542 __ ThrowUncatchable(rax);
2543 } 2543 }
2544 2544
2545 2545
2546 void CEntryStub::Generate(MacroAssembler* masm) {
2547 // rax: number of arguments including receiver
2548 // rbx: pointer to C function (C callee-saved)
2549 // rbp: frame pointer of calling JS frame (restored after C call)
2550 // rsp: stack pointer (restored after C call)
2551 // rsi: current context (restored)
2552
2553 // NOTE: Invocations of builtins may return failure objects
2554 // instead of a proper result. The builtin entry handles
2555 // this by performing a garbage collection and retrying the
2556 // builtin once.
2557
2558 ProfileEntryHookStub::MaybeCallEntryHook(masm);
2559
2560 // Enter the exit frame that transitions from JavaScript to C++.
2561 #ifdef _WIN64
2562 int arg_stack_space = (result_size_ < 2 ? 2 : 4);
2563 #else
2564 int arg_stack_space = 0;
2565 #endif
2566 __ EnterExitFrame(arg_stack_space, save_doubles_);
2567
2568 // rax: Holds the context at this point, but should not be used.
2569 // On entry to code generated by GenerateCore, it must hold
2570 // a failure result if the collect_garbage argument to GenerateCore
2571 // is true. This failure result can be the result of code
2572 // generated by a previous call to GenerateCore. The value
2573 // of rax is then passed to Runtime::PerformGC.
2574 // rbx: pointer to builtin function (C callee-saved).
2575 // rbp: frame pointer of exit frame (restored after C call).
2576 // rsp: stack pointer (restored after C call).
2577 // r14: number of arguments including receiver (C callee-saved).
2578 // r15: argv pointer (C callee-saved).
2579
2580 Label throw_normal_exception;
2581 Label throw_termination_exception;
2582
2583 // Call into the runtime system.
2584 GenerateCore(masm,
2585 &throw_normal_exception,
2586 &throw_termination_exception,
2587 false,
2588 false);
2589
2590 // Do space-specific GC and retry runtime call.
2591 GenerateCore(masm,
2592 &throw_normal_exception,
2593 &throw_termination_exception,
2594 true,
2595 false);
2596
2597 // Do full GC and retry runtime call one final time.
2598 Failure* failure = Failure::InternalError();
2599 __ Move(rax, failure, Assembler::RelocInfoNone());
2600 GenerateCore(masm,
2601 &throw_normal_exception,
2602 &throw_termination_exception,
2603 true,
2604 true);
2605
2606 { FrameScope scope(masm, StackFrame::MANUAL);
2607 __ PrepareCallCFunction(0);
2608 __ CallCFunction(
2609 ExternalReference::out_of_memory_function(masm->isolate()), 0);
2610 }
2611
2612 __ bind(&throw_termination_exception);
2613 __ ThrowUncatchable(rax);
2614
2615 __ bind(&throw_normal_exception);
2616 __ Throw(rax);
2617 }
2618
2619
2620 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { 2546 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
2621 Label invoke, handler_entry, exit; 2547 Label invoke, handler_entry, exit;
2622 Label not_outermost_js, not_outermost_js_2; 2548 Label not_outermost_js, not_outermost_js_2;
2623 2549
2624 ProfileEntryHookStub::MaybeCallEntryHook(masm); 2550 ProfileEntryHookStub::MaybeCallEntryHook(masm);
2625 2551
2626 { // NOLINT. Scope block confuses linter. 2552 { // NOLINT. Scope block confuses linter.
2627 MacroAssembler::NoRootArrayScope uninitialized_root_register(masm); 2553 MacroAssembler::NoRootArrayScope uninitialized_root_register(masm);
2628 // Set up frame. 2554 // Set up frame.
2629 __ pushq(rbp); 2555 __ pushq(rbp);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2695 // Jump to a faked try block that does the invoke, with a faked catch 2621 // Jump to a faked try block that does the invoke, with a faked catch
2696 // block that sets the pending exception. 2622 // block that sets the pending exception.
2697 __ jmp(&invoke); 2623 __ jmp(&invoke);
2698 __ bind(&handler_entry); 2624 __ bind(&handler_entry);
2699 handler_offset_ = handler_entry.pos(); 2625 handler_offset_ = handler_entry.pos();
2700 // Caught exception: Store result (exception) in the pending exception 2626 // Caught exception: Store result (exception) in the pending exception
2701 // field in the JSEnv and return a failure sentinel. 2627 // field in the JSEnv and return a failure sentinel.
2702 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, 2628 ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
2703 isolate); 2629 isolate);
2704 __ Store(pending_exception, rax); 2630 __ Store(pending_exception, rax);
2705 __ Move(rax, Failure::Exception(), Assembler::RelocInfoNone()); 2631 __ LoadRoot(rax, Heap::kExceptionRootIndex);
2706 __ jmp(&exit); 2632 __ jmp(&exit);
2707 2633
2708 // Invoke: Link this frame into the handler chain. There's only one 2634 // Invoke: Link this frame into the handler chain. There's only one
2709 // handler block in this code object, so its index is 0. 2635 // handler block in this code object, so its index is 0.
2710 __ bind(&invoke); 2636 __ bind(&invoke);
2711 __ PushTryHandler(StackHandler::JS_ENTRY, 0); 2637 __ PushTryHandler(StackHandler::JS_ENTRY, 0);
2712 2638
2713 // Clear any pending exceptions. 2639 // Clear any pending exceptions.
2714 __ LoadRoot(rax, Heap::kTheHoleValueRootIndex); 2640 __ LoadRoot(rax, Heap::kTheHoleValueRootIndex);
2715 __ Store(pending_exception, rax); 2641 __ Store(pending_exception, rax);
(...skipping 2312 matching lines...) Expand 10 before | Expand all | Expand 10 after
5028 return_value_operand, 4954 return_value_operand,
5029 NULL); 4955 NULL);
5030 } 4956 }
5031 4957
5032 4958
5033 #undef __ 4959 #undef __
5034 4960
5035 } } // namespace v8::internal 4961 } } // namespace v8::internal
5036 4962
5037 #endif // V8_TARGET_ARCH_X64 4963 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/stub-cache.cc ('k') | src/x64/regexp-macro-assembler-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698