Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: utf8.h 5920 2006-11-05 21:23:09Z twisti $
-
*/
-
#include "config.h"
+
+#include <assert.h>
+
#include "vm/types.h"
#include "mm/memory.h"
+#include "toolbox/logging.h"
+
#include "vmcore/annotation.h"
#include "vmcore/class.h"
#include "vmcore/suck.h"
+#if !defined(ENABLE_ANNOTATIONS)
+# error annotation support has to be enabled when compling this file!
+#endif
+
+/* annotation_bytearray_new ***************************************************
+
+ Allocate a new bytearray.
+
+*******************************************************************************/
+
+annotation_bytearray_t *annotation_bytearray_new(uint32_t size)
+{
+ annotation_bytearray_t *ba =
+ mem_alloc(sizeof(uint32_t) + sizeof(uint8_t) * size);
+
+ if (ba != NULL) {
+ ba->size = size;
+ }
+
+ return ba;
+}
+
+
+/* annotation_bytearray_free **************************************************
+
+ Free a bytearray.
+
+*******************************************************************************/
+
+void annotation_bytearray_free(annotation_bytearray_t *ba)
+{
+ if (ba != NULL) {
+ mem_free(ba, sizeof(uint32_t) + sizeof(uint8_t) * ba->size);
+ }
+}
+
+
+/* annotation_bytearrays_new **************************************************
+
+ Allocate a new array of bytearrays.
+
+*******************************************************************************/
+
+annotation_bytearrays_t *annotation_bytearrays_new(uint32_t size)
+{
+ annotation_bytearrays_t *bas =
+ mem_alloc(sizeof(uint32_t) + sizeof(annotation_bytearray_t*) * size);
+
+ if (bas != NULL) {
+ bas->size = size;
+ }
+
+ return bas;
+}
+
+
+/* annotation_bytearrays_resize ***********************************************
+
+ Resize an array of bytearrays.
+
+*******************************************************************************/
+
+bool annotation_bytearrays_resize(annotation_bytearrays_t **bas,
+ uint32_t size)
+{
+ annotation_bytearrays_t *newbas = NULL;
+ uint32_t i;
+ uint32_t minsize;
+
+ assert(bas != NULL);
+
+ newbas = annotation_bytearrays_new(size);
+
+ if (newbas == NULL) {
+ return false;
+ }
+
+ if (*bas != NULL) {
+ minsize = size < (*bas)->size ? size : (*bas)->size;
+
+ for (i = size; i < (*bas)->size; ++ i) {
+ annotation_bytearray_free((*bas)->data[i]);
+ }
+
+ for (i = 0; i < minsize; ++i) {
+ newbas->data[i] = (*bas)->data[i];
+ }
+ }
+
+ *bas = newbas;
+
+ return true;
+}
+
+
+/* annotation_bytearrays_insert ***********************************************
+
+ Insert a bytearray into an array of bytearrays.
-/* annotation_load_attribute_runtimevisibleannotations *************************
+*******************************************************************************/
+
+bool annotation_bytearrays_insert(annotation_bytearrays_t **bas,
+ uint32_t index, annotation_bytearray_t *ba)
+{
+ assert(bas != NULL);
+
+ if (ba != NULL) {
+ if (*bas == NULL || (*bas)->size <= index) {
+ if (!annotation_bytearrays_resize(bas, index + 1)) {
+ return false;
+ }
+ }
+ else {
+ /* free old bytearray (if any) */
+ annotation_bytearray_free((*bas)->data[index]);
+ }
+
+ /* insert new bytearray */
+ (*bas)->data[index] = ba;
+ }
+ else if (*bas != NULL && (*bas)->size > index) {
+ /* do not resize when just inserting NULL,
+ * but free old bytearray if there is any */
+ annotation_bytearray_free((*bas)->data[index]);
+ }
+
+ return true;
+}
+
+
+/* annotation_bytearrays_free *************************************************
+
+ Free an array of bytearrays.
+
+*******************************************************************************/
- RuntimeVisibleAnnotations_attribute {
+void annotation_bytearrays_free(annotation_bytearrays_t *bas)
+{
+ uint32_t i;
+
+ if (bas != NULL) {
+ for (i = 0; i < bas->size; ++ i) {
+ annotation_bytearray_free(bas->data[i]);
+ }
+
+ mem_free(bas, sizeof(uint32_t) +
+ sizeof(annotation_bytearray_t*) * bas->size);
+ }
+}
+
+
+/* annotation_load_attribute_body *********************************************
+
+ This function loads the body of a generic attribute.
+
+ XXX: Maybe this function should be called loader_load_attribute_body and
+ located in vmcore/loader.c?
+
+ attribute_info {
u2 attribute_name_index;
u4 attribute_length;
- u2 num_annotations;
- annotation annotations[num_annotations];
+ u1 info[attribute_length];
}
- annotation {
- u2 type_index;
- u2 num_element_value_pairs;
- {
- u2 element_name_index;
- element_value element;
- } element_value_pairs[num_element_value_pairs];
- }
+ IN:
+ cb.................classbuffer from which to read the data.
+ errormsg_prefix....prefix for error messages (if any).
- element_value {
- u1 tag;
- union {
- u2 const_value_index;
- {
- u2 type_name_index;
- u2 const_name_index;
- } enum_const_value;
- u2 class_info_index;
- annotation annotation_value;
- {
- u2 num_values;
- element_value values[num_values];
- } array_value;
- } value;
- }
+ OUT:
+ attribute..........bytearray-pointer which will be set to the read data.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
*******************************************************************************/
-bool annotation_load_attribute_runtimevisibleannotations(classbuffer *cb)
+static bool annotation_load_attribute_body(classbuffer *cb,
+ annotation_bytearray_t **attribute, const char *errormsg_prefix)
{
- classinfo *c;
- u4 attribute_length;
- u2 num_annotations;
- annotation_t *annotations;
- element_value_t *element_value;
- u2 type_index;
- u2 num_element_value_pairs;
- u2 element_name_index;
- u4 i, j;
+ uint32_t size = 0;
+ annotation_bytearray_t *ba = NULL;
- /* get classinfo */
+ assert(cb != NULL);
+ assert(attribute != NULL);
- c = cb->class;
+ if (!suck_check_classbuffer_size(cb, 4)) {
+ log_println("%s: size missing", errormsg_prefix);
+ return false;
+ }
- if (!suck_check_classbuffer_size(cb, 4 + 2))
+ /* load attribute_length */
+ size = suck_u4(cb);
+
+ if (!suck_check_classbuffer_size(cb, size)) {
+ log_println("%s: invalid size", errormsg_prefix);
return false;
+ }
+
+ /* if attribute_length == 0 then NULL is
+ * the right value for this attribute */
+ if (size > 0) {
+ ba = annotation_bytearray_new(size);
+
+ if (ba == NULL) {
+ /* out of memory */
+ return false;
+ }
+
+ /* load data */
+ suck_nbytes(ba->data, cb, size);
+
+ /* return data */
+ *attribute = ba;
+ }
+
+ return true;
+}
- /* attribute_length */
- attribute_length = suck_u4(cb);
+/* annotation_load_method_attribute_annotationdefault *************************
- if (!suck_check_classbuffer_size(cb, attribute_length))
+ Load annotation default value.
+
+ AnnotationDefault_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ element_value default_value;
+ }
+
+ IN:
+ cb.................classbuffer from which to read the data.
+ m..................methodinfo for the method of which the annotation
+ default value is read and into which the value is
+ stored into.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_annotationdefault(
+ classbuffer *cb, methodinfo *m)
+{
+ int slot = 0;
+ annotation_bytearray_t *annotationdefault = NULL;
+ annotation_bytearrays_t **annotationdefaults = NULL;
+
+ assert(cb != NULL);
+ assert(m != NULL);
+
+ annotationdefaults = &(m->class->method_annotationdefaults);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotationdefault,
+ "invalid annotation default method attribute")) {
return false;
+ }
+
+ if (annotationdefault != NULL) {
+ slot = m - m->class->methods;
- /* get number of annotations */
+ if (!annotation_bytearrays_insert(
+ annotationdefaults, slot, annotationdefault)) {
+ annotation_bytearray_free(annotationdefault);
+ return false;
+ }
+ }
- num_annotations = suck_u2(cb);
+ return true;
+}
- printf("num_annotations: %d\n", num_annotations);
- /* allocate annotations-array */
+/* annotation_load_method_attribute_runtimevisibleparameterannotations ********
- annotations = MNEW(annotation_t, num_annotations);
+ Load runtime visible parameter annotations.
- /* parse all annotations */
+ RuntimeVisibleParameterAnnotations_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 num_parameters;
+ {
+ u2 num_annotations;
+ annotation annotations[num_annotations];
+ } parameter_annotations[num_parameters];
+ }
- for (i = 0; i < num_annotations; i++) {
- /* get annotation type */
+ IN:
+ cb.................classbuffer from which to read the data.
+ m..................methodinfo for the method of which the parameter
+ annotations are read and into which the parameter
+ annotations are stored into.
- type_index = suck_u2(cb);
+ RETURN VALUE:
+ true if all went good. false otherwhise.
- if (!(annotations[i].type =
- class_getconstant(c, type_index, CONSTANT_Utf8)))
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimevisibleparameterannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ int slot = 0;
+ annotation_bytearray_t *annotations = NULL;
+ annotation_bytearrays_t **parameterannotations = NULL;
+
+ assert(cb != NULL);
+ assert(m != NULL);
+
+ parameterannotations = &(m->class->method_parameterannotations);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible parameter annotations method attribute")) {
+ return false;
+ }
+
+ if (annotations != NULL) {
+ slot = m - m->class->methods;
+
+ if (!annotation_bytearrays_insert(
+ parameterannotations, slot, annotations)) {
+ annotation_bytearray_free(annotations);
return false;
+ }
+ }
+
+ return true;
+}
+
- printf("type: ");
- utf_display_printable_ascii(annotations[i].type);
- printf("\n");
+/* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
+
+ Load runtime invisible parameter annotations.
- /* get number of element values */
+ <quote cite="http://jcp.org/en/jsr/detail?id=202">
+ The RuntimeInvisibleParameterAnnotations attribute is similar to the
+ RuntimeVisibleParameterAnnotations attribute, except that the annotations
+ represented by a RuntimeInvisibleParameterAnnotations attribute must not be
+ made available for return by reflective APIs, unless the the JVM has
+ specifically been instructed to retain these annotations via some
+ implementation-specific mechanism such as a command line flag. In the
+ absence of such instructions, the JVM ignores this attribute.
+ </quote>
- num_element_value_pairs = suck_u2(cb);
+ Hotspot loads them into the same bytearray as the runtime visible parameter
+ annotations (after the runtime visible parameter annotations). But in J2SE
+ the bytearray will only be parsed as if ther is only one annotation
+ structure in it, so the runtime invisible parameter annotatios will be
+ ignored.
- printf("num_element_value_pairs: %d\n", num_element_value_pairs);
+ Therefore I do not even bother to read them.
- element_value = MNEW(element_value_t, num_element_value_pairs);
+ RuntimeInvisibleParameterAnnotations_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 num_parameters;
+ {
+ u2 num_annotations;
+ annotation annotations[num_annotations];
+ } parameter_annotations[num_parameters];
+ }
- /* parse all element values */
+ IN:
+ cb.................classbuffer from which to read the data.
+ m..................methodinfo for the method of which the parameter
+ annotations are read and into which the parameter
+ annotations are stored into.
- for (j = 0; j < num_element_value_pairs; j++) {
- /* get element name */
+ RETURN VALUE:
+ true if all went good. false otherwhise.
- element_name_index = suck_u2(cb);
+*******************************************************************************/
- if (!(element_value[j].name =
- class_getconstant(c, element_name_index, CONSTANT_Utf8)))
- return false;
+bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ return loader_skip_attribute_body(cb);
+}
- /* get element tag */
- element_value[i].tag = suck_u1(cb);
+/* annotation_load_class_attribute_runtimevisibleannotations ******************
+
+ Load runtime visible annotations of a class.
+
+*******************************************************************************/
+
+bool annotation_load_class_attribute_runtimevisibleannotations(
+ classbuffer *cb)
+{
+ return annotation_load_attribute_body(
+ cb, &(cb->class->annotations),
+ "invalid runtime visible annotations class attribute");
+}
+
+
+/* annotation_load_class_attribute_runtimeinvisibleannotations ****************
+
+ Load runtime invisible annotations of a class (just skip them).
+
+*******************************************************************************/
+
+bool annotation_load_class_attribute_runtimeinvisibleannotations(
+ classbuffer *cb)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/* annotation_load_method_attribute_runtimevisibleannotations *****************
+
+ Load runtime visible annotations of a method.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimevisibleannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ int slot = 0;
+ annotation_bytearray_t *annotations = NULL;
+ annotation_bytearrays_t **method_annotations = NULL;
+
+ assert(cb != NULL);
+ assert(m != NULL);
+
+ method_annotations = &(m->class->method_annotations);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible annotations method attribute")) {
+ return false;
+ }
+
+ if (annotations != NULL) {
+ slot = m - m->class->methods;
+
+ if (!annotation_bytearrays_insert(
+ method_annotations, slot, annotations)) {
+ annotation_bytearray_free(annotations);
+ return false;
}
+ }
+
+ return true;
+}
+
+
+/* annotation_load_method_attribute_runtimeinvisibleannotations ****************
+
+ Load runtime invisible annotations of a method (just skip them).
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/* annotation_load_field_attribute_runtimevisibleannotations ******************
+
+ Load runtime visible annotations of a field.
+
+*******************************************************************************/
+
+bool annotation_load_field_attribute_runtimevisibleannotations(
+ classbuffer *cb, fieldinfo *f)
+{
+ int slot = 0;
+ annotation_bytearray_t *annotations = NULL;
+ annotation_bytearrays_t **field_annotations = NULL;
+
+ assert(cb != NULL);
+ assert(f != NULL);
- /* store element value data */
+ field_annotations = &(f->class->field_annotations);
- annotations[i].element_valuescount = num_element_value_pairs;
- annotations[i].element_values = element_value;
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible annotations field attribute")) {
+ return false;
}
- /* store annotation variables */
+ if (annotations != NULL) {
+ slot = f - f->class->fields;
- c->runtimevisibleannotationscount = num_annotations;
- c->runtimevisibleannotations = annotations;
+ if (!annotation_bytearrays_insert(
+ field_annotations, slot, annotations)) {
+ annotation_bytearray_free(annotations);
+ return false;
+ }
+ }
return true;
}
+/* annotation_load_field_attribute_runtimeinvisibleannotations ****************
+
+ Load runtime invisible annotations of a field (just skip them).
+
+*******************************************************************************/
+
+bool annotation_load_field_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, fieldinfo *f)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
/*
* 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