/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim : set ts = 8 sts = 2 et sw = 2 tw = 80 :
*
* * * * * * BEGIN LICENSE BLOCK * * * * *
* Copyright ( C ) 2008 Apple Inc . All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1 . Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2 . Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC . ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL APPLE INC . OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL ,
* EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO ,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR
* PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* ***** END LICENSE BLOCK ***** */
#ifndef jit_x86_shared_AssemblerBuffer_x86_shared_h
#define jit_x86_shared_AssemblerBuffer_x86_shared_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Likely.h"
#include "mozilla/Vector.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include "jit/JitContext.h"
#include "jit/JitSpewer.h"
#include "jit/ProcessExecutableMemory.h"
#include "js/AllocPolicy.h"
#include "js/Vector.h"
// Spew formatting helpers.
#define PRETTYHEX(x) \
(((x) < 0 ) ? "-" : "" ), \
((unsigned )((x) ^ ((x) >> 31 )) + ((unsigned )(x) >> 31 ))
#define MEM_o "%s0x%x"
#define MEM_os MEM_o "(,%s,%d)"
#define MEM_ob MEM_o "(%s)"
#define MEM_obs MEM_o "(%s,%s,%d)"
#define MEM_o32 "%s0x%04x"
#define MEM_o32s MEM_o32 "(,%s,%d)"
#define MEM_o32b MEM_o32 "(%s)"
#define MEM_o32bs MEM_o32 "(%s,%s,%d)"
#define MEM_o32r ".Lfrom%d(%%rip)"
#define ADDR_o(offset) PRETTYHEX(offset)
#define ADDR_os(offset, index, scale) \
ADDR_o(offset), GPRegName((index)), (1 << (scale))
#define ADDR_ob(offset, base) ADDR_o(offset), GPRegName((base))
#define ADDR_obs(offset, base, index, scale) \
ADDR_ob(offset, base), GPRegName((index)), (1 << (scale))
#define ADDR_o32(offset) ADDR_o(offset)
#define ADDR_o32s(offset, index, scale) ADDR_os(offset, index, scale)
#define ADDR_o32b(offset, base) ADDR_ob(offset, base)
#define ADDR_o32bs(offset, base, index, scale) \
ADDR_obs(offset, base, index, scale)
#define ADDR_o32r(offset) (offset)
namespace js {
class JS_PUBLIC_API Sprinter;
namespace jit {
namespace x86_shared {
// AllocPolicy for AssemblerBuffer. OOMs when trying to allocate more than
// MaxCodeBytesPerProcess bytes. Use private inheritance to make sure we
// explicitly have to expose SystemAllocPolicy methods.
class AssemblerBufferAllocPolicy : private SystemAllocPolicy {
public :
using SystemAllocPolicy::checkSimulatedOOM;
using SystemAllocPolicy::free_;
using SystemAllocPolicy::reportAllocOverflow;
template <typename T>
T* pod_realloc(T* p, size_t oldSize, size_t newSize) {
static_assert(
sizeof (T) == 1 ,
"AssemblerBufferAllocPolicy should only be used with byte vectors" );
MOZ_ASSERT(oldSize <= MaxCodeBytesPerProcess);
if (MOZ_UNLIKELY(newSize > MaxCodeBytesPerProcess)) {
return nullptr;
}
return SystemAllocPolicy::pod_realloc<T>(p, oldSize, newSize);
}
template <typename T>
T* pod_malloc(size_t numElems) {
static_assert(
sizeof (T) == 1 ,
"AssemblerBufferAllocPolicy should only be used with byte vectors" );
if (MOZ_UNLIKELY(numElems > MaxCodeBytesPerProcess)) {
return nullptr;
}
return SystemAllocPolicy::pod_malloc<T>(numElems);
}
};
class AssemblerBuffer {
template <size_t size, typename T>
MOZ_ALWAYS_INLINE void sizedAppendUnchecked(T value) {
m_buffer.infallibleAppend(reinterpret_cast <unsigned char *>(&value), size);
}
template <size_t size, typename T>
MOZ_ALWAYS_INLINE void sizedAppend(T value) {
if (MOZ_UNLIKELY(
!m_buffer.append(reinterpret_cast <unsigned char *>(&value), size))) {
oomDetected();
}
}
public :
AssemblerBuffer() : m_oom(false ) {}
void ensureSpace(size_t space) {
// This should only be called with small |space| values to ensure
// we don't overflow below.
MOZ_ASSERT(space <= 16 );
if (MOZ_UNLIKELY(!m_buffer.reserve(m_buffer.length() + space))) {
oomDetected();
}
}
bool isAligned(size_t alignment) const {
return !(m_buffer.length() & (alignment - 1 ));
}
MOZ_ALWAYS_INLINE void putByteUnchecked(int value) {
sizedAppendUnchecked<1 >(value);
}
MOZ_ALWAYS_INLINE void putShortUnchecked(int value) {
sizedAppendUnchecked<2 >(value);
}
MOZ_ALWAYS_INLINE void putIntUnchecked(int value) {
sizedAppendUnchecked<4 >(value);
}
MOZ_ALWAYS_INLINE void putInt64Unchecked(int64_t value) {
sizedAppendUnchecked<8 >(value);
}
MOZ_ALWAYS_INLINE void putByte(int value) { sizedAppend<1 >(value); }
MOZ_ALWAYS_INLINE void putShort(int value) { sizedAppend<2 >(value); }
MOZ_ALWAYS_INLINE void putInt(int value) { sizedAppend<4 >(value); }
MOZ_ALWAYS_INLINE void putInt64(int64_t value) { sizedAppend<8 >(value); }
[[nodiscard]] bool append(const unsigned char * values, size_t size) {
if (MOZ_UNLIKELY(!m_buffer.append(values, size))) {
oomDetected();
return false ;
}
return true ;
}
size_t size() const { return m_buffer.length(); }
bool oom() const { return m_oom; }
bool reserve(size_t size) { return !m_oom && m_buffer.reserve(size); }
bool swap(Vector<uint8_t, 0 , SystemAllocPolicy>& bytes);
const unsigned char * buffer() const {
MOZ_RELEASE_ASSERT(!m_oom);
return m_buffer.begin();
}
unsigned char * data() { return m_buffer.begin(); }
protected :
/*
* OOM handling : This class can OOM in the ensureSpace ( ) method trying
* to allocate a new buffer . In response to an OOM , we need to avoid
* crashing and report the error . We also want to make it so that
* users of this class need to check for OOM only at certain points
* and not after every operation .
*
* Our strategy for handling an OOM is to set m_oom , and then clear ( but
* not free ) m_buffer , preserving the current buffer . This way , the user
* can continue assembling into the buffer , deferring OOM checking
* until the user wants to read code out of the buffer .
*
* See also the | buffer | method .
*/
void oomDetected() {
m_oom = true ;
m_buffer.clear();
#ifdef DEBUG
JitContext* context = MaybeGetJitContext();
if (context) {
context->setOOM();
}
#endif
}
mozilla::Vector<unsigned char , 256 , AssemblerBufferAllocPolicy> m_buffer;
bool m_oom;
};
} // namespace x86_shared
class GenericAssembler {
#ifdef JS_JITSPEW
Sprinter* printer;
#endif
public :
GenericAssembler()
#ifdef JS_JITSPEW
: printer(nullptr)
#endif
{
}
void setPrinter(Sprinter* sp) {
#ifdef JS_JITSPEW
printer = sp;
#endif
}
#ifdef JS_JITSPEW
inline void spew(const char * fmt, ...) MOZ_FORMAT_PRINTF(2 , 3 ) {
if (MOZ_UNLIKELY(printer || JitSpewEnabled(JitSpew_Codegen))) {
va_list va;
va_start(va, fmt);
spew(fmt, va);
va_end(va);
}
}
#else
MOZ_ALWAYS_INLINE void spew(const char * fmt, ...) MOZ_FORMAT_PRINTF(2 , 3 ) {}
#endif
#ifdef JS_JITSPEW
MOZ_COLD void spew(const char * fmt, va_list va) MOZ_FORMAT_PRINTF(2 , 0 );
#endif
};
} // namespace jit
} // namespace js
#endif /* jit_x86_shared_AssemblerBuffer_x86_shared_h */
Messung V0.5 in Prozent C=96 H=100 G=97
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland