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