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