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__
43 #include "jsanalyze.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 slowTraceHint
;
96 struct EqualityGenInfo
{
97 DataLabelPtr addrLabel
;
101 MaybeJump jumpToStub
;
103 jsbytecode
*jumpTarget
;
105 Assembler::Condition cond
;
106 JSC::MacroAssembler::RegisterID tempReg
;
109 struct TraceGenInfo
{
112 DataLabelPtr addrLabel
;
113 jsbytecode
*jumpTarget
;
115 MaybeJump slowTraceHint
;
117 TraceGenInfo() : initialized(false) {}
120 /* InlineFrameAssembler wants to see this. */
123 CallGenInfo(uint32 argc
)
128 * These members map to members in CallICInfo. See that structure for
133 DataLabelPtr funGuard
;
141 DataLabelPtr addrLabel1
;
142 DataLabelPtr addrLabel2
;
144 RegisterID funObjReg
;
145 RegisterID funPtrReg
;
153 * Writes of call return addresses which needs to be delayed until the final
154 * absolute address of the join point is known.
156 struct CallPatchInfo
{
158 DataLabelPtr fastNcodePatch
;
159 DataLabelPtr slowNcodePatch
;
164 BaseICInfo(JSOp op
) : op(op
)
167 Label fastPathRejoin
;
170 DataLabelPtr paramAddr
;
173 void copyTo(ic::BaseIC
&to
, JSC::LinkBuffer
&full
, JSC::LinkBuffer
&stub
) {
174 to
.fastPathStart
= full
.locationOf(fastPathStart
);
175 to
.fastPathRejoin
= full
.locationOf(fastPathRejoin
);
176 to
.slowPathStart
= stub
.locationOf(slowPathStart
);
177 to
.slowPathCall
= stub
.locationOf(slowPathCall
);
179 JS_ASSERT(to
.op
== op
);
183 struct GetElementICInfo
: public BaseICInfo
{
184 GetElementICInfo(JSOp op
) : BaseICInfo(op
)
193 struct PICGenInfo
: public BaseICInfo
{
194 PICGenInfo(ic::PICInfo::Kind kind
, JSOp op
, bool usePropCache
)
195 : BaseICInfo(op
), kind(kind
), usePropCache(usePropCache
)
197 ic::PICInfo::Kind kind
;
209 # if defined JS_CPU_X64
210 ic::PICLabels labels
;
213 void copySimpleMembersTo(ic::PICInfo
&ic
) const {
215 ic
.shapeReg
= shapeReg
;
218 ic
.usePropCache
= usePropCache
;
221 } else if (ic
.isGet()) {
222 ic
.u
.get
.typeReg
= typeReg
;
223 ic
.u
.get
.hasTypeCheck
= hasTypeCheck
;
236 struct InternalCallSite
{
251 JSObject
*scopeChain
;
255 analyze::Script
*analysis
;
260 js::Vector
<BranchPatch
, 64> branchPatches
;
261 #if defined JS_MONOIC
262 js::Vector
<MICGenInfo
, 64> mics
;
263 js::Vector
<CallGenInfo
, 64> callICs
;
264 js::Vector
<EqualityGenInfo
, 64> equalityICs
;
265 js::Vector
<TraceGenInfo
, 64> traceICs
;
267 #if defined JS_POLYIC
268 js::Vector
<PICGenInfo
, 16> pics
;
269 js::Vector
<GetElementICInfo
> getElemICs
;
271 js::Vector
<CallPatchInfo
, 64> callPatches
;
272 js::Vector
<InternalCallSite
, 64> callSites
;
273 js::Vector
<DoublePatch
, 16> doubleList
;
281 // Special atom index used to indicate that the atom is 'length'. This
282 // follows interpreter usage in JSOP_LENGTH.
283 enum { LengthAtomIndex
= uint32(-2) };
285 Compiler(JSContext
*cx
, JSStackFrame
*fp
);
288 CompileStatus
compile();
290 jsbytecode
*getPC() { return PC
; }
291 Label
getLabel() { return masm
.label(); }
292 bool knownJump(jsbytecode
*pc
);
293 Label
labelOf(jsbytecode
*target
);
294 void *findCallSite(const CallSite
&callSite
);
297 CompileStatus
performCompilation(JITScript
**jitp
);
298 CompileStatus
generatePrologue();
299 CompileStatus
generateMethod();
300 CompileStatus
generateEpilogue();
301 CompileStatus
finishThisUp(JITScript
**jitp
);
303 /* Non-emitting helpers. */
304 uint32
fullAtomIndex(jsbytecode
*pc
);
305 void jumpInScript(Jump j
, jsbytecode
*pc
);
306 bool compareTwoValues(JSContext
*cx
, JSOp op
, const Value
&lhs
, const Value
&rhs
);
307 void addCallSite(uint32 id
, bool stub
);
309 /* Emitting helpers. */
310 void restoreFrameRegs(Assembler
&masm
);
311 void emitStubCmpOp(BoolStub stub
, jsbytecode
*target
, JSOp fused
);
312 void iter(uintN flags
);
316 MaybeJump
loadDouble(FrameEntry
*fe
, FPRegisterID fpReg
);
318 void passICAddress(BaseICInfo
*ic
);
321 void passMICAddress(MICGenInfo
&mic
);
323 bool constructThis();
325 /* Opcode handlers. */
326 void jumpAndTrace(Jump j
, jsbytecode
*target
, Jump
*slow
= NULL
);
327 void jsop_bindname(uint32 index
, bool usePropCache
);
328 void jsop_setglobal(uint32 index
);
329 void jsop_getglobal(uint32 index
);
330 void jsop_getprop_slow(JSAtom
*atom
, bool usePropCache
= true);
331 void jsop_getarg(uint32 slot
);
332 void jsop_setarg(uint32 slot
, bool popped
);
334 void emitReturn(FrameEntry
*fe
);
335 void emitFinalReturn(Assembler
&masm
);
336 void loadReturnValue(Assembler
*masm
, FrameEntry
*fe
);
337 void emitReturnValue(Assembler
*masm
, FrameEntry
*fe
);
338 void dispatchCall(VoidPtrStubUInt32 stub
, uint32 argc
);
339 void interruptCheckHelper();
340 void emitUncachedCall(uint32 argc
, bool callingNew
);
341 void inlineCallHelper(uint32 argc
, bool callingNew
);
342 void fixPrimitiveReturn(Assembler
*masm
, FrameEntry
*fe
);
343 void jsop_gnameinc(JSOp op
, VoidStubAtom stub
, uint32 index
);
344 bool jsop_nameinc(JSOp op
, VoidStubAtom stub
, uint32 index
);
345 bool jsop_propinc(JSOp op
, VoidStubAtom stub
, uint32 index
);
346 void jsop_eleminc(JSOp op
, VoidStub
);
347 void jsop_getgname(uint32 index
);
348 void jsop_getgname_slow(uint32 index
);
349 void jsop_setgname(uint32 index
);
350 void jsop_setgname_slow(uint32 index
);
351 void jsop_bindgname();
352 void jsop_setelem_slow();
353 void jsop_getelem_slow();
355 bool jsop_getprop(JSAtom
*atom
, bool typeCheck
= true, bool usePropCache
= true);
357 bool jsop_setprop(JSAtom
*atom
, bool usePropCache
= true);
358 void jsop_setprop_slow(JSAtom
*atom
, bool usePropCache
= true);
359 bool jsop_callprop_slow(JSAtom
*atom
);
360 bool jsop_callprop(JSAtom
*atom
);
361 bool jsop_callprop_obj(JSAtom
*atom
);
362 bool jsop_callprop_str(JSAtom
*atom
);
363 bool jsop_callprop_generic(JSAtom
*atom
);
364 bool jsop_instanceof();
365 void jsop_name(JSAtom
*atom
);
366 bool jsop_xname(JSAtom
*atom
);
367 void enterBlock(JSObject
*obj
);
371 /* Fast arithmetic. */
372 void jsop_binary(JSOp op
, VoidStub stub
);
373 void jsop_binary_full(FrameEntry
*lhs
, FrameEntry
*rhs
, JSOp op
, VoidStub stub
);
374 void jsop_binary_full_simple(FrameEntry
*fe
, JSOp op
, VoidStub stub
);
375 void jsop_binary_double(FrameEntry
*lhs
, FrameEntry
*rhs
, JSOp op
, VoidStub stub
);
376 void slowLoadConstantDouble(Assembler
&masm
, FrameEntry
*fe
,
378 void maybeJumpIfNotInt32(Assembler
&masm
, MaybeJump
&mj
, FrameEntry
*fe
,
379 MaybeRegisterID
&mreg
);
380 void maybeJumpIfNotDouble(Assembler
&masm
, MaybeJump
&mj
, FrameEntry
*fe
,
381 MaybeRegisterID
&mreg
);
382 void jsop_relational(JSOp op
, BoolStub stub
, jsbytecode
*target
, JSOp fused
);
383 void jsop_relational_self(JSOp op
, BoolStub stub
, jsbytecode
*target
, JSOp fused
);
384 void jsop_relational_full(JSOp op
, BoolStub stub
, jsbytecode
*target
, JSOp fused
);
385 void jsop_relational_double(JSOp op
, BoolStub stub
, jsbytecode
*target
, JSOp fused
);
387 void emitLeftDoublePath(FrameEntry
*lhs
, FrameEntry
*rhs
, FrameState::BinaryAlloc
®s
,
388 MaybeJump
&lhsNotDouble
, MaybeJump
&rhsNotNumber
,
389 MaybeJump
&lhsUnknownDone
);
390 void emitRightDoublePath(FrameEntry
*lhs
, FrameEntry
*rhs
, FrameState::BinaryAlloc
®s
,
391 MaybeJump
&rhsNotNumber2
);
392 bool tryBinaryConstantFold(JSContext
*cx
, FrameState
&frame
, JSOp op
,
393 FrameEntry
*lhs
, FrameEntry
*rhs
);
396 void jsop_bitop(JSOp op
);
398 RegisterID
rightRegForShift(FrameEntry
*rhs
);
399 void jsop_rsh_int_int(FrameEntry
*lhs
, FrameEntry
*rhs
);
400 void jsop_rsh_const_int(FrameEntry
*lhs
, FrameEntry
*rhs
);
401 void jsop_rsh_int_const(FrameEntry
*lhs
, FrameEntry
*rhs
);
402 void jsop_rsh_int_unknown(FrameEntry
*lhs
, FrameEntry
*rhs
);
403 void jsop_rsh_const_const(FrameEntry
*lhs
, FrameEntry
*rhs
);
404 void jsop_rsh_const_unknown(FrameEntry
*lhs
, FrameEntry
*rhs
);
405 void jsop_rsh_unknown_const(FrameEntry
*lhs
, FrameEntry
*rhs
);
406 void jsop_rsh_unknown_any(FrameEntry
*lhs
, FrameEntry
*rhs
);
407 void jsop_globalinc(JSOp op
, uint32 index
);
413 void booleanJumpScript(JSOp op
, jsbytecode
*target
);
414 void jsop_ifneq(JSOp op
, jsbytecode
*target
);
415 void jsop_andor(JSOp op
, jsbytecode
*target
);
416 void jsop_arginc(JSOp op
, uint32 slot
, bool popped
);
417 void jsop_localinc(JSOp op
, uint32 slot
, bool popped
);
420 void jsop_stricteq(JSOp op
);
421 void jsop_equality(JSOp op
, BoolStub stub
, jsbytecode
*target
, JSOp fused
);
422 void jsop_equality_int_string(JSOp op
, BoolStub stub
, jsbytecode
*target
, JSOp fused
);
425 #define STUB_CALL_TYPE(type) \
426 Call stubCall(type stub) { \
427 return stubCall(JS_FUNC_TO_DATA_PTR(void *, stub)); \
430 STUB_CALL_TYPE(JSObjStub
);
431 STUB_CALL_TYPE(VoidStubUInt32
);
432 STUB_CALL_TYPE(VoidStub
);
433 STUB_CALL_TYPE(VoidPtrStubUInt32
);
434 STUB_CALL_TYPE(VoidPtrStub
);
435 STUB_CALL_TYPE(BoolStub
);
436 STUB_CALL_TYPE(JSObjStubUInt32
);
437 STUB_CALL_TYPE(JSObjStubFun
);
438 STUB_CALL_TYPE(JSObjStubJSObj
);
439 STUB_CALL_TYPE(VoidStubAtom
);
440 STUB_CALL_TYPE(JSStrStub
);
441 STUB_CALL_TYPE(JSStrStubUInt32
);
442 STUB_CALL_TYPE(VoidStubJSObj
);
443 STUB_CALL_TYPE(VoidPtrStubPC
);
444 STUB_CALL_TYPE(VoidVpStub
);
445 STUB_CALL_TYPE(VoidStubPC
);
446 STUB_CALL_TYPE(BoolStubUInt32
);
447 STUB_CALL_TYPE(VoidStubFun
);
449 #undef STUB_CALL_TYPE
450 void prepareStubCall(Uses uses
);
451 Call
stubCall(void *ptr
);
455 } /* namespace mjit */