CACAO
annotation.cpp
Go to the documentation of this file.
1 /* src/vm/annotation.cpp - class annotations
2 
3  Copyright (C) 2006-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include <assert.h>
29 #include <stdint.h>
30 
31 #include "native/llni.hpp"
32 
33 #include "mm/memory.hpp"
34 
35 #include "toolbox/logging.hpp"
36 
37 #include "vm/annotation.hpp"
38 #include "vm/array.hpp"
39 #include "vm/jit/builtin.hpp"
40 #include "vm/class.hpp"
41 #include "vm/field.hpp"
42 #include "vm/loader.hpp"
43 #include "vm/method.hpp"
44 #include "vm/primitive.hpp"
45 #include "vm/suck.hpp"
46 #include "vm/types.hpp"
47 
48 #if !defined(ENABLE_ANNOTATIONS)
49 # error annotation support has to be enabled when compling this file!
50 #endif
51 
52 namespace cacao {
53 
54 /* annotation_bytearrays_resize ***********************************************
55 
56  Resize an array of bytearrays.
57 
58  IN:
59  bytearrays.....array of bytearrays
60  size...........new size of the refered array
61 
62  RETURN VALUE:
63  The new array if a resize was neccessarry, the old if the given size
64  equals the current size or NULL if an error occured.
65 
66 *******************************************************************************/
67 
69  java_handle_objectarray_t *bytearrays, uint32_t size)
70 {
71  uint32_t minsize = 0; /* count of object refs to copy */
72  uint32_t oldsize = 0; /* size of old array */
73 
74  ObjectArray bas(bytearrays);
75 
76  if (bytearrays != NULL) {
77  oldsize = bas.get_length();
78 
79  /* if the size already fits do nothing */
80  if (size == oldsize) {
81  return bytearrays;
82  }
83  }
84 
85  // Allocate new array on the heap.
86 
87  ObjectArray newbas(size,
89 
90  /* is there a old byte array array? */
91  if (newbas.is_non_null() && bytearrays != NULL) {
92  minsize = size < oldsize ? size : oldsize;
93 
95  MCOPY(
96  newbas.get_raw_data_ptr(), bas.get_raw_data_ptr(),
97  java_object_t*, minsize);
99  }
100 
101  return newbas.get_handle();
102 }
103 
104 
105 /* annotation_bytearrays_insert ***********************************************
106 
107  Insert a bytearray into an array of bytearrays.
108 
109  IN:
110  bytearrays........array of bytearrays where 'bytearray' has to be
111  inserted at position 'index'.
112  index.............position where 'ba' has to be inserted into
113  'bytearrays'.
114  bytearray.........byte array which has to be inserted into
115  'bytearrays'.
116 
117  RETURN VALUE:
118  The new array if a resize was neccessarry, the old if the given size
119  equals the current size or NULL if an error occured.
120 
121 *******************************************************************************/
122 
124  java_handle_t *bytearrays, uint32_t index,
125  java_handle_bytearray_t *bytearray)
126 {
127  uint32_t size = 0; /* current size of the array */
128 
129  /* do nothing if NULL is inserted but no array exists */
130  if (bytearray == NULL && bytearrays == NULL) {
131  return NULL;
132  }
133 
134  ObjectArray bas(bytearrays);
135 
136  /* get lengths if array exists */
137  if (bytearrays != NULL) {
138  size = bas.get_length();
139  }
140 
141  if (bytearray == NULL) {
142  /* insert NULL only if array is big enough */
143  if (size > index) {
144  bas.set_element(index, NULL);
145  }
146  }
147  else {
148  // XXX: We should use a clone function here!!!
149  /* resize array if it's not enough for inserted value */
150  if (size <= index) {
151  bas = annotation_bytearrays_resize(bas.get_handle(), index + 1);
152 
153  if (bas.is_null()) {
154  /* out of memory */
155  return NULL;
156  }
157  }
158 
159  bas.set_element(index, (java_handle_t*) bytearray);
160  }
161 
162  return bas.get_handle();
163 }
164 
165 
166 /* annotation_load_attribute_body *********************************************
167 
168  This function loads the body of a generic attribute.
169 
170  XXX: Maybe this function should be called loader_load_attribute_body and
171  located in vm/loader.c?
172 
173  attribute_info {
174  u2 attribute_name_index;
175  u4 attribute_length;
176  u1 info[attribute_length];
177  }
178 
179  IN:
180  cb.................classbuffer from which to read the data.
181  errormsg_prefix....prefix for error messages (if any).
182 
183  OUT:
184  attribute..........bytearray-pointer which will be set to the read data.
185 
186  RETURN VALUE:
187  true if all went good. false otherwhise.
188 
189 *******************************************************************************/
190 
192  java_handle_bytearray_t **attribute,
193  const char *errormsg_prefix) {
194  assert(cb);
195  assert(attribute != NULL);
196 
197  if (!cb.check_size(4)) {
198  log_println("%s: size missing", errormsg_prefix);
199  return false;
200  }
201 
202  /* load attribute_length */
203  uint32_t size = cb.read_u4();
204 
205  if (!cb.check_size(size)) {
206  log_println("%s: invalid size", errormsg_prefix);
207  return false;
208  }
209 
210  /* if attribute_length == 0 then NULL is
211  * the right value for this attribute */
212  if (size > 0) {
213  ByteArray ba(size);
214 
215  if (ba.is_null()) {
216  /* out of memory */
217  return false;
218  }
219 
220  /* load data */
222 
223  uint8_t* ptr = (uint8_t*) ba.get_raw_data_ptr();
224  cb.read_nbytes(ptr, size);
225 
227 
228  /* return data */
229  *attribute = ba.get_handle();
230  }
231 
232  return true;
233 }
234 
235 
236 /* annotation_load_method_attribute_annotationdefault *************************
237 
238  Load annotation default value.
239 
240  AnnotationDefault_attribute {
241  u2 attribute_name_index;
242  u4 attribute_length;
243  element_value default_value;
244  }
245 
246  IN:
247  cb.................classbuffer from which to read the data.
248  m..................methodinfo for the method of which the annotation
249  default value is read and into which the value is
250  stored into.
251 
252  RETURN VALUE:
253  true if all went good. false otherwhise.
254 
255 *******************************************************************************/
256 
258  int slot = 0; // the slot of the method
259  java_handle_bytearray_t *annotationdefault = NULL; // unparsed annotation defalut value
260  java_handle_t *annotationdefaults = NULL; // array of unparsed annotation default values
261 
262  assert(cb);
263  assert(m != NULL);
264 
266  method_annotationdefaults,
267  annotationdefaults);
268 
270  &annotationdefault,
271  "invalid annotation default method attribute"))
272  return false;
273 
274  if (annotationdefault != NULL) {
275  slot = m - m->clazz->methods;
276  annotationdefaults = annotation_bytearrays_insert(
277  annotationdefaults, slot, annotationdefault);
278 
279  if (annotationdefaults == NULL) {
280  return false;
281  }
282 
284  m->clazz, method_annotationdefaults, annotationdefaults);
285  }
286 
287  return true;
288 }
289 
290 
291 /* annotation_load_method_attribute_runtimevisibleparameterannotations ********
292 
293  Load runtime visible parameter annotations.
294 
295  RuntimeVisibleParameterAnnotations_attribute {
296  u2 attribute_name_index;
297  u4 attribute_length;
298  u1 num_parameters;
299  {
300  u2 num_annotations;
301  annotation annotations[num_annotations];
302  } parameter_annotations[num_parameters];
303  }
304 
305  IN:
306  cb.................classbuffer from which to read the data.
307  m..................methodinfo for the method of which the parameter
308  annotations are read and into which the parameter
309  annotations are stored into.
310 
311  RETURN VALUE:
312  true if all went good. false otherwhise.
313 
314 *******************************************************************************/
315 
317  methodinfo *m) {
318  int slot = 0; // the slot of the method
319  java_handle_bytearray_t *annotations = NULL; // unparsed parameter annotations
320  java_handle_t *parameterannotations = NULL; // array of unparsed parameter annotations
321 
322  assert(cb);
323  assert(m != NULL);
324 
326  method_parameterannotations,
327  parameterannotations);
328 
330  &annotations,
331  "invalid runtime visible parameter annotations method attribute"))
332  return false;
333 
334  if (annotations != NULL) {
335  slot = m - m->clazz->methods;
336  parameterannotations = annotation_bytearrays_insert(
337  parameterannotations, slot, annotations);
338 
339  if (parameterannotations == NULL) {
340  return false;
341  }
342 
344  m->clazz, method_parameterannotations, parameterannotations);
345  }
346 
347  return true;
348 }
349 
350 
351 /* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
352 
353  Load runtime invisible parameter annotations.
354 
355  <quote cite="http://jcp.org/en/jsr/detail?id=202">
356  The RuntimeInvisibleParameterAnnotations attribute is similar to the
357  RuntimeVisibleParameterAnnotations attribute, except that the annotations
358  represented by a RuntimeInvisibleParameterAnnotations attribute must not be
359  made available for return by reflective APIs, unless the the JVM has
360  specifically been instructed to retain these annotations via some
361  implementation-specific mechanism such as a command line flag. In the
362  absence of such instructions, the JVM ignores this attribute.
363  </quote>
364 
365  Hotspot loads them into the same bytearray as the runtime visible parameter
366  annotations (after the runtime visible parameter annotations). But in J2SE
367  the bytearray will only be parsed as if there is only one annotation
368  structure in it, so the runtime invisible parameter annotatios will be
369  ignored.
370 
371  Therefore I do not even bother to read them.
372 
373  RuntimeInvisibleParameterAnnotations_attribute {
374  u2 attribute_name_index;
375  u4 attribute_length;
376  u1 num_parameters;
377  {
378  u2 num_annotations;
379  annotation annotations[num_annotations];
380  } parameter_annotations[num_parameters];
381  }
382 
383  IN:
384  cb.................classbuffer from which to read the data.
385  m..................methodinfo for the method of which the parameter
386  annotations are read and into which the parameter
387  annotations are stored into.
388 
389  RETURN VALUE:
390  true if all went good. false otherwhise.
391 
392 *******************************************************************************/
393 
395  methodinfo *m) {
396  return loader_skip_attribute_body(cb);
397 }
398 
399 
400 /* annotation_load_class_attribute_runtimevisibleannotations ******************
401 
402  Load runtime visible annotations of a class.
403 
404  IN:
405  cb........the classbuffer from which the attribute has to be loaded.
406 
407  RETURN VALUE:
408  true if all went good. false otherwhise.
409 
410 *******************************************************************************/
411 
413  java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
414 
416  cb, &annotations,
417  "invalid runtime visible annotations class attribute")) {
418  return false;
419  }
420 
421  LLNI_classinfo_field_set(cb.get_class(), annotations, (java_handle_t*)annotations);
422 
423  return true;
424 }
425 
426 
427 /* annotation_load_class_attribute_runtimeinvisibleannotations ****************
428 
429  Load runtime invisible annotations of a class (just skip them).
430 
431  IN:
432  cb........the classbuffer from which the attribute has to be loaded.
433 
434  RETURN VALUE:
435  true if all went good. false otherwhise.
436 
437 *******************************************************************************/
438 
440  return loader_skip_attribute_body(cb);
441 }
442 
443 
444 /* annotation_load_method_attribute_runtimevisibleannotations *****************
445 
446  Load runtime visible annotations of a method.
447 
448  IN:
449  cb........the classbuffer from which the attribute has to be loaded.
450  m.........the method of which the runtime visible annotations have
451  to be loaded.
452 
453  RETURN VALUE:
454  true if all went good. false otherwhise.
455 
456 *******************************************************************************/
457 
459  methodinfo *m) {
460  int slot = 0; // slot of the method
461  java_handle_bytearray_t *annotations = NULL; // unparsed annotations
462  java_handle_t *method_annotations = NULL; // array of unparsed method annotations */
463 
464  assert(cb);
465  assert(m != NULL);
466 
468  m->clazz, method_annotations, method_annotations);
469 
471  cb, &annotations,
472  "invalid runtime visible annotations method attribute")) {
473  return false;
474  }
475 
476  if (annotations != NULL) {
477  slot = m - m->clazz->methods;
478  method_annotations = annotation_bytearrays_insert(
479  method_annotations, slot, annotations);
480 
481  if (method_annotations == NULL) {
482  return false;
483  }
484 
486  m->clazz, method_annotations, method_annotations);
487  }
488 
489  return true;
490 }
491 
492 
493 /* annotation_load_method_attribute_runtimeinvisibleannotations ****************
494 
495  Load runtime invisible annotations of a method (just skip them).
496 
497  IN:
498  cb........the classbuffer from which the attribute has to be loaded.
499  m.........the method of which the runtime invisible annotations have
500  to be loaded.
501 
502  RETURN VALUE:
503  true if all went good. false otherwhise.
504 
505 *******************************************************************************/
506 
508  methodinfo *m) {
509  return loader_skip_attribute_body(cb);
510 }
511 
512 
513 /* annotation_load_field_attribute_runtimevisibleannotations ******************
514 
515  Load runtime visible annotations of a field.
516 
517  IN:
518  cb........the classbuffer from which the attribute has to be loaded.
519  f.........the field of which the runtime visible annotations have
520  to be loaded.
521 
522  RETURN VALUE:
523  true if all went good. false otherwhise.
524 
525 *******************************************************************************/
526 
528  fieldinfo *f) {
529  int slot = 0; // slot of the field
530  java_handle_bytearray_t *annotations = NULL; // unparsed annotations
531  java_handle_t *field_annotations = NULL; // array of unparsed field annotations
532 
533  assert(cb);
534  assert(f != NULL);
535 
537  f->clazz, field_annotations, field_annotations);
538 
540  cb, &annotations,
541  "invalid runtime visible annotations field attribute")) {
542  return false;
543  }
544 
545  if (annotations != NULL) {
546  slot = f - f->clazz->fields;
547  field_annotations = annotation_bytearrays_insert(
548  field_annotations, slot, annotations);
549 
550  if (field_annotations == NULL) {
551  return false;
552  }
553 
555  f->clazz, field_annotations, field_annotations);
556  }
557 
558  return true;
559 }
560 
561 
562 /* annotation_load_field_attribute_runtimeinvisibleannotations ****************
563 
564  Load runtime invisible annotations of a field (just skip them).
565 
566  IN:
567  cb........the classbuffer from which the attribute has to be loaded.
568  f.........the field of which the runtime invisible annotations have
569  to be loaded.
570 
571  RETURN VALUE:
572  true if all went good. false otherwhise.
573 
574 *******************************************************************************/
575 
577  fieldinfo *f) {
578  return loader_skip_attribute_body(cb);
579 }
580 
581 } // end namespace cacao;
582 
583 /*
584  * These are local overrides for various environment variables in Emacs.
585  * Please do not remove this and leave it at the end of the file, where
586  * Emacs will automagically detect them.
587  * ---------------------------------------------------------------------
588  * Local variables:
589  * mode: c++
590  * indent-tabs-mode: t
591  * c-basic-offset: 4
592  * tab-width: 4
593  * End:
594  * vim:noexpandtab:sw=4:ts=4:
595  */
jlong jlong jlong jlong jint jmethodID jint slot
Definition: jvmti.h:497
std::size_t index
bool annotation_load_method_attribute_runtimevisibleparameterannotations(ClassBuffer &cb, methodinfo *m)
Definition: annotation.cpp:316
methodinfo * methods
Definition: class.hpp:113
bool annotation_load_method_attribute_runtimevisibleannotations(ClassBuffer &cb, methodinfo *m)
Definition: annotation.cpp:458
virtual java_handle_array_t * get_handle() const
Definition: array.hpp:103
int8_t * get_raw_data_ptr()
Definition: array.hpp:333
Actual implementation of access class for Java Object arrays.
Definition: array.hpp:381
bool annotation_load_field_attribute_runtimeinvisibleannotations(ClassBuffer &cb, fieldinfo *f)
Definition: annotation.cpp:576
#define LLNI_CRITICAL_END
Definition: llni.hpp:141
static classinfo * get_arrayclass_by_type(int type)
Returns the primitive array-class of the given type.
Definition: primitive.cpp:336
void set_element(int32_t index, T value)
Definition: array.hpp:255
void log_println(const char *text,...)
Definition: logging.cpp:193
static bool annotation_load_attribute_body(ClassBuffer &cb, java_handle_bytearray_t **attribute, const char *errormsg_prefix)
Definition: annotation.cpp:191
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
bool loader_skip_attribute_body(ClassBuffer &cb)
Definition: loader.cpp:499
fieldinfo * fields
Definition: class.hpp:110
bool annotation_load_method_attribute_annotationdefault(ClassBuffer &cb, methodinfo *m)
Definition: annotation.cpp:257
int32_t get_length() const
Definition: array.hpp:189
classinfo * clazz
Definition: method.hpp:80
void read_nbytes(uint8_t *dst, size_t num_bytes)
Transfer block of classfile into a buffer.
Definition: suck.hpp:186
static java_handle_objectarray_t * annotation_bytearrays_resize(java_handle_objectarray_t *bytearrays, uint32_t size)
Definition: annotation.cpp:68
#define LLNI_classinfo_field_get(cls, field, variable)
Definition: llni.hpp:82
classinfo * clazz
Definition: field.hpp:55
bool annotation_load_method_attribute_runtimeinvisibleannotations(ClassBuffer &cb, methodinfo *m)
Definition: annotation.cpp:507
uint32_t read_u4()
Definition: suck.hpp:155
bool is_non_null() const
Definition: array.hpp:208
#define LLNI_classinfo_field_set(cls, field, variable)
Definition: llni.hpp:94
static java_handle_t * annotation_bytearrays_insert(java_handle_t *bytearrays, uint32_t index, java_handle_bytearray_t *bytearray)
Definition: annotation.cpp:123
classinfo * get_class() const
Definition: suck.hpp:117
bool annotation_load_class_attribute_runtimevisibleannotations(ClassBuffer &cb)
Definition: annotation.cpp:412
#define LLNI_CRITICAL_START
Definition: llni.hpp:140
bool annotation_load_field_attribute_runtimevisibleannotations(ClassBuffer &cb, fieldinfo *f)
Definition: annotation.cpp:527
bool check_size(size_t sz)
Assert that at least &lt;sz&gt; bytes are left to read.
Definition: suck.hpp:135
#define MCOPY(dest, src, type, num)
Definition: memory.hpp:103
bool is_null() const
Definition: array.hpp:203
bool annotation_load_class_attribute_runtimeinvisibleannotations(ClassBuffer &cb)
Definition: annotation.cpp:439
bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(ClassBuffer &cb, methodinfo *m)
Definition: annotation.cpp:394
java_handle_t ** get_raw_data_ptr()
Definition: array.hpp:385