From b0dba1116d03fbe97d75e8ccfb933a51caf05601 Mon Sep 17 00:00:00 2001 From: twisti Date: Mon, 18 Dec 2006 18:21:37 +0000 Subject: [PATCH] * src/vm/class.c (vm/suck.h): Added. (class_load_attribute_sourcefile): New function. (class_load_attribute_enclosingmethod): Likewise. (class_load_attributes): Likewise. * src/vm/loader.c [ENABLE_JAVASE] (vm/annotation.h, vm/stackmap.h): Added. (skipattributebody): Renamed to loader_skip_attribute_body, made non-static. (skipattributes): Removed. (loader_load_attribute_signature): New function. (load_field): Use loader_load_attribute_signature. (load_method): Renamed to loader_load_method, call stackmap_load_attribute_stackmaptable and loader_load_attribute_signature. (load_attributes): Removed. (load_class_from_classbuffer): Renamed load_method to loader_load_method and load_attributes to class_load_attributes. * src/vm/loader.h (loader_skip_attribute_body): Added. [ENABLE_JAVASE] (loader_load_attribute_signature): Likewise. * src/vm/method.h [ENABLE_JAVASE] (vm/stackmap.h): Added. (methodinfo) [ENABLE_JAVASE]: Added signature and stack_map. * src/vm/statistics.c (size_stack_map): Added. (print_stats): Print stack_map size. * src/vm/statistics.h (size_stack_map): Likewise. * src/vm/global.h (JAVA_VERSION): Changed to "1.5.0". (CLASS_VERSION): Changed to "50.0". (MAJOR_VERSION): Changed to 50. * src/vm/utf8.c [ENABLE_JAVASE] (utf_EnclosingMethod) (utf_RuntimeVisibleAnnotations, utf_StackMapTable): Added. (utf8_init) [ENABLE_JAVASE]: Init utf_EnclosingMethod, utf_RuntimeVisibleAnnotations and utf_StackMapTable. * src/vm/utf8.h [ENABLE_JAVASE] (utf_EnclosingMethod) (utf_RuntimeVisibleAnnotations, utf_StackMapTable): Added. * src/vm/properties.c (properties_init): Changed java.specification.version to 1.5. * src/vm/Makefile.am [ENABLE_JAVASE] (ANNOTATION_OBJ): Renamed to ANNOTATION_SOURCES. [ENABLE_JAVASE] (STACKMAP_SOURCES): Added. [ENABLE_STATISTICS] (STATISTICS_OBJ): Renamed to STATISTICS_SOURCES. (libvmcore_la_SOURCES): Added STACKMAP_SOURCES. * src/vm/stackmap.c: New file. * src/vm/stackmap.h: Likewise. --- src/vm/Makefile.am | 15 +- src/vm/class.c | 267 +++++++++++++++++++++- src/vm/global.h | 11 +- src/vm/loader.c | 415 ++++++++++++++++------------------ src/vm/loader.h | 8 +- src/vm/method.h | 13 +- src/vm/properties.c | 4 +- src/vm/stackmap.c | 530 ++++++++++++++++++++++++++++++++++++++++++++ src/vm/stackmap.h | 237 ++++++++++++++++++++ src/vm/statistics.c | 7 +- src/vm/statistics.h | 4 +- src/vm/utf8.c | 19 +- src/vm/utf8.h | 11 +- 13 files changed, 1281 insertions(+), 260 deletions(-) create mode 100644 src/vm/stackmap.c create mode 100644 src/vm/stackmap.h diff --git a/src/vm/Makefile.am b/src/vm/Makefile.am index 09cbf4e35..9c6da3a59 100644 --- a/src/vm/Makefile.am +++ b/src/vm/Makefile.am @@ -26,7 +26,7 @@ ## ## Authors: Christian Thalinger ## -## $Id: Makefile.am 6084 2006-11-29 17:04:14Z twisti $ +## $Id: Makefile.am 6216 2006-12-18 18:21:37Z twisti $ ## Process this file with automake to produce Makefile.in @@ -37,13 +37,17 @@ LIBS = SUBDIRS = jit if ENABLE_JAVASE -ANNOTATION_OBJ = \ +ANNOTATION_SOURCES = \ annotation.c \ annotation.h + +STACKMAP_SOURCES = \ + stackmap.c \ + stackmap.h endif if ENABLE_STATISTICS -STATISTICS_OBJ = \ +STATISTICS_SOURCES = \ statistics.c \ statistics.h endif @@ -76,7 +80,7 @@ noinst_LTLIBRARIES = \ libvmcore_la_SOURCES = \ access.c \ access.h \ - $(ANNOTATION_OBJ) \ + $(ANNOTATION_SOURCES) \ builtin.c \ builtin.h \ builtintable.inc \ @@ -110,9 +114,10 @@ libvmcore_la_SOURCES = \ resolve.h \ $(RT_TIMING_OBJ) \ rt-timing.h \ - $(STATISTICS_OBJ) \ + $(STATISTICS_SOURCES) \ signal.c \ signallocal.h \ + $(STACKMAP_SOURCES) \ string.c \ stringlocal.h \ suck.c \ diff --git a/src/vm/class.c b/src/vm/class.c index 50b6fd24f..62c541fd8 100644 --- a/src/vm/class.c +++ b/src/vm/class.c @@ -25,13 +25,12 @@ Contact: cacao@cacaojvm.org Authors: Reinhard Grafl - - Changes: Mark Probst + Mark Probst Andreas Krall Christian Thalinger - Edwin Steiner + Edwin Steiner - $Id: class.c 6033 2006-11-21 16:56:56Z michi $ + $Id: class.c 6216 2006-12-18 18:21:37Z twisti $ */ @@ -60,6 +59,7 @@ #include "vm/resolve.h" #include "vm/statistics.h" #include "vm/stringlocal.h" +#include "vm/suck.h" #include "vm/utf8.h" @@ -263,6 +263,254 @@ void class_postset_header_vftbl(void) } +/* class_load_attribute_sourcefile ********************************************* + + SourceFile_attribute { + u2 attribute_name_index; + u4 attribute_length; + u2 sourcefile_index; + } + +*******************************************************************************/ + +static bool class_load_attribute_sourcefile(classbuffer *cb) +{ + classinfo *c; + u4 attribute_length; + u2 sourcefile_index; + utf *sourcefile; + + /* get classinfo */ + + c = cb->class; + + /* check buffer size */ + + if (!suck_check_classbuffer_size(cb, 4 + 2)) + return false; + + /* check attribute length */ + + attribute_length = suck_u4(cb); + + if (attribute_length != 2) { + exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute"); + return false; + } + + /* there can be no more than one SourceFile attribute */ + + if (c->sourcefile != NULL) { + exceptions_throw_classformaterror(c, "Multiple SourceFile attributes"); + return false; + } + + /* get sourcefile */ + + sourcefile_index = suck_u2(cb); + sourcefile = class_getconstant(c, sourcefile_index, CONSTANT_Utf8); + + if (sourcefile == NULL) + return false; + + /* store sourcefile */ + + c->sourcefile = sourcefile; + + return true; +} + + +/* class_load_attribute_enclosingmethod **************************************** + + EnclosingMethod_attribute { + u2 attribute_name_index; + u4 attribute_length; + u2 class_index; + u2 method_index; + } + +*******************************************************************************/ + +static bool class_load_attribute_enclosingmethod(classbuffer *cb) +{ + classinfo *c; + u4 attribute_length; + u2 class_index; + u2 method_index; + classref_or_classinfo cr; + constant_nameandtype *cn; + + /* get classinfo */ + + c = cb->class; + + /* check buffer size */ + + if (!suck_check_classbuffer_size(cb, 4 + 2 + 2)) + return false; + + /* check attribute length */ + + attribute_length = suck_u4(cb); + + if (attribute_length != 4) { + exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute"); + return false; + } + + /* there can be no more than one EnclosingMethod attribute */ + + if (c->enclosingmethod != NULL) { + exceptions_throw_classformaterror(c, "Multiple EnclosingMethod attributes"); + return false; + } + + /* get class index */ + + class_index = suck_u2(cb); + cr.ref = innerclass_getconstant(c, class_index, CONSTANT_Class); + + /* get method index */ + + method_index = suck_u2(cb); + cn = innerclass_getconstant(c, method_index, CONSTANT_NameAndType); + + /* store info in classinfo */ + + c->enclosingclass.any = cr.any; + c->enclosingmethod = cn; + + return true; +} + + +/* class_load_attributes ******************************************************* + + Read attributes from ClassFile. + + attribute_info { + u2 attribute_name_index; + u4 attribute_length; + u1 info[attribute_length]; + } + + InnerClasses_attribute { + u2 attribute_name_index; + u4 attribute_length; + } + +*******************************************************************************/ + +bool class_load_attributes(classbuffer *cb) +{ + classinfo *c; + u4 i, j; + u2 attributes_count; + u2 attribute_name_index; + utf *attribute_name; + + c = cb->class; + + /* get attributes count */ + + if (!suck_check_classbuffer_size(cb, 2)) + return false; + + attributes_count = suck_u2(cb); + + for (i = 0; i < attributes_count; i++) { + /* get attribute name */ + + if (!suck_check_classbuffer_size(cb, 2)) + return false; + + attribute_name_index = suck_u2(cb); + attribute_name = + class_getconstant(c, attribute_name_index, CONSTANT_Utf8); + + if (attribute_name == NULL) + return false; + + if (attribute_name == utf_InnerClasses) { + /* InnerClasses */ + + if (c->innerclass != NULL) { + exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes"); + return false; + } + + if (!suck_check_classbuffer_size(cb, 4 + 2)) + return false; + + /* skip attribute length */ + suck_u4(cb); + + /* number of records */ + c->innerclasscount = suck_u2(cb); + + if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount)) + return false; + + /* allocate memory for innerclass structure */ + c->innerclass = MNEW(innerclassinfo, c->innerclasscount); + + for (j = 0; j < c->innerclasscount; j++) { + /* The innerclass structure contains a class with an encoded + name, its defining scope, its simple name and a bitmask of + the access flags. If an inner class is not a member, its + outer_class is NULL, if a class is anonymous, its name is + NULL. */ + + innerclassinfo *info = c->innerclass + j; + + info->inner_class.ref = + innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); + info->outer_class.ref = + innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); + info->name = + innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8); + info->flags = suck_u2(cb); + } + } + else if (attribute_name == utf_SourceFile) { + /* SourceFile */ + + if (!class_load_attribute_sourcefile(cb)) + return false; + } +#if defined(ENABLE_JAVASE) + else if (attribute_name == utf_EnclosingMethod) { + /* EnclosingMethod */ + + if (!class_load_attribute_enclosingmethod(cb)) + return false; + } + else if (attribute_name == utf_Signature) { + /* Signature */ + + if (!loader_load_attribute_signature(cb, &(c->signature))) + return false; + } + else if (attribute_name == utf_RuntimeVisibleAnnotations) { + /* RuntimeVisibleAnnotations */ + + if (!annotation_load_attribute_runtimevisibleannotations(cb)) + return false; + } +#endif + else { + /* unknown attribute */ + + if (!loader_skip_attribute_body(cb)) + return false; + } + } + + return true; +} + + /* class_freepool ************************************************************** Frees all resources used by this classes Constant Pool. @@ -328,8 +576,8 @@ voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype) /* check index and type of constantpool entry */ /* (pos == 0 is caught by type comparison) */ - if (pos >= c->cpcount || c->cptags[pos] != ctype) { - *exceptionptr = new_classformaterror(c, "Illegal constant pool index"); + if ((pos >= c->cpcount) || (c->cptags[pos] != ctype)) { + exceptions_throw_classformaterror(c, "Illegal constant pool index"); return NULL; } @@ -346,16 +594,19 @@ voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype) voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype) { /* invalid position in constantpool */ + if (pos >= c->cpcount) { - *exceptionptr = new_classformaterror(c, "Illegal constant pool index"); + exceptions_throw_classformaterror(c, "Illegal constant pool index"); return NULL; } /* constantpool entry of type 0 */ - if (!c->cptags[pos]) + + if (c->cptags[pos] == 0) return NULL; /* check type of constantpool entry */ + if (c->cptags[pos] != ctype) { *exceptionptr = new_classformaterror(c, "Illegal constant pool index"); return NULL; diff --git a/src/vm/global.h b/src/vm/global.h index 1ab05e467..5943147fa 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -26,14 +26,13 @@ Authors: Reinhard Grafl Andreas Krall - - Changes: Mark Probst + Mark Probst Philipp Tomsich Edwin Steiner Joseph Wenninger Christian Thalinger - $Id: global.h 6030 2006-11-20 14:18:12Z michi $ + $Id: global.h 6216 2006-12-18 18:21:37Z twisti $ */ @@ -146,14 +145,14 @@ typedef struct java_objectarray java_objectarray; /* some Java related defines **************************************************/ -#define JAVA_VERSION "1.4.2" /* this version is supported by CACAO */ -#define CLASS_VERSION "49.0" +#define JAVA_VERSION "1.5.0" /* this version is supported by CACAO */ +#define CLASS_VERSION "50.0" /* Java class file constants **************************************************/ #define MAGIC 0xCAFEBABE -#define MAJOR_VERSION 49 +#define MAJOR_VERSION 50 #define MINOR_VERSION 0 diff --git a/src/vm/loader.c b/src/vm/loader.c index 9386ac59d..5433718a1 100644 --- a/src/vm/loader.c +++ b/src/vm/loader.c @@ -31,7 +31,7 @@ Edwin Steiner Christian Thalinger - $Id: loader.c 6033 2006-11-21 16:56:56Z michi $ + $Id: loader.c 6216 2006-12-18 18:21:37Z twisti $ */ @@ -53,6 +53,12 @@ #endif #include "toolbox/logging.h" + +#if defined(ENABLE_JAVASE) +# include "vm/annotation.h" +# include "vm/stackmap.h" +#endif + #include "vm/builtin.h" #include "vm/classcache.h" #include "vm/exceptions.h" @@ -277,54 +283,31 @@ void loader_load_all_classes(void) } -/* skipattributebody *********************************************************** +/* loader_skip_attribute_body ************************************************** - Skips an attribute after the 16 bit reference to attribute_name has - already been read. + Skips an attribute the attribute_name_index has already been read. + attribute_info { + u2 attribute_name_index; + u4 attribute_length; + u1 info[attribute_length]; + } + *******************************************************************************/ -static bool skipattributebody(classbuffer *cb) +bool loader_skip_attribute_body(classbuffer *cb) { - u4 len; + u4 attribute_length; if (!suck_check_classbuffer_size(cb, 4)) return false; - len = suck_u4(cb); + attribute_length = suck_u4(cb); - if (!suck_check_classbuffer_size(cb, len)) + if (!suck_check_classbuffer_size(cb, attribute_length)) return false; - suck_skip_nbytes(cb, len); - - return true; -} - - -/************************* Function: skipattributes **************************** - - skips num attribute structures - -*******************************************************************************/ - -static bool skipattributes(classbuffer *cb, u4 num) -{ - u4 i; - u4 len; - - for (i = 0; i < num; i++) { - if (!suck_check_classbuffer_size(cb, 2 + 4)) - return false; - - suck_u2(cb); - len = suck_u4(cb); - - if (!suck_check_classbuffer_size(cb, len)) - return false; - - suck_skip_nbytes(cb, len); - } + suck_skip_nbytes(cb, attribute_length); return true; } @@ -779,6 +762,58 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool) } +/* loader_load_attribute_signature ********************************************* + + Signature_attribute { + u2 attribute_name_index; + u4 atrribute_length; + u2 signature_index; + } + +*******************************************************************************/ + +#if defined(ENABLE_JAVASE) +bool loader_load_attribute_signature(classbuffer *cb, utf **signature) +{ + classinfo *c; + u4 attribute_length; + u2 signature_index; + + /* get classinfo */ + + c = cb->class; + + /* check remaining bytecode */ + + if (!suck_check_classbuffer_size(cb, 4 + 2)) + return false; + + /* check attribute length */ + + attribute_length = suck_u4(cb); + + if (attribute_length != 2) { + exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute"); + return false; + } + + if (*signature != NULL) { + exceptions_throw_classformaterror(c, "Multiple Signature attributes"); + return false; + } + + /* get signature */ + + signature_index = suck_u2(cb); + + if (!(*signature = class_getconstant(c, signature_index, CONSTANT_Utf8))) + return false; + + return true; +} +#endif /* defined(ENABLE_JAVASE) */ + + /* load_field ****************************************************************** Load everything about a class field from the class file and fill a @@ -980,28 +1015,18 @@ static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool) log_text("Invalid Constant - Type"); } } +#if defined(ENABLE_JAVASE) else if (u == utf_Signature) { - if (!suck_check_classbuffer_size(cb, 4 + 2)) - return false; - - /* check attribute length */ + /* Signature */ - if (suck_u4(cb) != 2) { - exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute"); - return false; - } - - if (f->signature != NULL) { - exceptions_throw_classformaterror(c, "Multiple Signature attributes"); - return false; - } - - if (!(f->signature = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + if (!loader_load_attribute_signature(cb, &(f->signature))) return false; } +#endif else { /* unknown attribute */ - if (!skipattributebody(cb)) + + if (!loader_skip_attribute_body(cb)) return false; } } @@ -1012,23 +1037,56 @@ static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool) } -/* load_method ***************************************************************** +/* loader_load_method ********************************************************** Loads a method from the class file and fills an existing 'methodinfo' structure. For native methods, the function pointer field is set to the real function pointer, for JavaVM methods a pointer to the compiler is used preliminarily. - + + method_info { + u2 access_flags; + u2 name_index; + u2 descriptor_index; + u2 attributes_count; + attribute_info attributes[attribute_count]; + } + + attribute_info { + u2 attribute_name_index; + u4 attribute_length; + u1 info[attribute_length]; + } + + LineNumberTable_attribute { + u2 attribute_name_index; + u4 attribute_length; + u2 line_number_table_length; + { + u2 start_pc; + u2 line_number; + } line_number_table[line_number_table_length]; + } + *******************************************************************************/ -static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool) +static bool loader_load_method(classbuffer *cb, methodinfo *m, + descriptor_pool *descpool) { classinfo *c; int argcount; - s4 i, j; - u4 attrnum; - u4 codeattrnum; - utf *u; + s4 i, j, k, l; + utf *u; + u2 name_index; + u2 descriptor_index; + u2 attributes_count; + u2 attribute_name_index; + utf *attribute_name; + u2 code_attributes_count; + u2 code_attribute_name_index; + utf *code_attribute_name; + + /* get classinfo */ c = cb->class; @@ -1043,19 +1101,29 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo /* all fields of m have been zeroed in load_class_from_classbuffer */ - m->class = c; + m->class = c; if (!suck_check_classbuffer_size(cb, 2 + 2 + 2)) return false; + /* access flags */ + m->flags = suck_u2(cb); - if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + /* name */ + + name_index = suck_u2(cb); + + if (!(u = class_getconstant(c, name_index, CONSTANT_Utf8))) return false; m->name = u; - if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + /* descriptor */ + + descriptor_index = suck_u2(cb); + + if (!(u = class_getconstant(c, descriptor_index, CONSTANT_Utf8))) return false; m->descriptor = u; @@ -1140,18 +1208,24 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo if (!suck_check_classbuffer_size(cb, 2)) return false; - - attrnum = suck_u2(cb); - for (i = 0; i < attrnum; i++) { - utf *aname; + /* attributes count */ + + attributes_count = suck_u2(cb); + + for (i = 0; i < attributes_count; i++) { if (!suck_check_classbuffer_size(cb, 2)) return false; - if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + /* attribute name index */ + + attribute_name_index = suck_u2(cb); + + if (!(attribute_name = class_getconstant(c, attribute_name_index, CONSTANT_Utf8))) return false; - if (aname == utf_Code) { + if (attribute_name == utf_Code) { + /* Code */ if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) { exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods"); return false; @@ -1233,24 +1307,34 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo if (!suck_check_classbuffer_size(cb, 2)) return false; - codeattrnum = suck_u2(cb); + /* code attributes count */ - for (; codeattrnum > 0; codeattrnum--) { - utf *caname; + code_attributes_count = suck_u2(cb); + for (k = 0; k < code_attributes_count; k++) { if (!suck_check_classbuffer_size(cb, 2)) return false; - if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + /* code attribute name index */ + + code_attribute_name_index = suck_u2(cb); + + if (!(code_attribute_name = class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8))) return false; - if (caname == utf_LineNumberTable) { - u2 lncid; + /* check which code attribute */ + if (code_attribute_name == utf_LineNumberTable) { + /* LineNumberTable */ if (!suck_check_classbuffer_size(cb, 4 + 2)) return false; - suck_u4(cb); + /* attribute length */ + + (void) suck_u4(cb); + + /* line number table length */ + m->linenumbercount = suck_u2(cb); if (!suck_check_classbuffer_size(cb, @@ -1259,27 +1343,29 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo m->linenumbers = MNEW(lineinfo, m->linenumbercount); - for (lncid = 0; lncid < m->linenumbercount; lncid++) { - m->linenumbers[lncid].start_pc = suck_u2(cb); - m->linenumbers[lncid].line_number = suck_u2(cb); + for (l = 0; l < m->linenumbercount; l++) { + m->linenumbers[l].start_pc = suck_u2(cb); + m->linenumbers[l].line_number = suck_u2(cb); } - codeattrnum--; + } + else if (code_attribute_name == utf_StackMapTable) { + /* StackTableMap */ - if (!skipattributes(cb, codeattrnum)) + if (!stackmap_load_attribute_stackmaptable(cb, m)) return false; - - break; + } + else { + /* unknown code attribute */ - } else { - if (!skipattributebody(cb)) + if (!loader_skip_attribute_body(cb)) return false; } } } - else if (aname == utf_Exceptions) { - s4 j; + else if (attribute_name == utf_Exceptions) { + /* Exceptions */ - if (m->thrownexceptions) { + if (m->thrownexceptions != NULL) { exceptions_throw_classformaterror(c, "Multiple Exceptions attributes"); return false; } @@ -1287,7 +1373,10 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo if (!suck_check_classbuffer_size(cb, 4 + 2)) return false; - suck_u4(cb); /* length */ + /* attribute length */ + + (void) suck_u4(cb); + m->thrownexceptionscount = suck_u2(cb); if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount)) @@ -1302,32 +1391,23 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo return false; } } - else if (aname == utf_Signature) { - if (!suck_check_classbuffer_size(cb, 4 + 2)) - return false; - - /* check attribute length */ - - if (suck_u4(cb) != 2) { - exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute"); - return false; - } +#if defined(ENABLE_JAVASE) + else if (attribute_name == utf_Signature) { + /* Signature */ - if (m->signature != NULL) { - exceptions_throw_classformaterror(c, "Multiple Signature attributes"); - return false; - } - - if (!(m->signature = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) + if (!loader_load_attribute_signature(cb, &(m->signature))) return false; } +#endif else { - if (!skipattributebody(cb)) + /* unknown attribute */ + + if (!loader_skip_attribute_body(cb)) return false; } } - if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) { + if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) { exceptions_throw_classformaterror(c, "Missing Code attribute"); return false; } @@ -1338,120 +1418,6 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo } -/* load_attribute ************************************************************** - - Read attributes from classfile. - -*******************************************************************************/ - -static bool load_attributes(classbuffer *cb, u4 num) -{ - classinfo *c; - utf *aname; - u4 i, j; - - c = cb->class; - - for (i = 0; i < num; i++) { - /* retrieve attribute name */ - - if (!suck_check_classbuffer_size(cb, 2)) - return false; - - if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) - return false; - - if (aname == utf_InnerClasses) { - /* InnerClasses attribute */ - - if (c->innerclass != NULL) { - exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes"); - return false; - } - - if (!suck_check_classbuffer_size(cb, 4 + 2)) - return false; - - /* skip attribute length */ - suck_u4(cb); - - /* number of records */ - c->innerclasscount = suck_u2(cb); - - if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount)) - return false; - - /* allocate memory for innerclass structure */ - c->innerclass = MNEW(innerclassinfo, c->innerclasscount); - - for (j = 0; j < c->innerclasscount; j++) { - /* The innerclass structure contains a class with an encoded - name, its defining scope, its simple name and a bitmask of - the access flags. If an inner class is not a member, its - outer_class is NULL, if a class is anonymous, its name is - NULL. */ - - innerclassinfo *info = c->innerclass + j; - - info->inner_class.ref = - innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); - info->outer_class.ref = - innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class); - info->name = - innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8); - info->flags = suck_u2(cb); - } - } - else if (aname == utf_SourceFile) { - /* SourceFile attribute */ - - if (!suck_check_classbuffer_size(cb, 4 + 2)) - return false; - - if (suck_u4(cb) != 2) { - exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute"); - return false; - } - - if (c->sourcefile != NULL) { - exceptions_throw_classformaterror(c, "Multiple SourceFile attributes"); - return false; - } - - if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) - return false; - } - else if (aname == utf_Signature) { - /* Signature attribute */ - - if (!suck_check_classbuffer_size(cb, 4 + 2)) - return false; - - if (suck_u4(cb) != 2) { - exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute"); - return false; - } - - if (c->signature != NULL) { - exceptions_throw_classformaterror(c, "Multiple Signature attributes"); - return false; - } - - if (!(c->signature = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) - return false; - } - else { - /* unknown attribute */ - - if (!skipattributebody(cb)) - return false; - } - } - - return true; -} - - /* load_class_from_sysloader *************************************************** Load the class with the given name using the system class loader @@ -2104,7 +2070,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) MZERO(c->methods, methodinfo, c->methodscount); for (i = 0; i < c->methodscount; i++) { - if (!load_method(cb, &(c->methods[i]),descpool)) + if (!loader_load_method(cb, &(c->methods[i]), descpool)) goto return_exception; } @@ -2349,10 +2315,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) /* load attribute structures */ - if (!suck_check_classbuffer_size(cb, 2)) - goto return_exception; - - if (!load_attributes(cb, suck_u2(cb))) + if (!class_load_attributes(cb)) goto return_exception; /* Pre Java 1.5 version don't check this. This implementation is like diff --git a/src/vm/loader.h b/src/vm/loader.h index 07034a8fa..ee2db94ca 100644 --- a/src/vm/loader.h +++ b/src/vm/loader.h @@ -28,7 +28,7 @@ Changes: Christian Thalinger - $Id: loader.h 4959 2006-05-26 12:09:29Z edwin $ + $Id: loader.h 6216 2006-12-18 18:21:37Z twisti $ */ @@ -122,6 +122,12 @@ bool loader_init(void); void loader_load_all_classes(void); +bool loader_skip_attribute_body(classbuffer *cb); + +#if defined(ENABLE_JAVASE) +bool loader_load_attribute_signature(classbuffer *cb, utf **signature); +#endif + /* free resources */ void loader_close(void); diff --git a/src/vm/method.h b/src/vm/method.h index ec57352af..59f506589 100644 --- a/src/vm/method.h +++ b/src/vm/method.h @@ -28,7 +28,7 @@ Christian Thalinger Edwin Steiner - $Id: method.h 6012 2006-11-16 19:45:15Z twisti $ + $Id: method.h 6216 2006-12-18 18:21:37Z twisti $ */ @@ -50,6 +50,11 @@ typedef struct method_worklist method_worklist; #include "vm/global.h" #include "vm/linker.h" #include "vm/references.h" + +#if defined(ENABLE_JAVASE) +# include "vm/stackmap.h" +#endif + #include "vm/utf8.h" #include "vm/jit/code.h" #include "vm/jit/jit.h" @@ -62,7 +67,11 @@ struct methodinfo { /* method structure */ s4 flags; /* ACC flags */ utf *name; /* name of method */ utf *descriptor; /* JavaVM descriptor string of method */ - utf *signature; /* Signature attribute string */ +#if defined(ENABLE_JAVASE) + utf *signature; /* Signature attribute */ + stack_map_t *stack_map; /* StackMapTable attribute */ +#endif + methoddesc *parseddesc; /* parsed descriptor */ classinfo *class; /* class, the method belongs to */ diff --git a/src/vm/properties.c b/src/vm/properties.c index 37618e3f4..08940ab16 100644 --- a/src/vm/properties.c +++ b/src/vm/properties.c @@ -26,7 +26,7 @@ Authors: Christian Thalinger - $Id: properties.c 6015 2006-11-18 22:16:32Z twisti $ + $Id: properties.c 6216 2006-12-18 18:21:37Z twisti $ */ @@ -139,7 +139,7 @@ bool properties_init(void) properties_add("java.vm.version", VERSION); properties_add("java.vm.vendor", "CACAO Team"); properties_add("java.vm.name", "CACAO"); - properties_add("java.specification.version", "1.4"); + properties_add("java.specification.version", "1.5"); properties_add("java.specification.vendor", "Sun Microsystems Inc."); properties_add("java.specification.name", "Java Platform API Specification"); properties_add("java.class.version", CLASS_VERSION); diff --git a/src/vm/stackmap.c b/src/vm/stackmap.c new file mode 100644 index 000000000..93c1b70ab --- /dev/null +++ b/src/vm/stackmap.c @@ -0,0 +1,530 @@ +/* src/vm/stackmap.c - class attribute StackMapTable + + Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates, + R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, + C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, + Institut f. Computersprachen - TU Wien + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Contact: cacao@cacaojvm.org + + Authors: Christian Thalinger + + $Id: utf8.h 5920 2006-11-05 21:23:09Z twisti $ + +*/ + + +#include "config.h" +#include "vm/types.h" + +#include "mm/memory.h" +#include "vm/class.h" +#include "vm/exceptions.h" +#include "vm/method.h" +#include "vm/options.h" +#include "vm/stackmap.h" + +#if defined(ENABLE_STATISTICS) +# include "vm/statistics.h" +#endif + +#include "vm/suck.h" + + +/* stackmap_get_verification_type_info ***************************************** + + union verification_type_info { + Top_variable_info; + Integer_variable_info; + Float_variable_info; + Long_variable_info; + Double_variable_info; + Null_variable_info; + UninitializedThis_variable_info; + Object_variable_info; + Uninitialized_variable_info; + } + + Top_variable_info { + u1 tag = ITEM_Top; // 0 + } + + Integer_variable_info { + u1 tag = ITEM_Integer; // 1 + } + + Float_variable_info { + u1 tag = ITEM_Float; // 2 + } + + Long_variable_info { + u1 tag = ITEM_Long; // 4 + } + + Double_variable_info { + u1 tag = ITEM_Double; // 3 + } + + Null_variable_info { + u1 tag = ITEM_Null; // 5 + } + + UninitializedThis_variable_info { + u1 tag = ITEM_UninitializedThis; // 6 + } + + Object_variable_info { + u1 tag = ITEM_Object; // 7 + u2 cpool_index; + } + + Uninitialized_variable_info { + u1 tag = ITEM_Uninitialized; // 8 + u2 offset; + } + +*******************************************************************************/ + +static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info) +{ + /* get verification type */ + + if (!suck_check_classbuffer_size(cb, 1)) + return false; + + verification_type_info->tag = suck_u1(cb); + + /* process the tag */ + + switch (verification_type_info->tag) { + case ITEM_Top: + case ITEM_Integer: + case ITEM_Float: + case ITEM_Long: + case ITEM_Double: + case ITEM_Null: + case ITEM_UninitializedThis: + break; + + case ITEM_Object: + /* get constant pool index */ + + if (!suck_check_classbuffer_size(cb, 2)) + return false; + + verification_type_info->Object_variable_info.cpool_index = suck_u2(cb); + break; + + case ITEM_Uninitialized: + /* get offset */ + + if (!suck_check_classbuffer_size(cb, 2)) + return false; + + verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb); + break; + } + + return true; +} + + +/* stackmap_get_same_locals_1_stack_item_frame ********************************* + + same_locals_1_stack_item_frame { + u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127 + verification_type_info stack[1]; + } + +*******************************************************************************/ + +static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame) +{ + same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame; + + /* for convenience */ + + same_locals_1_stack_item_frame = + &(stack_map_frame->same_locals_1_stack_item_frame); + + if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0]))) + return false; + + return true; +} + + +/* stackmap_get_same_locals_1_stack_item_frame_extended ************************ + + same_locals_1_stack_item_frame_extended { + u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247 + u2 offset_delta; + verification_type_info stack[1]; + } + +*******************************************************************************/ + +static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame) +{ + same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended; + + /* for convenience */ + + same_locals_1_stack_item_frame_extended = + &(stack_map_frame->same_locals_1_stack_item_frame_extended); + + /* check buffer size */ + + if (!suck_check_classbuffer_size(cb, 2)) + return false; + + /* get offset delta */ + + same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb); + + /* process stack */ + + if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0]))) + return false; + + return true; +} + + +/* stackmap_get_chop_frame ***************************************************** + + chop_frame { + u1 frame_type = CHOP_FRAME; // 248-250 + u2 offset_delta; + } + +*******************************************************************************/ + +static bool stackmap_get_chop_frame(classbuffer *cb, + stack_map_frame_t *stack_map_frame) +{ + chop_frame_t *chop_frame; + + /* for convenience */ + + chop_frame = &(stack_map_frame->chop_frame); + + /* check buffer size */ + + if (!suck_check_classbuffer_size(cb, 2)) + return false; + + /* get offset delta */ + + chop_frame->offset_delta = suck_u2(cb); + + return true; +} + + +/* stackmap_get_same_frame_extended ******************************************** + + same_frame_extended { + u1 frame_type = SAME_FRAME_EXTENDED; // 251 + u2 offset_delta; + } + +*******************************************************************************/ + +static bool stackmap_get_same_frame_extended(classbuffer *cb, + stack_map_frame_t *stack_map_frame) +{ + same_frame_extended_t *same_frame_extended; + + /* for convenience */ + + same_frame_extended = &(stack_map_frame->same_frame_extended); + + /* check buffer size */ + + if (!suck_check_classbuffer_size(cb, 2)) + return false; + + /* get offset delta */ + + same_frame_extended->offset_delta = suck_u2(cb); + + return true; +} + + +/* stackmap_get_append_frame *************************************************** + + append_frame { + u1 frame_type = APPEND_FRAME; // 252-254 + u2 offset_delta; + verification_type_info locals[frame_Type - 251]; + } + +*******************************************************************************/ + +static bool stackmap_get_append_frame(classbuffer *cb, + stack_map_frame_t *stack_map_frame) +{ + append_frame_t *append_frame; + s4 number_of_locals; + s4 i; + + /* for convenience */ + + append_frame = &(stack_map_frame->append_frame); + + /* check buffer size */ + + if (!suck_check_classbuffer_size(cb, 2)) + return false; + + /* get offset delta */ + + append_frame->offset_delta = suck_u2(cb); + + /* allocate locals array */ + + number_of_locals = append_frame->frame_type - 251; + + append_frame->locals = DMNEW(verification_type_info_t, number_of_locals); + + /* process all locals */ + + for (i = 0; i < number_of_locals; i++) + if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i]))) + return false; + + return true; +} + + +/* stackmap_get_full_frame ***************************************************** + + full_frame { + u1 frame_type = FULL_FRAME; + u2 offset_delta; + u2 number_of_locals; + verification_type_info locals[number_of_locals]; + u2 number_of_stack_items; + verification_type_info stack[number_of_stack_items]; + } + +*******************************************************************************/ + +static bool stackmap_get_full_frame(classbuffer *cb, + stack_map_frame_t *stack_map_frame) +{ + full_frame_t *full_frame; + s4 i; + + /* for convenience */ + + full_frame = &(stack_map_frame->full_frame); + + /* check buffer size */ + + if (!suck_check_classbuffer_size(cb, 2 + 2)) + return false; + + /* get offset delta */ + + stack_map_frame->full_frame.offset_delta = suck_u2(cb); + + /* get number of locals */ + + full_frame->number_of_locals = suck_u2(cb); + + /* allocate locals array */ + + full_frame->locals = + DMNEW(verification_type_info_t, full_frame->number_of_locals); + + /* process all locals */ + + for (i = 0; i < full_frame->number_of_locals; i++) + if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i]))) + return false; + + /* get number of stack items */ + + if (!suck_check_classbuffer_size(cb, 2)) + return false; + + full_frame->number_of_stack_items = suck_u2(cb); + + /* allocate stack array */ + + full_frame->stack = + DMNEW(verification_type_info_t, full_frame->number_of_stack_items); + + /* process all stack items */ + + for (i = 0; i < full_frame->number_of_stack_items; i++) + if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i]))) + return false; + + return true; +} + + +/* stackmap_load_attribute_stackmaptable *************************************** + + stack_map { + u2 attribute_name_index; + u4 attribute_length; + u2 number_of_entries; + stack_map_frame entries[number_of_entries]; + } + + union stack_map_frame { + same_frame; + same_locals_1_stack_item_frame; + same_locals_1_stack_item_frame_extended; + chop_frame; + same_frame_extended; + append_frame; + full_frame; + } + + same_frame { + u1 frame_type = SAME; // 0-63 + } + +*******************************************************************************/ + +bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m) +{ + classinfo *c; + stack_map_t *stack_map; + s4 i; + u1 frame_type; + + /* get classinfo */ + + c = cb->class; + + /* allocate stack map structure */ + + stack_map = DNEW(stack_map_t); + + STATISTICS(size_stack_map += sizeof(stack_map_t)); + + /* check buffer size */ + + if (!suck_check_classbuffer_size(cb, 4 + 2)) + return false; + + /* attribute_length */ + + stack_map->attribute_length = suck_u4(cb); + + if (!suck_check_classbuffer_size(cb, stack_map->attribute_length)) + return false; + + /* get number of entries */ + + stack_map->number_of_entries = suck_u2(cb); + + /* process all entries */ + + stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries); + + for (i = 0; i < stack_map->number_of_entries; i++) { + /* get the frame type */ + + frame_type = suck_u1(cb); + + stack_map->entries[i].frame_type = frame_type; + + /* process frame */ + + if (frame_type <= FRAME_TYPE_SAME) { + /* same_frame */ + } + else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) { + /* same_locals_1_stack_item_frame */ + + if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i]))) + return false; + } + else if (frame_type <= FRAME_TYPE_RESERVED) { + /* reserved */ + + exceptions_throw_classformaterror(c, "reserved frame type"); + return false; + } + else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) { + /* same_locals_1_stack_item_frame_extended */ + + if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i]))) + return false; + } + else if (frame_type <= FRAME_TYPE_CHOP) { + /* chop_frame */ + + if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i]))) + return false; + } + else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) { + /* same_frame_extended */ + + if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i]))) + return false; + } + else if (frame_type <= FRAME_TYPE_APPEND) { + /* append_frame */ + + if (!stackmap_get_append_frame(cb, &(stack_map->entries[i]))) + return false; + } + else if (frame_type == FRAME_TYPE_FULL_FRAME) { + /* full_frame */ + + if (!stackmap_get_full_frame(cb, &(stack_map->entries[i]))) + return false; + } + } + + /* store stack map in method structure */ + +#if 0 + /* currently not used */ + + m->stack_map = stack_map; +#endif + + return true; +} + + +/* + * These are local overrides for various environment variables in Emacs. + * Please do not remove this and leave it at the end of the file, where + * Emacs will automagically detect them. + * --------------------------------------------------------------------- + * Local variables: + * mode: c + * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * End: + * vim:noexpandtab:sw=4:ts=4: + */ diff --git a/src/vm/stackmap.h b/src/vm/stackmap.h new file mode 100644 index 000000000..e86c7434b --- /dev/null +++ b/src/vm/stackmap.h @@ -0,0 +1,237 @@ +/* src/vm/stackmap.h - class attribute StackMapTable + + Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates, + R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, + C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, + Institut f. Computersprachen - TU Wien + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Contact: cacao@cacaojvm.org + + Authors: Christian Thalinger + + $Id: utf8.h 5920 2006-11-05 21:23:09Z twisti $ + +*/ + + +#ifndef _STACKMAP_H +#define _STACKMAP_H + +/* forward typedefs ***********************************************************/ + +typedef struct stack_map_t stack_map_t; +typedef union stack_map_frame_t stack_map_frame_t; +typedef struct same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame_t; +typedef struct same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended_t; +typedef struct chop_frame_t chop_frame_t; +typedef struct same_frame_extended_t same_frame_extended_t; +typedef struct append_frame_t append_frame_t; +typedef struct full_frame_t full_frame_t; + +typedef union verification_type_info_t verification_type_info_t; +typedef struct Top_variable_info_t Top_variable_info_t; +typedef struct Integer_variable_info_t Integer_variable_info_t; +typedef struct Float_variable_info_t Float_variable_info_t; +typedef struct Long_variable_info_t Long_variable_info_t; +typedef struct Double_variable_info_t Double_variable_info_t; +typedef struct Null_variable_info_t Null_variable_info_t; +typedef struct UninitializedThis_variable_info_t UninitializedThis_variable_info_t; +typedef struct Object_variable_info_t Object_variable_info_t; +typedef struct Uninitialized_variable_info_t Uninitialized_variable_info_t; + + +#include "config.h" +#include "vm/types.h" + +#include "vm/global.h" +#include "vm/loader.h" +#include "vm/method.h" + + +/* verification_type_info *****************************************************/ + +#define ITEM_Top 0 +#define ITEM_Integer 1 +#define ITEM_Float 2 +#define ITEM_Double 3 +#define ITEM_Long 4 +#define ITEM_Null 5 +#define ITEM_UninitializedThis 6 +#define ITEM_Object 7 +#define ITEM_Uninitialized 8 + +struct Top_variable_info_t { + u1 tag; +}; + +struct Integer_variable_info_t { + u1 tag; +}; + +struct Float_variable_info_t { + u1 tag; +}; + +struct Long_variable_info_t { + u1 tag; +}; + +struct Double_variable_info_t { + u1 tag; +}; + +struct Null_variable_info_t { + u1 tag; +}; + +struct UninitializedThis_variable_info_t { + u1 tag; +}; + +struct Object_variable_info_t { + u1 tag; + u2 cpool_index; +}; + +struct Uninitialized_variable_info_t { + u1 tag; + u2 offset; +}; + +union verification_type_info_t { + u1 tag; + Top_variable_info_t Top_variable_info; + Integer_variable_info_t Integer_variable_info; + Float_variable_info_t Float_variable_info; + Long_variable_info_t Long_variable_info; + Double_variable_info_t Double_variable_info; + Null_variable_info_t Null_variable_info; + UninitializedThis_variable_info_t UninitializedThis_variable_info; + Object_variable_info_t Object_variable_info; + Uninitialized_variable_info_t Uninitialized_variable_info; +}; + + +/* stack_map_t ****************************************************************/ + +struct stack_map_t { + u2 attribute_name_index; + u4 attribute_length; + u2 number_of_entries; + stack_map_frame_t *entries; +}; + + +/* same_locals_1_stack_item_frame_t *******************************************/ + +struct same_locals_1_stack_item_frame_t { + u1 frame_type; + verification_type_info_t stack[1]; +}; + + +/* same_locals_1_stack_item_frame_extended_t **********************************/ + +struct same_locals_1_stack_item_frame_extended_t { + u1 frame_type; + u2 offset_delta; + verification_type_info_t stack[1]; +}; + + +/* chop_frame_t ***************************************************************/ + +struct chop_frame_t { + u1 frame_type; + u2 offset_delta; +}; + + +/* same_frame_extended_t ******************************************************/ + +struct same_frame_extended_t { + u1 frame_type; + u2 offset_delta; +}; + + +/* append_frame_t *************************************************************/ + +struct append_frame_t { + u1 frame_type; + u2 offset_delta; + verification_type_info_t *locals; +}; + + +/* full_frame_t ***************************************************************/ + +struct full_frame_t { + u1 frame_type; + u2 offset_delta; + u2 number_of_locals; + verification_type_info_t *locals; + u2 number_of_stack_items; + verification_type_info_t *stack; +}; + + +/* stack_map_frame_t **********************************************************/ + +#define FRAME_TYPE_SAME 63 /* 0-63 */ +#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM 127 /* 0-127 */ +#define FRAME_TYPE_RESERVED 246 /* 128-246 */ +#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED 247 /* 247 */ +#define FRAME_TYPE_CHOP 250 /* 248-250 */ +#define FRAME_TYPE_SAME_FRAME_EXTENDED 251 /* 251 */ +#define FRAME_TYPE_APPEND 254 /* 252-254 */ +#define FRAME_TYPE_FULL_FRAME 255 /* 255 */ + +union stack_map_frame_t { + u1 frame_type; + same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame; + same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended; + chop_frame_t chop_frame; + same_frame_extended_t same_frame_extended; + append_frame_t append_frame; + full_frame_t full_frame; +}; + + +/* function prototypes ********************************************************/ + +bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m); + +#endif /* _STACKMAP_H */ + + +/* + * These are local overrides for various environment variables in Emacs. + * Please do not remove this and leave it at the end of the file, where + * Emacs will automagically detect them. + * --------------------------------------------------------------------- + * Local variables: + * mode: c + * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * End: + * vim:noexpandtab:sw=4:ts=4: + */ diff --git a/src/vm/statistics.c b/src/vm/statistics.c index e88f6bd72..0f142ea3f 100644 --- a/src/vm/statistics.c +++ b/src/vm/statistics.c @@ -26,7 +26,7 @@ Authors: Christian Thalinger - $Id: statistics.c 6080 2006-11-28 22:28:52Z twisti $ + $Id: statistics.c 6216 2006-12-18 18:21:37Z twisti $ */ @@ -76,6 +76,8 @@ s4 size_fieldinfo = 0; s4 size_methodinfo = 0; s4 size_codeinfo = 0; +s4 size_stack_map = 0; + int count_const_pool_len = 0; int count_classref_len = 0; int count_parsed_desc_len = 0; @@ -524,7 +526,8 @@ void print_stats(void) log_println("Size of native stubs: %10.3f kB", (float) count_nstub_len / 1024); log_println("Size of utf: %10.3f kB", (float) count_utf_len / 1024); log_println("Size of VMCode: %10.3f kB", (float) count_vmcode_len / 1024); - log_println("Size of exception tables: %10.3f kB\n", (float) count_extable_len / 1024); + log_println("Size of exception tables: %10.3f kB", (float) count_extable_len / 1024); + log_println("size of stack map: %10.3f kb\n", (float) size_stack_map / 1024); dolog("Number of class loads: %6d", count_class_loads); dolog("Number of class inits: %6d", count_class_inits); diff --git a/src/vm/statistics.h b/src/vm/statistics.h index fbe035a9e..a19e78862 100644 --- a/src/vm/statistics.h +++ b/src/vm/statistics.h @@ -26,7 +26,7 @@ Authors: Christian Thalinger - $Id: statistics.h 6080 2006-11-28 22:28:52Z twisti $ + $Id: statistics.h 6216 2006-12-18 18:21:37Z twisti $ */ @@ -98,6 +98,8 @@ extern s4 size_fieldinfo; extern s4 size_methodinfo; extern s4 size_codeinfo; +extern s4 size_stack_map; + extern int count_const_pool_len; extern int count_classref_len; extern int count_parsed_desc_len; diff --git a/src/vm/utf8.c b/src/vm/utf8.c index 4c65b5835..63a26a8b6 100644 --- a/src/vm/utf8.c +++ b/src/vm/utf8.c @@ -25,13 +25,12 @@ Contact: cacao@cacaojvm.org Authors: Reinhard Grafl - - Changes: Mark Probst + Mark Probst Andreas Krall Christian Thalinger - Edwin Steiner + Edwin Steiner - $Id: utf8.c 5920 2006-11-05 21:23:09Z twisti $ + $Id: utf8.c 6216 2006-12-18 18:21:37Z twisti $ */ @@ -121,7 +120,13 @@ utf *utf_Code; /* Code */ utf *utf_Exceptions; /* Exceptions */ utf *utf_LineNumberTable; /* LineNumberTable */ utf *utf_SourceFile; /* SourceFile */ + +#if defined(ENABLE_JAVASE) +utf *utf_EnclosingMethod; utf *utf_Signature; +utf *utf_RuntimeVisibleAnnotations; +utf *utf_StackMapTable; +#endif utf *utf_init; /* */ utf *utf_clinit; /* */ @@ -268,7 +273,13 @@ bool utf8_init(void) utf_Exceptions = utf_new_char("Exceptions"); utf_LineNumberTable = utf_new_char("LineNumberTable"); utf_SourceFile = utf_new_char("SourceFile"); + +#if defined(ENABLE_JAVASE) + utf_EnclosingMethod = utf_new_char("EnclosingMethod"); utf_Signature = utf_new_char("Signature"); + utf_RuntimeVisibleAnnotations = utf_new_char("RuntimeVisibleAnnotations"); + utf_StackMapTable = utf_new_char("StackMapTable"); +#endif utf_init = utf_new_char(""); utf_clinit = utf_new_char(""); diff --git a/src/vm/utf8.h b/src/vm/utf8.h index f58106510..acc5c14d2 100644 --- a/src/vm/utf8.h +++ b/src/vm/utf8.h @@ -25,10 +25,9 @@ Contact: cacao@cacaojvm.org Authors: Christian Thalinger + Edwin Steiner - Changes: Edwin Steiner - - $Id: utf8.h 5920 2006-11-05 21:23:09Z twisti $ + $Id: utf8.h 6216 2006-12-18 18:21:37Z twisti $ */ @@ -114,7 +113,13 @@ extern utf *utf_Code; extern utf *utf_Exceptions; extern utf *utf_LineNumberTable; extern utf *utf_SourceFile; + +#if defined(ENABLE_JAVASE) +extern utf *utf_EnclosingMethod; extern utf *utf_Signature; +extern utf *utf_RuntimeVisibleAnnotations; +extern utf *utf_StackMapTable; +#endif extern utf *utf_init; extern utf *utf_clinit; -- 2.25.1