CACAO
field.cpp
Go to the documentation of this file.
1 /* src/vm/field.cpp - field functions
2 
3  Copyright (C) 1996-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 <stdio.h>
30 
31 #include "mm/memory.hpp"
32 
33 #include "native/llni.hpp"
34 
35 #include "vm/types.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/descriptor.hpp"
42 #include "vm/exceptions.hpp"
43 #include "vm/field.hpp"
44 #include "vm/global.hpp"
45 #include "vm/globals.hpp"
46 #include "vm/loader.hpp"
47 #include "vm/options.hpp"
48 #include "vm/primitive.hpp"
49 #include "vm/references.hpp"
50 #include "vm/string.hpp"
51 #include "vm/suck.hpp"
52 #include "vm/utf8.hpp"
53 #include "vm/vm.hpp"
54 
55 using namespace cacao;
56 
57 /* field_load ******************************************************************
58 
59  Load everything about a class field from the class file and fill a
60  fieldinfo structure.
61 
62 *******************************************************************************/
63 
64 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
65 
67 {
68  u4 attrnum, i;
69  u4 pindex = field_load_NOVALUE; /* constantvalue_index */
70  Utf8String u;
71 
72  /* Get class. */
73 
74  classinfo *c = cb.get_class();
75 
76  f->clazz = c;
77 
78  /* Get access flags. */
79 
80  if (!cb.check_size(2 + 2 + 2))
81  return false;
82 
83  f->flags = cb.read_u2();
84 
85  /* Get name. */
86 
87  if (!(u = (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_Utf8)))
88  return false;
89 
90  f->name = u;
91 
92  /* Get descriptor. */
93 
94  if (!(u = (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_Utf8)))
95  return false;
96 
97  f->descriptor = u;
98  f->parseddesc = NULL;
99 
100  if (!descpool.add_field(u))
101  return false;
102 
103  /* descriptor_pool_add accepts method descriptors, so we have to
104  check against them here before the call of
105  descriptor_to_basic_type below. */
106 
107  if (u[0] == '(') {
108  exceptions_throw_classformaterror(c, "Method descriptor used for field");
109  return false;
110  }
111 
112 #ifdef ENABLE_VERIFIER
113  if (opt_verify) {
114  /* check name */
115  if (!f->name.is_valid_name() || f->name[0] == '<') {
117  "Illegal Field name \"%s\"",
118  f->name.begin());
119  return false;
120  }
121 
122  /* check flag consistency */
123  i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
124 
125  if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
126  ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
128  "Illegal field modifiers: 0x%X",
129  f->flags);
130  return false;
131  }
132 
133  if (c->flags & ACC_INTERFACE) {
134  if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
135  != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
136  f->flags & ACC_TRANSIENT) {
138  "Illegal field modifiers: 0x%X",
139  f->flags);
140  return false;
141  }
142  }
143  }
144 #endif /* ENABLE_VERIFIER */
145 
146  /* data type */
147 
149 
150  /* For static-fields allocate memory for the value and set the
151  value to 0. */
152 
153  if (f->flags & ACC_STATIC) {
154  switch (f->type) {
155  case TYPE_INT:
156  case TYPE_LNG:
157  case TYPE_FLT:
158  case TYPE_DBL:
159  f->value = NEW(imm_union);
160  break;
161 
162  case TYPE_ADR:
163 #if !defined(ENABLE_GC_BOEHM)
164  f->value = NEW(imm_union);
165 #else
167 #endif
168  break;
169 
170  default:
171  vm_abort("field_load: invalid field type %d", f->type);
172  }
173 
174  /* Set the field to zero, for float and double fields set the
175  correct 0.0 value. */
176 
177  switch (f->type) {
178  case TYPE_INT:
179  case TYPE_LNG:
180  case TYPE_ADR:
181  f->value->l = 0;
182  break;
183 
184  case TYPE_FLT:
185  f->value->f = 0.0;
186  break;
187 
188  case TYPE_DBL:
189  f->value->d = 0.0;
190  break;
191  }
192  }
193  else {
194  /* For instance-fields set the offset to 0. */
195 
196  f->offset = 0;
197 
198  /* For final fields, which are not static, we need a value
199  structure. */
200 
201  if (f->flags & ACC_FINAL) {
202  f->value = NEW(imm_union);
203  /* XXX hack */
204  f->value->l = 0;
205  }
206 
207  switch (f->type) {
208  case TYPE_ADR:
210  break;
211  }
212  }
213 
214  /* read attributes */
215 
216  if (!cb.check_size(2))
217  return false;
218 
219  attrnum = cb.read_u2();
220 
221  for (i = 0; i < attrnum; i++) {
222  if (!cb.check_size(2))
223  return false;
224 
225  if (!(u = (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_Utf8)))
226  return false;
227 
228  if (u == utf8::ConstantValue) {
229  if (!cb.check_size(4 + 2))
230  return false;
231 
232  /* check attribute length */
233 
234  if (cb.read_u4() != 2) {
235  exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
236  return false;
237  }
238 
239  /* constant value attribute */
240 
241  if (pindex != field_load_NOVALUE) {
242  exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
243  return false;
244  }
245 
246  /* index of value in constantpool */
247 
248  pindex = cb.read_u2();
249 
250  /* initialize field with value from constantpool */
251 
252  switch (f->type) {
253  case TYPE_INT: {
254  int32_t *ci;
255 
256  if (!(ci = (int32_t*) class_getconstant(c, pindex, CONSTANT_Integer)))
257  return false;
258 
259  f->value->i = *ci;
260  }
261  break;
262 
263  case TYPE_LNG: {
264  int64_t *cl;
265 
266  if (!(cl = (int64_t*) class_getconstant(c, pindex, CONSTANT_Long)))
267  return false;
268 
269  f->value->l = *cl;
270  }
271  break;
272 
273  case TYPE_FLT: {
274  float *cf;
275 
276  if (!(cf = (float*) class_getconstant(c, pindex, CONSTANT_Float)))
277  return false;
278 
279  f->value->f = *cf;
280  }
281  break;
282 
283  case TYPE_DBL: {
284  double *cd;
285 
286  if (!(cd = (double*) class_getconstant(c, pindex, CONSTANT_Double)))
287  return false;
288 
289  f->value->d = *cd;
290  }
291  break;
292 
293  case TYPE_ADR:
294  if (!(u = (utf*) class_getconstant(c, pindex, CONSTANT_String)))
295  return false;
296 
297  /* Create Java-string from compressed UTF8-string. */
298 
300  linker_create_string_later(reinterpret_cast<java_object_t**>(&f->value->a), u);
301  else
302  f->value->a = JavaString::literal(u);
303  break;
304 
305  default:
306  vm_abort("field_load: invalid field type %d", f->type);
307  }
308  }
309 #if defined(ENABLE_JAVASE)
310  else if (u == utf8::Signature) {
311  /* Signature */
312 
313  // TODO: change fieldinfo.signature to Utf8String
314  // and use it directly
315 
317 
318  if (!loader_load_attribute_signature(cb, signature)) {
319  return false;
320  }
321 
322  f->signature = signature;
323  }
324 
325 #if defined(ENABLE_ANNOTATIONS)
326  else if (u == utf8::RuntimeVisibleAnnotations) {
327  /* RuntimeVisibleAnnotations */
329  return false;
330  }
331  else if (u == utf8::RuntimeInvisibleAnnotations) {
332  /* RuntimeInvisibleAnnotations */
334  return false;
335  }
336 #endif
337 #endif
338  else {
339  /* unknown attribute */
340 
342  return false;
343  }
344  }
345 
346  /* everything was ok */
347 
348  return true;
349 }
350 
351 
352 /* field_get_type **************************************************************
353 
354  Returns the type of the field as class.
355 
356 *******************************************************************************/
357 
359 {
360  typedesc *td;
361  Utf8String u;
362  classinfo *c;
363 
364  td = f->parseddesc;
365 
366  if (td->type == TYPE_ADR) {
367  assert(td->classref);
368 
369  u = td->classref->name;
370 
371  /* load the class of the field-type with the field's
372  classloader */
373 
375  }
376  else {
378  }
379 
380  return c;
381 }
382 
383 
384 /* field_free ******************************************************************
385 
386  Frees a fields' resources.
387 
388 *******************************************************************************/
389 
391 {
392  /* free memory for fields which have a value */
393 
394  if (f->value)
395 #if defined(ENABLE_GC_BOEHM)
396  if (f->type != TYPE_ADR)
397 #endif
398  FREE(f->value, imm_union);
399 }
400 
401 
402 /* field_get_annotations ******************************************************
403 
404  Get a fields' unparsed annotations in a byte array.
405 
406  IN:
407  f........the field of which the annotations should be returned
408 
409  RETURN VALUE:
410  The unparsed annotations in a byte array (or NULL if there aren't any).
411 
412 *******************************************************************************/
413 
415 {
416 #if defined(ENABLE_ANNOTATIONS)
417  classinfo *c; /* declaring class */
418  int slot; /* slot of this field */
419  java_handle_t *field_annotations; /* array of unparsed */
420  /* annotations of all fields of the declaring class */
421 
422  c = f->clazz;
423  slot = f - c->fields;
424 
425  LLNI_classinfo_field_get(c, field_annotations, field_annotations);
426 
427  ObjectArray oa(field_annotations);
428 
429  /* the field_annotations array might be shorter then the field
430  * count if the fields above a certain index have no annotations.
431  */
432  if (field_annotations != NULL && oa.get_length() > slot) {
433  return (java_handle_bytearray_t*) oa.get_element(slot);
434  } else {
435  return NULL;
436  }
437 #else
438  return NULL;
439 #endif
440 }
441 
442 
443 /* field_printflags ************************************************************
444 
445  (debugging only)
446 
447 *******************************************************************************/
448 
449 #if !defined(NDEBUG)
451 {
452  if (f == NULL) {
453  printf("NULL");
454  return;
455  }
456 
457  if (f->flags & ACC_PUBLIC) printf(" PUBLIC");
458  if (f->flags & ACC_PRIVATE) printf(" PRIVATE");
459  if (f->flags & ACC_PROTECTED) printf(" PROTECTED");
460  if (f->flags & ACC_STATIC) printf(" STATIC");
461  if (f->flags & ACC_FINAL) printf(" FINAL");
462  if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
463  if (f->flags & ACC_VOLATILE) printf(" VOLATILE");
464  if (f->flags & ACC_TRANSIENT) printf(" TRANSIENT");
465  if (f->flags & ACC_NATIVE) printf(" NATIVE");
466  if (f->flags & ACC_INTERFACE) printf(" INTERFACE");
467  if (f->flags & ACC_ABSTRACT) printf(" ABSTRACT");
468 }
469 #endif
470 
471 
472 /* field_print *****************************************************************
473 
474  (debugging only)
475 
476 *******************************************************************************/
477 
478 #if !defined(NDEBUG)
480 {
481  if (f == NULL) {
482  printf("(fieldinfo*)NULL");
483  return;
484  }
485 
487  printf(".");
489  printf(" ");
491 
492  field_printflags(f);
493 
494  if (!(f->flags & ACC_STATIC)) {
495  printf(", offset: %d", f->offset);
496  }
497 }
498 #endif
499 
500 
501 /* field_println ***************************************************************
502 
503  (debugging only)
504 
505 *******************************************************************************/
506 
507 #if !defined(NDEBUG)
509 {
510  field_print(f);
511  printf("\n");
512 }
513 #endif
514 
515 /* field_fieldref_print ********************************************************
516 
517  (debugging only)
518 
519 *******************************************************************************/
520 
521 #if !defined(NDEBUG)
523 {
524  if (fr == NULL) {
525  printf("(constant_FMIref *)NULL");
526  return;
527  }
528 
529  if (fr->is_resolved()) {
530  printf("<field> ");
531  field_print(fr->p.field);
532  }
533  else {
534  printf("<fieldref> ");
536  printf(".");
538  printf(" ");
540  }
541 }
542 #endif
543 
544 /* field_fieldref_println ******************************************************
545 
546  (debugging only)
547 
548 *******************************************************************************/
549 
550 #if !defined(NDEBUG)
552 {
554  printf("\n");
555 }
556 #endif
557 
558 /*
559  * These are local overrides for various environment variables in Emacs.
560  * Please do not remove this and leave it at the end of the file, where
561  * Emacs will automagically detect them.
562  * ---------------------------------------------------------------------
563  * Local variables:
564  * mode: c++
565  * indent-tabs-mode: t
566  * c-basic-offset: 4
567  * tab-width: 4
568  * End:
569  * vim:noexpandtab:sw=4:ts=4:
570  */
jlong jlong jlong jlong jint jmethodID jint slot
Definition: jvmti.h:497
float f
Definition: global.hpp:56
Utf8String name
Definition: field.hpp:61
#define field_load_NOVALUE
Definition: field.cpp:64
void * class_getconstant(classinfo *c, u4 pos, ConstantPoolTag ctype)
Definition: class.cpp:679
double d
Definition: global.hpp:57
#define NEW(type)
Definition: memory.hpp:93
static classinfo * get_class_by_type(int type)
Returns the primitive class of the given type.
Definition: primitive.cpp:253
void * a
Definition: global.hpp:58
#define FREE(ptr, type)
Definition: memory.hpp:94
classinfo * field_get_type(fieldinfo *f)
Definition: field.cpp:358
void utf_display_printable_ascii_classname(Utf8String u)
Definition: utf8.cpp:552
classloader_t * classloader
Definition: class.hpp:151
Actual implementation of access class for Java Object arrays.
Definition: array.hpp:381
T get_element(int32_t index)
Definition: array.hpp:238
union constant_FMIref::@26 p
void field_println(fieldinfo *f)
Definition: field.cpp:508
bool annotation_load_field_attribute_runtimeinvisibleannotations(ClassBuffer &cb, fieldinfo *f)
Definition: annotation.cpp:576
void exceptions_throw_classformaterror(classinfo *c, const char *message,...)
Definition: exceptions.cpp:634
#define GCNEW_UNCOLLECTABLE(type, num)
Definition: memory.hpp:115
void field_fieldref_print(constant_FMIref *fr)
Definition: field.cpp:522
const Utf8String name
Definition: references.hpp:103
Utf8String signature
Definition: method.hpp:74
bool loader_skip_attribute_body(ClassBuffer &cb)
Definition: loader.cpp:499
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
fieldinfo * fields
Definition: class.hpp:110
bool add_field(Utf8String desc)
Definition: descriptor.cpp:543
Utf8String descriptor
Definition: field.hpp:62
uint16_t read_u2()
Definition: suck.hpp:150
bool is_resolved() const
Definition: references.hpp:107
int32_t get_length() const
Definition: array.hpp:189
void linker_create_string_later(java_object_t **a, Utf8String u)
Definition: linker.cpp:1187
int32_t offset
Definition: field.hpp:66
void field_free(fieldinfo *f)
Definition: field.cpp:390
void field_print(fieldinfo *f)
Definition: field.cpp:479
Utf8String name
Definition: class.hpp:91
s4 flags
Definition: field.hpp:59
imm_union * value
Definition: field.hpp:67
bool is_valid_name() const
Definition: utf8.cpp:393
s4 flags
Definition: class.hpp:90
typedesc * parseddesc
Definition: field.hpp:64
MIIterator i
Fieldref, Methodref and InterfaceMethodref.
Definition: references.hpp:86
#define LLNI_classinfo_field_get(cls, field, variable)
Definition: llni.hpp:82
classinfo * clazz
Definition: field.hpp:55
Type descriptor_to_basic_type(Utf8String descriptor)
Definition: descriptor.cpp:978
const Utf8String descriptor
Definition: references.hpp:104
bool loader_load_attribute_signature(ClassBuffer &cb, Utf8String &signature)
Definition: loader.cpp:960
bool opt_verify
Definition: options.cpp:103
uint32_t read_u4()
Definition: suck.hpp:155
void utf_display_printable_ascii(Utf8String u)
Definition: utf8.cpp:532
uint32_t u4
Definition: types.hpp:46
java_handle_bytearray_t * field_get_annotations(fieldinfo *f)
Definition: field.cpp:414
classinfo * class_java_lang_String
Definition: globals.cpp:39
classinfo * get_class() const
Definition: suck.hpp:117
byte_iterator begin() const
Definition: utf8.hpp:106
s4 type
Definition: field.hpp:60
constant_classref * classref
Definition: references.hpp:97
classinfo * load_class_from_classloader(Utf8String name, classloader_t *cl)
Definition: loader.cpp:1071
bool annotation_load_field_attribute_runtimevisibleannotations(ClassBuffer &cb, fieldinfo *f)
Definition: annotation.cpp:527
bool field_load(ClassBuffer &cb, fieldinfo *f, DescriptorPool &descpool)
Definition: field.cpp:66
bool check_size(size_t sz)
Assert that at least &lt;sz&gt; bytes are left to read.
Definition: suck.hpp:135
void field_printflags(fieldinfo *f)
Definition: field.cpp:450
void field_fieldref_println(constant_FMIref *fr)
Definition: field.cpp:551
fieldinfo * field
Definition: references.hpp:100
Utf8String signature
Definition: field.hpp:63
PrimitiveType primitivetype
Definition: descriptor.hpp:137
static JavaString literal(Utf8String)
Definition: string.cpp:257
const Utf8String name
Definition: references.hpp:48
#define printf(...)
Definition: ssa2.cpp:40
constant_classref * classref
Definition: descriptor.hpp:135