* Merged with 79e3a1932e59.
[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 */
32
33
34 #include "config.h"
35
36 #include <assert.h>
37 #include <errno.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/time.h>
41
42 #include "vm/types.h"
43
44 #include "arch.h"
45 #include "md-abi.h"
46
47 #include "fdlibm/fdlibm.h"
48 #if defined(__CYGWIN__) && defined(Bias)
49 # undef Bias
50 #endif
51
52 #include "mm/gc-common.h"
53 #include "mm/memory.h"
54
55 #include "native/jni.h"
56 #include "native/llni.h"
57
58 #include "threads/lock-common.h"
59 #include "threads/threads-common.h"
60
61 #include "toolbox/logging.h"
62 #include "toolbox/util.h"
63
64 #include "vm/array.h"
65 #include "vm/builtin.h"
66 #include "vm/cycles-stats.h"
67 #include "vm/exceptions.h"
68 #include "vm/global.h"
69 #include "vm/initialize.h"
70 #include "vm/primitive.h"
71 #include "vm/stringlocal.h"
72
73 #include "vm/jit/asmpart.h"
74 #include "vm/jit/trace.h"
75
76 #include "vmcore/class.h"
77 #include "vmcore/linker.h"
78 #include "vmcore/loader.h"
79 #include "vmcore/options.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         methodinfo         *m;
111
112         /* mark start of dump memory area */
113
114         dumpsize = dump_size();
115
116         /* create a new descriptor pool */
117
118         descpool = descriptor_pool_new(class_java_lang_Object);
119
120         /* add some entries we need */
121
122         if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
123                 return false;
124
125         if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
126                 return false;
127
128         /* first add all descriptors to the pool */
129
130         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
131                 bte->name       = utf_new_char(bte->cname);
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.  NOTE: builtin-functions are treated
172            like static methods (no `this' pointer). */
173
174         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
175                 bte->md =
176                         descriptor_pool_parse_method_descriptor(descpool,
177                                                                                                         bte->descriptor,
178                                                                                                         ACC_STATIC | ACC_METHOD_BUILTIN,
179                                                                                                         NULL);
180
181                 /* generate a builtin stub if we need one */
182
183                 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
184                         m = method_new_builtin(bte);
185                         codegen_generate_stub_builtin(m, bte);
186                 }
187         }
188
189         for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
190                 bte->md =
191                         descriptor_pool_parse_method_descriptor(descpool,
192                                                                                                         bte->descriptor,
193                                                                                                         ACC_STATIC | ACC_METHOD_BUILTIN,
194                                                                                                         NULL);
195
196                 /* no stubs should be needed for this table */
197
198                 assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
199         }
200
201         for (bte = builtintable_function; bte->fp != NULL; bte++) {
202                 bte->md =
203                         descriptor_pool_parse_method_descriptor(descpool,
204                                                                                                         bte->descriptor,
205                                                                                                         ACC_STATIC | ACC_METHOD_BUILTIN,
206                                                                                                         NULL);
207
208                 /* generate a builtin stub if we need one */
209
210                 if (bte->flags & BUILTINTABLE_FLAG_STUB) {
211                         m = method_new_builtin(bte);
212                         codegen_generate_stub_builtin(m, bte);
213                 }
214         }
215
216         /* release dump area */
217
218         dump_release(dumpsize);
219
220         return true;
221 }
222
223
224 /* builtintable_comparator *****************************************************
225
226    qsort comparator for the automatic builtin table.
227
228 *******************************************************************************/
229
230 static int builtintable_comparator(const void *a, const void *b)
231 {
232         builtintable_entry *bte1;
233         builtintable_entry *bte2;
234
235         bte1 = (builtintable_entry *) a;
236         bte2 = (builtintable_entry *) b;
237
238         return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
239 }
240
241
242 /* builtintable_sort_automatic *************************************************
243
244    Sorts the automatic builtin table.
245
246 *******************************************************************************/
247
248 static void builtintable_sort_automatic(void)
249 {
250         s4 entries;
251
252         /* calculate table size statically (`- 1' comment see builtintable.inc) */
253
254         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
255
256         qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
257                   builtintable_comparator);
258 }
259
260
261 /* builtin_init ****************************************************************
262
263    Initialize the global table of builtin functions.
264
265 *******************************************************************************/
266
267 bool builtin_init(void)
268 {
269         /* initialize the builtin tables */
270
271         if (!builtintable_init())
272                 return false;
273
274         /* sort builtin tables */
275
276         builtintable_sort_automatic();
277
278         return true;
279 }
280
281
282 /* builtintable_get_internal ***************************************************
283
284    Finds an entry in the builtintable for internal functions and
285    returns the a pointer to the structure.
286
287 *******************************************************************************/
288
289 builtintable_entry *builtintable_get_internal(functionptr fp)
290 {
291         builtintable_entry *bte;
292
293         for (bte = builtintable_internal; bte->fp != NULL; bte++) {
294                 if (bte->fp == fp)
295                         return bte;
296         }
297
298         return NULL;
299 }
300
301
302 /* builtintable_get_automatic **************************************************
303
304    Finds an entry in the builtintable for functions which are replaced
305    automatically and returns the a pointer to the structure.
306
307 *******************************************************************************/
308
309 builtintable_entry *builtintable_get_automatic(s4 opcode)
310 {
311         builtintable_entry *first;
312         builtintable_entry *last;
313         builtintable_entry *middle;
314         s4                  half;
315         s4                  entries;
316
317         /* calculate table size statically (`- 1' comment see builtintable.inc) */
318
319         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
320
321         first = builtintable_automatic;
322         last = builtintable_automatic + entries;
323
324         while (entries > 0) {
325                 half = entries / 2;
326                 middle = first + half;
327
328                 if (middle->opcode < opcode) {
329                         first = middle + 1;
330                         entries -= half + 1;
331                 }
332                 else
333                         entries = half;
334         }
335
336         return (first != last ? first : NULL);
337 }
338
339
340 /* builtintable_replace_function ***********************************************
341
342    XXX
343
344 *******************************************************************************/
345
346 #if defined(ENABLE_JIT)
347 bool builtintable_replace_function(void *iptr_)
348 {
349         constant_FMIref    *mr;
350         builtintable_entry *bte;
351         instruction        *iptr;
352
353         iptr = (instruction *) iptr_; /* twisti will kill me ;) */
354
355         /* get name and descriptor of the function */
356
357         switch (iptr->opc) {
358         case ICMD_INVOKESTATIC:
359                 /* The instruction MUST be resolved, otherwise we run into
360                    lazy loading troubles.  Anyway, we should/can only replace
361                    very VM-close functions. */
362
363                 if (INSTRUCTION_IS_UNRESOLVED(iptr))
364                         return false;
365
366                 mr = iptr->sx.s23.s3.fmiref;
367                 break;  
368
369         default:
370                 return false;
371         }
372
373         /* search the function table */
374
375         for (bte = builtintable_function; bte->fp != NULL; bte++) {
376                 if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
377                         (mr->name                == bte->name) &&
378                         (mr->descriptor          == bte->descriptor)) {
379
380                         /* set the values in the instruction */
381
382                         iptr->opc           = bte->opcode;
383                         iptr->sx.s23.s3.bte = bte;
384
385                         if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
386                                 iptr->flags.bits |= INS_FLAG_CHECK;
387                         else
388                                 iptr->flags.bits &= ~INS_FLAG_CHECK;
389
390                         return true;
391                 }
392         }
393
394         return false;
395 }
396 #endif /* defined(ENABLE_JIT) */
397
398
399 /*****************************************************************************
400                                                                 TYPE CHECKS
401 *****************************************************************************/
402
403 /* builtin_instanceof **********************************************************
404
405    Checks if an object is an instance of some given class (or subclass
406    of that class). If class is an interface, checks if the interface
407    is implemented.
408
409    Return value: 1 ... o is an instance of class or implements the interface
410                  0 ... otherwise or if o == NULL
411                          
412 *******************************************************************************/
413
414 s4 builtin_instanceof(java_handle_t *o, classinfo *class)
415 {
416         classinfo *c;
417
418         if (o == NULL)
419                 return 0;
420
421         LLNI_class_get(o, c);
422
423         return class_isanysubclass(c, class);
424 }
425
426
427
428 /* builtin_checkcast ***********************************************************
429
430    The same as builtin_instanceof except that 1 is returned when o ==
431    NULL.
432                           
433 *******************************************************************************/
434
435 s4 builtin_checkcast(java_handle_t *o, classinfo *class)
436 {
437         classinfo *c;
438
439         if (o == NULL)
440                 return 1;
441
442         LLNI_class_get(o, c);
443
444         if (class_isanysubclass(c, class))
445                 return 1;
446
447         return 0;
448 }
449
450
451 /* builtin_descriptorscompatible ***********************************************
452
453    Checks if two array type descriptors are assignment compatible
454
455    Return value: 1 ... target = desc is possible
456                  0 ... otherwise
457                         
458 *******************************************************************************/
459
460 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
461                                                                                 arraydescriptor *target)
462 {
463         if (desc == target)
464                 return 1;
465
466         if (desc->arraytype != target->arraytype)
467                 return 0;
468
469         if (desc->arraytype != ARRAYTYPE_OBJECT)
470                 return 1;
471         
472         /* {both arrays are arrays of references} */
473
474         if (desc->dimension == target->dimension) {
475                 /* an array which contains elements of interface types is
476            allowed to be casted to Object (JOWENN)*/
477
478                 if ((desc->elementvftbl->baseval < 0) &&
479                         (target->elementvftbl->baseval == 1))
480                         return 1;
481
482                 return class_isanysubclass(desc->elementvftbl->class,
483                                                                    target->elementvftbl->class);
484         }
485
486         if (desc->dimension < target->dimension)
487                 return 0;
488
489         /* {desc has higher dimension than target} */
490
491         return class_isanysubclass(pseudo_class_Arraystub,
492                                                            target->elementvftbl->class);
493 }
494
495
496 /* builtin_arraycheckcast ******************************************************
497
498    Checks if an object is really a subtype of the requested array
499    type.  The object has to be an array to begin with. For simple
500    arrays (int, short, double, etc.) the types have to match exactly.
501    For arrays of objects, the type of elements in the array has to be
502    a subtype (or the same type) of the requested element type. For
503    arrays of arrays (which in turn can again be arrays of arrays), the
504    types at the lowest level have to satisfy the corresponding sub
505    class relation.
506         
507 *******************************************************************************/
508
509 s4 builtin_arraycheckcast(java_handle_t *o, classinfo *targetclass)
510 {
511         arraydescriptor *desc;
512
513         if (o == NULL)
514                 return 1;
515
516         desc = LLNI_vftbl_direct(o)->arraydesc;
517
518         if (desc == NULL)
519                 return 0;
520  
521         return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
522 }
523
524
525 s4 builtin_arrayinstanceof(java_handle_t *o, classinfo *targetclass)
526 {
527         if (o == NULL)
528                 return 0;
529
530         return builtin_arraycheckcast(o, targetclass);
531 }
532
533
534 /* builtin_throw_exception *****************************************************
535
536    Sets the exceptionptr with the thrown exception and prints some
537    debugging information.  Called from asm_vm_call_method.
538
539 *******************************************************************************/
540
541 void *builtin_throw_exception(java_object_t *xptr)
542 {
543 #if !defined(NDEBUG)
544         /* print exception trace */
545
546         if (opt_TraceExceptions)
547                 trace_exception_builtin(xptr);
548 #endif /* !defined(NDEBUG) */
549
550         /* actually set the exception */
551
552         exceptions_set_exception(xptr);
553
554         /* Return a NULL pointer.  This is required for vm_call_method to
555            check for an exception.  This is for convenience. */
556
557         return NULL;
558 }
559
560
561 /* builtin_canstore ************************************************************
562
563    Checks, if an object can be stored in an array.
564
565    Return value: 1 ... possible
566                  0 ... otherwise (throws an ArrayStoreException)
567
568 *******************************************************************************/
569
570 s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
571 {
572         int result;
573
574         LLNI_CRITICAL_START;
575
576         result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
577
578         LLNI_CRITICAL_END;
579
580         /* if not possible, throw an exception */
581
582         if (result == 0)
583                 exceptions_throw_arraystoreexception();
584
585         return result;
586 }
587
588
589 s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
590 {
591         arraydescriptor *desc;
592         arraydescriptor *valuedesc;
593         vftbl_t         *componentvftbl;
594         vftbl_t         *valuevftbl;
595         int32_t          baseval;
596         uint32_t         diffval;
597         int              result;
598
599         if (o == NULL)
600                 return 1;
601
602         /* The following is guaranteed (by verifier checks):
603          *
604          *     *) oa->...vftbl->arraydesc != NULL
605          *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
606          *     *) o->vftbl is not an interface vftbl
607          */
608         
609         desc           = oa->header.objheader.vftbl->arraydesc;
610         componentvftbl = desc->componentvftbl;
611         valuevftbl     = o->vftbl;
612         valuedesc      = valuevftbl->arraydesc;
613
614         if ((desc->dimension - 1) == 0) {
615                 /* {oa is a one-dimensional array} */
616                 /* {oa is an array of references} */
617                 
618                 if (valuevftbl == componentvftbl)
619                         return 1;
620
621                 LOCK_MONITOR_ENTER(linker_classrenumber_lock);
622
623                 baseval = componentvftbl->baseval;
624
625                 if (baseval <= 0) {
626                         /* an array of interface references */
627
628                         result = ((valuevftbl->interfacetablelength > -baseval) &&
629                                           (valuevftbl->interfacetable[baseval] != NULL));
630                 }
631                 else {
632                         diffval = valuevftbl->baseval - componentvftbl->baseval;
633                         result  = diffval <= (uint32_t) componentvftbl->diffval;
634                 }
635
636                 LOCK_MONITOR_EXIT(linker_classrenumber_lock);
637         }
638         else if (valuedesc == NULL) {
639                 /* {oa has dimension > 1} */
640                 /* {componentvftbl->arraydesc != NULL} */
641
642                 /* check if o is an array */
643
644                 return 0;
645         }
646         else {
647                 /* {o is an array} */
648
649                 result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
650         }
651
652         /* return result */
653
654         return result;
655 }
656
657
658 /* This is an optimized version where a is guaranteed to be one-dimensional */
659 s4 builtin_canstore_onedim (java_objectarray_t *a, java_object_t *o)
660 {
661         arraydescriptor *desc;
662         vftbl_t         *elementvftbl;
663         vftbl_t         *valuevftbl;
664         int32_t          baseval;
665         uint32_t         diffval;
666         int              result;
667         
668         if (o == NULL)
669                 return 1;
670
671         /* The following is guaranteed (by verifier checks):
672          *
673          *     *) a->...vftbl->arraydesc != NULL
674          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
675          *     *) a->...vftbl->arraydesc->dimension == 1
676          *     *) o->vftbl is not an interface vftbl
677          */
678
679         desc = a->header.objheader.vftbl->arraydesc;
680     elementvftbl = desc->elementvftbl;
681         valuevftbl = o->vftbl;
682
683         /* {a is a one-dimensional array} */
684         
685         if (valuevftbl == elementvftbl)
686                 return 1;
687
688         LOCK_MONITOR_ENTER(linker_classrenumber_lock);
689
690         baseval = elementvftbl->baseval;
691
692         if (baseval <= 0) {
693                 /* an array of interface references */
694                 result = ((valuevftbl->interfacetablelength > -baseval) &&
695                                   (valuevftbl->interfacetable[baseval] != NULL));
696         }
697         else {
698                 diffval = valuevftbl->baseval - elementvftbl->baseval;
699                 result  = diffval <= (uint32_t) elementvftbl->diffval;
700         }
701
702         LOCK_MONITOR_EXIT(linker_classrenumber_lock);
703
704         return result;
705 }
706
707
708 /* This is an optimized version where a is guaranteed to be a
709  * one-dimensional array of a class type */
710 s4 builtin_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
711 {
712         vftbl_t  *elementvftbl;
713         vftbl_t  *valuevftbl;
714         uint32_t  diffval;
715         int       result;
716         
717         if (o == NULL)
718                 return 1;
719
720         /* The following is guaranteed (by verifier checks):
721          *
722          *     *) a->...vftbl->arraydesc != NULL
723          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
724          *     *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
725          *     *) a->...vftbl->arraydesc->dimension == 1
726          *     *) o->vftbl is not an interface vftbl
727          */
728
729     elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
730         valuevftbl = o->vftbl;
731
732         /* {a is a one-dimensional array} */
733         
734         if (valuevftbl == elementvftbl)
735                 return 1;
736
737         LOCK_MONITOR_ENTER(linker_classrenumber_lock);
738
739         diffval = valuevftbl->baseval - elementvftbl->baseval;
740         result  = diffval <= (uint32_t) elementvftbl->diffval;
741
742         LOCK_MONITOR_EXIT(linker_classrenumber_lock);
743
744         return result;
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_handle_t *builtin_new(classinfo *c)
758 {
759         java_object_t *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_object_t *builtin_fast_new(classinfo *c)
829 {
830         java_object_t *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_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
890 {
891         arraydescriptor *desc;
892         s4               dataoffset;
893         s4               componentsize;
894         s4               actualsize;
895         java_array_t    *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         LLNI_array_size(a) = 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_handle_objectarray_t *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_handle_objectarray_t *) 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_handle_booleanarray_t *builtin_newarray_boolean(s4 size)
983 {
984         return (java_handle_booleanarray_t *)
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_handle_bytearray_t *builtin_newarray_byte(s4 size)
1000 {
1001         return (java_handle_bytearray_t *)
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_handle_chararray_t *builtin_newarray_char(s4 size)
1016 {
1017         return (java_handle_chararray_t *)
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_handle_shortarray_t *builtin_newarray_short(s4 size)
1032 {
1033         return (java_handle_shortarray_t *)
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_handle_intarray_t *builtin_newarray_int(s4 size)
1048 {
1049         return (java_handle_intarray_t *)
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_handle_longarray_t *builtin_newarray_long(s4 size)
1064 {
1065         return (java_handle_longarray_t *)
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_handle_floatarray_t *builtin_newarray_float(s4 size)
1080 {
1081         return (java_handle_floatarray_t *)
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_handle_doublearray_t *builtin_newarray_double(s4 size)
1096 {
1097         return (java_handle_doublearray_t *)
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_handle_t *builtin_multianewarray_intern(int n,
1119                                                                                                         classinfo *arrayclass,
1120                                                                                                         long *dims)
1121 {
1122         s4             size;
1123         java_handle_t *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_handle_t *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                 LLNI_objectarray_element_set((java_handle_objectarray_t *) a, i, 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_handle_objectarray_t *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 (java_handle_objectarray_t *)
1200                 builtin_multianewarray_intern(n, arrayclass, dims);
1201 }
1202
1203
1204 /*****************************************************************************
1205                                           METHOD LOGGING
1206
1207         Various functions for printing a message at method entry or exit (for
1208         debugging)
1209         
1210 *****************************************************************************/
1211
1212 /* builtin_print_argument ******************************************************
1213
1214    Prints arguments and return values for the call trace.
1215
1216 *******************************************************************************/
1217
1218 #if !defined(NDEBUG)
1219 static char *builtin_print_argument(char *logtext, s4 *logtextlen,
1220                                                                         typedesc *paramtype, s8 value)
1221 {
1222         imm_union          imu;
1223         java_object_t     *o;
1224         classinfo         *c;
1225         utf               *u;
1226         u4                 len;
1227
1228         switch (paramtype->type) {
1229         case TYPE_INT:
1230                 imu.i = (s4) value;
1231                 sprintf(logtext + strlen(logtext), "%d (0x%08x)", imu.i, imu.i);
1232                 break;
1233
1234         case TYPE_LNG:
1235                 imu.l = value;
1236 #if SIZEOF_VOID_P == 4
1237                 sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
1238 #else
1239                 sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
1240 #endif
1241                 break;
1242
1243         case TYPE_FLT:
1244 #if defined(__S390__)
1245                 imu.l = value;
1246                 /* The below won't work on S390 */
1247 #else
1248                 imu.i = (s4) value;
1249 #endif
1250                 sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
1251                 break;
1252
1253         case TYPE_DBL:
1254                 imu.l = value;
1255 #if SIZEOF_VOID_P == 4
1256                 sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
1257 #else
1258                 sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
1259 #endif
1260                 break;
1261
1262         case TYPE_ADR:
1263 #if SIZEOF_VOID_P == 4
1264                 sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) value);
1265 #else
1266                 sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) value);
1267 #endif
1268
1269                 /* cast to java.lang.Object */
1270
1271                 o = (java_object_t *) (ptrint) value;
1272
1273                 /* check return argument for java.lang.Class or java.lang.String */
1274
1275                 if (o != NULL) {
1276                         if (o->vftbl->class == class_java_lang_String) {
1277                                 /* get java.lang.String object and the length of the
1278                                    string */
1279
1280                                 u = javastring_toutf(o, false);
1281
1282                                 len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
1283
1284                                 /* realloc memory for string length */
1285
1286                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1287                                 *logtextlen += len;
1288
1289                                 /* convert to utf8 string and strcat it to the logtext */
1290
1291                                 strcat(logtext, " (String = \"");
1292                                 utf_cat(logtext, u);
1293                                 strcat(logtext, "\")");
1294                         }
1295                         else {
1296                                 if (o->vftbl->class == class_java_lang_Class) {
1297                                         /* if the object returned is a java.lang.Class
1298                                            cast it to classinfo structure and get the name
1299                                            of the class */
1300
1301                                         c = (classinfo *) o;
1302
1303                                         u = c->name;
1304                                 }
1305                                 else {
1306                                         /* if the object returned is not a java.lang.String or
1307                                            a java.lang.Class just print the name of the class */
1308
1309                                         u = o->vftbl->class->name;
1310                                 }
1311
1312                                 len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
1313
1314                                 /* realloc memory for string length */
1315
1316                                 logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
1317                                 *logtextlen += len;
1318
1319                                 /* strcat to the logtext */
1320
1321                                 strcat(logtext, " (Class = \"");
1322                                 utf_cat_classname(logtext, u);
1323                                 strcat(logtext, "\")");
1324                         }
1325                 }
1326         }
1327
1328         return logtext;
1329 }
1330 #endif /* !defined(NDEBUG) */
1331
1332 /* builtin_verbosecall_enter ***************************************************
1333
1334    Print method call with arguments for -verbose:call.
1335
1336 *******************************************************************************/
1337
1338 #if !defined(NDEBUG)
1339
1340 #ifdef TRACE_ARGS_NUM
1341 void builtin_verbosecall_enter(s8 a0, s8 a1,
1342 # if TRACE_ARGS_NUM >= 4
1343                                                            s8 a2, s8 a3,
1344 # endif
1345 # if TRACE_ARGS_NUM >= 6
1346                                                            s8 a4, s8 a5,
1347 # endif
1348 # if TRACE_ARGS_NUM == 8
1349                                                            s8 a6, s8 a7,
1350 # endif
1351                                                            methodinfo *m)
1352 {
1353         methoddesc *md;
1354         char       *logtext;
1355         s4          logtextlen;
1356         s4          dumpsize;
1357         s4          i;
1358         s4          pos;
1359         int         methodindent;
1360         int         callcount;
1361
1362 #if defined(ENABLE_DEBUG_FILTER)
1363         if (! show_filters_test_verbosecall_enter(m)) return;
1364 #endif
1365
1366 #if defined(ENABLE_VMLOG)
1367         vmlog_cacao_enter_method(m);
1368         return;
1369 #endif
1370
1371         md = m->parseddesc;
1372
1373         methodindent = TRACEJAVACALLINDENT;
1374
1375         /* calculate message length */
1376
1377         logtextlen =
1378                 strlen("4294967295 ") +
1379                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1380                 methodindent +
1381                 strlen("called: ") +
1382                 utf_bytes(m->class->name) +
1383                 strlen(".") +
1384                 utf_bytes(m->name) +
1385                 utf_bytes(m->descriptor);
1386
1387         /* Actually it's not possible to have all flags printed, but:
1388            safety first! */
1389
1390         logtextlen +=
1391                 strlen(" PUBLIC") +
1392                 strlen(" PRIVATE") +
1393                 strlen(" PROTECTED") +
1394                 strlen(" STATIC") +
1395                 strlen(" FINAL") +
1396                 strlen(" SYNCHRONIZED") +
1397                 strlen(" VOLATILE") +
1398                 strlen(" TRANSIENT") +
1399                 strlen(" NATIVE") +
1400                 strlen(" INTERFACE") +
1401                 strlen(" ABSTRACT");
1402
1403         /* add maximal argument length */
1404
1405         logtextlen +=
1406                 strlen("(") +
1407                 strlen("-9223372036854775808 (0x123456789abcdef0), ") * TRACE_ARGS_NUM +
1408                 strlen("...(255)") +
1409                 strlen(")");
1410
1411         /* allocate memory */
1412
1413         dumpsize = dump_size();
1414
1415         logtext = DMNEW(char, logtextlen);
1416
1417         callcount = ++TRACEJAVACALLCOUNT;
1418
1419         sprintf(logtext, "%10d ", callcount);
1420         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1421
1422         pos = strlen(logtext);
1423
1424         for (i = 0; i < methodindent; i++)
1425                 logtext[pos++] = '\t';
1426
1427         strcpy(logtext + pos, "called: ");
1428
1429         utf_cat_classname(logtext, m->class->name);
1430         strcat(logtext, ".");
1431         utf_cat(logtext, m->name);
1432         utf_cat(logtext, m->descriptor);
1433
1434         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1435         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1436         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1437         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1438         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1439         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1440         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1441         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1442         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1443         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1444         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1445
1446         strcat(logtext, "(");
1447
1448         if (md->paramcount >= 1) {
1449                 logtext = builtin_print_argument(logtext, &logtextlen,
1450                                                                                  &md->paramtypes[0], a0);
1451         }
1452
1453         if (md->paramcount >= 2) {
1454                 strcat(logtext, ", ");
1455
1456                 logtext = builtin_print_argument(logtext, &logtextlen,
1457                                                                                  &md->paramtypes[1], a1);
1458         }
1459
1460 #if TRACE_ARGS_NUM >= 4
1461         if (md->paramcount >= 3) {
1462                 strcat(logtext, ", ");
1463
1464                 logtext = builtin_print_argument(logtext, &logtextlen,
1465                                                                                  &md->paramtypes[2], a2);
1466         }
1467
1468         if (md->paramcount >= 4) {
1469                 strcat(logtext, ", ");
1470
1471                 logtext = builtin_print_argument(logtext, &logtextlen,
1472                                                                                  &md->paramtypes[3], a3);
1473         }
1474 #endif
1475
1476 #if TRACE_ARGS_NUM >= 6
1477         if (md->paramcount >= 5) {
1478                 strcat(logtext, ", ");
1479
1480                 logtext = builtin_print_argument(logtext, &logtextlen,
1481                                                                                  &md->paramtypes[4], a4);
1482         }
1483
1484         if (md->paramcount >= 6) {
1485                 strcat(logtext, ", ");
1486
1487                 logtext = builtin_print_argument(logtext, &logtextlen,
1488                                                                                  &md->paramtypes[5], a5);
1489         }
1490 #endif
1491
1492 #if TRACE_ARGS_NUM == 8
1493         if (md->paramcount >= 7) {
1494                 strcat(logtext, ", ");
1495
1496                 logtext = builtin_print_argument(logtext, &logtextlen,
1497                                                                                  &md->paramtypes[6], a6);
1498         }
1499
1500         if (md->paramcount >= 8) {
1501                 strcat(logtext, ", ");
1502
1503                 logtext = builtin_print_argument(logtext, &logtextlen,
1504                                                                                  &md->paramtypes[7], a7);
1505         }
1506 #endif
1507
1508         if (md->paramcount > 8) {
1509                 sprintf(logtext + strlen(logtext), ", ...(%d)",
1510                                 md->paramcount - TRACE_ARGS_NUM);
1511         }
1512
1513         strcat(logtext, ")");
1514
1515         log_text(logtext);
1516
1517         /* release memory */
1518
1519         dump_release(dumpsize);
1520
1521         TRACEJAVACALLINDENT++;
1522
1523 }
1524 #endif
1525 #endif /* !defined(NDEBUG) */
1526
1527
1528 /* builtin_verbosecall_exit ****************************************************
1529
1530    Print method exit for -verbose:call.
1531
1532 *******************************************************************************/
1533
1534 #if !defined(NDEBUG)
1535 void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
1536 {
1537         methoddesc *md;
1538         char       *logtext;
1539         s4          logtextlen;
1540         s4          dumpsize;
1541         s4          i;
1542         s4          pos;
1543         imm_union   val;
1544         int         methodindent;
1545
1546 #if defined(ENABLE_DEBUG_FILTER)
1547         if (! show_filters_test_verbosecall_exit(m)) return;
1548 #endif
1549
1550 #if defined(ENABLE_VMLOG)
1551         vmlog_cacao_leave_method(m);
1552         return;
1553 #endif
1554
1555         md = m->parseddesc;
1556
1557         /* outdent the log message */
1558
1559         if (TRACEJAVACALLINDENT)
1560                 TRACEJAVACALLINDENT--;
1561         else
1562                 log_text("WARNING: unmatched methodindent--");
1563
1564         methodindent = TRACEJAVACALLINDENT;
1565
1566         /* calculate message length */
1567
1568         logtextlen =
1569                 strlen("4294967295 ") +
1570                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1571                 methodindent +
1572                 strlen("finished: ") +
1573                 utf_bytes(m->class->name) +
1574                 strlen(".") +
1575                 utf_bytes(m->name) +
1576                 utf_bytes(m->descriptor) +
1577                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1578
1579         /* add maximal argument length */
1580
1581         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1582
1583         /* allocate memory */
1584
1585         dumpsize = dump_size();
1586
1587         logtext = DMNEW(char, logtextlen);
1588
1589         /* generate the message */
1590
1591         sprintf(logtext, "           ");
1592         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1593
1594         pos = strlen(logtext);
1595
1596         for (i = 0; i < methodindent; i++)
1597                 logtext[pos++] = '\t';
1598
1599         strcpy(logtext + pos, "finished: ");
1600         utf_cat_classname(logtext, m->class->name);
1601         strcat(logtext, ".");
1602         utf_cat(logtext, m->name);
1603         utf_cat(logtext, m->descriptor);
1604
1605         if (!IS_VOID_TYPE(md->returntype.type)) {
1606                 strcat(logtext, "->");
1607
1608                 switch (md->returntype.type) {
1609                 case TYPE_INT:
1610                 case TYPE_LNG:
1611                 case TYPE_ADR:
1612                         val.l = l;
1613                         break;
1614
1615                 case TYPE_FLT:
1616                         val.f = f;
1617                         break;
1618
1619                 case TYPE_DBL:
1620                         val.d = d;
1621                         break;
1622                 }
1623
1624                 logtext =
1625                         builtin_print_argument(logtext, &logtextlen, &md->returntype, val.l);
1626         }
1627
1628         log_text(logtext);
1629
1630         /* release memory */
1631
1632         dump_release(dumpsize);
1633
1634 }
1635 #endif /* !defined(NDEBUG) */
1636
1637
1638 #if defined(ENABLE_CYCLES_STATS)
1639 void builtin_print_cycles_stats(FILE *file)
1640 {
1641         fprintf(file,"builtin cylce count statistics:\n");
1642
1643         CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1644         CYCLES_STATS_PRINT(builtin_new         ,file);
1645
1646         fprintf(file,"\n");
1647 }
1648 #endif /* defined(ENABLE_CYCLES_STATS) */
1649
1650
1651 /*****************************************************************************
1652                           MISCELLANEOUS HELPER FUNCTIONS
1653 *****************************************************************************/
1654
1655
1656
1657 /*********** Functions for integer divisions *****************************
1658  
1659         On some systems (eg. DEC ALPHA), integer division is not supported by the
1660         CPU. These helper functions implement the missing functionality.
1661
1662 ******************************************************************************/
1663
1664 #if !SUPPORT_DIVISION || defined(DISABLE_GC)
1665 s4 builtin_idiv(s4 a, s4 b)
1666 {
1667         s4 c;
1668
1669         c = a / b;
1670
1671         return c;
1672 }
1673
1674 s4 builtin_irem(s4 a, s4 b)
1675 {
1676         s4 c;
1677
1678         c = a % b;
1679
1680         return c;
1681 }
1682 #endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
1683
1684
1685 /* functions for long arithmetics **********************************************
1686
1687    On systems where 64 bit Integers are not supported by the CPU,
1688    these functions are needed.
1689
1690 ******************************************************************************/
1691
1692 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1693 s8 builtin_ladd(s8 a, s8 b)
1694 {
1695         s8 c;
1696
1697 #if U8_AVAILABLE
1698         c = a + b; 
1699 #else
1700         c = builtin_i2l(0);
1701 #endif
1702
1703         return c;
1704 }
1705
1706 s8 builtin_lsub(s8 a, s8 b)
1707 {
1708         s8 c;
1709
1710 #if U8_AVAILABLE
1711         c = a - b; 
1712 #else
1713         c = builtin_i2l(0);
1714 #endif
1715
1716         return c;
1717 }
1718
1719 s8 builtin_lneg(s8 a)
1720 {
1721         s8 c;
1722
1723 #if U8_AVAILABLE
1724         c = -a;
1725 #else
1726         c = builtin_i2l(0);
1727 #endif
1728
1729         return c;
1730 }
1731 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1732
1733
1734 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1735 s8 builtin_lmul(s8 a, s8 b)
1736 {
1737         s8 c;
1738
1739 #if U8_AVAILABLE
1740         c = a * b; 
1741 #else
1742         c = builtin_i2l(0);
1743 #endif
1744
1745         return c;
1746 }
1747 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1748
1749
1750 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
1751 s8 builtin_ldiv(s8 a, s8 b)
1752 {
1753         s8 c;
1754
1755 #if U8_AVAILABLE
1756         c = a / b; 
1757 #else
1758         c = builtin_i2l(0);
1759 #endif
1760
1761         return c;
1762 }
1763
1764 s8 builtin_lrem(s8 a, s8 b)
1765 {
1766         s8 c;
1767
1768 #if U8_AVAILABLE
1769         c = a % b; 
1770 #else
1771         c = builtin_i2l(0);
1772 #endif
1773
1774         return c;
1775 }
1776 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
1777
1778
1779 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
1780 s8 builtin_lshl(s8 a, s4 b)
1781 {
1782         s8 c;
1783
1784 #if U8_AVAILABLE
1785         c = a << (b & 63);
1786 #else
1787         c = builtin_i2l(0);
1788 #endif
1789
1790         return c;
1791 }
1792
1793 s8 builtin_lshr(s8 a, s4 b)
1794 {
1795         s8 c;
1796
1797 #if U8_AVAILABLE
1798         c = a >> (b & 63);
1799 #else
1800         c = builtin_i2l(0);
1801 #endif
1802
1803         return c;
1804 }
1805
1806 s8 builtin_lushr(s8 a, s4 b)
1807 {
1808         s8 c;
1809
1810 #if U8_AVAILABLE
1811         c = ((u8) a) >> (b & 63);
1812 #else
1813         c = builtin_i2l(0);
1814 #endif
1815
1816         return c;
1817 }
1818 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
1819
1820
1821 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
1822 s8 builtin_land(s8 a, s8 b)
1823 {
1824         s8 c;
1825
1826 #if U8_AVAILABLE
1827         c = a & b; 
1828 #else
1829         c = builtin_i2l(0);
1830 #endif
1831
1832         return c;
1833 }
1834
1835 s8 builtin_lor(s8 a, s8 b)
1836 {
1837         s8 c;
1838
1839 #if U8_AVAILABLE
1840         c = a | b; 
1841 #else
1842         c = builtin_i2l(0);
1843 #endif
1844
1845         return c;
1846 }
1847
1848 s8 builtin_lxor(s8 a, s8 b) 
1849 {
1850         s8 c;
1851
1852 #if U8_AVAILABLE
1853         c = a ^ b; 
1854 #else
1855         c = builtin_i2l(0);
1856 #endif
1857
1858         return c;
1859 }
1860 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
1861
1862
1863 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
1864 s4 builtin_lcmp(s8 a, s8 b)
1865
1866 #if U8_AVAILABLE
1867         if (a < b)
1868                 return -1;
1869
1870         if (a > b)
1871                 return 1;
1872
1873         return 0;
1874 #else
1875         return 0;
1876 #endif
1877 }
1878 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
1879
1880
1881 /* functions for unsupported floating instructions ****************************/
1882
1883 /* used to convert FLT_xxx defines into float values */
1884
1885 static inline float intBitsToFloat(s4 i)
1886 {
1887         imm_union imb;
1888
1889         imb.i = i;
1890         return imb.f;
1891 }
1892
1893
1894 /* used to convert DBL_xxx defines into double values */
1895
1896 static inline float longBitsToDouble(s8 l)
1897 {
1898         imm_union imb;
1899
1900         imb.l = l;
1901         return imb.d;
1902 }
1903
1904
1905 #if !SUPPORT_FLOAT
1906 float builtin_fadd(float a, float b)
1907 {
1908         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1909         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1910         if (finitef(a)) {
1911                 if (finitef(b))
1912                         return a + b;
1913                 else
1914                         return b;
1915         }
1916         else {
1917                 if (finitef(b))
1918                         return a;
1919                 else {
1920                         if (copysignf(1.0, a) == copysignf(1.0, b))
1921                                 return a;
1922                         else
1923                                 return intBitsToFloat(FLT_NAN);
1924                 }
1925         }
1926 }
1927
1928
1929 float builtin_fsub(float a, float b)
1930 {
1931         return builtin_fadd(a, builtin_fneg(b));
1932 }
1933
1934
1935 float builtin_fmul(float a, float b)
1936 {
1937         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1938         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1939         if (finitef(a)) {
1940                 if (finitef(b)) return a * b;
1941                 else {
1942                         if (a == 0) return intBitsToFloat(FLT_NAN);
1943                         else return copysignf(b, copysignf(1.0, b)*a);
1944                 }
1945         }
1946         else {
1947                 if (finitef(b)) {
1948                         if (b == 0) return intBitsToFloat(FLT_NAN);
1949                         else return copysignf(a, copysignf(1.0, a)*b);
1950                 }
1951                 else {
1952                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1953                 }
1954         }
1955 }
1956
1957
1958 /* builtin_ddiv ****************************************************************
1959
1960    Implementation as described in VM Spec.
1961
1962 *******************************************************************************/
1963
1964 float builtin_fdiv(float a, float b)
1965 {
1966         if (finitef(a)) {
1967                 if (finitef(b)) {
1968                         /* If neither value1' nor value2' is NaN, the sign of the result */
1969                         /* is positive if both values have the same sign, negative if the */
1970                         /* values have different signs. */
1971
1972                         return a / b;
1973
1974                 } else {
1975                         if (isnanf(b)) {
1976                                 /* If either value1' or value2' is NaN, the result is NaN. */
1977
1978                                 return intBitsToFloat(FLT_NAN);
1979
1980                         } else {
1981                                 /* Division of a finite value by an infinity results in a */
1982                                 /* signed zero, with the sign-producing rule just given. */
1983
1984                                 /* is sign equal? */
1985
1986                                 if (copysignf(1.0, a) == copysignf(1.0, b))
1987                                         return 0.0;
1988                                 else
1989                                         return -0.0;
1990                         }
1991                 }
1992
1993         } else {
1994                 if (isnanf(a)) {
1995                         /* If either value1' or value2' is NaN, the result is NaN. */
1996
1997                         return intBitsToFloat(FLT_NAN);
1998
1999                 } else if (finitef(b)) {
2000                         /* Division of an infinity by a finite value results in a signed */
2001                         /* infinity, with the sign-producing rule just given. */
2002
2003                         /* is sign equal? */
2004
2005                         if (copysignf(1.0, a) == copysignf(1.0, b))
2006                                 return intBitsToFloat(FLT_POSINF);
2007                         else
2008                                 return intBitsToFloat(FLT_NEGINF);
2009
2010                 } else {
2011                         /* Division of an infinity by an infinity results in NaN. */
2012
2013                         return intBitsToFloat(FLT_NAN);
2014                 }
2015         }
2016 }
2017
2018
2019 float builtin_fneg(float a)
2020 {
2021         if (isnanf(a)) return a;
2022         else {
2023                 if (finitef(a)) return -a;
2024                 else return copysignf(a, -copysignf(1.0, a));
2025         }
2026 }
2027 #endif /* !SUPPORT_FLOAT */
2028
2029
2030 #if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
2031 s4 builtin_fcmpl(float a, float b)
2032 {
2033         if (isnanf(a))
2034                 return -1;
2035
2036         if (isnanf(b))
2037                 return -1;
2038
2039         if (!finitef(a) || !finitef(b)) {
2040                 a = finitef(a) ? 0 : copysignf(1.0,     a);
2041                 b = finitef(b) ? 0 : copysignf(1.0, b);
2042         }
2043
2044         if (a > b)
2045                 return 1;
2046
2047         if (a == b)
2048                 return 0;
2049
2050         return -1;
2051 }
2052
2053
2054 s4 builtin_fcmpg(float a, float b)
2055 {
2056         if (isnanf(a)) return 1;
2057         if (isnanf(b)) return 1;
2058         if (!finitef(a) || !finitef(b)) {
2059                 a = finitef(a) ? 0 : copysignf(1.0, a);
2060                 b = finitef(b) ? 0 : copysignf(1.0, b);
2061         }
2062         if (a > b) return 1;
2063         if (a == b) return 0;
2064         return -1;
2065 }
2066 #endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
2067
2068
2069 float builtin_frem(float a, float b)
2070 {
2071         return fmodf(a, b);
2072 }
2073
2074
2075 /* functions for unsupported double instructions ******************************/
2076
2077 #if !SUPPORT_DOUBLE
2078 double builtin_dadd(double a, double b)
2079 {
2080         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2081         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2082         if (finite(a)) {
2083                 if (finite(b)) return a + b;
2084                 else return b;
2085         }
2086         else {
2087                 if (finite(b)) return a;
2088                 else {
2089                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
2090                         else return longBitsToDouble(DBL_NAN);
2091                 }
2092         }
2093 }
2094
2095
2096 double builtin_dsub(double a, double b)
2097 {
2098         return builtin_dadd(a, builtin_dneg(b));
2099 }
2100
2101
2102 double builtin_dmul(double a, double b)
2103 {
2104         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2105         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2106         if (finite(a)) {
2107                 if (finite(b)) return a * b;
2108                 else {
2109                         if (a == 0) return longBitsToDouble(DBL_NAN);
2110                         else return copysign(b, copysign(1.0, b) * a);
2111                 }
2112         }
2113         else {
2114                 if (finite(b)) {
2115                         if (b == 0) return longBitsToDouble(DBL_NAN);
2116                         else return copysign(a, copysign(1.0, a) * b);
2117                 }
2118                 else {
2119                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2120                 }
2121         }
2122 }
2123
2124
2125 /* builtin_ddiv ****************************************************************
2126
2127    Implementation as described in VM Spec.
2128
2129 *******************************************************************************/
2130
2131 double builtin_ddiv(double a, double b)
2132 {
2133         if (finite(a)) {
2134                 if (finite(b)) {
2135                         /* If neither value1' nor value2' is NaN, the sign of the result */
2136                         /* is positive if both values have the same sign, negative if the */
2137                         /* values have different signs. */
2138
2139                         return a / b;
2140
2141                 } else {
2142                         if (isnan(b)) {
2143                                 /* If either value1' or value2' is NaN, the result is NaN. */
2144
2145                                 return longBitsToDouble(DBL_NAN);
2146
2147                         } else {
2148                                 /* Division of a finite value by an infinity results in a */
2149                                 /* signed zero, with the sign-producing rule just given. */
2150
2151                                 /* is sign equal? */
2152
2153                                 if (copysign(1.0, a) == copysign(1.0, b))
2154                                         return 0.0;
2155                                 else
2156                                         return -0.0;
2157                         }
2158                 }
2159
2160         } else {
2161                 if (isnan(a)) {
2162                         /* If either value1' or value2' is NaN, the result is NaN. */
2163
2164                         return longBitsToDouble(DBL_NAN);
2165
2166                 } else if (finite(b)) {
2167                         /* Division of an infinity by a finite value results in a signed */
2168                         /* infinity, with the sign-producing rule just given. */
2169
2170                         /* is sign equal? */
2171
2172                         if (copysign(1.0, a) == copysign(1.0, b))
2173                                 return longBitsToDouble(DBL_POSINF);
2174                         else
2175                                 return longBitsToDouble(DBL_NEGINF);
2176
2177                 } else {
2178                         /* Division of an infinity by an infinity results in NaN. */
2179
2180                         return longBitsToDouble(DBL_NAN);
2181                 }
2182         }
2183 }
2184
2185
2186 /* builtin_dneg ****************************************************************
2187
2188    Implemented as described in VM Spec.
2189
2190 *******************************************************************************/
2191
2192 double builtin_dneg(double a)
2193 {
2194         if (isnan(a)) {
2195                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2196                 /* sign). */
2197
2198                 return a;
2199
2200         } else {
2201                 if (finite(a)) {
2202                         /* If the operand is a zero, the result is the zero of opposite */
2203                         /* sign. */
2204
2205                         return -a;
2206
2207                 } else {
2208                         /* If the operand is an infinity, the result is the infinity of */
2209                         /* opposite sign. */
2210
2211                         return copysign(a, -copysign(1.0, a));
2212                 }
2213         }
2214 }
2215 #endif /* !SUPPORT_DOUBLE */
2216
2217
2218 #if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
2219 s4 builtin_dcmpl(double a, double b)
2220 {
2221         if (isnan(a))
2222                 return -1;
2223
2224         if (isnan(b))
2225                 return -1;
2226
2227         if (!finite(a) || !finite(b)) {
2228                 a = finite(a) ? 0 : copysign(1.0, a);
2229                 b = finite(b) ? 0 : copysign(1.0, b);
2230         }
2231
2232         if (a > b)
2233                 return 1;
2234
2235         if (a == b)
2236                 return 0;
2237
2238         return -1;
2239 }
2240
2241
2242 s4 builtin_dcmpg(double a, double b)
2243 {
2244         if (isnan(a))
2245                 return 1;
2246
2247         if (isnan(b))
2248                 return 1;
2249
2250         if (!finite(a) || !finite(b)) {
2251                 a = finite(a) ? 0 : copysign(1.0, a);
2252                 b = finite(b) ? 0 : copysign(1.0, b);
2253         }
2254
2255         if (a > b)
2256                 return 1;
2257
2258         if (a == b)
2259                 return 0;
2260
2261         return -1;
2262 }
2263 #endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
2264
2265
2266 double builtin_drem(double a, double b)
2267 {
2268         return fmod(a, b);
2269 }
2270
2271
2272 /* conversion operations ******************************************************/
2273
2274 #if 0
2275 s8 builtin_i2l(s4 i)
2276 {
2277 #if U8_AVAILABLE
2278         return i;
2279 #else
2280         s8 v;
2281         v.high = 0;
2282         v.low = i;
2283         return v;
2284 #endif
2285 }
2286
2287 s4 builtin_l2i(s8 l)
2288 {
2289 #if U8_AVAILABLE
2290         return (s4) l;
2291 #else
2292         return l.low;
2293 #endif
2294 }
2295 #endif
2296
2297
2298 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2299 float builtin_i2f(s4 a)
2300 {
2301         float f = (float) a;
2302         return f;
2303 }
2304 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2305
2306
2307 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2308 double builtin_i2d(s4 a)
2309 {
2310         double d = (double) a;
2311         return d;
2312 }
2313 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2314
2315
2316 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2317 float builtin_l2f(s8 a)
2318 {
2319 #if U8_AVAILABLE
2320         float f = (float) a;
2321         return f;
2322 #else
2323         return 0.0;
2324 #endif
2325 }
2326 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2327
2328
2329 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2330 double builtin_l2d(s8 a)
2331 {
2332 #if U8_AVAILABLE
2333         double d = (double) a;
2334         return d;
2335 #else
2336         return 0.0;
2337 #endif
2338 }
2339 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2340
2341
2342 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2343 s4 builtin_f2i(float a) 
2344 {
2345         s4 i;
2346
2347         i = builtin_d2i((double) a);
2348
2349         return i;
2350
2351         /*      float f;
2352         
2353                 if (isnanf(a))
2354                 return 0;
2355                 if (finitef(a)) {
2356                 if (a > 2147483647)
2357                 return 2147483647;
2358                 if (a < (-2147483648))
2359                 return (-2147483648);
2360                 return (s4) a;
2361                 }
2362                 f = copysignf((float) 1.0, a);
2363                 if (f > 0)
2364                 return 2147483647;
2365                 return (-2147483648); */
2366 }
2367 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2368
2369
2370 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
2371 s8 builtin_f2l(float a)
2372 {
2373         s8 l;
2374
2375         l = builtin_d2l((double) a);
2376
2377         return l;
2378
2379         /*      float f;
2380         
2381                 if (finitef(a)) {
2382                 if (a > 9223372036854775807L)
2383                 return 9223372036854775807L;
2384                 if (a < (-9223372036854775808L))
2385                 return (-9223372036854775808L);
2386                 return (s8) a;
2387                 }
2388                 if (isnanf(a))
2389                 return 0;
2390                 f = copysignf((float) 1.0, a);
2391                 if (f > 0)
2392                 return 9223372036854775807L;
2393                 return (-9223372036854775808L); */
2394 }
2395 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2396
2397
2398 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
2399 s4 builtin_d2i(double a) 
2400
2401         double d;
2402         
2403         if (finite(a)) {
2404                 if (a >= 2147483647)
2405                         return 2147483647;
2406                 if (a <= (-2147483647-1))
2407                         return (-2147483647-1);
2408                 return (s4) a;
2409         }
2410         if (isnan(a))
2411                 return 0;
2412         d = copysign(1.0, a);
2413         if (d > 0)
2414                 return 2147483647;
2415         return (-2147483647-1);
2416 }
2417 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
2418
2419
2420 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
2421 s8 builtin_d2l(double a)
2422 {
2423         double d;
2424         
2425         if (finite(a)) {
2426                 if (a >= 9223372036854775807LL)
2427                         return 9223372036854775807LL;
2428                 if (a <= (-9223372036854775807LL-1))
2429                         return (-9223372036854775807LL-1);
2430                 return (s8) a;
2431         }
2432         if (isnan(a))
2433                 return 0;
2434         d = copysign(1.0, a);
2435         if (d > 0)
2436                 return 9223372036854775807LL;
2437         return (-9223372036854775807LL-1);
2438 }
2439 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2440
2441
2442 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2443 double builtin_f2d(float a)
2444 {
2445         if (finitef(a)) return (double) a;
2446         else {
2447                 if (isnanf(a))
2448                         return longBitsToDouble(DBL_NAN);
2449                 else
2450                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2451         }
2452 }
2453
2454 float builtin_d2f(double a)
2455 {
2456         if (finite(a))
2457                 return (float) a;
2458         else {
2459                 if (isnan(a))
2460                         return intBitsToFloat(FLT_NAN);
2461                 else
2462                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2463         }
2464 }
2465 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2466
2467
2468 /* builtin_arraycopy ***********************************************************
2469
2470    Builtin for java.lang.System.arraycopy.
2471
2472    ATTENTION: This builtin function returns a boolean value to signal
2473    the ICMD_BUILTIN if there was an exception.
2474
2475 *******************************************************************************/
2476
2477 bool builtin_arraycopy(java_handle_t *src, s4 srcStart,
2478                                            java_handle_t *dest, s4 destStart, s4 len)
2479 {
2480         arraydescriptor *sdesc;
2481         arraydescriptor *ddesc;
2482         s4               i;
2483
2484         if ((src == NULL) || (dest == NULL)) { 
2485                 exceptions_throw_nullpointerexception();
2486                 return false;
2487         }
2488
2489         sdesc = LLNI_vftbl_direct(src)->arraydesc;
2490         ddesc = LLNI_vftbl_direct(dest)->arraydesc;
2491
2492         if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
2493                 exceptions_throw_arraystoreexception();
2494                 return false;
2495         }
2496
2497         /* we try to throw exception with the same message as SUN does */
2498
2499         if ((len < 0) || (srcStart < 0) || (destStart < 0) ||
2500                 (srcStart  + len < 0) || (srcStart  + len > LLNI_array_size(src)) ||
2501                 (destStart + len < 0) || (destStart + len > LLNI_array_size(dest))) {
2502                 exceptions_throw_arrayindexoutofboundsexception();
2503                 return false;
2504         }
2505
2506         if (sdesc->componentvftbl == ddesc->componentvftbl) {
2507                 /* We copy primitive values or references of exactly the same type */
2508
2509                 s4 dataoffset = sdesc->dataoffset;
2510                 s4 componentsize = sdesc->componentsize;
2511
2512                 memmove(((u1 *) dest) + dataoffset + componentsize * destStart,
2513                                 ((u1 *) src)  + dataoffset + componentsize * srcStart,
2514                                 (size_t) len * componentsize);
2515         }
2516         else {
2517                 /* We copy references of different type */
2518
2519                 java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
2520                 java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
2521  
2522                 if (destStart <= srcStart) {
2523                         for (i = 0; i < len; i++) {
2524                                 java_handle_t *o;
2525
2526                                 LLNI_objectarray_element_get(oas, srcStart + i, o);
2527
2528                                 if (!builtin_canstore(oad, o))
2529                                         return false;
2530
2531                                 LLNI_objectarray_element_set(oad, destStart + i, o);
2532                         }
2533                 }
2534                 else {
2535                         /* XXX this does not completely obey the specification!
2536                            If an exception is thrown only the elements above the
2537                            current index have been copied. The specification
2538                            requires that only the elements *below* the current
2539                            index have been copied before the throw. */
2540
2541                         for (i = len - 1; i >= 0; i--) {
2542                                 java_handle_t *o;
2543
2544                                 LLNI_objectarray_element_get(oas, srcStart + i, o);
2545
2546                                 if (!builtin_canstore(oad, o))
2547                                         return false;
2548
2549                                 LLNI_objectarray_element_set(oad, destStart + i, o);
2550                         }
2551                 }
2552         }
2553
2554         return true;
2555 }
2556
2557
2558 /* builtin_nanotime ************************************************************
2559
2560    Return the current time in nanoseconds.
2561
2562 *******************************************************************************/
2563
2564 s8 builtin_nanotime(void)
2565 {
2566         struct timeval tv;
2567         s8             usecs;
2568
2569         if (gettimeofday(&tv, NULL) == -1)
2570                 vm_abort("gettimeofday failed: %s", strerror(errno));
2571
2572         usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
2573
2574         return usecs * 1000;
2575 }
2576
2577
2578 /* builtin_currenttimemillis ***************************************************
2579
2580    Return the current time in milliseconds.
2581
2582 *******************************************************************************/
2583
2584 s8 builtin_currenttimemillis(void)
2585 {
2586         s8 msecs;
2587
2588         msecs = builtin_nanotime() / 1000 / 1000;
2589
2590         return msecs;
2591 }
2592
2593
2594 /* builtin_clone ***************************************************************
2595
2596    Function for cloning objects or arrays.
2597
2598 *******************************************************************************/
2599
2600 java_handle_t *builtin_clone(void *env, java_handle_t *o)
2601 {
2602         arraydescriptor *ad;
2603         java_handle_t   *ah;
2604         u4               size;
2605         classinfo       *c;
2606         java_handle_t   *co;                /* cloned object header               */
2607
2608         /* get the array descriptor */
2609
2610         ad = LLNI_vftbl_direct(o)->arraydesc;
2611
2612         /* we are cloning an array */
2613
2614         if (ad != NULL) {
2615                 ah = (java_handle_t *) o;
2616
2617                 size = ad->dataoffset + ad->componentsize * LLNI_array_size(ah);
2618         
2619                 co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
2620
2621                 if (co == NULL)
2622                         return NULL;
2623
2624                 MCOPY(co, o, u1, size);
2625
2626 #if defined(ENABLE_GC_CACAO)
2627                 heap_init_objectheader(co, size);
2628 #endif
2629
2630 #if defined(ENABLE_THREADS)
2631                 lock_init_object_lock(co);
2632 #endif
2633
2634                 return co;
2635         }
2636     
2637     /* we are cloning a non-array */
2638
2639     if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
2640         exceptions_throw_clonenotsupportedexception();
2641         return NULL;
2642     }
2643
2644         /* get the class of the object */
2645
2646         LLNI_class_get(o, c);
2647
2648         /* create new object */
2649
2650     co = builtin_new(c);
2651
2652     if (co == NULL)
2653         return NULL;
2654
2655     MCOPY(co, o, u1, c->instancesize);
2656
2657 #if defined(ENABLE_GC_CACAO)
2658         heap_init_objectheader(co, c->instancesize);
2659 #endif
2660
2661 #if defined(ENABLE_THREADS)
2662         lock_init_object_lock(co);
2663 #endif
2664
2665     return co;
2666 }
2667
2668 #if defined(ENABLE_VMLOG)
2669 #define NDEBUG
2670 #include <vmlog_cacao.c>
2671 #endif
2672
2673
2674 /*
2675  * These are local overrides for various environment variables in Emacs.
2676  * Please do not remove this and leave it at the end of the file, where
2677  * Emacs will automagically detect them.
2678  * ---------------------------------------------------------------------
2679  * Local variables:
2680  * mode: c
2681  * indent-tabs-mode: t
2682  * c-basic-offset: 4
2683  * tab-width: 4
2684  * End:
2685  * vim:noexpandtab:sw=4:ts=4:
2686  */