home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
kaffe-0.5p4-src.tgz
/
tar.out
/
contrib
/
kaffe
/
kaffevm
/
intrp
/
machine.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
5KB
|
212 lines
/*
* machine.c
* Java virtual machine interpreter.
*
* Copyright (c) 1996 Systems Architecture Research Centre,
* City University, London, UK.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* Written by Tim Wilkinson <tim@sarc.city.ac.uk>, May, June 1996.
*/
#define DBG(s)
#define RDBG(s)
#define NDBG(s)
#define IDBG(s)
#include "config.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <setjmp.h>
#include <math.h>
#if defined(HAVE_MALLOC_H)
#include <malloc.h>
#endif
#include "gtypes.h"
#include "bytecode.h"
#include "slots.h"
#include "machine.h"
#include "icode.h"
#include "access.h"
#include "object.h"
#include "constants.h"
#include "classMethod.h"
#include "lookup.h"
#include "soft.h"
#include "exception.h"
#include "external.h"
#include "baseClasses.h"
#include "checks.h"
#include "gc.h"
#define define_insn(code) break; \
case code: \
IDBG( printf("%03d: %s\n", pc, #code); )
void unimp(void);
/*
* Length of each opcode.
*/
static uint8 oplen[256] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 3, 2, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, 0, 1, 1, 1, 1,
1, 1, 3, 3, 3, 3, 3, 3, 3, 5, 1, 3, 2, 3, 1, 1,
3, 3, 1, 1, 2, 4, 3, 3, 5, 5, 1, 1, 1, 1, 1, 1,
1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
/* Call, field and creation information */
callInfo cinfo;
fieldInfo flinfo;
createInfo crinfo;
exceptionInfo info;
/* Misc machine variables */
jint cc;
jlong lcc;
slots* cnst;
slots tmp[1];
slots tmp2[1];
slots mtable[1];
/* Slot to store the return value */
slots retarg[1];
/* Misc stuff */
jmp_buf* cjbuf;
object* exceptionObject;
#define code ((bytecode*)meth->code)
void
virtualMachine(methods* meth, slots* arg)
{
slots* lcl;
int sp;
uintp pc;
uintp npc;
object* mobj;
jmp_buf mjbuf;
jmp_buf* pjbuf;
/* Variables used directly in the machine */
uint16 wide;
int32 idx;
jint low;
jint high;
/* If this is native, then call the real function */
if (meth->accflags & ACC_NATIVE) {
NDBG( printf("Call to native %s.%s%s.\n", meth->class->name, meth->pair->s1, meth->pair->s2); )
native(meth);
(*(void(*)(void*))meth->ncode)(arg);
return;
}
/* Allocate stack space and locals. */
lcl = alloca(sizeof(slots) * (meth->localsz + meth->stacksz));
mobj = 0;
pc = 0;
npc = 0;
/* If we have any exception handlers we must prepare to catch them.
* We also need to catch if we are synchronised (so we can release it).
*/
pjbuf = cjbuf;
if (meth->exception_table_len > 0 || (meth->accflags & ACC_SYNCHRONISED)) {
cjbuf = &mjbuf;
if (setjmp(mjbuf) != 0) {
/* Look for handler */
if (findExceptionBlockInMethod(pc, exceptionObject->dtable->class, meth, &info) == false) {
/* If not here, exit monitor if synchronised. */
if (mobj != 0) {
soft_monitorexit(mobj);
}
/* Rethrow exception */
cjbuf = pjbuf;
throwException(exceptionObject);
}
cjbuf = &mjbuf;
npc = info.handler;
sp = meth->stacksz - 1;
lcl[meth->localsz+sp].v.taddr = exceptionObject;
goto restart;
}
}
/* Calculate number of arguments */
idx = meth->ins + (meth->accflags & ACC_STATIC ? 0 : 1);
DBG( printf("Call to method %s.%s%s.\n", meth->class->name, meth->pair->s1, meth->pair->s2); )
/* Copy in the arguments */
for (sp = 0; sp < idx; sp++) {
lcl[sp] = arg[idx - sp - 1];
}
/* And zero the rest */
for(; sp < meth->localsz; sp++) {
lcl[sp].v.tint = 0;
}
/* Sync. if required */
if (meth->accflags & ACC_SYNCHRONISED) {
if (meth->accflags & ACC_STATIC) {
mobj = &meth->class->head;
}
else {
mobj = (object*)lcl[0].v.taddr;
}
soft_monitorenter(mobj);
}
sp = meth->stacksz;
restart:
wide = 0;
/* Finally we get to actually execute the machine */
for (;;) {
assert(npc < meth->codelen);
pc = npc;
npc = pc + oplen[code[pc]];
switch (code[pc]) {
default:
unimp();
#include "kaffe.def"
}
}
end:
/* Unsync. if required */
if (mobj != 0) {
soft_monitorexit(mobj);
}
cjbuf = pjbuf;
RDBG( printf("Returning from method %s%s.\n", meth->pair->s1, meth->pair->s2); )
}
void
unimp(void)
{
assert("Unimplemented VM function" == 0);
}