OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
11 #include "src/debug/debug.h" | 11 #include "src/debug/debug.h" |
12 #include "src/full-codegen/full-codegen.h" | 12 #include "src/full-codegen/full-codegen.h" |
13 #include "src/ic/ic.h" | 13 #include "src/ic/ic.h" |
14 #include "src/parsing/parser.h" | 14 #include "src/parsing/parser.h" |
15 | 15 |
16 namespace v8 { | 16 namespace v8 { |
17 namespace internal { | 17 namespace internal { |
18 | 18 |
19 #define __ ACCESS_MASM(masm_) | 19 #define __ ACCESS_MASM(masm()) |
20 | |
21 | 20 |
22 class JumpPatchSite BASE_EMBEDDED { | 21 class JumpPatchSite BASE_EMBEDDED { |
23 public: | 22 public: |
24 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { | 23 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { |
25 #ifdef DEBUG | 24 #ifdef DEBUG |
26 info_emitted_ = false; | 25 info_emitted_ = false; |
27 #endif | 26 #endif |
28 } | 27 } |
29 | 28 |
30 ~JumpPatchSite() { | 29 ~JumpPatchSite() { |
(...skipping 29 matching lines...) Expand all Loading... |
60 | 59 |
61 private: | 60 private: |
62 // jc will be patched with jz, jnc will become jnz. | 61 // jc will be patched with jz, jnc will become jnz. |
63 void EmitJump(Condition cc, Label* target, Label::Distance near_jump) { | 62 void EmitJump(Condition cc, Label* target, Label::Distance near_jump) { |
64 DCHECK(!patch_site_.is_bound() && !info_emitted_); | 63 DCHECK(!patch_site_.is_bound() && !info_emitted_); |
65 DCHECK(cc == carry || cc == not_carry); | 64 DCHECK(cc == carry || cc == not_carry); |
66 __ bind(&patch_site_); | 65 __ bind(&patch_site_); |
67 __ j(cc, target, near_jump); | 66 __ j(cc, target, near_jump); |
68 } | 67 } |
69 | 68 |
| 69 MacroAssembler* masm() { return masm_; } |
70 MacroAssembler* masm_; | 70 MacroAssembler* masm_; |
71 Label patch_site_; | 71 Label patch_site_; |
72 #ifdef DEBUG | 72 #ifdef DEBUG |
73 bool info_emitted_; | 73 bool info_emitted_; |
74 #endif | 74 #endif |
75 }; | 75 }; |
76 | 76 |
77 | 77 |
78 // Generate code for a JS function. On entry to the function the receiver | 78 // Generate code for a JS function. On entry to the function the receiver |
79 // and arguments have been pushed on the stack left to right, with the | 79 // and arguments have been pushed on the stack left to right, with the |
(...skipping 1791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1871 __ bind(&continuation); | 1871 __ bind(&continuation); |
1872 // When we arrive here, the stack top is the resume mode and | 1872 // When we arrive here, the stack top is the resume mode and |
1873 // result_register() holds the input value (the argument given to the | 1873 // result_register() holds the input value (the argument given to the |
1874 // respective resume operation). | 1874 // respective resume operation). |
1875 __ RecordGeneratorContinuation(); | 1875 __ RecordGeneratorContinuation(); |
1876 __ Pop(rbx); | 1876 __ Pop(rbx); |
1877 __ SmiCompare(rbx, Smi::FromInt(JSGeneratorObject::RETURN)); | 1877 __ SmiCompare(rbx, Smi::FromInt(JSGeneratorObject::RETURN)); |
1878 __ j(not_equal, &resume); | 1878 __ j(not_equal, &resume); |
1879 __ Push(result_register()); | 1879 __ Push(result_register()); |
1880 EmitCreateIteratorResult(true); | 1880 EmitCreateIteratorResult(true); |
1881 EmitUnwindBeforeReturn(); | 1881 EmitUnwindAndReturn(); |
1882 EmitReturnSequence(); | |
1883 | 1882 |
1884 __ bind(&suspend); | 1883 __ bind(&suspend); |
1885 VisitForAccumulatorValue(expr->generator_object()); | 1884 VisitForAccumulatorValue(expr->generator_object()); |
1886 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1885 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
1887 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), | 1886 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), |
1888 Smi::FromInt(continuation.pos())); | 1887 Smi::FromInt(continuation.pos())); |
1889 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); | 1888 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); |
1890 __ movp(rcx, rsi); | 1889 __ movp(rcx, rsi); |
1891 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, | 1890 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, |
1892 kDontSaveFPRegs); | 1891 kDontSaveFPRegs); |
(...skipping 10 matching lines...) Expand all Loading... |
1903 EmitReturnSequence(); | 1902 EmitReturnSequence(); |
1904 | 1903 |
1905 __ bind(&resume); | 1904 __ bind(&resume); |
1906 context()->Plug(result_register()); | 1905 context()->Plug(result_register()); |
1907 break; | 1906 break; |
1908 } | 1907 } |
1909 | 1908 |
1910 case Yield::kFinal: { | 1909 case Yield::kFinal: { |
1911 // Pop value from top-of-stack slot, box result into result register. | 1910 // Pop value from top-of-stack slot, box result into result register. |
1912 EmitCreateIteratorResult(true); | 1911 EmitCreateIteratorResult(true); |
1913 EmitUnwindBeforeReturn(); | 1912 EmitUnwindAndReturn(); |
1914 EmitReturnSequence(); | |
1915 break; | 1913 break; |
1916 } | 1914 } |
1917 | 1915 |
1918 case Yield::kDelegating: { | 1916 case Yield::kDelegating: { |
1919 VisitForStackValue(expr->generator_object()); | 1917 VisitForStackValue(expr->generator_object()); |
1920 | 1918 |
1921 // Initial stack layout is as follows: | 1919 // Initial stack layout is as follows: |
1922 // [sp + 1 * kPointerSize] iter | 1920 // [sp + 1 * kPointerSize] iter |
1923 // [sp + 0 * kPointerSize] g | 1921 // [sp + 0 * kPointerSize] g |
1924 | 1922 |
(...skipping 2658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4583 } | 4581 } |
4584 } | 4582 } |
4585 | 4583 |
4586 | 4584 |
4587 // ---------------------------------------------------------------------------- | 4585 // ---------------------------------------------------------------------------- |
4588 // Non-local control flow support. | 4586 // Non-local control flow support. |
4589 | 4587 |
4590 | 4588 |
4591 void FullCodeGenerator::EnterFinallyBlock() { | 4589 void FullCodeGenerator::EnterFinallyBlock() { |
4592 DCHECK(!result_register().is(rdx)); | 4590 DCHECK(!result_register().is(rdx)); |
4593 DCHECK(!result_register().is(rcx)); | |
4594 // Cook return address on top of stack (smi encoded Code* delta) | |
4595 __ PopReturnAddressTo(rdx); | |
4596 __ Move(rcx, masm_->CodeObject()); | |
4597 __ subp(rdx, rcx); | |
4598 __ Integer32ToSmi(rdx, rdx); | |
4599 __ Push(rdx); | |
4600 | |
4601 // Store result register while executing finally block. | |
4602 __ Push(result_register()); | |
4603 | 4591 |
4604 // Store pending message while executing finally block. | 4592 // Store pending message while executing finally block. |
4605 ExternalReference pending_message_obj = | 4593 ExternalReference pending_message_obj = |
4606 ExternalReference::address_of_pending_message_obj(isolate()); | 4594 ExternalReference::address_of_pending_message_obj(isolate()); |
4607 __ Load(rdx, pending_message_obj); | 4595 __ Load(rdx, pending_message_obj); |
4608 __ Push(rdx); | 4596 __ Push(rdx); |
4609 | 4597 |
4610 ClearPendingMessage(); | 4598 ClearPendingMessage(); |
4611 } | 4599 } |
4612 | 4600 |
4613 | 4601 |
4614 void FullCodeGenerator::ExitFinallyBlock() { | 4602 void FullCodeGenerator::ExitFinallyBlock() { |
4615 DCHECK(!result_register().is(rdx)); | 4603 DCHECK(!result_register().is(rdx)); |
4616 DCHECK(!result_register().is(rcx)); | |
4617 // Restore pending message from stack. | 4604 // Restore pending message from stack. |
4618 __ Pop(rdx); | 4605 __ Pop(rdx); |
4619 ExternalReference pending_message_obj = | 4606 ExternalReference pending_message_obj = |
4620 ExternalReference::address_of_pending_message_obj(isolate()); | 4607 ExternalReference::address_of_pending_message_obj(isolate()); |
4621 __ Store(pending_message_obj, rdx); | 4608 __ Store(pending_message_obj, rdx); |
4622 | |
4623 // Restore result register from stack. | |
4624 __ Pop(result_register()); | |
4625 | |
4626 // Uncook return address. | |
4627 __ Pop(rdx); | |
4628 __ SmiToInteger32(rdx, rdx); | |
4629 __ Move(rcx, masm_->CodeObject()); | |
4630 __ addp(rdx, rcx); | |
4631 __ jmp(rdx); | |
4632 } | 4609 } |
4633 | 4610 |
4634 | 4611 |
4635 void FullCodeGenerator::ClearPendingMessage() { | 4612 void FullCodeGenerator::ClearPendingMessage() { |
4636 DCHECK(!result_register().is(rdx)); | 4613 DCHECK(!result_register().is(rdx)); |
4637 ExternalReference pending_message_obj = | 4614 ExternalReference pending_message_obj = |
4638 ExternalReference::address_of_pending_message_obj(isolate()); | 4615 ExternalReference::address_of_pending_message_obj(isolate()); |
4639 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); | 4616 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); |
4640 __ Store(pending_message_obj, rdx); | 4617 __ Store(pending_message_obj, rdx); |
4641 } | 4618 } |
4642 | 4619 |
4643 | 4620 |
4644 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { | 4621 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { |
4645 DCHECK(!slot.IsInvalid()); | 4622 DCHECK(!slot.IsInvalid()); |
4646 __ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot)); | 4623 __ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot)); |
4647 } | 4624 } |
4648 | 4625 |
| 4626 void FullCodeGenerator::DeferredCommands::EmitCommands() { |
| 4627 __ Pop(result_register()); // Restore the accumulator. |
| 4628 __ Pop(rdx); // Get the token. |
| 4629 for (DeferredCommand cmd : commands_) { |
| 4630 Label skip; |
| 4631 __ SmiCompare(rdx, Smi::FromInt(cmd.token)); |
| 4632 __ j(not_equal, &skip); |
| 4633 switch (cmd.command) { |
| 4634 case kReturn: |
| 4635 codegen_->EmitUnwindAndReturn(); |
| 4636 break; |
| 4637 case kThrow: |
| 4638 __ Push(result_register()); |
| 4639 __ CallRuntime(Runtime::kReThrow); |
| 4640 break; |
| 4641 case kContinue: |
| 4642 codegen_->EmitContinue(cmd.target); |
| 4643 break; |
| 4644 case kBreak: |
| 4645 codegen_->EmitBreak(cmd.target); |
| 4646 break; |
| 4647 } |
| 4648 __ bind(&skip); |
| 4649 } |
| 4650 } |
4649 | 4651 |
4650 #undef __ | 4652 #undef __ |
4651 | 4653 |
4652 | 4654 |
4653 static const byte kJnsInstruction = 0x79; | 4655 static const byte kJnsInstruction = 0x79; |
4654 static const byte kNopByteOne = 0x66; | 4656 static const byte kNopByteOne = 0x66; |
4655 static const byte kNopByteTwo = 0x90; | 4657 static const byte kNopByteTwo = 0x90; |
4656 #ifdef DEBUG | 4658 #ifdef DEBUG |
4657 static const byte kCallInstruction = 0xe8; | 4659 static const byte kCallInstruction = 0xe8; |
4658 #endif | 4660 #endif |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4719 isolate->builtins()->OnStackReplacement()->entry()) { | 4721 isolate->builtins()->OnStackReplacement()->entry()) { |
4720 return ON_STACK_REPLACEMENT; | 4722 return ON_STACK_REPLACEMENT; |
4721 } | 4723 } |
4722 | 4724 |
4723 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4725 DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4724 Assembler::target_address_at(call_target_address, | 4726 Assembler::target_address_at(call_target_address, |
4725 unoptimized_code)); | 4727 unoptimized_code)); |
4726 return OSR_AFTER_STACK_CHECK; | 4728 return OSR_AFTER_STACK_CHECK; |
4727 } | 4729 } |
4728 | 4730 |
4729 | |
4730 } // namespace internal | 4731 } // namespace internal |
4731 } // namespace v8 | 4732 } // namespace v8 |
4732 | 4733 |
4733 #endif // V8_TARGET_ARCH_X64 | 4734 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |