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