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"
48 #include "jscompartment.h"
51 #include "jsgcinlines.h"
54 using namespace js::mjit
;
58 JSStackFrame::methodjitStaticAsserts()
60 /* Static assert for x86 trampolines in MethodJIT.cpp. */
61 #if defined(JS_CPU_X86)
62 JS_STATIC_ASSERT(offsetof(JSStackFrame
, rval_
) == 0x18);
63 JS_STATIC_ASSERT(offsetof(JSStackFrame
, rval_
) + 4 == 0x1C);
64 JS_STATIC_ASSERT(offsetof(JSStackFrame
, ncode_
) == 0x14);
65 /* ARM uses decimal literals. */
66 JS_STATIC_ASSERT(offsetof(JSStackFrame
, rval_
) == 24);
67 JS_STATIC_ASSERT(offsetof(JSStackFrame
, rval_
) + 4 == 28);
68 JS_STATIC_ASSERT(offsetof(JSStackFrame
, ncode_
) == 20);
69 #elif defined(JS_CPU_X64)
70 JS_STATIC_ASSERT(offsetof(JSStackFrame
, rval_
) == 0x30);
71 JS_STATIC_ASSERT(offsetof(JSStackFrame
, ncode_
) == 0x28);
76 * Explanation of VMFrame activation and various helper thunks below.
78 * JaegerTrampoline - Executes a method JIT-compiled JSFunction. This function
79 * creates a VMFrame on the machine stack and jumps into JIT'd code. The JIT'd
80 * code will eventually jump back to the VMFrame.
82 * - Called from C++ function EnterMethodJIT.
83 * - Parameters: cx, fp, code, stackLimit
85 * JaegerThrowpoline - Calls into an exception handler from JIT'd code, and if a
86 * scripted exception handler is not found, unwinds the VMFrame and returns
89 * - To start exception handling, we return from a stub call to the throwpoline.
90 * - On entry to the throwpoline, the normal conditions of the jit-code ABI
92 * - To do the unwinding and find out where to continue executing, we call
94 * - js_InternalThrow may return 0, which means the place to continue, if any,
95 * is above this JaegerShot activation, so we just return, in the same way
96 * the trampoline does.
97 * - Otherwise, js_InternalThrow returns a jit-code address to continue execution
98 * at. Because the jit-code ABI conditions are satisfied, we can just jump to
101 * InjectJaegerReturn - Implements the tail of InlineReturn. This is needed for
102 * tracer integration, where a "return" opcode might not be a safe-point,
103 * and thus the return path must be injected by hijacking the stub return
106 * - Used by RunTracer()
109 #ifdef JS_METHODJIT_PROFILE_STUBS
110 static const size_t STUB_CALLS_FOR_OP_COUNT
= 255;
111 static uint32 StubCallsForOp
[STUB_CALLS_FOR_OP_COUNT
];
114 extern "C" void JaegerTrampolineReturn();
116 extern "C" void JS_FASTCALL
117 PushActiveVMFrame(VMFrame
&f
)
119 f
.previous
= JS_METHODJIT_DATA(f
.cx
).activeFrame
;
120 JS_METHODJIT_DATA(f
.cx
).activeFrame
= &f
;
122 f
.regs
.fp
->setNativeReturnAddress(JS_FUNC_TO_DATA_PTR(void*, JaegerTrampolineReturn
));
125 extern "C" void JS_FASTCALL
126 PopActiveVMFrame(VMFrame
&f
)
128 JS_ASSERT(JS_METHODJIT_DATA(f
.cx
).activeFrame
);
129 JS_METHODJIT_DATA(f
.cx
).activeFrame
= JS_METHODJIT_DATA(f
.cx
).activeFrame
->previous
;
132 extern "C" void JS_FASTCALL
133 SetVMFrameRegs(VMFrame
&f
)
135 f
.cx
->setCurrentRegs(&f
.regs
);
138 #if defined(__APPLE__) || defined(XP_WIN)
139 # define SYMBOL_STRING(name) "_" #name
141 # define SYMBOL_STRING(name) #name
144 JS_STATIC_ASSERT(offsetof(JSFrameRegs
, sp
) == 0);
146 #if defined(__linux__) && defined(JS_CPU_X64)
147 # define SYMBOL_STRING_RELOC(name) #name "@plt"
149 # define SYMBOL_STRING_RELOC(name) SYMBOL_STRING(name)
152 #if defined(XP_WIN) && defined(JS_CPU_X86)
153 # define SYMBOL_STRING_VMFRAME(name) "@" #name "@4"
155 # define SYMBOL_STRING_VMFRAME(name) SYMBOL_STRING_RELOC(name)
158 #if defined(XP_MACOSX)
159 # define HIDE_SYMBOL(name) ".private_extern _" #name
160 #elif defined(__linux__)
161 # define HIDE_SYMBOL(name) ".hidden" #name
163 # define HIDE_SYMBOL(name)
166 #if defined(__GNUC__)
168 /* If this assert fails, you need to realign VMFrame to 16 bytes. */
170 JS_STATIC_ASSERT(sizeof(VMFrame
) % 8 == 0);
172 JS_STATIC_ASSERT(sizeof(VMFrame
) % 16 == 0);
175 # if defined(JS_CPU_X64)
179 * If these assertions break, update the constants below.
182 JS_STATIC_ASSERT(offsetof(VMFrame
, savedRBX
) == 0x58);
183 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x38);
185 JS_STATIC_ASSERT(JSVAL_TAG_MASK
== 0xFFFF800000000000LL
);
186 JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK
== 0x00007FFFFFFFFFFFLL
);
190 ".globl " SYMBOL_STRING(JaegerTrampoline
) "\n"
191 SYMBOL_STRING(JaegerTrampoline
) ":" "\n"
194 "movq %rsp, %rbp" "\n"
195 /* Save non-volatile registers. */
202 /* Load mask registers. */
203 "movq $0xFFFF800000000000, %r13" "\n"
204 "movq $0x00007FFFFFFFFFFF, %r14" "\n"
206 /* Build the JIT frame.
209 * rcx = inlineCallCount
210 * fp must go into rbx
212 "pushq %rsi" "\n" /* entryFp */
213 "pushq %rcx" "\n" /* inlineCallCount */
214 "pushq %rdi" "\n" /* cx */
215 "pushq %rsi" "\n" /* fp */
216 "movq %rsi, %rbx" "\n"
218 /* Space for the rest of the VMFrame. */
219 "subq $0x28, %rsp" "\n"
221 /* This is actually part of the VMFrame. */
224 /* Set cx->regs and set the active frame. Save rdx and align frame in one. */
226 "movq %rsp, %rdi" "\n"
227 "call " SYMBOL_STRING_VMFRAME(SetVMFrameRegs
) "\n"
228 "movq %rsp, %rdi" "\n"
229 "call " SYMBOL_STRING_VMFRAME(PushActiveVMFrame
) "\n"
231 /* Jump into the JIT'd code. */
237 ".globl " SYMBOL_STRING(JaegerTrampolineReturn
) "\n"
238 SYMBOL_STRING(JaegerTrampolineReturn
) ":" "\n"
240 "movq %rcx, 0x30(%rbx)" "\n"
241 "movq %rsp, %rdi" "\n"
242 "call " SYMBOL_STRING_VMFRAME(PopActiveVMFrame
) "\n"
244 "addq $0x58, %rsp" "\n"
257 ".globl " SYMBOL_STRING(JaegerThrowpoline
) "\n"
258 SYMBOL_STRING(JaegerThrowpoline
) ":" "\n"
259 "movq %rsp, %rdi" "\n"
260 "call " SYMBOL_STRING_RELOC(js_InternalThrow
) "\n"
261 "testq %rax, %rax" "\n"
262 "je throwpoline_exit" "\n"
264 "throwpoline_exit:" "\n"
265 "movq %rsp, %rdi" "\n"
266 "call " SYMBOL_STRING_VMFRAME(PopActiveVMFrame
) "\n"
267 "addq $0x58, %rsp" "\n"
274 "xorq %rax,%rax" "\n"
278 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x38);
282 ".globl " SYMBOL_STRING(InjectJaegerReturn
) "\n"
283 SYMBOL_STRING(InjectJaegerReturn
) ":" "\n"
284 "movq 0x30(%rbx), %rcx" "\n" /* load fp->rval_ into typeReg */
285 "movq 0x28(%rbx), %rax" "\n" /* fp->ncode_ */
287 /* Reimplementation of PunboxAssembler::loadValueAsComponents() */
288 "movq %r14, %rdx" "\n" /* payloadReg = payloadMaskReg */
289 "andq %rcx, %rdx" "\n"
290 "xorq %rdx, %rcx" "\n"
292 "movq 0x38(%rsp), %rbx" "\n" /* f.fp */
293 "jmp *%rax" "\n" /* return. */
296 # elif defined(JS_CPU_X86)
300 * If these assertions break, update the constants below. The throwpoline
301 * should have the offset of savedEBX plus 4, because it needs to clean
305 JS_STATIC_ASSERT(offsetof(VMFrame
, savedEBX
) == 0x2c);
306 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x1C);
310 ".globl " SYMBOL_STRING(JaegerTrampoline
) "\n"
311 SYMBOL_STRING(JaegerTrampoline
) ":" "\n"
314 "movl %esp, %ebp" "\n"
315 /* Save non-volatile registers. */
320 /* Build the JIT frame. Push fields in order,
321 * then align the stack to form esp == VMFrame. */
322 "movl 12(%ebp), %ebx" "\n" /* load fp */
323 "pushl %ebx" "\n" /* entryFp */
324 "pushl 20(%ebp)" "\n" /* stackLimit */
325 "pushl 8(%ebp)" "\n" /* cx */
326 "pushl %ebx" "\n" /* fp */
327 "subl $0x1C, %esp" "\n"
329 /* Jump into the JIT'd code. */
330 "movl %esp, %ecx" "\n"
331 "call " SYMBOL_STRING_VMFRAME(SetVMFrameRegs
) "\n"
332 "movl %esp, %ecx" "\n"
333 "call " SYMBOL_STRING_VMFRAME(PushActiveVMFrame
) "\n"
340 ".globl " SYMBOL_STRING(JaegerTrampolineReturn
) "\n"
341 SYMBOL_STRING(JaegerTrampolineReturn
) ":" "\n"
342 "movl %edx, 0x18(%ebx)" "\n"
343 "movl %ecx, 0x1C(%ebx)" "\n"
344 "movl %esp, %ecx" "\n"
345 "call " SYMBOL_STRING_VMFRAME(PopActiveVMFrame
) "\n"
347 "addl $0x2C, %esp" "\n"
358 ".globl " SYMBOL_STRING(JaegerThrowpoline
) "\n"
359 SYMBOL_STRING(JaegerThrowpoline
) ":" "\n"
360 /* Align the stack to 16 bytes. */
365 "call " SYMBOL_STRING_RELOC(js_InternalThrow
) "\n"
366 /* Bump the stack by 0x2c, as in the basic trampoline, but
367 * also one more word to clean up the stack for js_InternalThrow,
368 * and another to balance the alignment above. */
369 "addl $0x10, %esp" "\n"
370 "testl %eax, %eax" "\n"
371 "je throwpoline_exit" "\n"
373 "throwpoline_exit:" "\n"
374 "movl %esp, %ecx" "\n"
375 "call " SYMBOL_STRING_VMFRAME(PopActiveVMFrame
) "\n"
376 "addl $0x2c, %esp" "\n"
381 "xorl %eax, %eax" "\n"
385 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x1C);
389 ".globl " SYMBOL_STRING(InjectJaegerReturn
) "\n"
390 SYMBOL_STRING(InjectJaegerReturn
) ":" "\n"
391 "movl 0x18(%ebx), %edx" "\n" /* fp->rval_ data */
392 "movl 0x1C(%ebx), %ecx" "\n" /* fp->rval_ type */
393 "movl 0x14(%ebx), %eax" "\n" /* fp->ncode_ */
394 "movl 0x1C(%esp), %ebx" "\n" /* f.fp */
398 # elif defined(JS_CPU_ARM)
400 JS_STATIC_ASSERT(sizeof(VMFrame
) == 80);
401 JS_STATIC_ASSERT(offsetof(VMFrame
, savedLR
) == (4*19));
402 JS_STATIC_ASSERT(offsetof(VMFrame
, entryFp
) == (4*10));
403 JS_STATIC_ASSERT(offsetof(VMFrame
, stackLimit
) == (4*9));
404 JS_STATIC_ASSERT(offsetof(VMFrame
, cx
) == (4*8));
405 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == (4*7));
406 JS_STATIC_ASSERT(offsetof(VMFrame
, unused
) == (4*4));
407 JS_STATIC_ASSERT(offsetof(VMFrame
, previous
) == (4*3));
409 JS_STATIC_ASSERT(JSFrameReg
== JSC::ARMRegisters::r11
);
410 JS_STATIC_ASSERT(JSReturnReg_Data
== JSC::ARMRegisters::r1
);
411 JS_STATIC_ASSERT(JSReturnReg_Type
== JSC::ARMRegisters::r2
);
414 #define FUNCTION_HEADER_EXTRA \
419 #define FUNCTION_HEADER_EXTRA
424 FUNCTION_HEADER_EXTRA
425 ".globl " SYMBOL_STRING(InjectJaegerReturn
) "\n"
426 SYMBOL_STRING(InjectJaegerReturn
) ":" "\n"
427 /* Restore frame regs. */
428 "ldr lr, [r11, #20]" "\n" /* fp->ncode */
429 "ldr r1, [r11, #24]" "\n" /* fp->rval data */
430 "ldr r2, [r11, #28]" "\n" /* fp->rval type */
431 "ldr r11, [sp, #28]" "\n" /* load f.fp */
437 FUNCTION_HEADER_EXTRA
438 ".globl " SYMBOL_STRING(JaegerTrampoline
) "\n"
439 SYMBOL_STRING(JaegerTrampoline
) ":" "\n"
441 * On entry to JaegerTrampoline:
447 * The VMFrame for ARM looks like this:
451 * [ r9 ] | Callee-saved registers.
452 * [ r8 ] | VFP registers d8-d15 may be required here too, but
453 * [ r7 ] | unconditionally preserving them might be expensive
454 * [ r6 ] | considering that we might not use them anyway.
470 /* Push callee-saved registers. */
471 " push {r4-r11,lr}" "\n"
472 /* Push interesting VMFrame content. */
473 " push {r1}" "\n" /* entryFp */
474 " push {r3}" "\n" /* stackLimit */
475 " push {r0}" "\n" /* cx */
476 " push {r1}" "\n" /* regs.fp */
477 /* Remaining fields are set elsewhere, but we need to leave space for them. */
478 " sub sp, sp, #(4*7)" "\n"
480 /* Preserve 'code' (r2) in an arbitrary callee-saved register. */
482 /* Preserve 'fp' (r1) in r11 (JSFrameReg). */
486 " blx " SYMBOL_STRING_VMFRAME(SetVMFrameRegs
) "\n"
488 " blx " SYMBOL_STRING_VMFRAME(PushActiveVMFrame
)"\n"
490 /* Call the compiled JavaScript function. */
496 FUNCTION_HEADER_EXTRA
497 ".globl " SYMBOL_STRING(JaegerTrampolineReturn
) "\n"
498 SYMBOL_STRING(JaegerTrampolineReturn
) ":" "\n"
499 " str r1, [r11, #24]" "\n" /* fp->rval data */
500 " str r2, [r11, #28]" "\n" /* fp->rval type */
504 " blx " SYMBOL_STRING_VMFRAME(PopActiveVMFrame
) "\n"
506 /* Skip past the parameters we pushed (such as cx and the like). */
507 " add sp, sp, #(4*7 + 4*4)" "\n"
509 /* Set a 'true' return value to indicate successful completion. */
511 " pop {r4-r11,pc}" "\n"
516 FUNCTION_HEADER_EXTRA
517 ".globl " SYMBOL_STRING(JaegerThrowpoline
) "\n"
518 SYMBOL_STRING(JaegerThrowpoline
) ":" "\n"
519 /* Find the VMFrame pointer for js_InternalThrow. */
522 /* Call the utility function that sets up the internal throw routine. */
523 " blx " SYMBOL_STRING_RELOC(js_InternalThrow
) "\n"
525 /* If js_InternalThrow found a scripted handler, jump to it. Otherwise, tidy
531 /* Tidy up, then return '0' to represent an unhandled exception. */
533 " blx " SYMBOL_STRING_VMFRAME(PopActiveVMFrame
) "\n"
534 " add sp, sp, #(4*7 + 4*4)" "\n"
536 " pop {r4-r11,pc}" "\n"
541 FUNCTION_HEADER_EXTRA
542 ".globl " SYMBOL_STRING(JaegerStubVeneer
) "\n"
543 SYMBOL_STRING(JaegerStubVeneer
) ":" "\n"
544 /* We enter this function as a veneer between a compiled method and one of the js_ stubs. We
545 * need to store the LR somewhere (so it can be modified in case on an exception) and then
546 * branch to the js_ stub as if nothing had happened.
547 * The arguments are identical to those for js_* except that the target function should be in
555 # error "Unsupported CPU!"
557 #elif defined(_MSC_VER)
559 #if defined(JS_CPU_X86)
563 * If these assertions break, update the constants below. The throwpoline
564 * should have the offset of savedEBX plus 4, because it needs to clean
568 JS_STATIC_ASSERT(offsetof(VMFrame
, savedEBX
) == 0x2c);
569 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x1C);
573 __declspec(naked
) void InjectJaegerReturn()
576 mov edx
, [ebx
+ 0x18];
577 mov ecx
, [ebx
+ 0x1C];
578 mov eax
, [ebx
+ 0x14];
579 mov ebx
, [esp
+ 0x1C];
584 __declspec(naked
) JSBool
JaegerTrampoline(JSContext
*cx
, JSStackFrame
*fp
, void *code
,
591 /* Save non-volatile registers. */
596 /* Build the JIT frame. Push fields in order,
597 * then align the stack to form esp == VMFrame. */
605 /* Jump into into the JIT'd code. */
609 call PushActiveVMFrame
;
611 jmp dword ptr
[ebp
+ 16];
615 __declspec(naked
) void JaegerTrampolineReturn()
618 mov
[ebx
+ 0x18], edx
;
619 mov
[ebx
+ 0x1C], ecx
;
621 call PopActiveVMFrame
;
634 extern "C" void *js_InternalThrow(js::VMFrame
&f
);
636 __declspec(naked
) void *JaegerThrowpoline(js::VMFrame
*vmFrame
) {
638 /* Align the stack to 16 bytes. */
643 call js_InternalThrow
;
644 /* Bump the stack by 0x2c, as in the basic trampoline, but
645 * also one more word to clean up the stack for js_InternalThrow,
646 * and another to balance the alignment above. */
653 call PopActiveVMFrame
;
665 #elif defined(JS_CPU_X64)
669 * If these assertions break, update the constants below.
672 JS_STATIC_ASSERT(offsetof(VMFrame
, savedRBX
) == 0x58);
673 JS_STATIC_ASSERT(offsetof(VMFrame
, regs
.fp
) == 0x38);
674 JS_STATIC_ASSERT(JSVAL_TAG_MASK
== 0xFFFF800000000000LL
);
675 JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK
== 0x00007FFFFFFFFFFFLL
);
677 // Windows x64 uses assembler version since compiler doesn't support
680 # error "Unsupported CPU!"
683 #endif /* _MSC_VER */
686 ThreadData::Initialize()
688 execAlloc
= new JSC::ExecutableAllocator();
692 TrampolineCompiler
tc(execAlloc
, &trampolines
);
698 #ifdef JS_METHODJIT_PROFILE_STUBS
699 for (size_t i
= 0; i
< STUB_CALLS_FOR_OP_COUNT
; ++i
)
700 StubCallsForOp
[i
] = 0;
711 TrampolineCompiler::release(&trampolines
);
713 #ifdef JS_METHODJIT_PROFILE_STUBS
714 FILE *fp
= fopen("/tmp/stub-profiling", "wt");
715 # define OPDEF(op,val,name,image,length,nuses,ndefs,prec,format) \
716 fprintf(fp, "%03d %s %d\n", val, #op, StubCallsForOp[val]);
717 # include "jsopcode.tbl"
723 extern "C" JSBool
JaegerTrampoline(JSContext
*cx
, JSStackFrame
*fp
, void *code
,
727 EnterMethodJIT(JSContext
*cx
, JSStackFrame
*fp
, void *code
)
730 JS_CHECK_RECURSION(cx
, return JS_FALSE
;);
732 #ifdef JS_METHODJIT_SPEW
734 JSScript
*script
= fp
->script();
736 JaegerSpew(JSpew_Prof
, "%s jaeger script, line %d\n",
737 script
->filename
, script
->lineno
);
741 Value
*stackLimit
= cx
->stack().getStackLimit(cx
);
745 JSFrameRegs
*oldRegs
= cx
->regs
;
747 JSAutoResolveFlags
rf(cx
, JSRESOLVE_INFER
);
748 JSBool ok
= JaegerTrampoline(cx
, fp
, code
, stackLimit
);
750 cx
->setCurrentRegs(oldRegs
);
751 JS_ASSERT(fp
== cx
->fp());
753 /* The trampoline wrote the return value but did not set the HAS_RVAL flag. */
754 fp
->markReturnValue();
756 #ifdef JS_METHODJIT_SPEW
758 JaegerSpew(JSpew_Prof
, "script run took %d ms\n", prof
.time_ms());
765 mjit::JaegerShot(JSContext
*cx
)
767 JSStackFrame
*fp
= cx
->fp();
768 JSScript
*script
= fp
->script();
769 JITScript
*jit
= script
->getJIT(fp
->isConstructing());
772 if (TRACE_RECORDER(cx
))
773 AbortRecording(cx
, "attempt to enter method JIT while recording");
776 JS_ASSERT(cx
->regs
->pc
== script
->code
);
778 return EnterMethodJIT(cx
, cx
->fp(), jit
->invokeEntry
);
782 js::mjit::JaegerShotAtSafePoint(JSContext
*cx
, void *safePoint
)
785 JS_ASSERT(!TRACE_RECORDER(cx
));
788 return EnterMethodJIT(cx
, cx
->fp(), safePoint
);
791 template <typename T
>
792 static inline void Destroy(T
&t
)
798 mjit::JITScript::release()
800 #if defined DEBUG && (defined JS_CPU_X86 || defined JS_CPU_X64)
801 void *addr
= code
.m_code
.executableAddress();
802 memset(addr
, 0xcc, code
.m_size
);
805 code
.m_executablePool
->release();
807 #if defined JS_POLYIC
808 for (uint32 i
= 0; i
< nPICs
; i
++) {
809 pics
[i
].releasePools();
810 Destroy(pics
[i
].execPools
);
814 #if defined JS_MONOIC
815 for (uint32 i
= 0; i
< nCallICs
; i
++)
816 callICs
[i
].releasePools();
821 mjit::ReleaseScriptCode(JSContext
*cx
, JSScript
*script
)
823 // NB: The recompiler may call ReleaseScriptCode, in which case it
824 // will get called again when the script is destroyed, so we
825 // must protect against calling ReleaseScriptCode twice.
827 if (script
->jitNormal
) {
828 script
->jitNormal
->release();
829 script
->jitArityCheckNormal
= NULL
;
830 cx
->free(script
->jitNormal
);
831 script
->jitNormal
= NULL
;
832 script
->nmapNormal
= NULL
;
835 if (script
->jitCtor
) {
836 script
->jitCtor
->release();
837 script
->jitArityCheckCtor
= NULL
;
838 cx
->free(script
->jitCtor
);
839 script
->jitCtor
= NULL
;
840 script
->nmapCtor
= NULL
;
844 #ifdef JS_METHODJIT_PROFILE_STUBS
846 mjit::ProfileStubCall(VMFrame
&f
)
848 JSOp op
= JSOp(*f
.regs
.pc
);
849 StubCallsForOp
[op
]++;