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