1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "jit/Linker.h"
8
9 #include "gc/GC.h"
10
11 #include "gc/StoreBuffer-inl.h"
12
13 namespace js {
14 namespace jit {
15
newCode(JSContext * cx,CodeKind kind,bool hasPatchableBackedges)16 JitCode* Linker::newCode(JSContext* cx, CodeKind kind,
17 bool hasPatchableBackedges /* = false */) {
18 MOZ_ASSERT_IF(hasPatchableBackedges, kind == CodeKind::Ion);
19
20 JS::AutoAssertNoGC nogc(cx);
21 if (masm.oom()) return fail(cx);
22
23 masm.performPendingReadBarriers();
24
25 static const size_t ExecutableAllocatorAlignment = sizeof(void*);
26 static_assert(CodeAlignment >= ExecutableAllocatorAlignment,
27 "Unexpected alignment requirements");
28
29 // We require enough bytes for the code, header, and worst-case alignment
30 // padding.
31 size_t bytesNeeded = masm.bytesNeeded() + sizeof(JitCodeHeader) +
32 (CodeAlignment - ExecutableAllocatorAlignment);
33 if (bytesNeeded >= MAX_BUFFER_SIZE) return fail(cx);
34
35 // ExecutableAllocator requires bytesNeeded to be aligned.
36 bytesNeeded = AlignBytes(bytesNeeded, ExecutableAllocatorAlignment);
37
38 ExecutableAllocator& execAlloc =
39 hasPatchableBackedges ? cx->runtime()->jitRuntime()->backedgeExecAlloc()
40 : cx->runtime()->jitRuntime()->execAlloc();
41
42 ExecutablePool* pool;
43 uint8_t* result = (uint8_t*)execAlloc.alloc(cx, bytesNeeded, &pool, kind);
44 if (!result) return fail(cx);
45
46 // The JitCodeHeader will be stored right before the code buffer.
47 uint8_t* codeStart = result + sizeof(JitCodeHeader);
48
49 // Bump the code up to a nice alignment.
50 codeStart = (uint8_t*)AlignBytes((uintptr_t)codeStart, CodeAlignment);
51 MOZ_ASSERT(codeStart + masm.bytesNeeded() <= result + bytesNeeded);
52 uint32_t headerSize = codeStart - result;
53 JitCode* code = JitCode::New<NoGC>(cx, codeStart, bytesNeeded - headerSize,
54 headerSize, pool, kind);
55 if (!code) return fail(cx);
56 if (masm.oom()) return fail(cx);
57 awjc.emplace(result, bytesNeeded);
58 code->copyFrom(masm);
59 masm.link(code);
60 if (masm.embedsNurseryPointers())
61 cx->zone()->group()->storeBuffer().putWholeCell(code);
62 return code;
63 }
64
65 } // namespace jit
66 } // namespace js
67