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
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
20 * The Initial Developer of the Original Code is
21 * Brendan Eich <brendan@mozilla.org>
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__
45 #include "BytecodeAnalyzer.h"
46 #include "MethodJIT.h"
47 #include "CodeGenIncludes.h"
48 #include "BaseCompiler.h"
49 #include "StubCompiler.h"
56 class Compiler
: public BaseCompiler
60 BranchPatch(const Jump
&j
, jsbytecode
*pc
)
70 MICGenInfo(ic::MICInfo::Kind kind
) : kind(kind
)
75 DataLabelPtr addrLabel
;
76 #if defined JS_PUNBOX64
77 uint32 patchValueOffset
;
81 ic::MICInfo::Kind kind
;
82 jsbytecode
*jumpTarget
;
84 MaybeJump slowTraceHintOne
;
85 MaybeJump slowTraceHintTwo
;
97 /* InlineFrameAssembler wants to see this. */
100 CallGenInfo(uint32 argc
)
105 * These members map to members in CallICInfo. See that structure for
110 DataLabelPtr funGuard
;
118 DataLabelPtr addrLabel1
;
119 DataLabelPtr addrLabel2
;
121 RegisterID funObjReg
;
122 RegisterID funPtrReg
;
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
{
135 DataLabelPtr fastNcodePatch
;
136 DataLabelPtr slowNcodePatch
;
140 #if defined JS_POLYIC
142 PICGenInfo(ic::PICInfo::Kind kind
) : kind(kind
)
144 ic::PICInfo::Kind kind
;
149 DataLabelPtr addrLabel
;
161 # if defined JS_CPU_X64
162 ic::PICLabels labels
;
165 void copySimpleMembersTo(ic::PICInfo
&pi
) const {
167 pi
.shapeReg
= shapeReg
;
170 if (kind
== ic::PICInfo::SET
) {
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
;
190 struct InternalCallSite
{
205 JSObject
*scopeChain
;
209 BytecodeAnalyzer analysis
;
214 js::Vector
<BranchPatch
, 64> branchPatches
;
215 #if defined JS_MONOIC
216 js::Vector
<MICGenInfo
, 64> mics
;
217 js::Vector
<CallGenInfo
, 64> callICs
;
219 #if defined JS_POLYIC
220 js::Vector
<PICGenInfo
, 16> pics
;
222 js::Vector
<CallPatchInfo
, 64> callPatches
;
223 js::Vector
<InternalCallSite
, 64> callSites
;
224 js::Vector
<DoublePatch
, 16> doubleList
;
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
);
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
);
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
);
266 MaybeJump
loadDouble(FrameEntry
*fe
, FPRegisterID fpReg
);
268 void passPICAddress(PICGenInfo
&pic
);
271 void passMICAddress(MICGenInfo
&mic
);
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
);
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();
304 void jsop_getprop(JSAtom
*atom
, bool typeCheck
= true);
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
);
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
,
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
®s
,
336 MaybeJump
&lhsNotDouble
, MaybeJump
&rhsNotNumber
,
337 MaybeJump
&lhsUnknownDone
);
338 void emitRightDoublePath(FrameEntry
*lhs
, FrameEntry
*rhs
, FrameState::BinaryAlloc
®s
,
339 MaybeJump
&rhsNotNumber2
);
340 bool tryBinaryConstantFold(JSContext
*cx
, FrameState
&frame
, JSOp op
,
341 FrameEntry
*lhs
, FrameEntry
*rhs
);
344 void jsop_bitop(JSOp op
);
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
);
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
);
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
);
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
);
410 } /* namespace mjit */