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