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