mirror of
https://github.com/corda/corda.git
synced 2024-12-28 00:38:55 +00:00
factor system.cpp and class-finder.cpp out of main.cpp
This commit is contained in:
parent
9f91f221dd
commit
0f7a2137bf
12
makefile
12
makefile
@ -1,4 +1,4 @@
|
||||
MAKEFLAGS = -s
|
||||
#MAKEFLAGS = -s
|
||||
|
||||
arch = $(shell uname -m)
|
||||
ifeq ($(arch),i586)
|
||||
@ -43,7 +43,7 @@ ifeq ($(mode),stress-major)
|
||||
cflags += -O0 -g3 -DVM_STRESS -DVM_STRESS_MAJOR
|
||||
endif
|
||||
ifeq ($(mode),fast)
|
||||
fast = -Os -DNDEBUG
|
||||
cflags += -Os -DNDEBUG -DMONOLITHIC
|
||||
endif
|
||||
|
||||
lflags = $(thread-lflags) -ldl
|
||||
@ -81,11 +81,13 @@ interpreter-depends = \
|
||||
$(src)/machine.h
|
||||
|
||||
interpreter-sources = \
|
||||
$(src)/run.cpp \
|
||||
$(src)/system.cpp \
|
||||
$(src)/class-finder.cpp \
|
||||
$(src)/machine.cpp \
|
||||
$(src)/jnienv.cpp \
|
||||
$(src)/builtin.cpp \
|
||||
$(src)/heap.cpp \
|
||||
$(src)/run.cpp \
|
||||
$(src)/builtin.cpp \
|
||||
$(src)/jnienv.cpp \
|
||||
$(src)/main.cpp
|
||||
|
||||
ifeq ($(arch),i386)
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "run.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
namespace builtin {
|
||||
|
||||
jstring
|
||||
@ -262,4 +263,5 @@ populate(Thread* t, object map)
|
||||
}
|
||||
|
||||
} // namespace builtin
|
||||
|
||||
} // namespace vm
|
||||
|
@ -4,12 +4,14 @@
|
||||
#include "machine.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
namespace builtin {
|
||||
|
||||
void
|
||||
populate(Thread* t, object map);
|
||||
|
||||
} // namespace builtin
|
||||
|
||||
} // namespace vm
|
||||
|
||||
#endif//BUILTIN_H
|
||||
|
167
src/class-finder.cpp
Normal file
167
src/class-finder.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
|
||||
|
||||
#include "sys/mman.h"
|
||||
#include "sys/types.h"
|
||||
#include "sys/stat.h"
|
||||
#include "fcntl.h"
|
||||
|
||||
|
||||
|
||||
#include "system.h"
|
||||
#include "class-finder.h"
|
||||
|
||||
using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
const char*
|
||||
append(System* s, const char* a, const char* b, const char* c,
|
||||
const char* d)
|
||||
{
|
||||
unsigned al = strlen(a);
|
||||
unsigned bl = strlen(b);
|
||||
unsigned cl = strlen(c);
|
||||
unsigned dl = strlen(d);
|
||||
char* p = static_cast<char*>(s->allocate(al + bl + cl + dl + 1));
|
||||
memcpy(p, a, al);
|
||||
memcpy(p + al, b, bl);
|
||||
memcpy(p + al + bl, c, cl);
|
||||
memcpy(p + al + bl + cl, d, dl + 1);
|
||||
return p;
|
||||
}
|
||||
|
||||
const char**
|
||||
parsePath(System* s, const char* path)
|
||||
{
|
||||
class Tokenizer {
|
||||
public:
|
||||
class Token {
|
||||
public:
|
||||
Token(const char* s, unsigned length): s(s), length(length) { }
|
||||
|
||||
const char* s;
|
||||
unsigned length;
|
||||
};
|
||||
|
||||
Tokenizer(const char* s, char delimiter): s(s), delimiter(delimiter) { }
|
||||
|
||||
bool hasMore() {
|
||||
while (*s == delimiter) ++s;
|
||||
return *s;
|
||||
}
|
||||
|
||||
Token next() {
|
||||
const char* p = s;
|
||||
while (*s and *s != delimiter) ++s;
|
||||
return Token(p, s - p);
|
||||
}
|
||||
|
||||
const char* s;
|
||||
char delimiter;
|
||||
};
|
||||
|
||||
unsigned count = 0;
|
||||
for (Tokenizer t(path, ':'); t.hasMore(); t.next()) ++ count;
|
||||
|
||||
const char** v = static_cast<const char**>
|
||||
(s->allocate((count + 1) * sizeof(const char*)));
|
||||
|
||||
unsigned i = 0;
|
||||
for (Tokenizer t(path, ':'); t.hasMore(); ++i) {
|
||||
Tokenizer::Token token(t.next());
|
||||
char* p = static_cast<char*>(s->allocate(token.length + 1));
|
||||
memcpy(p, token.s, token.length);
|
||||
p[token.length] = 0;
|
||||
v[i] = p;
|
||||
}
|
||||
|
||||
v[i] = 0;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
class MyClassFinder: public ClassFinder {
|
||||
public:
|
||||
MyClassFinder(System* system, const char* path):
|
||||
system(system),
|
||||
path(parsePath(system, path))
|
||||
{ }
|
||||
|
||||
class Data: public ClassFinder::Data {
|
||||
public:
|
||||
Data(System* system, uint8_t* start, size_t length):
|
||||
system(system),
|
||||
start_(start),
|
||||
length_(length)
|
||||
{ }
|
||||
|
||||
virtual const uint8_t* start() {
|
||||
return start_;
|
||||
}
|
||||
|
||||
virtual size_t length() {
|
||||
return length_;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (start_) {
|
||||
munmap(start_, length_);
|
||||
}
|
||||
system->free(this);
|
||||
}
|
||||
|
||||
System* system;
|
||||
uint8_t* start_;
|
||||
size_t length_;
|
||||
};
|
||||
|
||||
virtual Data* find(const char* className) {
|
||||
Data* d = new (system->allocate(sizeof(Data))) Data(system, 0, 0);
|
||||
|
||||
for (const char** p = path; *p; ++p) {
|
||||
const char* file = append(system, *p, "/", className, ".class");
|
||||
int fd = open(file, O_RDONLY);
|
||||
system->free(file);
|
||||
|
||||
if (fd != -1) {
|
||||
struct stat s;
|
||||
int r = fstat(fd, &s);
|
||||
if (r != -1) {
|
||||
void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (data) {
|
||||
d->start_ = static_cast<uint8_t*>(data);
|
||||
d->length_ = s.st_size;
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
system->free(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
for (const char** p = path; *p; ++p) {
|
||||
system->free(*p);
|
||||
}
|
||||
system->free(path);
|
||||
|
||||
system->free(this);
|
||||
}
|
||||
|
||||
System* system;
|
||||
const char** path;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
ClassFinder*
|
||||
makeClassFinder(System* s, const char* path)
|
||||
{
|
||||
return new (s->allocate(sizeof(MyClassFinder))) MyClassFinder(s, path);
|
||||
}
|
||||
|
||||
} // namespace vm
|
@ -2,6 +2,7 @@
|
||||
#define CLASS_FINDER_H
|
||||
|
||||
#include "common.h"
|
||||
#include "system.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
@ -17,8 +18,12 @@ class ClassFinder {
|
||||
|
||||
virtual ~ClassFinder() { }
|
||||
virtual Data* find(const char* className) = 0;
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
ClassFinder*
|
||||
makeClassFinder(System* s, const char* path);
|
||||
|
||||
} // namespace vm
|
||||
|
||||
#endif//CLASS_FINDER_H
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdarg.h"
|
||||
@ -27,6 +29,8 @@
|
||||
|
||||
inline void* operator new(size_t, void* p) throw() { return p; }
|
||||
|
||||
|
||||
|
||||
namespace vm {
|
||||
|
||||
typedef void* object;
|
||||
@ -127,6 +131,6 @@ mask(T* p)
|
||||
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vm
|
||||
|
||||
#endif//COMMON_H
|
||||
|
@ -168,7 +168,7 @@ enum OpCode {
|
||||
ldc = 0x12,
|
||||
ldc_w = 0x13,
|
||||
ldc2_w = 0x14,
|
||||
ldiv = 0x6d,
|
||||
ldiv_ = 0x6d,
|
||||
lload = 0x16,
|
||||
lload_0 = 0x1e,
|
||||
lload_1 = 0x1f,
|
||||
|
174
src/heap.cpp
174
src/heap.cpp
@ -1374,99 +1374,99 @@ collect(Context* c)
|
||||
}
|
||||
}
|
||||
|
||||
class MyHeap: public Heap {
|
||||
public:
|
||||
MyHeap(System* system): c(system) { }
|
||||
|
||||
virtual void collect(CollectionType type, Client* client) {
|
||||
switch (type) {
|
||||
case MinorCollection:
|
||||
c.mode = ::MinorCollection;
|
||||
break;
|
||||
|
||||
case MajorCollection:
|
||||
c.mode = ::MajorCollection;
|
||||
break;
|
||||
|
||||
default: abort(&c);
|
||||
}
|
||||
|
||||
c.client = client;
|
||||
|
||||
::collect(&c);
|
||||
}
|
||||
|
||||
virtual bool needsMark(void** p) {
|
||||
return *p and c.gen2.contains(p) and not c.gen2.contains(*p);
|
||||
}
|
||||
|
||||
virtual void mark(void** p) {
|
||||
if (Debug) {
|
||||
fprintf(stderr, "mark %p (%s) at %p (%s)\n",
|
||||
*p, segment(&c, *p), p, segment(&c, p));
|
||||
}
|
||||
|
||||
c.heapMap.set(p);
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
c.dispose();
|
||||
c.system->free(this);
|
||||
}
|
||||
|
||||
virtual void* follow(void* p) {
|
||||
if (wasCollected(&c, p)) {
|
||||
if (Debug) {
|
||||
fprintf(stderr, "follow %p (%s) to %p (%s)\n",
|
||||
p, segment(&c, p),
|
||||
::follow(&c, p), segment(&c, ::follow(&c, p)));
|
||||
}
|
||||
|
||||
return ::follow(&c, p);
|
||||
} else {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Status status(void* p) {
|
||||
p = mask(p);
|
||||
|
||||
if (p == 0) {
|
||||
return Null;
|
||||
} else if (c.nextGen1.contains(p)) {
|
||||
return Reachable;
|
||||
} else if (c.nextGen2.contains(p)
|
||||
or (c.gen2.contains(p)
|
||||
and (c.mode == ::MinorCollection
|
||||
or c.gen2.indexOf(p) >= c.gen2Base)))
|
||||
{
|
||||
return Tenured;
|
||||
} else if (wasCollected(&c, p)) {
|
||||
return Reachable;
|
||||
} else {
|
||||
return Unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
virtual CollectionType collectionType() {
|
||||
if (c.mode == ::MinorCollection) {
|
||||
return MinorCollection;
|
||||
} else {
|
||||
return MajorCollection;
|
||||
}
|
||||
}
|
||||
|
||||
Context c;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
Heap*
|
||||
makeHeap(System* system)
|
||||
{
|
||||
class Heap: public vm::Heap {
|
||||
public:
|
||||
Heap(System* system): c(system) { }
|
||||
|
||||
virtual void collect(CollectionType type, Client* client) {
|
||||
switch (type) {
|
||||
case MinorCollection:
|
||||
c.mode = ::MinorCollection;
|
||||
break;
|
||||
|
||||
case MajorCollection:
|
||||
c.mode = ::MajorCollection;
|
||||
break;
|
||||
|
||||
default: abort(&c);
|
||||
}
|
||||
|
||||
c.client = client;
|
||||
|
||||
::collect(&c);
|
||||
}
|
||||
|
||||
virtual bool needsMark(void** p) {
|
||||
return *p and c.gen2.contains(p) and not c.gen2.contains(*p);
|
||||
}
|
||||
|
||||
virtual void mark(void** p) {
|
||||
if (Debug) {
|
||||
fprintf(stderr, "mark %p (%s) at %p (%s)\n",
|
||||
*p, segment(&c, *p), p, segment(&c, p));
|
||||
}
|
||||
|
||||
c.heapMap.set(p);
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
c.dispose();
|
||||
c.system->free(this);
|
||||
}
|
||||
|
||||
virtual void* follow(void* p) {
|
||||
if (wasCollected(&c, p)) {
|
||||
if (Debug) {
|
||||
fprintf(stderr, "follow %p (%s) to %p (%s)\n",
|
||||
p, segment(&c, p),
|
||||
::follow(&c, p), segment(&c, ::follow(&c, p)));
|
||||
}
|
||||
|
||||
return ::follow(&c, p);
|
||||
} else {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
virtual Status status(void* p) {
|
||||
p = mask(p);
|
||||
|
||||
if (p == 0) {
|
||||
return Null;
|
||||
} else if (c.nextGen1.contains(p)) {
|
||||
return Reachable;
|
||||
} else if (c.nextGen2.contains(p)
|
||||
or (c.gen2.contains(p)
|
||||
and (c.mode == ::MinorCollection
|
||||
or c.gen2.indexOf(p) >= c.gen2Base)))
|
||||
{
|
||||
return Tenured;
|
||||
} else if (wasCollected(&c, p)) {
|
||||
return Reachable;
|
||||
} else {
|
||||
return Unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
virtual CollectionType collectionType() {
|
||||
if (c.mode == ::MinorCollection) {
|
||||
return MinorCollection;
|
||||
} else {
|
||||
return MajorCollection;
|
||||
}
|
||||
}
|
||||
|
||||
Context c;
|
||||
};
|
||||
|
||||
return new (system->allocate(sizeof(Heap))) Heap(system);
|
||||
{
|
||||
return new (system->allocate(sizeof(MyHeap))) MyHeap(system);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "machine.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
namespace jni {
|
||||
|
||||
jsize
|
||||
@ -51,4 +52,5 @@ populate(JNIEnvVTable* table)
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
|
||||
} // namespace vm
|
||||
|
@ -4,12 +4,14 @@
|
||||
#include "machine.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
namespace jni {
|
||||
|
||||
void
|
||||
populate(JNIEnvVTable* table);
|
||||
|
||||
} // namespace jni
|
||||
|
||||
} // namespace vm
|
||||
|
||||
#endif//JNIENV_H
|
||||
|
@ -2008,6 +2008,12 @@ wait(Thread* t, object o, int64_t milliseconds)
|
||||
stress(t);
|
||||
}
|
||||
|
||||
inline void
|
||||
vmWait(Thread* t, object o, int64_t milliseconds)
|
||||
{
|
||||
wait(t, o, milliseconds);
|
||||
}
|
||||
|
||||
inline void
|
||||
notify(Thread* t, object o)
|
||||
{
|
||||
@ -2025,6 +2031,12 @@ notify(Thread* t, object o)
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
vmNotify(Thread* t, object o)
|
||||
{
|
||||
notify(t, o);
|
||||
}
|
||||
|
||||
inline void
|
||||
notifyAll(Thread* t, object o)
|
||||
{
|
||||
@ -2042,6 +2054,12 @@ notifyAll(Thread* t, object o)
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
vmNotifyAll(Thread* t, object o)
|
||||
{
|
||||
notifyAll(t, o);
|
||||
}
|
||||
|
||||
void
|
||||
exit(Thread* t);
|
||||
|
||||
|
535
src/main.cpp
535
src/main.cpp
@ -1,13 +1,3 @@
|
||||
#include "sys/mman.h"
|
||||
#include "sys/types.h"
|
||||
#include "sys/stat.h"
|
||||
#include "sys/time.h"
|
||||
#include "time.h"
|
||||
#include "fcntl.h"
|
||||
#include "dlfcn.h"
|
||||
#include "errno.h"
|
||||
#include "pthread.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "system.h"
|
||||
#include "heap.h"
|
||||
@ -16,534 +6,21 @@
|
||||
|
||||
using namespace vm;
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
extern "C" uint64_t
|
||||
cdeclCall(void* function, void* stack, unsigned stackSize,
|
||||
unsigned returnType);
|
||||
|
||||
namespace {
|
||||
|
||||
inline uint64_t
|
||||
dynamicCall(void* function, uint32_t* arguments, uint8_t*,
|
||||
unsigned, unsigned argumentsSize, unsigned returnType)
|
||||
{
|
||||
return cdeclCall(function, arguments, argumentsSize, returnType);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#elif defined __x86_64__
|
||||
|
||||
extern "C" uint64_t
|
||||
amd64Call(void* function, void* stack, unsigned stackSize,
|
||||
void* gprTable, void* sseTable, unsigned returnType);
|
||||
|
||||
namespace {
|
||||
|
||||
uint64_t
|
||||
dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
||||
unsigned argumentCount, unsigned, unsigned returnType)
|
||||
{
|
||||
const unsigned GprCount = 6;
|
||||
uint64_t gprTable[GprCount];
|
||||
unsigned gprIndex = 0;
|
||||
|
||||
const unsigned SseCount = 8;
|
||||
uint64_t sseTable[SseCount];
|
||||
unsigned sseIndex = 0;
|
||||
|
||||
uint64_t stack[argumentCount];
|
||||
unsigned stackIndex = 0;
|
||||
|
||||
for (unsigned i = 0; i < argumentCount; ++i) {
|
||||
switch (argumentTypes[i]) {
|
||||
case FLOAT_TYPE:
|
||||
case DOUBLE_TYPE: {
|
||||
if (sseIndex < SseCount) {
|
||||
sseTable[sseIndex++] = arguments[i];
|
||||
} else {
|
||||
stack[stackIndex++] = arguments[i];
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
if (gprIndex < GprCount) {
|
||||
gprTable[gprIndex++] = arguments[i];
|
||||
} else {
|
||||
stack[stackIndex++] = arguments[i];
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
return amd64Call(function, stack, stackIndex * 8, (gprIndex ? gprTable : 0),
|
||||
(sseIndex ? sseTable : 0), returnType);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#else
|
||||
# error unsupported platform
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
void*
|
||||
run(void* t)
|
||||
{
|
||||
static_cast<vm::System::Thread*>(t)->run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t
|
||||
now()
|
||||
{
|
||||
timeval tv = { 0, 0 };
|
||||
gettimeofday(&tv, 0);
|
||||
return (static_cast<int64_t>(tv.tv_sec) * 1000) +
|
||||
(static_cast<int64_t>(tv.tv_usec) / 1000);
|
||||
}
|
||||
|
||||
const char*
|
||||
append(vm::System* s, const char* a, const char* b, const char* c,
|
||||
const char* d)
|
||||
{
|
||||
unsigned al = strlen(a);
|
||||
unsigned bl = strlen(b);
|
||||
unsigned cl = strlen(c);
|
||||
unsigned dl = strlen(d);
|
||||
char* p = static_cast<char*>(s->allocate(al + bl + cl + dl + 1));
|
||||
memcpy(p, a, al);
|
||||
memcpy(p + al, b, bl);
|
||||
memcpy(p + al + bl, c, cl);
|
||||
memcpy(p + al + bl + cl, d, dl + 1);
|
||||
return p;
|
||||
}
|
||||
|
||||
const bool Verbose = false;
|
||||
|
||||
class System: public vm::System {
|
||||
public:
|
||||
class Thread: public vm::System::Thread {
|
||||
public:
|
||||
Thread(vm::System* s, vm::System::Runnable* r): s(s), r(r) { }
|
||||
|
||||
virtual void run() {
|
||||
r->run(this);
|
||||
}
|
||||
|
||||
virtual void join() {
|
||||
int rv = pthread_join(thread, 0);
|
||||
assert(s, rv == 0);
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (r) {
|
||||
r->dispose();
|
||||
}
|
||||
s->free(this);
|
||||
}
|
||||
|
||||
vm::System* s;
|
||||
vm::System::Runnable* r;
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
class Monitor: public vm::System::Monitor {
|
||||
public:
|
||||
Monitor(vm::System* s): s(s), context(0), depth(0) {
|
||||
pthread_mutex_init(&mutex, 0);
|
||||
pthread_cond_init(&condition, 0);
|
||||
}
|
||||
|
||||
virtual bool tryAcquire(void* context) {
|
||||
if (this->context == context) {
|
||||
++ depth;
|
||||
return true;
|
||||
} else {
|
||||
switch (pthread_mutex_trylock(&mutex)) {
|
||||
case EBUSY:
|
||||
return false;
|
||||
|
||||
case 0:
|
||||
this->context = context;
|
||||
++ depth;
|
||||
return true;
|
||||
|
||||
default:
|
||||
vm::abort(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void acquire(void* context) {
|
||||
if (this->context != context) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
this->context = context;
|
||||
}
|
||||
++ depth;
|
||||
}
|
||||
|
||||
virtual void release(void* context) {
|
||||
if (this->context == context) {
|
||||
if (-- depth == 0) {
|
||||
this->context = 0;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
} else {
|
||||
vm::abort(s);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void wait(void* context, int64_t time) {
|
||||
if (this->context == context) {
|
||||
unsigned depth = this->depth;
|
||||
this->depth = 0;
|
||||
this->context = 0;
|
||||
if (time) {
|
||||
int64_t then = now() + time;
|
||||
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
|
||||
int rv = pthread_cond_timedwait(&condition, &mutex, &ts);
|
||||
assert(s, rv == 0);
|
||||
} else {
|
||||
int rv = pthread_cond_wait(&condition, &mutex);
|
||||
assert(s, rv == 0);
|
||||
}
|
||||
this->context = context;
|
||||
this->depth = depth;
|
||||
} else {
|
||||
vm::abort(s);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void notify(void* context) {
|
||||
if (this->context == context) {
|
||||
int rv = pthread_cond_signal(&condition);
|
||||
assert(s, rv == 0);
|
||||
} else {
|
||||
vm::abort(s);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void notifyAll(void* context) {
|
||||
if (this->context == context) {
|
||||
int rv = pthread_cond_broadcast(&condition);
|
||||
assert(s, rv == 0);
|
||||
} else {
|
||||
vm::abort(s);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void* owner() {
|
||||
return context;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
assert(s, context == 0);
|
||||
pthread_mutex_destroy(&mutex);
|
||||
pthread_cond_destroy(&condition);
|
||||
s->free(this);
|
||||
}
|
||||
|
||||
vm::System* s;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t condition;
|
||||
void* context;
|
||||
unsigned depth;
|
||||
};
|
||||
|
||||
class Library: public vm::System::Library {
|
||||
public:
|
||||
Library(vm::System* s, void* p, vm::System::Library* next):
|
||||
s(s),
|
||||
p(p),
|
||||
next_(next)
|
||||
{ }
|
||||
|
||||
virtual void* resolve(const char* function) {
|
||||
return dlsym(p, function);
|
||||
}
|
||||
|
||||
virtual vm::System::Library* next() {
|
||||
return next_;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "close %p\n", p);
|
||||
}
|
||||
|
||||
dlclose(p);
|
||||
|
||||
if (next_) {
|
||||
next_->dispose();
|
||||
}
|
||||
s->free(this);
|
||||
}
|
||||
|
||||
vm::System* s;
|
||||
void* p;
|
||||
vm::System::Library* next_;
|
||||
};
|
||||
|
||||
System(unsigned limit): limit(limit), count(0) {
|
||||
pthread_mutex_init(&mutex, 0);
|
||||
}
|
||||
|
||||
~System() {
|
||||
pthread_mutex_destroy(&mutex);
|
||||
}
|
||||
|
||||
virtual bool success(Status s) {
|
||||
return s == 0;
|
||||
}
|
||||
|
||||
virtual void* tryAllocate(unsigned size) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "try %d; count: %d; limit: %d\n",
|
||||
size, count, limit);
|
||||
}
|
||||
|
||||
if (count + size > limit) {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return 0;
|
||||
} else {
|
||||
uintptr_t* up = static_cast<uintptr_t*>
|
||||
(malloc(size + sizeof(uintptr_t)));
|
||||
if (up == 0) {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
vm::abort(this);
|
||||
} else {
|
||||
*up = size;
|
||||
count += *up;
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return up + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void free(const void* p) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
if (p) {
|
||||
const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1;
|
||||
if (count < *up) {
|
||||
abort();
|
||||
}
|
||||
count -= *up;
|
||||
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "free " LD "; count: %d; limit: %d\n",
|
||||
*up, count, limit);
|
||||
}
|
||||
|
||||
::free(const_cast<uintptr_t*>(up));
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
virtual Status attach(vm::System::Thread** tp) {
|
||||
Thread* t = new (vm::System::allocate(sizeof(Thread))) Thread(this, 0);
|
||||
t->thread = pthread_self();
|
||||
*tp = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Status start(Runnable* r) {
|
||||
Thread* t = new (vm::System::allocate(sizeof(Thread))) Thread(this, r);
|
||||
int rv = pthread_create(&(t->thread), 0, run, t);
|
||||
assert(this, rv == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Status make(vm::System::Monitor** m) {
|
||||
*m = new (vm::System::allocate(sizeof(Monitor))) Monitor(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void sleep(int64_t milliseconds) {
|
||||
timespec ts = { milliseconds / 1000, (milliseconds % 1000) * 1000 * 1000 };
|
||||
|
||||
nanosleep(&ts, 0);
|
||||
}
|
||||
|
||||
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||
unsigned count, unsigned size, unsigned returnType)
|
||||
{
|
||||
return dynamicCall(function, arguments, types, count, size, returnType);
|
||||
}
|
||||
|
||||
virtual Status load(vm::System::Library** lib,
|
||||
const char* name,
|
||||
vm::System::Library* next)
|
||||
{
|
||||
unsigned size = strlen(name) + 7;
|
||||
char buffer[size];
|
||||
snprintf(buffer, size, "lib%s.so", name);
|
||||
|
||||
void* p = dlopen(buffer, RTLD_LAZY);
|
||||
if (p) {
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "open %s as %p\n", buffer, p);
|
||||
}
|
||||
|
||||
*lib = new (vm::System::allocate(sizeof(Library)))
|
||||
Library(this, p, next);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void abort() {
|
||||
::abort();
|
||||
}
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
unsigned limit;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
class ClassFinder: public vm::ClassFinder {
|
||||
public:
|
||||
ClassFinder(vm::System* system, const char** path):
|
||||
system(system),
|
||||
path(path)
|
||||
{ }
|
||||
|
||||
class Data: public vm::ClassFinder::Data {
|
||||
public:
|
||||
Data(vm::System* system, uint8_t* start, size_t length):
|
||||
system(system),
|
||||
start_(start),
|
||||
length_(length)
|
||||
{ }
|
||||
|
||||
virtual const uint8_t* start() {
|
||||
return start_;
|
||||
}
|
||||
|
||||
virtual size_t length() {
|
||||
return length_;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (start_) {
|
||||
munmap(start_, length_);
|
||||
}
|
||||
system->free(this);
|
||||
}
|
||||
|
||||
vm::System* system;
|
||||
uint8_t* start_;
|
||||
size_t length_;
|
||||
};
|
||||
|
||||
virtual Data* find(const char* className) {
|
||||
Data* d = new (system->allocate(sizeof(Data))) Data(system, 0, 0);
|
||||
|
||||
for (const char** p = path; *p; ++p) {
|
||||
const char* file = append(system, *p, "/", className, ".class");
|
||||
int fd = open(file, O_RDONLY);
|
||||
system->free(file);
|
||||
|
||||
if (fd != -1) {
|
||||
struct stat s;
|
||||
int r = fstat(fd, &s);
|
||||
if (r != -1) {
|
||||
void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (data) {
|
||||
d->start_ = static_cast<uint8_t*>(data);
|
||||
d->length_ = s.st_size;
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
system->free(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vm::System* system;
|
||||
const char** path;
|
||||
};
|
||||
|
||||
const char**
|
||||
parsePath(vm::System* s, const char* path)
|
||||
{
|
||||
class Tokenizer {
|
||||
public:
|
||||
class Token {
|
||||
public:
|
||||
Token(const char* s, unsigned length): s(s), length(length) { }
|
||||
|
||||
const char* s;
|
||||
unsigned length;
|
||||
};
|
||||
|
||||
Tokenizer(const char* s, char delimiter): s(s), delimiter(delimiter) { }
|
||||
|
||||
bool hasMore() {
|
||||
while (*s == delimiter) ++s;
|
||||
return *s;
|
||||
}
|
||||
|
||||
Token next() {
|
||||
const char* p = s;
|
||||
while (*s and *s != delimiter) ++s;
|
||||
return Token(p, s - p);
|
||||
}
|
||||
|
||||
const char* s;
|
||||
char delimiter;
|
||||
};
|
||||
|
||||
unsigned count = 0;
|
||||
for (Tokenizer t(path, ':'); t.hasMore(); t.next()) ++ count;
|
||||
|
||||
const char** v = static_cast<const char**>
|
||||
(s->allocate((count + 1) * sizeof(const char*)));
|
||||
|
||||
unsigned i = 0;
|
||||
for (Tokenizer t(path, ':'); t.hasMore(); ++i) {
|
||||
Tokenizer::Token token(t.next());
|
||||
char* p = static_cast<char*>(s->allocate(token.length + 1));
|
||||
memcpy(p, token.s, token.length);
|
||||
p[token.length] = 0;
|
||||
v[i] = p;
|
||||
}
|
||||
|
||||
v[i] = 0;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int
|
||||
run(unsigned heapSize, const char* path, const char* class_, int argc,
|
||||
const char** argv)
|
||||
{
|
||||
System s(heapSize);
|
||||
System* s = makeSystem(heapSize);
|
||||
ClassFinder* cf = makeClassFinder(s, path);
|
||||
Heap* heap = makeHeap(s);
|
||||
|
||||
const char** pathv = parsePath(&s, path);
|
||||
ClassFinder cf(&s, pathv);
|
||||
|
||||
Heap* heap = makeHeap(&s);
|
||||
|
||||
int exitCode = run(&s, heap, &cf, class_, argc, argv);
|
||||
int exitCode = run(s, heap, cf, class_, argc, argv);
|
||||
|
||||
heap->dispose();
|
||||
|
||||
for (const char** p = pathv; *p; ++p) {
|
||||
s.free(*p);
|
||||
}
|
||||
|
||||
s.free(pathv);
|
||||
cf->dispose();
|
||||
s->dispose();
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
@ -1656,7 +1656,7 @@ run(Thread* t)
|
||||
}
|
||||
} goto loop;
|
||||
|
||||
case vm::ldiv: {
|
||||
case ldiv_: {
|
||||
int64_t b = popLong(t);
|
||||
int64_t a = popLong(t);
|
||||
|
||||
@ -2386,4 +2386,4 @@ run(System* system, Heap* heap, ClassFinder* classFinder,
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vm
|
||||
|
@ -16,6 +16,6 @@ int
|
||||
run(System* sys, Heap* heap, ClassFinder* classFinder,
|
||||
const char* className, int argc, const char** argv);
|
||||
|
||||
}
|
||||
} // namespace vm
|
||||
|
||||
#endif//RUN_H
|
||||
|
403
src/system.cpp
Normal file
403
src/system.cpp
Normal file
@ -0,0 +1,403 @@
|
||||
#include "sys/mman.h"
|
||||
#include "sys/types.h"
|
||||
#include "sys/stat.h"
|
||||
#include "sys/time.h"
|
||||
#include "time.h"
|
||||
#include "fcntl.h"
|
||||
#include "dlfcn.h"
|
||||
#include "errno.h"
|
||||
#include "pthread.h"
|
||||
#include "stdint.h"
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
extern "C" uint64_t
|
||||
cdeclCall(void* function, void* stack, unsigned stackSize,
|
||||
unsigned returnType);
|
||||
|
||||
namespace {
|
||||
|
||||
inline uint64_t
|
||||
dynamicCall(void* function, uint32_t* arguments, uint8_t*,
|
||||
unsigned, unsigned argumentsSize, unsigned returnType)
|
||||
{
|
||||
return cdeclCall(function, arguments, argumentsSize, returnType);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#elif defined __x86_64__
|
||||
|
||||
extern "C" uint64_t
|
||||
amd64Call(void* function, void* stack, unsigned stackSize,
|
||||
void* gprTable, void* sseTable, unsigned returnType);
|
||||
|
||||
#include "system.h"
|
||||
|
||||
namespace {
|
||||
|
||||
uint64_t
|
||||
dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
||||
unsigned argumentCount, unsigned, unsigned returnType)
|
||||
{
|
||||
const unsigned GprCount = 6;
|
||||
uint64_t gprTable[GprCount];
|
||||
unsigned gprIndex = 0;
|
||||
|
||||
const unsigned SseCount = 8;
|
||||
uint64_t sseTable[SseCount];
|
||||
unsigned sseIndex = 0;
|
||||
|
||||
uint64_t stack[argumentCount];
|
||||
unsigned stackIndex = 0;
|
||||
|
||||
for (unsigned i = 0; i < argumentCount; ++i) {
|
||||
switch (argumentTypes[i]) {
|
||||
case FLOAT_TYPE:
|
||||
case DOUBLE_TYPE: {
|
||||
if (sseIndex < SseCount) {
|
||||
sseTable[sseIndex++] = arguments[i];
|
||||
} else {
|
||||
stack[stackIndex++] = arguments[i];
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
if (gprIndex < GprCount) {
|
||||
gprTable[gprIndex++] = arguments[i];
|
||||
} else {
|
||||
stack[stackIndex++] = arguments[i];
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
return amd64Call(function, stack, stackIndex * 8, (gprIndex ? gprTable : 0),
|
||||
(sseIndex ? sseTable : 0), returnType);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#else
|
||||
# error unsupported platform
|
||||
#endif
|
||||
|
||||
using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
void*
|
||||
run(void* t)
|
||||
{
|
||||
static_cast<System::Thread*>(t)->run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t
|
||||
now()
|
||||
{
|
||||
timeval tv = { 0, 0 };
|
||||
gettimeofday(&tv, 0);
|
||||
return (static_cast<int64_t>(tv.tv_sec) * 1000) +
|
||||
(static_cast<int64_t>(tv.tv_usec) / 1000);
|
||||
}
|
||||
|
||||
const bool Verbose = false;
|
||||
|
||||
class MySystem: public System {
|
||||
public:
|
||||
class Thread: public System::Thread {
|
||||
public:
|
||||
Thread(System* s, System::Runnable* r): s(s), r(r) { }
|
||||
|
||||
virtual void run() {
|
||||
r->run(this);
|
||||
}
|
||||
|
||||
virtual void join() {
|
||||
int rv = pthread_join(thread, 0);
|
||||
assert(s, rv == 0);
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (r) {
|
||||
r->dispose();
|
||||
}
|
||||
s->free(this);
|
||||
}
|
||||
|
||||
System* s;
|
||||
System::Runnable* r;
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
class Monitor: public System::Monitor {
|
||||
public:
|
||||
Monitor(System* s): s(s), context(0), depth(0) {
|
||||
pthread_mutex_init(&mutex, 0);
|
||||
pthread_cond_init(&condition, 0);
|
||||
}
|
||||
|
||||
virtual bool tryAcquire(void* context) {
|
||||
if (this->context == context) {
|
||||
++ depth;
|
||||
return true;
|
||||
} else {
|
||||
switch (pthread_mutex_trylock(&mutex)) {
|
||||
case EBUSY:
|
||||
return false;
|
||||
|
||||
case 0:
|
||||
this->context = context;
|
||||
++ depth;
|
||||
return true;
|
||||
|
||||
default:
|
||||
sysAbort(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void acquire(void* context) {
|
||||
if (this->context != context) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
this->context = context;
|
||||
}
|
||||
++ depth;
|
||||
}
|
||||
|
||||
virtual void release(void* context) {
|
||||
if (this->context == context) {
|
||||
if (-- depth == 0) {
|
||||
this->context = 0;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
} else {
|
||||
sysAbort(s);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void wait(void* context, int64_t time) {
|
||||
if (this->context == context) {
|
||||
unsigned depth = this->depth;
|
||||
this->depth = 0;
|
||||
this->context = 0;
|
||||
if (time) {
|
||||
int64_t then = now() + time;
|
||||
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
|
||||
int rv = pthread_cond_timedwait(&condition, &mutex, &ts);
|
||||
assert(s, rv == 0);
|
||||
} else {
|
||||
int rv = pthread_cond_wait(&condition, &mutex);
|
||||
assert(s, rv == 0);
|
||||
}
|
||||
this->context = context;
|
||||
this->depth = depth;
|
||||
} else {
|
||||
sysAbort(s);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void notify(void* context) {
|
||||
if (this->context == context) {
|
||||
int rv = pthread_cond_signal(&condition);
|
||||
assert(s, rv == 0);
|
||||
} else {
|
||||
sysAbort(s);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void notifyAll(void* context) {
|
||||
if (this->context == context) {
|
||||
int rv = pthread_cond_broadcast(&condition);
|
||||
assert(s, rv == 0);
|
||||
} else {
|
||||
sysAbort(s);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void* owner() {
|
||||
return context;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
assert(s, context == 0);
|
||||
pthread_mutex_destroy(&mutex);
|
||||
pthread_cond_destroy(&condition);
|
||||
s->free(this);
|
||||
}
|
||||
|
||||
System* s;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t condition;
|
||||
void* context;
|
||||
unsigned depth;
|
||||
};
|
||||
|
||||
class Library: public System::Library {
|
||||
public:
|
||||
Library(System* s, void* p, System::Library* next):
|
||||
s(s),
|
||||
p(p),
|
||||
next_(next)
|
||||
{ }
|
||||
|
||||
virtual void* resolve(const char* function) {
|
||||
return dlsym(p, function);
|
||||
}
|
||||
|
||||
virtual System::Library* next() {
|
||||
return next_;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "close %p\n", p);
|
||||
}
|
||||
|
||||
dlclose(p);
|
||||
|
||||
if (next_) {
|
||||
next_->dispose();
|
||||
}
|
||||
s->free(this);
|
||||
}
|
||||
|
||||
System* s;
|
||||
void* p;
|
||||
System::Library* next_;
|
||||
};
|
||||
|
||||
MySystem(unsigned limit): limit(limit), count(0) {
|
||||
pthread_mutex_init(&mutex, 0);
|
||||
}
|
||||
|
||||
virtual bool success(Status s) {
|
||||
return s == 0;
|
||||
}
|
||||
|
||||
virtual void* tryAllocate(unsigned size) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "try %d; count: %d; limit: %d\n",
|
||||
size, count, limit);
|
||||
}
|
||||
|
||||
if (count + size > limit) {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return 0;
|
||||
} else {
|
||||
uintptr_t* up = static_cast<uintptr_t*>
|
||||
(malloc(size + sizeof(uintptr_t)));
|
||||
if (up == 0) {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
sysAbort(this);
|
||||
} else {
|
||||
*up = size;
|
||||
count += *up;
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return up + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void free(const void* p) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
if (p) {
|
||||
const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1;
|
||||
if (count < *up) {
|
||||
abort();
|
||||
}
|
||||
count -= *up;
|
||||
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "free " LD "; count: %d; limit: %d\n",
|
||||
*up, count, limit);
|
||||
}
|
||||
|
||||
::free(const_cast<uintptr_t*>(up));
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
virtual Status attach(System::Thread** tp) {
|
||||
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, 0);
|
||||
t->thread = pthread_self();
|
||||
*tp = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Status start(Runnable* r) {
|
||||
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r);
|
||||
int rv = pthread_create(&(t->thread), 0, run, t);
|
||||
assert(this, rv == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Status make(System::Monitor** m) {
|
||||
*m = new (System::allocate(sizeof(Monitor))) Monitor(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void sleep(int64_t milliseconds) {
|
||||
timespec ts = { milliseconds / 1000, (milliseconds % 1000) * 1000 * 1000 };
|
||||
|
||||
nanosleep(&ts, 0);
|
||||
}
|
||||
|
||||
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||
unsigned count, unsigned size, unsigned returnType)
|
||||
{
|
||||
return dynamicCall(function, arguments, types, count, size, returnType);
|
||||
}
|
||||
|
||||
virtual Status load(System::Library** lib,
|
||||
const char* name,
|
||||
System::Library* next)
|
||||
{
|
||||
unsigned size = strlen(name) + 7;
|
||||
char buffer[size];
|
||||
snprintf(buffer, size, "lib%s.so", name);
|
||||
|
||||
void* p = dlopen(buffer, RTLD_LAZY);
|
||||
if (p) {
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "open %s as %p\n", buffer, p);
|
||||
}
|
||||
|
||||
*lib = new (System::allocate(sizeof(Library))) Library(this, p, next);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void abort() {
|
||||
::abort();
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
pthread_mutex_destroy(&mutex);
|
||||
::free(this);
|
||||
}
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
unsigned limit;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
System*
|
||||
makeSystem(unsigned heapSize)
|
||||
{
|
||||
return new (malloc(sizeof(MySystem))) MySystem(heapSize);
|
||||
}
|
||||
|
||||
} // namespace vm
|
10
src/system.h
10
src/system.h
@ -65,6 +65,7 @@ class System: public Allocator {
|
||||
unsigned returnType) = 0;
|
||||
virtual Status load(Library**, const char* name, Library* next) = 0;
|
||||
virtual void abort() = 0;
|
||||
virtual void dispose() = 0;
|
||||
|
||||
virtual void* allocate(unsigned size) {
|
||||
void* p = tryAllocate(size);
|
||||
@ -82,6 +83,12 @@ abort(System* s)
|
||||
::abort();
|
||||
}
|
||||
|
||||
inline void NO_RETURN
|
||||
sysAbort(System* s)
|
||||
{
|
||||
abort(s);
|
||||
}
|
||||
|
||||
inline void
|
||||
expect(System* s, bool v)
|
||||
{
|
||||
@ -100,6 +107,9 @@ assert(System* s, bool v)
|
||||
}
|
||||
#endif
|
||||
|
||||
System*
|
||||
makeSystem(unsigned heapSize);
|
||||
|
||||
} // namespace vm
|
||||
|
||||
#endif//SYSTEM_H
|
||||
|
Loading…
Reference in New Issue
Block a user