OLD | NEW |
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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 bind(&L); | 58 bind(&L); |
59 } | 59 } |
60 | 60 |
61 | 61 |
62 void MacroAssembler::ConstructAndTestJSFunction() { | 62 void MacroAssembler::ConstructAndTestJSFunction() { |
63 const int initial_buffer_size = 4 * KB; | 63 const int initial_buffer_size = 4 * KB; |
64 char* buffer = new char[initial_buffer_size]; | 64 char* buffer = new char[initial_buffer_size]; |
65 MacroAssembler masm(buffer, initial_buffer_size); | 65 MacroAssembler masm(buffer, initial_buffer_size); |
66 | 66 |
67 const uint64_t secret = V8_INT64_C(0xdeadbeefcafebabe); | 67 const uint64_t secret = V8_INT64_C(0xdeadbeefcafebabe); |
| 68 Handle<String> constant = |
| 69 Factory::NewStringFromAscii(Vector<const char>("451", 3), TENURED); |
68 #define __ ACCESS_MASM((&masm)) | 70 #define __ ACCESS_MASM((&masm)) |
69 // Construct a simple JSfunction here, using Assembler and MacroAssembler | 71 // Construct a simple JSfunction here, using Assembler and MacroAssembler |
70 // commands. | 72 // commands. |
71 __ movq(rax, secret, RelocInfo::NONE); | 73 __ movq(rax, constant, RelocInfo::EMBEDDED_OBJECT); |
| 74 __ push(rax); |
| 75 __ CallRuntime(Runtime::kStringParseFloat, 1); |
| 76 __ movq(kScratchRegister, secret, RelocInfo::NONE); |
| 77 __ addq(rax, kScratchRegister); |
72 __ ret(0); | 78 __ ret(0); |
73 #undef __ | 79 #undef __ |
74 CodeDesc desc; | 80 CodeDesc desc; |
75 masm.GetCode(&desc); | 81 masm.GetCode(&desc); |
76 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); | 82 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION); |
77 Object* code = Heap::CreateCode(desc, NULL, flags, Handle<Object>::null()); | 83 Object* code = Heap::CreateCode(desc, NULL, flags, Handle<Object>::null()); |
78 if (!code->IsFailure()) { | 84 if (!code->IsFailure()) { |
79 Handle<Code> code_handle(Code::cast(code)); | 85 Handle<Code> code_handle(Code::cast(code)); |
80 Handle<String> name = | 86 Handle<String> name = |
81 Factory::NewStringFromAscii(Vector<const char>("foo", 3), NOT_TENURED); | 87 Factory::NewStringFromAscii(Vector<const char>("foo", 3), NOT_TENURED); |
82 Handle<JSFunction> function = | 88 Handle<JSFunction> function = |
83 Factory::NewFunction(name, | 89 Factory::NewFunction(name, |
84 JS_FUNCTION_TYPE, | 90 JS_FUNCTION_TYPE, |
85 JSObject::kHeaderSize, | 91 JSObject::kHeaderSize, |
86 code_handle, | 92 code_handle, |
87 true); | 93 true); |
88 bool pending_exceptions; | 94 bool pending_exceptions; |
89 Handle<Object> result = | 95 Handle<Object> result = |
90 Execution::Call(function, | 96 Execution::Call(function, |
91 Handle<Object>::cast(function), | 97 Handle<Object>::cast(function), |
92 0, | 98 0, |
93 NULL, | 99 NULL, |
94 &pending_exceptions); | 100 &pending_exceptions); |
95 CHECK(result->IsSmi()); | 101 CHECK(result->IsSmi()); |
96 CHECK(secret == reinterpret_cast<uint64_t>(*result)); | 102 CHECK(secret + (451 << kSmiTagSize) == reinterpret_cast<uint64_t>(*result)); |
97 } | 103 } |
98 } | 104 } |
99 | 105 |
100 | 106 |
101 void MacroAssembler::Abort(const char* msg) { | 107 void MacroAssembler::Abort(const char* msg) { |
102 // We want to pass the msg string like a smi to avoid GC | 108 // We want to pass the msg string like a smi to avoid GC |
103 // problems, however msg is not guaranteed to be aligned | 109 // problems, however msg is not guaranteed to be aligned |
104 // properly. Instead, we pass an aligned pointer that is | 110 // properly. Instead, we pass an aligned pointer that is |
105 // a proper v8 smi, but also pass the alignment difference | 111 // a proper v8 smi, but also pass the alignment difference |
106 // from the real pointer as a smi. | 112 // from the real pointer as a smi. |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 movq(rbp, rsp); | 580 movq(rbp, rsp); |
575 | 581 |
576 // Reserve room for entry stack pointer and push the debug marker. | 582 // Reserve room for entry stack pointer and push the debug marker. |
577 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 583 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
578 push(Immediate(0)); // saved entry sp, patched before call | 584 push(Immediate(0)); // saved entry sp, patched before call |
579 push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0)); | 585 push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0)); |
580 | 586 |
581 // Save the frame pointer and the context in top. | 587 // Save the frame pointer and the context in top. |
582 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); | 588 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); |
583 ExternalReference context_address(Top::k_context_address); | 589 ExternalReference context_address(Top::k_context_address); |
584 movq(kScratchRegister, rax); | 590 movq(rdi, rax); // Backup rax before we use it. |
| 591 |
585 movq(rax, rbp); | 592 movq(rax, rbp); |
586 store_rax(c_entry_fp_address); | 593 store_rax(c_entry_fp_address); |
587 movq(rax, rsi); | 594 movq(rax, rsi); |
588 store_rax(context_address); | 595 store_rax(context_address); |
589 movq(rax, kScratchRegister); | |
590 | 596 |
591 // Setup argc and argv in callee-saved registers. | 597 // Setup argv in callee-saved register r15. |
592 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; | 598 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
593 movq(rdi, rax); | 599 lea(r15, Operand(rbp, rdi, kTimesPointerSize, offset)); |
594 lea(rsi, Operand(rbp, rax, kTimesPointerSize, offset)); | |
595 | 600 |
596 #ifdef ENABLE_DEBUGGER_SUPPORT | 601 #ifdef ENABLE_DEBUGGER_SUPPORT |
597 // Save the state of all registers to the stack from the memory | 602 // Save the state of all registers to the stack from the memory |
598 // location. This is needed to allow nested break points. | 603 // location. This is needed to allow nested break points. |
599 if (type == StackFrame::EXIT_DEBUG) { | 604 if (type == StackFrame::EXIT_DEBUG) { |
600 // TODO(1243899): This should be symmetric to | 605 // TODO(1243899): This should be symmetric to |
601 // CopyRegistersFromStackToMemory() but it isn't! esp is assumed | 606 // CopyRegistersFromStackToMemory() but it isn't! esp is assumed |
602 // correct here, but computed for the other call. Very error | 607 // correct here, but computed for the other call. Very error |
603 // prone! FIX THIS. Actually there are deeper problems with | 608 // prone! FIX THIS. Actually there are deeper problems with |
604 // register saving than this asymmetry (see the bug report | 609 // register saving than this asymmetry (see the bug report |
605 // associated with this issue). | 610 // associated with this issue). |
606 PushRegistersFromMemory(kJSCallerSaved); | 611 PushRegistersFromMemory(kJSCallerSaved); |
607 } | 612 } |
608 #endif | 613 #endif |
609 | 614 |
610 // Reserve space for two arguments: argc and argv. | 615 // Reserve space for two arguments: argc and argv |
611 subq(rsp, Immediate(2 * kPointerSize)); | 616 subq(rsp, Immediate(2 * kPointerSize)); |
612 | 617 |
613 // Get the required frame alignment for the OS. | 618 // Get the required frame alignment for the OS. |
614 static const int kFrameAlignment = OS::ActivationFrameAlignment(); | 619 static const int kFrameAlignment = OS::ActivationFrameAlignment(); |
615 if (kFrameAlignment > 0) { | 620 if (kFrameAlignment > 0) { |
616 ASSERT(IsPowerOf2(kFrameAlignment)); | 621 ASSERT(IsPowerOf2(kFrameAlignment)); |
617 movq(r10, Immediate(-kFrameAlignment)); | 622 movq(kScratchRegister, Immediate(-kFrameAlignment)); |
618 and_(rsp, r10); | 623 and_(rsp, kScratchRegister); |
619 } | 624 } |
620 | 625 |
621 // Patch the saved entry sp. | 626 // Patch the saved entry sp. |
622 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); | 627 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); |
623 } | 628 } |
624 | 629 |
625 | 630 |
626 void MacroAssembler::LeaveExitFrame(StackFrame::Type type) { | 631 void MacroAssembler::LeaveExitFrame(StackFrame::Type type) { |
| 632 // Registers: |
| 633 // r14 : argc |
| 634 // r15 : argv |
627 #ifdef ENABLE_DEBUGGER_SUPPORT | 635 #ifdef ENABLE_DEBUGGER_SUPPORT |
628 // Restore the memory copy of the registers by digging them out from | 636 // Restore the memory copy of the registers by digging them out from |
629 // the stack. This is needed to allow nested break points. | 637 // the stack. This is needed to allow nested break points. |
630 if (type == StackFrame::EXIT_DEBUG) { | 638 if (type == StackFrame::EXIT_DEBUG) { |
631 // It's okay to clobber register ebx below because we don't need | 639 // It's okay to clobber register ebx below because we don't need |
632 // the function pointer after this. | 640 // the function pointer after this. |
633 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; | 641 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; |
634 int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize; | 642 int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize; |
635 lea(rbx, Operand(rbp, kOffset)); | 643 lea(rbx, Operand(rbp, kOffset)); |
636 CopyRegistersFromStackToMemory(rbx, rcx, kJSCallerSaved); | 644 CopyRegistersFromStackToMemory(rbx, rcx, kJSCallerSaved); |
637 } | 645 } |
638 #endif | 646 #endif |
639 | 647 |
640 // Get the return address from the stack and restore the frame pointer. | 648 // Get the return address from the stack and restore the frame pointer. |
641 movq(rcx, Operand(rbp, 1 * kPointerSize)); | 649 movq(rcx, Operand(rbp, 1 * kPointerSize)); |
642 movq(rbp, Operand(rbp, 0 * kPointerSize)); | 650 movq(rbp, Operand(rbp, 0 * kPointerSize)); |
643 | 651 |
644 // Pop the arguments and the receiver from the caller stack. | 652 // Pop the arguments and the receiver from the caller stack. |
645 lea(rsp, Operand(rsi, 1 * kPointerSize)); | 653 lea(rsp, Operand(r15, 1 * kPointerSize)); |
646 | 654 |
647 // Restore current context from top and clear it in debug mode. | 655 // Restore current context from top and clear it in debug mode. |
648 ExternalReference context_address(Top::k_context_address); | 656 ExternalReference context_address(Top::k_context_address); |
649 movq(kScratchRegister, context_address); | 657 movq(kScratchRegister, context_address); |
650 movq(rsi, Operand(kScratchRegister, 0)); | 658 movq(rsi, Operand(kScratchRegister, 0)); |
651 #ifdef DEBUG | 659 #ifdef DEBUG |
652 movq(Operand(kScratchRegister, 0), Immediate(0)); | 660 movq(Operand(kScratchRegister, 0), Immediate(0)); |
653 #endif | 661 #endif |
654 | 662 |
655 // Push the return address to get ready to return. | 663 // Push the return address to get ready to return. |
656 push(rcx); | 664 push(rcx); |
657 | 665 |
658 // Clear the top frame. | 666 // Clear the top frame. |
659 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); | 667 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); |
660 movq(kScratchRegister, c_entry_fp_address); | 668 movq(kScratchRegister, c_entry_fp_address); |
661 movq(Operand(kScratchRegister, 0), Immediate(0)); | 669 movq(Operand(kScratchRegister, 0), Immediate(0)); |
662 } | 670 } |
663 | 671 |
664 | 672 |
665 } } // namespace v8::internal | 673 } } // namespace v8::internal |
OLD | NEW |