Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
7 #ifndef jit_shared_Lowering_shared_h
8 #define jit_shared_Lowering_shared_h
10 // This file declares the structures that are used for attaching LIR to a
11 // MIRGraph.
13 #include "jit/LIR.h"
15 namespace js {
16 namespace jit {
18 class MBasicBlock;
19 class MTableSwitch;
20 class MIRGenerator;
21 class MIRGraph;
22 class MDefinition;
23 class MInstruction;
24 class LOsiPoint;
26 class LIRGeneratorShared : public MInstructionVisitorWithDefaults
27 {
28 protected:
29 MIRGenerator *gen;
30 MIRGraph &graph;
31 LIRGraph &lirGraph_;
32 LBlock *current;
33 MResumePoint *lastResumePoint_;
34 LRecoverInfo *cachedRecoverInfo_;
35 LOsiPoint *osiPoint_;
37 public:
38 LIRGeneratorShared(MIRGenerator *gen, MIRGraph &graph, LIRGraph &lirGraph)
39 : gen(gen),
40 graph(graph),
41 lirGraph_(lirGraph),
42 lastResumePoint_(nullptr),
43 cachedRecoverInfo_(nullptr),
44 osiPoint_(nullptr)
45 { }
47 MIRGenerator *mir() {
48 return gen;
49 }
51 protected:
52 // A backend can decide that an instruction should be emitted at its uses,
53 // rather than at its definition. To communicate this, set the
54 // instruction's virtual register set to 0. When using the instruction,
55 // its virtual register is temporarily reassigned. To know to clear it
56 // after constructing the use information, the worklist bit is temporarily
57 // unset.
58 //
59 // The backend can use the worklist bit to determine whether or not a
60 // definition should be created.
61 inline bool emitAtUses(MInstruction *mir);
63 // The lowest-level calls to use, those that do not wrap another call to
64 // use(), must prefix grabbing virtual register IDs by these calls.
65 inline bool ensureDefined(MDefinition *mir);
67 // These all create a use of a virtual register, with an optional
68 // allocation policy.
69 inline LUse use(MDefinition *mir, LUse policy);
70 inline LUse use(MDefinition *mir);
71 inline LUse useAtStart(MDefinition *mir);
72 inline LUse useRegister(MDefinition *mir);
73 inline LUse useRegisterAtStart(MDefinition *mir);
74 inline LUse useFixed(MDefinition *mir, Register reg);
75 inline LUse useFixed(MDefinition *mir, FloatRegister reg);
76 inline LUse useFixed(MDefinition *mir, AnyRegister reg);
77 inline LUse useFixedAtStart(MDefinition *mir, Register reg);
78 inline LAllocation useOrConstant(MDefinition *mir);
79 // "Any" is architecture dependent, and will include registers and stack slots on X86,
80 // and only registers on ARM.
81 inline LAllocation useAny(MDefinition *mir);
82 inline LAllocation useAnyOrConstant(MDefinition *mir);
83 // "Storable" is architecture dependend, and will include registers and constants on X86
84 // and only registers on ARM.
85 // this is a generic "things we can expect to write into memory in 1 instruction"
86 inline LAllocation useStorable(MDefinition *mir);
87 inline LAllocation useStorableAtStart(MDefinition *mir);
88 inline LAllocation useKeepaliveOrConstant(MDefinition *mir);
89 inline LAllocation useRegisterOrConstant(MDefinition *mir);
90 inline LAllocation useRegisterOrConstantAtStart(MDefinition *mir);
91 inline LAllocation useRegisterOrNonNegativeConstantAtStart(MDefinition *mir);
92 inline LAllocation useRegisterOrNonDoubleConstant(MDefinition *mir);
94 #ifdef JS_NUNBOX32
95 inline LUse useType(MDefinition *mir, LUse::Policy policy);
96 inline LUse usePayload(MDefinition *mir, LUse::Policy policy);
97 inline LUse usePayloadAtStart(MDefinition *mir, LUse::Policy policy);
98 inline LUse usePayloadInRegisterAtStart(MDefinition *mir);
100 // Adds a box input to an instruction, setting operand |n| to the type and
101 // |n+1| to the payload. Does not modify the operands, instead expecting a
102 // policy to already be set.
103 inline bool fillBoxUses(LInstruction *lir, size_t n, MDefinition *mir);
104 #endif
106 // These create temporary register requests.
107 inline LDefinition temp(LDefinition::Type type = LDefinition::GENERAL,
108 LDefinition::Policy policy = LDefinition::DEFAULT);
109 inline LDefinition tempFloat32();
110 inline LDefinition tempDouble();
111 inline LDefinition tempCopy(MDefinition *input, uint32_t reusedInput);
113 // Note that the fixed register has a GENERAL type.
114 inline LDefinition tempFixed(Register reg);
116 template <size_t Ops, size_t Temps>
117 inline bool defineFixed(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir,
118 const LAllocation &output);
120 template <size_t Ops, size_t Temps>
121 inline bool defineBox(LInstructionHelper<BOX_PIECES, Ops, Temps> *lir, MDefinition *mir,
122 LDefinition::Policy policy = LDefinition::DEFAULT);
124 inline bool defineReturn(LInstruction *lir, MDefinition *mir);
126 template <size_t Ops, size_t Temps>
127 inline bool define(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir,
128 const LDefinition &def);
130 template <size_t Ops, size_t Temps>
131 inline bool define(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir,
132 LDefinition::Policy policy = LDefinition::DEFAULT);
134 template <size_t Ops, size_t Temps>
135 inline bool defineReuseInput(LInstructionHelper<1, Ops, Temps> *lir, MDefinition *mir, uint32_t operand);
137 // Rather than defining a new virtual register, sets |ins| to have the same
138 // virtual register as |as|.
139 inline bool redefine(MDefinition *ins, MDefinition *as);
141 // Defines an IR's output as the same as another IR. This is similar to
142 // redefine(), but used when creating new LIR.
143 inline bool defineAs(LInstruction *outLir, MDefinition *outMir, MDefinition *inMir);
145 TempAllocator &alloc() const {
146 return graph.alloc();
147 }
149 uint32_t getVirtualRegister() {
150 return lirGraph_.getVirtualRegister();
151 }
153 template <typename T> void annotate(T *ins);
154 template <typename T> bool add(T *ins, MInstruction *mir = nullptr);
156 void lowerTypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex);
157 bool defineTypedPhi(MPhi *phi, size_t lirIndex);
159 LOsiPoint *popOsiPoint() {
160 LOsiPoint *tmp = osiPoint_;
161 osiPoint_ = nullptr;
162 return tmp;
163 }
165 LRecoverInfo *getRecoverInfo(MResumePoint *rp);
166 LSnapshot *buildSnapshot(LInstruction *ins, MResumePoint *rp, BailoutKind kind);
167 bool assignPostSnapshot(MInstruction *mir, LInstruction *ins);
169 // Marks this instruction as fallible, meaning that before it performs
170 // effects (if any), it may check pre-conditions and bailout if they do not
171 // hold. This function informs the register allocator that it will need to
172 // capture appropriate state.
173 bool assignSnapshot(LInstruction *ins, BailoutKind kind = Bailout_Normal);
175 // Marks this instruction as needing to call into either the VM or GC. This
176 // function may build a snapshot that captures the result of its own
177 // instruction, and as such, should generally be called after define*().
178 bool assignSafepoint(LInstruction *ins, MInstruction *mir);
180 public:
181 bool visitConstant(MConstant *ins);
183 // Whether to generate typed reads for element accesses with hole checks.
184 static bool allowTypedElementHoleCheck() {
185 return false;
186 }
188 // Whether to generate typed array accesses on statically known objects.
189 static bool allowStaticTypedArrayAccesses() {
190 return false;
191 }
193 // Whether we can emit Float32 specific optimizations.
194 static bool allowFloat32Optimizations() {
195 return false;
196 }
198 // Whether we can inline ForkJoinGetSlice.
199 static bool allowInlineForkJoinGetSlice() {
200 return false;
201 }
202 };
204 } // namespace jit
205 } // namespace js
207 #endif /* jit_shared_Lowering_shared_h */