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_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 |
6 | 6 |
7 // Note on Mips implementation: | 7 // Note on Mips implementation: |
8 // | 8 // |
9 // The result_register() for mips is the 'v0' register, which is defined | 9 // The result_register() for mips is the 'v0' register, which is defined |
10 // by the ABI to contain function return values. However, the first | 10 // by the ABI to contain function return values. However, the first |
11 // parameter to a function is defined to be 'a0'. So there are many | 11 // parameter to a function is defined to be 'a0'. So there are many |
12 // places where we have to move a previous result in v0 to a0 for the | 12 // places where we have to move a previous result in v0 to a0 for the |
13 // next call: mov(a0, v0). This is not needed on the other architectures. | 13 // next call: mov(a0, v0). This is not needed on the other architectures. |
14 | 14 |
15 #include "src/ast/scopes.h" | 15 #include "src/ast/scopes.h" |
16 #include "src/code-factory.h" | 16 #include "src/code-factory.h" |
17 #include "src/code-stubs.h" | 17 #include "src/code-stubs.h" |
18 #include "src/codegen.h" | 18 #include "src/codegen.h" |
19 #include "src/debug/debug.h" | 19 #include "src/debug/debug.h" |
20 #include "src/full-codegen/full-codegen.h" | 20 #include "src/full-codegen/full-codegen.h" |
21 #include "src/ic/ic.h" | 21 #include "src/ic/ic.h" |
22 #include "src/parsing/parser.h" | 22 #include "src/parsing/parser.h" |
23 | 23 |
24 #include "src/mips64/code-stubs-mips64.h" | 24 #include "src/mips64/code-stubs-mips64.h" |
25 #include "src/mips64/macro-assembler-mips64.h" | 25 #include "src/mips64/macro-assembler-mips64.h" |
26 | 26 |
27 namespace v8 { | 27 namespace v8 { |
28 namespace internal { | 28 namespace internal { |
29 | 29 |
30 #define __ ACCESS_MASM(masm_) | 30 #define __ ACCESS_MASM(masm()) |
31 | |
32 | 31 |
33 // A patch site is a location in the code which it is possible to patch. This | 32 // A patch site is a location in the code which it is possible to patch. This |
34 // class has a number of methods to emit the code which is patchable and the | 33 // class has a number of methods to emit the code which is patchable and the |
35 // method EmitPatchInfo to record a marker back to the patchable code. This | 34 // method EmitPatchInfo to record a marker back to the patchable code. This |
36 // marker is a andi zero_reg, rx, #yyyy instruction, and rx * 0x0000ffff + yyyy | 35 // marker is a andi zero_reg, rx, #yyyy instruction, and rx * 0x0000ffff + yyyy |
37 // (raw 16 bit immediate value is used) is the delta from the pc to the first | 36 // (raw 16 bit immediate value is used) is the delta from the pc to the first |
38 // instruction of the patchable code. | 37 // instruction of the patchable code. |
39 // The marker instruction is effectively a NOP (dest is zero_reg) and will | 38 // The marker instruction is effectively a NOP (dest is zero_reg) and will |
40 // never be emitted by normal code. | 39 // never be emitted by normal code. |
41 class JumpPatchSite BASE_EMBEDDED { | 40 class JumpPatchSite BASE_EMBEDDED { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 __ andi(zero_reg, reg, delta_to_patch_site % kImm16Mask); | 78 __ andi(zero_reg, reg, delta_to_patch_site % kImm16Mask); |
80 #ifdef DEBUG | 79 #ifdef DEBUG |
81 info_emitted_ = true; | 80 info_emitted_ = true; |
82 #endif | 81 #endif |
83 } else { | 82 } else { |
84 __ nop(); // Signals no inlined code. | 83 __ nop(); // Signals no inlined code. |
85 } | 84 } |
86 } | 85 } |
87 | 86 |
88 private: | 87 private: |
| 88 MacroAssembler* masm() { return masm_; } |
89 MacroAssembler* masm_; | 89 MacroAssembler* masm_; |
90 Label patch_site_; | 90 Label patch_site_; |
91 #ifdef DEBUG | 91 #ifdef DEBUG |
92 bool info_emitted_; | 92 bool info_emitted_; |
93 #endif | 93 #endif |
94 }; | 94 }; |
95 | 95 |
96 | 96 |
97 // Generate code for a JS function. On entry to the function the receiver | 97 // Generate code for a JS function. On entry to the function the receiver |
98 // and arguments have been pushed on the stack left to right. The actual | 98 // and arguments have been pushed on the stack left to right. The actual |
(...skipping 1837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1936 __ bind(&continuation); | 1936 __ bind(&continuation); |
1937 // When we arrive here, the stack top is the resume mode and | 1937 // When we arrive here, the stack top is the resume mode and |
1938 // result_register() holds the input value (the argument given to the | 1938 // result_register() holds the input value (the argument given to the |
1939 // respective resume operation). | 1939 // respective resume operation). |
1940 __ RecordGeneratorContinuation(); | 1940 __ RecordGeneratorContinuation(); |
1941 __ pop(a1); | 1941 __ pop(a1); |
1942 __ Branch(&resume, ne, a1, | 1942 __ Branch(&resume, ne, a1, |
1943 Operand(Smi::FromInt(JSGeneratorObject::RETURN))); | 1943 Operand(Smi::FromInt(JSGeneratorObject::RETURN))); |
1944 __ push(result_register()); | 1944 __ push(result_register()); |
1945 EmitCreateIteratorResult(true); | 1945 EmitCreateIteratorResult(true); |
1946 EmitUnwindBeforeReturn(); | 1946 EmitUnwindAndReturn(); |
1947 EmitReturnSequence(); | |
1948 | 1947 |
1949 __ bind(&suspend); | 1948 __ bind(&suspend); |
1950 VisitForAccumulatorValue(expr->generator_object()); | 1949 VisitForAccumulatorValue(expr->generator_object()); |
1951 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1950 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
1952 __ li(a1, Operand(Smi::FromInt(continuation.pos()))); | 1951 __ li(a1, Operand(Smi::FromInt(continuation.pos()))); |
1953 __ sd(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset)); | 1952 __ sd(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset)); |
1954 __ sd(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset)); | 1953 __ sd(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset)); |
1955 __ mov(a1, cp); | 1954 __ mov(a1, cp); |
1956 __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2, | 1955 __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2, |
1957 kRAHasBeenSaved, kDontSaveFPRegs); | 1956 kRAHasBeenSaved, kDontSaveFPRegs); |
1958 __ Daddu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); | 1957 __ Daddu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); |
1959 __ Branch(&post_runtime, eq, sp, Operand(a1)); | 1958 __ Branch(&post_runtime, eq, sp, Operand(a1)); |
1960 __ push(v0); // generator object | 1959 __ push(v0); // generator object |
1961 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1960 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
1962 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1961 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1963 __ bind(&post_runtime); | 1962 __ bind(&post_runtime); |
1964 __ pop(result_register()); | 1963 __ pop(result_register()); |
1965 EmitReturnSequence(); | 1964 EmitReturnSequence(); |
1966 | 1965 |
1967 __ bind(&resume); | 1966 __ bind(&resume); |
1968 context()->Plug(result_register()); | 1967 context()->Plug(result_register()); |
1969 break; | 1968 break; |
1970 } | 1969 } |
1971 | 1970 |
1972 case Yield::kFinal: { | 1971 case Yield::kFinal: { |
1973 // Pop value from top-of-stack slot, box result into result register. | 1972 // Pop value from top-of-stack slot, box result into result register. |
1974 EmitCreateIteratorResult(true); | 1973 EmitCreateIteratorResult(true); |
1975 EmitUnwindBeforeReturn(); | 1974 EmitUnwindAndReturn(); |
1976 EmitReturnSequence(); | |
1977 break; | 1975 break; |
1978 } | 1976 } |
1979 | 1977 |
1980 case Yield::kDelegating: { | 1978 case Yield::kDelegating: { |
1981 VisitForStackValue(expr->generator_object()); | 1979 VisitForStackValue(expr->generator_object()); |
1982 | 1980 |
1983 // Initial stack layout is as follows: | 1981 // Initial stack layout is as follows: |
1984 // [sp + 1 * kPointerSize] iter | 1982 // [sp + 1 * kPointerSize] iter |
1985 // [sp + 0 * kPointerSize] g | 1983 // [sp + 0 * kPointerSize] g |
1986 | 1984 |
(...skipping 2684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4671 } | 4669 } |
4672 __ push(at); | 4670 __ push(at); |
4673 } | 4671 } |
4674 | 4672 |
4675 | 4673 |
4676 // ---------------------------------------------------------------------------- | 4674 // ---------------------------------------------------------------------------- |
4677 // Non-local control flow support. | 4675 // Non-local control flow support. |
4678 | 4676 |
4679 void FullCodeGenerator::EnterFinallyBlock() { | 4677 void FullCodeGenerator::EnterFinallyBlock() { |
4680 DCHECK(!result_register().is(a1)); | 4678 DCHECK(!result_register().is(a1)); |
4681 // Store result register while executing finally block. | |
4682 __ push(result_register()); | |
4683 // Cook return address in link register to stack (smi encoded Code* delta). | |
4684 __ Dsubu(a1, ra, Operand(masm_->CodeObject())); | |
4685 __ SmiTag(a1); | |
4686 | |
4687 // Store result register while executing finally block. | |
4688 __ push(a1); | |
4689 | |
4690 // Store pending message while executing finally block. | 4679 // Store pending message while executing finally block. |
4691 ExternalReference pending_message_obj = | 4680 ExternalReference pending_message_obj = |
4692 ExternalReference::address_of_pending_message_obj(isolate()); | 4681 ExternalReference::address_of_pending_message_obj(isolate()); |
4693 __ li(at, Operand(pending_message_obj)); | 4682 __ li(at, Operand(pending_message_obj)); |
4694 __ ld(a1, MemOperand(at)); | 4683 __ ld(a1, MemOperand(at)); |
4695 __ push(a1); | 4684 __ push(a1); |
4696 | 4685 |
4697 ClearPendingMessage(); | 4686 ClearPendingMessage(); |
4698 } | 4687 } |
4699 | 4688 |
4700 | 4689 |
4701 void FullCodeGenerator::ExitFinallyBlock() { | 4690 void FullCodeGenerator::ExitFinallyBlock() { |
4702 DCHECK(!result_register().is(a1)); | 4691 DCHECK(!result_register().is(a1)); |
4703 // Restore pending message from stack. | 4692 // Restore pending message from stack. |
4704 __ pop(a1); | 4693 __ pop(a1); |
4705 ExternalReference pending_message_obj = | 4694 ExternalReference pending_message_obj = |
4706 ExternalReference::address_of_pending_message_obj(isolate()); | 4695 ExternalReference::address_of_pending_message_obj(isolate()); |
4707 __ li(at, Operand(pending_message_obj)); | 4696 __ li(at, Operand(pending_message_obj)); |
4708 __ sd(a1, MemOperand(at)); | 4697 __ sd(a1, MemOperand(at)); |
4709 | |
4710 // Restore result register from stack. | |
4711 __ pop(a1); | |
4712 | |
4713 // Uncook return address and return. | |
4714 __ pop(result_register()); | |
4715 | |
4716 __ SmiUntag(a1); | |
4717 __ Daddu(at, a1, Operand(masm_->CodeObject())); | |
4718 __ Jump(at); | |
4719 } | 4698 } |
4720 | 4699 |
4721 | 4700 |
4722 void FullCodeGenerator::ClearPendingMessage() { | 4701 void FullCodeGenerator::ClearPendingMessage() { |
4723 DCHECK(!result_register().is(a1)); | 4702 DCHECK(!result_register().is(a1)); |
4724 ExternalReference pending_message_obj = | 4703 ExternalReference pending_message_obj = |
4725 ExternalReference::address_of_pending_message_obj(isolate()); | 4704 ExternalReference::address_of_pending_message_obj(isolate()); |
4726 __ LoadRoot(a1, Heap::kTheHoleValueRootIndex); | 4705 __ LoadRoot(a1, Heap::kTheHoleValueRootIndex); |
4727 __ li(at, Operand(pending_message_obj)); | 4706 __ li(at, Operand(pending_message_obj)); |
4728 __ sd(a1, MemOperand(at)); | 4707 __ sd(a1, MemOperand(at)); |
4729 } | 4708 } |
4730 | 4709 |
4731 | 4710 |
4732 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { | 4711 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { |
4733 DCHECK(!slot.IsInvalid()); | 4712 DCHECK(!slot.IsInvalid()); |
4734 __ li(VectorStoreICTrampolineDescriptor::SlotRegister(), | 4713 __ li(VectorStoreICTrampolineDescriptor::SlotRegister(), |
4735 Operand(SmiFromSlot(slot))); | 4714 Operand(SmiFromSlot(slot))); |
4736 } | 4715 } |
4737 | 4716 |
| 4717 void FullCodeGenerator::DeferredCommands::EmitCommands() { |
| 4718 __ Pop(result_register()); // Restore the accumulator. |
| 4719 __ Pop(a1); // Get the token. |
| 4720 for (DeferredCommand cmd : commands_) { |
| 4721 Label skip; |
| 4722 __ li(at, Operand(Smi::FromInt(cmd.token))); |
| 4723 __ Branch(&skip, ne, a1, Operand(at)); |
| 4724 switch (cmd.command) { |
| 4725 case kReturn: |
| 4726 codegen_->EmitUnwindAndReturn(); |
| 4727 break; |
| 4728 case kThrow: |
| 4729 __ Push(result_register()); |
| 4730 __ CallRuntime(Runtime::kReThrow); |
| 4731 break; |
| 4732 case kContinue: |
| 4733 codegen_->EmitContinue(cmd.target); |
| 4734 break; |
| 4735 case kBreak: |
| 4736 codegen_->EmitBreak(cmd.target); |
| 4737 break; |
| 4738 } |
| 4739 __ bind(&skip); |
| 4740 } |
| 4741 } |
4738 | 4742 |
4739 #undef __ | 4743 #undef __ |
4740 | 4744 |
4741 | 4745 |
4742 void BackEdgeTable::PatchAt(Code* unoptimized_code, | 4746 void BackEdgeTable::PatchAt(Code* unoptimized_code, |
4743 Address pc, | 4747 Address pc, |
4744 BackEdgeState target_state, | 4748 BackEdgeState target_state, |
4745 Code* replacement_code) { | 4749 Code* replacement_code) { |
4746 static const int kInstrSize = Assembler::kInstrSize; | 4750 static const int kInstrSize = Assembler::kInstrSize; |
4747 Address branch_address = pc - 8 * kInstrSize; | 4751 Address branch_address = pc - 8 * kInstrSize; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4817 reinterpret_cast<uint64_t>( | 4821 reinterpret_cast<uint64_t>( |
4818 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4822 isolate->builtins()->OsrAfterStackCheck()->entry())); |
4819 return OSR_AFTER_STACK_CHECK; | 4823 return OSR_AFTER_STACK_CHECK; |
4820 } | 4824 } |
4821 | 4825 |
4822 | 4826 |
4823 } // namespace internal | 4827 } // namespace internal |
4824 } // namespace v8 | 4828 } // namespace v8 |
4825 | 4829 |
4826 #endif // V8_TARGET_ARCH_MIPS64 | 4830 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |