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