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