| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 | 386 |
| 387 | 387 |
| 388 void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { | 388 void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { |
| 389 CallRuntime(Runtime::FunctionForId(id), num_arguments); | 389 CallRuntime(Runtime::FunctionForId(id), num_arguments); |
| 390 } | 390 } |
| 391 | 391 |
| 392 | 392 |
| 393 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { | 393 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { |
| 394 const Runtime::Function* function = Runtime::FunctionForId(id); | 394 const Runtime::Function* function = Runtime::FunctionForId(id); |
| 395 Set(rax, function->nargs); | 395 Set(rax, function->nargs); |
| 396 movq(rbx, ExternalReference(function)); | 396 movq(rbx, ExternalReference(function, isolate())); |
| 397 CEntryStub ces(1); | 397 CEntryStub ces(1); |
| 398 ces.SaveDoubles(); | 398 ces.SaveDoubles(); |
| 399 CallStub(&ces); | 399 CallStub(&ces); |
| 400 } | 400 } |
| 401 | 401 |
| 402 | 402 |
| 403 MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, | 403 MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, |
| 404 int num_arguments) { | 404 int num_arguments) { |
| 405 return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); | 405 return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); |
| 406 } | 406 } |
| 407 | 407 |
| 408 | 408 |
| 409 void MacroAssembler::CallRuntime(const Runtime::Function* f, | 409 void MacroAssembler::CallRuntime(const Runtime::Function* f, |
| 410 int num_arguments) { | 410 int num_arguments) { |
| 411 // If the expected number of arguments of the runtime function is | 411 // If the expected number of arguments of the runtime function is |
| 412 // constant, we check that the actual number of arguments match the | 412 // constant, we check that the actual number of arguments match the |
| 413 // expectation. | 413 // expectation. |
| 414 if (f->nargs >= 0 && f->nargs != num_arguments) { | 414 if (f->nargs >= 0 && f->nargs != num_arguments) { |
| 415 IllegalOperation(num_arguments); | 415 IllegalOperation(num_arguments); |
| 416 return; | 416 return; |
| 417 } | 417 } |
| 418 | 418 |
| 419 // TODO(1236192): Most runtime routines don't need the number of | 419 // TODO(1236192): Most runtime routines don't need the number of |
| 420 // arguments passed in because it is constant. At some point we | 420 // arguments passed in because it is constant. At some point we |
| 421 // should remove this need and make the runtime routine entry code | 421 // should remove this need and make the runtime routine entry code |
| 422 // smarter. | 422 // smarter. |
| 423 Set(rax, num_arguments); | 423 Set(rax, num_arguments); |
| 424 movq(rbx, ExternalReference(f)); | 424 movq(rbx, ExternalReference(f, isolate())); |
| 425 CEntryStub ces(f->result_size); | 425 CEntryStub ces(f->result_size); |
| 426 CallStub(&ces); | 426 CallStub(&ces); |
| 427 } | 427 } |
| 428 | 428 |
| 429 | 429 |
| 430 MaybeObject* MacroAssembler::TryCallRuntime(const Runtime::Function* f, | 430 MaybeObject* MacroAssembler::TryCallRuntime(const Runtime::Function* f, |
| 431 int num_arguments) { | 431 int num_arguments) { |
| 432 if (f->nargs >= 0 && f->nargs != num_arguments) { | 432 if (f->nargs >= 0 && f->nargs != num_arguments) { |
| 433 IllegalOperation(num_arguments); | 433 IllegalOperation(num_arguments); |
| 434 // Since we did not call the stub, there was no allocation failure. | 434 // Since we did not call the stub, there was no allocation failure. |
| 435 // Return some non-failure object. | 435 // Return some non-failure object. |
| 436 return HEAP->undefined_value(); | 436 return HEAP->undefined_value(); |
| 437 } | 437 } |
| 438 | 438 |
| 439 // TODO(1236192): Most runtime routines don't need the number of | 439 // TODO(1236192): Most runtime routines don't need the number of |
| 440 // arguments passed in because it is constant. At some point we | 440 // arguments passed in because it is constant. At some point we |
| 441 // should remove this need and make the runtime routine entry code | 441 // should remove this need and make the runtime routine entry code |
| 442 // smarter. | 442 // smarter. |
| 443 Set(rax, num_arguments); | 443 Set(rax, num_arguments); |
| 444 movq(rbx, ExternalReference(f)); | 444 movq(rbx, ExternalReference(f, isolate())); |
| 445 CEntryStub ces(f->result_size); | 445 CEntryStub ces(f->result_size); |
| 446 return TryCallStub(&ces); | 446 return TryCallStub(&ces); |
| 447 } | 447 } |
| 448 | 448 |
| 449 | 449 |
| 450 void MacroAssembler::CallExternalReference(const ExternalReference& ext, | 450 void MacroAssembler::CallExternalReference(const ExternalReference& ext, |
| 451 int num_arguments) { | 451 int num_arguments) { |
| 452 Set(rax, num_arguments); | 452 Set(rax, num_arguments); |
| 453 movq(rbx, ext); | 453 movq(rbx, ext); |
| 454 | 454 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 // should remove this need and make the runtime routine entry code | 490 // should remove this need and make the runtime routine entry code |
| 491 // smarter. | 491 // smarter. |
| 492 Set(rax, num_arguments); | 492 Set(rax, num_arguments); |
| 493 return TryJumpToExternalReference(ext, result_size); | 493 return TryJumpToExternalReference(ext, result_size); |
| 494 } | 494 } |
| 495 | 495 |
| 496 | 496 |
| 497 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, | 497 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, |
| 498 int num_arguments, | 498 int num_arguments, |
| 499 int result_size) { | 499 int result_size) { |
| 500 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); | 500 TailCallExternalReference(ExternalReference(fid, isolate()), |
| 501 num_arguments, |
| 502 result_size); |
| 501 } | 503 } |
| 502 | 504 |
| 503 | 505 |
| 504 MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid, | 506 MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid, |
| 505 int num_arguments, | 507 int num_arguments, |
| 506 int result_size) { | 508 int result_size) { |
| 507 return TryTailCallExternalReference(ExternalReference(fid), | 509 return TryTailCallExternalReference(ExternalReference(fid, isolate()), |
| 508 num_arguments, | 510 num_arguments, |
| 509 result_size); | 511 result_size); |
| 510 } | 512 } |
| 511 | 513 |
| 512 | 514 |
| 513 static int Offset(ExternalReference ref0, ExternalReference ref1) { | 515 static int Offset(ExternalReference ref0, ExternalReference ref1) { |
| 514 int64_t offset = (ref0.address() - ref1.address()); | 516 int64_t offset = (ref0.address() - ref1.address()); |
| 515 // Check that fits into int. | 517 // Check that fits into int. |
| 516 ASSERT(static_cast<int>(offset) == offset); | 518 ASSERT(static_cast<int>(offset) == offset); |
| 517 return static_cast<int>(offset); | 519 return static_cast<int>(offset); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 544 ExternalReference next_address = | 546 ExternalReference next_address = |
| 545 ExternalReference::handle_scope_next_address(); | 547 ExternalReference::handle_scope_next_address(); |
| 546 const int kNextOffset = 0; | 548 const int kNextOffset = 0; |
| 547 const int kLimitOffset = Offset( | 549 const int kLimitOffset = Offset( |
| 548 ExternalReference::handle_scope_limit_address(), | 550 ExternalReference::handle_scope_limit_address(), |
| 549 next_address); | 551 next_address); |
| 550 const int kLevelOffset = Offset( | 552 const int kLevelOffset = Offset( |
| 551 ExternalReference::handle_scope_level_address(), | 553 ExternalReference::handle_scope_level_address(), |
| 552 next_address); | 554 next_address); |
| 553 ExternalReference scheduled_exception_address = | 555 ExternalReference scheduled_exception_address = |
| 554 ExternalReference::scheduled_exception_address(); | 556 ExternalReference::scheduled_exception_address(isolate()); |
| 555 | 557 |
| 556 // Allocate HandleScope in callee-save registers. | 558 // Allocate HandleScope in callee-save registers. |
| 557 Register prev_next_address_reg = r14; | 559 Register prev_next_address_reg = r14; |
| 558 Register prev_limit_reg = rbx; | 560 Register prev_limit_reg = rbx; |
| 559 Register base_reg = r15; | 561 Register base_reg = r15; |
| 560 movq(base_reg, next_address); | 562 movq(base_reg, next_address); |
| 561 movq(prev_next_address_reg, Operand(base_reg, kNextOffset)); | 563 movq(prev_next_address_reg, Operand(base_reg, kNextOffset)); |
| 562 movq(prev_limit_reg, Operand(base_reg, kLimitOffset)); | 564 movq(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
| 563 addl(Operand(base_reg, kLevelOffset), Immediate(1)); | 565 addl(Operand(base_reg, kLevelOffset), Immediate(1)); |
| 564 // Call the api function! | 566 // Call the api function! |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 | 610 |
| 609 // HandleScope limit has changed. Delete allocated extensions. | 611 // HandleScope limit has changed. Delete allocated extensions. |
| 610 bind(&delete_allocated_handles); | 612 bind(&delete_allocated_handles); |
| 611 movq(Operand(base_reg, kLimitOffset), prev_limit_reg); | 613 movq(Operand(base_reg, kLimitOffset), prev_limit_reg); |
| 612 movq(prev_limit_reg, rax); | 614 movq(prev_limit_reg, rax); |
| 613 #ifdef _WIN64 | 615 #ifdef _WIN64 |
| 614 movq(rcx, ExternalReference::isolate_address()); | 616 movq(rcx, ExternalReference::isolate_address()); |
| 615 #else | 617 #else |
| 616 movq(rdi, ExternalReference::isolate_address()); | 618 movq(rdi, ExternalReference::isolate_address()); |
| 617 #endif | 619 #endif |
| 618 movq(rax, ExternalReference::delete_handle_scope_extensions()); | 620 movq(rax, ExternalReference::delete_handle_scope_extensions(isolate())); |
| 619 call(rax); | 621 call(rax); |
| 620 movq(rax, prev_limit_reg); | 622 movq(rax, prev_limit_reg); |
| 621 jmp(&leave_exit_frame); | 623 jmp(&leave_exit_frame); |
| 622 | 624 |
| 623 return result; | 625 return result; |
| 624 } | 626 } |
| 625 | 627 |
| 626 | 628 |
| 627 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext, | 629 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext, |
| 628 int result_size) { | 630 int result_size) { |
| (...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1608 push(rbp); | 1610 push(rbp); |
| 1609 } else { | 1611 } else { |
| 1610 ASSERT(try_location == IN_JS_ENTRY); | 1612 ASSERT(try_location == IN_JS_ENTRY); |
| 1611 // The frame pointer does not point to a JS frame so we save NULL | 1613 // The frame pointer does not point to a JS frame so we save NULL |
| 1612 // for rbp. We expect the code throwing an exception to check rbp | 1614 // for rbp. We expect the code throwing an exception to check rbp |
| 1613 // before dereferencing it to restore the context. | 1615 // before dereferencing it to restore the context. |
| 1614 push(Immediate(StackHandler::ENTRY)); | 1616 push(Immediate(StackHandler::ENTRY)); |
| 1615 push(Immediate(0)); // NULL frame pointer. | 1617 push(Immediate(0)); // NULL frame pointer. |
| 1616 } | 1618 } |
| 1617 // Save the current handler. | 1619 // Save the current handler. |
| 1618 movq(kScratchRegister, ExternalReference(Isolate::k_handler_address)); | 1620 movq(kScratchRegister, |
| 1621 ExternalReference(Isolate::k_handler_address, isolate())); |
| 1619 push(Operand(kScratchRegister, 0)); | 1622 push(Operand(kScratchRegister, 0)); |
| 1620 // Link this handler. | 1623 // Link this handler. |
| 1621 movq(Operand(kScratchRegister, 0), rsp); | 1624 movq(Operand(kScratchRegister, 0), rsp); |
| 1622 } | 1625 } |
| 1623 | 1626 |
| 1624 | 1627 |
| 1625 void MacroAssembler::PopTryHandler() { | 1628 void MacroAssembler::PopTryHandler() { |
| 1626 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); | 1629 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); |
| 1627 // Unlink this handler. | 1630 // Unlink this handler. |
| 1628 movq(kScratchRegister, ExternalReference(Isolate::k_handler_address)); | 1631 movq(kScratchRegister, |
| 1632 ExternalReference(Isolate::k_handler_address, isolate())); |
| 1629 pop(Operand(kScratchRegister, 0)); | 1633 pop(Operand(kScratchRegister, 0)); |
| 1630 // Remove the remaining fields. | 1634 // Remove the remaining fields. |
| 1631 addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); | 1635 addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); |
| 1632 } | 1636 } |
| 1633 | 1637 |
| 1634 | 1638 |
| 1635 void MacroAssembler::Throw(Register value) { | 1639 void MacroAssembler::Throw(Register value) { |
| 1636 // Check that stack should contain next handler, frame pointer, state and | 1640 // Check that stack should contain next handler, frame pointer, state and |
| 1637 // return address in that order. | 1641 // return address in that order. |
| 1638 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == | 1642 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == |
| 1639 StackHandlerConstants::kStateOffset); | 1643 StackHandlerConstants::kStateOffset); |
| 1640 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == | 1644 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == |
| 1641 StackHandlerConstants::kPCOffset); | 1645 StackHandlerConstants::kPCOffset); |
| 1642 // Keep thrown value in rax. | 1646 // Keep thrown value in rax. |
| 1643 if (!value.is(rax)) { | 1647 if (!value.is(rax)) { |
| 1644 movq(rax, value); | 1648 movq(rax, value); |
| 1645 } | 1649 } |
| 1646 | 1650 |
| 1647 ExternalReference handler_address(Isolate::k_handler_address); | 1651 ExternalReference handler_address(Isolate::k_handler_address, isolate()); |
| 1648 movq(kScratchRegister, handler_address); | 1652 movq(kScratchRegister, handler_address); |
| 1649 movq(rsp, Operand(kScratchRegister, 0)); | 1653 movq(rsp, Operand(kScratchRegister, 0)); |
| 1650 // get next in chain | 1654 // get next in chain |
| 1651 pop(rcx); | 1655 pop(rcx); |
| 1652 movq(Operand(kScratchRegister, 0), rcx); | 1656 movq(Operand(kScratchRegister, 0), rcx); |
| 1653 pop(rbp); // pop frame pointer | 1657 pop(rbp); // pop frame pointer |
| 1654 pop(rdx); // remove state | 1658 pop(rdx); // remove state |
| 1655 | 1659 |
| 1656 // Before returning we restore the context from the frame pointer if not NULL. | 1660 // Before returning we restore the context from the frame pointer if not NULL. |
| 1657 // The frame pointer is NULL in the exception handler of a JS entry frame. | 1661 // The frame pointer is NULL in the exception handler of a JS entry frame. |
| 1658 Set(rsi, 0); // Tentatively set context pointer to NULL | 1662 Set(rsi, 0); // Tentatively set context pointer to NULL |
| 1659 NearLabel skip; | 1663 NearLabel skip; |
| 1660 cmpq(rbp, Immediate(0)); | 1664 cmpq(rbp, Immediate(0)); |
| 1661 j(equal, &skip); | 1665 j(equal, &skip); |
| 1662 movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1666 movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1663 bind(&skip); | 1667 bind(&skip); |
| 1664 ret(0); | 1668 ret(0); |
| 1665 } | 1669 } |
| 1666 | 1670 |
| 1667 | 1671 |
| 1668 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, | 1672 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
| 1669 Register value) { | 1673 Register value) { |
| 1670 // Keep thrown value in rax. | 1674 // Keep thrown value in rax. |
| 1671 if (!value.is(rax)) { | 1675 if (!value.is(rax)) { |
| 1672 movq(rax, value); | 1676 movq(rax, value); |
| 1673 } | 1677 } |
| 1674 // Fetch top stack handler. | 1678 // Fetch top stack handler. |
| 1675 ExternalReference handler_address(Isolate::k_handler_address); | 1679 ExternalReference handler_address(Isolate::k_handler_address, isolate()); |
| 1676 movq(kScratchRegister, handler_address); | 1680 movq(kScratchRegister, handler_address); |
| 1677 movq(rsp, Operand(kScratchRegister, 0)); | 1681 movq(rsp, Operand(kScratchRegister, 0)); |
| 1678 | 1682 |
| 1679 // Unwind the handlers until the ENTRY handler is found. | 1683 // Unwind the handlers until the ENTRY handler is found. |
| 1680 NearLabel loop, done; | 1684 NearLabel loop, done; |
| 1681 bind(&loop); | 1685 bind(&loop); |
| 1682 // Load the type of the current stack handler. | 1686 // Load the type of the current stack handler. |
| 1683 const int kStateOffset = StackHandlerConstants::kStateOffset; | 1687 const int kStateOffset = StackHandlerConstants::kStateOffset; |
| 1684 cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY)); | 1688 cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY)); |
| 1685 j(equal, &done); | 1689 j(equal, &done); |
| 1686 // Fetch the next handler in the list. | 1690 // Fetch the next handler in the list. |
| 1687 const int kNextOffset = StackHandlerConstants::kNextOffset; | 1691 const int kNextOffset = StackHandlerConstants::kNextOffset; |
| 1688 movq(rsp, Operand(rsp, kNextOffset)); | 1692 movq(rsp, Operand(rsp, kNextOffset)); |
| 1689 jmp(&loop); | 1693 jmp(&loop); |
| 1690 bind(&done); | 1694 bind(&done); |
| 1691 | 1695 |
| 1692 // Set the top handler address to next handler past the current ENTRY handler. | 1696 // Set the top handler address to next handler past the current ENTRY handler. |
| 1693 movq(kScratchRegister, handler_address); | 1697 movq(kScratchRegister, handler_address); |
| 1694 pop(Operand(kScratchRegister, 0)); | 1698 pop(Operand(kScratchRegister, 0)); |
| 1695 | 1699 |
| 1696 if (type == OUT_OF_MEMORY) { | 1700 if (type == OUT_OF_MEMORY) { |
| 1697 // Set external caught exception to false. | 1701 // Set external caught exception to false. |
| 1698 ExternalReference external_caught( | 1702 ExternalReference external_caught( |
| 1699 Isolate::k_external_caught_exception_address); | 1703 Isolate::k_external_caught_exception_address, isolate()); |
| 1700 movq(rax, Immediate(false)); | 1704 movq(rax, Immediate(false)); |
| 1701 store_rax(external_caught); | 1705 store_rax(external_caught); |
| 1702 | 1706 |
| 1703 // Set pending exception and rax to out of memory exception. | 1707 // Set pending exception and rax to out of memory exception. |
| 1704 ExternalReference pending_exception(Isolate::k_pending_exception_address); | 1708 ExternalReference pending_exception(Isolate::k_pending_exception_address, |
| 1709 isolate()); |
| 1705 movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); | 1710 movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); |
| 1706 store_rax(pending_exception); | 1711 store_rax(pending_exception); |
| 1707 } | 1712 } |
| 1708 | 1713 |
| 1709 // Clear the context pointer. | 1714 // Clear the context pointer. |
| 1710 Set(rsi, 0); | 1715 Set(rsi, 0); |
| 1711 | 1716 |
| 1712 // Restore registers from handler. | 1717 // Restore registers from handler. |
| 1713 STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == | 1718 STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == |
| 1714 StackHandlerConstants::kFPOffset); | 1719 StackHandlerConstants::kFPOffset); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1914 subl(operand, Immediate(value)); | 1919 subl(operand, Immediate(value)); |
| 1915 } | 1920 } |
| 1916 } | 1921 } |
| 1917 } | 1922 } |
| 1918 | 1923 |
| 1919 | 1924 |
| 1920 #ifdef ENABLE_DEBUGGER_SUPPORT | 1925 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 1921 void MacroAssembler::DebugBreak() { | 1926 void MacroAssembler::DebugBreak() { |
| 1922 ASSERT(allow_stub_calls()); | 1927 ASSERT(allow_stub_calls()); |
| 1923 Set(rax, 0); // No arguments. | 1928 Set(rax, 0); // No arguments. |
| 1924 movq(rbx, ExternalReference(Runtime::kDebugBreak)); | 1929 movq(rbx, ExternalReference(Runtime::kDebugBreak, isolate())); |
| 1925 CEntryStub ces(1); | 1930 CEntryStub ces(1); |
| 1926 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 1931 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
| 1927 } | 1932 } |
| 1928 #endif // ENABLE_DEBUGGER_SUPPORT | 1933 #endif // ENABLE_DEBUGGER_SUPPORT |
| 1929 | 1934 |
| 1930 | 1935 |
| 1931 void MacroAssembler::InvokeCode(Register code, | 1936 void MacroAssembler::InvokeCode(Register code, |
| 1932 const ParameterCount& expected, | 1937 const ParameterCount& expected, |
| 1933 const ParameterCount& actual, | 1938 const ParameterCount& actual, |
| 1934 InvokeFlag flag, | 1939 InvokeFlag flag, |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2068 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 2073 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
| 2069 push(Immediate(0)); // Saved entry sp, patched before call. | 2074 push(Immediate(0)); // Saved entry sp, patched before call. |
| 2070 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 2075 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
| 2071 push(kScratchRegister); // Accessed from EditFrame::code_slot. | 2076 push(kScratchRegister); // Accessed from EditFrame::code_slot. |
| 2072 | 2077 |
| 2073 // Save the frame pointer and the context in top. | 2078 // Save the frame pointer and the context in top. |
| 2074 if (save_rax) { | 2079 if (save_rax) { |
| 2075 movq(r14, rax); // Backup rax in callee-save register. | 2080 movq(r14, rax); // Backup rax in callee-save register. |
| 2076 } | 2081 } |
| 2077 | 2082 |
| 2078 movq(kScratchRegister, ExternalReference(Isolate::k_c_entry_fp_address)); | 2083 movq(kScratchRegister, |
| 2084 ExternalReference(Isolate::k_c_entry_fp_address, isolate())); |
| 2079 movq(Operand(kScratchRegister, 0), rbp); | 2085 movq(Operand(kScratchRegister, 0), rbp); |
| 2080 | 2086 |
| 2081 movq(kScratchRegister, ExternalReference(Isolate::k_context_address)); | 2087 movq(kScratchRegister, |
| 2088 ExternalReference(Isolate::k_context_address, isolate())); |
| 2082 movq(Operand(kScratchRegister, 0), rsi); | 2089 movq(Operand(kScratchRegister, 0), rsi); |
| 2083 } | 2090 } |
| 2084 | 2091 |
| 2085 | 2092 |
| 2086 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, | 2093 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, |
| 2087 bool save_doubles) { | 2094 bool save_doubles) { |
| 2088 #ifdef _WIN64 | 2095 #ifdef _WIN64 |
| 2089 const int kShadowSpace = 4; | 2096 const int kShadowSpace = 4; |
| 2090 arg_stack_space += kShadowSpace; | 2097 arg_stack_space += kShadowSpace; |
| 2091 #endif | 2098 #endif |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2163 void MacroAssembler::LeaveApiExitFrame() { | 2170 void MacroAssembler::LeaveApiExitFrame() { |
| 2164 movq(rsp, rbp); | 2171 movq(rsp, rbp); |
| 2165 pop(rbp); | 2172 pop(rbp); |
| 2166 | 2173 |
| 2167 LeaveExitFrameEpilogue(); | 2174 LeaveExitFrameEpilogue(); |
| 2168 } | 2175 } |
| 2169 | 2176 |
| 2170 | 2177 |
| 2171 void MacroAssembler::LeaveExitFrameEpilogue() { | 2178 void MacroAssembler::LeaveExitFrameEpilogue() { |
| 2172 // Restore current context from top and clear it in debug mode. | 2179 // Restore current context from top and clear it in debug mode. |
| 2173 ExternalReference context_address(Isolate::k_context_address); | 2180 ExternalReference context_address(Isolate::k_context_address, isolate()); |
| 2174 movq(kScratchRegister, context_address); | 2181 movq(kScratchRegister, context_address); |
| 2175 movq(rsi, Operand(kScratchRegister, 0)); | 2182 movq(rsi, Operand(kScratchRegister, 0)); |
| 2176 #ifdef DEBUG | 2183 #ifdef DEBUG |
| 2177 movq(Operand(kScratchRegister, 0), Immediate(0)); | 2184 movq(Operand(kScratchRegister, 0), Immediate(0)); |
| 2178 #endif | 2185 #endif |
| 2179 | 2186 |
| 2180 // Clear the top frame. | 2187 // Clear the top frame. |
| 2181 ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address); | 2188 ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address, |
| 2189 isolate()); |
| 2182 movq(kScratchRegister, c_entry_fp_address); | 2190 movq(kScratchRegister, c_entry_fp_address); |
| 2183 movq(Operand(kScratchRegister, 0), Immediate(0)); | 2191 movq(Operand(kScratchRegister, 0), Immediate(0)); |
| 2184 } | 2192 } |
| 2185 | 2193 |
| 2186 | 2194 |
| 2187 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 2195 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
| 2188 Register scratch, | 2196 Register scratch, |
| 2189 Label* miss) { | 2197 Label* miss) { |
| 2190 Label same_contexts; | 2198 Label same_contexts; |
| 2191 | 2199 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2244 j(not_equal, miss); | 2252 j(not_equal, miss); |
| 2245 | 2253 |
| 2246 bind(&same_contexts); | 2254 bind(&same_contexts); |
| 2247 } | 2255 } |
| 2248 | 2256 |
| 2249 | 2257 |
| 2250 void MacroAssembler::LoadAllocationTopHelper(Register result, | 2258 void MacroAssembler::LoadAllocationTopHelper(Register result, |
| 2251 Register scratch, | 2259 Register scratch, |
| 2252 AllocationFlags flags) { | 2260 AllocationFlags flags) { |
| 2253 ExternalReference new_space_allocation_top = | 2261 ExternalReference new_space_allocation_top = |
| 2254 ExternalReference::new_space_allocation_top_address(); | 2262 ExternalReference::new_space_allocation_top_address(isolate()); |
| 2255 | 2263 |
| 2256 // Just return if allocation top is already known. | 2264 // Just return if allocation top is already known. |
| 2257 if ((flags & RESULT_CONTAINS_TOP) != 0) { | 2265 if ((flags & RESULT_CONTAINS_TOP) != 0) { |
| 2258 // No use of scratch if allocation top is provided. | 2266 // No use of scratch if allocation top is provided. |
| 2259 ASSERT(!scratch.is_valid()); | 2267 ASSERT(!scratch.is_valid()); |
| 2260 #ifdef DEBUG | 2268 #ifdef DEBUG |
| 2261 // Assert that result actually contains top on entry. | 2269 // Assert that result actually contains top on entry. |
| 2262 movq(kScratchRegister, new_space_allocation_top); | 2270 movq(kScratchRegister, new_space_allocation_top); |
| 2263 cmpq(result, Operand(kScratchRegister, 0)); | 2271 cmpq(result, Operand(kScratchRegister, 0)); |
| 2264 Check(equal, "Unexpected allocation top"); | 2272 Check(equal, "Unexpected allocation top"); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2281 | 2289 |
| 2282 | 2290 |
| 2283 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, | 2291 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, |
| 2284 Register scratch) { | 2292 Register scratch) { |
| 2285 if (emit_debug_code()) { | 2293 if (emit_debug_code()) { |
| 2286 testq(result_end, Immediate(kObjectAlignmentMask)); | 2294 testq(result_end, Immediate(kObjectAlignmentMask)); |
| 2287 Check(zero, "Unaligned allocation in new space"); | 2295 Check(zero, "Unaligned allocation in new space"); |
| 2288 } | 2296 } |
| 2289 | 2297 |
| 2290 ExternalReference new_space_allocation_top = | 2298 ExternalReference new_space_allocation_top = |
| 2291 ExternalReference::new_space_allocation_top_address(); | 2299 ExternalReference::new_space_allocation_top_address(isolate()); |
| 2292 | 2300 |
| 2293 // Update new top. | 2301 // Update new top. |
| 2294 if (result_end.is(rax)) { | 2302 if (result_end.is(rax)) { |
| 2295 // rax can be stored directly to a memory location. | 2303 // rax can be stored directly to a memory location. |
| 2296 store_rax(new_space_allocation_top); | 2304 store_rax(new_space_allocation_top); |
| 2297 } else { | 2305 } else { |
| 2298 // Register required - use scratch provided if available. | 2306 // Register required - use scratch provided if available. |
| 2299 if (scratch.is_valid()) { | 2307 if (scratch.is_valid()) { |
| 2300 movq(Operand(scratch, 0), result_end); | 2308 movq(Operand(scratch, 0), result_end); |
| 2301 } else { | 2309 } else { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2326 jmp(gc_required); | 2334 jmp(gc_required); |
| 2327 return; | 2335 return; |
| 2328 } | 2336 } |
| 2329 ASSERT(!result.is(result_end)); | 2337 ASSERT(!result.is(result_end)); |
| 2330 | 2338 |
| 2331 // Load address of new object into result. | 2339 // Load address of new object into result. |
| 2332 LoadAllocationTopHelper(result, scratch, flags); | 2340 LoadAllocationTopHelper(result, scratch, flags); |
| 2333 | 2341 |
| 2334 // Calculate new top and bail out if new space is exhausted. | 2342 // Calculate new top and bail out if new space is exhausted. |
| 2335 ExternalReference new_space_allocation_limit = | 2343 ExternalReference new_space_allocation_limit = |
| 2336 ExternalReference::new_space_allocation_limit_address(); | 2344 ExternalReference::new_space_allocation_limit_address(isolate()); |
| 2337 | 2345 |
| 2338 Register top_reg = result_end.is_valid() ? result_end : result; | 2346 Register top_reg = result_end.is_valid() ? result_end : result; |
| 2339 | 2347 |
| 2340 if (!top_reg.is(result)) { | 2348 if (!top_reg.is(result)) { |
| 2341 movq(top_reg, result); | 2349 movq(top_reg, result); |
| 2342 } | 2350 } |
| 2343 addq(top_reg, Immediate(object_size)); | 2351 addq(top_reg, Immediate(object_size)); |
| 2344 j(carry, gc_required); | 2352 j(carry, gc_required); |
| 2345 movq(kScratchRegister, new_space_allocation_limit); | 2353 movq(kScratchRegister, new_space_allocation_limit); |
| 2346 cmpq(top_reg, Operand(kScratchRegister, 0)); | 2354 cmpq(top_reg, Operand(kScratchRegister, 0)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2383 jmp(gc_required); | 2391 jmp(gc_required); |
| 2384 return; | 2392 return; |
| 2385 } | 2393 } |
| 2386 ASSERT(!result.is(result_end)); | 2394 ASSERT(!result.is(result_end)); |
| 2387 | 2395 |
| 2388 // Load address of new object into result. | 2396 // Load address of new object into result. |
| 2389 LoadAllocationTopHelper(result, scratch, flags); | 2397 LoadAllocationTopHelper(result, scratch, flags); |
| 2390 | 2398 |
| 2391 // Calculate new top and bail out if new space is exhausted. | 2399 // Calculate new top and bail out if new space is exhausted. |
| 2392 ExternalReference new_space_allocation_limit = | 2400 ExternalReference new_space_allocation_limit = |
| 2393 ExternalReference::new_space_allocation_limit_address(); | 2401 ExternalReference::new_space_allocation_limit_address(isolate()); |
| 2394 | 2402 |
| 2395 // We assume that element_count*element_size + header_size does not | 2403 // We assume that element_count*element_size + header_size does not |
| 2396 // overflow. | 2404 // overflow. |
| 2397 lea(result_end, Operand(element_count, element_size, header_size)); | 2405 lea(result_end, Operand(element_count, element_size, header_size)); |
| 2398 addq(result_end, result); | 2406 addq(result_end, result); |
| 2399 j(carry, gc_required); | 2407 j(carry, gc_required); |
| 2400 movq(kScratchRegister, new_space_allocation_limit); | 2408 movq(kScratchRegister, new_space_allocation_limit); |
| 2401 cmpq(result_end, Operand(kScratchRegister, 0)); | 2409 cmpq(result_end, Operand(kScratchRegister, 0)); |
| 2402 j(above, gc_required); | 2410 j(above, gc_required); |
| 2403 | 2411 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2430 jmp(gc_required); | 2438 jmp(gc_required); |
| 2431 return; | 2439 return; |
| 2432 } | 2440 } |
| 2433 ASSERT(!result.is(result_end)); | 2441 ASSERT(!result.is(result_end)); |
| 2434 | 2442 |
| 2435 // Load address of new object into result. | 2443 // Load address of new object into result. |
| 2436 LoadAllocationTopHelper(result, scratch, flags); | 2444 LoadAllocationTopHelper(result, scratch, flags); |
| 2437 | 2445 |
| 2438 // Calculate new top and bail out if new space is exhausted. | 2446 // Calculate new top and bail out if new space is exhausted. |
| 2439 ExternalReference new_space_allocation_limit = | 2447 ExternalReference new_space_allocation_limit = |
| 2440 ExternalReference::new_space_allocation_limit_address(); | 2448 ExternalReference::new_space_allocation_limit_address(isolate()); |
| 2441 if (!object_size.is(result_end)) { | 2449 if (!object_size.is(result_end)) { |
| 2442 movq(result_end, object_size); | 2450 movq(result_end, object_size); |
| 2443 } | 2451 } |
| 2444 addq(result_end, result); | 2452 addq(result_end, result); |
| 2445 j(carry, gc_required); | 2453 j(carry, gc_required); |
| 2446 movq(kScratchRegister, new_space_allocation_limit); | 2454 movq(kScratchRegister, new_space_allocation_limit); |
| 2447 cmpq(result_end, Operand(kScratchRegister, 0)); | 2455 cmpq(result_end, Operand(kScratchRegister, 0)); |
| 2448 j(above, gc_required); | 2456 j(above, gc_required); |
| 2449 | 2457 |
| 2450 // Update allocation top. | 2458 // Update allocation top. |
| 2451 UpdateAllocationTopHelper(result_end, scratch); | 2459 UpdateAllocationTopHelper(result_end, scratch); |
| 2452 | 2460 |
| 2453 // Tag the result if requested. | 2461 // Tag the result if requested. |
| 2454 if ((flags & TAG_OBJECT) != 0) { | 2462 if ((flags & TAG_OBJECT) != 0) { |
| 2455 addq(result, Immediate(kHeapObjectTag)); | 2463 addq(result, Immediate(kHeapObjectTag)); |
| 2456 } | 2464 } |
| 2457 } | 2465 } |
| 2458 | 2466 |
| 2459 | 2467 |
| 2460 void MacroAssembler::UndoAllocationInNewSpace(Register object) { | 2468 void MacroAssembler::UndoAllocationInNewSpace(Register object) { |
| 2461 ExternalReference new_space_allocation_top = | 2469 ExternalReference new_space_allocation_top = |
| 2462 ExternalReference::new_space_allocation_top_address(); | 2470 ExternalReference::new_space_allocation_top_address(isolate()); |
| 2463 | 2471 |
| 2464 // Make sure the object has no tag before resetting top. | 2472 // Make sure the object has no tag before resetting top. |
| 2465 and_(object, Immediate(~kHeapObjectTagMask)); | 2473 and_(object, Immediate(~kHeapObjectTagMask)); |
| 2466 movq(kScratchRegister, new_space_allocation_top); | 2474 movq(kScratchRegister, new_space_allocation_top); |
| 2467 #ifdef DEBUG | 2475 #ifdef DEBUG |
| 2468 cmpq(object, Operand(kScratchRegister, 0)); | 2476 cmpq(object, Operand(kScratchRegister, 0)); |
| 2469 Check(below, "Undo allocation of non allocated memory"); | 2477 Check(below, "Undo allocation of non allocated memory"); |
| 2470 #endif | 2478 #endif |
| 2471 movq(Operand(kScratchRegister, 0), object); | 2479 movq(Operand(kScratchRegister, 0), object); |
| 2472 } | 2480 } |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2758 CPU::FlushICache(address_, size_); | 2766 CPU::FlushICache(address_, size_); |
| 2759 | 2767 |
| 2760 // Check that the code was patched as expected. | 2768 // Check that the code was patched as expected. |
| 2761 ASSERT(masm_.pc_ == address_ + size_); | 2769 ASSERT(masm_.pc_ == address_ + size_); |
| 2762 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2770 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 2763 } | 2771 } |
| 2764 | 2772 |
| 2765 } } // namespace v8::internal | 2773 } } // namespace v8::internal |
| 2766 | 2774 |
| 2767 #endif // V8_TARGET_ARCH_X64 | 2775 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |