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