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