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