#ifndef AbstractMacroAssembler_h
#define AbstractMacroAssembler_h
-#include <wtf/Platform.h>
-
-#include <MacroAssemblerCodeRef.h>
-#include <CodeLocation.h>
+#include "CodeLocation.h"
+#include "MacroAssemblerCodeRef.h"
#include <wtf/Noncopyable.h>
#include <wtf/UnusedParam.h>
template <class AssemblerType>
class AbstractMacroAssembler {
public:
+ friend class JITWriteBarrierBase;
typedef AssemblerType AssemblerType_T;
typedef MacroAssemblerCodePtr CodePtr;
class Jump;
typedef typename AssemblerType::RegisterID RegisterID;
- typedef typename AssemblerType::FPRegisterID FPRegisterID;
- typedef typename AssemblerType::JmpSrc JmpSrc;
- typedef typename AssemblerType::JmpDst JmpDst;
-
// Section 1: MacroAssembler operand types
//
int32_t offset;
};
+ struct ExtendedAddress {
+ explicit ExtendedAddress(RegisterID base, intptr_t offset = 0)
+ : base(base)
+ , offset(offset)
+ {
+ }
+
+ RegisterID base;
+ intptr_t offset;
+ };
+
// ImplicitAddress:
//
// This class is used for explicit 'load' and 'store' operations
// Describes an memory operand given by a pointer. For regular load & store
// operations an unwrapped void* will be used, rather than using this.
struct AbsoluteAddress {
- explicit AbsoluteAddress(void* ptr)
+ explicit AbsoluteAddress(const void* ptr)
: m_ptr(ptr)
{
}
- void* m_ptr;
+ const void* m_ptr;
};
- // ImmPtr:
+ // TrustedImmPtr:
//
// A pointer sized immediate operand to an instruction - this is wrapped
// in a class requiring explicit construction in order to differentiate
// from pointers used as absolute addresses to memory operations
- struct ImmPtr {
- explicit ImmPtr(void* value)
+ struct TrustedImmPtr {
+ explicit TrustedImmPtr(const void* value)
: m_value(value)
{
}
return reinterpret_cast<intptr_t>(m_value);
}
- void* m_value;
+ const void* m_value;
+ };
+
+ struct ImmPtr : public TrustedImmPtr {
+ explicit ImmPtr(const void* value)
+ : TrustedImmPtr(value)
+ {
+ }
};
- // Imm32:
+ // TrustedImm32:
//
// A 32bit immediate operand to an instruction - this is wrapped in a
// class requiring explicit construction in order to prevent RegisterIDs
// (which are implemented as an enum) from accidentally being passed as
// immediate values.
- struct Imm32 {
- explicit Imm32(int32_t value)
+ struct TrustedImm32 {
+ explicit TrustedImm32(int32_t value)
: m_value(value)
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM) || CPU(MIPS)
, m_isPointer(false)
#endif
{
}
-#if !PLATFORM(X86_64)
- explicit Imm32(ImmPtr ptr)
+#if !CPU(X86_64)
+ explicit TrustedImm32(TrustedImmPtr ptr)
: m_value(ptr.asIntptr())
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM) || CPU(MIPS)
, m_isPointer(true)
#endif
{
#endif
int32_t m_value;
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM) || CPU(MIPS)
// We rely on being able to regenerate code to recover exception handling
// information. Since ARMv7 supports 16-bit immediates there is a danger
// that if pointer values change the layout of the generated code will change.
// To avoid this problem, always generate pointers (and thus Imm32s constructed
// from ImmPtrs) with a code sequence that is able to represent any pointer
// value - don't use a more compact form in these cases.
+ // Same for MIPS.
bool m_isPointer;
#endif
};
+ struct Imm32 : public TrustedImm32 {
+ explicit Imm32(int32_t value)
+ : TrustedImm32(value)
+ {
+ }
+#if !CPU(X86_64)
+ explicit Imm32(TrustedImmPtr ptr)
+ : TrustedImm32(ptr)
+ {
+ }
+#endif
+ };
+
// Section 2: MacroAssembler code buffer handles
//
// The following types are used to reference items in the code buffer
{
}
- bool isUsed() const { return m_label.isUsed(); }
- void used() { m_label.used(); }
+ bool isSet() const { return m_label.isSet(); }
private:
- JmpDst m_label;
+ AssemblerLabel m_label;
};
// DataLabelPtr:
{
}
+ bool isSet() const { return m_label.isSet(); }
+
private:
- JmpDst m_label;
+ AssemblerLabel m_label;
};
// DataLabel32:
{
}
+ AssemblerLabel label() const { return m_label; }
+
+ private:
+ AssemblerLabel m_label;
+ };
+
+ // DataLabelCompact:
+ //
+ // A DataLabelCompact is used to refer to a location in the code containing a
+ // compact immediate to be patched after the code has been generated.
+ class DataLabelCompact {
+ template<class TemplateAssemblerType>
+ friend class AbstractMacroAssembler;
+ friend class LinkBuffer;
+ public:
+ DataLabelCompact()
+ {
+ }
+
+ DataLabelCompact(AbstractMacroAssembler<AssemblerType>* masm)
+ : m_label(masm->m_assembler.label())
+ {
+ }
+
+ DataLabelCompact(AssemblerLabel label)
+ : m_label(label)
+ {
+ }
+
private:
- JmpDst m_label;
+ AssemblerLabel m_label;
};
// Call:
{
}
- Call(JmpSrc jmp, Flags flags)
+ Call(AssemblerLabel jmp, Flags flags)
: m_jmp(jmp)
, m_flags(flags)
{
return Call(jump.m_jmp, Linkable);
}
- JmpSrc m_jmp;
-
+ AssemblerLabel m_jmp;
private:
Flags m_flags;
};
{
}
- Jump(JmpSrc jmp)
+#if CPU(ARM_THUMB2)
+ // Fixme: this information should be stored in the instruction stream, not in the Jump object.
+ Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid)
: m_jmp(jmp)
+ , m_type(type)
+ , m_condition(condition)
{
}
-
- void link(AbstractMacroAssembler<AssemblerType>* masm)
+#else
+ Jump(AssemblerLabel jmp)
+ : m_jmp(jmp)
{
+ }
+#endif
+
+ void link(AbstractMacroAssembler<AssemblerType>* masm) const
+ {
+#if CPU(ARM_THUMB2)
+ masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label(), m_type, m_condition);
+#else
masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
+#endif
}
- void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
+ void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const
{
+#if CPU(ARM_THUMB2)
+ masm->m_assembler.linkJump(m_jmp, label.m_label, m_type, m_condition);
+#else
masm->m_assembler.linkJump(m_jmp, label.m_label);
+#endif
}
+ bool isSet() const { return m_jmp.isSet(); }
+
private:
- JmpSrc m_jmp;
+ AssemblerLabel m_jmp;
+#if CPU(ARM_THUMB2)
+ ARMv7Assembler::JumpType m_type;
+ ARMv7Assembler::Condition m_condition;
+#endif
};
// JumpList:
return !m_jumps.size();
}
+ void clear()
+ {
+ m_jumps.clear();
+ }
+
const JumpVector& jumps() { return m_jumps; }
private:
// Section 3: Misc admin methods
-
- static CodePtr trampolineAt(CodeRef ref, Label label)
- {
- return CodePtr(AssemblerType::getRelocatedAddress(ref.m_code.dataLocation(), label.m_label));
- }
-
- size_t size()
- {
- return m_assembler.size();
- }
-
Label label()
{
return Label(this);
{
return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
}
+
+ ptrdiff_t differenceBetween(Label from, DataLabelCompact to)
+ {
+ return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
+ }
ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
{
return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
}
+ // Temporary interface; likely to be removed, since may be hard to port to all architectures.
+#if CPU(X86) || CPU(X86_64)
+ void rewindToLabel(Label rewindTo) { m_assembler.rewindToLabel(rewindTo.m_label); }
+#endif
+
+ void beginUninterruptedSequence() { }
+ void endUninterruptedSequence() { }
+
+#ifndef NDEBUG
+ unsigned debugOffset() { return m_assembler.debugOffset(); }
+#endif
+
protected:
AssemblerType m_assembler;
AssemblerType::linkJump(code, jump.m_jmp, target.dataLocation());
}
- static void linkPointer(void* code, typename AssemblerType::JmpDst label, void* value)
+ static void linkPointer(void* code, AssemblerLabel label, void* value)
{
AssemblerType::linkPointer(code, label, value);
}
- static void* getLinkerAddress(void* code, typename AssemblerType::JmpSrc label)
- {
- return AssemblerType::getRelocatedAddress(code, label);
- }
-
- static void* getLinkerAddress(void* code, typename AssemblerType::JmpDst label)
+ static void* getLinkerAddress(void* code, AssemblerLabel label)
{
return AssemblerType::getRelocatedAddress(code, label);
}
AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
}
+ static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
+ {
+ AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value);
+ }
+
static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
{
AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
{
AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
}
-
- static void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
+
+ static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr)
{
- AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation());
+ return AssemblerType::readPointer(dataLabelPtr.dataLocation());
}
};