| 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 |