/****************************** comp/parse.c *********************************** Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst See file COPYRIGHT for information on usage and disclaimer of warranties Enth"alt den Parser f"ur die Bytecode-Darstellung der Methoden Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at Andreas Krall EMAIL: cacao@complang.tuwien.ac.at Last Change: 1997/10/17 *******************************************************************************/ /* Kurzschreibweise f"ur oft verwendete Funktionen */ #define LOADCONST_I pcmd_loadconst_i #define LOADCONST_L pcmd_loadconst_l #define LOADCONST_F pcmd_loadconst_f #define LOADCONST_D pcmd_loadconst_d #define LOADCONST_A pcmd_loadconst_a #define MOVE pcmd_move #define IINC pcmd_iinc #define OP pcmd_op #define MEM pcmd_mem #define BRA pcmd_bra #define TABLEJUMP pcmd_tablejump #define METHOD pcmd_method #define BUILTIN1 pcmd_builtin1 #define BUILTIN2 pcmd_builtin2 #define BUILTIN3 pcmd_builtin3 #define DROP pcmd_drop #define ACTIVATE pcmd_activate #define BRA_N_DROP pcmd_bra_n_drop #define MOVE_N_DROP pcmd_move_n_drop #define OP1(opcode,s,d) OP(opcode,s,NOVAR,NOVAR,d) #define OP2(opcode,s1,s2,d) OP(opcode,s1,s2,NOVAR,d) #define OP3(opcode,s1,s2,s3,d) OP(opcode,s1,s2,s3,d) #define EXCREATOR(exclass) block_createexcreator (exclass, p) #define EXFORWARDER(exvar) block_createexforwarder (exvar, p) /****************** Funktion: addreturnlog ************************************ f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung ein. ******************************************************************************/ static void addreturnhandling() { if (checksync && (method->flags & ACC_SYNCHRONIZED) ) { stack_makesaved (); #ifdef USE_THREADS if (method->flags & ACC_STATIC) { varid v = var_create (TYPE_ADDRESS); LOADCONST_A (class, v); BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR); } else { BUILTIN1 ( (functionptr) builtin_monitorexit, local_get (0, TYPE_ADDRESS) , NOVAR); } #endif } } /*************** Funktion: addreturnexceptionlog ***************************** f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung mit Exception ein. ******************************************************************************/ static void addreturnexceptionhandling() { if (runverbose) { varid v; stack_makesaved (); v = var_create (TYPE_ADDRESS); LOADCONST_A (method, v); BUILTIN1 ( (functionptr) builtin_displaymethodexception, v, NOVAR); } if (checksync && (method->flags & ACC_SYNCHRONIZED) ) { stack_makesaved (); #ifdef USE_THREADS if (method->flags & ACC_STATIC) { varid v = var_create (TYPE_ADDRESS); LOADCONST_A (class, v); BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR); } else { BUILTIN1 ( (functionptr) builtin_monitorexit, local_get (0, TYPE_ADDRESS) , NOVAR); } #endif } } /****************************************************************************** *************** Funktion 'parse' zum Durcharbeiten des Bytecodes ************** ******************************************************************************/ static void parse (basicblock *b) { varid v,v1,v2,v3,ve; u4 poolindex; s4 type; u4 p,i; basicblock *target=NULL; bool iswide=false; stack_restore (b->stack); subroutine_set (b->subroutine); switch (b->type) { /* Code fuer einen Exception-Forwarder generieren */ case BLOCKTYPE_EXFORWARDER: if (!compileall) { ACTIVATE (b->exvar); stack_repush (b->exvar); stack_makesaved (); for (i=0; ithrowpos && extable[i].endpc > b->throwpos) { if (!extable[i].catchtype) goto exceptionfits; stack_makesaved(); v1 = var_create (TYPE_ADDRESS); v2 = var_create (TYPE_ADDRESS); v = var_create (TYPE_INT); MOVE (TYPE_ADDRESS, b->exvar, v1); LOADCONST_A (extable[i].catchtype, v2); BUILTIN2 ((functionptr) builtin_instanceof, v1,v2, v); block_reach (target); BRA_N_DROP (CMD_IFNE, v,NOVAR, NOVAR, target); } } target = NULL; } goto exceptionfits; /* Code fuer einen Exception-Creator generieren */ case BLOCKTYPE_EXCREATOR: if (!compileall) { java_objectheader *o = b->exproto; LOADCONST_A (o, stack_push(TYPE_ADDRESS) ); for (i=0; ithrowpos && extable[i].endpc > b->throwpos) { if (!extable[i].catchtype) goto exceptionfits; if (builtin_instanceof (o, extable[i].catchtype) ) goto exceptionfits; } } target = NULL; } /*** Der Sprung zum Exception-Handler (oder Methodenbeendigung) ***/ exceptionfits: if (!compileall) { if (target) { block_reach (target); BRA (CMD_GOTO, NOVAR,NOVAR,NOVAR, target); goto cleanup; } #ifdef STATISTICS count_pcmd_returnx++; #endif switch (mreturntype) { case TYPE_INT: addreturnexceptionhandling(); v1 = var_create (TYPE_INT); LOADCONST_I (0, v1); BRA_N_DROP (CMD_IRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL); break; case TYPE_LONG: addreturnexceptionhandling(); v1 = var_create (TYPE_LONG); LOADCONST_I (0, v1); BRA_N_DROP (CMD_LRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL); break; case TYPE_FLOAT: addreturnexceptionhandling(); v1 = var_create (TYPE_FLOAT); LOADCONST_F (0.0, v1); BRA_N_DROP (CMD_FRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL); break; case TYPE_DOUBLE: addreturnexceptionhandling(); v1 = var_create (TYPE_DOUBLE); LOADCONST_D (0.0, v1); BRA_N_DROP (CMD_DRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL); break; case TYPE_ADDRESS: addreturnexceptionhandling(); v1 = var_create (TYPE_ADDRESS); LOADCONST_A (NULL, v1); BRA_N_DROP (CMD_ARETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL); break; case TYPE_VOID: addreturnexceptionhandling(); BRA (CMD_RETURN, NOVAR,stack_pop(TYPE_ADDRESS), NOVAR, NULL); break; } } goto cleanup; } /* Code fuer einen (normalen) JavaVM - Block generieren */ p = b->jpc; if ( p==0) { /* Method call protocolling */ if (runverbose) { stack_makesaved(); pcmd_trace (method); } /* Synchronization */ if (checksync && (method->flags & ACC_SYNCHRONIZED)) { stack_makesaved(); #ifdef USE_THREADS if (method->flags & ACC_STATIC) { varid v = var_create (TYPE_ADDRESS); LOADCONST_A (class, v); BUILTIN1 ( (functionptr) builtin_monitorenter, v, NOVAR); } else { BUILTIN1 ( (functionptr) builtin_monitorenter, local_get (0, TYPE_ADDRESS), NOVAR ); } #endif } } for (;;) { u1 opcode; u4 nextp; opcode = code_get_u1 (p); nextp = p + jcommandsize[opcode]; count_javainstr++; if (showstack) { printf ("PC: %3d OPCODE: %3d Stack: ",(int) p, (int) opcode); stack_display (stack_get()); printf ("\n"); } switch (opcode) { /*** Pushing constants onto the stack ***/ case CMD_BIPUSH: LOADCONST_I (code_get_s1 (p+1), stack_push (TYPE_INT) ); break; case CMD_SIPUSH: LOADCONST_I (code_get_s2 (p+1), stack_push (TYPE_INT) ); break; case CMD_LDC1: poolindex = code_get_u1 (p+1); goto pushconstantitem; case CMD_LDC2: case CMD_LDC2W: poolindex = code_get_u2 (p+1); pushconstantitem: switch (class_constanttype(class, poolindex)) { case CONSTANT_Integer: { constant_integer *c; c = class_getconstant (class, poolindex, CONSTANT_Integer); LOADCONST_I (c->value, stack_push(TYPE_INT) ); } break; case CONSTANT_Long: { constant_long *c; c = class_getconstant (class, poolindex, CONSTANT_Long); LOADCONST_L (c->value, stack_push(TYPE_LONG) ); } break; case CONSTANT_Float: { constant_float *c; c = class_getconstant (class, poolindex, CONSTANT_Float); LOADCONST_F (c->value, stack_push(TYPE_FLOAT) ); } break; case CONSTANT_Double: { constant_double *c; c = class_getconstant (class, poolindex, CONSTANT_Double); LOADCONST_D (c->value, stack_push(TYPE_DOUBLE) ); } break; case CONSTANT_String: { unicode *s; s = class_getconstant (class, poolindex, CONSTANT_String); LOADCONST_A ( literalstring_new (s), stack_push(TYPE_ADDRESS) ); } break; default: panic ("Invalid constant type to push"); } break; case CMD_ACONST_NULL: LOADCONST_A (0, stack_push (TYPE_ADDRESS) ); break; case CMD_ICONST_M1: case CMD_ICONST_0: case CMD_ICONST_1: case CMD_ICONST_2: case CMD_ICONST_3: case CMD_ICONST_4: case CMD_ICONST_5: LOADCONST_I (opcode - CMD_ICONST_0, stack_push (TYPE_INT) ); break; case CMD_LCONST_0: case CMD_LCONST_1: #if U8_AVAILABLE LOADCONST_L (opcode - CMD_LCONST_0, stack_push (TYPE_LONG) ); #else { u8 v; v.low = opcode - CMD_LCONST_0; v.high = 0; LOADCONST_L (v, stack_push(TYPE_LONG) ); } #endif break; case CMD_FCONST_0: case CMD_FCONST_1: case CMD_FCONST_2: LOADCONST_F (opcode - CMD_FCONST_0, stack_push (TYPE_FLOAT) ); break; case CMD_DCONST_0: case CMD_DCONST_1: LOADCONST_D (opcode - CMD_DCONST_0, stack_push (TYPE_DOUBLE) ); break; /*** Loading variables onto the Stack ***/ case CMD_ILOAD: if (!iswide) { MOVE ( TYPE_INT, local_get (code_get_u1 (p+1), TYPE_INT), stack_push (TYPE_INT) ); } else { MOVE ( TYPE_INT, local_get (code_get_u2 (p+1), TYPE_INT), stack_push (TYPE_INT) ); nextp = p+3; iswide = false; } break; case CMD_ILOAD_0: case CMD_ILOAD_1: case CMD_ILOAD_2: case CMD_ILOAD_3: MOVE ( TYPE_INT, local_get (opcode - CMD_ILOAD_0, TYPE_INT), stack_push (TYPE_INT) ); break; case CMD_LLOAD: if (!iswide) { MOVE ( TYPE_LONG, local_get (code_get_u1 (p+1), TYPE_LONG), stack_push (TYPE_LONG) ); } else { MOVE ( TYPE_LONG, local_get (code_get_u2 (p+1), TYPE_LONG), stack_push (TYPE_LONG) ); nextp = p+3; iswide = false; } break; case CMD_LLOAD_0: case CMD_LLOAD_1: case CMD_LLOAD_2: case CMD_LLOAD_3: MOVE ( TYPE_LONG, local_get (opcode - CMD_LLOAD_0, TYPE_LONG), stack_push (TYPE_LONG) ); break; case CMD_FLOAD: if (!iswide) { MOVE ( TYPE_FLOAT, local_get (code_get_u1 (p+1), TYPE_FLOAT), stack_push (TYPE_FLOAT) ); } else { MOVE ( TYPE_FLOAT, local_get (code_get_u2 (p+1), TYPE_FLOAT), stack_push (TYPE_FLOAT) ); nextp = p+3; iswide = false; } break; case CMD_FLOAD_0: case CMD_FLOAD_1: case CMD_FLOAD_2: case CMD_FLOAD_3: MOVE ( TYPE_FLOAT, local_get (opcode - CMD_FLOAD_0, TYPE_FLOAT), stack_push (TYPE_FLOAT) ); break; case CMD_DLOAD: if (!iswide) { MOVE ( TYPE_DOUBLE, local_get (code_get_u1 (p+1), TYPE_DOUBLE), stack_push (TYPE_DOUBLE) ); } else { MOVE ( TYPE_DOUBLE, local_get (code_get_u2 (p+1), TYPE_DOUBLE), stack_push (TYPE_DOUBLE) ); nextp = p+3; iswide = false; } break; case CMD_DLOAD_0: case CMD_DLOAD_1: case CMD_DLOAD_2: case CMD_DLOAD_3: MOVE ( TYPE_DOUBLE, local_get (opcode - CMD_DLOAD_0, TYPE_DOUBLE), stack_push (TYPE_DOUBLE) ); break; case CMD_ALOAD: if (!iswide) { MOVE ( TYPE_ADDRESS, local_get (code_get_u1 (p+1), TYPE_ADDRESS), stack_push (TYPE_ADDRESS) ); } else { MOVE ( TYPE_ADDRESS, local_get (code_get_u2 (p+1), TYPE_ADDRESS), stack_push (TYPE_ADDRESS) ); nextp = p+3; iswide = false; } break; case CMD_ALOAD_0: case CMD_ALOAD_1: case CMD_ALOAD_2: case CMD_ALOAD_3: MOVE ( TYPE_ADDRESS, local_get (opcode - CMD_ALOAD_0, TYPE_ADDRESS), stack_push (TYPE_ADDRESS) ); break; /*** Storing Stack Values into Local Variables ***/ case CMD_ISTORE: v = stack_pop (TYPE_INT); if (!iswide) { MOVE_N_DROP (TYPE_INT, v, local_get (code_get_u1 (p+1), TYPE_INT) ); } else { MOVE_N_DROP (TYPE_INT, v, local_get (code_get_u2 (p+1), TYPE_INT) ); iswide=false; nextp = p+3; } break; case CMD_ISTORE_0: case CMD_ISTORE_1: case CMD_ISTORE_2: case CMD_ISTORE_3: v = stack_pop (TYPE_INT); MOVE_N_DROP (TYPE_INT, v, local_get (opcode - CMD_ISTORE_0, TYPE_INT) ); break; case CMD_LSTORE: v = stack_pop (TYPE_LONG); if (!iswide) { MOVE_N_DROP (TYPE_LONG, v, local_get (code_get_u1 (p+1), TYPE_LONG) ); } else { MOVE_N_DROP (TYPE_LONG, v, local_get (code_get_u2 (p+1), TYPE_LONG) ); iswide=false; nextp = p+3; } break; case CMD_LSTORE_0: case CMD_LSTORE_1: case CMD_LSTORE_2: case CMD_LSTORE_3: v = stack_pop (TYPE_LONG); MOVE_N_DROP (TYPE_LONG, v, local_get (opcode - CMD_LSTORE_0, TYPE_LONG) ); break; case CMD_FSTORE: v = stack_pop (TYPE_FLOAT); if (!iswide) { MOVE_N_DROP (TYPE_FLOAT, v, local_get (code_get_u1 (p+1), TYPE_FLOAT) ); } else { MOVE_N_DROP (TYPE_FLOAT, v, local_get (code_get_u2 (p+1), TYPE_FLOAT) ); iswide=false; nextp = p+3; } break; case CMD_FSTORE_0: case CMD_FSTORE_1: case CMD_FSTORE_2: case CMD_FSTORE_3: v = stack_pop (TYPE_FLOAT); MOVE_N_DROP (TYPE_FLOAT, v, local_get (opcode - CMD_FSTORE_0, TYPE_FLOAT) ); break; case CMD_DSTORE: v = stack_pop (TYPE_DOUBLE); if (!iswide) { MOVE_N_DROP (TYPE_DOUBLE, v, local_get (code_get_u1 (p+1), TYPE_DOUBLE) ); } else { MOVE_N_DROP (TYPE_DOUBLE, v, local_get (code_get_u2 (p+1), TYPE_DOUBLE) ); iswide=false; nextp = p+3; } break; case CMD_DSTORE_0: case CMD_DSTORE_1: case CMD_DSTORE_2: case CMD_DSTORE_3: v = stack_pop (TYPE_DOUBLE); MOVE_N_DROP (TYPE_DOUBLE, v, local_get (opcode - CMD_DSTORE_0, TYPE_DOUBLE) ); break; case CMD_ASTORE: v = stack_pop (TYPE_ADDRESS); if (!iswide) { MOVE_N_DROP (TYPE_ADDRESS, v, local_get (code_get_u1 (p+1), TYPE_ADDRESS) ); } else { MOVE_N_DROP (TYPE_ADDRESS, v, local_get (code_get_u2 (p+1), TYPE_ADDRESS) ); iswide=false; nextp = p+3; } break; case CMD_ASTORE_0: case CMD_ASTORE_1: case CMD_ASTORE_2: case CMD_ASTORE_3: v = stack_pop (TYPE_ADDRESS); MOVE_N_DROP (TYPE_ADDRESS, v, local_get (opcode - CMD_ASTORE_0, TYPE_ADDRESS) ); break; case CMD_IINC: if (!iswide) { v1 = local_get (code_get_u1 (p+1), TYPE_INT); IINC (code_get_s1 (p+2), v1 ); DROP (v1); } else { v1 = local_get (code_get_u2 (p+1), TYPE_INT); IINC (code_get_s2 (p+3), v1 ); DROP (v1); iswide = false; nextp = p+5; } break; /*** Wider index for Loading, Storing and Incrementing ***/ case CMD_WIDE: iswide=true; nextp = p+1; break; /******************** Managing Arrays **************************/ case CMD_NEWARRAY: v1 = stack_pop (TYPE_INT); BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) ); stack_makesaved (); v = stack_push (TYPE_ADDRESS); switch ( code_get_s1 (p+1) ) { case 4: BUILTIN1 ((functionptr) builtin_newarray_boolean, v1, v); break; case 5: BUILTIN1 ((functionptr) builtin_newarray_char, v1, v); break; case 6: BUILTIN1 ((functionptr) builtin_newarray_float, v1, v); break; case 7: BUILTIN1 ((functionptr) builtin_newarray_double, v1, v); break; case 8: BUILTIN1 ((functionptr) builtin_newarray_byte, v1, v); break; case 9: BUILTIN1 ((functionptr) builtin_newarray_short, v1, v); break; case 10: BUILTIN1 ((functionptr) builtin_newarray_int, v1, v); break; case 11: BUILTIN1 ((functionptr) builtin_newarray_long, v1, v); break; default: panic ("Invalid array-type to create"); } BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) ); break; case CMD_ANEWARRAY: poolindex = code_get_u2(p+1); if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) { /* anewarray mit Array-Typ! */ constant_arraydescriptor *desc = class_getconstant (class, poolindex, CONSTANT_Arraydescriptor); v1 = stack_pop (TYPE_INT); BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) ); v2 = var_create (TYPE_ADDRESS); LOADCONST_A (desc, v2); stack_makesaved (); v = stack_push (TYPE_ADDRESS); BUILTIN2 ((functionptr) builtin_newarray_array, v1,v2, v); BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) ); } else { classinfo *c = class_getconstant (class, poolindex, CONSTANT_Class); v1 = stack_pop (TYPE_INT); BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) ); v2 = var_create (TYPE_ADDRESS); LOADCONST_A (c, v2); stack_makesaved (); v = stack_push (TYPE_ADDRESS); BUILTIN2 ((functionptr) builtin_anewarray, v1,v2, v); BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) ); } break; case CMD_MULTIANEWARRAY: { constant_arraydescriptor *desc = class_getconstant (class, code_get_u2(p+1), CONSTANT_Arraydescriptor); int i, n = code_get_u1 (p+3); varid dims = var_create (TYPE_ADDRESS); /* array for dimensions */ varid dimsdim = var_create (TYPE_INT); /* groesse des arrays */ stack_makesaved (); LOADCONST_I (n, dimsdim); BUILTIN1 ((functionptr) builtin_newarray_int, dimsdim, dims); BRA (CMD_IFNULL, dims,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) ); for (i=0; isubroutine; if (!sub) { sub = subroutine_new(); target->subroutine = sub; } subroutine_set (sub); block_reach (target); subroutine_set (b->subroutine); BRA (CMD_JSR, NOVAR,NOVAR, stack_pop(TYPE_ADDRESS), target ); while (! stack_isempty() ) { v = stack_popany ( stack_topslots() ); DROP (v); } if (sub->returnfinished) { stackinfo *s = sub->returnstack; stack_restore (s); while (s) { ACTIVATE (s->var); s = s->prev; } block_reach ( block_find(nextp) ); } else { basicblock *n = block_find(nextp); n -> subroutine = b->subroutine; chain_addlast (sub->callers, n ); } } goto cleanup; case CMD_RET: if (!iswide) { v = local_get (code_get_u1 (p+1), TYPE_ADDRESS); } else { v = local_get (code_get_u2 (p+1), TYPE_ADDRESS); nextp = p+3; iswide = false; } { subroutineinfo *sub; basicblock *bb; sub = b->subroutine; if (!sub) panic ("RET outside of subroutine"); if (sub->returnfinished) panic ("Multiple RET in a subroutine"); sub->returnfinished = true; sub->returnstack = stack_get() ; while ( (bb = chain_first(sub->callers)) ) { chain_remove (sub->callers); subroutine_set (bb->subroutine); block_reach ( bb ); subroutine_set (sub); } BRA (CMD_RET, v,NOVAR, NOVAR, NULL); } goto cleanup; /*************** Function Return **************/ case CMD_IRETURN: addreturnhandling(); v = stack_pop (TYPE_INT); ve = var_create (TYPE_ADDRESS); LOADCONST_A (NULL, ve); BRA_N_DROP (opcode, v, ve, NOVAR, NULL); #ifdef STATISTICS count_pcmd_return++; #endif goto cleanup; case CMD_LRETURN: addreturnhandling(); v = stack_pop (TYPE_LONG); var_proposereg (v, reg_parlistresult(TYPE_LONG) ); ve = var_create (TYPE_ADDRESS); LOADCONST_A (NULL, ve); var_proposereg (ve, reg_parlistexception() ); BRA_N_DROP (opcode, v, ve, NOVAR, NULL); #ifdef STATISTICS count_pcmd_return++; #endif goto cleanup; case CMD_FRETURN: addreturnhandling(); v = stack_pop (TYPE_FLOAT); var_proposereg (v, reg_parlistresult(TYPE_FLOAT) ); ve = var_create (TYPE_ADDRESS); LOADCONST_A (NULL, ve); var_proposereg (ve, reg_parlistexception() ); BRA_N_DROP (opcode, v, ve, NOVAR, NULL); #ifdef STATISTICS count_pcmd_return++; #endif goto cleanup; case CMD_DRETURN: addreturnhandling(); v = stack_pop (TYPE_DOUBLE); var_proposereg (v, reg_parlistresult(TYPE_DOUBLE) ); ve = var_create (TYPE_ADDRESS); LOADCONST_A (NULL, ve); var_proposereg (ve, reg_parlistexception() ); BRA_N_DROP (opcode, v, ve, NOVAR, NULL); #ifdef STATISTICS count_pcmd_return++; #endif goto cleanup; case CMD_ARETURN: addreturnhandling(); v = stack_pop (TYPE_ADDRESS); var_proposereg (v, reg_parlistresult(TYPE_ADDRESS) ); ve = var_create (TYPE_ADDRESS); LOADCONST_A (NULL, ve); var_proposereg (ve, reg_parlistexception() ); BRA_N_DROP (opcode, v, ve, NOVAR, NULL); goto cleanup; #ifdef STATISTICS count_pcmd_return++; #endif case CMD_RETURN: addreturnhandling(); ve = var_create (TYPE_ADDRESS); LOADCONST_A (NULL, ve); var_proposereg (ve, reg_parlistexception() ); BRA_N_DROP (opcode, NOVAR,ve, NOVAR, NULL); #ifdef STATISTICS count_pcmd_return++; #endif goto cleanup; case CMD_BREAKPOINT: break; /**************** Table Jumping *****************/ case CMD_LOOKUPSWITCH: { u4 p2 = ALIGN((p+1), 4); basicblock *defaulttarget; u4 num, i; defaulttarget = block_find (p + code_get_s4 (p2) ); num = code_get_s4 (p2+4); v = stack_pop (TYPE_INT); for (i=0; iclass, fr->name, fr->descriptor); switch (opcode) { case CMD_PUTSTATIC: compiler_addinitclass (fr->class); v1 = var_create (TYPE_ADDRESS); v = stack_pop (fi->type); LOADCONST_A (&(fi->value), v1); MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, 0); DROP (v); DROP (v1); break; case CMD_GETSTATIC: compiler_addinitclass (fr->class); v1 = var_create (TYPE_ADDRESS); v = stack_push (fi->type); LOADCONST_A (&(fi->value), v1); MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, 0); DROP (v1); break; case CMD_PUTFIELD: v = stack_pop (fi->type); v1 = stack_pop (TYPE_ADDRESS); if (checknull) { #ifdef STATISTICS count_check_null++; #endif BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) ); } MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, fi->offset); DROP (v); DROP (v1); break; case CMD_GETFIELD: v1 = stack_pop (TYPE_ADDRESS); v = stack_push (fi->type); if (checknull) { #ifdef STATISTICS count_check_null++; #endif BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) ); } MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, fi->offset); DROP (v1); break; } } break; /*** Method invocation ***/ case CMD_INVOKEVIRTUAL: case CMD_INVOKESPECIAL: case CMD_INVOKESTATIC: case CMD_INVOKEINTERFACE: count_calls ++; { constant_FMIref *mr; methodinfo *mi; u4 i; s4 paramnum; u1 *paramtypes; s4 returntype; varid *params; bool stat = (opcode == CMD_INVOKESTATIC); if (opcode==CMD_INVOKEINTERFACE) { poolindex = code_get_u2 (p+1); mr = class_getconstant (class, poolindex, CONSTANT_InterfaceMethodref); } else { poolindex = code_get_u2 (p+1); mr = class_getconstant (class, poolindex, CONSTANT_Methodref); } mi = class_findmethod (mr->class, mr->name, mr->descriptor); if ( ((mi->flags & ACC_STATIC) != 0) != stat) panic ("Static/Nonstatic mismatch on method call"); descriptor2types (mi->descriptor, stat, ¶mnum, ¶mtypes, &returntype); mi->paramcount = paramnum; params = DMNEW (varid, paramnum); for (i=0; itype_s2 != TYPE_VOID) v2 = stack_pop(s->type_s2); v1 = stack_pop(s->type_s1); if (s->supported) { v = stack_push (s->type_d); if (v2) { OP2 (opcode, v1,v2, v); DROP (v1); DROP (v2); } else { OP1 (opcode, v1, v); DROP (v1); } } else { stack_makesaved (); v = stack_push (s->type_d); if (v2) { BUILTIN2 (s->builtin, v1,v2, v); } else { BUILTIN1 (s->builtin, v1, v); } } } /*************** invalid Opcode ***************/ else { sprintf (logtext, "Invalid opcode %d at position %ld", opcode, (long int) p); error (); } } break; } /* end switch */ p = nextp; if ( block_isany (p) ) { block_reach ( block_find (p) ); goto cleanup; } } /* end for */ cleanup: pcmd_untieall(); }