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