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