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>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "MethodJIT.h"
41 #include "assembler/jit/ExecutableAllocator.h"
43 #include "BaseAssembler.h"
46 #include "TrampolineCompiler.h"
47 #include "jscntxtinlines.h"
50 using namespace js::mjit
;
53 * Explanation of VMFrame activation and various helper thunks below.
55 * JaegerTrampoline - Executes a method JIT-compiled JSFunction. This function
56 * creates a VMFrame on the machine stack and calls into JIT'd code. The JIT'd
57 * code will eventually return to the VMFrame.
59 * - Called from C++ function EnterMethodJIT.
60 * - Parameters: cx, fp, code, stackLimit, safePoint
61 * - Notes: safePoint is used in combination with SafePointTrampoline,
62 * explained further down.
64 * JaegerThrowpoline - Calls into an exception handler from JIT'd code, and if a
65 * scripted exception handler is not found, unwinds the VMFrame and returns
68 * - To start exception handling, we return from a stub call to the throwpoline.
69 * - On entry to the throwpoline, the normal conditions of the jit-code ABI
71 * - To do the unwinding and find out where to continue executing, we call
73 * - js_InternalThrow may return 0, which means the place to continue, if any,
74 * is above this JaegerShot activation, so we just return, in the same way
75 * the trampoline does.
76 * - Otherwise, js_InternalThrow returns a jit-code address to continue execution
77 * at. Because the jit-code ABI conditions are satisfied, we can just jump to
81 * SafePointTrampoline - Inline script calls link their return addresses through
82 * JSStackFrame::ncode. This includes the return address that unwinds back
83 * to JaegerTrampoline. However, the tracer integration code often wants to
84 * enter a method JIT'd function at an arbitrary safe point. Safe points
85 * do not have the return address linking code that the method prologue has.
86 * SafePointTrampoline is a thunk which correctly links the initial return
87 * address. It is used in JaegerShotAtSafePoint, and passed as the "script
88 * code" parameter. Using the "safePoint" parameter to JaegerTrampoline, it
89 * correctly jumps to the intended point in the method.
91 * - Used by JaegerTrampoline()
93 * InjectJaegerReturn - Implements the tail of InlineReturn. This is needed for
94 * tracer integration, where a "return" opcode might not be a safe-point,
95 * and thus the return path must be injected by hijacking the stub return
98 * - Used by RunTracer()
101 #ifdef JS_METHODJIT_PROFILE_STUBS
102 static const size_t STUB_CALLS_FOR_OP_COUNT
= 255;
103 static uint32 StubCallsForOp
[STUB_CALLS_FOR_OP_COUNT
];
106 extern "C" void JS_FASTCALL
107 PushActiveVMFrame(VMFrame
&f
)
109 f
.previous
= JS_METHODJIT_DATA(f
.cx
).activeFrame
;
110 JS_METHODJIT_DATA(f
.cx
).activeFrame
= &f
;
113 extern "C" void JS_FASTCALL
114 PopActiveVMFrame(VMFrame
&f
)
116 JS_ASSERT(JS_METHODJIT_DATA(f
.cx
).activeFrame
);
117 JS_METHODJIT_DATA(f
.cx
).activeFrame
= JS_METHODJIT_DATA(f
.cx
).activeFrame
->previous
;
120 extern "C" void JS_FASTCALL
121 SetVMFrameRegs(VMFrame
&f
)
123 f
.oldRegs
= f
.cx
->regs
;
124 f
.cx
->setCurrentRegs(&f
.regs
);
127 extern "C" void JS_FASTCALL
128 UnsetVMFrameRegs(VMFrame
&f
)
131 f
.cx
->setCurrentRegs(f
.oldRegs
);
134 #if defined(__APPLE__) || defined(XP_WIN)
135 # define SYMBOL_STRING(name) "_" #name
137 # define SYMBOL_STRING(name) #name
140 JS_STATIC_ASSERT(offsetof(JSFrameRegs
, sp
) == 0);
142 #if defined(__linux__) && defined(JS_CPU_X64)
143 # define SYMBOL_STRING_RELOC(name) #name "@plt"
145 # define SYMBOL_STRING_RELOC(name) SYMBOL_STRING(name)
148 #if defined(XP_MACOSX)
149 # define HIDE_SYMBOL(name) ".private_extern _" #name
150 #elif defined(__linux__)
151 # define HIDE_SYMBOL(name) ".hidden" #name
153 # define HIDE_SYMBOL(name)
156 #if defined(__GNUC__)
158 /* If this assert fails, you need to realign VMFrame to 16 bytes. */
160 JS_STATIC_ASSERT(sizeof(VMFrame
) % 8 == 0);
162 JS_STATIC_ASSERT(sizeof(VMFrame
) % 16 == 0);
165 # if defined(JS_CPU_X64)
169 * If these assertions break, update the constants below.
172 JS_STATIC_ASSERT(offsetof(VMFrame
, savedRBX
) == 0x58);
173 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x38);
175 JS_STATIC_ASSERT(JSVAL_TAG_MASK
== 0xFFFF800000000000LL
);
176 JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK
== 0x00007FFFFFFFFFFFLL
);
180 ".globl " SYMBOL_STRING(JaegerTrampoline
) "\n"
181 SYMBOL_STRING(JaegerTrampoline
) ":" "\n"
184 "movq %rsp, %rbp" "\n"
185 /* Save non-volatile registers. */
192 /* Load mask registers. */
193 "movq $0xFFFF800000000000, %r13" "\n"
194 "movq $0x00007FFFFFFFFFFF, %r14" "\n"
196 /* Build the JIT frame.
199 * rcx = inlineCallCount
200 * fp must go into rbx
202 "pushq %rsi" "\n" /* entryFp */
203 "pushq %rcx" "\n" /* inlineCallCount */
204 "pushq %rdi" "\n" /* cx */
205 "pushq %rsi" "\n" /* fp */
206 "movq %rsi, %rbx" "\n"
208 /* Space for the rest of the VMFrame. */
209 "subq $0x28, %rsp" "\n"
212 * This is actually part of the VMFrame, but we need to save |r8| for
213 * SafePointTrampoline.
217 /* Set cx->regs and set the active frame. Save rdx and align frame in one. */
219 "movq %rsp, %rdi" "\n"
220 "call " SYMBOL_STRING_RELOC(SetVMFrameRegs
) "\n"
221 "movq %rsp, %rdi" "\n"
222 "call " SYMBOL_STRING_RELOC(PushActiveVMFrame
) "\n"
225 * Jump into into the JIT'd code.
228 "movq %rsp, %rdi" "\n"
229 "call " SYMBOL_STRING_RELOC(PopActiveVMFrame
) "\n"
230 "movq %rsp, %rdi" "\n"
231 "call " SYMBOL_STRING_RELOC(UnsetVMFrameRegs
) "\n"
233 "addq $0x58, %rsp" "\n"
246 ".globl " SYMBOL_STRING(JaegerThrowpoline
) "\n"
247 SYMBOL_STRING(JaegerThrowpoline
) ":" "\n"
248 "movq %rsp, %rdi" "\n"
249 "call " SYMBOL_STRING_RELOC(js_InternalThrow
) "\n"
250 "testq %rax, %rax" "\n"
251 "je throwpoline_exit" "\n"
253 "throwpoline_exit:" "\n"
254 "movq %rsp, %rdi" "\n"
255 "call " SYMBOL_STRING_RELOC(PopActiveVMFrame
) "\n"
256 "addq $0x58, %rsp" "\n"
263 "xorq %rax,%rax" "\n"
267 JS_STATIC_ASSERT(offsetof(JSStackFrame
, ncode
) == 0x60);
268 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x38);
272 ".globl " SYMBOL_STRING(SafePointTrampoline
) "\n"
273 SYMBOL_STRING(SafePointTrampoline
) ":" "\n"
275 "movq %rax, 0x60(%rbx)" "\n"
281 ".globl " SYMBOL_STRING(InjectJaegerReturn
) "\n"
282 SYMBOL_STRING(InjectJaegerReturn
) ":" "\n"
283 "movq 0x40(%rbx), %rcx" "\n" /* load Value into typeReg */
284 "movq 0x60(%rbx), %rax" "\n" /* fp->ncode */
286 /* Reimplementation of PunboxAssembler::loadValueAsComponents() */
287 "movq %r14, %rdx" "\n" /* payloadReg = payloadMaskReg */
288 "andq %rcx, %rdx" "\n"
289 "xorq %rdx, %rcx" "\n"
291 "movq 0x38(%rsp), %rbx" "\n" /* f.fp */
292 "jmp *%rax" "\n" /* return. */
295 # elif defined(JS_CPU_X86)
299 * If these assertions break, update the constants below. The throwpoline
300 * should have the offset of savedEBX plus 4, because it needs to clean
304 JS_STATIC_ASSERT(offsetof(VMFrame
, savedEBX
) == 0x2c);
305 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x1C);
309 ".globl " SYMBOL_STRING(JaegerTrampoline
) "\n"
310 SYMBOL_STRING(JaegerTrampoline
) ":" "\n"
313 "movl %esp, %ebp" "\n"
314 /* Save non-volatile registers. */
319 /* Build the JIT frame. Push fields in order,
320 * then align the stack to form esp == VMFrame. */
321 "movl 12(%ebp), %ebx" "\n" /* load fp */
322 "pushl %ebx" "\n" /* entryFp */
323 "pushl 20(%ebp)" "\n" /* stackLimit */
324 "pushl 8(%ebp)" "\n" /* cx */
325 "pushl %ebx" "\n" /* fp */
326 "subl $0x1C, %esp" "\n"
328 /* Jump into the JIT'd code. */
329 "movl %esp, %ecx" "\n"
330 "call " SYMBOL_STRING_RELOC(SetVMFrameRegs
) "\n"
331 "movl %esp, %ecx" "\n"
332 "call " SYMBOL_STRING_RELOC(PushActiveVMFrame
) "\n"
334 "call *16(%ebp)" "\n"
335 "movl %esp, %ecx" "\n"
336 "call " SYMBOL_STRING_RELOC(PopActiveVMFrame
) "\n"
337 "movl %esp, %ecx" "\n"
338 "call " SYMBOL_STRING_RELOC(UnsetVMFrameRegs
) "\n"
340 "addl $0x2C, %esp" "\n"
351 ".globl " SYMBOL_STRING(JaegerThrowpoline
) "\n"
352 SYMBOL_STRING(JaegerThrowpoline
) ":" "\n"
353 /* Align the stack to 16 bytes. */
358 "call " SYMBOL_STRING_RELOC(js_InternalThrow
) "\n"
359 /* Bump the stack by 0x2c, as in the basic trampoline, but
360 * also one more word to clean up the stack for js_InternalThrow,
361 * and another to balance the alignment above. */
362 "addl $0x10, %esp" "\n"
363 "testl %eax, %eax" "\n"
364 "je throwpoline_exit" "\n"
366 "throwpoline_exit:" "\n"
367 "movl %esp, %ecx" "\n"
368 "call " SYMBOL_STRING_RELOC(PopActiveVMFrame
) "\n"
369 "addl $0x2c, %esp" "\n"
374 "xorl %eax, %eax" "\n"
378 JS_STATIC_ASSERT(offsetof(JSStackFrame
, ncode
) == 0x3C);
379 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x1C);
383 ".globl " SYMBOL_STRING(InjectJaegerReturn
) "\n"
384 SYMBOL_STRING(InjectJaegerReturn
) ":" "\n"
385 "movl 0x28(%ebx), %edx" "\n" /* fp->rval data */
386 "movl 0x2C(%ebx), %ecx" "\n" /* fp->rval type */
387 "movl 0x3C(%ebx), %eax" "\n" /* fp->ncode */
388 "movl 0x1C(%esp), %ebx" "\n" /* f.fp */
394 * Take the fifth parameter from JaegerShot() and jump to it. This makes it so
395 * we can jump into arbitrary JIT code, which won't have the frame-fixup prologue.
399 ".globl " SYMBOL_STRING(SafePointTrampoline
) "\n"
400 SYMBOL_STRING(SafePointTrampoline
) ":" "\n"
402 "movl %eax, 0x3C(%ebx)" "\n"
406 # elif defined(JS_CPU_ARM)
408 JS_STATIC_ASSERT(sizeof(VMFrame
) == 80);
409 JS_STATIC_ASSERT(offsetof(VMFrame
, savedLR
) == (4*19));
410 JS_STATIC_ASSERT(offsetof(VMFrame
, entryFp
) == (4*10));
411 JS_STATIC_ASSERT(offsetof(VMFrame
, stackLimit
) == (4*9));
412 JS_STATIC_ASSERT(offsetof(VMFrame
, cx
) == (4*8));
413 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == (4*7));
414 JS_STATIC_ASSERT(offsetof(VMFrame
, oldRegs
) == (4*4));
415 JS_STATIC_ASSERT(offsetof(VMFrame
, previous
) == (4*3));
416 JS_STATIC_ASSERT(offsetof(JSStackFrame
, ncode
) == 60);
418 JS_STATIC_ASSERT(JSFrameReg
== JSC::ARMRegisters::r11
);
419 JS_STATIC_ASSERT(JSReturnReg_Data
== JSC::ARMRegisters::r1
);
420 JS_STATIC_ASSERT(JSReturnReg_Type
== JSC::ARMRegisters::r2
);
424 ".globl " SYMBOL_STRING(InjectJaegerReturn
) "\n"
425 SYMBOL_STRING(InjectJaegerReturn
) ":" "\n"
426 /* Restore frame regs. */
427 "ldr lr, [r11, #60]" "\n" /* fp->ncode */
428 "ldr r1, [r11, #40]" "\n" /* fp->rval data */
429 "ldr r2, [r11, #44]" "\n" /* fp->rval type */
430 "ldr r11, [sp, #28]" "\n" /* load f.fp */
436 ".globl " SYMBOL_STRING(SafePointTrampoline
) "\n"
437 SYMBOL_STRING(SafePointTrampoline
) ":"
439 * On entry to SafePointTrampoline:
443 "ldr ip, [sp, #80]" "\n"
444 /* Save the return address (in JaegerTrampoline) to fp->ncode. */
445 "str lr, [r11, #60]" "\n"
446 /* Jump to 'safePoint' via 'ip' because a load into the PC from an address on
447 * the stack looks like a return, and may upset return stack prediction. */
453 ".globl " SYMBOL_STRING(JaegerTrampoline
) "\n"
454 SYMBOL_STRING(JaegerTrampoline
) ":" "\n"
456 * On entry to JaegerTrampoline:
463 * The VMFrame for ARM looks like this:
467 * [ r9 ] | Callee-saved registers.
468 * [ r8 ] | VFP registers d8-d15 may be required here too, but
469 * [ r7 ] | unconditionally preserving them might be expensive
470 * [ r6 ] | considering that we might not use them anyway.
486 /* Push callee-saved registers. */
487 " push {r4-r11,lr}" "\n"
488 /* Push interesting VMFrame content. */
489 " push {r1}" "\n" /* entryFp */
490 " push {r3}" "\n" /* stackLimit */
491 " push {r0}" "\n" /* cx */
492 " push {r1}" "\n" /* regs.fp */
493 /* Remaining fields are set elsewhere, but we need to leave space for them. */
494 " sub sp, sp, #(4*7)" "\n"
496 /* Preserve 'code' (r2) in an arbitrary callee-saved register. */
498 /* Preserve 'fp' (r1) in r11 (JSFrameReg) for SafePointTrampoline. */
502 " bl " SYMBOL_STRING_RELOC(SetVMFrameRegs
) "\n"
504 " bl " SYMBOL_STRING_RELOC(PushActiveVMFrame
)"\n"
506 /* Call the compiled JavaScript function. */
511 " bl " SYMBOL_STRING_RELOC(PopActiveVMFrame
) "\n"
513 " bl " SYMBOL_STRING_RELOC(UnsetVMFrameRegs
) "\n"
515 /* Skip past the parameters we pushed (such as cx and the like). */
516 " add sp, sp, #(4*7 + 4*4)" "\n"
518 /* Set a 'true' return value to indicate successful completion. */
520 " pop {r4-r11,pc}" "\n"
525 ".globl " SYMBOL_STRING(JaegerThrowpoline
) "\n"
526 SYMBOL_STRING(JaegerThrowpoline
) ":" "\n"
527 /* Find the VMFrame pointer for js_InternalThrow. */
530 /* Call the utility function that sets up the internal throw routine. */
531 " bl " SYMBOL_STRING_RELOC(js_InternalThrow
) "\n"
533 /* If js_InternalThrow found a scripted handler, jump to it. Otherwise, tidy
539 /* Tidy up, then return '0' to represent an unhandled exception. */
541 " bl " SYMBOL_STRING_RELOC(PopActiveVMFrame
) "\n"
542 " add sp, sp, #(4*7 + 4*4)" "\n"
544 " pop {r4-r11,pc}" "\n"
549 ".globl " SYMBOL_STRING(JaegerStubVeneer
) "\n"
550 SYMBOL_STRING(JaegerStubVeneer
) ":" "\n"
551 /* We enter this function as a veneer between a compiled method and one of the js_ stubs. We
552 * need to store the LR somewhere (so it can be modified in case on an exception) and then
553 * branch to the js_ stub as if nothing had happened.
554 * The arguments are identical to those for js_* except that the target function should be in
562 # error "Unsupported CPU!"
564 #elif defined(_MSC_VER)
566 #if defined(JS_CPU_X86)
570 * If these assertions break, update the constants below. The throwpoline
571 * should have the offset of savedEBX plus 4, because it needs to clean
575 JS_STATIC_ASSERT(offsetof(VMFrame
, savedEBX
) == 0x2c);
576 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x1C);
580 __declspec(naked
) void InjectJaegerReturn()
583 mov edx
, [ebx
+ 0x28];
584 mov ecx
, [ebx
+ 0x2C];
585 mov eax
, [ebx
+ 0x3C];
586 mov ebx
, [esp
+ 0x1C];
592 __declspec(naked
) void SafePointTrampoline()
596 mov
[ebx
+ 0x3C], eax
;
601 __declspec(naked
) JSBool
JaegerTrampoline(JSContext
*cx
, JSStackFrame
*fp
, void *code
,
602 Value
*stackLimit
, void *safePoint
)
608 /* Save non-volatile registers. */
613 /* Build the JIT frame. Push fields in order,
614 * then align the stack to form esp == VMFrame. */
622 /* Jump into into the JIT'd code. */
626 call PushActiveVMFrame
;
630 call PopActiveVMFrame
;
632 call UnsetVMFrameRegs
;
645 extern "C" void *js_InternalThrow(js::VMFrame
&f
);
647 __declspec(naked
) void *JaegerThrowpoline(js::VMFrame
*vmFrame
) {
649 /* Align the stack to 16 bytes. */
654 call js_InternalThrow
;
655 /* Bump the stack by 0x2c, as in the basic trampoline, but
656 * also one more word to clean up the stack for js_InternalThrow,
657 * and another to balance the alignment above. */
664 call PopActiveVMFrame
;
676 #elif defined(JS_CPU_X64)
680 * If these assertions break, update the constants below.
683 JS_STATIC_ASSERT(offsetof(VMFrame
, savedRBX
) == 0x58);
684 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x38);
685 JS_STATIC_ASSERT(offsetof(JSStackFrame
, ncode
) == 0x60);
686 JS_STATIC_ASSERT(JSVAL_TAG_MASK
== 0xFFFF800000000000LL
);
687 JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK
== 0x00007FFFFFFFFFFFLL
);
689 // Windows x64 uses assembler version since compiler doesn't support
692 # error "Unsupported CPU!"
695 #endif /* _MSC_VER */
698 ThreadData::Initialize()
700 execPool
= new JSC::ExecutableAllocator();
704 TrampolineCompiler
tc(execPool
, &trampolines
);
710 #ifdef JS_METHODJIT_PROFILE_STUBS
711 for (size_t i
= 0; i
< STUB_CALLS_FOR_OP_COUNT
; ++i
)
712 StubCallsForOp
[i
] = 0;
723 TrampolineCompiler::release(&trampolines
);
725 #ifdef JS_METHODJIT_PROFILE_STUBS
726 FILE *fp
= fopen("/tmp/stub-profiling", "wt");
727 # define OPDEF(op,val,name,image,length,nuses,ndefs,prec,format) \
728 fprintf(fp, "%03d %s %d\n", val, #op, StubCallsForOp[val]);
729 # include "jsopcode.tbl"
735 extern "C" JSBool
JaegerTrampoline(JSContext
*cx
, JSStackFrame
*fp
, void *code
,
736 Value
*stackLimit
, void *safePoint
);
737 extern "C" void SafePointTrampoline();
740 EnterMethodJIT(JSContext
*cx
, JSStackFrame
*fp
, void *code
, void *safePoint
)
743 JS_CHECK_RECURSION(cx
, return JS_FALSE
;);
745 #ifdef JS_METHODJIT_SPEW
747 JSScript
*script
= fp
->getScript();
749 JaegerSpew(JSpew_Prof
, "%s jaeger script: %s, line %d\n",
750 safePoint
? "dropping" : "entering",
751 script
->filename
, script
->lineno
);
756 JSStackFrame
*checkFp
= fp
;
759 Value
*fpAsVp
= reinterpret_cast<Value
*>(fp
);
760 StackSpace
&stack
= cx
->stack();
761 Value
*stackLimit
= stack
.makeStackLimit(fpAsVp
);
764 * We ensure that there is always enough space to speculatively create a
765 * stack frame. By passing nslots = 0, we ensure only sizeof(JSStackFrame).
767 if (fpAsVp
+ VALUES_PER_STACK_FRAME
>= stackLimit
&&
768 !stack
.ensureSpace(cx
, fpAsVp
, cx
->regs
->sp
, stackLimit
, 0)) {
769 js_ReportOutOfScriptQuota(cx
);
773 JSAutoResolveFlags
rf(cx
, JSRESOLVE_INFER
);
774 JSBool ok
= JaegerTrampoline(cx
, fp
, code
, stackLimit
, safePoint
);
776 JS_ASSERT(checkFp
== cx
->fp());
778 #ifdef JS_METHODJIT_SPEW
780 JaegerSpew(JSpew_Prof
, "script run took %d ms\n", prof
.time_ms());
787 mjit::JaegerShot(JSContext
*cx
)
789 JSScript
*script
= cx
->fp()->getScript();
791 JS_ASSERT(script
->ncode
&& script
->ncode
!= JS_UNJITTABLE_METHOD
);
794 if (TRACE_RECORDER(cx
))
795 AbortRecording(cx
, "attempt to enter method JIT while recording");
798 JS_ASSERT(cx
->regs
->pc
== script
->code
);
800 return EnterMethodJIT(cx
, cx
->fp(), script
->jit
->invoke
, NULL
);
804 js::mjit::JaegerShotAtSafePoint(JSContext
*cx
, void *safePoint
)
807 JS_ASSERT(!TRACE_RECORDER(cx
));
810 void *code
= JS_FUNC_TO_DATA_PTR(void *, SafePointTrampoline
);
812 return EnterMethodJIT(cx
, cx
->fp(), code
, safePoint
);
815 template <typename T
>
816 static inline void Destroy(T
&t
)
822 mjit::ReleaseScriptCode(JSContext
*cx
, JSScript
*script
)
825 #if defined DEBUG && (defined JS_CPU_X86 || defined JS_CPU_X64)
826 memset(script
->jit
->invoke
, 0xcc, script
->jit
->inlineLength
+
827 script
->jit
->outOfLineLength
);
829 script
->jit
->execPool
->release();
830 script
->jit
->execPool
= NULL
;
832 // Releasing the execPool takes care of releasing the code.
833 script
->ncode
= NULL
;
835 #if defined JS_POLYIC
836 for (uint32 i
= 0; i
< script
->jit
->nPICs
; i
++) {
837 script
->pics
[i
].releasePools();
838 Destroy(script
->pics
[i
].execPools
);
842 #if defined JS_MONOIC
843 for (uint32 i
= 0; i
< script
->jit
->nCallICs
; i
++)
844 script
->callICs
[i
].releasePools();
847 cx
->free(script
->jit
);
849 // The recompiler may call ReleaseScriptCode, in which case it
850 // will get called again when the script is destroyed, so we
851 // must protect against calling ReleaseScriptCode twice.
857 mjit::SweepCallICs(JSContext
*cx
)
860 JSRuntime
*rt
= cx
->runtime
;
861 for (size_t i
= 0; i
< rt
->compartments
.length(); i
++) {
862 JSCompartment
*compartment
= rt
->compartments
[i
];
863 for (JSScript
*script
= (JSScript
*)compartment
->scripts
.next
;
864 &script
->links
!= &compartment
->scripts
;
865 script
= (JSScript
*)script
->links
.next
) {
867 ic::SweepCallICs(cx
, script
);
873 #ifdef JS_METHODJIT_PROFILE_STUBS
875 mjit::ProfileStubCall(VMFrame
&f
)
877 JSOp op
= JSOp(*f
.regs
.pc
);
878 StubCallsForOp
[op
]++;
883 VMFrame::slowEnsureSpace(uint32 nslots
)
885 return cx
->stack().ensureSpace(cx
, reinterpret_cast<Value
*>(entryFp
), regs
.sp
,
886 stackLimit
, nslots
+ VALUES_PER_STACK_FRAME
);