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