/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#ifndef MacroAssemblerCodeRef_h
#define MacroAssemblerCodeRef_h
+#include "Disassembler.h"
#include "ExecutableAllocator.h"
+#include "LLIntData.h"
+#include <wtf/DataLog.h>
#include <wtf/PassRefPtr.h>
+#include <wtf/PrintStream.h>
#include <wtf/RefPtr.h>
-#include <wtf/UnusedParam.h>
// ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
// instruction address on the platform (for example, check any alignment requirements).
-#if CPU(ARM_THUMB2)
-// ARM/thumb instructions must be 16-bit aligned, but all code pointers to be loaded
-// into the processor are decorated with the bottom bit set, indicating that this is
-// thumb code (as oposed to 32-bit traditional ARM). The first test checks for both
-// decorated and undectorated null, and the second test ensures that the pointer is
-// decorated.
+#if CPU(ARM_THUMB2) && ENABLE(JIT)
+// ARM instructions must be 16-bit aligned. Thumb2 code pointers to be loaded into
+// into the processor are decorated with the bottom bit set, while traditional ARM has
+// the lower bit clear. Since we don't know what kind of pointer, we check for both
+// decorated and undecorated null.
#define ASSERT_VALID_CODE_POINTER(ptr) \
- ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1); \
- ASSERT(reinterpret_cast<intptr_t>(ptr) & 1)
+ ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1)
#define ASSERT_VALID_CODE_OFFSET(offset) \
ASSERT(!(offset & 1)) // Must be multiple of 2.
#else
ASSERT_VALID_CODE_POINTER(m_value);
}
+ template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4, typename argType5>
+ FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4, argType5))
+ : m_value((void*)value)
+ {
+ ASSERT_VALID_CODE_POINTER(m_value);
+ }
+
+ template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4, typename argType5, typename argType6>
+ FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4, argType5, argType6))
+ : m_value((void*)value)
+ {
+ ASSERT_VALID_CODE_POINTER(m_value);
+ }
// MSVC doesn't seem to treat functions with different calling conventions as
// different types; these methods already defined for fastcall, below.
#if CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS)
}
void* value() const { return m_value; }
+
+ void dump(PrintStream& out) const
+ {
+ out.print(RawPointer(m_value));
+ }
private:
void* m_value;
return result;
}
- static MacroAssemblerCodePtr createLLIntCodePtr(void (*function)())
+ static MacroAssemblerCodePtr createLLIntCodePtr(OpcodeID codeId)
{
- return createFromExecutableAddress(bitwise_cast<void*>(function));
+ return createFromExecutableAddress(LLInt::getCodePtr(codeId));
}
+
explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
: m_value(ra.value())
{
void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
#endif
- bool operator!() const
+ explicit operator bool() const { return m_value; }
+
+ bool operator==(const MacroAssemblerCodePtr& other) const
+ {
+ return m_value == other.m_value;
+ }
+
+ void dumpWithName(const char* name, PrintStream& out) const
+ {
+ if (executableAddress() == dataLocation()) {
+ out.print(name, "(", RawPointer(executableAddress()), ")");
+ return;
+ }
+ out.print(name, "(executable = ", RawPointer(executableAddress()), ", dataLocation = ", RawPointer(dataLocation()), ")");
+ }
+
+ void dump(PrintStream& out) const
+ {
+ dumpWithName("CodePtr", out);
+ }
+
+ enum EmptyValueTag { EmptyValue };
+ enum DeletedValueTag { DeletedValue };
+
+ MacroAssemblerCodePtr(EmptyValueTag)
+ : m_value(emptyValue())
+ {
+ }
+
+ MacroAssemblerCodePtr(DeletedValueTag)
+ : m_value(deletedValue())
{
- return !m_value;
}
+
+ bool isEmptyValue() const { return m_value == emptyValue(); }
+ bool isDeletedValue() const { return m_value == deletedValue(); }
+
+ unsigned hash() const { return PtrHash<void*>::hash(m_value); }
private:
+ static void* emptyValue() { return bitwise_cast<void*>(static_cast<intptr_t>(1)); }
+ static void* deletedValue() { return bitwise_cast<void*>(static_cast<intptr_t>(2)); }
+
void* m_value;
};
+struct MacroAssemblerCodePtrHash {
+ static unsigned hash(const MacroAssemblerCodePtr& ptr) { return ptr.hash(); }
+ static bool equal(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b)
+ {
+ return a == b;
+ }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
// MacroAssemblerCodeRef:
//
// A reference to a section of JIT generated code. A CodeRef consists of a
}
// Helper for creating self-managed code refs from LLInt.
- static MacroAssemblerCodeRef createLLIntCodeRef(void (*function)())
+ static MacroAssemblerCodeRef createLLIntCodeRef(OpcodeID codeId)
{
- return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(bitwise_cast<void*>(function)));
+ return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(codeId)));
}
-
+
ExecutableMemoryHandle* executableMemory() const
{
return m_executableMemory.get();
return m_executableMemory->sizeInBytes();
}
- bool operator!() const { return !m_codePtr; }
+ bool tryToDisassemble(const char* prefix) const
+ {
+ return JSC::tryToDisassemble(m_codePtr, size(), prefix, WTF::dataFile());
+ }
+
+ explicit operator bool() const { return !!m_codePtr; }
+
+ void dump(PrintStream& out) const
+ {
+ m_codePtr.dumpWithName("CodeRef", out);
+ }
private:
MacroAssemblerCodePtr m_codePtr;
} // namespace JSC
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::MacroAssemblerCodePtr> {
+ typedef JSC::MacroAssemblerCodePtrHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::MacroAssemblerCodePtr> : public CustomHashTraits<JSC::MacroAssemblerCodePtr> { };
+
+} // namespace WTF
+
#endif // MacroAssemblerCodeRef_h