corda/src/main.cpp

274 lines
5.4 KiB
C++
Raw Normal View History

2007-06-20 19:20:25 +00:00
#include "sys/mman.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "system.h"
#include "heap.h"
#include "vm.h"
using namespace vm;
namespace {
class System: public vm::System {
public:
2007-06-20 21:27:22 +00:00
class Monitor: public vm::System::Monitor {
public:
Monitor(vm::System* s): s(s) { }
virtual bool tryAcquire(void*) { return true; }
virtual void acquire(void*) { }
virtual void release(void*) { }
virtual void wait(void*) { }
virtual void notify(void*) { }
virtual void notifyAll(void*) { }
virtual void dispose() { s->free(this); }
vm::System* s;
};
2007-06-20 19:20:25 +00:00
System(unsigned limit): limit(limit), count(0) { }
virtual bool success(Status s) {
return s == 0;
}
2007-06-22 02:13:17 +00:00
virtual void* tryAllocate(unsigned size) {
if (count + size > limit) {
return 0;
2007-06-20 19:20:25 +00:00
}
2007-06-22 02:13:17 +00:00
uintptr_t* up = static_cast<uintptr_t*>(malloc(size + sizeof(uintptr_t)));
2007-06-20 19:20:25 +00:00
if (up == 0) abort();
2007-06-22 02:13:17 +00:00
*up = size;
2007-06-21 01:38:02 +00:00
count += *up;
2007-06-20 19:20:25 +00:00
return up + 1;
}
virtual void free(const void* p) {
if (p) {
const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1;
2007-06-21 01:38:02 +00:00
if (count < *up) {
abort();
}
2007-06-20 19:20:25 +00:00
count -= *up;
2007-06-21 01:38:02 +00:00
2007-06-20 19:20:25 +00:00
::free(const_cast<uintptr_t*>(up));
}
}
virtual Status start(Thread*) {
return 1;
}
2007-06-20 21:27:22 +00:00
virtual Status make(vm::System::Monitor** m) {
*m = new (vm::System::allocate(sizeof(Monitor))) Monitor(this);
return 0;
2007-06-20 19:20:25 +00:00
}
virtual void abort() {
::abort();
}
unsigned limit;
unsigned count;
};
const char*
2007-06-21 01:38:02 +00:00
append(vm::System* s, const char* a, const char* b, const char* c,
const char* d)
2007-06-20 19:20:25 +00:00
{
unsigned al = strlen(a);
unsigned bl = strlen(b);
unsigned cl = strlen(c);
2007-06-21 01:38:02 +00:00
unsigned dl = strlen(d);
char* p = static_cast<char*>(s->allocate(al + bl + cl + dl + 1));
2007-06-20 19:20:25 +00:00
memcpy(p, a, al);
memcpy(p + al, b, bl);
2007-06-21 01:38:02 +00:00
memcpy(p + al + bl, c, cl);
memcpy(p + al + bl + cl, d, dl + 1);
2007-06-20 19:20:25 +00:00
return p;
}
class ClassFinder: public vm::ClassFinder {
public:
ClassFinder(vm::System* system, const char** path):
system(system),
path(path)
{ }
class Data: public vm::ClassFinder::Data {
public:
2007-06-21 01:38:02 +00:00
Data(vm::System* system, uint8_t* start, size_t length):
system(system),
2007-06-20 19:20:25 +00:00
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_);
}
2007-06-21 01:38:02 +00:00
system->free(this);
2007-06-20 19:20:25 +00:00
}
2007-06-21 01:38:02 +00:00
vm::System* system;
2007-06-20 19:20:25 +00:00
uint8_t* start_;
size_t length_;
};
virtual Data* find(const char* className) {
2007-06-21 01:38:02 +00:00
Data* d = new (system->allocate(sizeof(Data))) Data(system, 0, 0);
2007-06-20 19:20:25 +00:00
for (const char** p = path; *p; ++p) {
2007-06-21 01:38:02 +00:00
const char* file = append(system, *p, "/", className, ".class");
2007-06-20 19:20:25 +00:00
int fd = open(file, O_RDONLY);
2007-06-21 01:38:02 +00:00
system->free(file);
2007-06-20 19:20:25 +00:00
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;
2007-06-20 21:27:22 +00:00
for (Tokenizer t(path, ':'); t.hasMore(); t.next()) ++ count;
2007-06-20 19:20:25 +00:00
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());
2007-06-21 01:38:02 +00:00
char* p = static_cast<char*>(s->allocate(token.length + 1));
2007-06-20 19:20:25 +00:00
memcpy(p, token.s, token.length);
p[token.length] = 0;
v[i] = p;
}
v[i] = 0;
return v;
}
void
run(unsigned heapSize, const char* path, const char* class_, int argc,
const char** argv)
{
System s(heapSize);
const char** pathv = parsePath(&s, path);
ClassFinder cf(&s, pathv);
Heap* heap = makeHeap(&s);
run(&s, heap, &cf, class_, argc, argv);
heap->dispose();
for (const char** p = pathv; *p; ++p) {
s.free(*p);
}
s.free(pathv);
}
void
usageAndExit(const char* name)
{
fprintf(stderr, "usage: %s [-cp <classpath>] [-hs <maximum heap size>] "
2007-06-20 21:27:22 +00:00
"<class name> [<argument> ...]\n", name);
2007-06-20 19:20:25 +00:00
exit(-1);
}
} // namespace
int
main(int ac, const char** av)
{
unsigned heapSize = 4 * 1024 * 1024;
const char* path = ".";
const char* class_ = 0;
int argc = 0;
const char** argv = 0;
for (int i = 1; i < ac; ++i) {
if (strcmp(av[i], "-cp") == 0) {
path = av[++i];
} else if (strcmp(av[i], "-hs") == 0) {
heapSize = atoi(av[++i]);
} else {
class_ = av[i++];
if (i < ac) {
argc = ac - i;
argv = av + i;
i = ac;
}
}
}
if (class_ == 0) {
usageAndExit(av[0]);
}
run(heapSize, path, class_, argc, argv);
return 0;
}