]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/MacroAssemblerCodeRef.h
JavaScriptCore-7600.1.4.15.12.tar.gz
[apple/javascriptcore.git] / assembler / MacroAssemblerCodeRef.h
index 341a7ff338e51011c0dc8afd0ae1e96ef55ffc23..57951262d9a25d26c8f24c1f0e2dace25b36b657 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * 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
  *
  * 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
 
 #ifndef MacroAssemblerCodeRef_h
 #define MacroAssemblerCodeRef_h
 
-#include <wtf/Platform.h>
-
+#include "Disassembler.h"
 #include "ExecutableAllocator.h"
 #include "ExecutableAllocator.h"
-#include "PassRefPtr.h"
-#include "RefPtr.h"
-#include "UnusedParam.h"
-
-#if ENABLE(ASSEMBLER)
+#include "LLIntData.h"
+#include <wtf/DataLog.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/PrintStream.h>
+#include <wtf/RefPtr.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).
 
 // 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 PLATFORM_ARM_ARCH(7)
-// 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) \
 #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
 #define ASSERT_VALID_CODE_OFFSET(offset) \
     ASSERT(!(offset & 1)) // Must be multiple of 2.
 #else
 #define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes!
 #endif
 
 #define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes!
 #endif
 
+#if CPU(X86) && OS(WINDOWS)
+#define CALLING_CONVENTION_IS_STDCALL 1
+#ifndef CDECL
+#if COMPILER(MSVC)
+#define CDECL __cdecl
+#else
+#define CDECL __attribute__ ((__cdecl))
+#endif // COMPILER(MSVC)
+#endif // CDECL
+#else
+#define CALLING_CONVENTION_IS_STDCALL 0
+#endif
+
+#if CPU(X86)
+#define HAS_FASTCALL_CALLING_CONVENTION 1
+#ifndef FASTCALL
+#if COMPILER(MSVC)
+#define FASTCALL __fastcall
+#else
+#define FASTCALL  __attribute__ ((fastcall))
+#endif // COMPILER(MSVC)
+#endif // FASTCALL
+#else
+#define HAS_FASTCALL_CALLING_CONVENTION 0
+#endif // CPU(X86)
+
 namespace JSC {
 
 // FunctionPtr:
 namespace JSC {
 
 // FunctionPtr:
@@ -67,9 +90,132 @@ public:
     {
     }
 
     {
     }
 
+    template<typename returnType>
+    FunctionPtr(returnType(*value)())
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1>
+    FunctionPtr(returnType(*value)(argType1))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2>
+    FunctionPtr(returnType(*value)(argType1, argType2))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3>
+    FunctionPtr(returnType(*value)(argType1, argType2, argType3))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4>
+    FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4))
+        : m_value((void*)value)
+    {
+        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);
+    }
+
+// 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)
+
+    template<typename returnType>
+    FunctionPtr(returnType (CDECL *value)())
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1>
+    FunctionPtr(returnType (CDECL *value)(argType1))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2>
+    FunctionPtr(returnType (CDECL *value)(argType1, argType2))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3>
+    FunctionPtr(returnType (CDECL *value)(argType1, argType2, argType3))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4>
+    FunctionPtr(returnType (CDECL *value)(argType1, argType2, argType3, argType4))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+#endif
+
+#if HAS_FASTCALL_CALLING_CONVENTION
+
+    template<typename returnType>
+    FunctionPtr(returnType (FASTCALL *value)())
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1>
+    FunctionPtr(returnType (FASTCALL *value)(argType1))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2>
+    FunctionPtr(returnType (FASTCALL *value)(argType1, argType2))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3>
+    FunctionPtr(returnType (FASTCALL *value)(argType1, argType2, argType3))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4>
+    FunctionPtr(returnType (FASTCALL *value)(argType1, argType2, argType3, argType4))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+#endif
+
     template<typename FunctionType>
     explicit FunctionPtr(FunctionType* value)
     template<typename FunctionType>
     explicit FunctionPtr(FunctionType* value)
-        : m_value(reinterpret_cast<void*>(value))
+        // Using a C-ctyle cast here to avoid compiler error on RVTC:
+        // Error:  #694: reinterpret_cast cannot cast away const or other type qualifiers
+        // (I guess on RVTC function pointers have a different constness to GCC/MSVC?)
+        : m_value((void*)value)
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
@@ -108,6 +254,11 @@ public:
     }
 
     void* value() const { return m_value; }
     }
 
     void* value() const { return m_value; }
+    
+    void dump(PrintStream& out) const
+    {
+        out.print(RawPointer(m_value));
+    }
 
 private:
     void* m_value;
 
 private:
     void* m_value;
@@ -124,7 +275,7 @@ public:
     }
 
     explicit MacroAssemblerCodePtr(void* value)
     }
 
     explicit MacroAssemblerCodePtr(void* value)
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM_THUMB2)
         // Decorate the pointer as a thumb code pointer.
         : m_value(reinterpret_cast<char*>(value) + 1)
 #else
         // Decorate the pointer as a thumb code pointer.
         : m_value(reinterpret_cast<char*>(value) + 1)
 #else
@@ -133,6 +284,19 @@ public:
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
+    
+    static MacroAssemblerCodePtr createFromExecutableAddress(void* value)
+    {
+        ASSERT_VALID_CODE_POINTER(value);
+        MacroAssemblerCodePtr result;
+        result.m_value = value;
+        return result;
+    }
+
+    static MacroAssemblerCodePtr createLLIntCodePtr(OpcodeID codeId)
+    {
+        return createFromExecutableAddress(LLInt::getCodePtr(codeId));
+    }
 
     explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
         : m_value(ra.value())
 
     explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
         : m_value(ra.value())
@@ -141,48 +305,165 @@ public:
     }
 
     void* executableAddress() const { return m_value; }
     }
 
     void* executableAddress() const { return m_value; }
-#if PLATFORM_ARM_ARCH(7)
+#if CPU(ARM_THUMB2)
     // To use this pointer as a data address remove the decoration.
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast<char*>(m_value) - 1; }
 #else
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
 #endif
 
     // To use this pointer as a data address remove the decoration.
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast<char*>(m_value) - 1; }
 #else
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
 #endif
 
-    bool operator!()
+    typedef void* (MacroAssemblerCodePtr::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const
+    {
+        return !!m_value ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0;
+    }
+    
+    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:
 
 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;
 };
 
     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
 // pointer to the code, and a ref pointer to the pool from within which it
 // was allocated.
 class MacroAssemblerCodeRef {
 // MacroAssemblerCodeRef:
 //
 // A reference to a section of JIT generated code.  A CodeRef consists of a
 // pointer to the code, and a ref pointer to the pool from within which it
 // was allocated.
 class MacroAssemblerCodeRef {
+private:
+    // This is private because it's dangerous enough that we want uses of it
+    // to be easy to find - hence the static create method below.
+    explicit MacroAssemblerCodeRef(MacroAssemblerCodePtr codePtr)
+        : m_codePtr(codePtr)
+    {
+        ASSERT(m_codePtr);
+    }
+
 public:
     MacroAssemblerCodeRef()
 public:
     MacroAssemblerCodeRef()
-        : m_size(0)
     {
     }
 
     {
     }
 
-    MacroAssemblerCodeRef(void* code, PassRefPtr<ExecutablePool> executablePool, size_t size)
-        : m_code(code)
-        , m_executablePool(executablePool)
-        , m_size(size)
+    MacroAssemblerCodeRef(PassRefPtr<ExecutableMemoryHandle> executableMemory)
+        : m_codePtr(executableMemory->start())
+        , m_executableMemory(executableMemory)
+    {
+        ASSERT(m_executableMemory->isManaged());
+        ASSERT(m_executableMemory->start());
+        ASSERT(m_codePtr);
+    }
+    
+    // Use this only when you know that the codePtr refers to code that is
+    // already being kept alive through some other means. Typically this means
+    // that codePtr is immortal.
+    static MacroAssemblerCodeRef createSelfManagedCodeRef(MacroAssemblerCodePtr codePtr)
+    {
+        return MacroAssemblerCodeRef(codePtr);
+    }
+    
+    // Helper for creating self-managed code refs from LLInt.
+    static MacroAssemblerCodeRef createLLIntCodeRef(OpcodeID codeId)
     {
     {
+        return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(codeId)));
     }
 
     }
 
-    MacroAssemblerCodePtr m_code;
-    RefPtr<ExecutablePool> m_executablePool;
-    size_t m_size;
+    ExecutableMemoryHandle* executableMemory() const
+    {
+        return m_executableMemory.get();
+    }
+    
+    MacroAssemblerCodePtr code() const
+    {
+        return m_codePtr;
+    }
+    
+    size_t size() const
+    {
+        if (!m_executableMemory)
+            return 0;
+        return m_executableMemory->sizeInBytes();
+    }
+    
+    bool tryToDisassemble(const char* prefix) const
+    {
+        return JSC::tryToDisassemble(m_codePtr, size(), prefix, WTF::dataFile());
+    }
+    
+    typedef void* (MacroAssemblerCodeRef::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const
+    {
+        return !!m_codePtr ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0;
+    }
+    
+    void dump(PrintStream& out) const
+    {
+        m_codePtr.dumpWithName("CodeRef", out);
+    }
+
+private:
+    MacroAssemblerCodePtr m_codePtr;
+    RefPtr<ExecutableMemoryHandle> m_executableMemory;
 };
 
 } // namespace JSC
 
 };
 
 } // namespace JSC
 
-#endif // ENABLE(ASSEMBLER)
+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
 
 #endif // MacroAssemblerCodeRef_h