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