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