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