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_compilerbase_h__ && defined JS_METHODJIT
41 #define jsjaeger_compilerbase_h__
45 #include "assembler/assembler/MacroAssembler.h"
46 #include "assembler/assembler/LinkBuffer.h"
47 #include "assembler/assembler/RepatchBuffer.h"
48 #include "assembler/jit/ExecutableAllocator.h"
51 #if defined JS_CPU_ARM
52 # define POST_INST_OFFSET(__expr) ((__expr) - sizeof(ARMWord))
54 # define POST_INST_OFFSET(__expr) (__expr)
60 struct MacroAssemblerTypedefs
{
61 typedef JSC::MacroAssembler::Label Label
;
62 typedef JSC::MacroAssembler::Imm32 Imm32
;
63 typedef JSC::MacroAssembler::ImmPtr ImmPtr
;
64 typedef JSC::MacroAssembler::RegisterID RegisterID
;
65 typedef JSC::MacroAssembler::FPRegisterID FPRegisterID
;
66 typedef JSC::MacroAssembler::Address Address
;
67 typedef JSC::MacroAssembler::BaseIndex BaseIndex
;
68 typedef JSC::MacroAssembler::AbsoluteAddress AbsoluteAddress
;
69 typedef JSC::MacroAssembler MacroAssembler
;
70 typedef JSC::MacroAssembler::Jump Jump
;
71 typedef JSC::MacroAssembler::JumpList JumpList
;
72 typedef JSC::MacroAssembler::Call Call
;
73 typedef JSC::MacroAssembler::DataLabelPtr DataLabelPtr
;
74 typedef JSC::MacroAssembler::DataLabel32 DataLabel32
;
75 typedef JSC::FunctionPtr FunctionPtr
;
76 typedef JSC::RepatchBuffer RepatchBuffer
;
77 typedef JSC::CodeLocationLabel CodeLocationLabel
;
78 typedef JSC::CodeLocationDataLabel32 CodeLocationDataLabel32
;
79 typedef JSC::CodeLocationJump CodeLocationJump
;
80 typedef JSC::CodeLocationCall CodeLocationCall
;
81 typedef JSC::CodeLocationInstruction CodeLocationInstruction
;
82 typedef JSC::ReturnAddressPtr ReturnAddressPtr
;
83 typedef JSC::MacroAssemblerCodePtr MacroAssemblerCodePtr
;
84 typedef JSC::JITCode JITCode
;
85 #if defined JS_CPU_ARM
86 typedef JSC::ARMWord ARMWord
;
90 class BaseCompiler
: public MacroAssemblerTypedefs
96 BaseCompiler() : cx(NULL
)
99 BaseCompiler(JSContext
*cx
) : cx(cx
)
104 JSC::ExecutablePool
*
105 getExecPool(JSScript
*script
, size_t size
) {
106 return BaseCompiler::GetExecPool(cx
, script
, size
);
110 static JSC::ExecutablePool
*
111 GetExecPool(JSContext
*cx
, JSScript
*script
, size_t size
) {
112 JaegerCompartment
*jc
= script
->compartment
->jaegerCompartment
;
113 JSC::ExecutablePool
*pool
= jc
->poolForSize(size
);
115 js_ReportOutOfMemory(cx
);
120 // This class wraps JSC::LinkBuffer for Mozilla-specific memory handling.
121 // Every return |false| guarantees an OOM that has been correctly propagated,
122 // and should continue to propagate.
123 class LinkerHelper
: public JSC::LinkBuffer
132 LinkerHelper(Assembler
&masm
) : masm(masm
)
134 , verifiedRange(false)
139 JS_ASSERT(verifiedRange
);
142 bool verifyRange(const JSC::JITCode
&other
) {
144 verifiedRange
= true;
147 uintptr_t lowest
= JS_MIN(uintptr_t(m_code
), uintptr_t(other
.start()));
149 uintptr_t myEnd
= uintptr_t(m_code
) + m_size
;
150 uintptr_t otherEnd
= uintptr_t(other
.start()) + other
.size();
151 uintptr_t highest
= JS_MAX(myEnd
, otherEnd
);
153 return (highest
- lowest
< INT_MAX
);
159 bool verifyRange(JITScript
*jit
) {
160 return verifyRange(JSC::JITCode(jit
->code
.m_code
.executableAddress(), jit
->code
.m_size
));
163 JSC::ExecutablePool
*init(JSContext
*cx
) {
164 // The pool is incref'd after this call, so it's necessary to release()
166 JSScript
*script
= cx
->fp()->script();
167 JSC::ExecutablePool
*ep
= BaseCompiler::GetExecPool(cx
, script
, masm
.size());
171 m_code
= executableCopy(masm
, ep
);
174 js_ReportOutOfMemory(cx
);
177 m_size
= masm
.size(); // must come after the call to executableCopy()
181 JSC::CodeLocationLabel
finalize() {
182 masm
.finalize(*this);
183 return finalizeCodeAddendum();
186 void maybeLink(MaybeJump jump
, JSC::CodeLocationLabel label
) {
189 link(jump
.get(), label
);
192 size_t size() const {
198 * On ARM, we periodically flush a constant pool into the instruction stream
199 * where constants are found using PC-relative addressing. This is necessary
200 * because the fixed-width instruction set doesn't support wide immediates.
202 * ICs perform repatching on the inline (fast) path by knowing small and
203 * generally fixed code location offset values where the patchable instructions
204 * live. Dumping a huge constant pool into the middle of an IC's inline path
205 * makes the distance between emitted instructions potentially variable and/or
206 * large, which makes the IC offsets invalid. We must reserve contiguous space
207 * up front to prevent this from happening.
210 template <size_t reservedSpace
>
211 class AutoReserveICSpace
{
212 typedef Assembler::Label Label
;
221 AutoReserveICSpace(Assembler
&masm
) : masm(masm
) {
222 masm
.ensureSpace(reservedSpace
);
226 startLabel
= masm
.label();
228 /* Assert that the constant pool is not flushed until we reach a safe point. */
229 masm
.allowPoolFlush(false);
231 JaegerSpew(JSpew_Insns
, " -- BEGIN CONSTANT-POOL-FREE REGION -- \n");
235 /* Allow manual IC space checks so that non-patchable code at the end of an IC section can be
236 * free to use constant pools. */
239 JS_ASSERT(!didCheck
);
242 Label endLabel
= masm
.label();
243 int spaceUsed
= masm
.differenceBetween(startLabel
, endLabel
);
245 /* Spew the space used, to help tuning of reservedSpace. */
246 JaegerSpew(JSpew_Insns
,
247 " -- END CONSTANT-POOL-FREE REGION: %u bytes used of %u reserved. -- \n",
248 spaceUsed
, reservedSpace
);
250 /* Assert that we didn't emit more code than we protected. */
251 JS_ASSERT(spaceUsed
>= 0);
252 JS_ASSERT(size_t(spaceUsed
) <= reservedSpace
);
254 /* Allow the pool to be flushed. */
255 masm
.allowPoolFlush(true);
259 ~AutoReserveICSpace() {
261 /* Automatically check the IC space if we didn't already do it manually. */
269 # define RESERVE_IC_SPACE(__masm) AutoReserveICSpace<128> arics(__masm)
270 # define CHECK_IC_SPACE() arics.check()
272 /* The OOL path can need a lot of space because we save and restore a lot of registers. The actual
273 * sequene varies. However, dumping the literal pool before an OOL block is probably a good idea
274 * anyway, as we branch directly to the start of the block from the fast path. */
275 # define RESERVE_OOL_SPACE(__masm) AutoReserveICSpace<256> arics_ool(__masm)
277 /* Allow the OOL patch to be checked before object destruction. Often, non-patchable epilogues or
278 * rejoining sequences are emitted, and it isn't necessary to protect these from literal pools. */
279 # define CHECK_OOL_SPACE() arics_ool.check()
281 # define RESERVE_IC_SPACE(__masm) /* Do nothing. */
282 # define CHECK_IC_SPACE() /* Do nothing. */
283 # define RESERVE_OOL_SPACE(__masm) /* Do nothing. */
284 # define CHECK_OOL_SPACE() /* Do nothing. */
288 } /* namespace mjit */