1 /* src/vm/builtin.c - functions for unsupported operations
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
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
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
39 $Id: builtin.c 2201 2005-04-03 21:48:11Z twisti $
53 #include "mm/memory.h"
54 #include "native/native.h"
55 #include "native/include/java_lang_Cloneable.h"
56 #include "native/include/java_lang_VMObject.h"
58 #if defined(USE_THREADS)
59 # if defined(NATIVE_THREADS)
60 # include "threads/native/threads.h"
62 # include "threads/green/threads.h"
63 # include "threads/green/locks.h"
67 #include "toolbox/logging.h"
68 #include "vm/builtin.h"
69 #include "vm/exceptions.h"
70 #include "vm/global.h"
71 #include "vm/initialize.h"
72 #include "vm/loader.h"
73 #include "vm/options.h"
74 #include "vm/stringlocal.h"
75 #include "vm/tables.h"
76 #include "vm/jit/asmpart.h"
79 #undef DEBUG /*define DEBUG 1*/
81 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
82 THREADSPECIFIC void *_thread_nativestackframeinfo = NULL;
85 #if defined(USEBUILTINTABLE)
88 stdopdescriptor builtintable[] = {
89 { ICMD_LCMP, TYPE_LONG, TYPE_LONG, TYPE_INT, ICMD_BUILTIN2,
90 (functionptr) builtin_lcmp , SUPPORT_LONG && SUPPORT_LONG_CMP, false },
91 { ICMD_LAND, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
92 (functionptr) builtin_land , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
93 { ICMD_LOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
94 (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
95 { ICMD_LXOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
96 (functionptr) builtin_lxor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
97 { ICMD_LSHL, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
98 (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
99 { ICMD_LSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
100 (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
101 { ICMD_LUSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
102 (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
103 { ICMD_LADD, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
104 (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
105 { ICMD_LSUB, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
106 (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
107 { ICMD_LNEG, TYPE_LONG, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
108 (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, true },
109 { ICMD_LMUL, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
110 (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MUL, false },
111 { ICMD_I2F, TYPE_INT, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
112 (functionptr) builtin_i2f, SUPPORT_FLOAT && SUPPORT_IFCVT, true },
113 { ICMD_I2D, TYPE_INT, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
114 (functionptr) builtin_i2d, SUPPORT_DOUBLE && SUPPORT_IFCVT, true },
115 { ICMD_L2F, TYPE_LONG, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
116 (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
117 { ICMD_L2D, TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
118 (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
119 { ICMD_F2L, TYPE_FLOAT, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
120 (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
121 { ICMD_D2L, TYPE_DOUBLE, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
122 (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
123 { ICMD_F2I, TYPE_FLOAT, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
124 (functionptr) builtin_f2i, SUPPORT_FLOAT && SUPPORT_FICVT, true },
125 { ICMD_D2I, TYPE_DOUBLE, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
126 (functionptr) builtin_d2i, SUPPORT_DOUBLE && SUPPORT_FICVT, true },
127 { 255, 0, 0, 0, 0, NULL, true, false },
132 static int builtintablelen;
134 #endif /* USEBUILTINTABLE */
137 /*****************************************************************************
138 TABLE OF BUILTIN FUNCTIONS
140 This table lists the builtin functions which are used inside
143 The first part of the table (up to the 255-marker) lists the
144 opcodes which are automatically replaced in stack.c.
146 The second part lists the builtin functions which are "manually"
147 used for BUILTIN* opcodes in parse.c and stack.c.
149 *****************************************************************************/
151 builtin_descriptor builtin_desc[] = {
152 #if defined(USEBUILTINTABLE)
153 {ICMD_LCMP , BUILTIN_lcmp ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_INT ,
154 SUPPORT_LONG && SUPPORT_LONG_CMP,false,"lcmp"},
156 {ICMD_LAND , BUILTIN_land ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
157 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"land"},
158 {ICMD_LOR , BUILTIN_lor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
159 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lor"},
160 {ICMD_LXOR , BUILTIN_lxor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
161 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lxor"},
163 {ICMD_LSHL , BUILTIN_lshl ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
164 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshl"},
165 {ICMD_LSHR , BUILTIN_lshr ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
166 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshr"},
167 {ICMD_LUSHR, BUILTIN_lushr,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
168 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lushr"},
170 {ICMD_LADD , BUILTIN_ladd ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
171 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"ladd"},
172 {ICMD_LSUB , BUILTIN_lsub ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
173 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lsub"},
174 {ICMD_LNEG , BUILTIN_lneg ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
175 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lneg"},
176 {ICMD_LMUL , BUILTIN_lmul ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
177 SUPPORT_LONG && SUPPORT_LONG_MUL,false,"lmul"},
179 {ICMD_I2F , BUILTIN_i2f ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
180 SUPPORT_FLOAT && SUPPORT_IFCVT,true ,"i2f"},
181 {ICMD_I2D , BUILTIN_i2d ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
182 SUPPORT_DOUBLE && SUPPORT_IFCVT,true ,"i2d"},
183 {ICMD_L2F , BUILTIN_l2f ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
184 SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT,true ,"l2f"},
185 {ICMD_L2D , BUILTIN_l2d ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
186 SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT,true ,"l2d"},
187 {ICMD_F2L , BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
188 SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"f2l"},
189 {ICMD_D2L , BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
190 SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"d2l"},
191 {ICMD_F2I , BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
192 SUPPORT_FLOAT && SUPPORT_FICVT,true ,"f2i"},
193 {ICMD_D2I , BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
194 SUPPORT_DOUBLE && SUPPORT_FICVT,true ,"d2i"},
196 { ICMD_FADD , BUILTIN_fadd , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fadd" },
197 { ICMD_FSUB , BUILTIN_fsub , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fsub" },
198 { ICMD_FMUL , BUILTIN_fmul , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fmul" },
199 { ICMD_FDIV , BUILTIN_fdiv , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fdiv" },
200 { ICMD_FNEG , BUILTIN_fneg , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fneg" },
201 { ICMD_FCMPL, BUILTIN_fcmpl , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpl" },
202 { ICMD_FCMPG, BUILTIN_fcmpg , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpg" },
204 { ICMD_DADD , BUILTIN_dadd , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dadd" },
205 { ICMD_DSUB , BUILTIN_dsub , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dsub" },
206 { ICMD_DMUL , BUILTIN_dmul , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dmul" },
207 { ICMD_DDIV , BUILTIN_ddiv , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "ddiv" },
208 { ICMD_DNEG , BUILTIN_dneg , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dneg" },
209 { ICMD_DCMPL, BUILTIN_dcmpl , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpl" },
210 { ICMD_DCMPG, BUILTIN_dcmpg , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpg" },
212 { ICMD_F2D, BUILTIN_f2d , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "f2d" },
213 { ICMD_D2F, BUILTIN_d2f , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "d2f" },
216 /* this record marks the end of the automatically replaced opcodes */
217 {255,NULL,0,0,0,0,0,0,0,"<INVALID>"},
219 /* the following functions are not replaced automatically */
221 #if defined(__ALPHA__)
222 {255, BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"f2l"},
223 {255, BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"d2l"},
224 {255, BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"f2i"},
225 {255, BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"d2i"},
228 {255,BUILTIN_instanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"instanceof"},
229 {255,BUILTIN_arrayinstanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"arrayinstanceof"},
230 {255,BUILTIN_checkarraycast ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,0,0,"checkarraycast"},
231 {255,BUILTIN_aastore ,ICMD_BUILTIN3,TYPE_ADR ,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,0,0,"aastore"},
232 {255,BUILTIN_new ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"new"},
233 {255,BUILTIN_newarray ,ICMD_BUILTIN2,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray"},
234 {255,BUILTIN_newarray_boolean,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_boolean"},
235 {255,BUILTIN_newarray_char ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_char"},
236 {255,BUILTIN_newarray_float ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_float"},
237 {255,BUILTIN_newarray_double ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_double"},
238 {255,BUILTIN_newarray_byte ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_byte"},
239 {255,BUILTIN_newarray_short ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_short"},
240 {255,BUILTIN_newarray_int ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_int"},
241 {255,BUILTIN_newarray_long ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_long"},
242 {255,BUILTIN_anewarray ,ICMD_BUILTIN2,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,TYPE_ADR ,0,0,"anewarray"},
243 #if defined(USE_THREADS)
244 {255,BUILTIN_monitorenter ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorenter"},
245 {255,BUILTIN_monitorexit ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorexit"},
247 #if !SUPPORT_DIVISION
248 {255,BUILTIN_idiv ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"idiv"},
249 {255,BUILTIN_irem ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"irem"},
251 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
252 {255,BUILTIN_ldiv ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"ldiv"},
253 {255,BUILTIN_lrem ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"lrem"},
255 {255,BUILTIN_frem ,ICMD_BUILTIN2,TYPE_FLOAT ,TYPE_FLOAT ,TYPE_VOID ,TYPE_FLOAT ,0,0,"frem"},
256 {255,BUILTIN_drem ,ICMD_BUILTIN2,TYPE_DOUBLE,TYPE_DOUBLE,TYPE_VOID ,TYPE_DOUBLE,0,0,"drem"},
258 /* this record marks the end of the list */
259 { 0,NULL,0,0,0,0,0,0,0,"<END>"}
263 #if defined(USEBUILTINTABLE)
265 static int stdopcompare(const void *a, const void *b)
267 builtin_descriptor *o1 = (builtin_descriptor *) a;
268 builtin_descriptor *o2 = (builtin_descriptor *) b;
269 if (!o1->supported && o2->supported)
271 if (o1->supported && !o2->supported)
273 return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
277 void sort_builtintable(void)
282 while (builtin_desc[len].opcode != 255) len++;
283 qsort(builtin_desc, len, sizeof(builtin_descriptor), stdopcompare);
285 for (--len; len>=0 && builtin_desc[len].supported; len--);
286 builtintablelen = ++len;
290 builtin_descriptor *find_builtin(int icmd)
292 builtin_descriptor *first = builtin_desc;
293 builtin_descriptor *last = builtin_desc + builtintablelen;
294 int len = last - first;
296 builtin_descriptor *middle;
300 middle = first + half;
301 if (middle->opcode < icmd) {
307 return first != last ? first : NULL;
310 #endif /* defined(USEBUILTINTABLE) */
313 /*****************************************************************************
315 *****************************************************************************/
319 /*************** internal function: builtin_isanysubclass *********************
321 Checks a subclass relation between two classes. Implemented interfaces
322 are interpreted as super classes.
323 Return value: 1 ... sub is subclass of super
326 *****************************************************************************/
327 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
330 castinfo classvalues;
335 if (super->flags & ACC_INTERFACE)
336 return (sub->vftbl->interfacetablelength > super->index) &&
337 (sub->vftbl->interfacetable[-super->index] != NULL);
339 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
341 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
342 (u4) classvalues.super_diffval;
348 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
352 castinfo classvalues;
357 asm_getclassvalues_atomic(super, sub, &classvalues);
359 if ((base = classvalues.super_baseval) <= 0)
360 /* super is an interface */
361 res = (sub->interfacetablelength > -base) &&
362 (sub->interfacetable[base] != NULL);
364 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
365 <= (u4) classvalues.super_diffval;
371 /****************** function: builtin_instanceof *****************************
373 Checks if an object is an instance of some given class (or subclass of
374 that class). If class is an interface, checks if the interface is
376 Return value: 1 ... obj is an instance of class or implements the interface
377 0 ... otherwise or if obj == NULL
379 *****************************************************************************/
381 /* XXX should use vftbl */
382 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
385 log_text ("builtin_instanceof called");
390 return builtin_isanysubclass(obj->vftbl->class, class);
395 /**************** function: builtin_checkcast *******************************
397 The same as builtin_instanceof except that 1 is returned when
400 ****************************************************************************/
402 /* XXX should use vftbl */
403 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
406 log_text("builtin_checkcast called");
411 if (builtin_isanysubclass(obj->vftbl->class, class))
415 printf("#### checkcast failed ");
416 utf_display(obj->vftbl->class->name);
418 utf_display(class->name);
426 /*********** internal function: builtin_descriptorscompatible ******************
428 Checks if two array type descriptors are assignment compatible
429 Return value: 1 ... target = desc is possible
432 ******************************************************************************/
434 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
436 if (desc==target) return 1;
437 if (desc->arraytype != target->arraytype) return 0;
438 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
440 /* {both arrays are arrays of references} */
441 if (desc->dimension == target->dimension) {
442 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
443 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
444 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
446 if (desc->dimension < target->dimension) return 0;
448 /* {desc has higher dimension than target} */
449 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
453 /******************** function: builtin_checkarraycast ***********************
455 Checks if an object is really a subtype of the requested array type.
456 The object has to be an array to begin with. For simple arrays (int, short,
457 double, etc.) the types have to match exactly.
458 For arrays of objects, the type of elements in the array has to be a
459 subtype (or the same type) of the requested element type. For arrays of
460 arrays (which in turn can again be arrays of arrays), the types at the
461 lowest level have to satisfy the corresponding sub class relation.
463 Return value: 1 ... cast is possible
466 ATTENTION: a cast with a NULL pointer is always possible.
468 *****************************************************************************/
470 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
472 arraydescriptor *desc;
475 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
477 return builtin_descriptorscompatible(desc, target->arraydesc);
481 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
484 return builtin_checkarraycast(obj, target);
488 /************************** exception functions *******************************
490 ******************************************************************************/
492 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
495 char logtext[MAXLOGTEXT];
496 sprintf(logtext, "Builtin exception thrown: ");
499 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
501 utf_sprint_classname(logtext + strlen(logtext),
502 xptr->vftbl->class->name);
504 if (t->detailMessage) {
507 buf = javastring_tochar((java_objectheader *) t->detailMessage);
508 sprintf(logtext + strlen(logtext), ": %s", buf);
509 MFREE(buf, char, strlen(buf));
513 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
519 *exceptionptr = xptr;
526 /******************* function: builtin_canstore *******************************
528 Checks, if an object can be stored in an array.
529 Return value: 1 ... possible
532 ******************************************************************************/
534 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
536 arraydescriptor *desc;
537 arraydescriptor *valuedesc;
538 vftbl_t *componentvftbl;
542 castinfo classvalues;
546 /* The following is guaranteed (by verifier checks):
548 * *) a->...vftbl->arraydesc != NULL
549 * *) a->...vftbl->arraydesc->componentvftbl != NULL
550 * *) o->vftbl is not an interface vftbl
553 desc = a->header.objheader.vftbl->arraydesc;
554 componentvftbl = desc->componentvftbl;
555 valuevftbl = o->vftbl;
557 if ((dim_m1 = desc->dimension - 1) == 0) {
560 /* {a is a one-dimensional array} */
561 /* {a is an array of references} */
563 if (valuevftbl == componentvftbl)
566 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
568 if ((base = classvalues.super_baseval) <= 0)
569 /* an array of interface references */
570 return (valuevftbl->interfacetablelength > -base &&
571 valuevftbl->interfacetable[base] != NULL);
573 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
574 <= (unsigned) classvalues.super_diffval;
578 /* {a has dimension > 1} */
579 /* {componentvftbl->arraydesc != NULL} */
581 /* check if o is an array */
582 if ((valuedesc = valuevftbl->arraydesc) == NULL)
584 /* {o is an array} */
586 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
590 /* This is an optimized version where a is guaranteed to be one-dimensional */
591 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
593 arraydescriptor *desc;
594 vftbl_t *elementvftbl;
598 castinfo classvalues;
602 /* The following is guaranteed (by verifier checks):
604 * *) a->...vftbl->arraydesc != NULL
605 * *) a->...vftbl->arraydesc->elementvftbl != NULL
606 * *) a->...vftbl->arraydesc->dimension == 1
607 * *) o->vftbl is not an interface vftbl
610 desc = a->header.objheader.vftbl->arraydesc;
611 elementvftbl = desc->elementvftbl;
612 valuevftbl = o->vftbl;
614 /* {a is a one-dimensional array} */
616 if (valuevftbl == elementvftbl)
619 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
621 if ((base = classvalues.super_baseval) <= 0)
622 /* an array of interface references */
623 return (valuevftbl->interfacetablelength > -base &&
624 valuevftbl->interfacetable[base] != NULL);
626 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
627 <= (unsigned) classvalues.super_diffval;
633 /* This is an optimized version where a is guaranteed to be a
634 * one-dimensional array of a class type */
635 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
637 vftbl_t *elementvftbl;
640 castinfo classvalues;
644 /* The following is guaranteed (by verifier checks):
646 * *) a->...vftbl->arraydesc != NULL
647 * *) a->...vftbl->arraydesc->elementvftbl != NULL
648 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
649 * *) a->...vftbl->arraydesc->dimension == 1
650 * *) o->vftbl is not an interface vftbl
653 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
654 valuevftbl = o->vftbl;
656 /* {a is a one-dimensional array} */
658 if (valuevftbl == elementvftbl)
661 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
663 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
664 <= (unsigned) classvalues.super_diffval;
670 /* builtin_new *****************************************************************
672 Creates a new instance of class c on the heap.
674 Return value: pointer to the object or NULL if no memory is
677 *******************************************************************************/
679 java_objectheader *builtin_new(classinfo *c)
681 java_objectheader *o;
683 /* is the class loaded */
684 /*utf_fprint(stderr,c->name);fprintf(stderr,"\n");*/
687 /* is the class linked */
692 if (!c->initialized) {
694 log_message_class("Initialize class (from builtin_new): ", c);
696 if (!initialize_class(c))
700 o = heap_allocate(c->instancesize, true, c->finalizer);
705 MSET(o, 0, u1, c->instancesize);
709 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
717 /* builtin_newarray ************************************************************
719 Creates an array with the given vftbl on the heap.
721 Return value: pointer to the array or NULL if no memory is available
723 CAUTION: The given vftbl must be the vftbl of the *array* class,
724 not of the element class.
726 *******************************************************************************/
728 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
731 arraydescriptor *desc;
736 desc = arrayvftbl->arraydesc;
737 dataoffset = desc->dataoffset;
738 componentsize = desc->componentsize;
741 *exceptionptr = new_negativearraysizeexception();
745 actualsize = dataoffset + size * componentsize;
747 if (((u4) actualsize) < ((u4) size)) { /* overflow */
748 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
752 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
757 MSET(a, 0, u1, actualsize);
759 a->objheader.vftbl = arrayvftbl;
761 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
762 initObjectLock(&a->objheader);
771 /********************** Function: builtin_anewarray *************************
773 Creates an array of references to the given class type on the heap.
775 Return value: pointer to the array or NULL if no memory is available
777 XXX This function does not do The Right Thing, because it uses a
778 classinfo pointer at runtime. builtin_newarray should be used
781 *****************************************************************************/
783 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
787 /* is class loaded */
788 assert(component->loaded);
790 /* is class linked */
791 if (!component->linked)
792 if (!link_class(component))
795 c = class_array_of(component,true);
798 return (java_objectarray *) builtin_newarray(size, c->vftbl);
802 /******************** Function: builtin_newarray_int ***********************
804 Creates an array of 32 bit Integers on the heap.
806 Return value: pointer to the array or NULL if no memory is available
808 *****************************************************************************/
810 java_intarray *builtin_newarray_int(s4 size)
812 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
816 /******************** Function: builtin_newarray_long ***********************
818 Creates an array of 64 bit Integers on the heap.
820 Return value: pointer to the array or NULL if no memory is available
822 *****************************************************************************/
824 java_longarray *builtin_newarray_long(s4 size)
826 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
830 /******************** function: builtin_newarray_float ***********************
832 Creates an array of 32 bit IEEE floats on the heap.
834 Return value: pointer to the array or NULL if no memory is available
836 *****************************************************************************/
838 java_floatarray *builtin_newarray_float(s4 size)
840 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
844 /******************** function: builtin_newarray_double ***********************
846 Creates an array of 64 bit IEEE floats on the heap.
848 Return value: pointer to the array or NULL if no memory is available
850 *****************************************************************************/
852 java_doublearray *builtin_newarray_double(s4 size)
854 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
858 /******************** function: builtin_newarray_byte ***********************
860 Creates an array of 8 bit Integers on the heap.
862 Return value: pointer to the array or NULL if no memory is available
864 *****************************************************************************/
866 java_bytearray *builtin_newarray_byte(s4 size)
868 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
872 /******************** function: builtin_newarray_char ************************
874 Creates an array of characters on the heap.
876 Return value: pointer to the array or NULL if no memory is available
878 *****************************************************************************/
880 java_chararray *builtin_newarray_char(s4 size)
882 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
886 /******************** function: builtin_newarray_short ***********************
888 Creates an array of 16 bit Integers on the heap.
890 Return value: pointer to the array or NULL if no memory is available
892 *****************************************************************************/
894 java_shortarray *builtin_newarray_short(s4 size)
896 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
900 /******************** function: builtin_newarray_boolean ************************
902 Creates an array of bytes on the heap. The array is designated as an array
903 of booleans (important for casts)
905 Return value: pointer to the array or NULL if no memory is available
907 *****************************************************************************/
909 java_booleanarray *builtin_newarray_boolean(s4 size)
911 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
915 /**************** function: builtin_nmultianewarray ***************************
917 Creates a multi-dimensional array on the heap. The dimensions are passed in
921 n............number of dimensions to create
922 arrayvftbl...vftbl of the array class
923 dims.........array containing the size of each dimension to create
925 Return value: pointer to the array or NULL if no memory is available
927 ******************************************************************************/
929 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
930 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
934 vftbl_t *componentvftbl;
936 /* utf_display(arrayclass->name); */
938 /* class_load(arrayclass); */
939 /* class_link(arrayclass); */
941 /* create this dimension */
943 a = builtin_newarray(size, arrayvftbl);
944 /* a = builtin_newarray(size, arrayclass->vftbl); */
949 /* if this is the last dimension return */
953 /* get the vftbl of the components to create */
954 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
955 /* component = arrayclass->vftbl->arraydesc; */
957 /* The verifier guarantees this. */
958 /* if (!componentvftbl) */
959 /* panic ("multianewarray with too many dimensions"); */
961 /* create the component arrays */
962 for (i = 0; i < size; i++) {
963 java_arrayheader *ea =
964 builtin_nmultianewarray(n, componentvftbl, dims + 1);
969 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
976 /*****************************************************************************
979 Various functions for printing a message at method entry or exit (for
982 *****************************************************************************/
986 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
996 log_text("WARNING: unmatched methodindent--");
998 if (opt_verbose || runverbose || verboseexception) {
1000 printf("Exception ");
1001 utf_display_classname(xptr->vftbl->class->name);
1004 printf("Some Throwable");
1006 printf(" thrown in ");
1009 utf_display_classname(m->class->name);
1011 utf_display(m->name);
1012 if (m->flags & ACC_SYNCHRONIZED) {
1019 if (m->flags & ACC_NATIVE) {
1021 #if POINTERSIZE == 8
1022 printf(")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1024 printf(")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1028 #if POINTERSIZE == 8
1029 printf(")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1031 printf(")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1033 if (m->class->sourcefile == NULL) {
1034 printf("<NO CLASSFILE INFORMATION>");
1037 utf_display(m->class->sourcefile);
1039 printf(":%d)\n", line);
1043 printf("call_java_method\n");
1051 #ifdef TRACE_ARGS_NUM
1052 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1053 #if TRACE_ARGS_NUM >= 6
1056 #if TRACE_ARGS_NUM == 8
1062 char logtext[MAXLOGTEXT];
1063 for (i = 0; i < methodindent; i++)
1065 if (methodindent == 0)
1066 sprintf(logtext + methodindent, "1st_call: ");
1068 sprintf(logtext + methodindent, "called: ");
1070 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1071 sprintf(logtext + strlen(logtext), ".");
1072 utf_sprint(logtext + strlen(logtext), m->name);
1073 utf_sprint(logtext + strlen(logtext), m->descriptor);
1075 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1076 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1077 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1078 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1079 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1080 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1081 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1082 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1083 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1084 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1085 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1088 sprintf(logtext + strlen(logtext), "(");
1090 switch (m->paramcount) {
1094 #if defined(__I386__) || defined(__POWERPC__)
1096 sprintf(logtext+strlen(logtext), "%llx", a0);
1100 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1104 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1108 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1112 #if TRACE_ARGS_NUM >= 6
1114 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1115 a0, a1, a2, a3, a4);
1119 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1120 a0, a1, a2, a3, a4, a5);
1122 #endif /* TRACE_ARGS_NUM >= 6 */
1124 #if TRACE_ARGS_NUM == 8
1126 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1127 a0, a1, a2, a3, a4, a5, a6);
1131 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1132 a0, a1, a2, a3, a4, a5, a6, a7);
1136 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1137 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1139 #else /* TRACE_ARGS_NUM == 8 */
1141 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1142 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1144 #endif /* TRACE_ARGS_NUM == 8 */
1145 #else /* defined(__I386__) || defined(__POWERPC__) */
1147 sprintf(logtext+strlen(logtext), "%lx", a0);
1151 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1155 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1159 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1163 #if TRACE_ARGS_NUM >= 6
1165 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1166 a0, a1, a2, a3, a4);
1170 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1171 a0, a1, a2, a3, a4, a5);
1173 #endif /* TRACE_ARGS_NUM >= 6 */
1175 #if TRACE_ARGS_NUM == 8
1177 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1178 a0, a1, a2, a3, a4, a5, a6);
1182 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1183 a0, a1, a2, a3, a4, a5, a6, a7);
1185 #endif /* TRACE_ARGS_NUM == 8 */
1188 #if TRACE_ARGS_NUM == 4
1189 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1190 a0, a1, a2, a3, m->paramcount - 4);
1192 #elif TRACE_ARGS_NUM == 6
1193 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1194 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1196 #elif TRACE_ARGS_NUM == 8
1197 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1198 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1201 #endif /* defined(__I386__) || defined(__POWERPC__) */
1204 sprintf(logtext + strlen(logtext), ")");
1212 void builtin_displaymethodstart(methodinfo *m)
1214 char logtext[MAXLOGTEXT];
1215 sprintf(logtext, " ");
1216 sprintf(logtext + methodindent, "called: ");
1217 utf_sprint(logtext + strlen(logtext), m->class->name);
1218 sprintf(logtext + strlen(logtext), ".");
1219 utf_sprint(logtext + strlen(logtext), m->name);
1220 utf_sprint(logtext + strlen(logtext), m->descriptor);
1222 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1223 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1224 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1225 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1226 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1227 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1228 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1229 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1230 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1231 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1232 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1239 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1242 char logtext[MAXLOGTEXT];
1243 for (i = 0; i < methodindent; i++)
1248 log_text("WARNING: unmatched methodindent--");
1250 sprintf(logtext + methodindent, "finished: ");
1251 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1252 sprintf(logtext + strlen(logtext), ".");
1253 utf_sprint(logtext + strlen(logtext), m->name);
1254 utf_sprint(logtext + strlen(logtext), m->descriptor);
1256 switch (m->returntype) {
1258 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1262 #if defined(__I386__) || defined(__POWERPC__)
1263 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1265 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1270 #if defined(__I386__) || defined(__POWERPC__)
1271 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1273 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1278 sprintf(logtext + strlen(logtext), "->%g", f);
1282 sprintf(logtext + strlen(logtext), "->%g", d);
1289 /****************************************************************************
1290 SYNCHRONIZATION FUNCTIONS
1291 *****************************************************************************/
1293 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1295 * Lock the mutex of an object.
1297 void internal_lock_mutex_for_object(java_objectheader *object)
1299 mutexHashEntry *entry;
1302 assert(object != 0);
1304 hashValue = MUTEX_HASH_VALUE(object);
1305 entry = &mutexHashTable[hashValue];
1307 if (entry->object != 0) {
1308 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1310 entry->mutex.holder = 0;
1311 entry->mutex.count = 0;
1312 entry->mutex.muxWaiters = 0;
1315 while (entry->next != 0 && entry->object != object)
1316 entry = entry->next;
1318 if (entry->object != object) {
1319 entry->next = firstFreeOverflowEntry;
1320 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1322 entry = entry->next;
1325 assert(entry->conditionCount == 0);
1330 entry->mutex.holder = 0;
1331 entry->mutex.count = 0;
1332 entry->mutex.muxWaiters = 0;
1335 if (entry->object == 0)
1336 entry->object = object;
1338 internal_lock_mutex(&entry->mutex);
1343 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1345 * Unlocks the mutex of an object.
1347 void internal_unlock_mutex_for_object (java_objectheader *object)
1350 mutexHashEntry *entry;
1352 hashValue = MUTEX_HASH_VALUE(object);
1353 entry = &mutexHashTable[hashValue];
1355 if (entry->object == object) {
1356 internal_unlock_mutex(&entry->mutex);
1359 while (entry->next != 0 && entry->next->object != object)
1360 entry = entry->next;
1362 assert(entry->next != 0);
1364 internal_unlock_mutex(&entry->next->mutex);
1366 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1367 mutexHashEntry *unlinked = entry->next;
1369 entry->next = unlinked->next;
1370 unlinked->next = firstFreeOverflowEntry;
1371 firstFreeOverflowEntry = unlinked;
1378 #if defined(USE_THREADS)
1379 void builtin_monitorenter(java_objectheader *o)
1381 #if !defined(NATIVE_THREADS)
1386 hashValue = MUTEX_HASH_VALUE(o);
1387 if (mutexHashTable[hashValue].object == o
1388 && mutexHashTable[hashValue].mutex.holder == currentThread)
1389 ++mutexHashTable[hashValue].mutex.count;
1391 internal_lock_mutex_for_object(o);
1395 monitorEnter((threadobject *) THREADOBJECT, o);
1401 #if defined(USE_THREADS)
1403 * Locks the class object - needed for static synchronized methods.
1404 * The use_class_as_object call is needed in order to circumvent a
1405 * possible deadlock with builtin_monitorenter called by another
1406 * thread calling use_class_as_object.
1408 void builtin_staticmonitorenter(classinfo *c)
1410 use_class_as_object(c);
1411 builtin_monitorenter(&c->header);
1416 #if defined(USE_THREADS)
1417 void *builtin_monitorexit(java_objectheader *o)
1419 #if !defined(NATIVE_THREADS)
1424 hashValue = MUTEX_HASH_VALUE(o);
1425 if (mutexHashTable[hashValue].object == o) {
1426 if (mutexHashTable[hashValue].mutex.count == 1
1427 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1428 internal_unlock_mutex_for_object(o);
1430 --mutexHashTable[hashValue].mutex.count;
1433 internal_unlock_mutex_for_object(o);
1438 monitorExit((threadobject *) THREADOBJECT, o);
1445 /*****************************************************************************
1446 MISCELLANEOUS HELPER FUNCTIONS
1447 *****************************************************************************/
1451 /*********** Functions for integer divisions *****************************
1453 On some systems (eg. DEC ALPHA), integer division is not supported by the
1454 CPU. These helper functions implement the missing functionality.
1456 ******************************************************************************/
1458 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1459 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1462 /************** Functions for long arithmetics *******************************
1464 On systems where 64 bit Integers are not supported by the CPU, these
1465 functions are needed.
1467 ******************************************************************************/
1470 s8 builtin_ladd(s8 a, s8 b)
1475 return builtin_i2l(0);
1479 s8 builtin_lsub(s8 a, s8 b)
1484 return builtin_i2l(0);
1488 s8 builtin_lmul(s8 a, s8 b)
1493 return builtin_i2l(0);
1497 s8 builtin_ldiv(s8 a, s8 b)
1502 return builtin_i2l(0);
1506 s8 builtin_lrem(s8 a, s8 b)
1511 return builtin_i2l(0);
1515 s8 builtin_lshl(s8 a, s4 b)
1518 return a << (b & 63);
1520 return builtin_i2l(0);
1524 s8 builtin_lshr(s8 a, s4 b)
1527 return a >> (b & 63);
1529 return builtin_i2l(0);
1533 s8 builtin_lushr(s8 a, s4 b)
1536 return ((u8) a) >> (b & 63);
1538 return builtin_i2l(0);
1542 s8 builtin_land(s8 a, s8 b)
1547 return builtin_i2l(0);
1551 s8 builtin_lor(s8 a, s8 b)
1556 return builtin_i2l(0);
1560 s8 builtin_lxor(s8 a, s8 b)
1565 return builtin_i2l(0);
1569 s8 builtin_lneg(s8 a)
1574 return builtin_i2l(0);
1578 s4 builtin_lcmp(s8 a, s8 b)
1581 if (a < b) return -1;
1582 if (a > b) return 1;
1593 /*********** Functions for floating point operations *************************/
1595 float builtin_fadd(float a, float b)
1597 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1598 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1609 if (copysignf(1.0, a) == copysignf(1.0, b))
1612 return intBitsToFloat(FLT_NAN);
1618 float builtin_fsub(float a, float b)
1620 return builtin_fadd(a, builtin_fneg(b));
1624 float builtin_fmul(float a, float b)
1626 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1627 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1629 if (finitef(b)) return a * b;
1631 if (a == 0) return intBitsToFloat(FLT_NAN);
1632 else return copysignf(b, copysignf(1.0, b)*a);
1637 if (b == 0) return intBitsToFloat(FLT_NAN);
1638 else return copysignf(a, copysignf(1.0, a)*b);
1641 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1647 float builtin_fdiv(float a, float b)
1649 if (finitef(a) && finitef(b)) {
1654 return intBitsToFloat(FLT_POSINF);
1656 return intBitsToFloat(FLT_NEGINF);
1659 return intBitsToFloat(FLT_NAN);
1663 float builtin_frem(float a, float b)
1669 float builtin_fneg(float a)
1671 if (isnanf(a)) return a;
1673 if (finitef(a)) return -a;
1674 else return copysignf(a, -copysignf(1.0, a));
1679 s4 builtin_fcmpl(float a, float b)
1681 if (isnanf(a)) return -1;
1682 if (isnanf(b)) return -1;
1683 if (!finitef(a) || !finitef(b)) {
1684 a = finitef(a) ? 0 : copysignf(1.0, a);
1685 b = finitef(b) ? 0 : copysignf(1.0, b);
1687 if (a > b) return 1;
1688 if (a == b) return 0;
1693 s4 builtin_fcmpg(float a, float b)
1695 if (isnanf(a)) return 1;
1696 if (isnanf(b)) return 1;
1697 if (!finitef(a) || !finitef(b)) {
1698 a = finitef(a) ? 0 : copysignf(1.0, a);
1699 b = finitef(b) ? 0 : copysignf(1.0, b);
1701 if (a > b) return 1;
1702 if (a == b) return 0;
1708 /************************* Functions for doubles ****************************/
1710 double builtin_dadd(double a, double b)
1712 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1713 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1715 if (finite(b)) return a + b;
1719 if (finite(b)) return a;
1721 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1722 else return longBitsToDouble(DBL_NAN);
1728 double builtin_dsub(double a, double b)
1730 return builtin_dadd(a, builtin_dneg(b));
1734 double builtin_dmul(double a, double b)
1736 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1737 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1739 if (finite(b)) return a * b;
1741 if (a == 0) return longBitsToDouble(DBL_NAN);
1742 else return copysign(b, copysign(1.0, b) * a);
1747 if (b == 0) return longBitsToDouble(DBL_NAN);
1748 else return copysign(a, copysign(1.0, a) * b);
1751 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1757 double builtin_ddiv(double a, double b)
1765 return longBitsToDouble(DBL_NAN);
1767 return copysign(0.0, b);
1773 return longBitsToDouble(DBL_POSINF);
1775 return longBitsToDouble(DBL_NEGINF);
1778 return longBitsToDouble(DBL_NAN);
1781 /* if (finite(a) && finite(b)) { */
1786 /* return longBitsToDouble(DBL_POSINF); */
1787 /* else if (a < 0) */
1788 /* return longBitsToDouble(DBL_NEGINF); */
1792 /* keep compiler happy */
1797 double builtin_drem(double a, double b)
1803 double builtin_dneg(double a)
1805 if (isnan(a)) return a;
1807 if (finite(a)) return -a;
1808 else return copysign(a, -copysign(1.0, a));
1813 s4 builtin_dcmpl(double a, double b)
1815 if (isnan(a)) return -1;
1816 if (isnan(b)) return -1;
1817 if (!finite(a) || !finite(b)) {
1818 a = finite(a) ? 0 : copysign(1.0, a);
1819 b = finite(b) ? 0 : copysign(1.0, b);
1821 if (a > b) return 1;
1822 if (a == b) return 0;
1827 s4 builtin_dcmpg(double a, double b)
1829 if (isnan(a)) return 1;
1830 if (isnan(b)) return 1;
1831 if (!finite(a) || !finite(b)) {
1832 a = finite(a) ? 0 : copysign(1.0, a);
1833 b = finite(b) ? 0 : copysign(1.0, b);
1835 if (a > b) return 1;
1836 if (a == b) return 0;
1841 /*********************** Conversion operations ****************************/
1843 s8 builtin_i2l(s4 i)
1856 float builtin_i2f(s4 a)
1858 float f = (float) a;
1863 double builtin_i2d(s4 a)
1865 double d = (double) a;
1870 s4 builtin_l2i(s8 l)
1880 float builtin_l2f(s8 a)
1883 float f = (float) a;
1891 double builtin_l2d(s8 a)
1894 double d = (double) a;
1902 s4 builtin_f2i(float a)
1905 return builtin_d2i((double) a);
1914 if (a < (-2147483648))
1915 return (-2147483648);
1918 f = copysignf((float) 1.0, a);
1921 return (-2147483648); */
1925 s8 builtin_f2l(float a)
1928 return builtin_d2l((double) a);
1933 if (a > 9223372036854775807L)
1934 return 9223372036854775807L;
1935 if (a < (-9223372036854775808L))
1936 return (-9223372036854775808L);
1941 f = copysignf((float) 1.0, a);
1943 return 9223372036854775807L;
1944 return (-9223372036854775808L); */
1948 double builtin_f2d(float a)
1950 if (finitef(a)) return (double) a;
1953 return longBitsToDouble(DBL_NAN);
1955 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1960 s4 builtin_d2i(double a)
1965 if (a >= 2147483647)
1967 if (a <= (-2147483647-1))
1968 return (-2147483647-1);
1973 d = copysign(1.0, a);
1976 return (-2147483647-1);
1980 s8 builtin_d2l(double a)
1985 if (a >= 9223372036854775807LL)
1986 return 9223372036854775807LL;
1987 if (a <= (-9223372036854775807LL-1))
1988 return (-9223372036854775807LL-1);
1993 d = copysign(1.0, a);
1995 return 9223372036854775807LL;
1996 return (-9223372036854775807LL-1);
2000 float builtin_d2f(double a)
2006 return intBitsToFloat(FLT_NAN);
2008 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2013 /* used to convert FLT_xxx defines into float values */
2015 inline float intBitsToFloat(s4 i)
2024 /* used to convert DBL_xxx defines into double values */
2026 inline float longBitsToDouble(s8 l)
2035 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2037 return (java_arrayheader *)
2038 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2044 panic("Internal error: builtin_dummy called (native function is missing)");
2045 return 0; /* for the compiler */
2049 /* builtin_asm_get_exceptionptrptr *********************************************
2051 this is a wrapper for calls from asmpart
2053 *******************************************************************************/
2055 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2056 java_objectheader **builtin_asm_get_exceptionptrptr()
2058 return builtin_get_exceptionptrptr();
2063 methodinfo *builtin_asm_get_threadrootmethod()
2065 return *threadrootmethod;
2069 inline void* builtin_asm_get_stackframeinfo()
2071 /*log_text("builtin_asm_get_stackframeinfo()");*/
2072 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2073 return &THREADINFO->_stackframeinfo;
2075 #if defined(__GNUC__)
2076 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2078 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2082 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2083 /* stacktraceelement *el;*/
2086 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2087 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2089 *el=MNEW(stacktraceelement,s+1); /*GC*/
2091 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2093 #if defined(__GNUC__)
2094 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2096 (*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 */
2101 * These are local overrides for various environment variables in Emacs.
2102 * Please do not remove this and leave it at the end of the file, where
2103 * Emacs will automagically detect them.
2104 * ---------------------------------------------------------------------
2107 * indent-tabs-mode: t