* src/vm/global.h (PRIMITIVETYPE_*): Removed.
[cacao.git] / src / vm / builtin.c
1 /* src/vm/builtin.c - functions for unsupported operations
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    Contains C functions for JavaVM Instructions that cannot be
26    translated to machine language directly. Consequently, the
27    generated machine code for these instructions contains function
28    calls instead of machine instructions, using the C calling
29    convention.
30
31    $Id: builtin.c 8060 2007-06-10 20:00:40Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39 #include <errno.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/time.h>
43
44 #include "vm/types.h"
45
46 #include "arch.h"
47 #include "md-abi.h"
48
49 #include "fdlibm/fdlibm.h"
50 #if defined(__CYGWIN__) && defined(Bias)
51 # undef Bias
52 #endif
53
54 #include "mm/gc-common.h"
55 #include "mm/memory.h"
56
57 #include "native/jni.h"
58 #include "native/include/java_lang_String.h"
59 #include "native/include/java_lang_Throwable.h"
60
61 #include "threads/lock-common.h"
62
63 #include "toolbox/logging.h"
64 #include "toolbox/util.h"
65
66 #include "vm/builtin.h"
67 #include "vm/cycles-stats.h"
68 #include "vm/exceptions.h"
69 #include "vm/global.h"
70 #include "vm/initialize.h"
71 #include "vm/stringlocal.h"
72
73 #include "vm/jit/asmpart.h"
74 #include "vm/jit/patcher.h"
75
76 #include "vmcore/class.h"
77 #include "vmcore/loader.h"
78 #include "vmcore/options.h"
79 #include "vmcore/primitive.h"
80 #include "vmcore/rt-timing.h"
81
82 #if defined(ENABLE_VMLOG)
83 #include <vmlog_cacao.h>
84 #endif
85
86 #if defined(ENABLE_DEBUG_FILTER)
87 #       include "vm/jit/show.h"
88 #endif
89
90 /* include builtin tables *****************************************************/
91
92 #include "vm/builtintable.inc"
93
94
95 CYCLES_STATS_DECLARE(builtin_new         ,100,5)
96 CYCLES_STATS_DECLARE(builtin_overhead    , 80,1)
97
98 /* builtintable_init ***********************************************************
99
100    Parse the descriptors of builtin functions and create the parsed
101    descriptors.
102
103 *******************************************************************************/
104
105 static bool builtintable_init(void)
106 {
107         descriptor_pool    *descpool;
108         s4                  dumpsize;
109         builtintable_entry *bte;
110
111         /* mark start of dump memory area */
112
113         dumpsize = dump_size();
114
115         /* create a new descriptor pool */
116
117         descpool = descriptor_pool_new(class_java_lang_Object);
118
119         /* add some entries we need */
120
121         if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
122                 return false;
123
124         if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
125                 return false;
126
127         /* first add all descriptors to the pool */
128
129         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
130                 /* create a utf8 string from descriptor */
131
132                 bte->descriptor = utf_new_char(bte->cdescriptor);
133
134                 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
135                         /* release dump area */
136
137                         dump_release(dumpsize);
138
139                         return false;
140                 }
141         }
142
143         for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
144                 bte->descriptor = utf_new_char(bte->cdescriptor);
145
146                 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
147                         dump_release(dumpsize);
148                         return false;
149                 }
150         }
151
152         for (bte = builtintable_function; bte->fp != NULL; bte++) {
153                 bte->classname  = utf_new_char(bte->cclassname);
154                 bte->name       = utf_new_char(bte->cname);
155                 bte->descriptor = utf_new_char(bte->cdescriptor);
156
157                 if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
158                         dump_release(dumpsize);
159                         return false;
160                 }
161         }
162
163         /* create the class reference table */
164
165         (void) descriptor_pool_create_classrefs(descpool, NULL);
166
167         /* allocate space for the parsed descriptors */
168
169         descriptor_pool_alloc_parsed_descriptors(descpool);
170
171         /* now parse all descriptors */
172
173         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
174                 /* parse the descriptor, builtin is always static (no `this' pointer) */
175
176                 bte->md = descriptor_pool_parse_method_descriptor(descpool,
177                                                                                                                   bte->descriptor,
178                                                                                                                   ACC_STATIC, NULL);
179         }
180
181         for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
182                 bte->md = descriptor_pool_parse_method_descriptor(descpool,
183                                                                                                                   bte->descriptor,
184                                                                                                                   ACC_STATIC, NULL);
185         }
186
187         for (bte = builtintable_function; bte->fp != NULL; bte++) {
188                 bte->md = descriptor_pool_parse_method_descriptor(descpool,
189                                                                                                                   bte->descriptor,
190                                                                                                                   ACC_STATIC, NULL);
191         }
192
193         /* release dump area */
194
195         dump_release(dumpsize);
196
197         return true;
198 }
199
200
201 /* builtintable_comparator *****************************************************
202
203    qsort comparator for the automatic builtin table.
204
205 *******************************************************************************/
206
207 static int builtintable_comparator(const void *a, const void *b)
208 {
209         builtintable_entry *bte1;
210         builtintable_entry *bte2;
211
212         bte1 = (builtintable_entry *) a;
213         bte2 = (builtintable_entry *) b;
214
215         return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
216 }
217
218
219 /* builtintable_sort_automatic *************************************************
220
221    Sorts the automatic builtin table.
222
223 *******************************************************************************/
224
225 static void builtintable_sort_automatic(void)
226 {
227         s4 entries;
228
229         /* calculate table size statically (`- 1' comment see builtintable.inc) */
230
231         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
232
233         qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
234                   builtintable_comparator);
235 }
236
237
238 /* builtin_init ****************************************************************
239
240    Initialize the global table of builtin functions.
241
242 *******************************************************************************/
243
244 bool builtin_init(void)
245 {
246         /* initialize the builtin tables */
247
248         if (!builtintable_init())
249                 return false;
250
251         /* sort builtin tables */
252
253         builtintable_sort_automatic();
254
255         return true;
256 }
257
258
259 /* builtintable_get_internal ***************************************************
260
261    Finds an entry in the builtintable for internal functions and
262    returns the a pointer to the structure.
263
264 *******************************************************************************/
265
266 builtintable_entry *builtintable_get_internal(functionptr fp)
267 {
268         builtintable_entry *bte;
269
270         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
271                 if (bte->fp == fp)
272                         return bte;
273         }
274
275         return NULL;
276 }
277
278
279 /* builtintable_get_automatic **************************************************
280
281    Finds an entry in the builtintable for functions which are replaced
282    automatically and returns the a pointer to the structure.
283
284 *******************************************************************************/
285
286 builtintable_entry *builtintable_get_automatic(s4 opcode)
287 {
288         builtintable_entry *first;
289         builtintable_entry *last;
290         builtintable_entry *middle;
291         s4                  half;
292         s4                  entries;
293
294         /* calculate table size statically (`- 1' comment see builtintable.inc) */
295
296         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
297
298         first = builtintable_automatic;
299         last = builtintable_automatic + entries;
300
301         while (entries > 0) {
302                 half = entries / 2;
303                 middle = first + half;
304
305                 if (middle->opcode < opcode) {
306                         first = middle + 1;
307                         entries -= half + 1;
308                 } else
309                         entries = half;
310         }
311
312         return (first != last ? first : NULL);
313 }
314
315
316 /* builtintable_replace_function ***********************************************
317
318    XXX
319
320 *******************************************************************************/
321
322 #if defined(ENABLE_JIT)
323 bool builtintable_replace_function(void *iptr_)
324 {
325         constant_FMIref    *mr;
326         builtintable_entry *bte;
327         instruction        *iptr;
328
329         iptr = (instruction *) iptr_; /* twisti will kill me ;) */
330
331         /* get name and descriptor of the function */
332
333         switch (iptr->opc) {
334         case ICMD_INVOKESTATIC:
335                 /* The instruction MUST be resolved, otherwise we run into
336                    lazy loading troubles.  Anyway, we should/can only replace
337                    very VM-close functions. */
338
339                 if (INSTRUCTION_IS_UNRESOLVED(iptr))
340                         return false;
341
342                 mr = iptr->sx.s23.s3.fmiref;
343                 break;  
344
345         default:
346                 return false;
347         }
348
349         /* search the function table */
350
351         for (bte = builtintable_function; bte->fp != NULL; bte++) {
352                 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
353                         (mr->name             == bte->name) &&
354                         (mr->descriptor       == bte->descriptor)) {
355
356                         /* set the values in the instruction */
357
358                         iptr->opc   = bte->opcode;
359                         iptr->sx.s23.s3.bte = bte;
360                         if (bte->checkexception)
361                                 iptr->flags.bits |= INS_FLAG_CHECK;
362                         else
363                                 iptr->flags.bits &= ~INS_FLAG_CHECK;
364
365                         return true;
366                 }
367         }
368
369         return false;
370 }
371 #endif /* defined(ENABLE_JIT) */
372
373
374 /*****************************************************************************
375                                                                 TYPE CHECKS
376 *****************************************************************************/
377
378 /* builtin_instanceof **********************************************************
379
380    Checks if an object is an instance of some given class (or subclass
381    of that class). If class is an interface, checks if the interface
382    is implemented.
383
384    Return value: 1 ... o is an instance of class or implements the interface
385                  0 ... otherwise or if o == NULL
386                          
387 *******************************************************************************/
388
389 s4 builtin_instanceof(java_objectheader *o, classinfo *class)
390 {
391         if (o == NULL)
392                 return 0;
393
394         return class_isanysubclass(o->vftbl->class, class);
395 }
396
397
398
399 /* builtin_checkcast ***********************************************************
400
401    The same as builtin_instanceof except that 1 is returned when o ==
402    NULL.
403                           
404 *******************************************************************************/
405
406 s4 builtin_checkcast(java_objectheader *o, classinfo *class)
407 {
408         if (o == NULL)
409                 return 1;
410
411         if (class_isanysubclass(o->vftbl->class, class))
412                 return 1;
413
414         return 0;
415 }
416
417
418 /* builtin_descriptorscompatible ***********************************************
419
420    Checks if two array type descriptors are assignment compatible
421
422    Return value: 1 ... target = desc is possible
423                  0 ... otherwise
424                         
425 *******************************************************************************/
426
427 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
428                                                                                 arraydescriptor *target)
429 {
430         if (desc == target)
431                 return 1;
432
433         if (desc->arraytype != target->arraytype)
434                 return 0;
435
436         if (desc->arraytype != ARRAYTYPE_OBJECT)
437                 return 1;
438         
439         /* {both arrays are arrays of references} */
440
441         if (desc->dimension == target->dimension) {
442                 /* an array which contains elements of interface types is
443            allowed to be casted to Object (JOWENN)*/
444
445                 if ((desc->elementvftbl->baseval < 0) &&
446                         (target->elementvftbl->baseval == 1))
447                         return 1;
448
449                 return class_isanysubclass(desc->elementvftbl->class,
450                                                                    target->elementvftbl->class);
451         }
452
453         if (desc->dimension < target->dimension)
454                 return 0;
455
456         /* {desc has higher dimension than target} */
457
458         return class_isanysubclass(pseudo_class_Arraystub,
459                                                            target->elementvftbl->class);
460 }
461
462
463 /* builtin_arraycheckcast ******************************************************
464
465    Checks if an object is really a subtype of the requested array
466    type.  The object has to be an array to begin with. For simple
467    arrays (int, short, double, etc.) the types have to match exactly.
468    For arrays of objects, the type of elements in the array has to be
469    a subtype (or the same type) of the requested element type. For
470    arrays of arrays (which in turn can again be arrays of arrays), the
471    types at the lowest level have to satisfy the corresponding sub
472    class relation.
473         
474 *******************************************************************************/
475
476 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
477 {
478         arraydescriptor *desc;
479
480         if (o == NULL)
481                 return 1;
482
483         desc = o->vftbl->arraydesc;
484
485         if (desc == NULL)
486                 return 0;
487  
488         return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
489 }
490
491
492 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
493 {
494         if (o == NULL)
495                 return 0;
496
497         return builtin_arraycheckcast(o, targetclass);
498 }
499
500
501 /* builtin_throw_exception *****************************************************
502
503    Sets the exceptionptr with the thrown exception and prints some
504    debugging information.  Called from asm_vm_call_method.
505
506 *******************************************************************************/
507
508 void *builtin_throw_exception(java_objectheader *xptr)
509 {
510 #if !defined(NDEBUG)
511     java_lang_Throwable *t;
512         char                *logtext;
513         s4                   logtextlen;
514         s4                   dumpsize;
515
516         if (opt_verbose) {
517                 t = (java_lang_Throwable *) xptr;
518
519                 /* calculate message length */
520
521                 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
522
523                 if (t) {
524                         logtextlen +=
525                                 utf_bytes(xptr->vftbl->class->name);
526                         if (t->detailMessage) {
527                                 logtextlen += strlen(": ") +
528                                         u2_utflength(t->detailMessage->value->data 
529                                                                         + t->detailMessage->offset,
530                                                          t->detailMessage->count);
531                         }
532                 } 
533                 else {
534                         logtextlen += strlen("(nil)");
535                 }
536
537                 /* allocate memory */
538
539                 dumpsize = dump_size();
540
541                 logtext = DMNEW(char, logtextlen);
542
543                 strcpy(logtext, "Builtin exception thrown: ");
544
545                 if (t) {
546                         utf_cat_classname(logtext, xptr->vftbl->class->name);
547
548                         if (t->detailMessage) {
549                                 char *buf;
550
551                                 buf = javastring_tochar((java_objectheader *) t->detailMessage);
552                                 strcat(logtext, ": ");
553                                 strcat(logtext, buf);
554                                 MFREE(buf, char, strlen(buf) + 1);
555                         }
556
557                 } else {
558                         strcat(logtext, "(nil)");
559                 }
560
561                 log_text(logtext);
562
563                 /* release memory */
564
565                 dump_release(dumpsize);
566         }
567 #endif /* !defined(NDEBUG) */
568
569         /* actually set the exception */
570
571         exceptions_set_exception(xptr);
572
573         /* Return a NULL pointer.  This is required for vm_call_method to
574            check for an exception.  This is for convenience. */
575
576         return NULL;
577 }
578
579
580 /* builtin_canstore ************************************************************
581
582    Checks, if an object can be stored in an array.
583
584    Return value: 1 ... possible
585                  0 ... otherwise (throws an ArrayStoreException)
586
587 *******************************************************************************/
588
589 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
590 {
591         arraydescriptor *desc;
592         arraydescriptor *valuedesc;
593         vftbl_t         *componentvftbl;
594         vftbl_t         *valuevftbl;
595         s4               base;
596         castinfo         classvalues;
597         s4               result;
598
599         if (o == NULL)
600                 return 1;
601
602         /* The following is guaranteed (by verifier checks):
603          *
604          *     *) oa->...vftbl->arraydesc != NULL
605          *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
606          *     *) o->vftbl is not an interface vftbl
607          */
608         
609         desc           = oa->header.objheader.vftbl->arraydesc;
610         componentvftbl = desc->componentvftbl;
611         valuevftbl     = o->vftbl;
612         valuedesc      = valuevftbl->arraydesc;
613
614         if ((desc->dimension - 1) == 0) {
615                 /* {oa is a one-dimensional array} */
616                 /* {oa is an array of references} */
617                 
618                 if (valuevftbl == componentvftbl)
619                         return 1;
620
621                 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
622
623                 base = classvalues.super_baseval;
624
625                 if (base <= 0) {
626                         /* an array of interface references */
627
628                         result = ((valuevftbl->interfacetablelength > -base) &&
629                                         (valuevftbl->interfacetable[base] != NULL));
630                 }
631                 else {
632                         result = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
633                                    <= (unsigned) classvalues.super_diffval);
634                 }
635         }
636         else if (valuedesc == NULL) {
637                 /* {oa has dimension > 1} */
638                 /* {componentvftbl->arraydesc != NULL} */
639
640                 /* check if o is an array */
641
642                 return 0;
643         }
644         else {
645                 /* {o is an array} */
646
647                 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
648         }
649
650         /* if not possible, throw an exception */
651
652         if (result == 0)
653                 exceptions_throw_arraystoreexception();
654
655         /* return result */
656
657         return result;
658 }
659
660
661 /* This is an optimized version where a is guaranteed to be one-dimensional */
662 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
663 {
664         arraydescriptor *desc;
665         vftbl_t *elementvftbl;
666         vftbl_t *valuevftbl;
667         s4 res;
668         int base;
669         castinfo classvalues;
670         
671         if (!o) return 1;
672
673         /* The following is guaranteed (by verifier checks):
674          *
675          *     *) a->...vftbl->arraydesc != NULL
676          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
677          *     *) a->...vftbl->arraydesc->dimension == 1
678          *     *) o->vftbl is not an interface vftbl
679          */
680
681         desc = a->header.objheader.vftbl->arraydesc;
682     elementvftbl = desc->elementvftbl;
683         valuevftbl = o->vftbl;
684
685         /* {a is a one-dimensional array} */
686         
687         if (valuevftbl == elementvftbl)
688                 return 1;
689
690         ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
691
692         if ((base = classvalues.super_baseval) <= 0)
693                 /* an array of interface references */
694                 return (valuevftbl->interfacetablelength > -base &&
695                                 valuevftbl->interfacetable[base] != NULL);
696
697         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
698                 <= (unsigned) classvalues.super_diffval;
699
700         return res;
701 }
702
703
704 /* This is an optimized version where a is guaranteed to be a
705  * one-dimensional array of a class type */
706 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
707 {
708         vftbl_t *elementvftbl;
709         vftbl_t *valuevftbl;
710         s4 res;
711         castinfo classvalues;
712         
713         if (!o) return 1;
714
715         /* The following is guaranteed (by verifier checks):
716          *
717          *     *) a->...vftbl->arraydesc != NULL
718          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
719          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
720          *     *) a->...vftbl->arraydesc->dimension == 1
721          *     *) o->vftbl is not an interface vftbl
722          */
723
724     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
725         valuevftbl = o->vftbl;
726
727         /* {a is a one-dimensional array} */
728         
729         if (valuevftbl == elementvftbl)
730                 return 1;
731
732         ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
733
734         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
735                 <= (unsigned) classvalues.super_diffval;
736
737         return res;
738 }
739
740
741 /* builtin_new *****************************************************************
742
743    Creates a new instance of class c on the heap.
744
745    Return value: pointer to the object or NULL if no memory is
746    available
747                         
748 *******************************************************************************/
749
750 java_objectheader *builtin_new(classinfo *c)
751 {
752         java_objectheader *o;
753 #if defined(ENABLE_RT_TIMING)
754         struct timespec time_start, time_end;
755 #endif
756 #if defined(ENABLE_CYCLES_STATS)
757         u8 cycles_start, cycles_end;
758 #endif
759
760         RT_TIMING_GET_TIME(time_start);
761         CYCLES_STATS_GET(cycles_start);
762
763         /* is the class loaded */
764
765         assert(c->state & CLASS_LOADED);
766
767         /* check if we can instantiate this class */
768
769         if (c->flags & ACC_ABSTRACT) {
770                 exceptions_throw_instantiationerror(c);
771                 return NULL;
772         }
773
774         /* is the class linked */
775
776         if (!(c->state & CLASS_LINKED))
777                 if (!link_class(c))
778                         return NULL;
779
780         if (!(c->state & CLASS_INITIALIZED)) {
781 #if !defined(NDEBUG)
782                 if (initverbose)
783                         log_message_class("Initialize class (from builtin_new): ", c);
784 #endif
785
786                 if (!initialize_class(c))
787                         return NULL;
788         }
789
790         o = heap_allocate(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
791                                           c->finalizer);
792
793         if (!o)
794                 return NULL;
795
796         o->vftbl = c->vftbl;
797
798 #if defined(ENABLE_THREADS)
799         lock_init_object_lock(o);
800 #endif
801
802         CYCLES_STATS_GET(cycles_end);
803         RT_TIMING_GET_TIME(time_end);
804
805         CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
806         RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
807
808         return o;
809 }
810
811
812 /* builtin_newarray ************************************************************
813
814    Creates an array with the given vftbl on the heap. This function
815    takes as class argument an array class.
816
817    Return value: pointer to the array or NULL if no memory is available
818
819 *******************************************************************************/
820
821 java_arrayheader *builtin_newarray(s4 size, classinfo *arrayclass)
822 {
823         arraydescriptor  *desc;
824         s4                dataoffset;
825         s4                componentsize;
826         s4                actualsize;
827         java_arrayheader *a;
828 #if defined(ENABLE_RT_TIMING)
829         struct timespec time_start, time_end;
830 #endif
831
832         RT_TIMING_GET_TIME(time_start);
833
834         desc          = arrayclass->vftbl->arraydesc;
835         dataoffset    = desc->dataoffset;
836         componentsize = desc->componentsize;
837
838         if (size < 0) {
839                 exceptions_throw_negativearraysizeexception();
840                 return NULL;
841         }
842
843         actualsize = dataoffset + size * componentsize;
844
845         /* check for overflow */
846
847         if (((u4) actualsize) < ((u4) size)) {
848                 exceptions_throw_outofmemoryerror();
849                 return NULL;
850         }
851
852         a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
853
854         if (a == NULL)
855                 return NULL;
856
857         a->objheader.vftbl = arrayclass->vftbl;
858
859 #if defined(ENABLE_THREADS)
860         lock_init_object_lock(&a->objheader);
861 #endif
862
863         a->size = size;
864
865         RT_TIMING_GET_TIME(time_end);
866         RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
867
868         return a;
869 }
870
871
872 /* builtin_anewarray ***********************************************************
873
874    Creates an array of references to the given class type on the heap.
875
876    Return value: pointer to the array or NULL if no memory is
877    available
878
879 *******************************************************************************/
880
881 java_objectarray *builtin_anewarray(s4 size, classinfo *componentclass)
882 {
883         classinfo *arrayclass;
884         
885         /* is class loaded */
886
887         assert(componentclass->state & CLASS_LOADED);
888
889         /* is class linked */
890
891         if (!(componentclass->state & CLASS_LINKED))
892                 if (!link_class(componentclass))
893                         return NULL;
894
895         arrayclass = class_array_of(componentclass, true);
896
897         if (!arrayclass)
898                 return NULL;
899
900         return (java_objectarray *) builtin_newarray(size, arrayclass);
901 }
902
903
904 /* builtin_newarray_boolean ****************************************************
905
906    Creates an array of bytes on the heap. The array is designated as
907    an array of booleans (important for casts)
908         
909    Return value: pointer to the array or NULL if no memory is
910    available
911
912 *******************************************************************************/
913
914 java_booleanarray *builtin_newarray_boolean(s4 size)
915 {
916         return (java_booleanarray *)
917                 builtin_newarray(size,
918                                                  primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass);
919 }
920
921
922 /* builtin_newarray_byte *******************************************************
923
924    Creates an array of 8 bit Integers on the heap.
925
926    Return value: pointer to the array or NULL if no memory is
927    available
928
929 *******************************************************************************/
930
931 java_bytearray *builtin_newarray_byte(s4 size)
932 {
933         return (java_bytearray *)
934                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayclass);
935 }
936
937
938 /* builtin_newarray_char *******************************************************
939
940    Creates an array of characters on the heap.
941
942    Return value: pointer to the array or NULL if no memory is
943    available
944
945 *******************************************************************************/
946
947 java_chararray *builtin_newarray_char(s4 size)
948 {
949         return (java_chararray *)
950                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayclass);
951 }
952
953
954 /* builtin_newarray_short ******************************************************
955
956    Creates an array of 16 bit Integers on the heap.
957
958    Return value: pointer to the array or NULL if no memory is
959    available
960
961 *******************************************************************************/
962
963 java_shortarray *builtin_newarray_short(s4 size)
964 {
965         return (java_shortarray *)
966                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayclass);
967 }
968
969
970 /* builtin_newarray_int ********************************************************
971
972    Creates an array of 32 bit Integers on the heap.
973
974    Return value: pointer to the array or NULL if no memory is
975    available
976
977 *******************************************************************************/
978
979 java_intarray *builtin_newarray_int(s4 size)
980 {
981         return (java_intarray *)
982                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayclass);
983 }
984
985
986 /* builtin_newarray_long *******************************************************
987
988    Creates an array of 64 bit Integers on the heap.
989
990    Return value: pointer to the array or NULL if no memory is
991    available
992
993 *******************************************************************************/
994
995 java_longarray *builtin_newarray_long(s4 size)
996 {
997         return (java_longarray *)
998                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayclass);
999 }
1000
1001
1002 /* builtin_newarray_float ******************************************************
1003
1004    Creates an array of 32 bit IEEE floats on the heap.
1005
1006    Return value: pointer to the array or NULL if no memory is
1007    available
1008
1009 *******************************************************************************/
1010
1011 java_floatarray *builtin_newarray_float(s4 size)
1012 {
1013         return (java_floatarray *)
1014                 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass);
1015 }
1016
1017
1018 /* builtin_newarray_double *****************************************************
1019
1020    Creates an array of 64 bit IEEE floats on the heap.
1021
1022    Return value: pointer to the array or NULL if no memory is
1023    available
1024
1025 *******************************************************************************/
1026
1027 java_doublearray *builtin_newarray_double(s4 size)
1028 {
1029         return (java_doublearray *)
1030                 builtin_newarray(size,
1031                                                  primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass);
1032 }
1033
1034
1035 /* builtin_multianewarray_intern ***********************************************
1036
1037    Creates a multi-dimensional array on the heap. The dimensions are
1038    passed in an array of longs.
1039
1040    Arguments:
1041        n.............number of dimensions to create
1042        arrayclass....the array class
1043        dims..........array containing the size of each dimension to create
1044
1045    Return value: pointer to the array or NULL if no memory is
1046    available
1047
1048 ******************************************************************************/
1049
1050 static java_arrayheader *builtin_multianewarray_intern(int n,
1051                                                                                                            classinfo *arrayclass,
1052                                                                                                            long *dims)
1053 {
1054         s4                size;
1055         java_arrayheader *a;
1056         classinfo        *componentclass;
1057         s4                i;
1058
1059         /* create this dimension */
1060
1061         size = (s4) dims[0];
1062         a = builtin_newarray(size, arrayclass);
1063
1064         if (!a)
1065                 return NULL;
1066
1067         /* if this is the last dimension return */
1068
1069         if (!--n)
1070                 return a;
1071
1072         /* get the class of the components to create */
1073
1074         componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
1075
1076         /* The verifier guarantees that the dimension count is in the range. */
1077
1078         /* create the component arrays */
1079
1080         for (i = 0; i < size; i++) {
1081                 java_arrayheader *ea =
1082 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1083                         /* we save an s4 to a s8 slot, 8-byte aligned */
1084
1085                         builtin_multianewarray_intern(n, componentclass, dims + 2);
1086 #else
1087                         builtin_multianewarray_intern(n, componentclass, dims + 1);
1088 #endif
1089
1090                 if (!ea)
1091                         return NULL;
1092                 
1093                 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1094         }
1095
1096         return a;
1097 }
1098
1099
1100 /* builtin_multianewarray ******************************************************
1101
1102    Wrapper for builtin_multianewarray_intern which checks all
1103    dimensions before we start allocating.
1104
1105 ******************************************************************************/
1106
1107 java_arrayheader *builtin_multianewarray(int n, classinfo *arrayclass,
1108                                                                                  long *dims)
1109 {
1110         s4 i;
1111         s4 size;
1112
1113         /* check all dimensions before doing anything */
1114
1115         for (i = 0; i < n; i++) {
1116 #if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1117                 /* we save an s4 to a s8 slot, 8-byte aligned */
1118                 size = (s4) dims[i * 2];
1119 #else
1120                 size = (s4) dims[i];
1121 #endif
1122
1123                 if (size < 0) {
1124                         exceptions_throw_negativearraysizeexception();
1125                         return NULL;
1126                 }
1127         }
1128
1129         /* now call the real function */
1130
1131         return builtin_multianewarray_intern(n, arrayclass, dims);
1132 }
1133
1134
1135 /*****************************************************************************
1136                                           METHOD LOGGING
1137
1138         Various functions for printing a message at method entry or exit (for
1139         debugging)
1140         
1141 *****************************************************************************/
1142
1143 #if !defined(NDEBUG)
1144 static s4 methodindent = 0;
1145 static u4 callcount = 0;
1146
1147 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1148                                                                                    methodinfo *m,
1149                                                                                    void *pos,
1150                                                                                    s4 indent)
1151 {
1152         char *logtext;
1153         s4    logtextlen;
1154         s4    dumpsize;
1155         codeinfo *code;
1156
1157 #if defined(ENABLE_DEBUG_FILTER)
1158         if (! show_filters_test_verbosecall_exit(m)) return xptr;
1159 #endif
1160
1161 #if defined(ENABLE_VMLOG)
1162         return xptr;
1163 #endif
1164
1165         if (opt_verbosecall && indent)
1166                 methodindent--;
1167
1168         /* calculate message length */
1169
1170         if (xptr) {
1171                 logtextlen =
1172                         strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
1173         } 
1174         else {
1175                 logtextlen = strlen("Some Throwable");
1176         }
1177
1178         logtextlen += strlen(" thrown in ");
1179
1180         if (m) {
1181                 logtextlen +=
1182                         utf_bytes(m->class->name) +
1183                         strlen(".") +
1184                         utf_bytes(m->name) +
1185                         utf_bytes(m->descriptor) +
1186                         strlen("(NOSYNC,NATIVE");
1187
1188 #if SIZEOF_VOID_P == 8
1189                 logtextlen +=
1190                         strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1191 #else
1192                 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1193 #endif
1194
1195                 if (m->class->sourcefile == NULL)
1196                         logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1197                 else
1198                         logtextlen += utf_bytes(m->class->sourcefile);
1199
1200                 logtextlen += strlen(":65536)");
1201
1202         } 
1203         else {
1204                 logtextlen += strlen("call_java_method");
1205         }
1206
1207         logtextlen += strlen("0");
1208
1209         /* allocate memory */
1210
1211         dumpsize = dump_size();
1212
1213         logtext = DMNEW(char, logtextlen);
1214
1215         if (xptr) {
1216                 strcpy(logtext, "Exception ");
1217                 utf_cat_classname(logtext, xptr->vftbl->class->name);
1218
1219         } else {
1220                 strcpy(logtext, "Some Throwable");
1221         }
1222
1223         strcat(logtext, " thrown in ");
1224
1225         if (m) {
1226                 utf_cat_classname(logtext, m->class->name);
1227                 strcat(logtext, ".");
1228                 utf_cat(logtext, m->name);
1229                 utf_cat(logtext, m->descriptor);
1230
1231                 if (m->flags & ACC_SYNCHRONIZED)
1232                         strcat(logtext, "(SYNC");
1233                 else
1234                         strcat(logtext, "(NOSYNC");
1235
1236                 if (m->flags & ACC_NATIVE) {
1237                         strcat(logtext, ",NATIVE");
1238
1239                         code = m->code;
1240
1241 #if SIZEOF_VOID_P == 8
1242                         sprintf(logtext + strlen(logtext),
1243                                         ")(0x%016lx) at position 0x%016lx",
1244                                         (ptrint) code->entrypoint, (ptrint) pos);
1245 #else
1246                         sprintf(logtext + strlen(logtext),
1247                                         ")(0x%08x) at position 0x%08x",
1248                                         (ptrint) code->entrypoint, (ptrint) pos);
1249 #endif
1250
1251                 } else {
1252
1253                         /* XXX preliminary: This should get the actual codeinfo */
1254                         /* in which the exception happened.                     */
1255                         code = m->code;
1256                         
1257 #if SIZEOF_VOID_P == 8
1258                         sprintf(logtext + strlen(logtext),
1259                                         ")(0x%016lx) at position 0x%016lx (",
1260                                         (ptrint) code->entrypoint, (ptrint) pos);
1261 #else
1262                         sprintf(logtext + strlen(logtext),
1263                                         ")(0x%08x) at position 0x%08x (",
1264                                         (ptrint) code->entrypoint, (ptrint) pos);
1265 #endif
1266
1267                         if (m->class->sourcefile == NULL)
1268                                 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1269                         else
1270                                 utf_cat(logtext, m->class->sourcefile);
1271
1272                         sprintf(logtext + strlen(logtext), ":%d)", 0);
1273                 }
1274
1275         } else
1276                 strcat(logtext, "call_java_method");
1277
1278         log_text(logtext);
1279
1280         /* release memory */
1281
1282         dump_release(dumpsize);
1283
1284         return xptr;
1285 }
1286 #endif /* !defined(NDEBUG) */
1287
1288
1289 /* builtin_print_argument ******************************************************
1290
1291    Prints arguments and return values for the call trace.
1292
1293 *******************************************************************************/
1294
1295 #if !defined(NDEBUG)
1296 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1297                                                                         typedesc *paramtype, s8 value)
1298 {
1299         imm_union          imu;
1300         java_objectheader *o;
1301         classinfo         *c;
1302         utf               *u;
1303         u4                 len;
1304
1305         switch (paramtype->type) {
1306         case TYPE_INT:
1307                 imu.i = (s4) value;
1308                 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1309                 break;
1310
1311         case TYPE_LNG:
1312                 imu.l = value;
1313 #if SIZEOF_VOID_P == 4
1314                 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1315 #else
1316                 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1317 #endif
1318                 break;
1319
1320         case TYPE_FLT:
1321 #if defined(__S390__)
1322                 imu.l = value;
1323                 /* The below won't work on S390 */
1324 #else
1325                 imu.i = (s4) value;
1326 #endif
1327                 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1328                 break;
1329
1330         case TYPE_DBL:
1331                 imu.l = value;
1332 #if SIZEOF_VOID_P == 4
1333                 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1334 #else
1335                 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1336 #endif
1337                 break;
1338
1339         case TYPE_ADR:
1340 #if SIZEOF_VOID_P == 4
1341                 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1342 #else
1343                 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1344 #endif
1345
1346                 /* cast to java.lang.Object */
1347
1348                 o = (java_objectheader *) (ptrint) value;
1349
1350                 /* check return argument for java.lang.Class or java.lang.String */
1351
1352                 if (o != NULL) {
1353                         if (o->vftbl->class == class_java_lang_String) {
1354                                 /* get java.lang.String object and the length of the
1355                                    string */
1356
1357                                 u = javastring_toutf(o, false);
1358
1359                                 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1360
1361                                 /* realloc memory for string length */
1362
1363                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1364                                 *logtextlen += len;
1365
1366                                 /* convert to utf8 string and strcat it to the logtext */
1367
1368                                 strcat(logtext, " (String = \"");
1369                                 utf_cat(logtext, u);
1370                                 strcat(logtext, "\")");
1371                         }
1372                         else {
1373                                 if (o->vftbl->class == class_java_lang_Class) {
1374                                         /* if the object returned is a java.lang.Class
1375                                            cast it to classinfo structure and get the name
1376                                            of the class */
1377
1378                                         c = (classinfo *) o;
1379
1380                                         u = c->name;
1381                                 }
1382                                 else {
1383                                         /* if the object returned is not a java.lang.String or
1384                                            a java.lang.Class just print the name of the class */
1385
1386                                         u = o->vftbl->class->name;
1387                                 }
1388
1389                                 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1390
1391                                 /* realloc memory for string length */
1392
1393                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1394                                 *logtextlen += len;
1395
1396                                 /* strcat to the logtext */
1397
1398                                 strcat(logtext, " (Class = \"");
1399                                 utf_cat_classname(logtext, u);
1400                                 strcat(logtext, "\")");
1401                         }
1402                 }
1403         }
1404
1405         return logtext;
1406 }
1407 #endif /* !defined(NDEBUG) */
1408
1409 /* builtin_verbosecall_enter ***************************************************
1410
1411    Print method call with arguments for -verbose:call.
1412
1413 *******************************************************************************/
1414
1415 #if !defined(NDEBUG)
1416
1417 #ifdef TRACE_ARGS_NUM
1418 void builtin_verbosecall_enter(s8 a0, s8 a1,
1419 # if TRACE_ARGS_NUM >= 4
1420                                                            s8 a2, s8 a3,
1421 # endif
1422 # if TRACE_ARGS_NUM >= 6
1423                                                            s8 a4, s8 a5,
1424 # endif
1425 # if TRACE_ARGS_NUM == 8
1426                                                            s8 a6, s8 a7,
1427 # endif
1428                                                            methodinfo *m)
1429 {
1430         methoddesc *md;
1431         char       *logtext;
1432         s4          logtextlen;
1433         s4          dumpsize;
1434         s4          i;
1435         s4          pos;
1436
1437 #if defined(ENABLE_DEBUG_FILTER)
1438         if (! show_filters_test_verbosecall_enter(m)) return;
1439 #endif
1440
1441 #if defined(ENABLE_VMLOG)
1442         vmlog_cacao_enter_method(m);
1443         return;
1444 #endif
1445
1446         md = m->parseddesc;
1447
1448         /* calculate message length */
1449
1450         logtextlen =
1451                 strlen("4294967295 ") +
1452                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1453                 methodindent +
1454                 strlen("called: ") +
1455                 utf_bytes(m->class->name) +
1456                 strlen(".") +
1457                 utf_bytes(m->name) +
1458                 utf_bytes(m->descriptor);
1459
1460         /* Actually it's not possible to have all flags printed, but:
1461            safety first! */
1462
1463         logtextlen +=
1464                 strlen(" PUBLIC") +
1465                 strlen(" PRIVATE") +
1466                 strlen(" PROTECTED") +
1467                 strlen(" STATIC") +
1468                 strlen(" FINAL") +
1469                 strlen(" SYNCHRONIZED") +
1470                 strlen(" VOLATILE") +
1471                 strlen(" TRANSIENT") +
1472                 strlen(" NATIVE") +
1473                 strlen(" INTERFACE") +
1474                 strlen(" ABSTRACT");
1475
1476         /* add maximal argument length */
1477
1478         logtextlen +=
1479                 strlen("(") +
1480                 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1481                 strlen("...(255)") +
1482                 strlen(")");
1483
1484         /* allocate memory */
1485
1486         dumpsize = dump_size();
1487
1488         logtext = DMNEW(char, logtextlen);
1489
1490         callcount++;
1491
1492         sprintf(logtext, "%10d ", callcount);
1493         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1494
1495         pos = strlen(logtext);
1496
1497         for (i = 0; i < methodindent; i++)
1498                 logtext[pos++] = '\t';
1499
1500         strcpy(logtext + pos, "called: ");
1501
1502         utf_cat_classname(logtext, m->class->name);
1503         strcat(logtext, ".");
1504         utf_cat(logtext, m->name);
1505         utf_cat(logtext, m->descriptor);
1506
1507         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1508         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1509         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1510         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1511         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1512         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1513         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1514         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1515         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1516         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1517         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1518
1519         strcat(logtext, "(");
1520
1521         if (md->paramcount >= 1) {
1522                 logtext = builtin_print_argument(logtext, &logtextlen,
1523                                                                                  &md->paramtypes[0], a0);
1524         }
1525
1526         if (md->paramcount >= 2) {
1527                 strcat(logtext, ", ");
1528
1529                 logtext = builtin_print_argument(logtext, &logtextlen,
1530                                                                                  &md->paramtypes[1], a1);
1531         }
1532
1533 #if TRACE_ARGS_NUM >= 4
1534         if (md->paramcount >= 3) {
1535                 strcat(logtext, ", ");
1536
1537                 logtext = builtin_print_argument(logtext, &logtextlen,
1538                                                                                  &md->paramtypes[2], a2);
1539         }
1540
1541         if (md->paramcount >= 4) {
1542                 strcat(logtext, ", ");
1543
1544                 logtext = builtin_print_argument(logtext, &logtextlen,
1545                                                                                  &md->paramtypes[3], a3);
1546         }
1547 #endif
1548
1549 #if TRACE_ARGS_NUM >= 6
1550         if (md->paramcount >= 5) {
1551                 strcat(logtext, ", ");
1552
1553                 logtext = builtin_print_argument(logtext, &logtextlen,
1554                                                                                  &md->paramtypes[4], a4);
1555         }
1556
1557         if (md->paramcount >= 6) {
1558                 strcat(logtext, ", ");
1559
1560                 logtext = builtin_print_argument(logtext, &logtextlen,
1561                                                                                  &md->paramtypes[5], a5);
1562         }
1563 #endif
1564
1565 #if TRACE_ARGS_NUM == 8
1566         if (md->paramcount >= 7) {
1567                 strcat(logtext, ", ");
1568
1569                 logtext = builtin_print_argument(logtext, &logtextlen,
1570                                                                                  &md->paramtypes[6], a6);
1571         }
1572
1573         if (md->paramcount >= 8) {
1574                 strcat(logtext, ", ");
1575
1576                 logtext = builtin_print_argument(logtext, &logtextlen,
1577                                                                                  &md->paramtypes[7], a7);
1578         }
1579 #endif
1580
1581         if (md->paramcount > 8) {
1582                 sprintf(logtext + strlen(logtext), ", ...(%d)",
1583                                 md->paramcount - TRACE_ARGS_NUM);
1584         }
1585
1586         strcat(logtext, ")");
1587
1588         log_text(logtext);
1589
1590         /* release memory */
1591
1592         dump_release(dumpsize);
1593
1594         methodindent++;
1595
1596 }
1597 #endif
1598 #endif /* !defined(NDEBUG) */
1599
1600
1601 /* builtin_verbosecall_exit ****************************************************
1602
1603    Print method exit for -verbose:call.
1604
1605 *******************************************************************************/
1606
1607 #if !defined(NDEBUG)
1608 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1609 {
1610         methoddesc *md;
1611         char       *logtext;
1612         s4          logtextlen;
1613         s4          dumpsize;
1614         s4          i;
1615         s4          pos;
1616         imm_union   val;
1617
1618 #if defined(ENABLE_DEBUG_FILTER)
1619         if (! show_filters_test_verbosecall_exit(m)) return;
1620 #endif
1621
1622 #if defined(ENABLE_VMLOG)
1623         vmlog_cacao_leave_method(m);
1624         return;
1625 #endif
1626
1627         md = m->parseddesc;
1628
1629         /* calculate message length */
1630
1631         logtextlen =
1632                 strlen("4294967295 ") +
1633                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1634                 methodindent +
1635                 strlen("finished: ") +
1636                 utf_bytes(m->class->name) +
1637                 strlen(".") +
1638                 utf_bytes(m->name) +
1639                 utf_bytes(m->descriptor) +
1640                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1641
1642         /* add maximal argument length */
1643
1644         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1645
1646         /* allocate memory */
1647
1648         dumpsize = dump_size();
1649
1650         logtext = DMNEW(char, logtextlen);
1651
1652         /* outdent the log message */
1653
1654         if (methodindent)
1655                 methodindent--;
1656         else
1657                 log_text("WARNING: unmatched methodindent--");
1658
1659         /* generate the message */
1660
1661         sprintf(logtext, "           ");
1662         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1663
1664         pos = strlen(logtext);
1665
1666         for (i = 0; i < methodindent; i++)
1667                 logtext[pos++] = '\t';
1668
1669         strcpy(logtext + pos, "finished: ");
1670         utf_cat_classname(logtext, m->class->name);
1671         strcat(logtext, ".");
1672         utf_cat(logtext, m->name);
1673         utf_cat(logtext, m->descriptor);
1674
1675         if (!IS_VOID_TYPE(md->returntype.type)) {
1676                 strcat(logtext, "->");
1677
1678                 switch (md->returntype.type) {
1679                 case TYPE_INT:
1680                 case TYPE_LNG:
1681                 case TYPE_ADR:
1682                         val.l = l;
1683                         break;
1684
1685                 case TYPE_FLT:
1686                         val.f = f;
1687                         break;
1688
1689                 case TYPE_DBL:
1690                         val.d = d;
1691                         break;
1692                 }
1693
1694                 logtext =
1695                         builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1696         }
1697
1698         log_text(logtext);
1699
1700         /* release memory */
1701
1702         dump_release(dumpsize);
1703
1704 }
1705 #endif /* !defined(NDEBUG) */
1706
1707
1708 #if defined(ENABLE_CYCLES_STATS)
1709 void builtin_print_cycles_stats(FILE *file)
1710 {
1711         fprintf(file,"builtin cylce count statistics:\n");
1712
1713         CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1714         CYCLES_STATS_PRINT(builtin_new         ,file);
1715
1716         fprintf(file,"\n");
1717 }
1718 #endif /* defined(ENABLE_CYCLES_STATS) */
1719
1720
1721 /*****************************************************************************
1722                           MISCELLANEOUS HELPER FUNCTIONS
1723 *****************************************************************************/
1724
1725
1726
1727 /*********** Functions for integer divisions *****************************
1728  
1729         On some systems (eg. DEC ALPHA), integer division is not supported by the
1730         CPU. These helper functions implement the missing functionality.
1731
1732 ******************************************************************************/
1733
1734 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1735 s4 builtin_idiv(s4 a, s4 b)
1736 {
1737         s4 c;
1738
1739         c = a / b;
1740
1741         return c;
1742 }
1743
1744 s4 builtin_irem(s4 a, s4 b)
1745 {
1746         s4 c;
1747
1748         c = a % b;
1749
1750         return c;
1751 }
1752 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1753
1754
1755 /* functions for long arithmetics **********************************************
1756
1757    On systems where 64 bit Integers are not supported by the CPU,
1758    these functions are needed.
1759
1760 ******************************************************************************/
1761
1762 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1763 s8 builtin_ladd(s8 a, s8 b)
1764 {
1765         s8 c;
1766
1767 #if U8_AVAILABLE
1768         c = a + b; 
1769 #else
1770         c = builtin_i2l(0);
1771 #endif
1772
1773         return c;
1774 }
1775
1776 s8 builtin_lsub(s8 a, s8 b)
1777 {
1778         s8 c;
1779
1780 #if U8_AVAILABLE
1781         c = a - b; 
1782 #else
1783         c = builtin_i2l(0);
1784 #endif
1785
1786         return c;
1787 }
1788
1789 s8 builtin_lneg(s8 a)
1790 {
1791         s8 c;
1792
1793 #if U8_AVAILABLE
1794         c = -a;
1795 #else
1796         c = builtin_i2l(0);
1797 #endif
1798
1799         return c;
1800 }
1801 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1802
1803
1804 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1805 s8 builtin_lmul(s8 a, s8 b)
1806 {
1807         s8 c;
1808
1809 #if U8_AVAILABLE
1810         c = a * b; 
1811 #else
1812         c = builtin_i2l(0);
1813 #endif
1814
1815         return c;
1816 }
1817 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1818
1819
1820 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1821 s8 builtin_ldiv(s8 a, s8 b)
1822 {
1823         s8 c;
1824
1825 #if U8_AVAILABLE
1826         c = a / b; 
1827 #else
1828         c = builtin_i2l(0);
1829 #endif
1830
1831         return c;
1832 }
1833
1834 s8 builtin_lrem(s8 a, s8 b)
1835 {
1836         s8 c;
1837
1838 #if U8_AVAILABLE
1839         c = a % b; 
1840 #else
1841         c = builtin_i2l(0);
1842 #endif
1843
1844         return c;
1845 }
1846 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1847
1848
1849 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1850 s8 builtin_lshl(s8 a, s4 b)
1851 {
1852         s8 c;
1853
1854 #if U8_AVAILABLE
1855         c = a << (b & 63);
1856 #else
1857         c = builtin_i2l(0);
1858 #endif
1859
1860         return c;
1861 }
1862
1863 s8 builtin_lshr(s8 a, s4 b)
1864 {
1865         s8 c;
1866
1867 #if U8_AVAILABLE
1868         c = a >> (b & 63);
1869 #else
1870         c = builtin_i2l(0);
1871 #endif
1872
1873         return c;
1874 }
1875
1876 s8 builtin_lushr(s8 a, s4 b)
1877 {
1878         s8 c;
1879
1880 #if U8_AVAILABLE
1881         c = ((u8) a) >> (b & 63);
1882 #else
1883         c = builtin_i2l(0);
1884 #endif
1885
1886         return c;
1887 }
1888 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1889
1890
1891 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1892 s8 builtin_land(s8 a, s8 b)
1893 {
1894         s8 c;
1895
1896 #if U8_AVAILABLE
1897         c = a & b; 
1898 #else
1899         c = builtin_i2l(0);
1900 #endif
1901
1902         return c;
1903 }
1904
1905 s8 builtin_lor(s8 a, s8 b)
1906 {
1907         s8 c;
1908
1909 #if U8_AVAILABLE
1910         c = a | b; 
1911 #else
1912         c = builtin_i2l(0);
1913 #endif
1914
1915         return c;
1916 }
1917
1918 s8 builtin_lxor(s8 a, s8 b) 
1919 {
1920         s8 c;
1921
1922 #if U8_AVAILABLE
1923         c = a ^ b; 
1924 #else
1925         c = builtin_i2l(0);
1926 #endif
1927
1928         return c;
1929 }
1930 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1931
1932
1933 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1934 s4 builtin_lcmp(s8 a, s8 b)
1935
1936 #if U8_AVAILABLE
1937         if (a < b)
1938                 return -1;
1939
1940         if (a > b)
1941                 return 1;
1942
1943         return 0;
1944 #else
1945         return 0;
1946 #endif
1947 }
1948 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1949
1950
1951 /* functions for unsupported floating instructions ****************************/
1952
1953 /* used to convert FLT_xxx defines into float values */
1954
1955 static inline float intBitsToFloat(s4 i)
1956 {
1957         imm_union imb;
1958
1959         imb.i = i;
1960         return imb.f;
1961 }
1962
1963
1964 /* used to convert DBL_xxx defines into double values */
1965
1966 static inline float longBitsToDouble(s8 l)
1967 {
1968         imm_union imb;
1969
1970         imb.l = l;
1971         return imb.d;
1972 }
1973
1974
1975 #if !SUPPORT_FLOAT
1976 float builtin_fadd(float a, float b)
1977 {
1978         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1979         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1980         if (finitef(a)) {
1981                 if (finitef(b))
1982                         return a + b;
1983                 else
1984                         return b;
1985         }
1986         else {
1987                 if (finitef(b))
1988                         return a;
1989                 else {
1990                         if (copysignf(1.0, a) == copysignf(1.0, b))
1991                                 return a;
1992                         else
1993                                 return intBitsToFloat(FLT_NAN);
1994                 }
1995         }
1996 }
1997
1998
1999 float builtin_fsub(float a, float b)
2000 {
2001         return builtin_fadd(a, builtin_fneg(b));
2002 }
2003
2004
2005 float builtin_fmul(float a, float b)
2006 {
2007         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2008         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2009         if (finitef(a)) {
2010                 if (finitef(b)) return a * b;
2011                 else {
2012                         if (a == 0) return intBitsToFloat(FLT_NAN);
2013                         else return copysignf(b, copysignf(1.0, b)*a);
2014                 }
2015         }
2016         else {
2017                 if (finitef(b)) {
2018                         if (b == 0) return intBitsToFloat(FLT_NAN);
2019                         else return copysignf(a, copysignf(1.0, a)*b);
2020                 }
2021                 else {
2022                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2023                 }
2024         }
2025 }
2026
2027
2028 /* builtin_ddiv ****************************************************************
2029
2030    Implementation as described in VM Spec.
2031
2032 *******************************************************************************/
2033
2034 float builtin_fdiv(float a, float b)
2035 {
2036         if (finitef(a)) {
2037                 if (finitef(b)) {
2038                         /* If neither value1' nor value2' is NaN, the sign of the result */
2039                         /* is positive if both values have the same sign, negative if the */
2040                         /* values have different signs. */
2041
2042                         return a / b;
2043
2044                 } else {
2045                         if (isnanf(b)) {
2046                                 /* If either value1' or value2' is NaN, the result is NaN. */
2047
2048                                 return intBitsToFloat(FLT_NAN);
2049
2050                         } else {
2051                                 /* Division of a finite value by an infinity results in a */
2052                                 /* signed zero, with the sign-producing rule just given. */
2053
2054                                 /* is sign equal? */
2055
2056                                 if (copysignf(1.0, a) == copysignf(1.0, b))
2057                                         return 0.0;
2058                                 else
2059                                         return -0.0;
2060                         }
2061                 }
2062
2063         } else {
2064                 if (isnanf(a)) {
2065                         /* If either value1' or value2' is NaN, the result is NaN. */
2066
2067                         return intBitsToFloat(FLT_NAN);
2068
2069                 } else if (finitef(b)) {
2070                         /* Division of an infinity by a finite value results in a signed */
2071                         /* infinity, with the sign-producing rule just given. */
2072
2073                         /* is sign equal? */
2074
2075                         if (copysignf(1.0, a) == copysignf(1.0, b))
2076                                 return intBitsToFloat(FLT_POSINF);
2077                         else
2078                                 return intBitsToFloat(FLT_NEGINF);
2079
2080                 } else {
2081                         /* Division of an infinity by an infinity results in NaN. */
2082
2083                         return intBitsToFloat(FLT_NAN);
2084                 }
2085         }
2086 }
2087
2088
2089 float builtin_fneg(float a)
2090 {
2091         if (isnanf(a)) return a;
2092         else {
2093                 if (finitef(a)) return -a;
2094                 else return copysignf(a, -copysignf(1.0, a));
2095         }
2096 }
2097 #endif /* !SUPPORT_FLOAT */
2098
2099
2100 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2101 s4 builtin_fcmpl(float a, float b)
2102 {
2103         if (isnanf(a))
2104                 return -1;
2105
2106         if (isnanf(b))
2107                 return -1;
2108
2109         if (!finitef(a) || !finitef(b)) {
2110                 a = finitef(a) ? 0 : copysignf(1.0,     a);
2111                 b = finitef(b) ? 0 : copysignf(1.0, b);
2112         }
2113
2114         if (a > b)
2115                 return 1;
2116
2117         if (a == b)
2118                 return 0;
2119
2120         return -1;
2121 }
2122
2123
2124 s4 builtin_fcmpg(float a, float b)
2125 {
2126         if (isnanf(a)) return 1;
2127         if (isnanf(b)) return 1;
2128         if (!finitef(a) || !finitef(b)) {
2129                 a = finitef(a) ? 0 : copysignf(1.0, a);
2130                 b = finitef(b) ? 0 : copysignf(1.0, b);
2131         }
2132         if (a > b) return 1;
2133         if (a == b) return 0;
2134         return -1;
2135 }
2136 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2137
2138
2139 float builtin_frem(float a, float b)
2140 {
2141         return fmodf(a, b);
2142 }
2143
2144
2145 /* functions for unsupported double instructions ******************************/
2146
2147 #if !SUPPORT_DOUBLE
2148 double builtin_dadd(double a, double b)
2149 {
2150         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2151         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2152         if (finite(a)) {
2153                 if (finite(b)) return a + b;
2154                 else return b;
2155         }
2156         else {
2157                 if (finite(b)) return a;
2158                 else {
2159                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
2160                         else return longBitsToDouble(DBL_NAN);
2161                 }
2162         }
2163 }
2164
2165
2166 double builtin_dsub(double a, double b)
2167 {
2168         return builtin_dadd(a, builtin_dneg(b));
2169 }
2170
2171
2172 double builtin_dmul(double a, double b)
2173 {
2174         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2175         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2176         if (finite(a)) {
2177                 if (finite(b)) return a * b;
2178                 else {
2179                         if (a == 0) return longBitsToDouble(DBL_NAN);
2180                         else return copysign(b, copysign(1.0, b) * a);
2181                 }
2182         }
2183         else {
2184                 if (finite(b)) {
2185                         if (b == 0) return longBitsToDouble(DBL_NAN);
2186                         else return copysign(a, copysign(1.0, a) * b);
2187                 }
2188                 else {
2189                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2190                 }
2191         }
2192 }
2193
2194
2195 /* builtin_ddiv ****************************************************************
2196
2197    Implementation as described in VM Spec.
2198
2199 *******************************************************************************/
2200
2201 double builtin_ddiv(double a, double b)
2202 {
2203         if (finite(a)) {
2204                 if (finite(b)) {
2205                         /* If neither value1' nor value2' is NaN, the sign of the result */
2206                         /* is positive if both values have the same sign, negative if the */
2207                         /* values have different signs. */
2208
2209                         return a / b;
2210
2211                 } else {
2212                         if (isnan(b)) {
2213                                 /* If either value1' or value2' is NaN, the result is NaN. */
2214
2215                                 return longBitsToDouble(DBL_NAN);
2216
2217                         } else {
2218                                 /* Division of a finite value by an infinity results in a */
2219                                 /* signed zero, with the sign-producing rule just given. */
2220
2221                                 /* is sign equal? */
2222
2223                                 if (copysign(1.0, a) == copysign(1.0, b))
2224                                         return 0.0;
2225                                 else
2226                                         return -0.0;
2227                         }
2228                 }
2229
2230         } else {
2231                 if (isnan(a)) {
2232                         /* If either value1' or value2' is NaN, the result is NaN. */
2233
2234                         return longBitsToDouble(DBL_NAN);
2235
2236                 } else if (finite(b)) {
2237                         /* Division of an infinity by a finite value results in a signed */
2238                         /* infinity, with the sign-producing rule just given. */
2239
2240                         /* is sign equal? */
2241
2242                         if (copysign(1.0, a) == copysign(1.0, b))
2243                                 return longBitsToDouble(DBL_POSINF);
2244                         else
2245                                 return longBitsToDouble(DBL_NEGINF);
2246
2247                 } else {
2248                         /* Division of an infinity by an infinity results in NaN. */
2249
2250                         return longBitsToDouble(DBL_NAN);
2251                 }
2252         }
2253 }
2254
2255
2256 /* builtin_dneg ****************************************************************
2257
2258    Implemented as described in VM Spec.
2259
2260 *******************************************************************************/
2261
2262 double builtin_dneg(double a)
2263 {
2264         if (isnan(a)) {
2265                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2266                 /* sign). */
2267
2268                 return a;
2269
2270         } else {
2271                 if (finite(a)) {
2272                         /* If the operand is a zero, the result is the zero of opposite */
2273                         /* sign. */
2274
2275                         return -a;
2276
2277                 } else {
2278                         /* If the operand is an infinity, the result is the infinity of */
2279                         /* opposite sign. */
2280
2281                         return copysign(a, -copysign(1.0, a));
2282                 }
2283         }
2284 }
2285 #endif /* !SUPPORT_DOUBLE */
2286
2287
2288 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2289 s4 builtin_dcmpl(double a, double b)
2290 {
2291         if (isnan(a))
2292                 return -1;
2293
2294         if (isnan(b))
2295                 return -1;
2296
2297         if (!finite(a) || !finite(b)) {
2298                 a = finite(a) ? 0 : copysign(1.0, a);
2299                 b = finite(b) ? 0 : copysign(1.0, b);
2300         }
2301
2302         if (a > b)
2303                 return 1;
2304
2305         if (a == b)
2306                 return 0;
2307
2308         return -1;
2309 }
2310
2311
2312 s4 builtin_dcmpg(double a, double b)
2313 {
2314         if (isnan(a))
2315                 return 1;
2316
2317         if (isnan(b))
2318                 return 1;
2319
2320         if (!finite(a) || !finite(b)) {
2321                 a = finite(a) ? 0 : copysign(1.0, a);
2322                 b = finite(b) ? 0 : copysign(1.0, b);
2323         }
2324
2325         if (a > b)
2326                 return 1;
2327
2328         if (a == b)
2329                 return 0;
2330
2331         return -1;
2332 }
2333 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2334
2335
2336 double builtin_drem(double a, double b)
2337 {
2338         return fmod(a, b);
2339 }
2340
2341
2342 /* conversion operations ******************************************************/
2343
2344 #if 0
2345 s8 builtin_i2l(s4 i)
2346 {
2347 #if U8_AVAILABLE
2348         return i;
2349 #else
2350         s8 v;
2351         v.high = 0;
2352         v.low = i;
2353         return v;
2354 #endif
2355 }
2356
2357 s4 builtin_l2i(s8 l)
2358 {
2359 #if U8_AVAILABLE
2360         return (s4) l;
2361 #else
2362         return l.low;
2363 #endif
2364 }
2365 #endif
2366
2367
2368 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2369 float builtin_i2f(s4 a)
2370 {
2371         float f = (float) a;
2372         return f;
2373 }
2374 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2375
2376
2377 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2378 double builtin_i2d(s4 a)
2379 {
2380         double d = (double) a;
2381         return d;
2382 }
2383 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2384
2385
2386 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2387 float builtin_l2f(s8 a)
2388 {
2389 #if U8_AVAILABLE
2390         float f = (float) a;
2391         return f;
2392 #else
2393         return 0.0;
2394 #endif
2395 }
2396 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2397
2398
2399 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2400 double builtin_l2d(s8 a)
2401 {
2402 #if U8_AVAILABLE
2403         double d = (double) a;
2404         return d;
2405 #else
2406         return 0.0;
2407 #endif
2408 }
2409 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2410
2411
2412 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2413 s4 builtin_f2i(float a) 
2414 {
2415         s4 i;
2416
2417         i = builtin_d2i((double) a);
2418
2419         return i;
2420
2421         /*      float f;
2422         
2423                 if (isnanf(a))
2424                 return 0;
2425                 if (finitef(a)) {
2426                 if (a > 2147483647)
2427                 return 2147483647;
2428                 if (a < (-2147483648))
2429                 return (-2147483648);
2430                 return (s4) a;
2431                 }
2432                 f = copysignf((float) 1.0, a);
2433                 if (f > 0)
2434                 return 2147483647;
2435                 return (-2147483648); */
2436 }
2437 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2438
2439
2440 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2441 s8 builtin_f2l(float a)
2442 {
2443         s8 l;
2444
2445         l = builtin_d2l((double) a);
2446
2447         return l;
2448
2449         /*      float f;
2450         
2451                 if (finitef(a)) {
2452                 if (a > 9223372036854775807L)
2453                 return 9223372036854775807L;
2454                 if (a < (-9223372036854775808L))
2455                 return (-9223372036854775808L);
2456                 return (s8) a;
2457                 }
2458                 if (isnanf(a))
2459                 return 0;
2460                 f = copysignf((float) 1.0, a);
2461                 if (f > 0)
2462                 return 9223372036854775807L;
2463                 return (-9223372036854775808L); */
2464 }
2465 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2466
2467
2468 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2469 s4 builtin_d2i(double a) 
2470
2471         double d;
2472         
2473         if (finite(a)) {
2474                 if (a >= 2147483647)
2475                         return 2147483647;
2476                 if (a <= (-2147483647-1))
2477                         return (-2147483647-1);
2478                 return (s4) a;
2479         }
2480         if (isnan(a))
2481                 return 0;
2482         d = copysign(1.0, a);
2483         if (d > 0)
2484                 return 2147483647;
2485         return (-2147483647-1);
2486 }
2487 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2488
2489
2490 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2491 s8 builtin_d2l(double a)
2492 {
2493         double d;
2494         
2495         if (finite(a)) {
2496                 if (a >= 9223372036854775807LL)
2497                         return 9223372036854775807LL;
2498                 if (a <= (-9223372036854775807LL-1))
2499                         return (-9223372036854775807LL-1);
2500                 return (s8) a;
2501         }
2502         if (isnan(a))
2503                 return 0;
2504         d = copysign(1.0, a);
2505         if (d > 0)
2506                 return 9223372036854775807LL;
2507         return (-9223372036854775807LL-1);
2508 }
2509 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2510
2511
2512 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2513 double builtin_f2d(float a)
2514 {
2515         if (finitef(a)) return (double) a;
2516         else {
2517                 if (isnanf(a))
2518                         return longBitsToDouble(DBL_NAN);
2519                 else
2520                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2521         }
2522 }
2523
2524 float builtin_d2f(double a)
2525 {
2526         if (finite(a))
2527                 return (float) a;
2528         else {
2529                 if (isnan(a))
2530                         return intBitsToFloat(FLT_NAN);
2531                 else
2532                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2533         }
2534 }
2535 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2536
2537
2538 /* builtin_arraycopy ***********************************************************
2539
2540    Builtin for java.lang.System.arraycopy.
2541
2542    ATTENTION: This builtin function returns a boolean value to signal
2543    the ICMD_BUILTIN if there was an exception.
2544
2545 *******************************************************************************/
2546
2547 bool builtin_arraycopy(java_arrayheader *src, s4 srcStart,
2548                                            java_arrayheader *dest, s4 destStart, s4 len)
2549 {
2550         arraydescriptor *sdesc;
2551         arraydescriptor *ddesc;
2552         s4               i;
2553
2554         if ((src == NULL) || (dest == NULL)) { 
2555                 exceptions_throw_nullpointerexception();
2556                 return false;
2557         }
2558
2559         sdesc = src->objheader.vftbl->arraydesc;
2560         ddesc = dest->objheader.vftbl->arraydesc;
2561
2562         if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2563                 exceptions_throw_arraystoreexception();
2564                 return false;
2565         }
2566
2567         /* we try to throw exception with the same message as SUN does */
2568
2569         if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2570                 (srcStart  + len < 0) || (srcStart  + len > src->size) ||
2571                 (destStart + len < 0) || (destStart + len > dest->size)) {
2572                 exceptions_throw_arrayindexoutofboundsexception();
2573                 return false;
2574         }
2575
2576         if (sdesc->componentvftbl == ddesc->componentvftbl) {
2577                 /* We copy primitive values or references of exactly the same type */
2578
2579                 s4 dataoffset = sdesc->dataoffset;
2580                 s4 componentsize = sdesc->componentsize;
2581
2582                 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2583                                 ((u1 *) src)  + dataoffset + componentsize * srcStart,
2584                                 (size_t) len * componentsize);
2585         }
2586         else {
2587                 /* We copy references of different type */
2588
2589                 java_objectarray *oas = (java_objectarray *) src;
2590                 java_objectarray *oad = (java_objectarray *) dest;
2591                 
2592                 if (destStart <= srcStart) {
2593                         for (i = 0; i < len; i++) {
2594                                 java_objectheader *o = oas->data[srcStart + i];
2595
2596                                 if (!builtin_canstore(oad, o))
2597                                         return false;
2598
2599                                 oad->data[destStart + i] = o;
2600                         }
2601                 }
2602                 else {
2603                         /* XXX this does not completely obey the specification!
2604                            If an exception is thrown only the elements above the
2605                            current index have been copied. The specification
2606                            requires that only the elements *below* the current
2607                            index have been copied before the throw. */
2608
2609                         for (i = len - 1; i >= 0; i--) {
2610                                 java_objectheader *o = oas->data[srcStart + i];
2611
2612                                 if (!builtin_canstore(oad, o))
2613                                         return false;
2614
2615                                 oad->data[destStart + i] = o;
2616                         }
2617                 }
2618         }
2619
2620         return true;
2621 }
2622
2623
2624 /* builtin_nanotime ************************************************************
2625
2626    Return the current time in nanoseconds.
2627
2628 *******************************************************************************/
2629
2630 s8 builtin_nanotime(void)
2631 {
2632         struct timeval tv;
2633         s8             usecs;
2634
2635         if (gettimeofday(&tv, NULL) == -1)
2636                 vm_abort("gettimeofday failed: %s", strerror(errno));
2637
2638         usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2639
2640         return usecs * 1000;
2641 }
2642
2643
2644 /* builtin_currenttimemillis ***************************************************
2645
2646    Return the current time in milliseconds.
2647
2648 *******************************************************************************/
2649
2650 s8 builtin_currenttimemillis(void)
2651 {
2652         s8 msecs;
2653
2654         msecs = builtin_nanotime() / 1000 / 1000;
2655
2656         return msecs;
2657 }
2658
2659
2660 /* builtin_clone ***************************************************************
2661
2662    Function for cloning objects or arrays.
2663
2664 *******************************************************************************/
2665
2666 java_objectheader *builtin_clone(void *env, java_objectheader *o)
2667 {
2668         arraydescriptor   *ad;
2669         java_arrayheader  *ah;
2670         u4                 size;
2671         classinfo         *c;
2672         java_objectheader *co;              /* cloned object header               */
2673
2674         /* get the array descriptor */
2675
2676         ad = o->vftbl->arraydesc;
2677
2678         /* we are cloning an array */
2679
2680         if (ad != NULL) {
2681                 ah = (java_arrayheader *) o;
2682
2683                 size = ad->dataoffset + ad->componentsize * ah->size;
2684         
2685                 co = heap_allocate(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL);
2686
2687                 if (co == NULL)
2688                         return NULL;
2689
2690                 MCOPY(co, o, u1, size);
2691
2692 #if defined(ENABLE_GC_CACAO)
2693                 heap_init_objectheader(co, size);
2694 #endif
2695
2696 #if defined(ENABLE_THREADS)
2697                 lock_init_object_lock(co);
2698 #endif
2699
2700                 return co;
2701         }
2702     
2703     /* we are cloning a non-array */
2704
2705     if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2706         exceptions_throw_clonenotsupportedexception();
2707         return NULL;
2708     }
2709
2710         /* get the class of the object */
2711
2712     c = o->vftbl->class;
2713
2714         /* create new object */
2715
2716     co = builtin_new(c);
2717
2718     if (co == NULL)
2719         return NULL;
2720
2721     MCOPY(co, o, u1, c->instancesize);
2722
2723 #if defined(ENABLE_GC_CACAO)
2724         heap_init_objectheader(co, c->instancesize);
2725 #endif
2726
2727 #if defined(ENABLE_THREADS)
2728         lock_init_object_lock(co);
2729 #endif
2730
2731     return co;
2732 }
2733
2734 #if defined(ENABLE_VMLOG)
2735 #define NDEBUG
2736 #include <vmlog_cacao.c>
2737 #endif
2738
2739
2740 /*
2741  * These are local overrides for various environment variables in Emacs.
2742  * Please do not remove this and leave it at the end of the file, where
2743  * Emacs will automagically detect them.
2744  * ---------------------------------------------------------------------
2745  * Local variables:
2746  * mode: c
2747  * indent-tabs-mode: t
2748  * c-basic-offset: 4
2749  * tab-width: 4
2750  * End:
2751  * vim:noexpandtab:sw=4:ts=4:
2752  */