Add support to the JIT for true non-lazy operation. When a call to a function
[oota-llvm.git] / lib / ExecutionEngine / JIT / JITMemoryManager.cpp
index 0bf42b80994b3ca26f139371063dd99691cbac2a..0dcc71f837c6c526e16c85f498b069fc635550f0 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/GlobalValue.h"
 #include "llvm/ExecutionEngine/JITMemoryManager.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/System/Memory.h"
 #include <map>
 #include <vector>
 #include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
 using namespace llvm;
 
 
@@ -199,6 +203,9 @@ TrimAllocationToSize(FreeRangeHeader *FreeList, uint64_t NewSize) {
   assert(ThisAllocated && getBlockAfter().PrevAllocated &&
          "Cannot deallocate part of an allocated block!");
 
+  // Don't allow blocks to be trimmed below minimum required size
+  NewSize = std::max<uint64_t>(FreeRangeHeader::getMinBlockSize(), NewSize);
+
   // Round up size for alignment of header.
   unsigned HeaderAlign = __alignof(FreeRangeHeader);
   NewSize = (NewSize+ (HeaderAlign-1)) & ~(HeaderAlign-1);
@@ -251,6 +258,7 @@ namespace {
     
     unsigned char *CurStubPtr, *StubBase;
     unsigned char *GOTBase;      // Target Specific reserved memory
+    void *DlsymTable;            // Stub external symbol information
 
     // Centralize memory block allocation.
     sys::MemoryBlock getNewMemoryBlock(unsigned size);
@@ -262,8 +270,10 @@ namespace {
     ~DefaultJITMemoryManager();
 
     void AllocateGOT();
-
-    unsigned char *allocateStub(unsigned StubSize, unsigned Alignment);
+    void SetDlsymTable(void *);
+    
+    unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
+                                unsigned Alignment);
     
     /// startFunctionBody - When a function starts, allocate a block of free
     /// executable memory, returning a pointer to it and its actual size.
@@ -283,17 +293,35 @@ namespace {
       assert(FunctionEnd > FunctionStart);
       assert(FunctionStart == (unsigned char *)(CurBlock+1) &&
              "Mismatched function start/end!");
-      
+
       uintptr_t BlockSize = FunctionEnd - (unsigned char *)CurBlock;
       FunctionBlocks[F] = CurBlock;
 
       // Release the memory at the end of this block that isn't needed.
       FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
     }
-    
+
+    /// allocateSpace - Allocate a memory block of the given size.
+    unsigned char *allocateSpace(intptr_t Size, unsigned Alignment) {
+      CurBlock = FreeMemoryList;
+      FreeMemoryList = FreeMemoryList->AllocateBlock();
+
+      unsigned char *result = (unsigned char *)CurBlock+1;
+
+      if (Alignment == 0) Alignment = 1;
+      result = (unsigned char*)(((intptr_t)result+Alignment-1) &
+               ~(intptr_t)(Alignment-1));
+
+      uintptr_t BlockSize = result + Size - (unsigned char *)CurBlock;
+      FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
+
+      return result;
+    }
+
     /// startExceptionTable - Use startFunctionBody to allocate memory for the 
     /// function's exception table.
-    unsigned char* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
+    unsigned char* startExceptionTable(const Function* F, 
+                                       uintptr_t &ActualSize) {
       return startFunctionBody(F, ActualSize);
     }
 
@@ -317,6 +345,10 @@ namespace {
       return GOTBase;
     }
     
+    void *getDlsymTable() const {
+      return DlsymTable;
+    }
+    
     /// deallocateMemForFunction - Deallocate all memory for the specified
     /// function body.
     void deallocateMemForFunction(const Function *F) {
@@ -357,14 +389,33 @@ namespace {
       // Finally, remove this entry from TableBlocks.
       TableBlocks.erase(I);
     }
+
+    /// setMemoryWritable - When code generation is in progress,
+    /// the code pages may need permissions changed.
+    void setMemoryWritable(void)
+    {
+      for (unsigned i = 0, e = Blocks.size(); i != e; ++i)
+        sys::Memory::setWritable(Blocks[i]);
+    }
+    /// setMemoryExecutable - When code generation is done and we're ready to
+    /// start execution, the code pages may need permissions changed.
+    void setMemoryExecutable(void)
+    {
+      for (unsigned i = 0, e = Blocks.size(); i != e; ++i)
+        sys::Memory::setExecutable(Blocks[i]);
+    }
   };
 }
 
 DefaultJITMemoryManager::DefaultJITMemoryManager() {
   // Allocate a 16M block of memory for functions.
+#if defined(__APPLE__) && defined(__arm__)
+  sys::MemoryBlock MemBlock = getNewMemoryBlock(4 << 20);
+#else
   sys::MemoryBlock MemBlock = getNewMemoryBlock(16 << 20);
+#endif
 
-  unsigned char *MemBase = reinterpret_cast<unsigned char*>(MemBlock.base());
+  unsigned char *MemBase = static_cast<unsigned char*>(MemBlock.base());
 
   // Allocate stubs backwards from the base, allocate functions forward
   // from the base.
@@ -418,6 +469,7 @@ DefaultJITMemoryManager::DefaultJITMemoryManager() {
   FreeMemoryList = Mem0;
 
   GOTBase = NULL;
+  DlsymTable = NULL;
 }
 
 void DefaultJITMemoryManager::AllocateGOT() {
@@ -426,6 +478,9 @@ void DefaultJITMemoryManager::AllocateGOT() {
   HasGOT = true;
 }
 
+void DefaultJITMemoryManager::SetDlsymTable(void *ptr) {
+  DlsymTable = ptr;
+}
 
 DefaultJITMemoryManager::~DefaultJITMemoryManager() {
   for (unsigned i = 0, e = Blocks.size(); i != e; ++i)
@@ -435,7 +490,8 @@ DefaultJITMemoryManager::~DefaultJITMemoryManager() {
   Blocks.clear();
 }
 
-unsigned char *DefaultJITMemoryManager::allocateStub(unsigned StubSize,
+unsigned char *DefaultJITMemoryManager::allocateStub(const GlobalValue* F,
+                                                     unsigned StubSize,
                                                      unsigned Alignment) {
   CurStubPtr -= StubSize;
   CurStubPtr = (unsigned char*)(((intptr_t)CurStubPtr) &