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_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
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/mips/code-stubs-mips.h" | 24 #include "src/mips/code-stubs-mips.h" |
25 #include "src/mips/macro-assembler-mips.h" | 25 #include "src/mips/macro-assembler-mips.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 1836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1935 __ bind(&continuation); | 1935 __ bind(&continuation); |
1936 // When we arrive here, the stack top is the resume mode and | 1936 // When we arrive here, the stack top is the resume mode and |
1937 // result_register() holds the input value (the argument given to the | 1937 // result_register() holds the input value (the argument given to the |
1938 // respective resume operation). | 1938 // respective resume operation). |
1939 __ RecordGeneratorContinuation(); | 1939 __ RecordGeneratorContinuation(); |
1940 __ pop(a1); | 1940 __ pop(a1); |
1941 __ Branch(&resume, ne, a1, | 1941 __ Branch(&resume, ne, a1, |
1942 Operand(Smi::FromInt(JSGeneratorObject::RETURN))); | 1942 Operand(Smi::FromInt(JSGeneratorObject::RETURN))); |
1943 __ push(result_register()); | 1943 __ push(result_register()); |
1944 EmitCreateIteratorResult(true); | 1944 EmitCreateIteratorResult(true); |
1945 EmitUnwindBeforeReturn(); | 1945 EmitUnwindAndReturn(); |
1946 EmitReturnSequence(); | |
1947 | 1946 |
1948 __ bind(&suspend); | 1947 __ bind(&suspend); |
1949 VisitForAccumulatorValue(expr->generator_object()); | 1948 VisitForAccumulatorValue(expr->generator_object()); |
1950 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1949 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
1951 __ li(a1, Operand(Smi::FromInt(continuation.pos()))); | 1950 __ li(a1, Operand(Smi::FromInt(continuation.pos()))); |
1952 __ sw(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset)); | 1951 __ sw(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset)); |
1953 __ sw(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset)); | 1952 __ sw(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset)); |
1954 __ mov(a1, cp); | 1953 __ mov(a1, cp); |
1955 __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2, | 1954 __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2, |
1956 kRAHasBeenSaved, kDontSaveFPRegs); | 1955 kRAHasBeenSaved, kDontSaveFPRegs); |
1957 __ Addu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); | 1956 __ Addu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); |
1958 __ Branch(&post_runtime, eq, sp, Operand(a1)); | 1957 __ Branch(&post_runtime, eq, sp, Operand(a1)); |
1959 __ push(v0); // generator object | 1958 __ push(v0); // generator object |
1960 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1959 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
1961 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1960 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1962 __ bind(&post_runtime); | 1961 __ bind(&post_runtime); |
1963 __ pop(result_register()); | 1962 __ pop(result_register()); |
1964 EmitReturnSequence(); | 1963 EmitReturnSequence(); |
1965 | 1964 |
1966 __ bind(&resume); | 1965 __ bind(&resume); |
1967 context()->Plug(result_register()); | 1966 context()->Plug(result_register()); |
1968 break; | 1967 break; |
1969 } | 1968 } |
1970 | 1969 |
1971 case Yield::kFinal: { | 1970 case Yield::kFinal: { |
1972 // Pop value from top-of-stack slot, box result into result register. | 1971 // Pop value from top-of-stack slot, box result into result register. |
1973 EmitCreateIteratorResult(true); | 1972 EmitCreateIteratorResult(true); |
1974 EmitUnwindBeforeReturn(); | 1973 EmitUnwindAndReturn(); |
1975 EmitReturnSequence(); | |
1976 break; | 1974 break; |
1977 } | 1975 } |
1978 | 1976 |
1979 case Yield::kDelegating: { | 1977 case Yield::kDelegating: { |
1980 VisitForStackValue(expr->generator_object()); | 1978 VisitForStackValue(expr->generator_object()); |
1981 | 1979 |
1982 // Initial stack layout is as follows: | 1980 // Initial stack layout is as follows: |
1983 // [sp + 1 * kPointerSize] iter | 1981 // [sp + 1 * kPointerSize] iter |
1984 // [sp + 0 * kPointerSize] g | 1982 // [sp + 0 * kPointerSize] g |
1985 | 1983 |
(...skipping 2671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4657 } | 4655 } |
4658 __ push(at); | 4656 __ push(at); |
4659 } | 4657 } |
4660 | 4658 |
4661 | 4659 |
4662 // ---------------------------------------------------------------------------- | 4660 // ---------------------------------------------------------------------------- |
4663 // Non-local control flow support. | 4661 // Non-local control flow support. |
4664 | 4662 |
4665 void FullCodeGenerator::EnterFinallyBlock() { | 4663 void FullCodeGenerator::EnterFinallyBlock() { |
4666 DCHECK(!result_register().is(a1)); | 4664 DCHECK(!result_register().is(a1)); |
4667 // Store result register while executing finally block. | |
4668 __ push(result_register()); | |
4669 // Cook return address in link register to stack (smi encoded Code* delta). | |
4670 __ Subu(a1, ra, Operand(masm_->CodeObject())); | |
4671 DCHECK_EQ(1, kSmiTagSize + kSmiShiftSize); | |
4672 STATIC_ASSERT(0 == kSmiTag); | |
4673 __ Addu(a1, a1, Operand(a1)); // Convert to smi. | |
4674 | |
4675 // Store result register while executing finally block. | |
4676 __ push(a1); | |
4677 | |
4678 // Store pending message while executing finally block. | 4665 // Store pending message while executing finally block. |
4679 ExternalReference pending_message_obj = | 4666 ExternalReference pending_message_obj = |
4680 ExternalReference::address_of_pending_message_obj(isolate()); | 4667 ExternalReference::address_of_pending_message_obj(isolate()); |
4681 __ li(at, Operand(pending_message_obj)); | 4668 __ li(at, Operand(pending_message_obj)); |
4682 __ lw(a1, MemOperand(at)); | 4669 __ lw(a1, MemOperand(at)); |
4683 __ push(a1); | 4670 __ push(a1); |
4684 | 4671 |
4685 ClearPendingMessage(); | 4672 ClearPendingMessage(); |
4686 } | 4673 } |
4687 | 4674 |
4688 | 4675 |
4689 void FullCodeGenerator::ExitFinallyBlock() { | 4676 void FullCodeGenerator::ExitFinallyBlock() { |
4690 DCHECK(!result_register().is(a1)); | 4677 DCHECK(!result_register().is(a1)); |
4691 // Restore pending message from stack. | 4678 // Restore pending message from stack. |
4692 __ pop(a1); | 4679 __ pop(a1); |
4693 ExternalReference pending_message_obj = | 4680 ExternalReference pending_message_obj = |
4694 ExternalReference::address_of_pending_message_obj(isolate()); | 4681 ExternalReference::address_of_pending_message_obj(isolate()); |
4695 __ li(at, Operand(pending_message_obj)); | 4682 __ li(at, Operand(pending_message_obj)); |
4696 __ sw(a1, MemOperand(at)); | 4683 __ sw(a1, MemOperand(at)); |
4697 | |
4698 // Restore result register from stack. | |
4699 __ pop(a1); | |
4700 | |
4701 // Uncook return address and return. | |
4702 __ pop(result_register()); | |
4703 DCHECK_EQ(1, kSmiTagSize + kSmiShiftSize); | |
4704 __ sra(a1, a1, 1); // Un-smi-tag value. | |
4705 __ Addu(at, a1, Operand(masm_->CodeObject())); | |
4706 __ Jump(at); | |
4707 } | 4684 } |
4708 | 4685 |
4709 | 4686 |
4710 void FullCodeGenerator::ClearPendingMessage() { | 4687 void FullCodeGenerator::ClearPendingMessage() { |
4711 DCHECK(!result_register().is(a1)); | 4688 DCHECK(!result_register().is(a1)); |
4712 ExternalReference pending_message_obj = | 4689 ExternalReference pending_message_obj = |
4713 ExternalReference::address_of_pending_message_obj(isolate()); | 4690 ExternalReference::address_of_pending_message_obj(isolate()); |
4714 __ LoadRoot(a1, Heap::kTheHoleValueRootIndex); | 4691 __ LoadRoot(a1, Heap::kTheHoleValueRootIndex); |
4715 __ li(at, Operand(pending_message_obj)); | 4692 __ li(at, Operand(pending_message_obj)); |
4716 __ sw(a1, MemOperand(at)); | 4693 __ sw(a1, MemOperand(at)); |
4717 } | 4694 } |
4718 | 4695 |
4719 | 4696 |
4720 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { | 4697 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) { |
4721 DCHECK(!slot.IsInvalid()); | 4698 DCHECK(!slot.IsInvalid()); |
4722 __ li(VectorStoreICTrampolineDescriptor::SlotRegister(), | 4699 __ li(VectorStoreICTrampolineDescriptor::SlotRegister(), |
4723 Operand(SmiFromSlot(slot))); | 4700 Operand(SmiFromSlot(slot))); |
4724 } | 4701 } |
4725 | 4702 |
| 4703 void FullCodeGenerator::DeferredCommands::EmitCommands() { |
| 4704 DCHECK(!result_register().is(a1)); |
| 4705 __ Pop(result_register()); // Restore the accumulator. |
| 4706 __ Pop(a1); // Get the token. |
| 4707 for (DeferredCommand cmd : commands_) { |
| 4708 Label skip; |
| 4709 __ li(at, Operand(Smi::FromInt(cmd.token))); |
| 4710 __ Branch(&skip, ne, a1, Operand(at)); |
| 4711 switch (cmd.command) { |
| 4712 case kReturn: |
| 4713 codegen_->EmitUnwindAndReturn(); |
| 4714 break; |
| 4715 case kThrow: |
| 4716 __ Push(result_register()); |
| 4717 __ CallRuntime(Runtime::kReThrow); |
| 4718 break; |
| 4719 case kContinue: |
| 4720 codegen_->EmitContinue(cmd.target); |
| 4721 break; |
| 4722 case kBreak: |
| 4723 codegen_->EmitBreak(cmd.target); |
| 4724 break; |
| 4725 } |
| 4726 __ bind(&skip); |
| 4727 } |
| 4728 } |
4726 | 4729 |
4727 #undef __ | 4730 #undef __ |
4728 | 4731 |
4729 | 4732 |
4730 void BackEdgeTable::PatchAt(Code* unoptimized_code, | 4733 void BackEdgeTable::PatchAt(Code* unoptimized_code, |
4731 Address pc, | 4734 Address pc, |
4732 BackEdgeState target_state, | 4735 BackEdgeState target_state, |
4733 Code* replacement_code) { | 4736 Code* replacement_code) { |
4734 static const int kInstrSize = Assembler::kInstrSize; | 4737 static const int kInstrSize = Assembler::kInstrSize; |
4735 Address branch_address = pc - 6 * kInstrSize; | 4738 Address branch_address = pc - 6 * kInstrSize; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4801 reinterpret_cast<uint32_t>( | 4804 reinterpret_cast<uint32_t>( |
4802 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4805 isolate->builtins()->OsrAfterStackCheck()->entry())); |
4803 return OSR_AFTER_STACK_CHECK; | 4806 return OSR_AFTER_STACK_CHECK; |
4804 } | 4807 } |
4805 | 4808 |
4806 | 4809 |
4807 } // namespace internal | 4810 } // namespace internal |
4808 } // namespace v8 | 4811 } // namespace v8 |
4809 | 4812 |
4810 #endif // V8_TARGET_ARCH_MIPS | 4813 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |