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