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
/
lookup.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
9KB
|
360 lines
/*
* lookup.c
* Various lookup calls for resolving objects, methods, exceptions, etc.
*
* 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>, February 1996.
*/
#define DBG(s)
#define FDBG(s)
#define EDBG(s)
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "gtypes.h"
#include "errors.h"
#include "slots.h"
#include "access.h"
#include "object.h"
#include "constants.h"
#include "classMethod.h"
#include "lookup.h"
#include "exception.h"
#include "thread.h"
#include "baseClasses.h"
#include "machine.h"
extern strpair* initpair;
extern methods* methodList;
extern classes* ObjectClass;
/*
* Lookup a method reference and get the various interesting bits.
*/
void
getMethodSignatureClass(constIndex idx, constants* pool, callInfo* call)
{
constIndex ci;
constIndex ni;
constIndex nin;
constIndex nis;
createInfo cls;
strpair* pair;
char* s;
int i;
int r;
methods* mptr;
classes* cptr;
if (pool->tags[idx] != CONSTANT_Methodref &&
pool->tags[idx] != CONSTANT_InterfaceMethodref) {
DBG( printf("No Methodref found\n"); )
throwException(NoSuchMethodError);
}
ni = METHODREF_NAMEANDTYPE(idx, pool);
if (pool->tags[ni] != CONSTANT_NameAndType) {
DBG( printf("No Methodref:NameAndType found\n"); )
throwException(NoSuchMethodError);
}
nin = NAMEANDTYPE_NAME(ni, pool);
if (pool->tags[nin] != CONSTANT_Utf8) {
DBG( printf("No Methodref:NameAndType:Utf8 found\n"); )
throwException(NoSuchMethodError);
}
nis = NAMEANDTYPE_SIGNATURE(ni, pool);
if (pool->tags[nis] != CONSTANT_Utf8) {
DBG( printf("No Methodref:NameAndType:Utf8 found\n"); )
throwException(NoSuchMethodError);
}
ci = METHODREF_CLASS(idx, pool);
if (pool->tags[ci] != CONSTANT_Class) {
DBG( printf("No Methodref:Class found\n"); )
throwException(NoSuchMethodError);
}
getClass(ci, pool, &cls);
DBG( printf("lookupMethodSignatureClass(%s,%s,%s)\n",
cls.class->name, pool->data[nin], pool->data[nis]); )
/*
* We now have a complete class and method signature. We can
* Now work out some things we might need to know, like no. of
* arguments, address of function, etc.
*/
countInsAndOuts(pool->data[nis].v.tstr, &call->in, &call->out, &call->rettype);
DBG( printf("in = %d, out = %d\n", call->in, call->out); )
pair = lookupStringPair(pool->data[nin].v.tstr, pool->data[nis].v.tstr);
assert(pair != 0);
call->mtag = (int)pair;
call->offset = pair->hash % MAXMETHOD;
call->dtable = cls.class->dtable;
/* Find method */
for (cptr = cls.class; cptr != 0; cptr = cptr->superclass) {
for (mptr = cptr->methodList; mptr != 0; mptr = mptr->next) {
if (mptr->pair == pair) {
goto foundit;
}
}
}
assert("Method not found" == 0);
foundit:
call->idx = mptr->idx;
/* Generate a short signature - used by calls */
if (call->type != 0) {
free(call->type);
}
if (call->in == 0) {
call->type = 0;
}
else {
call->type = malloc(call->in);
assert(call->type != 0);
s = pool->data[nis].v.tstr;
i = 0;
while (i < call->in) {
r = sizeofSigItem(&s, &call->type[i]);
if (r == -1) {
break;
}
else if (r == 2) {
call->type[i+1] = call->type[i];
}
i += r;
}
}
}
void
getClass(constIndex idx, constants* pool, createInfo* create)
{
constIndex cs;
classes* class;
char* cname;
if (pool->tags[idx] != CONSTANT_Class) {
DBG( printf("No Class found\n"); )
throwException(ClassNotFoundException);
}
cs = CLASS_NAME(idx, pool);
if (pool->tags[cs] != CONSTANT_Utf8) {
DBG( printf("No Class:Utf8 found\n"); )
throwException(ClassNotFoundException);
}
cname = pool->data[cs].v.tstr;
DBG( printf("Class name %s\n", cname); )
/* If an array, then treat as an array */
if (cname[0] == '[') {
class = lookupArray(cname);
}
else {
/* Lookup class */
class = lookupClass(cname);
}
if (class == 0) {
DBG( printf("Class %s not loaded.\n", cname); )
throwException(ClassNotFoundException);
}
create->class = class;
}
void
getField(constIndex idx, bool isStatic, constants* pool, fieldInfo* fld)
{
constIndex ci;
constIndex ni;
constIndex cis;
constIndex nin;
constIndex nis;
fields* field;
if (pool->tags[idx] != CONSTANT_Fieldref) {
FDBG( printf("No Fieldref found\n"); )
throwException(NoSuchFieldError);
}
ci = FIELDREF_CLASS(idx, pool);
if (pool->tags[ci] != CONSTANT_Class) {
FDBG( printf("No Methodref:Class found\n"); )
throwException(NoSuchFieldError);
}
ni = FIELDREF_NAMEANDTYPE(idx, pool);
if (pool->tags[ni] != CONSTANT_NameAndType) {
FDBG( printf("No Methodref:NameAndType found\n"); )
throwException(NoSuchFieldError);
}
cis = CLASS_NAME(ci, pool);
if (pool->tags[cis] != CONSTANT_Utf8) {
FDBG( printf("No Methodref:Class:Utf8 found\n"); )
throwException(NoSuchFieldError);
}
nin = NAMEANDTYPE_NAME(ni, pool);
if (pool->tags[nin] != CONSTANT_Utf8) {
FDBG( printf("No Methodref:NameAndType:Utf8 found\n"); )
throwException(NoSuchFieldError);
}
nis = NAMEANDTYPE_SIGNATURE(ni, pool);
if (pool->tags[nis] != CONSTANT_Utf8) {
FDBG( printf("No Methodref:NameAndType:Utf8 found\n"); )
throwException(NoSuchFieldError);
}
FDBG( printf("*** getField(%s,%s,%s)\n",
pool->data[cis], pool->data[nin], pool->data[nis]); )
field = lookupClassField(pool->data[cis].v.tstr, pool->data[nin].v.tstr, isStatic);
if (field == 0) {
FDBG( printf("Field not found\n"); )
throwException(NoSuchFieldError);
}
fld->class = field->class;
fld->size = field->size;
fld->offset = field->offset;
if (field->sig[0] == 'L' || field->sig[0] == '[') {
fld->isref = true;
}
else {
fld->isref = false;
}
FDBG( printf("class=%s, classsize=%d, fldsize=%d, fldoffset=%d\n",
fld->class->name, fld->class->fsize,
fld->size, fld->offset); )
}
/*
* Lookup a method (and translate) in the specified class.
*/
methods*
findMethod(classes* class, strpair* pair)
{
methods* mptr;
/*
* Lookup method - this could be alot more efficient but never mind.
* Also there is no attempt to honour PUBLIC, PRIVATE, etc.
*/
for (; class != 0; class = class->superclass) {
for (mptr = class->methodList; mptr != 0; mptr = mptr->next) {
if (mptr->pair == pair) {
#if defined(TRANSLATOR)
/*
* Generate code on demand.
*/
if (mptr->ncode == 0) {
intsDisable();
translate(mptr);
initClasses();
intsRestore();
}
#endif
return (mptr);
}
}
}
return (0);
}
#if defined(TRANSLATOR)
/*
* Find exception in method.
*/
void
findExceptionInMethod(uintp pc, classes* class, exceptionInfo* info)
{
methods* ptr;
for (ptr = methodList; ptr != 0; ptr = ptr->exception_next) {
if (pc < (uintp)ptr->ncode || pc >= (uintp)ptr->ncode_end) {
continue;
}
EDBG( printf("Found method %s.%s%s\n", ptr->class->name,
ptr->pair->s1, ptr->pair->s2); )
if (findExceptionBlockInMethod(pc, class, ptr, info) == true) {
return;
}
}
EDBG( printf("Exception not found.\n"); )
info->handler = 0;
}
/*
* Find method containing pc.
*/
methods*
findMethodFromPC(uintp pc)
{
methods* ptr;
for (ptr = methodList; ptr != 0; ptr = ptr->exception_next) {
if (pc >= (uintp)ptr->ncode && pc < (uintp)ptr->ncode_end) {
EDBG( printf("Found method %s.%s%s\n",
ptr->class->name,
ptr->pair->s1, ptr->pair->s2); )
break;
}
}
EDBG( if (ptr == 0) printf("Method not found.\n"); )
return (ptr);
}
#endif
/*
* Look for exception block in method.
*/
bool
findExceptionBlockInMethod(uintp pc, classes* class, methods* ptr, exceptionInfo* info)
{
jexception* eptr;
classes* cptr;
int i;
eptr = ptr->exception_table;
EDBG( printf("Nr of exceptions = %d\n", ptr->exception_table_len); )
/* Right method - look for exception */
for (i = 0; i < ptr->exception_table_len; i++) {
EDBG( printf("Exceptions %x (%x-%x)\n", pc, eptr[i].start_pc, eptr[i].end_pc); )
if (pc < eptr[i].start_pc || pc > eptr[i].end_pc) {
continue;
}
EDBG( printf("Found exception 0x%x\n", eptr[i].handler_pc); )
/* Stash info for later date */
info->class = ptr->class;
info->handler = eptr[i].handler_pc;
/* Found exception - is it right type */
if (eptr[i].catch_type == 0) {
return (true);
}
for (cptr = class; cptr != 0; cptr = cptr->superclass) {
if (cptr->name == eptr[i].catch_type) {
return (true);
}
}
}
return (false);
}