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