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 <[EMAIL PROTECTED]>
+       * kaffe/kaffevm/verify*.[ch]
+       Finished adding support for multiple inheritence.
+       Some more code cleaning:  checking off some basic TODOs.
+
+2004-06-26  Rob Gonzalez <[EMAIL PROTECTED]>
        * 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 <[EMAIL PROTECTED]>
+ *
+ * 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 <[EMAIL PROTECTED]>
  */
 
 #include "access.h"

_______________________________________________
kaffe mailing list
[EMAIL PROTECTED]
http://kaffe.org/cgi-bin/mailman/listinfo/kaffe

Reply via email to