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