Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 #include "src/compilation-info.h" | 6 #include "src/compilation-info.h" |
| 7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
| 8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
| 9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
| 10 #include "src/compiler/osr.h" | 10 #include "src/compiler/osr.h" |
| (...skipping 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1928 return true; | 1928 return true; |
| 1929 case kUnsignedGreaterThan: | 1929 case kUnsignedGreaterThan: |
| 1930 cc = ugt; | 1930 cc = ugt; |
| 1931 return true; | 1931 return true; |
| 1932 default: | 1932 default: |
| 1933 break; | 1933 break; |
| 1934 } | 1934 } |
| 1935 return false; | 1935 return false; |
| 1936 } | 1936 } |
| 1937 | 1937 |
| 1938 void AssembleBranchToLabels(CodeGenerator* gen, MacroAssembler* masm, | |
|
titzer
2017/01/11 09:54:27
Same comment as previous CL. It'd be great to keep
ahaas
2017/01/11 14:31:44
Done.
| |
| 1939 Instruction* instr, FlagsCondition condition, | |
| 1940 Label* tlabel, Label* flabel, bool fallthru) { | |
| 1941 MipsOperandConverter i(gen, instr); | |
| 1938 | 1942 |
| 1939 // Assembles branches after an instruction. | |
| 1940 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | |
| 1941 MipsOperandConverter i(this, instr); | |
| 1942 Label* tlabel = branch->true_label; | |
| 1943 Label* flabel = branch->false_label; | |
| 1944 Condition cc = kNoCondition; | 1943 Condition cc = kNoCondition; |
| 1945 // MIPS does not have condition code flags, so compare and branch are | 1944 // MIPS does not have condition code flags, so compare and branch are |
| 1946 // implemented differently than on the other arch's. The compare operations | 1945 // implemented differently than on the other arch's. The compare operations |
| 1947 // emit mips psuedo-instructions, which are handled here by branch | 1946 // emit mips psuedo-instructions, which are handled here by branch |
| 1948 // instructions that do the actual comparison. Essential that the input | 1947 // instructions that do the actual comparison. Essential that the input |
| 1949 // registers to compare pseudo-op are not modified before this branch op, as | 1948 // registers to compare pseudo-op are not modified before this branch op, as |
| 1950 // they are tested here. | 1949 // they are tested here. |
| 1951 | 1950 |
| 1952 if (instr->arch_opcode() == kMips64Tst) { | 1951 if (instr->arch_opcode() == kMips64Tst) { |
| 1953 cc = FlagsConditionToConditionTst(branch->condition); | 1952 cc = FlagsConditionToConditionTst(condition); |
| 1954 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 1953 masm->And(at, i.InputRegister(0), i.InputOperand(1)); |
| 1955 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 1954 masm->Branch(tlabel, cc, at, Operand(zero_reg)); |
| 1956 } else if (instr->arch_opcode() == kMips64Dadd || | 1955 } else if (instr->arch_opcode() == kMips64Dadd || |
| 1957 instr->arch_opcode() == kMips64Dsub) { | 1956 instr->arch_opcode() == kMips64Dsub) { |
| 1958 cc = FlagsConditionToConditionOvf(branch->condition); | 1957 cc = FlagsConditionToConditionOvf(condition); |
| 1959 __ dsra32(kScratchReg, i.OutputRegister(), 0); | 1958 masm->dsra32(kScratchReg, i.OutputRegister(), 0); |
| 1960 __ sra(at, i.OutputRegister(), 31); | 1959 masm->sra(at, i.OutputRegister(), 31); |
| 1961 __ Branch(tlabel, cc, at, Operand(kScratchReg)); | 1960 masm->Branch(tlabel, cc, at, Operand(kScratchReg)); |
| 1962 } else if (instr->arch_opcode() == kMips64DaddOvf) { | 1961 } else if (instr->arch_opcode() == kMips64DaddOvf) { |
| 1963 switch (branch->condition) { | 1962 switch (condition) { |
| 1964 case kOverflow: | 1963 case kOverflow: |
| 1965 __ DaddBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1964 masm->DaddBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1966 i.InputOperand(1), tlabel, flabel); | 1965 i.InputOperand(1), tlabel, flabel); |
| 1967 break; | 1966 break; |
| 1968 case kNotOverflow: | 1967 case kNotOverflow: |
| 1969 __ DaddBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1968 masm->DaddBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1970 i.InputOperand(1), flabel, tlabel); | 1969 i.InputOperand(1), flabel, tlabel); |
| 1971 break; | 1970 break; |
| 1972 default: | 1971 default: |
| 1973 UNSUPPORTED_COND(kMips64DaddOvf, branch->condition); | 1972 UNSUPPORTED_COND(kMips64DaddOvf, condition); |
| 1974 break; | 1973 break; |
| 1975 } | 1974 } |
| 1976 } else if (instr->arch_opcode() == kMips64DsubOvf) { | 1975 } else if (instr->arch_opcode() == kMips64DsubOvf) { |
| 1977 switch (branch->condition) { | 1976 switch (condition) { |
| 1978 case kOverflow: | 1977 case kOverflow: |
| 1979 __ DsubBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1978 masm->DsubBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1980 i.InputOperand(1), tlabel, flabel); | 1979 i.InputOperand(1), tlabel, flabel); |
| 1981 break; | 1980 break; |
| 1982 case kNotOverflow: | 1981 case kNotOverflow: |
| 1983 __ DsubBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1982 masm->DsubBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1984 i.InputOperand(1), flabel, tlabel); | 1983 i.InputOperand(1), flabel, tlabel); |
| 1985 break; | 1984 break; |
| 1986 default: | 1985 default: |
| 1987 UNSUPPORTED_COND(kMips64DsubOvf, branch->condition); | 1986 UNSUPPORTED_COND(kMips64DsubOvf, condition); |
| 1988 break; | 1987 break; |
| 1989 } | 1988 } |
| 1990 } else if (instr->arch_opcode() == kMips64MulOvf) { | 1989 } else if (instr->arch_opcode() == kMips64MulOvf) { |
| 1991 switch (branch->condition) { | 1990 switch (condition) { |
| 1992 case kOverflow: { | 1991 case kOverflow: { |
| 1993 __ MulBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1992 masm->MulBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1994 i.InputOperand(1), tlabel, flabel, kScratchReg); | 1993 i.InputOperand(1), tlabel, flabel, kScratchReg); |
| 1995 } break; | 1994 } break; |
| 1996 case kNotOverflow: { | 1995 case kNotOverflow: { |
| 1997 __ MulBranchOvf(i.OutputRegister(), i.InputRegister(0), | 1996 masm->MulBranchOvf(i.OutputRegister(), i.InputRegister(0), |
| 1998 i.InputOperand(1), flabel, tlabel, kScratchReg); | 1997 i.InputOperand(1), flabel, tlabel, kScratchReg); |
| 1999 } break; | 1998 } break; |
| 2000 default: | 1999 default: |
| 2001 UNSUPPORTED_COND(kMips64MulOvf, branch->condition); | 2000 UNSUPPORTED_COND(kMips64MulOvf, condition); |
| 2002 break; | 2001 break; |
| 2003 } | 2002 } |
| 2004 } else if (instr->arch_opcode() == kMips64Cmp) { | 2003 } else if (instr->arch_opcode() == kMips64Cmp) { |
| 2005 cc = FlagsConditionToConditionCmp(branch->condition); | 2004 cc = FlagsConditionToConditionCmp(condition); |
| 2006 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); | 2005 masm->Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
| 2007 } else if (instr->arch_opcode() == kMips64CmpS) { | 2006 } else if (instr->arch_opcode() == kMips64CmpS) { |
| 2008 if (!convertCondition(branch->condition, cc)) { | 2007 if (!convertCondition(condition, cc)) { |
| 2009 UNSUPPORTED_COND(kMips64CmpS, branch->condition); | 2008 UNSUPPORTED_COND(kMips64CmpS, condition); |
| 2010 } | 2009 } |
| 2011 FPURegister left = i.InputOrZeroSingleRegister(0); | 2010 FPURegister left = i.InputOrZeroSingleRegister(0); |
| 2012 FPURegister right = i.InputOrZeroSingleRegister(1); | 2011 FPURegister right = i.InputOrZeroSingleRegister(1); |
| 2013 if ((left.is(kDoubleRegZero) || right.is(kDoubleRegZero)) && | 2012 if ((left.is(kDoubleRegZero) || right.is(kDoubleRegZero)) && |
| 2014 !__ IsDoubleZeroRegSet()) { | 2013 !masm->IsDoubleZeroRegSet()) { |
| 2015 __ Move(kDoubleRegZero, 0.0); | 2014 masm->Move(kDoubleRegZero, 0.0); |
| 2016 } | 2015 } |
| 2017 __ BranchF32(tlabel, nullptr, cc, left, right); | 2016 masm->BranchF32(tlabel, nullptr, cc, left, right); |
| 2018 } else if (instr->arch_opcode() == kMips64CmpD) { | 2017 } else if (instr->arch_opcode() == kMips64CmpD) { |
| 2019 if (!convertCondition(branch->condition, cc)) { | 2018 if (!convertCondition(condition, cc)) { |
| 2020 UNSUPPORTED_COND(kMips64CmpD, branch->condition); | 2019 UNSUPPORTED_COND(kMips64CmpD, condition); |
| 2021 } | 2020 } |
| 2022 FPURegister left = i.InputOrZeroDoubleRegister(0); | 2021 FPURegister left = i.InputOrZeroDoubleRegister(0); |
| 2023 FPURegister right = i.InputOrZeroDoubleRegister(1); | 2022 FPURegister right = i.InputOrZeroDoubleRegister(1); |
| 2024 if ((left.is(kDoubleRegZero) || right.is(kDoubleRegZero)) && | 2023 if ((left.is(kDoubleRegZero) || right.is(kDoubleRegZero)) && |
| 2025 !__ IsDoubleZeroRegSet()) { | 2024 !masm->IsDoubleZeroRegSet()) { |
| 2026 __ Move(kDoubleRegZero, 0.0); | 2025 masm->Move(kDoubleRegZero, 0.0); |
| 2027 } | 2026 } |
| 2028 __ BranchF64(tlabel, nullptr, cc, left, right); | 2027 masm->BranchF64(tlabel, nullptr, cc, left, right); |
| 2029 } else { | 2028 } else { |
| 2030 PrintF("AssembleArchBranch Unimplemented arch_opcode: %d\n", | 2029 PrintF("AssembleArchBranch Unimplemented arch_opcode: %d\n", |
| 2031 instr->arch_opcode()); | 2030 instr->arch_opcode()); |
| 2032 UNIMPLEMENTED(); | 2031 UNIMPLEMENTED(); |
| 2033 } | 2032 } |
| 2034 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. | 2033 if (!fallthru) masm->Branch(flabel); // no fallthru to flabel. |
| 2034 } | |
| 2035 | |
| 2036 // Assembles branches after an instruction. | |
| 2037 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | |
| 2038 Label* tlabel = branch->true_label; | |
| 2039 Label* flabel = branch->false_label; | |
| 2040 | |
| 2041 AssembleBranchToLabels(this, masm(), instr, branch->condition, tlabel, flabel, | |
| 2042 branch->fallthru); | |
| 2035 } | 2043 } |
| 2036 | 2044 |
| 2037 | 2045 |
| 2038 void CodeGenerator::AssembleArchJump(RpoNumber target) { | 2046 void CodeGenerator::AssembleArchJump(RpoNumber target) { |
| 2039 if (!IsNextInAssemblyOrder(target)) __ Branch(GetLabel(target)); | 2047 if (!IsNextInAssemblyOrder(target)) __ Branch(GetLabel(target)); |
| 2040 } | 2048 } |
| 2041 | 2049 |
| 2042 void CodeGenerator::AssembleArchTrap(Instruction* instr, | 2050 void CodeGenerator::AssembleArchTrap(Instruction* instr, |
| 2043 FlagsCondition condition) { | 2051 FlagsCondition condition) { |
| 2044 UNREACHABLE(); | 2052 class OutOfLineTrap final : public OutOfLineCode { |
| 2053 public: | |
| 2054 OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr) | |
| 2055 : OutOfLineCode(gen), | |
| 2056 frame_elided_(frame_elided), | |
| 2057 instr_(instr), | |
| 2058 gen_(gen) {} | |
| 2059 void Generate() final { | |
| 2060 MipsOperandConverter i(gen_, instr_); | |
| 2061 Runtime::FunctionId trap_id = static_cast<Runtime::FunctionId>( | |
| 2062 i.InputInt32(instr_->InputCount() - 1)); | |
| 2063 bool old_has_frame = __ has_frame(); | |
| 2064 if (frame_elided_) { | |
| 2065 __ set_has_frame(true); | |
| 2066 __ EnterFrame(StackFrame::WASM); | |
| 2067 } | |
| 2068 GenerateCallToTrap(trap_id); | |
| 2069 if (frame_elided_) { | |
| 2070 __ set_has_frame(old_has_frame); | |
| 2071 } | |
| 2072 if (FLAG_debug_code) { | |
| 2073 __ stop(GetBailoutReason(kUnexpectedReturnFromWasmTrap)); | |
| 2074 } | |
| 2075 } | |
| 2076 | |
| 2077 private: | |
| 2078 void GenerateCallToTrap(Runtime::FunctionId trap_id) { | |
| 2079 if (trap_id == Runtime::kNumFunctions) { | |
| 2080 // We cannot test calls to the runtime in cctest/test-run-wasm. | |
| 2081 // Therefore we emit a call to C here instead of a call to the runtime. | |
| 2082 // We use the context register as the scratch register, because we do | |
| 2083 // not have a context here. | |
| 2084 __ PrepareCallCFunction(0, 0, cp); | |
| 2085 __ CallCFunction( | |
| 2086 ExternalReference::wasm_call_trap_callback_for_testing(isolate()), | |
| 2087 0); | |
| 2088 } else { | |
| 2089 __ Move(cp, isolate()->native_context()); | |
| 2090 gen_->AssembleSourcePosition(instr_); | |
| 2091 __ CallRuntime(trap_id); | |
| 2092 } | |
| 2093 ReferenceMap* reference_map = | |
| 2094 new (gen_->zone()) ReferenceMap(gen_->zone()); | |
| 2095 gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0, | |
| 2096 Safepoint::kNoLazyDeopt); | |
| 2097 } | |
| 2098 bool frame_elided_; | |
| 2099 Instruction* instr_; | |
| 2100 CodeGenerator* gen_; | |
| 2101 }; | |
| 2102 bool frame_elided = !frame_access_state()->has_frame(); | |
| 2103 auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr); | |
| 2104 Label* tlabel = ool->entry(); | |
| 2105 AssembleBranchToLabels(this, masm(), instr, condition, tlabel, nullptr, true); | |
| 2045 } | 2106 } |
| 2046 | 2107 |
| 2047 // Assembles boolean materializations after an instruction. | 2108 // Assembles boolean materializations after an instruction. |
| 2048 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 2109 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
| 2049 FlagsCondition condition) { | 2110 FlagsCondition condition) { |
| 2050 MipsOperandConverter i(this, instr); | 2111 MipsOperandConverter i(this, instr); |
| 2051 Label done; | 2112 Label done; |
| 2052 | 2113 |
| 2053 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 2114 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
| 2054 // last output of the instruction. | 2115 // last output of the instruction. |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2585 padding_size -= v8::internal::Assembler::kInstrSize; | 2646 padding_size -= v8::internal::Assembler::kInstrSize; |
| 2586 } | 2647 } |
| 2587 } | 2648 } |
| 2588 } | 2649 } |
| 2589 | 2650 |
| 2590 #undef __ | 2651 #undef __ |
| 2591 | 2652 |
| 2592 } // namespace compiler | 2653 } // namespace compiler |
| 2593 } // namespace internal | 2654 } // namespace internal |
| 2594 } // namespace v8 | 2655 } // namespace v8 |
| OLD | NEW |