move executable allocator out of System class

This commit is contained in:
Joshua Warner 2014-05-20 18:37:25 -06:00
parent a1631c00f9
commit 80cf745424
8 changed files with 178 additions and 60 deletions

View File

@ -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 <avian/util/slice.h>
#include <stdint.h>
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<uint8_t> allocate(size_t sizeInBytes, Permissions perms = ReadWrite);
// Free a contiguous range of pages.
static void free(util::Slice<uint8_t> pages);
// TODO: In the future:
// static void setPermissions(util::Slice<uint8_t> pages, Permissions perms);
};
} // namespace system
} // namespace avian
#endif

View File

@ -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;

View File

@ -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

View File

@ -15,6 +15,8 @@
#include "avian/target.h"
#include "avian/arch.h"
#include <avian/system/memory.h>
#include <avian/codegen/assembler.h>
#include <avian/codegen/architecture.h>
#include <avian/codegen/compiler.h>
@ -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<uint8_t*>(
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

View File

@ -54,6 +54,7 @@ typedef struct ucontext {
#include <avian/system/system.h>
#include <avian/system/signal.h>
#include <avian/system/memory.h>
#include <avian/util/math.h>
#define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_)(x)
@ -664,39 +665,7 @@ class MySystem : public System {
::free(const_cast<void*>(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<uint8_t*>(p) + sizeInBytes);
return static_cast<uint8_t*>(p);
}
}
virtual void freeExecutable(const void* p, unsigned sizeInBytes)
{
munmap(const_cast<void*>(p), sizeInBytes);
}
virtual bool success(Status s)
{
virtual bool success(Status s) {
return s == 0;
}

View File

@ -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 <avian/system/memory.h>
#include <avian/util/assert.h>
#include "sys/mman.h"
namespace avian {
namespace system {
const size_t Memory::PageSize = 1 << 12;
util::Slice<uint8_t> 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<uint8_t>(0, 0);
} else {
return util::Slice<uint8_t>(static_cast<uint8_t*>(p), sizeInBytes);
}
}
void Memory::free(util::Slice<uint8_t> pages)
{
munmap(const_cast<uint8_t*>(pages.begin()), pages.count);
}
} // namespace system
} // namespace avian

View File

@ -675,22 +675,7 @@ class MySystem : public System {
::free(const_cast<void*>(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<void*>(p), 0, MEM_RELEASE);
assertT(this, r);
}
#endif
virtual bool success(Status s)
{
virtual bool success(Status s) {
return s == 0;
}

View File

@ -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 <avian/system/memory.h>
#include <avian/util/assert.h>
#include <windows.h>
namespace avian {
namespace system {
const size_t Memory::PageSize = 1 << 12;
util::Slice<uint8_t> 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>((uint8_t*)ret, sizeInBytes);
}
void Memory::free(util::Slice<uint8_t> pages)
{
int r = VirtualFree(pages.begin(), 0, MEM_RELEASE);
(void) r;
ASSERT(r);
}
} // namespace system
} // namespace avian