Line data Source code
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 :
66 113368 : bool field_load(ClassBuffer& cb, fieldinfo *f, DescriptorPool& descpool)
67 : {
68 : u4 attrnum, i;
69 113368 : u4 pindex = field_load_NOVALUE; /* constantvalue_index */
70 113368 : Utf8String u;
71 :
72 : /* Get class. */
73 :
74 113368 : classinfo *c = cb.get_class();
75 :
76 113368 : f->clazz = c;
77 :
78 : /* Get access flags. */
79 :
80 113368 : if (!cb.check_size(2 + 2 + 2))
81 0 : return false;
82 :
83 113368 : f->flags = cb.read_u2();
84 :
85 : /* Get name. */
86 :
87 113368 : if (!(u = (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_Utf8)))
88 0 : return false;
89 :
90 113368 : f->name = u;
91 :
92 : /* Get descriptor. */
93 :
94 113368 : if (!(u = (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_Utf8)))
95 0 : return false;
96 :
97 113368 : f->descriptor = u;
98 113368 : f->parseddesc = NULL;
99 :
100 113368 : if (!descpool.add_field(u))
101 0 : 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 113368 : if (u[0] == '(') {
108 0 : exceptions_throw_classformaterror(c, "Method descriptor used for field");
109 0 : return false;
110 : }
111 :
112 : #ifdef ENABLE_VERIFIER
113 113368 : if (opt_verify) {
114 : /* check name */
115 113368 : if (!f->name.is_valid_name() || f->name[0] == '<') {
116 : exceptions_throw_classformaterror(c,
117 : "Illegal Field name \"%s\"",
118 0 : f->name.begin());
119 0 : return false;
120 : }
121 :
122 : /* check flag consistency */
123 113368 : i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
124 :
125 113368 : if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
126 : ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
127 : exceptions_throw_classformaterror(c,
128 : "Illegal field modifiers: 0x%X",
129 0 : f->flags);
130 0 : return false;
131 : }
132 :
133 113368 : if (c->flags & ACC_INTERFACE) {
134 2770 : if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
135 : != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
136 : f->flags & ACC_TRANSIENT) {
137 : exceptions_throw_classformaterror(c,
138 : "Illegal field modifiers: 0x%X",
139 0 : f->flags);
140 0 : return false;
141 : }
142 : }
143 : }
144 : #endif /* ENABLE_VERIFIER */
145 :
146 : /* data type */
147 :
148 113368 : f->type = descriptor_to_basic_type(f->descriptor);
149 :
150 : /* For static-fields allocate memory for the value and set the
151 : value to 0. */
152 :
153 113368 : if (f->flags & ACC_STATIC) {
154 61032 : switch (f->type) {
155 : case TYPE_INT:
156 : case TYPE_LNG:
157 : case TYPE_FLT:
158 : case TYPE_DBL:
159 36335 : f->value = NEW(imm_union);
160 36335 : break;
161 :
162 : case TYPE_ADR:
163 : #if !defined(ENABLE_GC_BOEHM)
164 : f->value = NEW(imm_union);
165 : #else
166 24697 : f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
167 : #endif
168 24697 : break;
169 :
170 : default:
171 0 : 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 61032 : switch (f->type) {
178 : case TYPE_INT:
179 : case TYPE_LNG:
180 : case TYPE_ADR:
181 58473 : f->value->l = 0;
182 58473 : break;
183 :
184 : case TYPE_FLT:
185 1454 : f->value->f = 0.0;
186 1454 : break;
187 :
188 : case TYPE_DBL:
189 1105 : f->value->d = 0.0;
190 : break;
191 : }
192 : }
193 : else {
194 : /* For instance-fields set the offset to 0. */
195 :
196 52336 : f->offset = 0;
197 :
198 : /* For final fields, which are not static, we need a value
199 : structure. */
200 :
201 52336 : if (f->flags & ACC_FINAL) {
202 16708 : f->value = NEW(imm_union);
203 : /* XXX hack */
204 16708 : f->value->l = 0;
205 : }
206 :
207 52336 : switch (f->type) {
208 : case TYPE_ADR:
209 31278 : c->flags |= ACC_CLASS_HAS_POINTERS;
210 : break;
211 : }
212 : }
213 :
214 : /* read attributes */
215 :
216 113368 : if (!cb.check_size(2))
217 0 : return false;
218 :
219 113368 : attrnum = cb.read_u2();
220 :
221 158832 : for (i = 0; i < attrnum; i++) {
222 45464 : if (!cb.check_size(2))
223 0 : return false;
224 :
225 45464 : if (!(u = (utf*) class_getconstant(c, cb.read_u2(), CONSTANT_Utf8)))
226 0 : return false;
227 :
228 45464 : if (u == utf8::ConstantValue) {
229 35864 : if (!cb.check_size(4 + 2))
230 0 : return false;
231 :
232 : /* check attribute length */
233 :
234 35864 : if (cb.read_u4() != 2) {
235 0 : exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
236 0 : return false;
237 : }
238 :
239 : /* constant value attribute */
240 :
241 35864 : if (pindex != field_load_NOVALUE) {
242 0 : exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
243 0 : return false;
244 : }
245 :
246 : /* index of value in constantpool */
247 :
248 35864 : pindex = cb.read_u2();
249 :
250 : /* initialize field with value from constantpool */
251 :
252 35864 : switch (f->type) {
253 : case TYPE_INT: {
254 : int32_t *ci;
255 :
256 24174 : if (!(ci = (int32_t*) class_getconstant(c, pindex, CONSTANT_Integer)))
257 0 : return false;
258 :
259 24174 : f->value->i = *ci;
260 : }
261 24174 : break;
262 :
263 : case TYPE_LNG: {
264 : int64_t *cl;
265 :
266 7934 : if (!(cl = (int64_t*) class_getconstant(c, pindex, CONSTANT_Long)))
267 0 : return false;
268 :
269 7934 : f->value->l = *cl;
270 : }
271 7934 : break;
272 :
273 : case TYPE_FLT: {
274 : float *cf;
275 :
276 1447 : if (!(cf = (float*) class_getconstant(c, pindex, CONSTANT_Float)))
277 0 : return false;
278 :
279 1447 : f->value->f = *cf;
280 : }
281 1447 : break;
282 :
283 : case TYPE_DBL: {
284 : double *cd;
285 :
286 1099 : if (!(cd = (double*) class_getconstant(c, pindex, CONSTANT_Double)))
287 0 : return false;
288 :
289 1099 : f->value->d = *cd;
290 : }
291 1099 : break;
292 :
293 : case TYPE_ADR:
294 1210 : if (!(u = (utf*) class_getconstant(c, pindex, CONSTANT_String)))
295 0 : return false;
296 :
297 : /* Create Java-string from compressed UTF8-string. */
298 :
299 1210 : if (!(class_java_lang_String->flags & CLASS_LINKED))
300 1210 : linker_create_string_later(reinterpret_cast<java_object_t**>(&f->value->a), u);
301 : else
302 0 : f->value->a = JavaString::literal(u);
303 1210 : break;
304 :
305 : default:
306 0 : vm_abort("field_load: invalid field type %d", f->type);
307 : }
308 : }
309 : #if defined(ENABLE_JAVASE)
310 9600 : else if (u == utf8::Signature) {
311 : /* Signature */
312 :
313 : // TODO: change fieldinfo.signature to Utf8String
314 : // and use it directly
315 :
316 9433 : Utf8String signature = f->signature;
317 :
318 9433 : if (!loader_load_attribute_signature(cb, signature)) {
319 0 : return false;
320 : }
321 :
322 9433 : f->signature = signature;
323 : }
324 :
325 : #if defined(ENABLE_ANNOTATIONS)
326 167 : else if (u == utf8::RuntimeVisibleAnnotations) {
327 : /* RuntimeVisibleAnnotations */
328 2 : if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
329 0 : return false;
330 : }
331 165 : else if (u == utf8::RuntimeInvisibleAnnotations) {
332 : /* RuntimeInvisibleAnnotations */
333 0 : if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
334 0 : return false;
335 : }
336 : #endif
337 : #endif
338 : else {
339 : /* unknown attribute */
340 :
341 165 : if (!loader_skip_attribute_body(cb))
342 0 : return false;
343 : }
344 : }
345 :
346 : /* everything was ok */
347 :
348 113368 : return true;
349 : }
350 :
351 :
352 : /* field_get_type **************************************************************
353 :
354 : Returns the type of the field as class.
355 :
356 : *******************************************************************************/
357 :
358 0 : classinfo *field_get_type(fieldinfo *f)
359 : {
360 : typedesc *td;
361 0 : Utf8String u;
362 : classinfo *c;
363 :
364 0 : td = f->parseddesc;
365 :
366 0 : if (td->type == TYPE_ADR) {
367 0 : assert(td->classref);
368 :
369 0 : u = td->classref->name;
370 :
371 : /* load the class of the field-type with the field's
372 : classloader */
373 :
374 0 : c = load_class_from_classloader(u, f->clazz->classloader);
375 : }
376 : else {
377 0 : c = Primitive::get_class_by_type(td->primitivetype);
378 : }
379 :
380 0 : return c;
381 : }
382 :
383 :
384 : /* field_free ******************************************************************
385 :
386 : Frees a fields' resources.
387 :
388 : *******************************************************************************/
389 :
390 2 : void field_free(fieldinfo *f)
391 : {
392 : /* free memory for fields which have a value */
393 :
394 2 : if (f->value)
395 : #if defined(ENABLE_GC_BOEHM)
396 2 : if (f->type != TYPE_ADR)
397 : #endif
398 0 : FREE(f->value, imm_union);
399 2 : }
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 :
414 879 : java_handle_bytearray_t *field_get_annotations(fieldinfo *f)
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 879 : c = f->clazz;
423 879 : slot = f - c->fields;
424 :
425 879 : LLNI_classinfo_field_get(c, field_annotations, field_annotations);
426 :
427 879 : 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 879 : if (field_annotations != NULL && oa.get_length() > slot) {
433 43 : return (java_handle_bytearray_t*) oa.get_element(slot);
434 : } else {
435 836 : return NULL;
436 0 : }
437 : #else
438 : return NULL;
439 : #endif
440 : }
441 :
442 :
443 : /* field_printflags ************************************************************
444 :
445 : (debugging only)
446 :
447 : *******************************************************************************/
448 :
449 : #if !defined(NDEBUG)
450 0 : void field_printflags(fieldinfo *f)
451 : {
452 0 : if (f == NULL) {
453 0 : printf("NULL");
454 0 : return;
455 : }
456 :
457 0 : if (f->flags & ACC_PUBLIC) printf(" PUBLIC");
458 0 : if (f->flags & ACC_PRIVATE) printf(" PRIVATE");
459 0 : if (f->flags & ACC_PROTECTED) printf(" PROTECTED");
460 0 : if (f->flags & ACC_STATIC) printf(" STATIC");
461 0 : if (f->flags & ACC_FINAL) printf(" FINAL");
462 0 : if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
463 0 : if (f->flags & ACC_VOLATILE) printf(" VOLATILE");
464 0 : if (f->flags & ACC_TRANSIENT) printf(" TRANSIENT");
465 0 : if (f->flags & ACC_NATIVE) printf(" NATIVE");
466 0 : if (f->flags & ACC_INTERFACE) printf(" INTERFACE");
467 0 : 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)
479 0 : void field_print(fieldinfo *f)
480 : {
481 0 : if (f == NULL) {
482 0 : printf("(fieldinfo*)NULL");
483 0 : return;
484 : }
485 :
486 0 : utf_display_printable_ascii_classname(f->clazz->name);
487 0 : printf(".");
488 0 : utf_display_printable_ascii(f->name);
489 0 : printf(" ");
490 0 : utf_display_printable_ascii(f->descriptor);
491 :
492 0 : field_printflags(f);
493 :
494 0 : if (!(f->flags & ACC_STATIC)) {
495 0 : 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)
508 0 : void field_println(fieldinfo *f)
509 : {
510 0 : field_print(f);
511 0 : printf("\n");
512 0 : }
513 : #endif
514 :
515 : /* field_fieldref_print ********************************************************
516 :
517 : (debugging only)
518 :
519 : *******************************************************************************/
520 :
521 : #if !defined(NDEBUG)
522 0 : void field_fieldref_print(constant_FMIref *fr)
523 : {
524 0 : if (fr == NULL) {
525 0 : printf("(constant_FMIref *)NULL");
526 0 : return;
527 : }
528 :
529 0 : if (fr->is_resolved()) {
530 0 : printf("<field> ");
531 0 : field_print(fr->p.field);
532 : }
533 : else {
534 0 : printf("<fieldref> ");
535 0 : utf_display_printable_ascii_classname(fr->p.classref->name);
536 0 : printf(".");
537 0 : utf_display_printable_ascii(fr->name);
538 0 : printf(" ");
539 0 : utf_display_printable_ascii(fr->descriptor);
540 : }
541 : }
542 : #endif
543 :
544 : /* field_fieldref_println ******************************************************
545 :
546 : (debugging only)
547 :
548 : *******************************************************************************/
549 :
550 : #if !defined(NDEBUG)
551 0 : void field_fieldref_println(constant_FMIref *fr)
552 : {
553 0 : field_fieldref_print(fr);
554 0 : printf("\n");
555 0 : }
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 : */
|