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 / classMethod.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  12KB  |  598 lines

  1. /*
  2.  * classMethod.c
  3.  * Dictionary of classes, methods and fields.
  4.  *
  5.  * Copyright (c) 1996 Systems Architecture Research Centre,
  6.  *           City University, London, UK.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
  12.  */
  13.  
  14. #define    CDBG(s)
  15. #define    MDBG(s)
  16. #define    FDBG(s)
  17.  
  18. #include <stdio.h>
  19. #include <assert.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include "gtypes.h"
  23. #include "slots.h"
  24. #include "access.h"
  25. #include "object.h"
  26. #include "constants.h"
  27. #include "classMethod.h"
  28. #include "code.h"
  29. #include "file.h"
  30. #include "readClass.h"
  31. #include "baseClasses.h"
  32. #include "errors.h"
  33. #include "exception.h"
  34.  
  35. extern strpair* initpair;    /* Class init pair <clinit>()V */
  36. extern strpair* finalpair;    /* Class finalize pair finalize()V */
  37. extern classes* classInitHead;
  38. extern int classInitLevel;
  39.  
  40. static classes* classPool[CLASSHASHSZ];
  41. methods* methodList;    /* For exception processing */
  42.  
  43. void findClass(char*);
  44.  
  45. static classes* internalAddClass(char*, char*, int, char*, classes*, int, constants*);
  46.  
  47. classes*
  48. addClass(constIndex c, constIndex s, u2 flags, constants* pool)
  49. {
  50.     char* str;
  51.     char* sstr;
  52.     classes* su;
  53.     int basesize;
  54.     char sig[CLASSMAXSIG];
  55.  
  56.     /* Find the name of the class */
  57.     if (pool->tags[c] != CONSTANT_Class) {
  58. CDBG(        printf("addClass: not a class.\n");            )
  59.         return (0);
  60.     }
  61.     c = pool->data[c].v.tint;
  62.     if (pool->tags[c] != CONSTANT_Utf8) {
  63. CDBG(        printf("addClass: not a Utf8.\n");            )
  64.         return (0);
  65.     }
  66.     str = pool->data[c].v.tstr;
  67.     assert(strlen(str) > 0);
  68.  
  69.     /* Build signature */
  70.     if (str[0] != '[') {
  71.         strcpy(sig, "L");
  72.         strcat(sig, str);
  73.         strcat(sig, ";");
  74.     }
  75.     else {
  76.         strcpy(sig, str);
  77.     }
  78.  
  79.     /* Find the name of the super class */
  80.     if (s != 0) {
  81.         if (pool->tags[s] != CONSTANT_Class) {
  82. CDBG(            printf("addClass: not a class.\n");        )
  83.             return (0);
  84.         }
  85.         s = pool->data[s].v.tint;
  86.         if (pool->tags[s] != CONSTANT_Utf8) {
  87. CDBG(            printf("addClass: not a Utf8.\n");        )
  88.             return (0);
  89.         }
  90.         sstr = pool->data[s].v.tstr;
  91.         /* Make sure it's loaded in */
  92.         su = lookupClass(sstr);
  93.         if (su == 0) {
  94.             return (0);
  95.         }
  96.         basesize = su->fsize;
  97.     }
  98.     else {
  99.         su = 0;
  100.         basesize = 0;
  101.         sstr = 0;
  102.     }
  103.  
  104. CDBG(    printf("Adding class %s (%x)\n", str, flags);            )
  105.  
  106.     return (internalAddClass(str, addString(sig), flags, sstr, su, basesize, pool));
  107. }
  108.  
  109. static
  110. classes*
  111. internalAddClass(char* str, char* sig, int flags, char* sstr, classes* su, int basesize, constants* pool)
  112. {
  113.     classes** clp;
  114.     classes* cl;
  115.     methodTable* mt;
  116.     uint32 hash;
  117.     int i;
  118.  
  119.     for (i = 0, hash = 0; str[i] != 0; i++) {
  120.         hash = hash * 33 + str[i];
  121.     }
  122.     hash %= CLASSHASHSZ;
  123.  
  124.     clp = &classPool[hash];
  125. #ifdef DEBUG
  126.     while (*clp != 0) {
  127.         assert(str != (*clp)->name);
  128.         clp = &(*clp)->next;
  129.     }
  130. #endif
  131.  
  132.     /* Allocate a class - it's an object too! */
  133.     cl = alloc_class();
  134.     if (cl == 0) {
  135.         return (0);
  136.     }
  137.     mt = (methodTable*)calloc(sizeof(methodTable), 1);
  138.     if (mt == 0) {
  139.         return (0);
  140.     }
  141.     mt->class = cl;
  142.  
  143.     cl->name = str;
  144.     cl->sig = sig;
  145.     cl->supername = sstr;
  146.     cl->constants = pool;
  147.     cl->methodList = 0;
  148.     cl->fieldList = 0;
  149.     cl->staticFieldList = 0;
  150.     cl->superclass = su;
  151.     if (su == 0) {
  152.         cl->msize = 0;
  153.     }
  154.     else {
  155.         cl->msize = su->msize;
  156.     }
  157.     cl->fsize = basesize;
  158.     cl->sfsize = 0;
  159.     cl->accflags = flags;
  160.     cl->mtable = mt;
  161.     cl->dtable = 0;
  162.     cl->staticFields = 0;
  163.         cl->interfaces = 0;
  164.     cl->interface_len = 0;
  165.     cl->state = CSTATE_OK;
  166.     cl->final = false;
  167.     /* Add into list */
  168.     cl->next = *clp;
  169.     *clp = cl;
  170.  
  171.     return (cl);
  172. }
  173.  
  174. methods*
  175. addMethod(classes* c, method_info* m)
  176. {
  177.     constIndex nc;
  178.     constIndex sc;
  179.     methods** mptr;
  180.     methods* mt;
  181.     constants* pool;
  182.     strpair* pair;
  183.     int idx;
  184.     classes* spc;
  185.  
  186.     pool = c->constants;
  187.  
  188.     nc = m->name_index;
  189.     if (pool->tags[nc] != CONSTANT_Utf8) {
  190. MDBG(        printf("addMethod: no method name.\n");            )
  191.         return (0);
  192.     }
  193.     sc = m->signature_index;
  194.     if (pool->tags[sc] != CONSTANT_Utf8) {
  195. MDBG(        printf("addMethod: no signature name.\n");        )
  196.         return (0);
  197.     }
  198.     pair = addStringConstantPair(pool->data[nc].v.tstr, pool->data[sc].v.tstr);
  199.     assert(pair != 0);
  200.  
  201.     /* Mark class for init if this is the class init method */
  202.     if (pair == initpair) {
  203.         c->state = CSTATE_NEEDINIT;
  204.     }
  205.     else if (pair == finalpair) {
  206.         c->final = true;
  207.     }
  208.  
  209.     /* Search superclasses for equivalent method name.  If found extract
  210.      * it's index nr.
  211.      */
  212.     for (spc = c->superclass; spc != 0; spc = spc->superclass) {
  213.         for (mt = spc->methodList; mt != 0; mt = mt->next) {
  214.             if (mt->pair == pair) {
  215.                 idx = mt->idx;
  216.                 goto foundmatch;
  217.             }
  218.         }
  219.     }
  220.     /* No match found so allocate a new index number */
  221.     idx = c->msize;
  222.     c->msize++;
  223.     foundmatch:
  224.  
  225.     mptr = &c->methodList;
  226. #ifdef DEBUG
  227.     /* Search down class for method name - don't allow duplicates */
  228.     while (*mptr != 0) {
  229.         assert(pair != (*mptr)->pair);
  230.         mptr = &(*mptr)->next;
  231.     }
  232. #endif
  233.  
  234. MDBG(    printf("Adding method %s:%s%s (%x)\n", c->name, pool->data[nc].v.str, pool->data[sc].v.str, m->access_flags);    )
  235.  
  236.     mt = malloc(sizeof(methods));
  237.     if (mt == 0) {
  238.         return (0);
  239.     }
  240.     mt->pair = pair;
  241.     mt->class = c;
  242.     mt->accflags = m->access_flags;
  243.     mt->code = 0;
  244.     mt->insn = 0;
  245.     mt->ncode = 0;
  246.     mt->constants = pool;
  247.     mt->stacksz = 0;
  248.     mt->localsz = 0;
  249.     mt->exception_table = 0;
  250.     mt->exception_table_len = 0;
  251.     mt->exception_next = 0;
  252.     mt->idx = idx;
  253.     countInsAndOuts(pool->data[sc].v.tstr, &mt->ins, &mt->outs, &mt->outtype);
  254.     mt->next = *mptr;
  255.     *mptr = mt;
  256.  
  257.     return (mt);
  258. }
  259.  
  260. /*
  261.  * All class methods read in.  Built the method dispatch table.
  262.  */
  263. void
  264. finishClassMethods(classes* c)
  265. {
  266.     dispatchTable* tab;
  267.  
  268.     tab = (dispatchTable*)calloc(sizeof(dispatchTable) + (c->msize * sizeof(void*)), 1);
  269.     assert(tab != 0);
  270.     tab->class = c;
  271.     tab->mtable = c->mtable;
  272.     c->dtable = tab;
  273. }
  274.  
  275. fields*
  276. addField(classes* c, field_info* f)
  277. {
  278.     constIndex nc;
  279.     constIndex sc;
  280.     fields** fptr;
  281.     fields* ft;
  282.     char* sig;
  283.     constants* pool;
  284.     int* optr;
  285.  
  286.     pool = c->constants;
  287.  
  288.     nc = f->name_index;
  289.     if (pool->tags[nc] != CONSTANT_Utf8) {
  290. FDBG(        printf("addField: no field name.\n");            )
  291.         return (0);
  292.     }
  293.  
  294.     /* Search down class for field name */
  295.     if (f->access_flags & ACC_STATIC) {
  296.         fptr = &c->staticFieldList;
  297.         optr = &c->sfsize;
  298.     }
  299.     else {
  300.         fptr = &c->fieldList;
  301.         optr = &c->fsize;
  302.     }
  303. #ifdef DEBUG
  304.     while (*fptr != 0) {
  305.         assert(pool->data[nc].v.tstr != (*fptr)->name);
  306.         fptr = &(*fptr)->next;
  307.     }
  308. #endif
  309.  
  310. FDBG(    printf("Adding field %s:%s\n", c->name, pool->data[nc].v.tstr);    )
  311.  
  312.     sc = f->signature_index;
  313.     if (pool->tags[sc] != CONSTANT_Utf8) {
  314. FDBG(        printf("addField: no signature name.\n");        )
  315.         return (0);
  316.     }
  317.     sig = pool->data[sc].v.tstr;
  318.  
  319.     ft = malloc(sizeof(fields));
  320.     if (ft == 0) {
  321.         return (0);
  322.     }
  323.     ft->name = pool->data[nc].v.tstr;
  324.     ft->sig = sig;
  325.     ft->class = c;
  326.     ft->accflags = f->access_flags;
  327.     ft->size = sizeofSig(&sig);
  328.     /* Align field offset */
  329.     if (((*optr) % ft->size) == 1) {
  330.         (*optr)++;
  331.     }
  332.     ft->offset = *optr;
  333.     (*optr) += ft->size;
  334.     ft->next = *fptr;
  335.     *fptr = ft;
  336.  
  337.     return (ft);
  338. }
  339.  
  340. void
  341. addMethodCode(methods* m, Code* c)
  342. {
  343.     m->code = c->code;
  344.     m->codelen = c->code_length;
  345.     m->stacksz = c->max_stack;
  346.     m->localsz = c->max_locals;
  347.     m->exception_table = c->exception_table;
  348.     m->exception_table_len = c->exception_table_length;
  349. }
  350.  
  351. void
  352. addInterfaces(classes* c, int inr, classes** inf)
  353. {
  354.     assert(inr > 0);
  355.  
  356.         c->interfaces = inf;
  357.     c->interface_len = inr;
  358. }
  359.  
  360. /*
  361.  * Lookup a named class, loading it if necessary.
  362.  */
  363. classes*
  364. lookupClass(char* c)
  365. {
  366.     classes* class;
  367.  
  368.     class = simpleLookupClass(c);
  369.     if (class == 0) {
  370.         /* Failed to find class, so must now load it */
  371.         findClass(c);
  372.  
  373.         /* Once loaded, allocate the static data space */
  374.         class = simpleLookupClass(c);
  375.         if (class == 0) {
  376.                         throwException(ClassNotFoundException);
  377.         }
  378.         if (class->sfsize > 0) {
  379.             class->staticFields = (int*)calloc(class->sfsize, sizeof(int));
  380.             assert(class->staticFields != 0);
  381.         }
  382.     }
  383.     /* This class requires initialisation so place it at head of
  384.        current init list.  If already at head of an init list (not this
  385.        one), then we have a recursive init which is an error */
  386.     if (class->state == CSTATE_OK || class->state == classInitLevel) {
  387.         /* Do nothing. */
  388.     }
  389.     else {
  390.         assert(class->state <= classInitLevel);
  391.         /* If already on a list, remove it */
  392.         if (class->state != CSTATE_NEEDINIT) {
  393.             if (class->prevInit == 0) {
  394.                                 throwException(ClassCircularityError);
  395.             }
  396.             class->prevInit->nextInit = class->nextInit;
  397.             if (class->nextInit != 0) {
  398.                 class->nextInit->prevInit = class->prevInit;
  399.             }
  400.         }
  401.         /* Insert onto current list */
  402.         class->state = classInitLevel;
  403.         class->prevInit = 0;
  404.         class->nextInit = classInitHead;
  405.         if (classInitHead) {
  406.             classInitHead->prevInit = class;
  407.         }
  408.         classInitHead = class;
  409. #if defined(INTERPRETER)
  410.         /* We must do this as we go along when interpreting */
  411.         initClasses();
  412. #endif
  413.     }
  414.     return (class);
  415. }
  416.  
  417. classes*
  418. simpleLookupClass(char* c)
  419. {
  420.     uint32 hash;
  421.     char* str;
  422.     classes* clp;
  423.  
  424.     for (str = c, hash = 0; *str !=  0; str++) {
  425.         hash = hash * 33 + *str;
  426.     }
  427.     hash %= CLASSHASHSZ;
  428.  
  429.     clp = classPool[hash];
  430.     while (clp != 0) {
  431.         if (c == clp->name) {
  432.             return (clp);
  433.         }
  434.         clp = clp->next;
  435.     }
  436.     return (0);
  437. }
  438.  
  439. /*
  440.  * Lookup a named field.
  441.  */
  442. fields*
  443. lookupClassField(char* c, char* f, bool isStatic)
  444. {
  445.     classes* clp;
  446.     fields* fptr;
  447.  
  448.     /* Look for class */
  449.     clp = lookupClass(c);
  450.     if (clp == 0) {
  451.         return (0);
  452.     }
  453.  
  454.     /* Search down class for field name */
  455.     if (isStatic) {
  456.         fptr = clp->staticFieldList;
  457.     }
  458.     else {
  459.         fptr = clp->fieldList;
  460.     }
  461.     while (fptr != 0) {
  462.         if (f == fptr->name) {
  463.             return (fptr);
  464.         }
  465.         fptr = fptr->next;
  466.     }
  467. FDBG(    printf("Class:field lookup failed %s:%s\n", c, f);        )
  468.     return (0);
  469. }
  470.  
  471. /*
  472.  * Determine the number of arguments and return values from the
  473.  * method signature.
  474.  */
  475. void
  476. countInsAndOuts(char* str, int* ins, int* outs, char* outtype)
  477. {
  478.     *ins = sizeofSig(&str);
  479.     *outtype = str[0];
  480.     *outs = sizeofSig(&str);
  481. }
  482.  
  483. /*
  484.  * Calculate size of data item based on signature.
  485.  */
  486. int
  487. sizeofSig(char** strp)
  488. {
  489.     int count;
  490.     int c;
  491.  
  492.     count = 0;
  493.     for (;;) {
  494.         c = sizeofSigItem(strp, 0);
  495.         if (c == -1) {
  496.             return (count);
  497.         }
  498.         count += c;
  499.     }
  500. }
  501.  
  502. /*
  503.  * Calculate size of a signature item.
  504.  */
  505. int
  506. sizeofSigItem(char** strp, char* sig)
  507. {
  508.     int count;
  509.     char* str;
  510.  
  511.     for (str = *strp; ; str++) {
  512.  
  513.         /* Return sig if requested */
  514.         if (sig != 0) {
  515.             *sig = *str;
  516.         }
  517.  
  518.         switch (*str) {
  519.         case '(':
  520.             continue;
  521.         case 0:
  522.         case ')':
  523.             count = -1;
  524.             break;
  525.         case 'V':
  526.             count = 0;
  527.             break;
  528.         case 'I':
  529.         case 'Z':
  530.         case 'S':
  531.         case 'B':
  532.         case 'C':
  533.         case 'F':
  534.             count = 1;
  535.             break;
  536.         case 'D':
  537.         case 'J':
  538.             count = 2;
  539.             break;
  540.         case '[':
  541.             count = 1;
  542.             arrayofarray:
  543.             str++;
  544.             if (*str == 'L') {
  545.                 while (*str != ';') {
  546.                     str++;
  547.                 }
  548.             }
  549.             else if (*str == '[') {
  550.                 goto arrayofarray;
  551.             }
  552.             break;
  553.         case 'L':
  554.             count = 1;
  555.             /* Skip to end of reference */
  556.             while (*str != ';') {
  557.                 str++;
  558.             }
  559.             break;
  560.         default:
  561.             abort();
  562.         }
  563.  
  564.         *strp = str + 1;
  565.         return (count);
  566.     }
  567. }
  568.  
  569. /*
  570.  * Add this method to the method list so we can find it when
  571.  * handling exceptions.
  572.  */
  573. void
  574. establishMethod(methods* m)
  575. {
  576.     m->exception_next = methodList;
  577.     methodList = m;
  578. }
  579.  
  580. /*
  581.  * Lookup an array class.
  582.  */
  583. classes*
  584. lookupArray(char* c)
  585. {
  586.     classes* class;
  587.  
  588.     class = simpleLookupClass(c);
  589.     if (class == 0) {
  590.         class = internalAddClass(c, c, 0, ObjectClassName, ObjectClass, 0, 0);
  591. CDBG(        if (class == 0) {
  592.             printf("Array Class %s not loaded.\n", c);
  593.         }                            )
  594.         finishClassMethods(class);
  595.     }
  596.     return (class);
  597. }
  598.