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