Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/src/jit/x86-shared/CodeGenerator-x86-shared.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2
 * vim: set ts=8 sts=4 et sw=4 tw=99:
3
 * This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef jit_x86_shared_CodeGenerator_x86_shared_h
8
#define jit_x86_shared_CodeGenerator_x86_shared_h
9
10
#include "jit/shared/CodeGenerator-shared.h"
11
12
namespace js {
13
namespace jit {
14
15
class CodeGeneratorX86Shared;
16
class OutOfLineBailout;
17
class OutOfLineUndoALUOperation;
18
class OutOfLineLoadTypedArrayOutOfBounds;
19
class MulNegativeZeroCheck;
20
class ModOverflowCheck;
21
class ReturnZero;
22
class OutOfLineTableSwitch;
23
24
using OutOfLineWasmTruncateCheck = OutOfLineWasmTruncateCheckBase<CodeGeneratorX86Shared>;
25
26
class CodeGeneratorX86Shared : public CodeGeneratorShared
27
{
28
    friend class MoveResolverX86;
29
30
    template <typename T>
31
    void bailout(const T& t, LSnapshot* snapshot);
32
33
  protected:
34
    CodeGeneratorX86Shared(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm);
35
36
    // Load a NaN or zero into a register for an out of bounds AsmJS or static
37
    // typed array load.
38
    class OutOfLineLoadTypedArrayOutOfBounds : public OutOfLineCodeBase<CodeGeneratorX86Shared>
39
    {
40
        AnyRegister dest_;
41
        Scalar::Type viewType_;
42
      public:
43
        OutOfLineLoadTypedArrayOutOfBounds(AnyRegister dest, Scalar::Type viewType)
44
          : dest_(dest), viewType_(viewType)
45
0
        {}
46
47
0
        AnyRegister dest() const { return dest_; }
48
0
        Scalar::Type viewType() const { return viewType_; }
49
0
        void accept(CodeGeneratorX86Shared* codegen) override {
50
0
            codegen->visitOutOfLineLoadTypedArrayOutOfBounds(this);
51
0
        }
52
    };
53
54
    NonAssertingLabel deoptLabel_;
55
56
    Operand ToOperand(const LAllocation& a);
57
    Operand ToOperand(const LAllocation* a);
58
    Operand ToOperand(const LDefinition* def);
59
60
#ifdef JS_PUNBOX64
61
    Operand ToOperandOrRegister64(const LInt64Allocation input);
62
#else
63
    Register64 ToOperandOrRegister64(const LInt64Allocation input);
64
#endif
65
66
    MoveOperand toMoveOperand(LAllocation a) const;
67
68
    void bailoutIf(Assembler::Condition condition, LSnapshot* snapshot);
69
    void bailoutIf(Assembler::DoubleCondition condition, LSnapshot* snapshot);
70
    void bailoutFrom(Label* label, LSnapshot* snapshot);
71
    void bailout(LSnapshot* snapshot);
72
73
    template <typename T1, typename T2>
74
0
    void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) {
75
0
        masm.cmpPtr(lhs, rhs);
76
0
        bailoutIf(c, snapshot);
77
0
    }
78
0
    void bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot* snapshot) {
79
0
        masm.testPtr(lhs, rhs);
80
0
        bailoutIf(c, snapshot);
81
0
    }
82
    template <typename T1, typename T2>
83
0
    void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) {
84
0
        masm.cmp32(lhs, rhs);
85
0
        bailoutIf(c, snapshot);
86
0
    }
Unexecuted instantiation: void js::jit::CodeGeneratorX86Shared::bailoutCmp32<js::jit::Register, js::jit::Imm32>(js::jit::AssemblerX86Shared::Condition, js::jit::Register, js::jit::Imm32, js::jit::LSnapshot*)
Unexecuted instantiation: void js::jit::CodeGeneratorX86Shared::bailoutCmp32<js::jit::Address, js::jit::Imm32>(js::jit::AssemblerX86Shared::Condition, js::jit::Address, js::jit::Imm32, js::jit::LSnapshot*)
Unexecuted instantiation: void js::jit::CodeGeneratorX86Shared::bailoutCmp32<js::jit::Register, js::jit::Register>(js::jit::AssemblerX86Shared::Condition, js::jit::Register, js::jit::Register, js::jit::LSnapshot*)
Unexecuted instantiation: void js::jit::CodeGeneratorX86Shared::bailoutCmp32<js::jit::Address, js::jit::Register>(js::jit::AssemblerX86Shared::Condition, js::jit::Address, js::jit::Register, js::jit::LSnapshot*)
87
    template <typename T1, typename T2>
88
0
    void bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) {
89
0
        masm.test32(lhs, rhs);
90
0
        bailoutIf(c, snapshot);
91
0
    }
92
0
    void bailoutIfFalseBool(Register reg, LSnapshot* snapshot) {
93
0
        masm.test32(reg, Imm32(0xFF));
94
0
        bailoutIf(Assembler::Zero, snapshot);
95
0
    }
96
0
    void bailoutCvttsd2si(FloatRegister src, Register dest, LSnapshot* snapshot) {
97
0
        // vcvttsd2si returns 0x80000000 on failure. Test for it by
98
0
        // subtracting 1 and testing overflow. The other possibility is to test
99
0
        // equality for INT_MIN after a comparison, but 1 costs fewer bytes to
100
0
        // materialize.
101
0
        masm.vcvttsd2si(src, dest);
102
0
        masm.cmp32(dest, Imm32(1));
103
0
        bailoutIf(Assembler::Overflow, snapshot);
104
0
    }
105
0
    void bailoutCvttss2si(FloatRegister src, Register dest, LSnapshot* snapshot) {
106
0
        // Same trick as explained in the above comment.
107
0
        masm.vcvttss2si(src, dest);
108
0
        masm.cmp32(dest, Imm32(1));
109
0
        bailoutIf(Assembler::Overflow, snapshot);
110
0
    }
111
112
    bool generateOutOfLineCode();
113
114
    void emitCompare(MCompare::CompareType type, const LAllocation* left, const LAllocation* right);
115
116
    // Emits a branch that directs control flow to the true block if |cond| is
117
    // true, and the false block if |cond| is false.
118
    void emitBranch(Assembler::Condition cond, MBasicBlock* ifTrue, MBasicBlock* ifFalse,
119
                    Assembler::NaNCond ifNaN = Assembler::NaN_HandledByCond);
120
    void emitBranch(Assembler::DoubleCondition cond, MBasicBlock* ifTrue, MBasicBlock* ifFalse);
121
122
    void testNullEmitBranch(Assembler::Condition cond, const ValueOperand& value,
123
                            MBasicBlock* ifTrue, MBasicBlock* ifFalse)
124
0
    {
125
0
        cond = masm.testNull(cond, value);
126
0
        emitBranch(cond, ifTrue, ifFalse);
127
0
    }
128
    void testUndefinedEmitBranch(Assembler::Condition cond, const ValueOperand& value,
129
                                 MBasicBlock* ifTrue, MBasicBlock* ifFalse)
130
0
    {
131
0
        cond = masm.testUndefined(cond, value);
132
0
        emitBranch(cond, ifTrue, ifFalse);
133
0
    }
134
    void testObjectEmitBranch(Assembler::Condition cond, const ValueOperand& value,
135
                                 MBasicBlock* ifTrue, MBasicBlock* ifFalse)
136
0
    {
137
0
        cond = masm.testObject(cond, value);
138
0
        emitBranch(cond, ifTrue, ifFalse);
139
0
    }
140
141
    void testZeroEmitBranch(Assembler::Condition cond, Register reg,
142
                            MBasicBlock* ifTrue, MBasicBlock* ifFalse)
143
0
    {
144
0
        MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
145
0
        masm.cmpPtr(reg, ImmWord(0));
146
0
        emitBranch(cond, ifTrue, ifFalse);
147
0
    }
148
149
    void emitTableSwitchDispatch(MTableSwitch* mir, Register index, Register base);
150
151
    void generateInvalidateEpilogue();
152
153
    void canonicalizeIfDeterministic(Scalar::Type type, const LAllocation* value);
154
155
  public:
156
    // Out of line visitors.
157
    void visitOutOfLineBailout(OutOfLineBailout* ool);
158
    void visitOutOfLineUndoALUOperation(OutOfLineUndoALUOperation* ool);
159
    void visitMulNegativeZeroCheck(MulNegativeZeroCheck* ool);
160
    void visitModOverflowCheck(ModOverflowCheck* ool);
161
    void visitReturnZero(ReturnZero* ool);
162
    void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool);
163
    void visitOutOfLineLoadTypedArrayOutOfBounds(OutOfLineLoadTypedArrayOutOfBounds* ool);
164
    void visitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateCheck* ool);
165
};
166
167
// An out-of-line bailout thunk.
168
class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorX86Shared>
169
{
170
    LSnapshot* snapshot_;
171
172
  public:
173
    explicit OutOfLineBailout(LSnapshot* snapshot)
174
      : snapshot_(snapshot)
175
201
    { }
176
177
    void accept(CodeGeneratorX86Shared* codegen) override;
178
179
201
    LSnapshot* snapshot() const {
180
201
        return snapshot_;
181
201
    }
182
};
183
184
} // namespace jit
185
} // namespace js
186
187
#endif /* jit_x86_shared_CodeGenerator_x86_shared_h */