mirror of
https://github.com/corda/corda.git
synced 2025-02-05 10:39:13 +00:00
sketch parseClass()
This commit is contained in:
parent
bb2494be83
commit
9e356c1b40
@ -200,6 +200,20 @@ enum TypeCode {
|
|||||||
T_LONG = 11
|
T_LONG = 11
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Constant {
|
||||||
|
CONSTANT_Class = 7,
|
||||||
|
CONSTANT_Fieldref = 9,
|
||||||
|
CONSTANT_Methodref = 10,
|
||||||
|
CONSTANT_InterfaceMethodref = 11,
|
||||||
|
CONSTANT_String = 8,
|
||||||
|
CONSTANT_Integer = 3,
|
||||||
|
CONSTANT_Float = 4,
|
||||||
|
CONSTANT_Long = 5,
|
||||||
|
CONSTANT_Double = 6,
|
||||||
|
CONSTANT_NameAndType = 12,
|
||||||
|
CONSTANT_Utf8 = 1
|
||||||
|
};
|
||||||
|
|
||||||
const unsigned ACC_PUBLIC = 1 << 0;
|
const unsigned ACC_PUBLIC = 1 << 0;
|
||||||
const unsigned ACC_FINAL = 1 << 4;
|
const unsigned ACC_FINAL = 1 << 4;
|
||||||
const unsigned ACC_SUPER = 1 << 5;
|
const unsigned ACC_SUPER = 1 << 5;
|
||||||
|
74
src/stream.h
Normal file
74
src/stream.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#ifndef STREAM_H
|
||||||
|
#define STREAM_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
class Stream {
|
||||||
|
public:
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
virtual ~Client() { }
|
||||||
|
virtual void NO_RETURN handleEOS() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stream(Client* client, const uint8_t* data, unsigned size):
|
||||||
|
client(client), data(data), size(size), position(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void skip(unsigned size) {
|
||||||
|
if (size > this->size - position) {
|
||||||
|
client->handleEOS();
|
||||||
|
} else {
|
||||||
|
position += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(uint8_t* data, unsigned size) {
|
||||||
|
if (size > this->size - position) {
|
||||||
|
client->handleEOS();
|
||||||
|
} else {
|
||||||
|
memcpy(data, this->data + position, size);
|
||||||
|
position += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read1() {
|
||||||
|
uint8_t v;
|
||||||
|
read(&v, 1);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t read2() {
|
||||||
|
uint16_t a = read1();
|
||||||
|
uint16_t b = read1();
|
||||||
|
return (a << 8) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t read4() {
|
||||||
|
uint32_t a = read2();
|
||||||
|
uint32_t b = read2();
|
||||||
|
return (a << 16) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t read8() {
|
||||||
|
uint64_t a = read4();
|
||||||
|
uint64_t b = read4();
|
||||||
|
return (a << 32) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t readFloat() {
|
||||||
|
#error todo
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t readDouble() {
|
||||||
|
#error todo
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Client* client;
|
||||||
|
const uint8_t* data;
|
||||||
|
unsigned size;
|
||||||
|
unsigned position;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif//STREAM_H
|
202
src/vm.cpp
202
src/vm.cpp
@ -2,6 +2,7 @@
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "class_finder.h"
|
#include "class_finder.h"
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
#define PROTECT(thread, name) \
|
#define PROTECT(thread, name) \
|
||||||
Thread::Protector MAKE_NAME(protector_) (thread, &name);
|
Thread::Protector MAKE_NAME(protector_) (thread, &name);
|
||||||
@ -42,6 +43,7 @@ class Machine {
|
|||||||
Thread* exclusive;
|
Thread* exclusive;
|
||||||
unsigned activeCount;
|
unsigned activeCount;
|
||||||
unsigned liveCount;
|
unsigned liveCount;
|
||||||
|
unsigned nextClassId;
|
||||||
System::Monitor* stateLock;
|
System::Monitor* stateLock;
|
||||||
System::Monitor* heapLock;
|
System::Monitor* heapLock;
|
||||||
System::Monitor* classLock;
|
System::Monitor* classLock;
|
||||||
@ -144,6 +146,7 @@ init(Machine* m, System* sys, Heap* heap, ClassFinder* classFinder)
|
|||||||
m->sys = sys;
|
m->sys = sys;
|
||||||
m->heap = heap;
|
m->heap = heap;
|
||||||
m->classFinder = classFinder;
|
m->classFinder = classFinder;
|
||||||
|
m->nextClassId = OtherType + 1;
|
||||||
|
|
||||||
if (not sys->success(sys->make(&(m->stateLock))) or
|
if (not sys->success(sys->make(&(m->stateLock))) or
|
||||||
not sys->success(sys->make(&(m->heapLock))) or
|
not sys->success(sys->make(&(m->heapLock))) or
|
||||||
@ -692,6 +695,186 @@ hashMapInsert(Thread* t, object map, uint32_t hash, object key, object value)
|
|||||||
set(t, rawArrayBody(t, map)[index], n);
|
set(t, rawArrayBody(t, map)[index], n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
parseClass(Thread* t, const uint8_t* data, unsigned size)
|
||||||
|
{
|
||||||
|
class Client : public Stream::Client {
|
||||||
|
public:
|
||||||
|
Client(Thread* t): t(t) { }
|
||||||
|
|
||||||
|
virtual void NO_RETURN handleEOS() {
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Thread* t;
|
||||||
|
} client(t);
|
||||||
|
|
||||||
|
Stream s(&client, data, size);
|
||||||
|
|
||||||
|
uint32_t magic = s.read4();
|
||||||
|
assert(t, magic == 0xCAFEBABE);
|
||||||
|
s.read2(); // minor version
|
||||||
|
s.read2(); // major version
|
||||||
|
|
||||||
|
unsigned poolCount = s.read2();
|
||||||
|
object pool = makeRawArray(t, poolCount);
|
||||||
|
PROTECT(t, pool);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < poolCount; ++i) {
|
||||||
|
switch (s.read1()) {
|
||||||
|
case CONSTANT_Class: {
|
||||||
|
set(t, rawArrayBody(t, pool)[i], rawArrayBody(t, pool)[s.read2()]);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case CONSTANT_Fieldref:
|
||||||
|
case CONSTANT_Methodref:
|
||||||
|
case CONSTANT_InterfaceMethodref: {
|
||||||
|
object c = rawArrayBody(t, pool)[s.read2()];
|
||||||
|
object nameAndType = rawArrayBody(t, pool)[s.read2()];
|
||||||
|
object value = makeReference
|
||||||
|
(t, c, pairFirst(t, nameAndType), pairSecond(t, nameAndType));
|
||||||
|
set(t, rawArrayBody(t, pool)[i], value);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case CONSTANT_String: {
|
||||||
|
object bytes = rawArrayBody(t, pool)[s.read2()];
|
||||||
|
object value = makeString(t, bytes, 0, byteArrayLength(t, bytes), 0);
|
||||||
|
set(t, rawArrayBody(t, pool)[i], value);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case CONSTANT_Integer: {
|
||||||
|
object value = makeInt(t, s.read4());
|
||||||
|
set(t, rawArrayBody(t, pool)[i], value);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case CONSTANT_Float: {
|
||||||
|
object value = makeFloat(t, s.readFloat());
|
||||||
|
set(t, rawArrayBody(t, pool)[i], value);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case CONSTANT_Long: {
|
||||||
|
object value = makeLong(t, s.read8());
|
||||||
|
set(t, rawArrayBody(t, pool)[i], value);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case CONSTANT_Double: {
|
||||||
|
object value = makeLong(t, s.readDouble());
|
||||||
|
set(t, rawArrayBody(t, pool)[i], value);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case CONSTANT_NameAndType: {
|
||||||
|
object name = rawArrayBody(t, pool)[s.read2()];
|
||||||
|
object type = rawArrayBody(t, pool)[s.read2()];
|
||||||
|
object value = makePair(t, name, type);
|
||||||
|
set(t, rawArrayBody(t, pool)[i], value);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case CONSTANT_Utf8: {
|
||||||
|
unsigned length = s.read2();
|
||||||
|
object value = makeByteArray(t, length);
|
||||||
|
s.read(reinterpret_cast<uint8_t*>(byteArrayBody(t, value)), length);
|
||||||
|
set(t, rawArrayBody(t, pool)[i], value);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned flags = s.read2();
|
||||||
|
unsigned name = s.read2();
|
||||||
|
unsigned super = s.read2();
|
||||||
|
|
||||||
|
unsigned interfaceCount = s.read2();
|
||||||
|
object interfaces = makeRawArray(t, interfaceCount * 2);
|
||||||
|
PROTECT(t, interfaces);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < interfaceCount * 2; i += 2) {
|
||||||
|
set(t, rawArrayBody(t, interfaces)[i], rawArrayBody(t, pool)[s.read2()]);
|
||||||
|
rawArrayBody(t, interfaces)[i + 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
object class_ = makeClass(t,
|
||||||
|
t->vm->nextClassId++,
|
||||||
|
0, // fixed size
|
||||||
|
0, // array size
|
||||||
|
0, // object mask
|
||||||
|
flags,
|
||||||
|
rawArrayBody(t, pool)[name],
|
||||||
|
rawArrayBody(t, pool)[super],
|
||||||
|
interfaces,
|
||||||
|
0, // fields
|
||||||
|
0, // methods
|
||||||
|
0, // static table
|
||||||
|
0); // initializers
|
||||||
|
PROTECT(t, class_);
|
||||||
|
|
||||||
|
unsigned fieldCount = s.read2();
|
||||||
|
object fields = makeRawArray(t, fieldCount * 2);
|
||||||
|
set(t, classFieldTable(t, class_), fields);
|
||||||
|
PROTECT(t, fields);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < fieldCount; ++i) {
|
||||||
|
unsigned flags = s.read2();
|
||||||
|
unsigned name = s.read2();
|
||||||
|
unsigned spec = s.read2();
|
||||||
|
|
||||||
|
unsigned attributeCount = s.read2();
|
||||||
|
for (unsigned j = 0; j < attributeCount; ++j) {
|
||||||
|
s.read2();
|
||||||
|
s.skip(s.read4());
|
||||||
|
}
|
||||||
|
|
||||||
|
object value = makeField(t,
|
||||||
|
flags,
|
||||||
|
0, // offset
|
||||||
|
rawArrayBody(t, pool)[name],
|
||||||
|
rawArrayBody(t, pool)[spec],
|
||||||
|
class_);
|
||||||
|
|
||||||
|
set(t, rawArrayBody(t, fields)[i], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned methodCount = s.read2();
|
||||||
|
object methods = makeRawArray(t, methodCount * 2);
|
||||||
|
set(t, classMethodTable(t, class_), methods);
|
||||||
|
PROTECT(t, methods);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < methodCount; ++i) {
|
||||||
|
unsigned flags = s.read2();
|
||||||
|
unsigned name = s.read2();
|
||||||
|
unsigned spec = s.read2();
|
||||||
|
|
||||||
|
object code = 0;
|
||||||
|
unsigned attributeCount = s.read2();
|
||||||
|
for (unsigned j = 0; j < attributeCount; ++j) {
|
||||||
|
object name = rawArrayBody(t, pool)[s.read2()];
|
||||||
|
if (strcmp(reinterpret_cast<const int8_t*>("Code"),
|
||||||
|
byteArrayBody(t, name)) == 0)
|
||||||
|
{
|
||||||
|
unsigned length = s.read2();
|
||||||
|
code = makeByteArray(t, length);
|
||||||
|
s.read(reinterpret_cast<uint8_t*>(byteArrayBody(t, code)), length);
|
||||||
|
} else {
|
||||||
|
s.skip(s.read4());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object value = makeMethod(t,
|
||||||
|
flags,
|
||||||
|
0, // offset
|
||||||
|
parameterCount(rawArrayBody(t, pool)[spec]),
|
||||||
|
rawArrayBody(t, pool)[name],
|
||||||
|
rawArrayBody(t, pool)[spec],
|
||||||
|
class_,
|
||||||
|
code);
|
||||||
|
|
||||||
|
set(t, rawArrayBody(t, methods)[i], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return class_;
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveClass(Thread* t, object spec)
|
resolveClass(Thread* t, object spec)
|
||||||
{
|
{
|
||||||
@ -706,11 +889,30 @@ resolveClass(Thread* t, object spec)
|
|||||||
(reinterpret_cast<const char*>(byteArrayBody(t, spec)), &size);
|
(reinterpret_cast<const char*>(byteArrayBody(t, spec)), &size);
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
|
// parse class file
|
||||||
class_ = parseClass(t, data, size);
|
class_ = parseClass(t, data, size);
|
||||||
|
|
||||||
t->vm->classFinder->free(data);
|
t->vm->classFinder->free(data);
|
||||||
|
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
|
// resolve superclass
|
||||||
|
object super = resolveClass(t, classSuper(t, class_));
|
||||||
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
set(t, classSuper(t, class_), super);
|
||||||
|
|
||||||
|
#error todo
|
||||||
|
// merge interface table with that of superclass and generate
|
||||||
|
// vtables
|
||||||
|
|
||||||
|
// concatenate field table with those of superclass and populate
|
||||||
|
// offsets
|
||||||
|
|
||||||
|
// merge method table with that of superclass and populate
|
||||||
|
// offsets
|
||||||
|
|
||||||
|
// cache class
|
||||||
hashMapInsert(t, t->vm->classMap, h, spec, class_);
|
hashMapInsert(t, t->vm->classMap, h, spec, class_);
|
||||||
} else {
|
} else {
|
||||||
object message = makeString(t, "%s", byteArrayBody(t, spec));
|
object message = makeString(t, "%s", byteArrayBody(t, spec));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user