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