mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
snapshot
This commit is contained in:
parent
f68f455d59
commit
9dc8b0529d
11
src/system.h
11
src/system.h
@ -27,6 +27,13 @@ class System {
|
|||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Library {
|
||||||
|
public:
|
||||||
|
virtual ~Library() { }
|
||||||
|
virtual void* resolve(const char* function) = 0;
|
||||||
|
virtual Library* next() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~System() { }
|
virtual ~System() { }
|
||||||
|
|
||||||
virtual bool success(Status) = 0;
|
virtual bool success(Status) = 0;
|
||||||
@ -34,6 +41,10 @@ class System {
|
|||||||
virtual void free(const void*) = 0;
|
virtual void free(const void*) = 0;
|
||||||
virtual Status start(Thread*) = 0;
|
virtual Status start(Thread*) = 0;
|
||||||
virtual Status make(Monitor**) = 0;
|
virtual Status make(Monitor**) = 0;
|
||||||
|
virtual uint64_t call(void* function, unsigned argumentCount,
|
||||||
|
uint32_t* argumentTable, uint8_t* argumentSizeTable,
|
||||||
|
unsigned returnSize);
|
||||||
|
virtual Status load(Library**, const char* name, Library* next);
|
||||||
virtual void abort() = 0;
|
virtual void abort() = 0;
|
||||||
|
|
||||||
void* allocate(unsigned size) {
|
void* allocate(unsigned size) {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
(type field
|
(type field
|
||||||
(uint16_t flags)
|
(uint16_t flags)
|
||||||
(uint16_t offset)
|
(uint16_t offset)
|
||||||
|
(uint8_t code)
|
||||||
(object name)
|
(object name)
|
||||||
(object spec)
|
(object spec)
|
||||||
(object class))
|
(object class))
|
||||||
@ -31,6 +32,12 @@
|
|||||||
(object class)
|
(object class)
|
||||||
(object code))
|
(object code))
|
||||||
|
|
||||||
|
(type nativeMethodData
|
||||||
|
(void* pointer)
|
||||||
|
(uint16_t argumentTableSize)
|
||||||
|
(uint8_t returnCode)
|
||||||
|
(array uint8_t parameterCodes))
|
||||||
|
|
||||||
(pod exceptionHandler
|
(pod exceptionHandler
|
||||||
(uint16_t start)
|
(uint16_t start)
|
||||||
(uint16_t end)
|
(uint16_t end)
|
||||||
|
366
src/vm.cpp
366
src/vm.cpp
@ -20,11 +20,14 @@ static const bool Debug = true;
|
|||||||
|
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
|
void (*Initializer)(Thread*, object);
|
||||||
|
|
||||||
void assert(Thread*, bool);
|
void assert(Thread*, bool);
|
||||||
object resolveClass(Thread*, object);
|
object resolveClass(Thread*, object);
|
||||||
object allocate(Thread*, unsigned);
|
object allocate(Thread*, unsigned);
|
||||||
object& arrayBodyUnsafe(Thread*, object, unsigned);
|
object& arrayBodyUnsafe(Thread*, object, unsigned);
|
||||||
void set(Thread*, object&, object);
|
void set(Thread*, object&, object);
|
||||||
|
object bootstrapInitializers(Thread*);
|
||||||
|
|
||||||
object&
|
object&
|
||||||
objectClass(object o)
|
objectClass(object o)
|
||||||
@ -32,6 +35,18 @@ objectClass(object o)
|
|||||||
return cast<object>(o, 0);
|
return cast<object>(o, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum FieldCode {
|
||||||
|
ByteField,
|
||||||
|
CharField,
|
||||||
|
DoubleField,
|
||||||
|
FloatField,
|
||||||
|
IntField,
|
||||||
|
LongField,
|
||||||
|
ShortField,
|
||||||
|
BooleanField,
|
||||||
|
ObjectField
|
||||||
|
};
|
||||||
|
|
||||||
class Machine {
|
class Machine {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
@ -250,9 +265,11 @@ Thread::Thread(Machine* m):
|
|||||||
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
|
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
|
||||||
set(t, objectClass(intArrayClass), classClass);
|
set(t, objectClass(intArrayClass), classClass);
|
||||||
|
|
||||||
|
m->unsafe = false;
|
||||||
|
|
||||||
m->classMap = makeHashMap(this, 0, 0);
|
m->classMap = makeHashMap(this, 0, 0);
|
||||||
|
|
||||||
m->unsafe = false;
|
m->bootstrapInitializers = bootstrapInitializers(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,64 +742,161 @@ isLongOrDouble(Thread* t, object o)
|
|||||||
or objectClass(o) == arrayBody(t, t->vm->types, Machine::DoubleType);
|
or objectClass(o) == arrayBody(t, t->vm->types, Machine::DoubleType);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
unsigned
|
||||||
getField(Thread* t, object instance, object field)
|
fieldCode(unsigned javaCode)
|
||||||
{
|
{
|
||||||
switch (byteArrayBody(t, fieldSpec(t, field), 0)) {
|
switch (javaCode) {
|
||||||
case 'B':
|
case 'B':
|
||||||
return makeByte(t, cast<int8_t>(instance, fieldOffset(t, field)));
|
return ByteField;
|
||||||
case 'C':
|
case 'C':
|
||||||
return makeChar(t, cast<int16_t>(instance, fieldOffset(t, field)));
|
return CharField;
|
||||||
case 'D':
|
case 'D':
|
||||||
return makeDouble(t, cast<int64_t>(instance, fieldOffset(t, field)));
|
return DoubleField;
|
||||||
case 'F':
|
case 'F':
|
||||||
return makeFloat(t, cast<int32_t>(instance, fieldOffset(t, field)));
|
return FloatField;
|
||||||
case 'I':
|
case 'I':
|
||||||
return makeInt(t, cast<int32_t>(instance, fieldOffset(t, field)));
|
return IntField;
|
||||||
case 'J':
|
case 'J':
|
||||||
return makeLong(t, cast<int64_t>(instance, fieldOffset(t, field)));
|
return LongField;
|
||||||
case 'S':
|
case 'S':
|
||||||
return makeShort(t, cast<int16_t>(instance, fieldOffset(t, field)));
|
return ShortField;
|
||||||
case 'Z':
|
case 'Z':
|
||||||
return makeBoolean(t, cast<int8_t>(instance, fieldOffset(t, field)));
|
return BooleanField;
|
||||||
case 'L':
|
case 'L':
|
||||||
case '[':
|
case '[':
|
||||||
|
return ObjectField;
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
primitiveValue(Thread* t, unsigned code, object o)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
case ByteField:
|
||||||
|
return byteValue(t, o);
|
||||||
|
case CharField:
|
||||||
|
return charValue(t, o);
|
||||||
|
case DoubleField:
|
||||||
|
return doubleValue(t, o);
|
||||||
|
case FloatField:
|
||||||
|
return floatValue(t, o);
|
||||||
|
case IntField:
|
||||||
|
return intValue(t, o);
|
||||||
|
case LongField:
|
||||||
|
return longValue(t, o);
|
||||||
|
case ShortField:
|
||||||
|
return shortValue(t, o);
|
||||||
|
case BooleanField:
|
||||||
|
return booleanValue(t, o);
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
makePrimitive(Thread* t, unsigned code, uint64_t value)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
case ByteField:
|
||||||
|
return makeByte(t, value);
|
||||||
|
case CharField:
|
||||||
|
return makeChar(t, value);
|
||||||
|
case DoubleField:
|
||||||
|
return makeDouble(t, value);
|
||||||
|
case FloatField:
|
||||||
|
return makeFloat(t, value);
|
||||||
|
case IntField:
|
||||||
|
return makeInt(t, value);
|
||||||
|
case LongField:
|
||||||
|
return makeLong(t, value);
|
||||||
|
case ShortField:
|
||||||
|
return makeShort(t, value);
|
||||||
|
case BooleanField:
|
||||||
|
return makeBoolean(t, value);
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
primitiveSize(unsigned code)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
case ByteField:
|
||||||
|
case BooleanField:
|
||||||
|
return 1;
|
||||||
|
case CharField:
|
||||||
|
case ShortField:
|
||||||
|
return 2;
|
||||||
|
case DoubleField:
|
||||||
|
case LongField:
|
||||||
|
return 8;
|
||||||
|
case FloatField:
|
||||||
|
case IntField:
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
default: abort(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
getField(Thread* t, object instance, object field)
|
||||||
|
{
|
||||||
|
switch (fieldCode(t, field)) {
|
||||||
|
case ByteField:
|
||||||
|
return makeByte(t, cast<int8_t>(instance, fieldOffset(t, field)));
|
||||||
|
case CharField:
|
||||||
|
return makeChar(t, cast<int16_t>(instance, fieldOffset(t, field)));
|
||||||
|
case DoubleField:
|
||||||
|
return makeDouble(t, cast<int64_t>(instance, fieldOffset(t, field)));
|
||||||
|
case FloatField:
|
||||||
|
return makeFloat(t, cast<int32_t>(instance, fieldOffset(t, field)));
|
||||||
|
case IntField:
|
||||||
|
return makeInt(t, cast<int32_t>(instance, fieldOffset(t, field)));
|
||||||
|
case LongField:
|
||||||
|
return makeLong(t, cast<int64_t>(instance, fieldOffset(t, field)));
|
||||||
|
case ShortField:
|
||||||
|
return makeShort(t, cast<int16_t>(instance, fieldOffset(t, field)));
|
||||||
|
case BooleanField:
|
||||||
|
return makeBoolean(t, cast<int8_t>(instance, fieldOffset(t, field)));
|
||||||
|
case ObjectField:
|
||||||
return cast<object>(instance, fieldOffset(t, field));
|
return cast<object>(instance, fieldOffset(t, field));
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
void
|
||||||
setField(Thread* t, object o, object field, object value)
|
setField(Thread* t, object o, object field, object value)
|
||||||
{
|
{
|
||||||
switch (byteArrayBody(t, fieldSpec(t, field), 0)) {
|
switch (fieldCode(t, field)) {
|
||||||
case 'B':
|
case ByteField:
|
||||||
cast<int8_t>(o, fieldOffset(t, field)) = byteValue(t, value);
|
cast<int8_t>(o, fieldOffset(t, field)) = byteValue(t, value);
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case CharField:
|
||||||
cast<int16_t>(o, fieldOffset(t, field)) = charValue(t, value);
|
cast<int16_t>(o, fieldOffset(t, field)) = charValue(t, value);
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case DoubleField:
|
||||||
cast<int64_t>(o, fieldOffset(t, field)) = doubleValue(t, value);
|
cast<int64_t>(o, fieldOffset(t, field)) = doubleValue(t, value);
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case FloatField:
|
||||||
cast<int32_t>(o, fieldOffset(t, field)) = floatValue(t, value);
|
cast<int32_t>(o, fieldOffset(t, field)) = floatValue(t, value);
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case IntField:
|
||||||
cast<int32_t>(o, fieldOffset(t, field)) = intValue(t, value);
|
cast<int32_t>(o, fieldOffset(t, field)) = intValue(t, value);
|
||||||
break;
|
break;
|
||||||
case 'J':
|
case LongField:
|
||||||
cast<int64_t>(o, fieldOffset(t, field)) = longValue(t, value);
|
cast<int64_t>(o, fieldOffset(t, field)) = longValue(t, value);
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case ShortField:
|
||||||
cast<int16_t>(o, fieldOffset(t, field)) = shortValue(t, value);
|
cast<int16_t>(o, fieldOffset(t, field)) = shortValue(t, value);
|
||||||
break;
|
break;
|
||||||
case 'Z':
|
case BooleanField:
|
||||||
cast<int8_t>(o, fieldOffset(t, field)) = booleanValue(t, value);
|
cast<int8_t>(o, fieldOffset(t, field)) = booleanValue(t, value);
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case ObjectField:
|
||||||
case '[':
|
|
||||||
set(t, cast<object>(o, fieldOffset(t, field)), value);
|
set(t, cast<object>(o, fieldOffset(t, field)), value);
|
||||||
|
|
||||||
default: abort(t);
|
default: abort(t);
|
||||||
@ -1277,40 +1391,14 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
set(t, classInterfaceTable(t, class_), interfaceTable);
|
set(t, classInterfaceTable(t, class_), interfaceTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
inline unsigned
|
||||||
isReferenceField(Thread* t, object field)
|
|
||||||
{
|
|
||||||
switch (byteArrayBody(t, fieldSpec(t, field), 0)) {
|
|
||||||
case 'L':
|
|
||||||
case '[':
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned
|
|
||||||
fieldSize(Thread* t, object field)
|
fieldSize(Thread* t, object field)
|
||||||
{
|
{
|
||||||
switch (byteArrayBody(t, fieldSpec(t, field), 0)) {
|
unsigned code = fieldCode(t, field);
|
||||||
case 'B':
|
if (code == ObjectField) {
|
||||||
return 1;
|
|
||||||
case 'C':
|
|
||||||
case 'S':
|
|
||||||
case 'Z':
|
|
||||||
return 2;
|
|
||||||
case 'D':
|
|
||||||
case 'J':
|
|
||||||
return 8;
|
|
||||||
case 'F':
|
|
||||||
case 'I':
|
|
||||||
return 4;
|
|
||||||
case 'L':
|
|
||||||
case '[':
|
|
||||||
return BytesPerWord;
|
return BytesPerWord;
|
||||||
|
} else {
|
||||||
default: abort(t);
|
return primitiveSize(code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1343,18 +1431,20 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
s.skip(s.read4());
|
s.skip(s.read4());
|
||||||
}
|
}
|
||||||
|
|
||||||
object value = makeField(t,
|
object value = makeField
|
||||||
flags,
|
(t,
|
||||||
0, // offset
|
flags,
|
||||||
arrayBody(t, pool, name - 1),
|
0, // offset
|
||||||
arrayBody(t, pool, spec - 1),
|
fieldCode(byteArrayBody(t, arrayBody(t, pool, spec - 1), 0)),
|
||||||
class_);
|
arrayBody(t, pool, name - 1),
|
||||||
|
arrayBody(t, pool, spec - 1),
|
||||||
|
class_);
|
||||||
|
|
||||||
if (flags & ACC_STATIC) {
|
if (flags & ACC_STATIC) {
|
||||||
fieldOffset(t, value) = staticOffset++;
|
fieldOffset(t, value) = staticOffset++;
|
||||||
} else {
|
} else {
|
||||||
unsigned excess = memberOffset % BytesPerWord;
|
unsigned excess = memberOffset % BytesPerWord;
|
||||||
if (excess and isReferenceField(t, value)) {
|
if (excess and fieldCode(t, value) == ObjectField) {
|
||||||
memberOffset += BytesPerWord - excess;
|
memberOffset += BytesPerWord - excess;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1385,7 +1475,7 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
if (fieldTable) {
|
if (fieldTable) {
|
||||||
for (int i = arrayLength(t, fieldTable) - 1; i >= 0; --i) {
|
for (int i = arrayLength(t, fieldTable) - 1; i >= 0; --i) {
|
||||||
object field = arrayBody(t, fieldTable, i);
|
object field = arrayBody(t, fieldTable, i);
|
||||||
if (isReferenceField(t, field)) {
|
if (fieldCode(t, field) == ObjectField) {
|
||||||
unsigned index = fieldOffset(t, field) / BytesPerWord;
|
unsigned index = fieldOffset(t, field) / BytesPerWord;
|
||||||
intArrayBody(t, mask, (index / 32)) |= 1 << (index % 32);
|
intArrayBody(t, mask, (index / 32)) |= 1 << (index % 32);
|
||||||
sawReferenceField = true;
|
sawReferenceField = true;
|
||||||
@ -1682,6 +1772,12 @@ resolveClass(Thread* t, object spec)
|
|||||||
|
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
|
object initializer = hashMapFind
|
||||||
|
(t, t->vm->bootstrapInitializers, spec, byteArrayHash, byteArrayEqual);
|
||||||
|
if (initializer) {
|
||||||
|
static_cast<Initializer>(pointerValue(t, initializer))(t, class_);
|
||||||
|
}
|
||||||
|
|
||||||
hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash);
|
hashMapInsert(t, t->vm->classMap, spec, class_, byteArrayHash);
|
||||||
} else {
|
} else {
|
||||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||||
@ -1752,6 +1848,89 @@ resolveMethod(Thread* t, object pool, unsigned index)
|
|||||||
return resolve(t, pool, index, findMethodInClass);
|
return resolve(t, pool, index, findMethodInClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
resolveNativeMethodData(Thread* t, object method)
|
||||||
|
{
|
||||||
|
if (objectClass(methodCode(t, method))
|
||||||
|
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
||||||
|
{
|
||||||
|
for (System::Library lib = t->vm->libraries; lib; lib = lib->next()) {
|
||||||
|
void* p = lib->resolve(reinterpret_cast<const char*>
|
||||||
|
(&byteArrayBody(t, methodCode(t, method), 0)));
|
||||||
|
if (p) {
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
object data = makeNativeMethodData(t,
|
||||||
|
p,
|
||||||
|
0, // argument table size
|
||||||
|
0, // return code
|
||||||
|
parameterCount,
|
||||||
|
false);
|
||||||
|
|
||||||
|
unsigned argumentTableSize = 0;
|
||||||
|
unsigned index = 0;
|
||||||
|
const char* s = reinterpret_cast<const char*>
|
||||||
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
|
++ s; // skip '('
|
||||||
|
while (*s and *s != ')') {
|
||||||
|
unsigned code = fieldCode(*s);
|
||||||
|
nativeMethodDataParameterCodes(t, data, index++) = code;
|
||||||
|
|
||||||
|
switch (*s) {
|
||||||
|
case 'L':
|
||||||
|
argumentTableSize += 1;
|
||||||
|
while (*s and *s != ';') ++ s;
|
||||||
|
++ s;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
argumentTableSize += 1;
|
||||||
|
while (*s == '[') ++ s;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
argumentTableSize += divide(primitiveSize(code), 4);
|
||||||
|
++ s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeMethodDataArgumentTableSize(t, data) = argumentTableSize;
|
||||||
|
nativeMethodReturnCode(t, data) = fieldCode(s[1]);
|
||||||
|
|
||||||
|
set(t, methodCode(t, method), data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return methodCode(t, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bsiVM(Thread* t, object class_)
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
bootstrapInitializers(Thread* t)
|
||||||
|
{
|
||||||
|
object map = makeHashMap(t, 0, 0);
|
||||||
|
PROTECT(t, map);
|
||||||
|
object key = 0;
|
||||||
|
PROTECT(t, key);
|
||||||
|
object value;
|
||||||
|
|
||||||
|
key = makeByteArray(t, "vm/VM");
|
||||||
|
value = makePointer(t, bsiVM);
|
||||||
|
hashMapInsert(t, map, key, value, hashByteArray);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
run(Thread* t)
|
run(Thread* t)
|
||||||
{
|
{
|
||||||
@ -3120,24 +3299,73 @@ run(Thread* t)
|
|||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned base = sp - parameterCount;
|
||||||
|
|
||||||
if (methodFlags(t, code) & ACC_NATIVE) {
|
if (methodFlags(t, code) & ACC_NATIVE) {
|
||||||
// todo
|
object data = resolveNativeMethodData(t, code);
|
||||||
abort(t);
|
if (UNLIKELY(data == 0)) {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s.%s:%s",
|
||||||
|
&byteArrayBody(t, className(t, methodClass(t, code)), 0),
|
||||||
|
&byteArrayBody(t, methodName(t, code), 0),
|
||||||
|
&byteArrayBody(t, methodSpec(t, code), 0));
|
||||||
|
exception = makeUnsatifiedLinkError(t, message);
|
||||||
|
goto throw_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t* args[nativeMethodDataArgumentTableSize(t, data)];
|
||||||
|
uint8_t sizes[parameterCount];
|
||||||
|
unsigned offset = 0;
|
||||||
|
for (unsigned i = 0; i < parameterCount; ++i) {
|
||||||
|
unsigned code = nativeMethodDataParameterCodes(t, data);
|
||||||
|
|
||||||
|
if (code == ObjectField) {
|
||||||
|
size[i] = 4;
|
||||||
|
args[offset++] = sp + i + 1;
|
||||||
|
} else {
|
||||||
|
size[i] = primitiveSize(code);
|
||||||
|
uint64_t v = primitiveValue(t, code, stack[sp + i]);
|
||||||
|
if (size[i] == 8) {
|
||||||
|
args[offset++] = v & 0xFFFFFFFF;
|
||||||
|
args[offset++] = v >> 32;
|
||||||
|
} else {
|
||||||
|
args[offset++] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned returnCode = nativeMethodDataReturnCode(t, data);
|
||||||
|
unsigned returnSize
|
||||||
|
= (code == ObjectField ? 4 : primitiveSize(returnCode));
|
||||||
|
|
||||||
|
uint64_t rv = t->vm->system->call(nativeMethodDataPointer(t, data),
|
||||||
|
parameterCount,
|
||||||
|
args,
|
||||||
|
sizes,
|
||||||
|
returnSize);
|
||||||
|
|
||||||
|
sp = base;
|
||||||
|
|
||||||
|
if (returnCode == ObjectField) {
|
||||||
|
push(t, (rv == 0 ? 0 : stack[rv - 1]));
|
||||||
|
} else {
|
||||||
|
push(t, makePrimitive(t, returnCode, rv));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
frameIp(t, frame) = ip;
|
frameIp(t, frame) = ip;
|
||||||
ip = 0;
|
ip = 0;
|
||||||
|
|
||||||
sp -= parameterCount;
|
frame = makeFrame(t, code, frame, 0, base,
|
||||||
|
|
||||||
frame = makeFrame(t, code, frame, 0, sp,
|
|
||||||
codeMaxLocals(t, methodCode(t, code)), false);
|
codeMaxLocals(t, methodCode(t, code)), false);
|
||||||
code = methodCode(t, code);
|
code = methodCode(t, code);
|
||||||
|
|
||||||
memcpy(&frameLocals(t, frame, 0), stack + sp,
|
memcpy(&frameLocals(t, frame, 0), stack + base,
|
||||||
parameterCount * BytesPerWord);
|
parameterCount * BytesPerWord);
|
||||||
|
|
||||||
memset(&frameLocals(t, frame, 0) + parameterCount, 0,
|
memset(&frameLocals(t, frame, 0) + parameterCount, 0,
|
||||||
(frameLength(t, frame) - parameterCount) * BytesPerWord);
|
(frameLength(t, frame) - parameterCount) * BytesPerWord);
|
||||||
|
|
||||||
|
sp = base;
|
||||||
}
|
}
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user