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