1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
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 #include "jit/JitZone.h"
11 #include "util/Memory.h"
12
13 #include "gc/StoreBuffer-inl.h"
14
15 namespace js {
16 namespace jit {
17
newCode(JSContext * cx,CodeKind kind)18 JitCode* Linker::newCode(JSContext* cx, CodeKind kind) {
19 JS::AutoAssertNoGC nogc(cx);
20 if (masm.oom()) {
21 return fail(cx);
22 }
23
24 static const size_t ExecutableAllocatorAlignment = sizeof(void*);
25 static_assert(CodeAlignment >= ExecutableAllocatorAlignment,
26 "Unexpected alignment requirements");
27
28 // We require enough bytes for the code, header, and worst-case alignment
29 // padding.
30 size_t bytesNeeded = masm.bytesNeeded() + sizeof(JitCodeHeader) +
31 (CodeAlignment - ExecutableAllocatorAlignment);
32 if (bytesNeeded >= MAX_BUFFER_SIZE) {
33 return fail(cx);
34 }
35
36 // ExecutableAllocator requires bytesNeeded to be aligned.
37 bytesNeeded = AlignBytes(bytesNeeded, ExecutableAllocatorAlignment);
38
39 JitZone* jitZone = cx->zone()->getJitZone(cx);
40 if (!jitZone) {
41 // Note: don't call fail(cx) here, getJitZone reports OOM.
42 return nullptr;
43 }
44
45 ExecutablePool* pool;
46 uint8_t* result =
47 (uint8_t*)jitZone->execAlloc().alloc(cx, bytesNeeded, &pool, kind);
48 if (!result) {
49 return fail(cx);
50 }
51
52 // The JitCodeHeader will be stored right before the code buffer.
53 uint8_t* codeStart = result + sizeof(JitCodeHeader);
54
55 // Bump the code up to a nice alignment.
56 codeStart = (uint8_t*)AlignBytes((uintptr_t)codeStart, CodeAlignment);
57 MOZ_ASSERT(codeStart + masm.bytesNeeded() <= result + bytesNeeded);
58 uint32_t headerSize = codeStart - result;
59 JitCode* code =
60 JitCode::New<NoGC>(cx, codeStart, bytesNeeded, headerSize, pool, kind);
61 if (!code) {
62 return fail(cx);
63 }
64 if (masm.oom()) {
65 return fail(cx);
66 }
67 awjcf.emplace(result, bytesNeeded);
68 if (!awjcf->makeWritable()) {
69 return fail(cx);
70 }
71 code->copyFrom(masm);
72 masm.link(code);
73 if (masm.embedsNurseryPointers()) {
74 cx->runtime()->gc.storeBuffer().putWholeCell(code);
75 }
76 return code;
77 }
78
79 } // namespace jit
80 } // namespace js
81