michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jit_IonLinker_h michael@0: #define jit_IonLinker_h michael@0: michael@0: #include "jscntxt.h" michael@0: #include "jscompartment.h" michael@0: #include "jsgc.h" michael@0: michael@0: #include "assembler/jit/ExecutableAllocator.h" michael@0: #include "jit/IonCode.h" michael@0: #include "jit/IonMacroAssembler.h" michael@0: #include "jit/JitCompartment.h" michael@0: michael@0: namespace js { michael@0: namespace jit { michael@0: michael@0: class Linker michael@0: { michael@0: MacroAssembler &masm; michael@0: michael@0: JitCode *fail(JSContext *cx) { michael@0: js_ReportOutOfMemory(cx); michael@0: return nullptr; michael@0: } michael@0: michael@0: template michael@0: JitCode *newCode(JSContext *cx, JSC::ExecutableAllocator *execAlloc, JSC::CodeKind kind) { michael@0: JS_ASSERT(kind == JSC::ION_CODE || michael@0: kind == JSC::BASELINE_CODE || michael@0: kind == JSC::OTHER_CODE); michael@0: JS_ASSERT(masm.numAsmJSAbsoluteLinks() == 0); michael@0: michael@0: gc::AutoSuppressGC suppressGC(cx); michael@0: if (masm.oom()) michael@0: return fail(cx); michael@0: michael@0: JSC::ExecutablePool *pool; michael@0: size_t bytesNeeded = masm.bytesNeeded() + sizeof(JitCode *) + CodeAlignment; michael@0: if (bytesNeeded >= MAX_BUFFER_SIZE) michael@0: return fail(cx); michael@0: michael@0: // ExecutableAllocator requires bytesNeeded to be word-size aligned. michael@0: bytesNeeded = AlignBytes(bytesNeeded, sizeof(void *)); michael@0: michael@0: uint8_t *result = (uint8_t *)execAlloc->alloc(bytesNeeded, &pool, kind); michael@0: if (!result) michael@0: return fail(cx); michael@0: michael@0: // The JitCode pointer will be stored right before the code buffer. michael@0: uint8_t *codeStart = result + sizeof(JitCode *); michael@0: michael@0: // Bump the code up to a nice alignment. michael@0: codeStart = (uint8_t *)AlignBytes((uintptr_t)codeStart, CodeAlignment); michael@0: uint32_t headerSize = codeStart - result; michael@0: JitCode *code = JitCode::New(cx, codeStart, bytesNeeded - headerSize, michael@0: headerSize, pool, kind); michael@0: if (!code) michael@0: return nullptr; michael@0: if (masm.oom()) michael@0: return fail(cx); michael@0: code->copyFrom(masm); michael@0: masm.link(code); michael@0: #ifdef JSGC_GENERATIONAL michael@0: if (masm.embedsNurseryPointers()) michael@0: cx->runtime()->gcStoreBuffer.putWholeCell(code); michael@0: #endif michael@0: return code; michael@0: } michael@0: michael@0: public: michael@0: Linker(MacroAssembler &masm) michael@0: : masm(masm) michael@0: { michael@0: masm.finish(); michael@0: } michael@0: michael@0: template michael@0: JitCode *newCode(JSContext *cx, JSC::CodeKind kind) { michael@0: return newCode(cx, cx->runtime()->jitRuntime()->execAlloc(), kind); michael@0: } michael@0: michael@0: JitCode *newCodeForIonScript(JSContext *cx) { michael@0: #ifdef JS_CODEGEN_ARM michael@0: // ARM does not yet use implicit interrupt checks, see bug 864220. michael@0: return newCode(cx, JSC::ION_CODE); michael@0: #else michael@0: // The caller must lock the runtime against interrupt requests, as the michael@0: // thread requesting an interrupt may use the executable allocator below. michael@0: JS_ASSERT(cx->runtime()->currentThreadOwnsInterruptLock()); michael@0: michael@0: JSC::ExecutableAllocator *alloc = cx->runtime()->jitRuntime()->getIonAlloc(cx); michael@0: if (!alloc) michael@0: return nullptr; michael@0: michael@0: return newCode(cx, alloc, JSC::ION_CODE); michael@0: #endif michael@0: } michael@0: }; michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif /* jit_IonLinker_h */