Bug 582900: JM: Missing rsh type set. (r=dvander)
[mozilla-central.git] / js / src / methodjit / Compiler.h
blob55ec93653e9940cb9c453f23c9168bf666591997
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=99:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 * May 28, 2008.
20 * The Initial Developer of the Original Code is
21 * Brendan Eich <brendan@mozilla.org>
23 * Contributor(s):
24 * David Anderson <danderson@mozilla.com>
25 * David Mandelin <dmandelin@mozilla.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
40 #if !defined jsjaeger_compiler_h__ && defined JS_METHODJIT
41 #define jsjaeger_compiler_h__
43 #include "jscntxt.h"
44 #include "jstl.h"
45 #include "BytecodeAnalyzer.h"
46 #include "MethodJIT.h"
47 #include "CodeGenIncludes.h"
48 #include "StubCompiler.h"
49 #include "MonoIC.h"
50 #include "PolyIC.h"
52 namespace js {
53 namespace mjit {
55 class Compiler
57 typedef JSC::MacroAssembler::Label Label;
58 typedef JSC::MacroAssembler::Imm32 Imm32;
59 typedef JSC::MacroAssembler::ImmPtr ImmPtr;
60 typedef JSC::MacroAssembler::RegisterID RegisterID;
61 typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
62 typedef JSC::MacroAssembler::Address Address;
63 typedef JSC::MacroAssembler::BaseIndex BaseIndex;
64 typedef JSC::MacroAssembler::Jump Jump;
65 typedef JSC::MacroAssembler::Call Call;
66 typedef JSC::MacroAssembler::DataLabelPtr DataLabelPtr;
68 struct BranchPatch {
69 BranchPatch(const Jump &j, jsbytecode *pc)
70 : jump(j), pc(pc)
71 { }
73 Jump jump;
74 jsbytecode *pc;
77 #if defined JS_MONOIC
78 struct MICGenInfo {
79 MICGenInfo(ic::MICInfo::Kind kind) : kind(kind)
80 { }
81 Label entry;
82 Label stubEntry;
83 DataLabelPtr shapeVal;
84 Label load;
85 Call call;
86 ic::MICInfo::Kind kind;
87 jsbytecode *jumpTarget;
88 Jump traceHint;
89 union {
90 struct {
91 bool typeConst;
92 bool dataConst;
93 bool dataWrite;
94 } name;
95 struct {
96 uint32 pcOffs;
97 } tracer;
98 } u;
100 #endif
102 #if defined JS_POLYIC
103 struct PICGenInfo {
104 PICGenInfo(ic::PICInfo::Kind kind) : kind(kind)
106 ic::PICInfo::Kind kind;
107 Label hotPathBegin;
108 Label storeBack;
109 Label typeCheck;
110 Label slowPathStart;
111 RegisterID shapeReg;
112 RegisterID objReg;
113 RegisterID idReg;
114 RegisterID typeReg;
115 Label shapeGuard;
116 JSAtom *atom;
117 StateRemat objRemat;
118 StateRemat idRemat;
119 Call callReturn;
120 bool hasTypeCheck;
121 ValueRemat vr;
123 void copySimpleMembersTo(ic::PICInfo &pi) const {
124 pi.kind = kind;
125 pi.shapeReg = shapeReg;
126 pi.objReg = objReg;
127 pi.atom = atom;
128 if (kind == ic::PICInfo::SET) {
129 pi.u.vr = vr;
130 } else if (kind != ic::PICInfo::NAME) {
131 pi.u.get.idReg = idReg;
132 pi.u.get.typeReg = typeReg;
133 pi.u.get.hasTypeCheck = hasTypeCheck;
134 pi.u.get.objRemat = objRemat.offset;
139 #endif
141 struct Defs {
142 Defs(uint32 ndefs)
143 : ndefs(ndefs)
145 uint32 ndefs;
148 class MaybeJump {
149 public:
150 MaybeJump()
151 : set(false)
154 inline Jump getJump() const { JS_ASSERT(set); return jump; }
155 inline Jump get() const { JS_ASSERT(set); return jump; }
156 inline void setJump(const Jump &j) { jump = j; set = true; }
157 inline bool isSet() const { return set; }
159 inline MaybeJump &operator=(Jump j) { setJump(j); return *this; }
161 private:
162 Jump jump;
163 bool set;
166 struct InternalCallSite {
167 bool stub;
168 Label location;
169 jsbytecode *pc;
170 uint32 id;
173 struct DoublePatch {
174 double d;
175 DataLabelPtr label;
176 bool ool;
179 JSContext *cx;
180 JSScript *script;
181 JSObject *scopeChain;
182 JSObject *globalObj;
183 JSFunction *fun;
184 BytecodeAnalyzer analysis;
185 Label *jumpMap;
186 jsbytecode *PC;
187 Assembler masm;
188 FrameState frame;
189 js::Vector<BranchPatch, 64> branchPatches;
190 #if defined JS_MONOIC
191 js::Vector<MICGenInfo, 64> mics;
192 #endif
193 #if defined JS_POLYIC
194 js::Vector<PICGenInfo, 64> pics;
195 #endif
196 js::Vector<InternalCallSite, 64> callSites;
197 js::Vector<DoublePatch, 16> doubleList;
198 StubCompiler stubcc;
199 Label invokeLabel;
200 bool addTraceHints;
202 public:
203 // Special atom index used to indicate that the atom is 'length'. This
204 // follows interpreter usage in JSOP_LENGTH.
205 enum { LengthAtomIndex = uint32(-2) };
207 Compiler(JSContext *cx, JSScript *script, JSFunction *fun, JSObject *scopeChain);
208 ~Compiler();
210 CompileStatus Compile();
212 jsbytecode *getPC() { return PC; }
213 Label getLabel() { return masm.label(); }
214 bool knownJump(jsbytecode *pc);
215 Label labelOf(jsbytecode *target);
216 void *findCallSite(const CallSite &callSite);
218 private:
219 CompileStatus generatePrologue();
220 CompileStatus generateMethod();
221 CompileStatus generateEpilogue();
222 CompileStatus finishThisUp();
224 /* Non-emitting helpers. */
225 uint32 fullAtomIndex(jsbytecode *pc);
226 void jumpInScript(Jump j, jsbytecode *pc);
227 JSC::ExecutablePool *getExecPool(size_t size);
228 bool compareTwoValues(JSContext *cx, JSOp op, const Value &lhs, const Value &rhs);
229 void addCallSite(uint32 id, bool stub);
231 /* Emitting helpers. */
232 void restoreFrameRegs(Assembler &masm);
233 void emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused);
234 void iterNext();
235 void iterMore();
236 MaybeJump loadDouble(FrameEntry *fe, FPRegisterID fpReg);
238 /* Opcode handlers. */
239 void jumpAndTrace(Jump j, jsbytecode *target);
240 void jsop_bindname(uint32 index);
241 void jsop_setglobal(uint32 index);
242 void jsop_getglobal(uint32 index);
243 void jsop_getprop_slow();
244 void jsop_getarg(uint32 index);
245 void jsop_this();
246 void emitReturn();
247 void dispatchCall(VoidPtrStubUInt32 stub, uint32 argc);
248 void interruptCheckHelper();
249 void inlineCallHelper(uint32 argc, bool callingNew);
250 void jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index);
251 void jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index);
252 void jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index);
253 void jsop_eleminc(JSOp op, VoidStub);
254 void jsop_getgname(uint32 index);
255 void jsop_getgname_slow(uint32 index);
256 void jsop_setgname(uint32 index);
257 void jsop_setgname_slow(uint32 index);
258 void jsop_bindgname();
259 void jsop_setelem_slow();
260 void jsop_getelem_slow();
261 void jsop_unbrand();
262 void jsop_getprop(JSAtom *atom, bool typeCheck = true);
263 void jsop_length();
264 void jsop_setprop(JSAtom *atom);
265 void jsop_setprop_slow(JSAtom *atom);
266 bool jsop_callprop_slow(JSAtom *atom);
267 bool jsop_callprop(JSAtom *atom);
268 bool jsop_callprop_obj(JSAtom *atom);
269 bool jsop_callprop_str(JSAtom *atom);
270 bool jsop_callprop_generic(JSAtom *atom);
271 void jsop_instanceof();
272 void jsop_name(JSAtom *atom);
274 /* Fast arithmetic. */
275 void jsop_binary(JSOp op, VoidStub stub);
276 void jsop_binary_full(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub);
277 void jsop_binary_full_simple(FrameEntry *fe, JSOp op, VoidStub stub);
278 void jsop_binary_double(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub);
279 void slowLoadConstantDouble(Assembler &masm, FrameEntry *fe,
280 FPRegisterID fpreg);
281 void maybeJumpIfNotInt32(Assembler &masm, MaybeJump &mj, FrameEntry *fe,
282 MaybeRegisterID &mreg);
283 void maybeJumpIfNotDouble(Assembler &masm, MaybeJump &mj, FrameEntry *fe,
284 MaybeRegisterID &mreg);
285 void jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
286 void jsop_relational_int(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
287 void jsop_relational_self(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
288 void jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
289 void jsop_relational_double(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
291 void emitLeftDoublePath(FrameEntry *lhs, FrameEntry *rhs, FrameState::BinaryAlloc &regs,
292 MaybeJump &lhsNotDouble, MaybeJump &rhsNotNumber,
293 MaybeJump &lhsUnknownDone);
294 void emitRightDoublePath(FrameEntry *lhs, FrameEntry *rhs, FrameState::BinaryAlloc &regs,
295 MaybeJump &rhsNotNumber2);
297 /* Fast opcodes. */
298 void jsop_bitop(JSOp op);
299 void jsop_rsh();
300 RegisterID rightRegForShift(FrameEntry *rhs);
301 void jsop_rsh_int_int(FrameEntry *lhs, FrameEntry *rhs);
302 void jsop_rsh_const_int(FrameEntry *lhs, FrameEntry *rhs);
303 void jsop_rsh_int_const(FrameEntry *lhs, FrameEntry *rhs);
304 void jsop_rsh_int_unknown(FrameEntry *lhs, FrameEntry *rhs);
305 void jsop_rsh_const_const(FrameEntry *lhs, FrameEntry *rhs);
306 void jsop_rsh_const_unknown(FrameEntry *lhs, FrameEntry *rhs);
307 void jsop_rsh_unknown_const(FrameEntry *lhs, FrameEntry *rhs);
308 void jsop_rsh_unknown_any(FrameEntry *lhs, FrameEntry *rhs);
309 void jsop_globalinc(JSOp op, uint32 index);
310 void jsop_mod();
311 void jsop_neg();
312 void jsop_bitnot();
313 void jsop_objtostr();
314 void jsop_not();
315 void jsop_typeof();
316 void booleanJumpScript(JSOp op, jsbytecode *target);
317 void jsop_ifneq(JSOp op, jsbytecode *target);
318 void jsop_andor(JSOp op, jsbytecode *target);
319 void jsop_arginc(JSOp op, uint32 slot, bool popped);
320 void jsop_localinc(JSOp op, uint32 slot, bool popped);
321 void jsop_setelem();
322 void jsop_getelem();
323 void jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
324 void jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
325 void jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
326 void jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, RegisterID idReg,
327 RegisterID shapeReg);
328 void jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg,
329 MaybeRegisterID &idReg, RegisterID shapeReg);
330 void jsop_stricteq(JSOp op);
331 void jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
332 void jsop_pos();
334 #define STUB_CALL_TYPE(type) \
335 Call stubCall(type stub) { \
336 return stubCall(JS_FUNC_TO_DATA_PTR(void *, stub)); \
339 STUB_CALL_TYPE(JSObjStub);
340 STUB_CALL_TYPE(VoidStubUInt32);
341 STUB_CALL_TYPE(VoidStub);
342 STUB_CALL_TYPE(VoidPtrStubUInt32);
343 STUB_CALL_TYPE(VoidPtrStub);
344 STUB_CALL_TYPE(BoolStub);
345 STUB_CALL_TYPE(JSObjStubUInt32);
346 STUB_CALL_TYPE(JSObjStubFun);
347 STUB_CALL_TYPE(JSObjStubJSObj);
348 STUB_CALL_TYPE(VoidStubAtom);
349 STUB_CALL_TYPE(JSStrStub);
350 STUB_CALL_TYPE(JSStrStubUInt32);
351 STUB_CALL_TYPE(VoidStubJSObj);
352 STUB_CALL_TYPE(VoidPtrStubPC);
353 STUB_CALL_TYPE(VoidVpStub);
354 STUB_CALL_TYPE(VoidStubPC);
356 #undef STUB_CALL_TYPE
357 void prepareStubCall(Uses uses);
358 Call stubCall(void *ptr);
361 } /* namespace js */
362 } /* namespace mjit */
364 #endif