diff --git a/include/avian/system/memory.h b/include/avian/system/memory.h new file mode 100644 index 0000000000..527d54da68 --- /dev/null +++ b/include/avian/system/memory.h @@ -0,0 +1,49 @@ + /* Copyright (c) 2008-2014, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_SYSTEM_MEMORY_H +#define AVIAN_SYSTEM_MEMORY_H + +#include + +#include + +namespace avian { +namespace system { + +class Memory { + public: + enum Permissions { + Read = 1 << 0, + Write = 1 << 1, + Execute = 1 << 2, + + // Utility munged constants + ReadWrite = Read | Write, + ReadExecute = Read | Execute, + ReadWriteExecute = Read | Write | Execute + }; + + static const size_t PageSize; + + // Allocate a contiguous range of pages. + static util::Slice allocate(size_t sizeInBytes, Permissions perms = ReadWrite); + + // Free a contiguous range of pages. + static void free(util::Slice pages); + + // TODO: In the future: + // static void setPermissions(util::Slice pages, Permissions perms); +}; + +} // namespace system +} // namespace avian + +#endif diff --git a/include/avian/system/system.h b/include/avian/system/system.h index ea31823f46..058d6d1fcd 100644 --- a/include/avian/system/system.h +++ b/include/avian/system/system.h @@ -113,10 +113,6 @@ class System : public avian::util::Aborter { virtual bool success(Status) = 0; virtual void* tryAllocate(unsigned sizeInBytes) = 0; virtual void free(const void* p) = 0; -#if !defined(AVIAN_AOT_ONLY) - virtual void* tryAllocateExecutable(unsigned sizeInBytes) = 0; - virtual void freeExecutable(const void* p, unsigned sizeInBytes) = 0; -#endif virtual Status attach(Runnable*) = 0; virtual Status start(Runnable*) = 0; virtual Status make(Mutex**) = 0; diff --git a/makefile b/makefile index e0e85411a0..23b6d49e18 100755 --- a/makefile +++ b/makefile @@ -1138,6 +1138,7 @@ vm-depends := $(generated-code) \ vm-sources = \ $(src)/system/$(system).cpp \ $(src)/system/$(system)/signal.cpp \ + $(src)/system/$(system)/memory.cpp \ $(src)/finder.cpp \ $(src)/machine.cpp \ $(src)/util.cpp \ @@ -1273,6 +1274,7 @@ generator-sources = \ $(src)/tools/type-generator/main.cpp \ $(src)/system/$(build-system).cpp \ $(src)/system/$(build-system)/signal.cpp \ + $(src)/system/$(build-system)/memory.cpp \ $(src)/finder.cpp \ $(src)/util/arg-parser.cpp diff --git a/src/compile.cpp b/src/compile.cpp index 7a546feb3a..0a0a3775ba 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -15,6 +15,8 @@ #include "avian/target.h" #include "avian/arch.h" +#include + #include #include #include @@ -8842,8 +8844,7 @@ class MyProcessor : public Processor { { if (codeAllocator.memory.begin()) { #if !defined(AVIAN_AOT_ONLY) - s->freeExecutable(codeAllocator.memory.begin(), - codeAllocator.memory.count); + Memory::free(codeAllocator.memory); #endif } @@ -9023,12 +9024,10 @@ class MyProcessor : public Processor { { #if !defined(AVIAN_AOT_ONLY) if (codeAllocator.memory.begin() == 0) { - codeAllocator.memory.items = static_cast( - s->tryAllocateExecutable(ExecutableAreaSizeInBytes)); + codeAllocator.memory = Memory::allocate(ExecutableAreaSizeInBytes, + Memory::ReadWriteExecute); - expect(t, codeAllocator.memory.items); - - codeAllocator.memory.count = ExecutableAreaSizeInBytes; + expect(t, codeAllocator.memory.begin()); } #endif diff --git a/src/system/posix.cpp b/src/system/posix.cpp index 1fb94e58e2..cf77851414 100644 --- a/src/system/posix.cpp +++ b/src/system/posix.cpp @@ -54,6 +54,7 @@ typedef struct ucontext { #include #include +#include #include #define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_)(x) @@ -664,39 +665,7 @@ class MySystem : public System { ::free(const_cast(p)); } - virtual void* tryAllocateExecutable(unsigned sizeInBytes) - { -#ifdef MAP_32BIT - // map to the lower 32 bits of memory when possible so as to avoid - // expensive relative jumps - const unsigned Extra = MAP_32BIT; -#else - const unsigned Extra = 0; -#endif - - void* p = mmap(0, - sizeInBytes, - PROT_EXEC | PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | Extra, - -1, - 0); - - if (p == MAP_FAILED) { - return 0; - } else { - // fprintf(stderr, "executable from %p to %p\n", p, - // static_cast(p) + sizeInBytes); - return static_cast(p); - } - } - - virtual void freeExecutable(const void* p, unsigned sizeInBytes) - { - munmap(const_cast(p), sizeInBytes); - } - - virtual bool success(Status s) - { + virtual bool success(Status s) { return s == 0; } diff --git a/src/system/posix/memory.cpp b/src/system/posix/memory.cpp new file mode 100644 index 0000000000..cdea451148 --- /dev/null +++ b/src/system/posix/memory.cpp @@ -0,0 +1,63 @@ +/* Copyright (c) 2008-2014, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include + +#include "sys/mman.h" + +namespace avian { +namespace system { + +const size_t Memory::PageSize = 1 << 12; + +util::Slice Memory::allocate(size_t sizeInBytes, + Permissions perms) +{ + unsigned prot = 0; + if(perms & Read) { + prot |= PROT_READ; + } + if(perms & Write) { + prot |= PROT_WRITE; + } + if(perms & Execute) { + prot |= PROT_EXEC; + } +#ifdef MAP_32BIT + // map to the lower 32 bits of memory when possible so as to avoid + // expensive relative jumps + const unsigned Extra = MAP_32BIT; +#else + const unsigned Extra = 0; +#endif + + void* p = mmap(0, + sizeInBytes, + prot, + MAP_PRIVATE | MAP_ANON | Extra, + -1, + 0); + + if (p == MAP_FAILED) { + return util::Slice(0, 0); + } else { + return util::Slice(static_cast(p), sizeInBytes); + } +} + +void Memory::free(util::Slice pages) +{ + munmap(const_cast(pages.begin()), pages.count); +} + +} // namespace system +} // namespace avian diff --git a/src/system/windows.cpp b/src/system/windows.cpp index f6a390e797..b713da966e 100644 --- a/src/system/windows.cpp +++ b/src/system/windows.cpp @@ -675,22 +675,7 @@ class MySystem : public System { ::free(const_cast(p)); } -#if !defined(AVIAN_AOT_ONLY) - virtual void* tryAllocateExecutable(unsigned sizeInBytes) - { - return VirtualAlloc( - 0, sizeInBytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - } - - virtual void freeExecutable(const void* p, unsigned) - { - int r UNUSED = VirtualFree(const_cast(p), 0, MEM_RELEASE); - assertT(this, r); - } -#endif - - virtual bool success(Status s) - { + virtual bool success(Status s) { return s == 0; } diff --git a/src/system/windows/memory.cpp b/src/system/windows/memory.cpp new file mode 100644 index 0000000000..6d4978262b --- /dev/null +++ b/src/system/windows/memory.cpp @@ -0,0 +1,55 @@ +/* Copyright (c) 2008-2014, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include + +#include + +#include + +namespace avian { +namespace system { + +const size_t Memory::PageSize = 1 << 12; + +util::Slice Memory::allocate(size_t sizeInBytes, + Permissions perms) +{ + unsigned prot; + switch(perms) { + case Read: + prot = PAGE_READONLY; + break; + case ReadWrite: + prot = PAGE_READWRITE; + break; + case ReadExecute: + prot = PAGE_EXECUTE_READ; + break; + case ReadWriteExecute: + prot = PAGE_EXECUTE_READWRITE; + break; + default: + UNREACHABLE_; + } + void* ret = VirtualAlloc( + 0, sizeInBytes, MEM_COMMIT | MEM_RESERVE, prot); + return util::Slice((uint8_t*)ret, sizeInBytes); +} + +void Memory::free(util::Slice pages) +{ + int r = VirtualFree(pages.begin(), 0, MEM_RELEASE); + (void) r; + ASSERT(r); +} + +} // namespace system +} // namespace avian