0529680f0eb1d81aa2b5267cfe827dcd5db68432
[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 4815 2006-04-23 19:16:54Z edwin $
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(USE_THREADS)
67 # if defined(NATIVE_THREADS)
68 #  include "threads/native/threads.h"
69 # else
70 #  include "threads/green/threads.h"
71 #  include "threads/green/locks.h"
72 # endif
73 #endif
74
75 #include "toolbox/logging.h"
76 #include "toolbox/util.h"
77 #include "vm/builtin.h"
78 #include "vm/class.h"
79 #include "vm/exceptions.h"
80 #include "vm/global.h"
81 #include "vm/initialize.h"
82 #include "vm/loader.h"
83 #include "vm/options.h"
84 #include "vm/stringlocal.h"
85 #include "vm/jit/asmpart.h"
86 #include "vm/jit/patcher.h"
87 #include "vm/rt-timing.h"
88 #include "vm/cycles-stats.h"
89
90
91 /* include builtin tables *****************************************************/
92
93 #include "vm/builtintable.inc"
94
95
96 CYCLES_STATS_DECLARE(builtin_monitorenter,100,2)
97 CYCLES_STATS_DECLARE(builtin_monitorexit ,100,2)
98 CYCLES_STATS_DECLARE(builtin_new         ,100,5)
99 CYCLES_STATS_DECLARE(builtin_overhead    , 80,1)
100
101 /* builtintable_init ***********************************************************
102
103    Parse the descriptors of builtin functions and create the parsed
104    descriptors.
105
106 *******************************************************************************/
107
108 static bool builtintable_init(void)
109 {
110         descriptor_pool *descpool;
111         s4               dumpsize;
112         utf             *descriptor;
113         s4               entries_internal;
114         s4               entries_automatic;
115         s4               i;
116
117         /* mark start of dump memory area */
118
119         dumpsize = dump_size();
120
121         /* create a new descriptor pool */
122
123         descpool = descriptor_pool_new(class_java_lang_Object);
124
125         /* add some entries we need */
126
127         if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
128                 return false;
129
130         if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
131                 return false;
132
133         /* calculate table entries statically */
134
135         entries_internal =
136                 sizeof(builtintable_internal) / sizeof(builtintable_entry);
137
138         entries_automatic =
139                 sizeof(builtintable_automatic) / sizeof(builtintable_entry)
140                 - 1; /* last filler entry (comment see builtintable.inc) */
141
142         /* first add all descriptors to the pool */
143
144         for (i = 0; i < entries_internal; i++) {
145                 /* create a utf8 string from descriptor */
146
147                 descriptor = utf_new_char(builtintable_internal[i].descriptor);
148
149                 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
150                         /* release dump area */
151
152                         dump_release(dumpsize);
153
154                         return false;
155                 }
156         }
157
158         for (i = 0; i < entries_automatic; i++) {
159                 /* create a utf8 string from descriptor */
160
161                 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
162
163                 if (!descriptor_pool_add(descpool, descriptor, NULL)) {
164                         /* release dump area */
165
166                         dump_release(dumpsize);
167
168                         return false;
169                 }
170         }
171
172         /* create the class reference table */
173
174         (void) descriptor_pool_create_classrefs(descpool, NULL);
175
176         /* allocate space for the parsed descriptors */
177
178         descriptor_pool_alloc_parsed_descriptors(descpool);
179
180         /* now parse all descriptors */
181
182         for (i = 0; i < entries_internal; i++) {
183                 /* create a utf8 string from descriptor */
184
185                 descriptor = utf_new_char(builtintable_internal[i].descriptor);
186
187                 /* parse the descriptor, builtin is always static (no `this' pointer) */
188
189                 builtintable_internal[i].md =
190                         descriptor_pool_parse_method_descriptor(descpool, descriptor,
191                                                                                                         ACC_STATIC, NULL);
192         }
193
194         for (i = 0; i < entries_automatic; i++) {
195                 /* create a utf8 string from descriptor */
196
197                 descriptor = utf_new_char(builtintable_automatic[i].descriptor);
198
199                 /* parse the descriptor, builtin is always static (no `this' pointer) */
200
201                 builtintable_automatic[i].md =
202                         descriptor_pool_parse_method_descriptor(descpool, descriptor,
203                                                                                                         ACC_STATIC, NULL);
204         }
205
206         /* release dump area */
207
208         dump_release(dumpsize);
209
210         return true;
211 }
212
213
214 /* builtintable_comparator *****************************************************
215
216    qsort comparator for the automatic builtin table.
217
218 *******************************************************************************/
219
220 static int builtintable_comparator(const void *a, const void *b)
221 {
222         builtintable_entry *bte1;
223         builtintable_entry *bte2;
224
225         bte1 = (builtintable_entry *) a;
226         bte2 = (builtintable_entry *) b;
227
228         return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
229 }
230
231
232 /* builtintable_sort_automatic *************************************************
233
234    Sorts the automatic builtin table.
235
236 *******************************************************************************/
237
238 static void builtintable_sort_automatic(void)
239 {
240         s4 entries;
241
242         /* calculate table size statically (`- 1' comment see builtintable.inc) */
243
244         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
245
246         qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
247                   builtintable_comparator);
248 }
249
250
251 /* builtin_init ****************************************************************
252
253    XXX
254
255 *******************************************************************************/
256
257 bool builtin_init(void)
258 {
259         /* initialize the builtin tables */
260
261         if (!builtintable_init())
262                 return false;
263
264         /* sort builtin tables */
265
266         builtintable_sort_automatic();
267
268         return true;
269 }
270
271
272 /* builtintable_get_internal ***************************************************
273
274    Finds an entry in the builtintable for internal functions and
275    returns the a pointer to the structure.
276
277 *******************************************************************************/
278
279 builtintable_entry *builtintable_get_internal(functionptr fp)
280 {
281         s4 i;
282
283         for (i = 0; builtintable_internal[i].fp != NULL; i++) {
284                 if (builtintable_internal[i].fp == fp)
285                         return &builtintable_internal[i];
286         }
287
288         return NULL;
289 }
290
291
292 /* builtintable_get_automatic **************************************************
293
294    Finds an entry in the builtintable for functions which are replaced
295    automatically and returns the a pointer to the structure.
296
297 *******************************************************************************/
298
299 builtintable_entry *builtintable_get_automatic(s4 opcode)
300 {
301         builtintable_entry *first;
302         builtintable_entry *last;
303         builtintable_entry *middle;
304         s4                  half;
305         s4                  entries;
306
307         /* calculate table size statically (`- 1' comment see builtintable.inc) */
308
309         entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
310
311         first = builtintable_automatic;
312         last = builtintable_automatic + entries;
313
314         while (entries > 0) {
315                 half = entries / 2;
316                 middle = first + half;
317
318                 if (middle->opcode < opcode) {
319                         first = middle + 1;
320                         entries -= half + 1;
321                 } else
322                         entries = half;
323         }
324
325         return (first != last ? first : NULL);
326 }
327
328
329 /*****************************************************************************
330                                                                 TYPE CHECKS
331 *****************************************************************************/
332
333
334
335 /*************** internal function: builtin_isanysubclass *********************
336
337         Checks a subclass relation between two classes. Implemented interfaces
338         are interpreted as super classes.
339         Return value:  1 ... sub is subclass of super
340                                    0 ... otherwise
341                                         
342 *****************************************************************************/                                  
343 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
344 {
345         s4 res;
346         castinfo classvalues;
347
348         if (sub == super)
349                 return 1;
350
351         if (super->flags & ACC_INTERFACE) {
352                 res = (sub->vftbl->interfacetablelength > super->index) &&
353                         (sub->vftbl->interfacetable[-super->index] != NULL);
354
355         } else {
356                 ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
357
358                 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
359                         (u4) classvalues.super_diffval;
360         }
361
362         return res;
363 }
364
365
366 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
367 {
368         s4 res;
369         s4 base;
370         castinfo classvalues;
371
372         if (sub == super)
373                 return 1;
374
375         ASM_GETCLASSVALUES_ATOMIC(super, sub, &classvalues);
376
377         if ((base = classvalues.super_baseval) <= 0) {
378                 /* super is an interface */
379                 res = (sub->interfacetablelength > -base) &&
380                         (sub->interfacetable[base] != NULL);
381         } else {
382             res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
383                         <= (u4) classvalues.super_diffval;
384         }
385
386         return res;
387 }
388
389
390 /****************** function: builtin_instanceof *****************************
391
392         Checks if an object is an instance of some given class (or subclass of
393         that class). If class is an interface, checks if the interface is
394         implemented.
395         Return value:  1 ... obj is an instance of class or implements the interface
396                                    0 ... otherwise or if obj == NULL
397                          
398 *****************************************************************************/
399
400 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
401 {
402         if (!obj)
403                 return 0;
404
405         return builtin_isanysubclass(obj->vftbl->class, class);
406 }
407
408
409
410 /**************** function: builtin_checkcast *******************************
411
412         The same as builtin_instanceof except that 1 is returned when
413         obj == NULL
414                           
415 ****************************************************************************/
416
417 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
418 {
419         if (obj == NULL)
420                 return 1;
421
422         if (builtin_isanysubclass(obj->vftbl->class, class))
423                 return 1;
424
425         return 0;
426 }
427
428
429 /* builtin_descriptorscompatible ***********************************************
430
431    Checks if two array type descriptors are assignment compatible
432
433    Return value: 1 ... target = desc is possible
434                  0 ... otherwise
435                         
436 *******************************************************************************/
437
438 static s4 builtin_descriptorscompatible(arraydescriptor *desc,
439                                                                                 arraydescriptor *target)
440 {
441         if (desc == target)
442                 return 1;
443
444         if (desc->arraytype != target->arraytype)
445                 return 0;
446
447         if (desc->arraytype != ARRAYTYPE_OBJECT)
448                 return 1;
449         
450         /* {both arrays are arrays of references} */
451
452         if (desc->dimension == target->dimension) {
453                 /* an array which contains elements of interface types is
454            allowed to be casted to Object (JOWENN)*/
455
456                 if ((desc->elementvftbl->baseval < 0) &&
457                         (target->elementvftbl->baseval == 1))
458                         return 1;
459
460                 return builtin_isanysubclass_vftbl(desc->elementvftbl,
461                                                                                    target->elementvftbl);
462         }
463
464         if (desc->dimension < target->dimension)
465                 return 0;
466
467         /* {desc has higher dimension than target} */
468
469         return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl,
470                                                                            target->elementvftbl);
471 }
472
473
474 /* builtin_arraycheckcast ******************************************************
475
476    Checks if an object is really a subtype of the requested array
477    type.  The object has to be an array to begin with. For simple
478    arrays (int, short, double, etc.) the types have to match exactly.
479    For arrays of objects, the type of elements in the array has to be
480    a subtype (or the same type) of the requested element type. For
481    arrays of arrays (which in turn can again be arrays of arrays), the
482    types at the lowest level have to satisfy the corresponding sub
483    class relation.
484         
485 *******************************************************************************/
486
487 s4 builtin_arraycheckcast(java_objectheader *o, classinfo *targetclass)
488 {
489         arraydescriptor *desc;
490
491         if (!o)
492                 return 1;
493
494         if ((desc = o->vftbl->arraydesc) == NULL)
495                 return 0;
496  
497         return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
498 }
499
500
501 s4 builtin_arrayinstanceof(java_objectheader *o, classinfo *targetclass)
502 {
503         if (!o)
504                 return 0;
505
506         return builtin_arraycheckcast(o, targetclass);
507 }
508
509
510 /* builtin_throw_exception *****************************************************
511
512    Sets the exceptionptr with the thrown exception and prints some
513    debugging information.  Called from asm_vm_call_method.
514
515 *******************************************************************************/
516
517 void *builtin_throw_exception(java_objectheader *xptr)
518 {
519 #if !defined(NDEBUG)
520     java_lang_Throwable *t;
521         char                *logtext;
522         s4                   logtextlen;
523         s4                   dumpsize;
524
525         if (opt_verbose) {
526                 t = (java_lang_Throwable *) xptr;
527
528                 /* calculate message length */
529
530                 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
531
532                 if (t) {
533                         logtextlen +=
534                                 utf_strlen(xptr->vftbl->class->name) +
535                                 strlen(": ") +
536                                 javastring_strlen(t->detailMessage);
537
538                 } else
539                         logtextlen += strlen("(nil)");
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_sprint_classname(logtext + strlen(logtext),
551                                                                  xptr->vftbl->class->name);
552
553                         if (t->detailMessage) {
554                                 char *buf;
555
556                                 buf = javastring_tochar((java_objectheader *) t->detailMessage);
557                                 strcat(logtext, ": ");
558                                 strcat(logtext, buf);
559                                 MFREE(buf, char, strlen(buf));
560                         }
561
562                 } else {
563                         strcat(logtext, "(nil)");
564                 }
565
566                 log_text(logtext);
567
568                 /* release memory */
569
570                 dump_release(dumpsize);
571         }
572 #endif /* !defined(NDEBUG) */
573
574         /* actually set the exception */
575
576         *exceptionptr = xptr;
577
578         /* Return a NULL pointer.  This is required for vm_call_method to
579            check for an exception.  This is for convenience. */
580
581         return NULL;
582 }
583
584
585 /* builtin_canstore ************************************************************
586
587    Checks, if an object can be stored in an array.
588
589    Return value: 1 ... possible
590                  0 ... otherwise
591
592 *******************************************************************************/
593
594 s4 builtin_canstore(java_objectarray *oa, java_objectheader *o)
595 {
596         arraydescriptor *desc;
597         arraydescriptor *valuedesc;
598         vftbl_t         *componentvftbl;
599         vftbl_t         *valuevftbl;
600         s4               base;
601         castinfo         classvalues;
602
603         if (!o)
604                 return 1;
605
606         /* The following is guaranteed (by verifier checks):
607          *
608          *     *) oa->...vftbl->arraydesc != NULL
609          *     *) oa->...vftbl->arraydesc->componentvftbl != NULL
610          *     *) o->vftbl is not an interface vftbl
611          */
612         
613         desc           = oa->header.objheader.vftbl->arraydesc;
614         componentvftbl = desc->componentvftbl;
615         valuevftbl     = o->vftbl;
616
617         if ((desc->dimension - 1) == 0) {
618                 s4 res;
619
620                 /* {oa is a one-dimensional array} */
621                 /* {oa is an array of references} */
622                 
623                 if (valuevftbl == componentvftbl)
624                         return 1;
625
626                 ASM_GETCLASSVALUES_ATOMIC(componentvftbl, valuevftbl, &classvalues);
627
628                 if ((base = classvalues.super_baseval) <= 0)
629                         /* an array of interface references */
630                         return (valuevftbl->interfacetablelength > -base &&
631                                         valuevftbl->interfacetable[base] != NULL);
632                 
633                 res = ((unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
634                            <= (unsigned) classvalues.super_diffval);
635
636                 return res;
637         }
638
639         /* {oa has dimension > 1} */
640         /* {componentvftbl->arraydesc != NULL} */
641
642         /* check if o is an array */
643
644         if ((valuedesc = valuevftbl->arraydesc) == NULL)
645                 return 0;
646
647         /* {o is an array} */
648
649         return builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
650 }
651
652
653 /* This is an optimized version where a is guaranteed to be one-dimensional */
654 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
655 {
656         arraydescriptor *desc;
657         vftbl_t *elementvftbl;
658         vftbl_t *valuevftbl;
659         s4 res;
660         int base;
661         castinfo classvalues;
662         
663         if (!o) return 1;
664
665         /* The following is guaranteed (by verifier checks):
666          *
667          *     *) a->...vftbl->arraydesc != NULL
668          *     *) a->...vftbl->arraydesc->elementvftbl != NULL
669          *     *) a->...vftbl->arraydesc->dimension == 1
670          *     *) o->vftbl is not an interface vftbl
671          */
672
673         desc = a->header.objheader.vftbl->arraydesc;
674     elementvftbl = desc->elementvftbl;
675         valuevftbl = o->vftbl;
676
677         /* {a is a one-dimensional array} */
678         
679         if (valuevftbl == elementvftbl)
680                 return 1;
681
682         ASM_GETCLASSVALUES_ATOMIC(elementvftbl, valuevftbl, &classvalues);
683
684         if ((base = classvalues.super_baseval) <= 0)
685                 /* an array of interface references */
686                 return (valuevftbl->interfacetablelength > -base &&
687                                 valuevftbl->interfacetable[base] != NULL);
688
689         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
690                 <= (unsigned) classvalues.super_diffval;
691
692         return res;
693 }
694
695
696 /* This is an optimized version where a is guaranteed to be a
697  * one-dimensional array of a class type */
698 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
699 {
700         vftbl_t *elementvftbl;
701         vftbl_t *valuevftbl;
702         s4 res;
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->elementvftbl is not an interface vftbl
712          *     *) a->...vftbl->arraydesc->dimension == 1
713          *     *) o->vftbl is not an interface vftbl
714          */
715
716     elementvftbl = a->header.objheader.vftbl->arraydesc->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         res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
727                 <= (unsigned) classvalues.super_diffval;
728
729         return res;
730 }
731
732
733 /* builtin_new *****************************************************************
734
735    Creates a new instance of class c on the heap.
736
737    Return value: pointer to the object or NULL if no memory is
738    available
739                         
740 *******************************************************************************/
741
742 java_objectheader *builtin_new(classinfo *c)
743 {
744         java_objectheader *o;
745 #if defined(ENABLE_RT_TIMING)
746         struct timespec time_start, time_end;
747 #endif
748 #if defined(ENABLE_CYCLES_STATS)
749         u8 cycles_start, cycles_end;
750 #endif
751
752         RT_TIMING_GET_TIME(time_start);
753         CYCLES_STATS_GET(cycles_start);
754
755         /* is the class loaded */
756
757         assert(c->state & CLASS_LOADED);
758
759         /* check if we can instantiate this class */
760
761         if (c->flags & ACC_ABSTRACT) {
762                 *exceptionptr =
763                         new_exception_utfmessage(string_java_lang_InstantiationError,
764                                                                          c->name);
765                 return NULL;
766         }
767
768         /* is the class linked */
769
770         if (!(c->state & CLASS_LINKED))
771                 if (!link_class(c))
772                         return NULL;
773
774         if (!(c->state & CLASS_INITIALIZED)) {
775 #if !defined(NDEBUG)
776                 if (initverbose)
777                         log_message_class("Initialize class (from builtin_new): ", c);
778 #endif
779
780                 if (!initialize_class(c))
781                         return NULL;
782         }
783
784         o = heap_allocate(c->instancesize, true, c->finalizer);
785
786         if (!o)
787                 return NULL;
788
789         o->vftbl = c->vftbl;
790
791 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
792         initObjectLock(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(USE_THREADS) && defined(NATIVE_THREADS)
851         initObjectLock(&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 ") +
1156                         utf_strlen(xptr->vftbl->class->name);
1157
1158         } else {
1159                 logtextlen = strlen("Some Throwable");
1160         }
1161
1162         logtextlen += strlen(" thrown in ");
1163
1164         if (m) {
1165                 logtextlen +=
1166                         utf_strlen(m->class->name) +
1167                         strlen(".") +
1168                         utf_strlen(m->name) +
1169                         utf_strlen(m->descriptor) +
1170                         strlen("(NOSYNC,NATIVE");
1171
1172 #if SIZEOF_VOID_P == 8
1173                 logtextlen +=
1174                         strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
1175 #else
1176                 logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
1177 #endif
1178
1179                 if (m->class->sourcefile == NULL)
1180                         logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1181                 else
1182                         logtextlen += utf_strlen(m->class->sourcefile);
1183
1184                 logtextlen += strlen(":65536)");
1185
1186         } else
1187                 logtextlen += strlen("call_java_method");
1188
1189         logtextlen += strlen("0");
1190
1191         /* allocate memory */
1192
1193         dumpsize = dump_size();
1194
1195         logtext = DMNEW(char, logtextlen);
1196
1197         if (xptr) {
1198                 strcpy(logtext, "Exception ");
1199                 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1200
1201         } else {
1202                 strcpy(logtext, "Some Throwable");
1203         }
1204
1205         strcat(logtext, " thrown in ");
1206
1207         if (m) {
1208                 utf_strcat_classname(logtext, m->class->name);
1209                 strcat(logtext, ".");
1210                 utf_strcat(logtext, m->name);
1211                 utf_strcat(logtext, m->descriptor);
1212
1213                 if (m->flags & ACC_SYNCHRONIZED)
1214                         strcat(logtext, "(SYNC");
1215                 else
1216                         strcat(logtext, "(NOSYNC");
1217
1218                 if (m->flags & ACC_NATIVE) {
1219                         strcat(logtext, ",NATIVE");
1220
1221                         code = m->code;
1222
1223 #if SIZEOF_VOID_P == 8
1224                         sprintf(logtext + strlen(logtext),
1225                                         ")(0x%016lx) at position 0x%016lx",
1226                                         (ptrint) code->entrypoint, (ptrint) pos);
1227 #else
1228                         sprintf(logtext + strlen(logtext),
1229                                         ")(0x%08x) at position 0x%08x",
1230                                         (ptrint) code->entrypoint, (ptrint) pos);
1231 #endif
1232
1233                 } else {
1234
1235                         /* XXX preliminary: This should get the actual codeinfo */
1236                         /* in which the exception happened.                     */
1237                         code = m->code;
1238                         
1239 #if SIZEOF_VOID_P == 8
1240                         sprintf(logtext + strlen(logtext),
1241                                         ")(0x%016lx) at position 0x%016lx (",
1242                                         (ptrint) code->entrypoint, (ptrint) pos);
1243 #else
1244                         sprintf(logtext + strlen(logtext),
1245                                         ")(0x%08x) at position 0x%08x (",
1246                                         (ptrint) code->entrypoint, (ptrint) pos);
1247 #endif
1248
1249                         if (m->class->sourcefile == NULL)
1250                                 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1251                         else
1252                                 utf_strcat(logtext, m->class->sourcefile);
1253
1254                         sprintf(logtext + strlen(logtext), ":%d)", 0);
1255                 }
1256
1257         } else
1258                 strcat(logtext, "call_java_method");
1259
1260         log_text(logtext);
1261
1262         /* release memory */
1263
1264         dump_release(dumpsize);
1265
1266         return xptr;
1267 }
1268 #endif /* !defined(NDEBUG) */
1269
1270
1271 /* builtin_trace_args **********************************************************
1272
1273    XXX
1274
1275 *******************************************************************************/
1276
1277 #if !defined(NDEBUG)
1278
1279 #ifdef TRACE_ARGS_NUM
1280 void builtin_trace_args(s8 a0, s8 a1,
1281 #if TRACE_ARGS_NUM >= 4
1282                                                 s8 a2, s8 a3,
1283 #endif /* TRACE_ARGS_NUM >= 4 */
1284 #if TRACE_ARGS_NUM >= 6
1285                                                 s8 a4, s8 a5,
1286 #endif /* TRACE_ARGS_NUM >= 6 */
1287 #if TRACE_ARGS_NUM == 8
1288                                                 s8 a6, s8 a7,
1289 #endif /* TRACE_ARGS_NUM == 8 */
1290                                                 methodinfo *m)
1291 {
1292         methoddesc *md;
1293         char       *logtext;
1294         s4          logtextlen;
1295         s4          dumpsize;
1296         s4          i;
1297         s4          pos;
1298
1299         md = m->parseddesc;
1300
1301         /* calculate message length */
1302
1303         logtextlen =
1304                 strlen("4294967295 ") +
1305                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1306                 methodindent +
1307                 strlen("called: ") +
1308                 utf_strlen(m->class->name) +
1309                 strlen(".") +
1310                 utf_strlen(m->name) +
1311                 utf_strlen(m->descriptor) +
1312                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1313
1314         /* add maximal argument length */
1315
1316         logtextlen += strlen("0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, 0x123456789abcdef0, ...(255)");
1317
1318         /* allocate memory */
1319
1320         dumpsize = dump_size();
1321
1322         logtext = DMNEW(char, logtextlen);
1323
1324         callcount++;
1325
1326         sprintf(logtext, "%10d ", callcount);
1327         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1328
1329         pos = strlen(logtext);
1330
1331         for (i = 0; i < methodindent; i++)
1332                 logtext[pos++] = '\t';
1333
1334         strcpy(logtext + pos, "called: ");
1335
1336         utf_strcat_classname(logtext, m->class->name);
1337         strcat(logtext, ".");
1338         utf_strcat(logtext, m->name);
1339         utf_strcat(logtext, m->descriptor);
1340
1341         if (m->flags & ACC_PUBLIC)       strcat(logtext, " PUBLIC");
1342         if (m->flags & ACC_PRIVATE)      strcat(logtext, " PRIVATE");
1343         if (m->flags & ACC_PROTECTED)    strcat(logtext, " PROTECTED");
1344         if (m->flags & ACC_STATIC)       strcat(logtext, " STATIC");
1345         if (m->flags & ACC_FINAL)        strcat(logtext, " FINAL");
1346         if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1347         if (m->flags & ACC_VOLATILE)     strcat(logtext, " VOLATILE");
1348         if (m->flags & ACC_TRANSIENT)    strcat(logtext, " TRANSIENT");
1349         if (m->flags & ACC_NATIVE)       strcat(logtext, " NATIVE");
1350         if (m->flags & ACC_INTERFACE)    strcat(logtext, " INTERFACE");
1351         if (m->flags & ACC_ABSTRACT)     strcat(logtext, " ABSTRACT");
1352
1353         strcat(logtext, "(");
1354
1355         /* xxxprintf ?Bug? an PowerPc Linux (rlwinm.inso)                */
1356         /* Only Arguments in integer Registers are passed correctly here */
1357         /* long longs spilled on Stack have an wrong offset of +4        */
1358         /* So preliminary Bugfix: Only pass 3 params at once to sprintf  */
1359         /* for SIZEOG_VOID_P == 4 && TRACE_ARGS_NUM == 8                 */
1360         switch (md->paramcount) {
1361         case 0:
1362                 break;
1363
1364 #if SIZEOF_VOID_P == 4
1365         case 1:
1366                 sprintf(logtext + strlen(logtext),
1367                                 "0x%llx",
1368                                 a0);
1369                 break;
1370
1371         case 2:
1372                 sprintf(logtext + strlen(logtext),
1373                                 "0x%llx, 0x%llx",
1374                                 a0, a1);
1375                 break;
1376
1377 #if TRACE_ARGS_NUM >= 4
1378         case 3:
1379                 sprintf(logtext + strlen(logtext),
1380                                 "0x%llx, 0x%llx, 0x%llx",
1381                                 a0, a1, a2);
1382                 break;
1383
1384         case 4:
1385                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1386                                 , a0, a1, a2);
1387                 sprintf(logtext + strlen(logtext), ", 0x%llx", a3);
1388
1389                 break;
1390 #endif /* TRACE_ARGS_NUM >= 4 */
1391
1392 #if TRACE_ARGS_NUM >= 6
1393         case 5:
1394                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1395                                 , a0, a1, a2);
1396                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a3, a4);
1397                 break;
1398
1399
1400         case 6:
1401                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1402                                 , a0, a1, a2);
1403                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1404                                 , a3, a4, a5);
1405                 break;
1406 #endif /* TRACE_ARGS_NUM >= 6 */
1407
1408 #if TRACE_ARGS_NUM == 8
1409         case 7:
1410                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1411                                 , a0, a1, a2);
1412                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1413                                 , a3, a4, a5);
1414                 sprintf(logtext + strlen(logtext), ", 0x%llx", a6);
1415                 break;
1416
1417         case 8:
1418                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, 0x%llx"
1419                                 , a0, a1, a2);
1420                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx, 0x%llx"
1421                                 , a3, a4, a5);
1422                 sprintf(logtext + strlen(logtext), ", 0x%llx, 0x%llx", a6, a7);
1423                 break;
1424 #endif /* TRACE_ARGS_NUM == 8 */
1425
1426         default:
1427 #if TRACE_ARGS_NUM == 2
1428                 sprintf(logtext + strlen(logtext), "0x%llx, 0x%llx, ...(%d)", a0, a1, md->paramcount - 2);
1429
1430 #elif TRACE_ARGS_NUM == 4
1431                 sprintf(logtext + strlen(logtext),
1432                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1433                                 a0, a1, a2, a3, md->paramcount - 4);
1434
1435 #elif TRACE_ARGS_NUM == 6
1436                 sprintf(logtext + strlen(logtext),
1437                                 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1438                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1439
1440 #elif TRACE_ARGS_NUM == 8
1441                 sprintf(logtext + strlen(logtext),"0x%llx, 0x%llx, 0x%llx,"
1442                                 , a0, a1, a2);
1443                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, 0x%llx,"
1444                                 , a3, a4, a5);
1445                 sprintf(logtext + strlen(logtext)," 0x%llx, 0x%llx, ...(%d)"
1446                                 , a6, a7, md->paramcount - 8);
1447 #endif
1448                 break;
1449
1450 #else /* SIZEOF_VOID_P == 4 */
1451
1452         case 1:
1453                 sprintf(logtext + strlen(logtext),
1454                                 "0x%lx",
1455                                 a0);
1456                 break;
1457
1458         case 2:
1459                 sprintf(logtext + strlen(logtext),
1460                                 "0x%lx, 0x%lx",
1461                                 a0, a1);
1462                 break;
1463
1464         case 3:
1465                 sprintf(logtext + strlen(logtext),
1466                                 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1467                 break;
1468
1469         case 4:
1470                 sprintf(logtext + strlen(logtext),
1471                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1472                                 a0, a1, a2, a3);
1473                 break;
1474
1475 #if TRACE_ARGS_NUM >= 6
1476         case 5:
1477                 sprintf(logtext + strlen(logtext),
1478                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1479                                 a0, a1, a2, a3, a4);
1480                 break;
1481
1482         case 6:
1483                 sprintf(logtext + strlen(logtext),
1484                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1485                                 a0, a1, a2, a3, a4, a5);
1486                 break;
1487 #endif /* TRACE_ARGS_NUM >= 6 */
1488
1489 #if TRACE_ARGS_NUM == 8
1490         case 7:
1491                 sprintf(logtext + strlen(logtext),
1492                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1493                                 a0, a1, a2, a3, a4, a5, a6);
1494                 break;
1495
1496         case 8:
1497                 sprintf(logtext + strlen(logtext),
1498                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1499                                 a0, a1, a2, a3, a4, a5, a6, a7);
1500                 break;
1501 #endif /* TRACE_ARGS_NUM == 8 */
1502
1503         default:
1504 #if TRACE_ARGS_NUM == 4
1505                 sprintf(logtext + strlen(logtext),
1506                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1507                                 a0, a1, a2, a3, md->paramcount - 4);
1508
1509 #elif TRACE_ARGS_NUM == 6
1510                 sprintf(logtext + strlen(logtext),
1511                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1512                                 a0, a1, a2, a3, a4, a5, md->paramcount - 6);
1513
1514 #elif TRACE_ARGS_NUM == 8
1515                 sprintf(logtext + strlen(logtext),
1516                                 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1517                                 a0, a1, a2, a3, a4, a5, a6, a7, md->paramcount - 8);
1518 #endif
1519                 break;
1520 #endif /* SIZEOF_VOID_P == 4 */
1521         }
1522
1523         strcat(logtext, ")");
1524
1525         log_text(logtext);
1526
1527         /* release memory */
1528
1529         dump_release(dumpsize);
1530
1531         methodindent++;
1532 }
1533 #endif
1534 #endif /* !defined(NDEBUG) */
1535
1536
1537 /* builtin_displaymethodstop ***************************************************
1538
1539    XXX
1540
1541 *******************************************************************************/
1542
1543 #if !defined(NDEBUG)
1544 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1545 {
1546         methoddesc        *md;
1547         char              *logtext;
1548         s4                 logtextlen;
1549         s4                 dumpsize;
1550         s4                 i;
1551         s4                 pos;
1552         java_objectheader *o;
1553         java_lang_String  *s;
1554         classinfo         *c;
1555         s4                 len;
1556         utf               *u;
1557         imm_union          imu;
1558
1559         md = m->parseddesc;
1560
1561         /* calculate message length */
1562
1563         logtextlen =
1564                 strlen("4294967295 ") +
1565                 strlen("-2147483647-") +        /* INT_MAX should be sufficient       */
1566                 methodindent +
1567                 strlen("finished: ") +
1568                 utf_strlen(m->class->name) +
1569                 strlen(".") +
1570                 utf_strlen(m->name) +
1571                 utf_strlen(m->descriptor) +
1572                 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1573
1574         /* add maximal argument length */
1575
1576         logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
1577
1578         /* allocate memory */
1579
1580         dumpsize = dump_size();
1581
1582         logtext = DMNEW(char, logtextlen);
1583
1584         /* outdent the log message */
1585
1586         if (methodindent)
1587                 methodindent--;
1588         else
1589                 log_text("WARNING: unmatched methodindent--");
1590
1591         /* generate the message */
1592
1593         sprintf(logtext, "           ");
1594         sprintf(logtext + strlen(logtext), "-%d-", methodindent);
1595
1596         pos = strlen(logtext);
1597
1598         for (i = 0; i < methodindent; i++)
1599                 logtext[pos++] = '\t';
1600
1601         strcpy(logtext + pos, "finished: ");
1602         utf_strcat_classname(logtext, m->class->name);
1603         strcat(logtext, ".");
1604         utf_strcat(logtext, m->name);
1605         utf_strcat(logtext, m->descriptor);
1606
1607         switch (md->returntype.type) {
1608         case TYPE_INT:
1609                 sprintf(logtext + strlen(logtext), "->%d (0x%08x)", (s4) l, (s4) l);
1610                 break;
1611
1612         case TYPE_LNG:
1613 #if SIZEOF_VOID_P == 4
1614                 sprintf(logtext + strlen(logtext), "->%lld (0x%016llx)", (s8) l, l);
1615 #else
1616                 sprintf(logtext + strlen(logtext), "->%ld (0x%016lx)", (s8) l, l);
1617 #endif
1618                 break;
1619
1620         case TYPE_ADR:
1621                 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1622
1623                 /* check return argument for java.lang.Class or java.lang.String */
1624
1625                 o = (java_objectheader *) (ptrint) l;
1626
1627                 if (o != NULL) {
1628                         if (o->vftbl->class == class_java_lang_String) {
1629                                 /* get java.lang.String object and the length of the
1630                    string */
1631
1632                                 s= (java_lang_String *) (ptrint) l;
1633
1634                                 len = strlen(", String = \"") + javastring_strlen(s) +
1635                                         strlen("\"");
1636
1637                                 /* realloc memory for string length */
1638
1639                                 DMREALLOC(logtext, char, logtextlen, logtextlen + len);
1640
1641                                 /* convert to utf8 string and strcat it to the logtext */
1642
1643                                 u = javastring_toutf(s, false);
1644
1645                                 strcat(logtext, ", String = \"");
1646                                 utf_strcat(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_strlen(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_strcat(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 /****************************************************************************
1706                          SYNCHRONIZATION FUNCTIONS
1707 *****************************************************************************/
1708
1709 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1710 /*
1711  * Lock the mutex of an object.
1712  */
1713 void internal_lock_mutex_for_object(java_objectheader *object)
1714 {
1715         mutexHashEntry *entry;
1716         int hashValue;
1717
1718         assert(object != 0);
1719
1720         hashValue = MUTEX_HASH_VALUE(object);
1721         entry = &mutexHashTable[hashValue];
1722
1723         if (entry->object != 0) {
1724                 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1725                         entry->object = 0;
1726                         entry->mutex.holder = 0;
1727                         entry->mutex.count = 0;
1728                         entry->mutex.muxWaiters = 0;
1729
1730                 } else {
1731                         while (entry->next != 0 && entry->object != object)
1732                                 entry = entry->next;
1733
1734                         if (entry->object != object) {
1735                                 entry->next = firstFreeOverflowEntry;
1736                                 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1737
1738                                 entry = entry->next;
1739                                 entry->object = 0;
1740                                 entry->next = 0;
1741                                 assert(entry->conditionCount == 0);
1742                         }
1743                 }
1744
1745         } else {
1746                 entry->mutex.holder = 0;
1747                 entry->mutex.count = 0;
1748                 entry->mutex.muxWaiters = 0;
1749         }
1750
1751         if (entry->object == 0)
1752                 entry->object = object;
1753         
1754         internal_lock_mutex(&entry->mutex);
1755 }
1756 #endif
1757
1758
1759 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1760 /*
1761  * Unlocks the mutex of an object.
1762  */
1763 void internal_unlock_mutex_for_object (java_objectheader *object)
1764 {
1765         int hashValue;
1766         mutexHashEntry *entry;
1767
1768         hashValue = MUTEX_HASH_VALUE(object);
1769         entry = &mutexHashTable[hashValue];
1770
1771         if (entry->object == object) {
1772                 internal_unlock_mutex(&entry->mutex);
1773
1774         } else {
1775                 while (entry->next != 0 && entry->next->object != object)
1776                         entry = entry->next;
1777
1778                 assert(entry->next != 0);
1779
1780                 internal_unlock_mutex(&entry->next->mutex);
1781
1782                 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1783                         mutexHashEntry *unlinked = entry->next;
1784
1785                         entry->next = unlinked->next;
1786                         unlinked->next = firstFreeOverflowEntry;
1787                         firstFreeOverflowEntry = unlinked;
1788                 }
1789         }
1790 }
1791 #endif
1792
1793 #if defined(ENABLE_CYCLES_STATS)
1794 void builtin_print_cycles_stats(FILE *file)
1795 {
1796         fprintf(file,"builtin cylce count statistics:\n");
1797
1798         CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
1799         CYCLES_STATS_PRINT(builtin_monitorenter,file);
1800         CYCLES_STATS_PRINT(builtin_monitorexit ,file);
1801         CYCLES_STATS_PRINT(builtin_new         ,file);
1802
1803         fprintf(file,"\n");
1804 }
1805 #endif /* defined(ENABLE_CYCLES_STATS) */
1806
1807 #if defined(USE_THREADS)
1808 void builtin_monitorenter(java_objectheader *o)
1809 {
1810 #if defined(ENABLE_CYCLES_STATS)
1811         u8 cycles_start, cycles_overhead, cycles_end;
1812 #endif
1813
1814 #if !defined(NATIVE_THREADS)
1815         int hashValue;
1816
1817         ++blockInts;
1818
1819         hashValue = MUTEX_HASH_VALUE(o);
1820         if (mutexHashTable[hashValue].object == o 
1821                 && mutexHashTable[hashValue].mutex.holder == currentThread)
1822                 ++mutexHashTable[hashValue].mutex.count;
1823         else
1824                 internal_lock_mutex_for_object(o);
1825
1826         --blockInts;
1827 #else /* defined(NATIVE_THREADS) */
1828         CYCLES_STATS_GET(cycles_start);
1829         CYCLES_STATS_GET(cycles_overhead);
1830
1831         monitorEnter((threadobject *) THREADOBJECT, o);
1832
1833         CYCLES_STATS_GET(cycles_end);
1834         CYCLES_STATS_COUNT(builtin_monitorenter, cycles_end - cycles_overhead);
1835         CYCLES_STATS_COUNT(builtin_overhead    , cycles_overhead - cycles_start);
1836 #endif /* defined(NATIVE_THREADS) */
1837 }
1838 #endif
1839
1840
1841 #if defined(USE_THREADS)
1842 /*
1843  * Locks the class object - needed for static synchronized methods.
1844  */
1845 void builtin_staticmonitorenter(classinfo *c)
1846 {
1847         builtin_monitorenter(&c->object.header);
1848 }
1849 #endif
1850
1851
1852 #if defined(USE_THREADS)
1853 void builtin_monitorexit(java_objectheader *o)
1854 {
1855 #if defined(ENABLE_CYCLES_STATS)
1856         u8 cycles_start, cycles_end;
1857 #endif
1858
1859 #if !defined(NATIVE_THREADS)
1860         int hashValue;
1861
1862         ++blockInts;
1863
1864         hashValue = MUTEX_HASH_VALUE(o);
1865         if (mutexHashTable[hashValue].object == o) {
1866                 if (mutexHashTable[hashValue].mutex.count == 1
1867                         && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1868                         internal_unlock_mutex_for_object(o);
1869                 else
1870                         --mutexHashTable[hashValue].mutex.count;
1871
1872         } else
1873                 internal_unlock_mutex_for_object(o);
1874
1875         --blockInts;
1876 #else /* defined(NATIVE_THREADS) */
1877         CYCLES_STATS_GET(cycles_start);
1878
1879         monitorExit((threadobject *) THREADOBJECT, o);
1880
1881         CYCLES_STATS_GET(cycles_end);
1882         CYCLES_STATS_COUNT(builtin_monitorexit, cycles_end - cycles_start);
1883 #endif /* defined(NATIVE_THREADS) */
1884 }
1885 #endif
1886
1887
1888 /*****************************************************************************
1889                           MISCELLANEOUS HELPER FUNCTIONS
1890 *****************************************************************************/
1891
1892
1893
1894 /*********** Functions for integer divisions *****************************
1895  
1896         On some systems (eg. DEC ALPHA), integer division is not supported by the
1897         CPU. These helper functions implement the missing functionality.
1898
1899 ******************************************************************************/
1900
1901 #if !SUPPORT_DIVISION
1902 s4 builtin_idiv(s4 a, s4 b)
1903 {
1904         s4 c;
1905
1906         c = a / b;
1907
1908         return c;
1909 }
1910
1911 s4 builtin_irem(s4 a, s4 b)
1912 {
1913         s4 c;
1914
1915         c = a % b;
1916
1917         return c;
1918 }
1919 #endif /* !SUPPORT_DIVISION */
1920
1921
1922 /* functions for long arithmetics **********************************************
1923
1924    On systems where 64 bit Integers are not supported by the CPU,
1925    these functions are needed.
1926
1927 ******************************************************************************/
1928
1929 #if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
1930 s8 builtin_ladd(s8 a, s8 b)
1931 {
1932         s8 c;
1933
1934 #if U8_AVAILABLE
1935         c = a + b; 
1936 #else
1937         c = builtin_i2l(0);
1938 #endif
1939
1940         return c;
1941 }
1942
1943 s8 builtin_lsub(s8 a, s8 b)
1944 {
1945         s8 c;
1946
1947 #if U8_AVAILABLE
1948         c = a - b; 
1949 #else
1950         c = builtin_i2l(0);
1951 #endif
1952
1953         return c;
1954 }
1955
1956 s8 builtin_lneg(s8 a)
1957 {
1958         s8 c;
1959
1960 #if U8_AVAILABLE
1961         c = -a;
1962 #else
1963         c = builtin_i2l(0);
1964 #endif
1965
1966         return c;
1967 }
1968 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
1969
1970
1971 #if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
1972 s8 builtin_lmul(s8 a, s8 b)
1973 {
1974         s8 c;
1975
1976 #if U8_AVAILABLE
1977         c = a * b; 
1978 #else
1979         c = builtin_i2l(0);
1980 #endif
1981
1982         return c;
1983 }
1984 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
1985
1986
1987 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1988 s8 builtin_ldiv(s8 a, s8 b)
1989 {
1990         s8 c;
1991
1992 #if U8_AVAILABLE
1993         c = a / b; 
1994 #else
1995         c = builtin_i2l(0);
1996 #endif
1997
1998         return c;
1999 }
2000
2001 s8 builtin_lrem(s8 a, s8 b)
2002 {
2003         s8 c;
2004
2005 #if U8_AVAILABLE
2006         c = a % b; 
2007 #else
2008         c = builtin_i2l(0);
2009 #endif
2010
2011         return c;
2012 }
2013 #endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
2014
2015
2016 #if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
2017 s8 builtin_lshl(s8 a, s4 b)
2018 {
2019         s8 c;
2020
2021 #if U8_AVAILABLE
2022         c = a << (b & 63);
2023 #else
2024         c = builtin_i2l(0);
2025 #endif
2026
2027         return c;
2028 }
2029
2030 s8 builtin_lshr(s8 a, s4 b)
2031 {
2032         s8 c;
2033
2034 #if U8_AVAILABLE
2035         c = a >> (b & 63);
2036 #else
2037         c = builtin_i2l(0);
2038 #endif
2039
2040         return c;
2041 }
2042
2043 s8 builtin_lushr(s8 a, s4 b)
2044 {
2045         s8 c;
2046
2047 #if U8_AVAILABLE
2048         c = ((u8) a) >> (b & 63);
2049 #else
2050         c = builtin_i2l(0);
2051 #endif
2052
2053         return c;
2054 }
2055 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
2056
2057
2058 #if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
2059 s8 builtin_land(s8 a, s8 b)
2060 {
2061         s8 c;
2062
2063 #if U8_AVAILABLE
2064         c = a & b; 
2065 #else
2066         c = builtin_i2l(0);
2067 #endif
2068
2069         return c;
2070 }
2071
2072 s8 builtin_lor(s8 a, s8 b)
2073 {
2074         s8 c;
2075
2076 #if U8_AVAILABLE
2077         c = a | b; 
2078 #else
2079         c = builtin_i2l(0);
2080 #endif
2081
2082         return c;
2083 }
2084
2085 s8 builtin_lxor(s8 a, s8 b) 
2086 {
2087         s8 c;
2088
2089 #if U8_AVAILABLE
2090         c = a ^ b; 
2091 #else
2092         c = builtin_i2l(0);
2093 #endif
2094
2095         return c;
2096 }
2097 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
2098
2099
2100 #if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
2101 s4 builtin_lcmp(s8 a, s8 b)
2102
2103 #if U8_AVAILABLE
2104         if (a < b)
2105                 return -1;
2106
2107         if (a > b)
2108                 return 1;
2109
2110         return 0;
2111 #else
2112         return 0;
2113 #endif
2114 }
2115 #endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
2116
2117
2118 /* functions for unsupported floating instructions ****************************/
2119
2120 /* used to convert FLT_xxx defines into float values */
2121
2122 static inline float intBitsToFloat(s4 i)
2123 {
2124         imm_union imb;
2125
2126         imb.i = i;
2127         return imb.f;
2128 }
2129
2130
2131 /* used to convert DBL_xxx defines into double values */
2132
2133 static inline float longBitsToDouble(s8 l)
2134 {
2135         imm_union imb;
2136
2137         imb.l = l;
2138         return imb.d;
2139 }
2140
2141
2142 #if !SUPPORT_FLOAT
2143 float builtin_fadd(float a, float b)
2144 {
2145         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2146         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2147         if (finitef(a)) {
2148                 if (finitef(b))
2149                         return a + b;
2150                 else
2151                         return b;
2152         }
2153         else {
2154                 if (finitef(b))
2155                         return a;
2156                 else {
2157                         if (copysignf(1.0, a) == copysignf(1.0, b))
2158                                 return a;
2159                         else
2160                                 return intBitsToFloat(FLT_NAN);
2161                 }
2162         }
2163 }
2164
2165
2166 float builtin_fsub(float a, float b)
2167 {
2168         return builtin_fadd(a, builtin_fneg(b));
2169 }
2170
2171
2172 float builtin_fmul(float a, float b)
2173 {
2174         if (isnanf(a)) return intBitsToFloat(FLT_NAN);
2175         if (isnanf(b)) return intBitsToFloat(FLT_NAN);
2176         if (finitef(a)) {
2177                 if (finitef(b)) return a * b;
2178                 else {
2179                         if (a == 0) return intBitsToFloat(FLT_NAN);
2180                         else return copysignf(b, copysignf(1.0, b)*a);
2181                 }
2182         }
2183         else {
2184                 if (finitef(b)) {
2185                         if (b == 0) return intBitsToFloat(FLT_NAN);
2186                         else return copysignf(a, copysignf(1.0, a)*b);
2187                 }
2188                 else {
2189                         return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
2190                 }
2191         }
2192 }
2193
2194
2195 /* builtin_ddiv ****************************************************************
2196
2197    Implementation as described in VM Spec.
2198
2199 *******************************************************************************/
2200
2201 float builtin_fdiv(float a, float b)
2202 {
2203         if (finitef(a)) {
2204                 if (finitef(b)) {
2205                         /* If neither value1' nor value2' is NaN, the sign of the result */
2206                         /* is positive if both values have the same sign, negative if the */
2207                         /* values have different signs. */
2208
2209                         return a / b;
2210
2211                 } else {
2212                         if (isnanf(b)) {
2213                                 /* If either value1' or value2' is NaN, the result is NaN. */
2214
2215                                 return intBitsToFloat(FLT_NAN);
2216
2217                         } else {
2218                                 /* Division of a finite value by an infinity results in a */
2219                                 /* signed zero, with the sign-producing rule just given. */
2220
2221                                 /* is sign equal? */
2222
2223                                 if (copysignf(1.0, a) == copysignf(1.0, b))
2224                                         return 0.0;
2225                                 else
2226                                         return -0.0;
2227                         }
2228                 }
2229
2230         } else {
2231                 if (isnanf(a)) {
2232                         /* If either value1' or value2' is NaN, the result is NaN. */
2233
2234                         return intBitsToFloat(FLT_NAN);
2235
2236                 } else if (finitef(b)) {
2237                         /* Division of an infinity by a finite value results in a signed */
2238                         /* infinity, with the sign-producing rule just given. */
2239
2240                         /* is sign equal? */
2241
2242                         if (copysignf(1.0, a) == copysignf(1.0, b))
2243                                 return intBitsToFloat(FLT_POSINF);
2244                         else
2245                                 return intBitsToFloat(FLT_NEGINF);
2246
2247                 } else {
2248                         /* Division of an infinity by an infinity results in NaN. */
2249
2250                         return intBitsToFloat(FLT_NAN);
2251                 }
2252         }
2253 }
2254
2255
2256 float builtin_fneg(float a)
2257 {
2258         if (isnanf(a)) return a;
2259         else {
2260                 if (finitef(a)) return -a;
2261                 else return copysignf(a, -copysignf(1.0, a));
2262         }
2263 }
2264 #endif /* !SUPPORT_FLOAT */
2265
2266
2267 #if !SUPPORT_FLOAT || defined(ENABLE_INTRP)
2268 s4 builtin_fcmpl(float a, float b)
2269 {
2270         if (isnanf(a)) return -1;
2271         if (isnanf(b)) return -1;
2272         if (!finitef(a) || !finitef(b)) {
2273                 a = finitef(a) ? 0 : copysignf(1.0,     a);
2274                 b = finitef(b) ? 0 : copysignf(1.0, b);
2275         }
2276         if (a > b) return 1;
2277         if (a == b) return 0;
2278         return -1;
2279 }
2280
2281
2282 s4 builtin_fcmpg(float a, float b)
2283 {
2284         if (isnanf(a)) return 1;
2285         if (isnanf(b)) return 1;
2286         if (!finitef(a) || !finitef(b)) {
2287                 a = finitef(a) ? 0 : copysignf(1.0, a);
2288                 b = finitef(b) ? 0 : copysignf(1.0, b);
2289         }
2290         if (a > b) return 1;
2291         if (a == b) return 0;
2292         return -1;
2293 }
2294 #endif /* !SUPPORT_FLOAT || defined(ENABLE_INTRP) */
2295
2296
2297 float builtin_frem(float a, float b)
2298 {
2299         return fmodf(a, b);
2300 }
2301
2302
2303 /* functions for unsupported double instructions ******************************/
2304
2305 #if !SUPPORT_DOUBLE
2306 double builtin_dadd(double a, double b)
2307 {
2308         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2309         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2310         if (finite(a)) {
2311                 if (finite(b)) return a + b;
2312                 else return b;
2313         }
2314         else {
2315                 if (finite(b)) return a;
2316                 else {
2317                         if (copysign(1.0, a)==copysign(1.0, b)) return a;
2318                         else return longBitsToDouble(DBL_NAN);
2319                 }
2320         }
2321 }
2322
2323
2324 double builtin_dsub(double a, double b)
2325 {
2326         return builtin_dadd(a, builtin_dneg(b));
2327 }
2328
2329
2330 double builtin_dmul(double a, double b)
2331 {
2332         if (isnan(a)) return longBitsToDouble(DBL_NAN);
2333         if (isnan(b)) return longBitsToDouble(DBL_NAN);
2334         if (finite(a)) {
2335                 if (finite(b)) return a * b;
2336                 else {
2337                         if (a == 0) return longBitsToDouble(DBL_NAN);
2338                         else return copysign(b, copysign(1.0, b) * a);
2339                 }
2340         }
2341         else {
2342                 if (finite(b)) {
2343                         if (b == 0) return longBitsToDouble(DBL_NAN);
2344                         else return copysign(a, copysign(1.0, a) * b);
2345                 }
2346                 else {
2347                         return copysign(a, copysign(1.0, a) * copysign(1.0, b));
2348                 }
2349         }
2350 }
2351
2352
2353 /* builtin_ddiv ****************************************************************
2354
2355    Implementation as described in VM Spec.
2356
2357 *******************************************************************************/
2358
2359 double builtin_ddiv(double a, double b)
2360 {
2361         if (finite(a)) {
2362                 if (finite(b)) {
2363                         /* If neither value1' nor value2' is NaN, the sign of the result */
2364                         /* is positive if both values have the same sign, negative if the */
2365                         /* values have different signs. */
2366
2367                         return a / b;
2368
2369                 } else {
2370                         if (isnan(b)) {
2371                                 /* If either value1' or value2' is NaN, the result is NaN. */
2372
2373                                 return longBitsToDouble(DBL_NAN);
2374
2375                         } else {
2376                                 /* Division of a finite value by an infinity results in a */
2377                                 /* signed zero, with the sign-producing rule just given. */
2378
2379                                 /* is sign equal? */
2380
2381                                 if (copysign(1.0, a) == copysign(1.0, b))
2382                                         return 0.0;
2383                                 else
2384                                         return -0.0;
2385                         }
2386                 }
2387
2388         } else {
2389                 if (isnan(a)) {
2390                         /* If either value1' or value2' is NaN, the result is NaN. */
2391
2392                         return longBitsToDouble(DBL_NAN);
2393
2394                 } else if (finite(b)) {
2395                         /* Division of an infinity by a finite value results in a signed */
2396                         /* infinity, with the sign-producing rule just given. */
2397
2398                         /* is sign equal? */
2399
2400                         if (copysign(1.0, a) == copysign(1.0, b))
2401                                 return longBitsToDouble(DBL_POSINF);
2402                         else
2403                                 return longBitsToDouble(DBL_NEGINF);
2404
2405                 } else {
2406                         /* Division of an infinity by an infinity results in NaN. */
2407
2408                         return longBitsToDouble(DBL_NAN);
2409                 }
2410         }
2411 }
2412
2413
2414 /* builtin_dneg ****************************************************************
2415
2416    Implemented as described in VM Spec.
2417
2418 *******************************************************************************/
2419
2420 double builtin_dneg(double a)
2421 {
2422         if (isnan(a)) {
2423                 /* If the operand is NaN, the result is NaN (recall that NaN has no */
2424                 /* sign). */
2425
2426                 return a;
2427
2428         } else {
2429                 if (finite(a)) {
2430                         /* If the operand is a zero, the result is the zero of opposite */
2431                         /* sign. */
2432
2433                         return -a;
2434
2435                 } else {
2436                         /* If the operand is an infinity, the result is the infinity of */
2437                         /* opposite sign. */
2438
2439                         return copysign(a, -copysign(1.0, a));
2440                 }
2441         }
2442 }
2443 #endif /* !SUPPORT_DOUBLE */
2444
2445
2446 #if !SUPPORT_DOUBLE || defined(ENABLE_INTRP)
2447 s4 builtin_dcmpl(double a, double b)
2448 {
2449         if (isnan(a)) return -1;
2450         if (isnan(b)) return -1;
2451         if (!finite(a) || !finite(b)) {
2452                 a = finite(a) ? 0 : copysign(1.0, a);
2453                 b = finite(b) ? 0 : copysign(1.0, b);
2454         }
2455         if (a > b) return 1;
2456         if (a == b) return 0;
2457         return -1;
2458 }
2459
2460
2461 s4 builtin_dcmpg(double a, double b)
2462 {
2463         if (isnan(a)) return 1;
2464         if (isnan(b)) return 1;
2465         if (!finite(a) || !finite(b)) {
2466                 a = finite(a) ? 0 : copysign(1.0, a);
2467                 b = finite(b) ? 0 : copysign(1.0, b);
2468         }
2469         if (a > b) return 1;
2470         if (a == b) return 0;
2471         return -1;
2472 }
2473 #endif /* !SUPPORT_DOUBLE || defined(ENABLE_INTRP) */
2474
2475
2476 double builtin_drem(double a, double b)
2477 {
2478         return fmod(a, b);
2479 }
2480
2481
2482 /* conversion operations ******************************************************/
2483
2484 #if 0
2485 s8 builtin_i2l(s4 i)
2486 {
2487 #if U8_AVAILABLE
2488         return i;
2489 #else
2490         s8 v;
2491         v.high = 0;
2492         v.low = i;
2493         return v;
2494 #endif
2495 }
2496
2497 s4 builtin_l2i(s8 l)
2498 {
2499 #if U8_AVAILABLE
2500         return (s4) l;
2501 #else
2502         return l.low;
2503 #endif
2504 }
2505 #endif
2506
2507
2508 #if !(SUPPORT_FLOAT && SUPPORT_I2F)
2509 float builtin_i2f(s4 a)
2510 {
2511         float f = (float) a;
2512         return f;
2513 }
2514 #endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
2515
2516
2517 #if !(SUPPORT_DOUBLE && SUPPORT_I2D)
2518 double builtin_i2d(s4 a)
2519 {
2520         double d = (double) a;
2521         return d;
2522 }
2523 #endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
2524
2525
2526 #if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
2527 float builtin_l2f(s8 a)
2528 {
2529 #if U8_AVAILABLE
2530         float f = (float) a;
2531         return f;
2532 #else
2533         return 0.0;
2534 #endif
2535 }
2536 #endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
2537
2538
2539 #if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
2540 double builtin_l2d(s8 a)
2541 {
2542 #if U8_AVAILABLE
2543         double d = (double) a;
2544         return d;
2545 #else
2546         return 0.0;
2547 #endif
2548 }
2549 #endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
2550
2551
2552 #if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP)
2553 s4 builtin_f2i(float a) 
2554 {
2555         s4 i;
2556
2557         i = builtin_d2i((double) a);
2558
2559         return i;
2560
2561         /*      float f;
2562         
2563                 if (isnanf(a))
2564                 return 0;
2565                 if (finitef(a)) {
2566                 if (a > 2147483647)
2567                 return 2147483647;
2568                 if (a < (-2147483648))
2569                 return (-2147483648);
2570                 return (s4) a;
2571                 }
2572                 f = copysignf((float) 1.0, a);
2573                 if (f > 0)
2574                 return 2147483647;
2575                 return (-2147483648); */
2576 }
2577 #endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) */
2578
2579
2580 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
2581 s8 builtin_f2l(float a)
2582 {
2583         s8 l;
2584
2585         l = builtin_d2l((double) a);
2586
2587         return l;
2588
2589         /*      float f;
2590         
2591                 if (finitef(a)) {
2592                 if (a > 9223372036854775807L)
2593                 return 9223372036854775807L;
2594                 if (a < (-9223372036854775808L))
2595                 return (-9223372036854775808L);
2596                 return (s8) a;
2597                 }
2598                 if (isnanf(a))
2599                 return 0;
2600                 f = copysignf((float) 1.0, a);
2601                 if (f > 0)
2602                 return 9223372036854775807L;
2603                 return (-9223372036854775808L); */
2604 }
2605 #endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
2606
2607
2608 #if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP)
2609 s4 builtin_d2i(double a) 
2610
2611         double d;
2612         
2613         if (finite(a)) {
2614                 if (a >= 2147483647)
2615                         return 2147483647;
2616                 if (a <= (-2147483647-1))
2617                         return (-2147483647-1);
2618                 return (s4) a;
2619         }
2620         if (isnan(a))
2621                 return 0;
2622         d = copysign(1.0, a);
2623         if (d > 0)
2624                 return 2147483647;
2625         return (-2147483647-1);
2626 }
2627 #endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) */
2628
2629
2630 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
2631 s8 builtin_d2l(double a)
2632 {
2633         double d;
2634         
2635         if (finite(a)) {
2636                 if (a >= 9223372036854775807LL)
2637                         return 9223372036854775807LL;
2638                 if (a <= (-9223372036854775807LL-1))
2639                         return (-9223372036854775807LL-1);
2640                 return (s8) a;
2641         }
2642         if (isnan(a))
2643                 return 0;
2644         d = copysign(1.0, a);
2645         if (d > 0)
2646                 return 9223372036854775807LL;
2647         return (-9223372036854775807LL-1);
2648 }
2649 #endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
2650
2651
2652 #if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
2653 double builtin_f2d(float a)
2654 {
2655         if (finitef(a)) return (double) a;
2656         else {
2657                 if (isnanf(a))
2658                         return longBitsToDouble(DBL_NAN);
2659                 else
2660                         return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2661         }
2662 }
2663
2664 float builtin_d2f(double a)
2665 {
2666         if (finite(a))
2667                 return (float) a;
2668         else {
2669                 if (isnan(a))
2670                         return intBitsToFloat(FLT_NAN);
2671                 else
2672                         return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2673         }
2674 }
2675 #endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
2676
2677
2678 /* builtin_clone_array *********************************************************
2679
2680    Wrapper function for cloning arrays.
2681
2682 *******************************************************************************/
2683
2684 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2685 {
2686         java_arrayheader    *ah;
2687         java_lang_Cloneable *c;
2688
2689         c = (java_lang_Cloneable *) o;
2690
2691         ah = (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, c);
2692
2693         return ah;
2694 }
2695
2696
2697 /* builtin_asm_get_exceptionptrptr *********************************************
2698
2699    this is a wrapper for calls from asmpart
2700
2701 *******************************************************************************/
2702
2703 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2704 java_objectheader **builtin_asm_get_exceptionptrptr(void)
2705 {
2706         return builtin_get_exceptionptrptr();
2707 }
2708 #endif
2709
2710
2711 /*
2712  * These are local overrides for various environment variables in Emacs.
2713  * Please do not remove this and leave it at the end of the file, where
2714  * Emacs will automagically detect them.
2715  * ---------------------------------------------------------------------
2716  * Local variables:
2717  * mode: c
2718  * indent-tabs-mode: t
2719  * c-basic-offset: 4
2720  * tab-width: 4
2721  * End:
2722  * vim:noexpandtab:sw=4:ts=4:
2723  */