[kaffe] CVS kaffe (rob): (verify2) fixed a couple of compile-time warnings.

Kaffe CVS cvs-commits at kaffe.org
Fri Jun 25 07:50:13 PDT 2004


PatchSet 4866 
Date: 2004/06/25 14:43:45
Author: rob
Branch: HEAD
Tag: (none) 
Log:
(verify2) fixed a couple of compile-time warnings.

(verify3) refactored all the major method calls to use a Verifier structure instead of an ever growing list of parameters.  it makes keeping track of memory allocation much easier.  it also makes it easier to add other data to the structure that is passed around to every method call.

(verify-type) started to add the support for the supertype list structure, including the structure itself and some methods.  at this point it is just skeleton code and is not used anywhere, as i got sidetracked in refactoring verify3.  eventually it'll be used/updated much like the uninit code.

Members: 
	kaffe/kaffevm/verifier/verify-block.h:1.1->1.2 
	kaffe/kaffevm/verifier/verify-debug.c:1.1->1.2 
	kaffe/kaffevm/verifier/verify-errors.h:1.1->1.2 
	kaffe/kaffevm/verifier/verify-sigstack.h:1.1->1.2 
	kaffe/kaffevm/verifier/verify-type.c:1.1->1.2 
	kaffe/kaffevm/verifier/verify-type.h:1.1->1.2 
	kaffe/kaffevm/verifier/verify-uninit.h:1.1->1.2 
	kaffe/kaffevm/verifier/verify.c:1.1->1.2 
	kaffe/kaffevm/verifier/verify.h:1.1->1.2 
	kaffe/kaffevm/verifier/verify2.c:1.1->1.2 

Index: kaffe/kaffe/kaffevm/verifier/verify-block.h
diff -u kaffe/kaffe/kaffevm/verifier/verify-block.h:1.1 kaffe/kaffe/kaffevm/verifier/verify-block.h:1.2
--- kaffe/kaffe/kaffevm/verifier/verify-block.h:1.1	Mon Jun 21 16:16:13 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-block.h	Fri Jun 25 14:43:45 2004
@@ -19,7 +19,7 @@
 /*
  * basic block header information
  */
-typedef struct block_info
+typedef struct BlockInfo
 {
         /* address of start of block */
 	uint32 startAddr;
Index: kaffe/kaffe/kaffevm/verifier/verify-debug.c
diff -u kaffe/kaffe/kaffevm/verifier/verify-debug.c:1.1 kaffe/kaffe/kaffevm/verifier/verify-debug.c:1.2
--- kaffe/kaffe/kaffevm/verifier/verify-debug.c:1.1	Mon Jun 21 16:16:13 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-debug.c	Fri Jun 25 14:43:45 2004
@@ -17,9 +17,22 @@
 /* for debugging */
 #if !(defined(NDEBUG) || !defined(KAFFE_VMDEBUG))
 
+/* change these indentations to whatever makes more sense, but
+ * but these values produce some easy-to-read debugging output.
+ */
 const char* indent  = "                ";
 const char* indent2 = "                        ";
 
+/* these prototypes are here to keep gcc from complaining */
+uint32 printConstantPoolEntry(const Hjava_lang_Class* class, uint32 idx);
+void printConstantPool(const Hjava_lang_Class* class);
+void printInstruction(const int opcode);
+void printType(const Type*);
+void printBlock(const Method* method, const BlockInfo* binfo, const char* id);
+
+
+
+
 uint32
 printConstantPoolEntry(const Hjava_lang_Class* class, uint32 idx)
 {
@@ -484,6 +497,14 @@
 		printType(&(t->data.uninit->type));
 		break;
 		
+	case TINFO_SUPERTYPES: {
+		uint32 i;
+		dprintf("TINFO_SUPERTYPES: ");
+		for (i = 0; i < t->data.supertypes->count; i++) {
+			dprintf("%s, ", CLASS_CNAME(t->data.supertypes->list[i]));
+		}
+	}
+		
 	default:
 		dprintf("UNRECOGNIZED TINFO");
 		break;
@@ -496,19 +517,19 @@
  *    For debugging.  Prints out a basic block.
  */
 void
-printBlock(const Method* method, const BlockInfo* binfo, const char* indent)
+printBlock(const Method* method, const BlockInfo* binfo, const char* local_indent)
 {
 	uint32 n;
 	
-	dprintf("%slocals:\n", indent);
+	dprintf("%slocals:\n", local_indent);
 	for (n = 0; n < method->localsz; n++) {
-		dprintf("%s    %d: ", indent, n);
+		dprintf("%s    %d: ", local_indent, n);
 		printType(&binfo->locals[n]);
 		dprintf("\n");
 	}
-	dprintf("%sopstack (%d):\n", indent, binfo->stacksz);
+	dprintf("%sopstack (%d):\n", local_indent, binfo->stacksz);
 	for (n = 0; n < method->stacksz; n++) {
-		dprintf("%s    %d: ", indent, n);
+		dprintf("%s    %d: ", local_indent, n);
 		printType(&binfo->opstack[n]);
 		dprintf("\n");
 	}
Index: kaffe/kaffe/kaffevm/verifier/verify-errors.h
diff -u kaffe/kaffe/kaffevm/verifier/verify-errors.h:1.1 kaffe/kaffe/kaffevm/verifier/verify-errors.h:1.2
--- kaffe/kaffe/kaffevm/verifier/verify-errors.h:1.1	Mon Jun 21 16:16:13 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-errors.h	Fri Jun 25 14:43:45 2004
@@ -16,40 +16,39 @@
  * Helper function for error reporting in verifyMethod3a.
  */
 static inline
-BlockInfo **
+void
 verifyErrorInVerifyMethod3a(errorInfo* einfo,
-			    Method* method,
+			    const Verifier* v,
 			    const char * msg)
 {
 	if (einfo->type == 0) {
 		postExceptionMessage(einfo, JAVA_LANG(VerifyError),
 				     "in method \"%s.%s\": %s",
-				     CLASS_CNAME(method->class), METHOD_NAMED(method), msg);
+				     CLASS_CNAME(v->method->class), METHOD_NAMED(v->method), msg);
 	}
-	return NULL;
 }
 
 /*
  * Helper function for error reporting in BRANCH_IN_BOUNDS macro in verifyMethod3a.
  */
 static inline
-BlockInfo **
+void
 branchInBoundsErrorInVerifyMethod3a(errorInfo* einfo,
-				    Method* method,
-				    int codelen,
+				    const Verifier* v,
+				    uint32 codelen,
 				    uint32 n)
 {
   DBG(VERIFY3, dprintf("ERROR: branch to (%d) out of bound (%d) \n", n, codelen); );
-  return verifyErrorInVerifyMethod3a(einfo, method, "branch out of method code");
+  verifyErrorInVerifyMethod3a(einfo, v, "branch out of method code");
 }
 
 /*
  * Helper function for error reporting in CHECK_LOCAL_INDEX macro in verifyMethod3a.
  */
 static inline
-BlockInfo **
+void
 checkLocalIndexErrorInVerifyMethod3a(errorInfo* einfo,
-				     Method* method,
+				     const Verifier* v,
 				     uint32 pc,
 				     unsigned char* code,
 				     uint32 n)
@@ -57,9 +56,9 @@
   DBG(VERIFY3,
       dprintf("ERROR:  pc = %d, instruction = ", pc);
       printInstruction(code[pc]);
-      dprintf(", localsz = %d, localindex = %d\n", method->localsz, n);
+      dprintf(", localsz = %d, localindex = %d\n", v->method->localsz, n);
       );
-  return verifyErrorInVerifyMethod3a(einfo, method, "attempting to access a local variable beyond local array");
+  verifyErrorInVerifyMethod3a(einfo, v, "attempting to access a local variable beyond local array");
 }
 
 #endif
Index: kaffe/kaffe/kaffevm/verifier/verify-sigstack.h
diff -u kaffe/kaffe/kaffevm/verifier/verify-sigstack.h:1.1 kaffe/kaffe/kaffevm/verifier/verify-sigstack.h:1.2
--- kaffe/kaffe/kaffevm/verifier/verify-sigstack.h:1.1	Mon Jun 21 16:16:13 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-sigstack.h	Fri Jun 25 14:43:45 2004
@@ -20,7 +20,7 @@
 /* TODO: use the builtin hash table data structure instead 
  * so we can avoid repeats
  */
-typedef struct sig_stack
+typedef struct SigStack
 {
 	const char* sig;
 	struct sig_stack* next;
Index: kaffe/kaffe/kaffevm/verifier/verify-type.c
diff -u kaffe/kaffe/kaffevm/verifier/verify-type.c:1.1 kaffe/kaffe/kaffevm/verifier/verify-type.c:1.2
--- kaffe/kaffe/kaffevm/verifier/verify-type.c:1.1	Mon Jun 21 16:16:13 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-type.c	Fri Jun 25 14:43:45 2004
@@ -13,6 +13,7 @@
 #include "debug.h"
 #include "itypes.h"
 #include "soft.h"
+#include "verify.h"
 #include "verify-debug.h"
 #include "verify-type.h"
 #include "verify-uninit.h"
@@ -166,9 +167,9 @@
 }
 
 
-/*
- * resolveType()
- *     Ensures that the type is a pointer to an instance of Hjava_lang_Class.
+/**
+ *  If the given type is a simply a signature or class name, we
+ *  resolve it to be a pointer to an actual Class object in memory.
  */
 void
 resolveType(errorInfo* einfo, Hjava_lang_Class* this, Type *type)
@@ -198,28 +199,48 @@
 	}
 }
 
+/**
+ * Constructs the list of common supertypes from t1 and t2,
+ * storing the result in t2 as a TINFO_SUPERTYPES.
+ * In the process, it allocates memory for the new supertype
+ * list and puts it onto our SupertypeSet of memory allocations.
+ */
+void
+mergeSupersets(SupertypeSet* supertypes, Type* t1, Type* t2)
+{
+	/* TODO */
+}
 
-/*
- * mergeTypes()
- *     merges two types, t1 and t2, into t2.  this result could
- *     be a common superclass, a common class that both types implement, or,
- *     in the event that the types are not compatible, TUNSTABLE.
+/**
+ * Frees all the memory allocated during the creation of the
+ * given SupertypeSet.
  *
- * returns whether an actual merger was made (i.e. they weren't the same type)
+ * @param supertypes The supertype list to be deallocated.
+ * @deffunc void freeSupertypes (SupertypeSet* supertypes)
+ */
+void
+freeSupertypes(SupertypeSet* supertypes)
+{
+	SupertypeSet* l;
+	while (supertypes) {
+		l = supertypes->next;
+		gc_free(supertypes->list);
+		gc_free(supertypes);
+		supertypes = l;
+	}
+}
+
+/*
+ * merges two types, t1 and t2, into t2.
+ * if t1 and t2 cannot be merged, t2 will become TUNSTABLE.
+ * frequently, merging will result in t2 being represented as a supertype list.
  *
- * note: the precedence of merged types goes (from highest to lowest):
+ * the precedence of merged types goes (from highest to lowest):
  *     actual pointer to Hjava_lang_Class*
  *     TINFO_SIG
  *     TINFO_NAME
  *
- * TODO: right now the priority is to be a common superclass, as stated in
- *       the JVML2 specs.  a better verification technique might check this first,
- *       and then check interfaces that both classes implement.  of course, depending
- *       on the complexity of the inheritance hirearchy, this could take a lot of time.
- *       
- *       the ideal solution is to remember *all* possible highest resolution types,
- *       which, of course, would require allocating more memory on the fly, etc., so,
- *       at least for now, we're not really even considering it.
+ * @return whether an actual merger was made (i.e. they two types given were not the same type)
  */
 bool
 mergeTypes(errorInfo* einfo, Hjava_lang_Class* this,
@@ -249,50 +270,56 @@
 		*t2 = *t1;
 		return true;
 	}
+	else if (t2->data.class == TOBJ->data.class) {
+		return false;
+	}
 	
 	
-	/* not equivalent, must resolve them */
+	/* must resolve them to go on */
 	resolveType(einfo, this, t1);
-	if (t1->data.class == NULL) {
-		return false;
-	}
-
 	resolveType(einfo, this, t2);
-	if (t2->data.class == NULL) {
+	if ((t1->tinfo & TINFO_CLASS && t1->data.class == NULL) ||
+	    (t2->tinfo & TINFO_CLASS && t2->data.class == NULL)) {
 		return false;
 	}
 	
-	if (CLASS_IS_INTERFACE(t1->data.class) &&
-	    instanceof_interface(t1->data.class, t2->data.class)) {
-	
-		/* t1 is an interface and t2 implements it,
-		 * so the interface is the merged type.
-		 */
 
-		*t2 = *t1;
-		
-		return true;
+	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,
+			 * so the interface is the merged type.
+			 */
+			*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)) {
+		/* TODO */
+	}
 	
-	} else if (CLASS_IS_INTERFACE(t2->data.class) &&
-		   instanceof_interface(t2->data.class, t1->data.class)) {
-		
-		/* same as above, but we don't need to merge, since
-		 * t2 already is the merged type
-		 */
-
-		return false;
-	} else {
-		/*
-		 * neither of the types is an interface, so we have to
-		 * check for common superclasses. Only merge iff t2 is
-		 * not the common superclass.
-		 */
+	/* 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;
-	} 
 }
 
 
@@ -331,7 +358,8 @@
 	return (type->tinfo & TINFO_NAME ||
 		type->tinfo & TINFO_SIG ||
 		type->tinfo & TINFO_CLASS ||
-		type->tinfo & TINFO_UNINIT);
+		type->tinfo & TINFO_UNINIT ||
+		type->tinfo & TINFO_SUPERTYPES);
 }
 
 /*
@@ -347,6 +375,12 @@
 	else if (type->tinfo & TINFO_NAME || type->tinfo & TINFO_SIG) {
 		return (*(type->data.sig) == '[');
 	}
+	else if (type->tinfo & TINFO_SUPERTYPES) {
+		/* if one of the supertypes is an array, it follows that
+		 * all supertypes in the list must be arrays
+		 */
+		return ((*CLASS_CNAME(type->data.supertypes->list[0])) == '[');
+	}
 	else if (type->tinfo != TINFO_CLASS) {
 		return false;
 	}
@@ -355,7 +389,6 @@
 	}
 }
 
-
 /*
  * sameType()
  *     returns whether two Types are effectively equivalent.
@@ -383,6 +416,12 @@
 			 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
+		 */
+		return false;
+		
 	default:
 		DBG(VERIFY3, dprintf("%ssameType(): unrecognized tinfo (%d)\n", indent, t1->tinfo); );
 		return false;
@@ -503,12 +542,19 @@
 	}
 }
 
-
-/*
- * returns whether t2 can be a t1
+/**
+ * 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
+ *
+ * @return whether t2 can be a t1.
  */
 bool
-typecheck(errorInfo* einfo, Hjava_lang_Class* this, Type* t1, Type* t2)
+typecheck(errorInfo* einfo, Verifier* v, Type* t1, Type* t2)
 {
 	DBG(VERIFY3, dprintf("%stypechecking ", indent); printType(t1); dprintf("  vs.  "); printType(t2); dprintf("\n"); );
 	
@@ -524,16 +570,26 @@
 	else if (sameType(t1, TOBJ)) {
 		return true;
 	}
+	/* TODO: supertype checking */
+	else if (t1->tinfo & TINFO_SUPERTYPES) {
 
-	resolveType(einfo, this, t1);
+	}
+	else if (t2->tinfo & TINFO_SUPERTYPES) {
+		/* t1 is NOTE a supertypes, so we simply 
+		 * TODO
+		 */
+	}
+	
+	
+	resolveType(einfo, v->class, t1);
 	if (t1->data.class == NULL) {
 		return false;
 	}
 
-	resolveType(einfo, this, t2);
+	resolveType(einfo, v->class, t2);
 	if (t2->data.class == NULL) {
 		return false;
 	}
-
+	
 	return instanceof(t1->data.class, t2->data.class);
 }
Index: kaffe/kaffe/kaffevm/verifier/verify-type.h
diff -u kaffe/kaffe/kaffevm/verifier/verify-type.h:1.1 kaffe/kaffe/kaffevm/verifier/verify-type.h:1.2
--- kaffe/kaffe/kaffevm/verifier/verify-type.h:1.1	Mon Jun 21 16:16:13 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-type.h	Fri Jun 25 14:43:45 2004
@@ -15,6 +15,30 @@
 
 #include "classMethod.h"
 
+
+struct Verifier;
+
+
+/* structure to hold the merger of two types in the event of
+ * multiple inheritence.
+ * it is implemented as a stack.
+ *
+ * also is a list of all supertype lists allocated during
+ * the verification of a specific method.  the memory used here
+ * is freed after verification of the method is completed.
+ */
+typedef struct SupertypeSet
+{
+	uint32 count;
+	Hjava_lang_Class** list;
+	
+	struct SupertypeSet* next;
+} SupertypeSet;
+
+
+/* represents a Type, which could get a primitive type, a reference type,
+ * or a system type such as an address or uninitialized.
+ */
 typedef struct Type
 {
 	uint32 tinfo;
@@ -26,10 +50,9 @@
 		Hjava_lang_Class* class;
 		
 	        /* uninitialized object reference */
-		struct unitialized_types_double_list* uninit;
+		struct UninitializedType* uninit;
 		
-	        /* list of supertypes in the event of multiple inheritence of interfaces. */
-		Hjava_lang_Class** supertypes;
+		SupertypeSet* supertypes;
 		
 	        /* return address for TINFO_ADDR */
 		uint32 addr;
@@ -50,7 +73,7 @@
  *   TINFO_UNINIT_SUPER reserved for the self-reference in a constructor method.  when the receiver of a call to <init>()
  *                      is of type TINFO_UNINIT_SUPER, then the <init>() referenced may be in the current class of in its
  *                      superclass.
- *   TINFO_SUPERLIST    a list of supertypes.  used when merging two types that have multiple common supertypes.
+ *   TINFO_SUPERTYPES   a set of supertypes.  used when merging two types that have multiple common supertypes.
  *                      this can occur with the multiple inheritence of interfaces.
  *                      the zeroth element is always a common superclass, the rest are common superinterfaces.
  */
@@ -62,7 +85,7 @@
 #define TINFO_CLASS        16
 #define TINFO_UNINIT       32
 #define TINFO_UNINIT_SUPER 96
-#define TINFO_SUPERLIST    128
+#define TINFO_SUPERTYPES    128
 
 #define IS_ADDRESS(_TINFO) ((_TINFO)->tinfo & TINFO_ADDR)
 #define IS_PRIMITIVE_TYPE(_TINFO) ((_TINFO)->tinfo & TINFO_PRIMITIVE)
@@ -103,10 +126,16 @@
 extern void resolveType(errorInfo* einfo, Hjava_lang_Class* this, Type *type);
 
 extern bool mergeTypes(errorInfo*, Hjava_lang_Class* this,
-				     Type* t1, Type* t2);
+		       Type* t1, Type* t2);
 extern Hjava_lang_Class*  getCommonSuperclass(Hjava_lang_Class* t1,
 					      Hjava_lang_Class* t2);
 
-extern bool typecheck(errorInfo*, Hjava_lang_Class* this, Type* t1, Type* t2);
+extern bool typecheck(errorInfo*, struct Verifier* v, Type* t1, Type* t2);
+
+
+/* for dealing with the supertype lists */
+extern void mergeSupersets(SupertypeSet* supertypes, Type* t1, Type* t2);
+extern void freeSupertypes(SupertypeSet* supertypes);
+
 
 #endif /* !defined(VERIFY_TYPE_H) */
Index: kaffe/kaffe/kaffevm/verifier/verify-uninit.h
diff -u kaffe/kaffe/kaffevm/verifier/verify-uninit.h:1.1 kaffe/kaffe/kaffevm/verifier/verify-uninit.h:1.2
--- kaffe/kaffe/kaffevm/verifier/verify-uninit.h:1.1	Mon Jun 21 16:16:13 2004
+++ kaffe/kaffe/kaffevm/verifier/verify-uninit.h	Fri Jun 25 14:43:45 2004
@@ -23,12 +23,12 @@
  *
  * doubly linked list to allow for easy removal of types
  */
-typedef struct unitialized_types_double_list
+typedef struct UninitializedType
 {
 	struct Type type;
 	
-	struct unitialized_types_double_list* prev;
-	struct unitialized_types_double_list* next;
+	struct UninitializedType* prev;
+	struct UninitializedType* next;
 } UninitializedType;
 
 
Index: kaffe/kaffe/kaffevm/verifier/verify.c
diff -u kaffe/kaffe/kaffevm/verifier/verify.c:1.1 kaffe/kaffe/kaffevm/verifier/verify.c:1.2
--- kaffe/kaffe/kaffevm/verifier/verify.c:1.1	Mon Jun 21 16:16:13 2004
+++ kaffe/kaffe/kaffevm/verifier/verify.c	Fri Jun 25 14:43:45 2004
@@ -250,35 +250,34 @@
 /***********************************************************************************
  * Methods for Pass 3 Verification
  ***********************************************************************************/
-static bool               verifyMethod(errorInfo* einfo, Method* method);
-static BlockInfo**        verifyMethod3a(errorInfo* einfo,
-					 Method* method,
-					 uint32* status,     /* array of status info for all opcodes */
-					 uint32* numBlocks); /* number of basic blocks */
+static bool               verifyMethod(errorInfo* einfo,
+				       Method* method);
+
+/* checks static constraints in bytecode */
+static void               verifyMethod3a(errorInfo* einfo,
+					 Verifier* v);
+
+/* typechecks bytecode and performs the rest of verification */
 static bool               verifyMethod3b(errorInfo* einfo,
-					 const Method* method,
-					 const uint32* status,
-					 BlockInfo** blocks,
-					 const uint32 numBlocks,
-					 SigStack** sigs,
-					 UninitializedType** uninits);
+					 Verifier* v);
 
-static bool               merge(errorInfo* einfo, const Method* method, BlockInfo* fromBlock, BlockInfo* toBlock);
-static bool               verifyBasicBlock(errorInfo*,
-					   const Method*,
-					   BlockInfo*,
-					   SigStack**,
-					   UninitializedType**);
 
-static const char*        getNextArg(const char* sig, char* buf);
-static bool               loadInitialArgs(const Method* method, errorInfo* einfo,
-					  BlockInfo* block, SigStack** sigs, UninitializedType** uninits);
+static bool               loadInitialArgs(errorInfo* einfo,
+					  Verifier* v);
+static bool               verifyBasicBlock(errorInfo*,
+					   Verifier* v,
+					   BlockInfo*);
+static bool               mergeBasicBlocks(errorInfo* einfo,
+					   const Method* method,
+					   BlockInfo* fromBlock,
+					   BlockInfo* toBlock);
 
+/* for verifying method calls */
 static const char*        getReturnSig(const Method*);
 static uint32             countSizeOfArgsInSignature(const char* sig);
-static bool               checkMethodCall(errorInfo* einfo, const Method* method,
-					  BlockInfo* binfo, uint32 pc,
-					  SigStack** sigs, UninitializedType** uninits);
+static const char*        getNextArg(const char* sig, char* buf);
+static bool               checkMethodCall(errorInfo* einfo, Verifier* v,
+					  BlockInfo* binfo, uint32 pc);
 
 /*
  * Verify pass 3:  Check the consistency of the bytecode.
@@ -297,7 +296,7 @@
 	 * NOTE: we don't skip interfaces here because an interface may contain a <clinit> method with bytecode
 	 */
 	if (isTrustedClass(class)) {
-		goto done;
+		return success;
 	}
 	
 	
@@ -306,18 +305,29 @@
 	
 	
 	DBG(VERIFY3, dprintf("\nPass 3 Verifying Class \"%s\"\n", CLASS_CNAME(class)); );
+	
 	DBG(VERIFY3, {
+		/* print out the superclass hirearchy */
 		Hjava_lang_Class* tmp;
 		for (tmp = class->superclass; tmp; tmp = tmp->superclass) {
-			dprintf("                        |-> %s\n", CLASS_CNAME(tmp));
+			dprintf("                       C|-> %s\n", CLASS_CNAME(tmp));
+		}
+	});
+	DBG(VERIFY3, {
+		/* print out the complete list of implemented interfaces */
+		int i;
+		for (i = class->total_interface_len - 1; i >=0; i--) {
+			dprintf("                       I|-> %s\n", CLASS_CNAME(class->interfaces[i]));
 		}
 	});
 	
+	
 	for (n = CLASS_NMETHODS(class), method = CLASS_METHODS(class);
 	     n > 0;
 	     --n, ++method) {
 		
-		DBG(VERIFY3, dprintf("\n  -----------------------------------\n  considering method %s%s\n",
+		DBG(VERIFY3, dprintf("\n  -----------------------------------\n  considering method %s.%s%s\n",
+				     CLASS_CNAME(class),
 				     METHOD_NAMED(method), METHOD_SIGD(method)); );
 		
 		/* if it's abstract or native, no verification necessary */
@@ -358,32 +368,33 @@
  */
 static
 void
-cleanupInVerifyMethod(uint32* status, SigStack* sigs, UninitializedType* uninits, uint32* numBlocks, BlockInfo ** blocks)
+cleanupInVerifyMethod(Verifier* v)
 {
 	DBG(VERIFY3, dprintf("    cleaning up..."); );
-	gc_free(status);
-	if (blocks != NULL) {
-		while (*numBlocks > 0) {
-			freeBlock(blocks[--(*numBlocks)]);
-		}
-		gc_free(blocks);
-	}
-        freeSigStack(sigs);
-        freeUninits(uninits);
+	gc_free(v->status);
+	if (v->blocks != NULL) {
+		while (v->numBlocks > 0) {
+			freeBlock(v->blocks[--v->numBlocks]);
+		}
+		gc_free(v->blocks);
+	}
+        freeSigStack(v->sigs);
+        freeUninits(v->uninits);
+	freeSupertypes(v->supertypes);
         DBG(VERIFY3, dprintf(" done\n"); );
 }
 
 static inline
 bool
-failInVerifyMethod(errorInfo *einfo, Method* method, uint32* status, SigStack* sigs, UninitializedType* uninits, uint32* numBlocks, BlockInfo ** blocks)
+failInVerifyMethod(errorInfo *einfo, Verifier* v)
 {
         DBG(VERIFY3, dprintf("    Verify Method 3b: %s.%s%s: FAILED\n",
-			     CLASS_CNAME(method->class), METHOD_NAMED(method), METHOD_SIGD(method)); );
+			     CLASS_CNAME(v->method->class), METHOD_NAMED(v->method), METHOD_SIGD(v->method)); );
 	if (einfo->type == 0) {
 		DBG(VERIFY3, dprintf("      DBG ERROR: should have raised an exception\n"); );
 		postException(einfo, JAVA_LANG(VerifyError));
 	}
-        cleanupInVerifyMethod(status, sigs, uninits, numBlocks, blocks);
+        cleanupInVerifyMethod(v);
         return(false);
 }
 
@@ -399,31 +410,32 @@
         /* to save some typing, etc. */
 	int codelen  = METHOD_BYTECODE_LEN(method);
 	
-	uint32* status = NULL; /* the status of each instruction...changed, visited, etc.
-				* used primarily to help find the basic blocks initially
-				*/
-
-	SigStack* sigs = NULL;
-	
-	UninitializedType* uninits = NULL;
+	Verifier v;
+	v.class = method->class;
+	v.method = method;
+	v.numBlocks = 0;
+	v.status = NULL;
+	v.blocks = NULL;
+	v.sigs = NULL;
+	v.uninits = NULL;
+	v.supertypes = NULL;
+	v.uninits = NULL;
 	
-	uint32      numBlocks = 0;
-	BlockInfo** blocks    = NULL;
 	
 	/**************************************************************************************************
 	 * Memory Allocation
 	 **************************************************************************************************/
 	DBG(VERIFY3, dprintf("        allocating memory for verification (codelen = %d)...\n", codelen); );
 	
-        status   = checkPtr((char*)gc_malloc(codelen * sizeof(uint32), GC_ALLOC_VERIFIER));
+        v.status = checkPtr((uint32*)gc_malloc(codelen * sizeof(uint32), GC_ALLOC_VERIFIER));
 	
 	/* find basic blocks and allocate memory for them */
-	blocks = verifyMethod3a(einfo, method, status, &numBlocks);
-	if (!blocks) {
+	verifyMethod3a(einfo, &v);
+	if (!v.blocks) {
 		DBG(VERIFY3, dprintf("        some kinda error finding the basic blocks in pass 3a\n"); );
 		
 		/* propagate error */
-		return failInVerifyMethod(einfo, method, status, sigs, uninits, &numBlocks, blocks);
+		return failInVerifyMethod(einfo, &v);
 	}
 	
 	DBG(VERIFY3, dprintf("        done allocating memory\n"); );
@@ -433,28 +445,26 @@
 	
 	/* load initial arguments into local variable array */
 	DBG(VERIFY3, dprintf("    about to load initial args...\n"); );
-	if (!loadInitialArgs(method, einfo, blocks[0], &sigs, &uninits)) {
+	if (!loadInitialArgs(einfo, &v)) {
 	        /* propagate error */
-		return failInVerifyMethod(einfo, method, status, sigs, uninits, &numBlocks, blocks);
+		return failInVerifyMethod(einfo, &v);
 	}
 	DBG(VERIFY3, {
 	        /* print out the local arguments */
 		int n;
-		for(n = 0; n < method->localsz; n++) {
+		for(n = 0; n < v.method->localsz; n++) {
 			dprintf("        local %d: ", n);
-			printType(&blocks[0]->locals[n]);
+			printType(&(v.blocks[0]->locals[n]));
 			dprintf("\n");
 		}
 	} );
 	
 	
-	if (!verifyMethod3b(einfo, method,
-			    status, blocks, numBlocks,
-			    &sigs, &uninits)) {
-		return failInVerifyMethod(einfo, method, status, sigs, uninits, &numBlocks, blocks);
+	if (!verifyMethod3b(einfo, &v)) {
+		return failInVerifyMethod(einfo, &v);
 	}
 	
-	cleanupInVerifyMethod(status, sigs, uninits, &numBlocks, blocks);
+	cleanupInVerifyMethod(&v);
 	DBG(VERIFY3, dprintf("    Verify Method 3b: done\n"); );
 	return(true);
 }
@@ -500,21 +510,18 @@
  *       of pass 3b, structural constraint checking.
  */
 static
-BlockInfo**
-verifyMethod3a(errorInfo* einfo,
-	       Method* method,
-	       uint32* status,    /* array of status info for all opcodes */
-	       uint32* numBlocks) /* number of basic blocks */
+void
+verifyMethod3a(errorInfo* einfo, Verifier* v)
 {
 
 #define ENSURE_NON_WIDE \
 	if (wide) { \
-		return verifyErrorInVerifyMethod3a(einfo, method, "illegal instruction following wide instruction"); \
+		return verifyErrorInVerifyMethod3a(einfo, v, "illegal instruction following wide instruction"); \
 	}
 
 #define CHECK_POOL_IDX(_IDX) \
 	if (_IDX > pool->size) { \
-		return verifyErrorInVerifyMethod3a(einfo, method, "attempt to access a constant pool index beyond constant pool range"); \
+		return verifyErrorInVerifyMethod3a(einfo, v, "attempt to access a constant pool index beyond constant pool range"); \
 	}
 
 	
@@ -527,23 +534,25 @@
 	CHECK_POOL_IDX(_IDX)
 
 #define BRANCH_IN_BOUNDS(_N, _INST) \
-	if (_N < 0 || _N >= codelen) { \
-	  return branchInBoundsErrorInVerifyMethod3a(einfo, method, codelen, _N); \
+	if (_N >= codelen) { \
+		branchInBoundsErrorInVerifyMethod3a(einfo, v, codelen, _N); \
+		return; \
 	}
 
         /* makes sure the index given for a local variable is within the correct index */
 #define CHECK_LOCAL_INDEX(_N) \
-	if ((_N) >= method->localsz) { \
-	  return checkLocalIndexErrorInVerifyMethod3a(einfo, method, pc, code, _N); \
+	if ((_N) >= v->method->localsz) { \
+		checkLocalIndexErrorInVerifyMethod3a(einfo, v, pc, code, _N); \
+		return; \
 	}
 	
-	constants* pool     = CLASS_CONSTANTS(method->class);
+	const constants* pool     = CLASS_CONSTANTS(v->method->class);
 	
 	/* used for looking at method signatures... */
 	const char* sig;
 	
-	int codelen         = METHOD_BYTECODE_LEN(method);
-	unsigned char* code = METHOD_BYTECODE_CODE(method);
+	uint32 codelen      = (uint32)METHOD_BYTECODE_LEN(v->method);
+	unsigned char* code = METHOD_BYTECODE_CODE(v->method);
 	
 	uint32 pc = 0, newpc = 0, n = 0, idx = 0;
 	int32 branchoffset = 0;
@@ -557,22 +566,24 @@
 	
 	
 	DBG(VERIFY3, dprintf("    Verifier Pass 3a: checking static constraints and finding basic blocks...\n"); );
-	
+	if (METHOD_BYTECODE_LEN(v->method) < 0) {
+		verifyErrorInVerifyMethod3a(einfo, v, "method bytecode length is less than 0");
+	}
 	
 	/* find the start of every instruction and basic block to determine legal branches
 	 *
 	 * also, this makes sure that only legal instructions follow the WIDE instruction
 	 */
-	status[0] |= START_BLOCK;
+	v->status[0] |= START_BLOCK;
 	wide = false;
 	pc = 0;
 	while(pc < codelen) {
-		status[pc] |= IS_INSTRUCTION;
+		v->status[pc] |= IS_INSTRUCTION;
 		
 		DBG(VERIFY3, dprintf("        instruction: (%d) ", pc); printInstruction(code[pc]); dprintf("\n"); );
 		
 		if (codelen < getNextPC(code, pc)) {
-			return verifyErrorInVerifyMethod3a(einfo, method, "last operand in code array is cut off");
+			return verifyErrorInVerifyMethod3a(einfo, v, "last operand in code array is cut off");
 		}
 		
 		switch(code[pc]) {
@@ -622,7 +633,8 @@
 			n = CONST_TAG(idx, pool);
 			if (n != CONSTANT_Integer && n != CONSTANT_Float &&
 			    n != CONSTANT_String && n != CONSTANT_ResolvedString) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "ldc* on constant pool entry other than int/float/string");
+				verifyErrorInVerifyMethod3a(einfo, v, "ldc* on constant pool entry other than int/float/string");
+				return;
 			}
 			break;
 			
@@ -630,7 +642,8 @@
 			GET_WIDX(idx, pc);
 			n = CONST_TAG(idx, pool);
 			if (n != CONSTANT_Double && n != CONSTANT_Long) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "ldc2_w on constant pool entry other than long or double");
+				verifyErrorInVerifyMethod3a(einfo, v, "ldc2_w on constant pool entry other than long or double");
+				return;
 			}
 			break;
 			
@@ -641,7 +654,8 @@
 			GET_WIDX(idx, pc);
 			idx = CONST_TAG(idx, pool);
 			if (idx != CONSTANT_Fieldref) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "[get/put][field/static] accesses something in the constant pool that is not a CONSTANT_Fieldref");
+				verifyErrorInVerifyMethod3a(einfo, v, "[get/put][field/static] accesses something in the constant pool that is not a CONSTANT_Fieldref");
+				return;
 			}
 			break;
 			
@@ -653,17 +667,20 @@
 			GET_WIDX(idx, pc);
 			n = CONST_TAG(idx, pool);
 			if (n != CONSTANT_Methodref) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "invoke* accesses something in the constant pool that is not a CONSTANT_Methodref");
+				verifyErrorInVerifyMethod3a(einfo, v, "invoke* accesses something in the constant pool that is not a CONSTANT_Methodref");
+				return;
 			}
 			
 			sig = METHODREF_SIGD(idx, pool);
 			if (*sig == '<') {
 				if (!strcmp(constructor_name->data, sig)) {
 					if (code[pc] != INVOKESPECIAL) {
-						return verifyErrorInVerifyMethod3a(einfo, method, "only invokespecial can be used to execute <init> methods");
+						 verifyErrorInVerifyMethod3a(einfo, v, "only invokespecial can be used to execute <init> methods");
+						 return;
 					}
 				} else {
-					return verifyErrorInVerifyMethod3a(einfo, method, "no method with a name whose first character is '<' may be called by an invoke instruction");
+					verifyErrorInVerifyMethod3a(einfo, v, "no method with a name whose first character is '<' may be called by an invoke instruction");
+					return;
 				}
 			}
 			
@@ -683,18 +700,22 @@
 			GET_WIDX(idx, pc);
 			n = CONST_TAG(idx, pool);
 			if (n != CONSTANT_InterfaceMethodref) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "invokeinterface accesses something in the constant pool that is not a CONSTANT_InterfaceMethodref");
+				verifyErrorInVerifyMethod3a(einfo, v, "invokeinterface accesses something in the constant pool that is not a CONSTANT_InterfaceMethodref");
+				return;
 			}
 			
 			sig = INTERFACEMETHODREF_SIGD(idx, pool);
 			if (*sig == '<') {
-				return verifyErrorInVerifyMethod3a(einfo, method, "invokeinterface cannot be used to invoke any instruction with a name starting with '<'");
+				verifyErrorInVerifyMethod3a(einfo, v, "invokeinterface cannot be used to invoke any instruction with a name starting with '<'");
+				return;
 			}
 			
 			if (code[pc + 3] == 0) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "fourth byte of invokeinterface is zero");
+				verifyErrorInVerifyMethod3a(einfo, v, "fourth byte of invokeinterface is zero");
+				return;
 			} else if (code[pc + 4] != 0) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "fifth byte of invokeinterface is not zero");
+				verifyErrorInVerifyMethod3a(einfo, v, "fifth byte of invokeinterface is not zero");
+				return;
 			}
 			
 			break;
@@ -707,7 +728,8 @@
 			GET_WIDX(n, pc);
 			n = CONST_TAG(n, pool);
 			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "instanceof/checkcast indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");
+				verifyErrorInVerifyMethod3a(einfo, v, "instanceof/checkcast indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");
+				return;
 			}
 			
 			break;
@@ -719,18 +741,21 @@
 			GET_WIDX(idx, pc);
 			n = CONST_TAG(idx, pool);
 			if (n != CONSTANT_Class && n != CONSTANT_ResolvedClass) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "multinewarray indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");
+				verifyErrorInVerifyMethod3a(einfo, v, "multinewarray indexes a constant pool entry that is not type CONSTANT_Class or CONSTANT_ResolvedClass");
+				return;
 			}
 			
 			/* number of dimensions must be <= num dimensions of array type being created */
 			sig = CLASS_NAMED(idx, pool);
 			newpc = code[pc + 3];
 			if (newpc == 0) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "dimensions operand of multianewarray must be non-zero");
+				verifyErrorInVerifyMethod3a(einfo, v, "dimensions operand of multianewarray must be non-zero");
+				return;
 			}
 			for(n = 0; *sig == '['; sig++, n++);
 			if (n < newpc) {
-				return verifyErrorInVerifyMethod3a(einfo, method, "dimensions operand of multianewarray is > the number of dimensions in array being created");
+				verifyErrorInVerifyMethod3a(einfo, v, "dimensions operand of multianewarray is > the number of dimensions in array being created");
+				return;
 			}
 			
 			break;
@@ -742,13 +767,15 @@
 			GET_WIDX(idx, pc);

*** Patch too long, truncated ***




More information about the kaffe mailing list