]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/LinkBuffer.h
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / assembler / LinkBuffer.h
index b48c7e9261258af7c5e29ccf97f2eac06b3e0ab5..516e4568c8074d557d9b2e00188ce09d67d8703c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2010, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #define GLOBAL_THUNK_ID reinterpret_cast<void*>(static_cast<intptr_t>(-1))
 #define REGEXP_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-2))
+#define CSS_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-3))
 
 #include "JITCompilationEffort.h"
 #include "MacroAssembler.h"
 #include <wtf/DataLog.h>
+#include <wtf/FastMalloc.h>
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
 
+class CodeBlock;
 class VM;
 
 // LinkBuffer:
@@ -58,7 +61,8 @@ class VM;
 //   * The value referenced by a DataLabel may be set.
 //
 class LinkBuffer {
-    WTF_MAKE_NONCOPYABLE(LinkBuffer);
+    WTF_MAKE_NONCOPYABLE(LinkBuffer); WTF_MAKE_FAST_ALLOCATED;
+    
     typedef MacroAssemblerCodeRef CodeRef;
     typedef MacroAssemblerCodePtr CodePtr;
     typedef MacroAssembler::Label Label;
@@ -76,30 +80,43 @@ class LinkBuffer {
 #endif
 
 public:
-    LinkBuffer(VM& vm, MacroAssembler* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed)
+    LinkBuffer(VM& vm, MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed)
         : m_size(0)
 #if ENABLE(BRANCH_COMPACTION)
         , m_initialSize(0)
 #endif
+        , m_didAllocate(false)
         , m_code(0)
-        , m_assembler(masm)
         , m_vm(&vm)
 #ifndef NDEBUG
         , m_completed(false)
-        , m_effort(effort)
 #endif
     {
-        linkCode(ownerUID, effort);
+        linkCode(macroAssembler, ownerUID, effort);
+    }
+
+    LinkBuffer(VM& vm, MacroAssembler& macroAssembler, void* code, size_t size)
+        : m_size(size)
+#if ENABLE(BRANCH_COMPACTION)
+        , m_initialSize(0)
+#endif
+        , m_didAllocate(false)
+        , m_code(code)
+        , m_vm(&vm)
+#ifndef NDEBUG
+        , m_completed(false)
+#endif
+    {
+        linkCode(macroAssembler, 0, JITCompilationCanFail);
     }
 
     ~LinkBuffer()
     {
-        ASSERT(m_completed || (!m_executableMemory && m_effort == JITCompilationCanFail));
     }
     
     bool didFailToAllocate() const
     {
-        return !m_executableMemory;
+        return !m_didAllocate;
     }
 
     bool isValid() const
@@ -116,6 +133,11 @@ public:
         MacroAssembler::linkCall(code(), call, function);
     }
     
+    void link(Call call, CodeLocationLabel label)
+    {
+        link(call, FunctionPtr(label.executableAddress()));
+    }
+    
     void link(Jump jump, CodeLocationLabel label)
     {
         jump.m_label = applyOffset(jump.m_label);
@@ -141,6 +163,11 @@ public:
     }
 
     // These methods are used to obtain handles to allow the code to be relinked / repatched later.
+    
+    CodeLocationLabel entrypoint()
+    {
+        return CodeLocationLabel(code());
+    }
 
     CodeLocationCall locationOf(Call call)
     {
@@ -199,13 +226,18 @@ public:
         return applyOffset(label.m_label).m_offset;
     }
 
+    unsigned offsetOf(PatchableJump jump)
+    {
+        return applyOffset(jump.m_jump.m_label).m_offset;
+    }
+
     // Upon completion of all patching 'FINALIZE_CODE()' should be called once to
     // complete generation of the code. Alternatively, call
     // finalizeCodeWithoutDisassembly() directly if you have your own way of
     // displaying disassembly.
     
-    CodeRef finalizeCodeWithoutDisassembly();
-    CodeRef finalizeCodeWithDisassembly(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
+    JS_EXPORT_PRIVATE CodeRef finalizeCodeWithoutDisassembly();
+    JS_EXPORT_PRIVATE CodeRef finalizeCodeWithDisassembly(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
 
     CodePtr trampolineAt(Label label)
     {
@@ -216,17 +248,27 @@ public:
     {
         return m_code;
     }
-    
-    size_t debugSize()
+
+    // FIXME: this does not account for the AssemblerData size!
+    size_t size()
     {
         return m_size;
     }
 
 private:
+#if ENABLE(BRANCH_COMPACTION)
+    int executableOffsetFor(int location)
+    {
+        if (!location)
+            return 0;
+        return bitwise_cast<int32_t*>(m_assemblerStorage.buffer())[location / sizeof(int32_t) - 1];
+    }
+#endif
+    
     template <typename T> T applyOffset(T src)
     {
 #if ENABLE(BRANCH_COMPACTION)
-        src.m_offset -= m_assembler->executableOffsetFor(src.m_offset);
+        src.m_offset -= executableOffsetFor(src.m_offset);
 #endif
         return src;
     }
@@ -236,11 +278,14 @@ private:
     {
         return m_code;
     }
+    
+    void allocate(size_t initialSize, void* ownerUID, JITCompilationEffort);
+    void shrink(size_t newSize);
 
-    void linkCode(void* ownerUID, JITCompilationEffort);
+    JS_EXPORT_PRIVATE void linkCode(MacroAssembler&, void* ownerUID, JITCompilationEffort);
 #if ENABLE(BRANCH_COMPACTION)
     template <typename InstructionType>
-    void copyCompactAndLinkCode(void* ownerUID, JITCompilationEffort);
+    void copyCompactAndLinkCode(MacroAssembler&, void* ownerUID, JITCompilationEffort);
 #endif
 
     void performFinalization();
@@ -257,13 +302,13 @@ private:
     size_t m_size;
 #if ENABLE(BRANCH_COMPACTION)
     size_t m_initialSize;
+    AssemblerData m_assemblerStorage;
 #endif
+    bool m_didAllocate;
     void* m_code;
-    MacroAssembler* m_assembler;
     VM* m_vm;
 #ifndef NDEBUG
     bool m_completed;
-    JITCompilationEffort m_effort;
 #endif
 };
 
@@ -272,6 +317,11 @@ private:
      ? ((linkBufferReference).finalizeCodeWithDisassembly dataLogFArgumentsForHeading) \
      : (linkBufferReference).finalizeCodeWithoutDisassembly())
 
+bool shouldShowDisassemblyFor(CodeBlock*);
+
+#define FINALIZE_CODE_FOR(codeBlock, linkBufferReference, dataLogFArgumentsForHeading)  \
+    FINALIZE_CODE_IF(shouldShowDisassemblyFor(codeBlock), linkBufferReference, dataLogFArgumentsForHeading)
+
 // Use this to finalize code, like so:
 //
 // CodeRef code = FINALIZE_CODE(linkBuffer, ("my super thingy number %d", number));
@@ -289,10 +339,10 @@ private:
 // is true, so you can hide expensive disassembly-only computations inside there.
 
 #define FINALIZE_CODE(linkBufferReference, dataLogFArgumentsForHeading)  \
-    FINALIZE_CODE_IF(Options::showDisassembly(), linkBufferReference, dataLogFArgumentsForHeading)
+    FINALIZE_CODE_IF(JSC::Options::showDisassembly(), linkBufferReference, dataLogFArgumentsForHeading)
 
 #define FINALIZE_DFG_CODE(linkBufferReference, dataLogFArgumentsForHeading)  \
-    FINALIZE_CODE_IF((Options::showDisassembly() || Options::showDFGDisassembly()), linkBufferReference, dataLogFArgumentsForHeading)
+    FINALIZE_CODE_IF((JSC::Options::showDisassembly() || Options::showDFGDisassembly()), linkBufferReference, dataLogFArgumentsForHeading)
 
 } // namespace JSC