* src/vmcore/primitive.c: Removed.
[cacao.git] / src / vmcore / field.c
1 /* src/vmcore/field.c - field functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: field.c 8288 2007-08-10 15:12:00Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34 #include <stdio.h>
35
36 #include "mm/memory.h"
37
38 #include "vm/types.h"
39
40 #include "mm/memory.h"
41
42 #include "vm/exceptions.h"
43 #include "vm/global.h"
44 #include "vm/primitive.h"
45 #include "vm/stringlocal.h"
46 #include "vm/vm.h"
47
48 #include "vmcore/annotation.h"
49 #include "vmcore/class.h"
50 #include "vmcore/descriptor.h"
51 #include "vmcore/field.h"
52 #include "vmcore/loader.h"
53 #include "vmcore/options.h"
54 #include "vmcore/references.h"
55 #include "vmcore/suck.h"
56 #include "vmcore/utf8.h"
57
58
59 /* field_load ******************************************************************
60
61    Load everything about a class field from the class file and fill a
62    fieldinfo structure.
63
64 *******************************************************************************/
65
66 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
67
68 bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
69 {
70         classinfo *c;
71         u4 attrnum, i;
72         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
73         utf *u;
74
75         /* Get class. */
76
77         c = cb->class;
78
79         f->class = c;
80
81         /* Get access flags. */
82
83         if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
84                 return false;
85
86         f->flags = suck_u2(cb);
87
88         /* Get name. */
89
90         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
91                 return false;
92
93         f->name = u;
94
95         /* Get descriptor. */
96
97         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
98                 return false;
99
100         f->descriptor = u;
101         f->parseddesc = NULL;
102
103         if (!descriptor_pool_add(descpool, u, NULL))
104                 return false;
105
106         /* descriptor_pool_add accepts method descriptors, so we have to
107            check against them here before the call of
108            descriptor_to_basic_type below. */
109
110         if (u->text[0] == '(') {
111                 exceptions_throw_classformaterror(c, "Method descriptor used for field");
112                 return false;
113         }
114
115 #ifdef ENABLE_VERIFIER
116         if (opt_verify) {
117                 /* check name */
118                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
119                         exceptions_throw_classformaterror(c,
120                                                                                           "Illegal Field name \"%s\"",
121                                                                                           f->name->text);
122                         return false;
123                 }
124
125                 /* check flag consistency */
126                 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
127
128                 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
129                         ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
130                         exceptions_throw_classformaterror(c,
131                                                                                           "Illegal field modifiers: 0x%X",
132                                                                                           f->flags);
133                         return false;
134                 }
135
136                 if (c->flags & ACC_INTERFACE) {
137                         if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
138                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
139                                 f->flags & ACC_TRANSIENT) {
140                                 exceptions_throw_classformaterror(c,
141                                                                                                   "Illegal field modifiers: 0x%X",
142                                                                                                   f->flags);
143                                 return false;
144                         }
145                 }
146         }
147 #endif /* ENABLE_VERIFIER */
148
149         /* data type */
150
151         f->type = descriptor_to_basic_type(f->descriptor);
152
153         /* For static-fields allocate memory for the value and set the
154            value to 0. */
155
156         if (f->flags & ACC_STATIC) {
157                 switch (f->type) {
158                 case TYPE_INT:
159                 case TYPE_LNG:
160                 case TYPE_FLT:
161                 case TYPE_DBL:
162                         f->value = NEW(imm_union);
163                         break;
164
165                 case TYPE_ADR:
166 #if defined(ENABLE_GC_CACAO)
167                         f->value = NEW(imm_union);
168 #else
169                         f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
170 #endif
171                         break;
172
173                 default:
174                         vm_abort("field_load: invalid field type %d", f->type);
175                 }
176
177                 /* Set the field to zero, for float and double fields set the
178                    correct 0.0 value. */
179
180                 switch (f->type) {
181                 case TYPE_INT:
182                 case TYPE_LNG:
183                 case TYPE_ADR:
184                         f->value->l = 0;
185                         break;
186
187                 case TYPE_FLT:
188                         f->value->f = 0.0;
189                         break;
190
191                 case TYPE_DBL:
192                         f->value->d = 0.0;
193                         break;
194                 }
195         }
196         else {
197                 /* For instance-fields set the offset to 0. */
198
199                 f->offset = 0;
200
201                 /* For final fields, which are not static, we need a value
202                    structure. */
203
204                 if (f->flags & ACC_FINAL) {
205                         f->value = NEW(imm_union);
206                         /* XXX hack */
207                         f->value->l = 0;
208                 }
209
210                 switch (f->type) {
211                 case TYPE_ADR:
212                         c->flags |= ACC_CLASS_HAS_POINTERS;
213                         break;
214                 }
215         }
216
217         /* read attributes */
218
219         if (!suck_check_classbuffer_size(cb, 2))
220                 return false;
221
222         attrnum = suck_u2(cb);
223
224         for (i = 0; i < attrnum; i++) {
225                 if (!suck_check_classbuffer_size(cb, 2))
226                         return false;
227
228                 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
229                         return false;
230
231                 if (u == utf_ConstantValue) {
232                         if (!suck_check_classbuffer_size(cb, 4 + 2))
233                                 return false;
234
235                         /* check attribute length */
236
237                         if (suck_u4(cb) != 2) {
238                                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
239                                 return false;
240                         }
241                         
242                         /* constant value attribute */
243
244                         if (pindex != field_load_NOVALUE) {
245                                 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
246                                 return false;
247                         }
248                         
249                         /* index of value in constantpool */
250
251                         pindex = suck_u2(cb);
252                 
253                         /* initialize field with value from constantpool */             
254
255                         switch (f->type) {
256                         case TYPE_INT: {
257                                 constant_integer *ci; 
258
259                                 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
260                                         return false;
261
262                                 f->value->i = ci->value;
263                         }
264                         break;
265                                         
266                         case TYPE_LNG: {
267                                 constant_long *cl; 
268
269                                 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
270                                         return false;
271
272                                 f->value->l = cl->value;
273                         }
274                         break;
275
276                         case TYPE_FLT: {
277                                 constant_float *cf;
278
279                                 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
280                                         return false;
281
282                                 f->value->f = cf->value;
283                         }
284                         break;
285                                                                                         
286                         case TYPE_DBL: {
287                                 constant_double *cd;
288
289                                 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
290                                         return false;
291
292                                 f->value->d = cd->value;
293                         }
294                         break;
295                                                 
296                         case TYPE_ADR:
297                                 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
298                                         return false;
299
300                                 /* Create Java-string from compressed UTF8-string. */
301
302                                 f->value->a = literalstring_new(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 == utf_Signature) {
311                         /* Signature */
312
313                         if (!loader_load_attribute_signature(cb, &(f->signature)))
314                                 return false;
315                 }
316
317 #if defined(ENABLE_ANNOTATIONS)
318                 else if (u == utf_RuntimeVisibleAnnotations) {
319                         /* RuntimeVisibleAnnotations */
320                         if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
321                                 return false;
322                 }
323                 else if (u == utf_RuntimeInvisibleAnnotations) {
324                         /* RuntimeInvisibleAnnotations */
325                         if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
326                                 return false;
327                 }
328 #endif
329 #endif
330                 else {
331                         /* unknown attribute */
332
333                         if (!loader_skip_attribute_body(cb))
334                                 return false;
335                 }
336         }
337
338         /* everything was ok */
339
340         return true;
341 }
342
343
344 /* field_get_type **************************************************************
345
346    Returns the type of the field as class.
347
348 *******************************************************************************/
349
350 classinfo *field_get_type(fieldinfo *f)
351 {
352         typedesc  *td;
353         utf       *u;
354         classinfo *c;
355
356         td = f->parseddesc;
357
358         if (td->type == TYPE_ADR) {
359                 assert(td->classref);
360
361                 u = td->classref->name;
362
363                 /* load the class of the field-type with the field's
364                    classloader */
365
366                 c = load_class_from_classloader(u, f->class->classloader);
367         }
368         else {
369                 c = primitive_class_get_by_type(td->decltype);
370         }
371
372         return c;
373 }
374
375
376 /* field_free ******************************************************************
377
378    Frees a fields' resources.
379
380 *******************************************************************************/
381
382 void field_free(fieldinfo *f)
383 {
384         /* empty */
385 }
386
387
388 #if defined(ENABLE_ANNOTATIONS)
389 /* field_get_annotations ******************************************************
390
391    Gets a fields' annotations (or NULL if none).
392
393 *******************************************************************************/
394
395 annotation_bytearray_t *field_get_annotations(fieldinfo *f)
396 {
397         classinfo *c = f->class;
398         int slot = f - c->fields;
399
400         if (c->field_annotations != NULL &&
401             c->field_annotations->size > slot) {
402                 return c->field_annotations->data[slot];
403         }
404
405         return NULL;
406 }
407 #endif
408
409
410 /* field_printflags ************************************************************
411
412    (debugging only)
413
414 *******************************************************************************/
415
416 #if !defined(NDEBUG)
417 void field_printflags(fieldinfo *f)
418 {
419         if (f == NULL) {
420                 printf("NULL");
421                 return;
422         }
423
424         if (f->flags & ACC_PUBLIC)       printf(" PUBLIC");
425         if (f->flags & ACC_PRIVATE)      printf(" PRIVATE");
426         if (f->flags & ACC_PROTECTED)    printf(" PROTECTED");
427         if (f->flags & ACC_STATIC)       printf(" STATIC");
428         if (f->flags & ACC_FINAL)        printf(" FINAL");
429         if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
430         if (f->flags & ACC_VOLATILE)     printf(" VOLATILE");
431         if (f->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
432         if (f->flags & ACC_NATIVE)       printf(" NATIVE");
433         if (f->flags & ACC_INTERFACE)    printf(" INTERFACE");
434         if (f->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
435 }
436 #endif
437
438
439 /* field_print *****************************************************************
440
441    (debugging only)
442
443 *******************************************************************************/
444
445 #if !defined(NDEBUG)
446 void field_print(fieldinfo *f)
447 {
448         if (f == NULL) {
449                 printf("(fieldinfo*)NULL");
450                 return;
451         }
452
453         utf_display_printable_ascii_classname(f->class->name);
454         printf(".");
455         utf_display_printable_ascii(f->name);
456         printf(" ");
457         utf_display_printable_ascii(f->descriptor);     
458
459         field_printflags(f);
460 }
461 #endif
462
463
464 /* field_println ***************************************************************
465
466    (debugging only)
467
468 *******************************************************************************/
469
470 #if !defined(NDEBUG)
471 void field_println(fieldinfo *f)
472 {
473         field_print(f);
474         printf("\n");
475 }
476 #endif
477
478 /* field_fieldref_print ********************************************************
479
480    (debugging only)
481
482 *******************************************************************************/
483
484 #if !defined(NDEBUG)
485 void field_fieldref_print(constant_FMIref *fr)
486 {
487         if (fr == NULL) {
488                 printf("(constant_FMIref *)NULL");
489                 return;
490         }
491
492         if (IS_FMIREF_RESOLVED(fr)) {
493                 printf("<field> ");
494                 field_print(fr->p.field);
495         }
496         else {
497                 printf("<fieldref> ");
498                 utf_display_printable_ascii_classname(fr->p.classref->name);
499                 printf(".");
500                 utf_display_printable_ascii(fr->name);
501                 printf(" ");
502                 utf_display_printable_ascii(fr->descriptor);
503         }
504 }
505 #endif
506
507 /* field_fieldref_println ******************************************************
508
509    (debugging only)
510
511 *******************************************************************************/
512
513 #if !defined(NDEBUG)
514 void field_fieldref_println(constant_FMIref *fr)
515 {
516         field_fieldref_print(fr);
517         printf("\n");
518 }
519 #endif
520
521 /*
522  * These are local overrides for various environment variables in Emacs.
523  * Please do not remove this and leave it at the end of the file, where
524  * Emacs will automagically detect them.
525  * ---------------------------------------------------------------------
526  * Local variables:
527  * mode: c
528  * indent-tabs-mode: t
529  * c-basic-offset: 4
530  * tab-width: 4
531  * End:
532  */