ICs for scripted new (bug 589398, r=luke,dmandelin).
[mozilla-central.git] / js / src / methodjit / Compiler.h
blob5b8d5ecd3bff5f521738ecbda8817cf73bf3b413
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 "BaseCompiler.h"
49 #include "StubCompiler.h"
50 #include "MonoIC.h"
51 #include "PolyIC.h"
53 namespace js {
54 namespace mjit {
56 class Compiler : public BaseCompiler
59 struct BranchPatch {
60 BranchPatch(const Jump &j, jsbytecode *pc)
61 : jump(j), pc(pc)
62 { }
64 Jump jump;
65 jsbytecode *pc;
68 #if defined JS_MONOIC
69 struct MICGenInfo {
70 MICGenInfo(ic::MICInfo::Kind kind) : kind(kind)
71 { }
72 Label entry;
73 Label stubEntry;
74 DataLabel32 shape;
75 DataLabelPtr addrLabel;
76 #if defined JS_PUNBOX64
77 uint32 patchValueOffset;
78 #endif
79 Label load;
80 Call call;
81 ic::MICInfo::Kind kind;
82 jsbytecode *jumpTarget;
83 Jump traceHint;
84 MaybeJump slowTraceHintOne;
85 MaybeJump slowTraceHintTwo;
86 union {
87 struct {
88 bool typeConst;
89 bool dataConst;
90 } name;
91 struct {
92 uint32 pcOffs;
93 } tracer;
94 } u;
97 /* InlineFrameAssembler wants to see this. */
98 public:
99 struct CallGenInfo {
100 CallGenInfo(uint32 argc)
101 : argc(argc)
105 * These members map to members in CallICInfo. See that structure for
106 * more comments.
108 jsbytecode *pc;
109 uint32 argc;
110 DataLabelPtr funGuard;
111 Jump funJump;
112 Jump hotJump;
113 Call oolCall;
114 Label joinPoint;
115 Label slowJoinPoint;
116 Label slowPathStart;
117 Label hotPathLabel;
118 DataLabelPtr addrLabel1;
119 DataLabelPtr addrLabel2;
120 Jump oolJump;
121 RegisterID funObjReg;
122 RegisterID funPtrReg;
123 uint32 frameDepth;
126 private:
127 #endif
130 * Writes of call return addresses which needs to be delayed until the final
131 * absolute address of the join point is known.
133 struct CallPatchInfo {
134 Label joinPoint;
135 DataLabelPtr fastNcodePatch;
136 DataLabelPtr slowNcodePatch;
137 bool hasSlowNcode;
140 #if defined JS_POLYIC
141 struct PICGenInfo {
142 PICGenInfo(ic::PICInfo::Kind kind) : kind(kind)
144 ic::PICInfo::Kind kind;
145 Label fastPathStart;
146 Label storeBack;
147 Label typeCheck;
148 Label slowPathStart;
149 DataLabelPtr addrLabel;
150 RegisterID shapeReg;
151 RegisterID objReg;
152 RegisterID idReg;
153 RegisterID typeReg;
154 Label shapeGuard;
155 JSAtom *atom;
156 StateRemat objRemat;
157 StateRemat idRemat;
158 Call callReturn;
159 bool hasTypeCheck;
160 ValueRemat vr;
161 # if defined JS_CPU_X64
162 ic::PICLabels labels;
163 # endif
165 void copySimpleMembersTo(ic::PICInfo &pi) const {
166 pi.kind = kind;
167 pi.shapeReg = shapeReg;
168 pi.objReg = objReg;
169 pi.atom = atom;
170 if (kind == ic::PICInfo::SET) {
171 pi.u.vr = vr;
172 } else if (kind != ic::PICInfo::NAME) {
173 pi.u.get.idReg = idReg;
174 pi.u.get.typeReg = typeReg;
175 pi.u.get.hasTypeCheck = hasTypeCheck;
176 pi.u.get.objRemat = objRemat.offset;
181 #endif
183 struct Defs {
184 Defs(uint32 ndefs)
185 : ndefs(ndefs)
187 uint32 ndefs;
190 struct InternalCallSite {
191 bool stub;
192 Label location;
193 jsbytecode *pc;
194 uint32 id;
197 struct DoublePatch {
198 double d;
199 DataLabelPtr label;
200 bool ool;
203 JSStackFrame *fp;
204 JSScript *script;
205 JSObject *scopeChain;
206 JSObject *globalObj;
207 JSFunction *fun;
208 bool isConstructing;
209 BytecodeAnalyzer analysis;
210 Label *jumpMap;
211 jsbytecode *PC;
212 Assembler masm;
213 FrameState frame;
214 js::Vector<BranchPatch, 64> branchPatches;
215 #if defined JS_MONOIC
216 js::Vector<MICGenInfo, 64> mics;
217 js::Vector<CallGenInfo, 64> callICs;
218 #endif
219 #if defined JS_POLYIC
220 js::Vector<PICGenInfo, 16> pics;
221 #endif
222 js::Vector<CallPatchInfo, 64> callPatches;
223 js::Vector<InternalCallSite, 64> callSites;
224 js::Vector<DoublePatch, 16> doubleList;
225 StubCompiler stubcc;
226 Label invokeLabel;
227 Label arityLabel;
228 bool addTraceHints;
230 public:
231 // Special atom index used to indicate that the atom is 'length'. This
232 // follows interpreter usage in JSOP_LENGTH.
233 enum { LengthAtomIndex = uint32(-2) };
235 Compiler(JSContext *cx, JSStackFrame *fp);
236 ~Compiler();
238 CompileStatus compile();
240 jsbytecode *getPC() { return PC; }
241 Label getLabel() { return masm.label(); }
242 bool knownJump(jsbytecode *pc);
243 Label labelOf(jsbytecode *target);
244 void *findCallSite(const CallSite &callSite);
246 private:
247 CompileStatus performCompilation(JITScript **jitp);
248 CompileStatus generatePrologue();
249 CompileStatus generateMethod();
250 CompileStatus generateEpilogue();
251 CompileStatus finishThisUp(JITScript **jitp);
253 /* Non-emitting helpers. */
254 uint32 fullAtomIndex(jsbytecode *pc);
255 void jumpInScript(Jump j, jsbytecode *pc);
256 bool compareTwoValues(JSContext *cx, JSOp op, const Value &lhs, const Value &rhs);
257 void addCallSite(uint32 id, bool stub);
259 /* Emitting helpers. */
260 void restoreFrameRegs(Assembler &masm);
261 void emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused);
262 void iter(uintN flags);
263 void iterNext();
264 void iterMore();
265 void iterEnd();
266 MaybeJump loadDouble(FrameEntry *fe, FPRegisterID fpReg);
267 #ifdef JS_POLYIC
268 void passPICAddress(PICGenInfo &pic);
269 #endif
270 #ifdef JS_MONOIC
271 void passMICAddress(MICGenInfo &mic);
272 #endif
273 void constructThis();
275 /* Opcode handlers. */
276 void jumpAndTrace(Jump j, jsbytecode *target, Jump *slowOne = NULL, Jump *slowTwo = NULL);
277 void jsop_bindname(uint32 index);
278 void jsop_setglobal(uint32 index);
279 void jsop_getglobal(uint32 index);
280 void jsop_getprop_slow();
281 void jsop_getarg(uint32 index);
282 void jsop_this();
283 void emitReturn(FrameEntry *fe);
284 void emitFinalReturn(Assembler &masm);
285 void loadReturnValue(Assembler *masm, FrameEntry *fe);
286 void emitReturnValue(Assembler *masm, FrameEntry *fe);
287 void dispatchCall(VoidPtrStubUInt32 stub, uint32 argc);
288 void interruptCheckHelper();
289 void emitUncachedCall(uint32 argc, bool callingNew);
290 void inlineCallHelper(uint32 argc, bool callingNew);
291 void fixPrimitiveReturn(Assembler *masm, FrameEntry *fe);
292 void jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index);
293 void jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index);
294 void jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index);
295 void jsop_eleminc(JSOp op, VoidStub);
296 void jsop_getgname(uint32 index);
297 void jsop_getgname_slow(uint32 index);
298 void jsop_setgname(uint32 index);
299 void jsop_setgname_slow(uint32 index);
300 void jsop_bindgname();
301 void jsop_setelem_slow();
302 void jsop_getelem_slow();
303 void jsop_unbrand();
304 void jsop_getprop(JSAtom *atom, bool typeCheck = true);
305 void jsop_length();
306 void jsop_setprop(JSAtom *atom);
307 void jsop_setprop_slow(JSAtom *atom);
308 bool jsop_callprop_slow(JSAtom *atom);
309 bool jsop_callprop(JSAtom *atom);
310 bool jsop_callprop_obj(JSAtom *atom);
311 bool jsop_callprop_str(JSAtom *atom);
312 bool jsop_callprop_generic(JSAtom *atom);
313 void jsop_instanceof();
314 void jsop_name(JSAtom *atom);
315 void jsop_xname(JSAtom *atom);
316 void enterBlock(JSObject *obj);
317 void leaveBlock();
319 /* Fast arithmetic. */
320 void jsop_binary(JSOp op, VoidStub stub);
321 void jsop_binary_full(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub);
322 void jsop_binary_full_simple(FrameEntry *fe, JSOp op, VoidStub stub);
323 void jsop_binary_double(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub);
324 void slowLoadConstantDouble(Assembler &masm, FrameEntry *fe,
325 FPRegisterID fpreg);
326 void maybeJumpIfNotInt32(Assembler &masm, MaybeJump &mj, FrameEntry *fe,
327 MaybeRegisterID &mreg);
328 void maybeJumpIfNotDouble(Assembler &masm, MaybeJump &mj, FrameEntry *fe,
329 MaybeRegisterID &mreg);
330 void jsop_relational(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
331 void jsop_relational_self(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
332 void jsop_relational_full(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
333 void jsop_relational_double(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
335 void emitLeftDoublePath(FrameEntry *lhs, FrameEntry *rhs, FrameState::BinaryAlloc &regs,
336 MaybeJump &lhsNotDouble, MaybeJump &rhsNotNumber,
337 MaybeJump &lhsUnknownDone);
338 void emitRightDoublePath(FrameEntry *lhs, FrameEntry *rhs, FrameState::BinaryAlloc &regs,
339 MaybeJump &rhsNotNumber2);
340 bool tryBinaryConstantFold(JSContext *cx, FrameState &frame, JSOp op,
341 FrameEntry *lhs, FrameEntry *rhs);
343 /* Fast opcodes. */
344 void jsop_bitop(JSOp op);
345 void jsop_rsh();
346 RegisterID rightRegForShift(FrameEntry *rhs);
347 void jsop_rsh_int_int(FrameEntry *lhs, FrameEntry *rhs);
348 void jsop_rsh_const_int(FrameEntry *lhs, FrameEntry *rhs);
349 void jsop_rsh_int_const(FrameEntry *lhs, FrameEntry *rhs);
350 void jsop_rsh_int_unknown(FrameEntry *lhs, FrameEntry *rhs);
351 void jsop_rsh_const_const(FrameEntry *lhs, FrameEntry *rhs);
352 void jsop_rsh_const_unknown(FrameEntry *lhs, FrameEntry *rhs);
353 void jsop_rsh_unknown_const(FrameEntry *lhs, FrameEntry *rhs);
354 void jsop_rsh_unknown_any(FrameEntry *lhs, FrameEntry *rhs);
355 void jsop_globalinc(JSOp op, uint32 index);
356 void jsop_mod();
357 void jsop_neg();
358 void jsop_bitnot();
359 void jsop_not();
360 void jsop_typeof();
361 void booleanJumpScript(JSOp op, jsbytecode *target);
362 void jsop_ifneq(JSOp op, jsbytecode *target);
363 void jsop_andor(JSOp op, jsbytecode *target);
364 void jsop_arginc(JSOp op, uint32 slot, bool popped);
365 void jsop_localinc(JSOp op, uint32 slot, bool popped);
366 void jsop_setelem();
367 void jsop_getelem();
368 void jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
369 void jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
370 void jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
371 void jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, RegisterID idReg,
372 RegisterID shapeReg);
373 void jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg,
374 MaybeRegisterID &idReg, RegisterID shapeReg);
375 void jsop_stricteq(JSOp op);
376 void jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
377 void jsop_equality_int_string(JSOp op, BoolStub stub, jsbytecode *target, JSOp fused);
378 void jsop_pos();
380 #define STUB_CALL_TYPE(type) \
381 Call stubCall(type stub) { \
382 return stubCall(JS_FUNC_TO_DATA_PTR(void *, stub)); \
385 STUB_CALL_TYPE(JSObjStub);
386 STUB_CALL_TYPE(VoidStubUInt32);
387 STUB_CALL_TYPE(VoidStub);
388 STUB_CALL_TYPE(VoidPtrStubUInt32);
389 STUB_CALL_TYPE(VoidPtrStub);
390 STUB_CALL_TYPE(BoolStub);
391 STUB_CALL_TYPE(JSObjStubUInt32);
392 STUB_CALL_TYPE(JSObjStubFun);
393 STUB_CALL_TYPE(JSObjStubJSObj);
394 STUB_CALL_TYPE(VoidStubAtom);
395 STUB_CALL_TYPE(JSStrStub);
396 STUB_CALL_TYPE(JSStrStubUInt32);
397 STUB_CALL_TYPE(VoidStubJSObj);
398 STUB_CALL_TYPE(VoidPtrStubPC);
399 STUB_CALL_TYPE(VoidVpStub);
400 STUB_CALL_TYPE(VoidStubPC);
401 STUB_CALL_TYPE(BoolStubUInt32);
402 STUB_CALL_TYPE(VoidStubFun);
404 #undef STUB_CALL_TYPE
405 void prepareStubCall(Uses uses);
406 Call stubCall(void *ptr);
409 } /* namespace js */
410 } /* namespace mjit */
412 #endif