+ Statistic<> NumBytes("jit", "Number of bytes of machine code compiled");
+ VM *TheVM = 0;
+
+ /// JITMemoryManager - Manage memory for the JIT code generation in a logical,
+ /// sane way. This splits a large block of MAP_NORESERVE'd memory into two
+ /// sections, one for function stubs, one for the functions themselves. We
+ /// have to do this because we may need to emit a function stub while in the
+ /// middle of emitting a function, and we don't know how large the function we
+ /// are emitting is. This never bothers to release the memory, because when
+ /// we are ready to destroy the JIT, the program exits.
+ class JITMemoryManager {
+ unsigned char *MemBase; // Base of block of memory, start of stub mem
+ unsigned char *FunctionBase; // Start of the function body area
+ unsigned char *CurStubPtr, *CurFunctionPtr;
+ public:
+ JITMemoryManager();
+
+ inline unsigned char *allocateStub(unsigned StubSize);
+ inline unsigned char *startFunctionBody();
+ inline void endFunctionBody(unsigned char *FunctionEnd);
+ };
+}
+
+// getMemory - Return a pointer to the specified number of bytes, which is
+// mapped as executable readable and writable.
+static void *getMemory(unsigned NumBytes) {
+ if (NumBytes == 0) return 0;
+ static const long pageSize = sysconf(_SC_PAGESIZE);
+ unsigned NumPages = (NumBytes+pageSize-1)/pageSize;
+
+#if defined(i386) || defined(__i386__) || defined(__x86__)
+ /* Linux and *BSD tend to have these flags named differently. */
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+# define MAP_ANONYMOUS MAP_ANON
+#endif /* defined(MAP_ANON) && !defined(MAP_ANONYMOUS) */
+#elif defined(sparc) || defined(__sparc__) || defined(__sparcv9)
+/* nothing */
+#else
+ std::cerr << "This architecture is not supported by the JIT!\n";
+ abort();
+#endif
+
+#if defined(__linux__)
+#define fd 0
+#else
+#define fd -1
+#endif
+
+ unsigned mmapFlags = MAP_PRIVATE|MAP_ANONYMOUS;
+#ifdef MAP_NORESERVE
+ mmapFlags |= MAP_NORESERVE;
+#endif
+
+ void *pa = mmap(0, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
+ mmapFlags, fd, 0);
+ if (pa == MAP_FAILED) {
+ perror("mmap");
+ abort();
+ }
+ return pa;
+}
+
+JITMemoryManager::JITMemoryManager() {
+ // Allocate a 16M block of memory...
+ MemBase = (unsigned char*)getMemory(16 << 20);
+ FunctionBase = MemBase + 512*1024; // Use 512k for stubs
+
+ // Allocate stubs backwards from the function base, allocate functions forward
+ // from the function base.
+ CurStubPtr = CurFunctionPtr = FunctionBase;
+}