[kaffe] CVS kaffe (rob): kaffe/kaffevm/verify*.[ch]
Kaffe CVS
cvs-commits at kaffe.org
Sat Jun 26 17:02:51 PDT 2004
PatchSet 4872
Date: 2004/06/26 23:57:18
Author: rob
Branch: HEAD
Tag: (none)
Log:
* kaffe/kaffevm/verify*.[ch]
Finished adding support for multiple inheritence.
Some more code cleaning: checking off some basic TODOs
Members:
ChangeLog:1.2438->1.2439
kaffe/kaffevm/verifier/verify-sigstack.h:1.2->1.3
kaffe/kaffevm/verifier/verify-type.c:1.3->1.4
kaffe/kaffevm/verifier/verify-type.h:1.3->1.4
kaffe/kaffevm/verifier/verify.c:1.3->1.4
kaffe/kaffevm/verifier/verify2.c:1.3->1.4
Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.2438 kaffe/ChangeLog:1.2439
--- kaffe/ChangeLog:1.2438 Sat Jun 26 20:08:44 2004
+++ kaffe/ChangeLog Sat Jun 26 23:57:18 2004
@@ -1,4 +1,9 @@
2004-06-26 Rob Gonzalez <rob at kaffe.org>
+ * kaffe/kaffevm/verify*.[ch]
+ Finished adding support for multiple inheritence.
+ Some more code cleaning: checking off some basic TODOs.
+
+2004-06-26 Rob Gonzalez <rob at kaffe.org>
* kaffe/kaffevm/external.c
(Kaffe_JNI*) renamed to KaffeVM_JNI*
(Kaffe_KNI*) renamed to KaffeVM_KNI*
Index: kaffe/kaffe/kaffevm/verifier/verify-sigstack.h
diff -u kaffe/kaffe/kaffevm/verifier/verify-sigstack.h:1.2 kaffe/kaffe/kaffevm/verifier/verify-sigstack.h:1.3
--- kaffe/kaffe/kaffevm/verifier/verify-sigstack.h:1.2 Fri Jun 25 14:43:45 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-sigstack.h Sat Jun 26 23:57:20 2004
@@ -23,7 +23,7 @@
typedef struct SigStack
{
const char* sig;
- struct sig_stack* next;
+ struct SigStack* next;
} SigStack;
extern SigStack* pushSig(SigStack* sigs, const char* sig);
Index: kaffe/kaffe/kaffevm/verifier/verify-type.c
diff -u kaffe/kaffe/kaffevm/verifier/verify-type.c:1.3 kaffe/kaffe/kaffevm/verifier/verify-type.c:1.4
--- kaffe/kaffe/kaffevm/verifier/verify-type.c:1.3 Sat Jun 26 18:21:35 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-type.c Sat Jun 26 23:57:20 2004
@@ -13,6 +13,9 @@
#include "debug.h"
#include "itypes.h"
#include "soft.h"
+#include "gc.h"
+#include "exception.h"
+#include "errors.h"
#include "verify.h"
#include "verify-debug.h"
#include "verify-type.h"
@@ -206,9 +209,42 @@
* list and puts it onto our SupertypeSet of memory allocations.
*/
void
-mergeSupersets(SupertypeSet* supertypes, Type* t1, Type* t2)
+mergeSupersets(Verifier* v, Type* t1, Type* t2)
{
- /* TODO */
+ int i, j;
+ SupertypeSet* set = checkPtr(gc_malloc(sizeof(SupertypeSet), GC_ALLOC_VERIFIER));
+
+ /* we allocate more memory than we'll ever use, but this is faster than
+ * counting out all the common superinterfaces, allocating memory for the set,
+ * and then finding all the common superinterfaces again.
+ *
+ * besides, we're just allocating a small amount of memory for pointers ;)
+ */
+ (t1->data.class->total_interface_len > t2->data.class->total_interface_len) ?
+ (i = t1->data.class->total_interface_len + 1)
+ :
+ (i = t2->data.class->total_interface_len + 1);
+ set->list = checkPtr(gc_malloc(i * sizeof(Hjava_lang_Class*), GC_ALLOC_VERIFIER));
+
+ /* the first common supertype is always a common class */
+ set->list[0] = getCommonSuperclass(t1->data.class, t2->data.class);
+ set->count = 1;
+
+ /* cycle through all interfaces that both inherit from, adding them
+ * to the list of common supertypes
+ */
+ for (i = 0; i < t1->data.class->total_interface_len; i++) {
+ for (j = 0; j < t2->data.class->total_interface_len; j++) {
+ if (t1->data.class->interfaces[i] == t2->data.class->interfaces[i]) {
+ set->list[set->count] = t1->data.class->interfaces[i];
+ set->count++;
+ break;
+ }
+ }
+ }
+
+ set->next = v->supertypes;
+ v->supertypes = set;
}
/**
@@ -282,7 +318,7 @@
return false;
}
-
+
if (CLASS_IS_INTERFACE(t1->data.class)) {
if (instanceof_interface(t1->data.class, t2->data.class)) {
/* t1 is an interface and t2 implements or extends it,
@@ -291,39 +327,38 @@
*t2 = *t1;
return true;
}
- else if (!CLASS_IS_INTERFACE(t2->data.class)) {
- t2->data.class = TOBJ->data.class;
- return true;
- }
/* we now know that t2 is an interface */
else if (instanceof_interface(t2->data.class, t1->data.class)) {
/* t2 is a superinterface of t1 */
return false;
}
- else {
- /* TODO: need to pass the actual SupertypeSet */
- mergeSupersets(NULL, t1, t2);
- return true;
+ }
+ else if (CLASS_IS_INTERFACE(t2->data.class)) {
+ /* t1 is not an interface here */
+ if (instanceof_interface(t2->data.class, t1->data.class)) {
+ /* t2 is a superinterface of t1 */
+ return false;
}
- } else if (CLASS_IS_INTERFACE(t2->data.class)) {
- /* TODO */
+ }
+ else {
+ /* neither is an interface */
}
- /* possibilities left:
- * 1) both are classes
- * 2)
- * 1) both are classes
- * TODO: create supertypes here */
- {
- Hjava_lang_Class *tmp = t2->data.class;
-
- t2->data.class = getCommonSuperclass(t1->data.class, t2->data.class);
-
- return tmp != t2->data.class;
+ /* at this point, neither type implements or extends the other,
+ * so we're going to build a supertype list.
+ */
+ mergeSupersets(v, t1, t2);
+ if (v->supertypes->count == 1) {
+ *t2 = *TOBJ;
+ }
+ else {
+ t2->tinfo = TINFO_SUPERTYPES;
+ t2->data.supertypes = v->supertypes;
+ return true;
}
+ return true;
}
-
/*
* returns the first (highest) common superclass of classes A and B.
*
@@ -350,8 +385,7 @@
/*
- * isReference()
- * returns whether the type is a reference type
+ * @return true if the type is a reference type
*/
bool
isReference(const Type* t)
@@ -417,14 +451,24 @@
sameRefType(&(t1->data.uninit->type),
&(t2->data.uninit->type))));
- case TINFO_SUPERTYPES:
- /* if we're unsure as to what type t1 might be, then
- * we have to perform a merge
- * TODO: compare the supertype lists. since we're merging
- * them in the order of the type hirearchy, then we simply
- * traverse each list until we get to a pair that doesn't match.
- */
- return false;
+ case TINFO_SUPERTYPES: {
+ uint32 i;
+ if (t2->tinfo != TINFO_SUPERTYPES ||
+ t1->data.supertypes->count != t2->data.supertypes->count) {
+ return false;
+ }
+ else if (t1->data.supertypes == t2->data.supertypes) {
+ return true;
+ }
+
+ for (i = 0; i < t1->data.supertypes->count; i++) {
+ if (t1->data.supertypes->list[i] != t2->data.supertypes->list[i])
+ return false;
+ }
+ return true;
+ }
+
+
default:
DBG(VERIFY3, dprintf("%ssameType(): unrecognized tinfo (%d)\n", indent, t1->tinfo); );
@@ -550,10 +594,9 @@
* Determines whether t2 can be used as a t1; that is, whether
* t2 implements or inherits from t1.
*
- * As a side effect, it (potentially) modifies t2's supertype
- * list, if present, by removing those types incompatible with t1.
- * If t1 is represented by a list, then t1 could be *any* of the
- * elements on the list. TODO
+ * pre: t1 is NOT a supertype list. (i believe that this can't
+ * happen right now. grep through the verifier sources to
+ * confirm).
*
* @return whether t2 can be a t1.
*/
@@ -574,19 +617,32 @@
else if (sameType(t1, TOBJ)) {
return true;
}
- /* TODO: supertype checking */
else if (t1->tinfo & TINFO_SUPERTYPES) {
-
- }
- else if (t2->tinfo & TINFO_SUPERTYPES) {
- /* t1 is NOTE a supertypes, so we simply
- * TODO
- */
+ /* we should never get this when type checking */
+ postExceptionMessage(v->einfo, JAVA_LANG(InternalError),
+ "in typecheck(): doing method %s.%s",
+ CLASS_CNAME(v->class), METHOD_NAMED(v->method));
+ return false;
}
resolveType(v, t1);
if (t1->data.class == NULL) {
+ return false;
+ }
+
+ if (t2->tinfo & TINFO_SUPERTYPES &&
+ CLASS_IS_INTERFACE(t1->data.class)) {
+ uint32 i;
+ SupertypeSet* s = t2->data.supertypes;
+
+ if (instanceof(t1->data.class, s->list[0]))
+ return true;
+
+ for (i = 1; i < s->count; i++) {
+ if (s->list[i] == t1->data.class)
+ return true;
+ }
return false;
}
Index: kaffe/kaffe/kaffevm/verifier/verify-type.h
diff -u kaffe/kaffe/kaffevm/verifier/verify-type.h:1.3 kaffe/kaffe/kaffevm/verifier/verify-type.h:1.4
--- kaffe/kaffe/kaffevm/verifier/verify-type.h:1.3 Sat Jun 26 18:21:35 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-type.h Sat Jun 26 23:57:20 2004
@@ -142,7 +142,7 @@
/* for dealing with the supertype lists */
-extern void mergeSupersets(SupertypeSet* supertypes,
+extern void mergeSupersets(struct Verifier* v,
Type* t1,
Type* t2);
extern void freeSupertypes(SupertypeSet* supertypes);
Index: kaffe/kaffe/kaffevm/verifier/verify.c
diff -u kaffe/kaffe/kaffevm/verifier/verify.c:1.3 kaffe/kaffe/kaffevm/verifier/verify.c:1.4
--- kaffe/kaffe/kaffevm/verifier/verify.c:1.3 Sat Jun 26 18:21:35 2004
+++ kaffe/kaffe/kaffevm/verifier/verify.c Sat Jun 26 23:57:19 2004
@@ -1,14 +1,17 @@
/*
* verify.c
- * Perform stages 2 & 3 of class verification. Stage 1 is performed
- * when the class is being loaded (so isn't here) and stage 4 is performed
- * as the method is being executed.
- *
- * verify2() was originally created by someone in Transvirtual Technologies. however,
- * it did almost nothing (only a shrivel of the stuff needed by pass 2...
- * specifically part 3 of of pass 2, which has been modified),
- * so questions regarding pass 2 should be sent to:
- * Rob Gonzalez <rob at kaffe.org>
+ *
+ * Copyright 2004
+ * Kaffe.org contributors. See ChangeLog for details. All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file.
+ *
+ *
+ * Perform stages 3 of class verification.
+ * Stage 1 is performed when the class is being loaded (so isn't here).
+ * Stage 2 is performed in verify2.
+ * stage 4 is performed as the method is being executed.
*
* verify3() was also originally created by someone in Transvirtual, but it only
* returned true :) Questions regarding this one can be sent to Rob as well.
@@ -25,11 +28,9 @@
#include "lookup.h"
#include "exception.h"
#include "errors.h"
-#include "jni.h"
#include "debug.h"
#include "utf8const.h"
-/* needed for pass 3 */
#include "bytecode.h"
#include "itypes.h"
#include "soft.h"
@@ -254,28 +255,27 @@
Method* method);
/* checks static constraints in bytecode */
-static void verifyMethod3a(errorInfo* einfo,
- Verifier* v);
+static void verifyMethod3a(Verifier* v);
/* typechecks bytecode and performs the rest of verification */
-static bool verifyMethod3b(errorInfo* einfo,
- Verifier* v);
+static bool verifyMethod3b(Verifier* v);
static bool loadInitialArgs(Verifier* v);
-static bool verifyBasicBlock(errorInfo*,
- Verifier* v,
+static bool verifyBasicBlock(Verifier* v,
BlockInfo*);
static bool mergeBasicBlocks(Verifier* v,
BlockInfo* fromBlock,
BlockInfo* toBlock);
/* for verifying method calls */
-static const char* getReturnSig(const Method*);
+static const char* getMethodReturnSig(const Method*);
static uint32 countSizeOfArgsInSignature(const char* sig);
-static const char* getNextArg(const char* sig, char* buf);
-static bool checkMethodCall(errorInfo* einfo, Verifier* v,
- BlockInfo* binfo, uint32 pc);
+static const char* getNextArg(const char* sig,
+ char* buf);
+static bool checkMethodCall(Verifier* v,
+ BlockInfo* binfo,
+ uint32 pc);
/*
* Verify pass 3: Check the consistency of the bytecode.
@@ -294,7 +294,7 @@
* NOTE: we don't skip interfaces here because an interface may contain a <clinit> method with bytecode
*/
if (isTrustedClass(class)) {
- return success;
+ return true;
}
@@ -363,10 +363,13 @@
**************************************************************************************************/
/* to make sure we don't forget to unalloc anything...
* should be called during ANY EXIT FROM verifyMethod
+ *
+ * NOTE: we don't free the Verifier object itself, just
+ * its data.
*/
static
void
-cleanupInVerifyMethod(Verifier* v)
+freeVerifierData(Verifier* v)
{
DBG(VERIFY3, dprintf(" cleaning up..."); );
gc_free(v->status);
@@ -384,15 +387,15 @@
static inline
bool
-failInVerifyMethod(errorInfo *einfo, Verifier* v)
+failInVerifyMethod(Verifier* v)
{
DBG(VERIFY3, dprintf(" Verify Method 3b: %s.%s%s: FAILED\n",
CLASS_CNAME(v->method->class), METHOD_NAMED(v->method), METHOD_SIGD(v->method)); );
- if (einfo->type == 0) {
+ if (v->einfo->type == 0) {
DBG(VERIFY3, dprintf(" DBG ERROR: should have raised an exception\n"); );
- postException(einfo, JAVA_LANG(VerifyError));
+ postException(v->einfo, JAVA_LANG(VerifyError));
}
- cleanupInVerifyMethod(v);
+ freeVerifierData(v);
return(false);
}
@@ -429,12 +432,12 @@
v.status = checkPtr((uint32*)gc_malloc(codelen * sizeof(uint32), GC_ALLOC_VERIFIER));
/* find basic blocks and allocate memory for them */
- verifyMethod3a(einfo, &v);
+ verifyMethod3a(&v);
if (!v.blocks) {
DBG(VERIFY3, dprintf(" some kinda error finding the basic blocks in pass 3a\n"); );
/* propagate error */
- return failInVerifyMethod(einfo, &v);
+ return failInVerifyMethod(&v);
}
DBG(VERIFY3, dprintf(" done allocating memory\n"); );
@@ -446,7 +449,7 @@
DBG(VERIFY3, dprintf(" about to load initial args...\n"); );
if (!loadInitialArgs(&v)) {
/* propagate error */
- return failInVerifyMethod(einfo, &v);
+ return failInVerifyMethod(&v);
}
DBG(VERIFY3, {
/* print out the local arguments */
@@ -459,11 +462,11 @@
} );
- if (!verifyMethod3b(einfo, &v)) {
- return failInVerifyMethod(einfo, &v);
+ if (!verifyMethod3b(&v)) {
+ return failInVerifyMethod(&v);
}
- cleanupInVerifyMethod(&v);
+ freeVerifierData(&v);
DBG(VERIFY3, dprintf(" Verify Method 3b: done\n"); );
return(true);
}
@@ -510,7 +513,7 @@
*/
static
void
-verifyMethod3a(errorInfo* einfo, Verifier* v)
+verifyMethod3a(Verifier* v)
{
#define ENSURE_NON_WIDE \
@@ -1162,7 +1165,7 @@
*/
if (entry->catch_type != 0) {
if (entry->catch_type == NULL) {
- entry->catch_type = getClass(entry->catch_idx, v->method->class, einfo);
+ entry->catch_type = getClass(entry->catch_idx, v->method->class, v->einfo);
}
if (entry->catch_type == NULL) {
DBG(VERIFY3, dprintf(" ERROR: could not resolve catch type...\n"); );
@@ -1312,7 +1315,7 @@
*/
static
bool
-verifyMethod3b(errorInfo* einfo, Verifier* v)
+verifyMethod3b(Verifier* v)
{
const uint32 codelen = METHOD_BYTECODE_LEN(v->method);
const unsigned char* code = METHOD_BYTECODE_CODE(v->method);
@@ -1362,7 +1365,7 @@
}
- if (!verifyBasicBlock(einfo, v, curBlock)) {
+ if (!verifyBasicBlock(v, curBlock)) {
return verifyErrorInVerifyMethod3b(v, curBlock, "failure to verify basic block");
}
@@ -1855,7 +1858,7 @@
*/
static
bool
-verifyBasicBlock(errorInfo* einfo, Verifier* v, BlockInfo* block)
+verifyBasicBlock(Verifier* v, BlockInfo* block)
{
/**************************************************************************************************
* VARIABLES
@@ -2662,7 +2665,7 @@
if (pool->tags[idx] == CONSTANT_ResolvedClass) {
class = CLASS_CLASS(idx, pool);
type->tinfo = TINFO_CLASS;
- type->data.class = lookupArray(class, einfo);
+ type->data.class = lookupArray(class, v->einfo);
if (type->data.class == NULL) {
return verifyError(v, "anewarray: error creating array type");
@@ -2902,7 +2905,7 @@
case INVOKEINTERFACE:
case INVOKESTATIC:
- if (!checkMethodCall(einfo, v, block, pc)) {
+ if (!checkMethodCall(v, block, pc)) {
DBG(VERIFY3,
dprintf("\n some problem with a method call...here's the block:\n");
printBlock(v->method, block, " "); );
@@ -2915,34 +2918,34 @@
case IRETURN:
OPSTACK_PEEK_T(TINT);
- sig = getReturnSig(v->method);
+ sig = getMethodReturnSig(v->method);
if (strlen(sig) != 1 || (*sig != 'I' && *sig != 'Z' && *sig != 'S' && *sig != 'B' && *sig != 'C')) {
return verifyError(v, "ireturn: method doesn't return an integer");
}
break;
case FRETURN:
OPSTACK_PEEK_T(TFLOAT);
- sig = getReturnSig(v->method);
+ sig = getMethodReturnSig(v->method);
if (strcmp(sig, "F")) {
return verifyError(v, "freturn: method doesn't return an float");
}
break;
case LRETURN:
OPSTACK_WPEEK_T(TLONG);
- sig = getReturnSig(v->method);
+ sig = getMethodReturnSig(v->method);
if (strcmp(sig, "J")) {
return verifyError(v, "lreturn: method doesn't return a long");
}
break;
case DRETURN:
OPSTACK_WPEEK_T(TDOUBLE);
- sig = getReturnSig(v->method);
+ sig = getMethodReturnSig(v->method);
if (strcmp(sig, "D")) {
return verifyError(v, "dreturn: method doesn't return a double");
}
break;
case RETURN:
- sig = getReturnSig(v->method);
+ sig = getMethodReturnSig(v->method);
if (strcmp(sig, "V")) {
return verifyError(v, "return: must return something in a non-void function");
}
@@ -2950,7 +2953,7 @@
case ARETURN:
ENSURE_OPSTACK_SIZE(1);
t->tinfo = TINFO_SIG;
- t->data.sig = getReturnSig(v->method);
+ t->data.sig = getMethodReturnSig(v->method);
if (!typecheck(v, t, getOpstackTop(block))) {
return verifyError(v, "areturn: top of stack is not type compatible with method return type");
}
@@ -3253,7 +3256,7 @@
*/
static
bool
-checkMethodCall(errorInfo* einfo, Verifier* v,
+checkMethodCall(Verifier* v,
BlockInfo* binfo, uint32 pc)
{
const unsigned char* code = METHOD_BYTECODE_CODE(v->method);
@@ -3498,7 +3501,7 @@
/* shouldn't get here because of parsing during pass 2... */
DBG(VERIFY3, dprintf(" unrecognized return type signature: %s\n", argbuf); );
gc_free(argbuf);
- postExceptionMessage(einfo, JAVA_LANG(InternalError),
+ postExceptionMessage(v->einfo, JAVA_LANG(InternalError),
"unrecognized return type signature");
return(false);
}
@@ -3621,11 +3624,12 @@
/*
- * getReturnSig()
+ * returns a pointer to the first character of the method's return value
+ * in the method's type descriptor.
*/
static
const char*
-getReturnSig(const Method* method)
+getMethodReturnSig(const Method* method)
{
const char* sig = METHOD_SIGD(method);
Index: kaffe/kaffe/kaffevm/verifier/verify2.c
diff -u kaffe/kaffe/kaffevm/verifier/verify2.c:1.3 kaffe/kaffe/kaffevm/verifier/verify2.c:1.4
--- kaffe/kaffe/kaffevm/verifier/verify2.c:1.3 Sat Jun 26 18:21:34 2004
+++ kaffe/kaffe/kaffevm/verifier/verify2.c Sat Jun 26 23:57:19 2004
@@ -7,7 +7,12 @@
* See the file "license.terms" for information on usage and redistribution
* of this file.
*
- * Second verifier pass.
+ *
+ * verify2() was originally created by someone in Transvirtual Technologies. however,
+ * it did almost nothing (only a shrivel of the stuff needed by pass 2...
+ * specifically part 3 of of pass 2, which has been modified),
+ * so questions regarding pass 2 should be sent to:
+ * Rob Gonzalez <rob at kaffe.org>
*/
#include "access.h"
More information about the kaffe
mailing list