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