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 2247 2005-04-06 16:05:32Z 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"},
259 /* assembler code patching functions */
261 { 255, asm_builtin_new , ICMD_BUILTIN1, TYPE_ADR , TYPE_VOID , TYPE_VOID , TYPE_ADR , 0, 0, "new (calling asm_builtin_new)" },
264 /* this record marks the end of the list */
266 { 0, NULL, 0, 0, 0, 0, 0, 0, 0, "<END>" }
270 #if defined(USEBUILTINTABLE)
272 static int stdopcompare(const void *a, const void *b)
274 builtin_descriptor *o1 = (builtin_descriptor *) a;
275 builtin_descriptor *o2 = (builtin_descriptor *) b;
276 if (!o1->supported && o2->supported)
278 if (o1->supported && !o2->supported)
280 return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
284 void sort_builtintable(void)
289 while (builtin_desc[len].opcode != 255) len++;
290 qsort(builtin_desc, len, sizeof(builtin_descriptor), stdopcompare);
292 for (--len; len>=0 && builtin_desc[len].supported; len--);
293 builtintablelen = ++len;
297 builtin_descriptor *find_builtin(int icmd)
299 builtin_descriptor *first = builtin_desc;
300 builtin_descriptor *last = builtin_desc + builtintablelen;
301 int len = last - first;
303 builtin_descriptor *middle;
307 middle = first + half;
308 if (middle->opcode < icmd) {
314 return first != last ? first : NULL;
317 #endif /* defined(USEBUILTINTABLE) */
320 /*****************************************************************************
322 *****************************************************************************/
326 /*************** internal function: builtin_isanysubclass *********************
328 Checks a subclass relation between two classes. Implemented interfaces
329 are interpreted as super classes.
330 Return value: 1 ... sub is subclass of super
333 *****************************************************************************/
334 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
337 castinfo classvalues;
342 if (super->flags & ACC_INTERFACE)
343 return (sub->vftbl->interfacetablelength > super->index) &&
344 (sub->vftbl->interfacetable[-super->index] != NULL);
346 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
348 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
349 (u4) classvalues.super_diffval;
355 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
359 castinfo classvalues;
364 asm_getclassvalues_atomic(super, sub, &classvalues);
366 if ((base = classvalues.super_baseval) <= 0)
367 /* super is an interface */
368 res = (sub->interfacetablelength > -base) &&
369 (sub->interfacetable[base] != NULL);
371 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
372 <= (u4) classvalues.super_diffval;
378 /****************** function: builtin_instanceof *****************************
380 Checks if an object is an instance of some given class (or subclass of
381 that class). If class is an interface, checks if the interface is
383 Return value: 1 ... obj is an instance of class or implements the interface
384 0 ... otherwise or if obj == NULL
386 *****************************************************************************/
388 /* XXX should use vftbl */
389 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
392 log_text ("builtin_instanceof called");
397 return builtin_isanysubclass(obj->vftbl->class, class);
402 /**************** function: builtin_checkcast *******************************
404 The same as builtin_instanceof except that 1 is returned when
407 ****************************************************************************/
409 /* XXX should use vftbl */
410 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
413 log_text("builtin_checkcast called");
418 if (builtin_isanysubclass(obj->vftbl->class, class))
422 printf("#### checkcast failed ");
423 utf_display(obj->vftbl->class->name);
425 utf_display(class->name);
433 /*********** internal function: builtin_descriptorscompatible ******************
435 Checks if two array type descriptors are assignment compatible
436 Return value: 1 ... target = desc is possible
439 ******************************************************************************/
441 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
443 if (desc==target) return 1;
444 if (desc->arraytype != target->arraytype) return 0;
445 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
447 /* {both arrays are arrays of references} */
448 if (desc->dimension == target->dimension) {
449 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
450 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
451 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
453 if (desc->dimension < target->dimension) return 0;
455 /* {desc has higher dimension than target} */
456 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
460 /******************** function: builtin_checkarraycast ***********************
462 Checks if an object is really a subtype of the requested array type.
463 The object has to be an array to begin with. For simple arrays (int, short,
464 double, etc.) the types have to match exactly.
465 For arrays of objects, the type of elements in the array has to be a
466 subtype (or the same type) of the requested element type. For arrays of
467 arrays (which in turn can again be arrays of arrays), the types at the
468 lowest level have to satisfy the corresponding sub class relation.
470 Return value: 1 ... cast is possible
473 ATTENTION: a cast with a NULL pointer is always possible.
475 *****************************************************************************/
477 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
479 arraydescriptor *desc;
482 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
484 return builtin_descriptorscompatible(desc, target->arraydesc);
488 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
491 return builtin_checkarraycast(obj, target);
495 /************************** exception functions *******************************
497 ******************************************************************************/
499 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
502 char logtext[MAXLOGTEXT];
503 sprintf(logtext, "Builtin exception thrown: ");
506 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
508 utf_sprint_classname(logtext + strlen(logtext),
509 xptr->vftbl->class->name);
511 if (t->detailMessage) {
514 buf = javastring_tochar((java_objectheader *) t->detailMessage);
515 sprintf(logtext + strlen(logtext), ": %s", buf);
516 MFREE(buf, char, strlen(buf));
520 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
526 *exceptionptr = xptr;
533 /******************* function: builtin_canstore *******************************
535 Checks, if an object can be stored in an array.
536 Return value: 1 ... possible
539 ******************************************************************************/
541 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
543 arraydescriptor *desc;
544 arraydescriptor *valuedesc;
545 vftbl_t *componentvftbl;
549 castinfo classvalues;
553 /* The following is guaranteed (by verifier checks):
555 * *) a->...vftbl->arraydesc != NULL
556 * *) a->...vftbl->arraydesc->componentvftbl != NULL
557 * *) o->vftbl is not an interface vftbl
560 desc = a->header.objheader.vftbl->arraydesc;
561 componentvftbl = desc->componentvftbl;
562 valuevftbl = o->vftbl;
564 if ((dim_m1 = desc->dimension - 1) == 0) {
567 /* {a is a one-dimensional array} */
568 /* {a is an array of references} */
570 if (valuevftbl == componentvftbl)
573 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
575 if ((base = classvalues.super_baseval) <= 0)
576 /* an array of interface references */
577 return (valuevftbl->interfacetablelength > -base &&
578 valuevftbl->interfacetable[base] != NULL);
580 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
581 <= (unsigned) classvalues.super_diffval;
585 /* {a has dimension > 1} */
586 /* {componentvftbl->arraydesc != NULL} */
588 /* check if o is an array */
589 if ((valuedesc = valuevftbl->arraydesc) == NULL)
591 /* {o is an array} */
593 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
597 /* This is an optimized version where a is guaranteed to be one-dimensional */
598 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
600 arraydescriptor *desc;
601 vftbl_t *elementvftbl;
605 castinfo classvalues;
609 /* The following is guaranteed (by verifier checks):
611 * *) a->...vftbl->arraydesc != NULL
612 * *) a->...vftbl->arraydesc->elementvftbl != NULL
613 * *) a->...vftbl->arraydesc->dimension == 1
614 * *) o->vftbl is not an interface vftbl
617 desc = a->header.objheader.vftbl->arraydesc;
618 elementvftbl = desc->elementvftbl;
619 valuevftbl = o->vftbl;
621 /* {a is a one-dimensional array} */
623 if (valuevftbl == elementvftbl)
626 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
628 if ((base = classvalues.super_baseval) <= 0)
629 /* an array of interface references */
630 return (valuevftbl->interfacetablelength > -base &&
631 valuevftbl->interfacetable[base] != NULL);
633 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
634 <= (unsigned) classvalues.super_diffval;
640 /* This is an optimized version where a is guaranteed to be a
641 * one-dimensional array of a class type */
642 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
644 vftbl_t *elementvftbl;
647 castinfo classvalues;
651 /* The following is guaranteed (by verifier checks):
653 * *) a->...vftbl->arraydesc != NULL
654 * *) a->...vftbl->arraydesc->elementvftbl != NULL
655 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
656 * *) a->...vftbl->arraydesc->dimension == 1
657 * *) o->vftbl is not an interface vftbl
660 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
661 valuevftbl = o->vftbl;
663 /* {a is a one-dimensional array} */
665 if (valuevftbl == elementvftbl)
668 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
670 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
671 <= (unsigned) classvalues.super_diffval;
677 /* builtin_new *****************************************************************
679 Creates a new instance of class c on the heap.
681 Return value: pointer to the object or NULL if no memory is
684 *******************************************************************************/
686 java_objectheader *builtin_new(classinfo *c)
688 java_objectheader *o;
690 /* is the class loaded */
691 /*utf_fprint(stderr,c->name);fprintf(stderr,"\n");*/
694 /* is the class linked */
699 if (!c->initialized) {
701 log_message_class("Initialize class (from builtin_new): ", c);
703 if (!initialize_class(c))
707 o = heap_allocate(c->instancesize, true, c->finalizer);
712 MSET(o, 0, u1, c->instancesize);
716 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
724 /* builtin_newarray ************************************************************
726 Creates an array with the given vftbl on the heap.
728 Return value: pointer to the array or NULL if no memory is available
730 CAUTION: The given vftbl must be the vftbl of the *array* class,
731 not of the element class.
733 *******************************************************************************/
735 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
738 arraydescriptor *desc;
743 desc = arrayvftbl->arraydesc;
744 dataoffset = desc->dataoffset;
745 componentsize = desc->componentsize;
748 *exceptionptr = new_negativearraysizeexception();
752 actualsize = dataoffset + size * componentsize;
754 if (((u4) actualsize) < ((u4) size)) { /* overflow */
755 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
759 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
764 MSET(a, 0, u1, actualsize);
766 a->objheader.vftbl = arrayvftbl;
768 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
769 initObjectLock(&a->objheader);
778 /********************** Function: builtin_anewarray *************************
780 Creates an array of references to the given class type on the heap.
782 Return value: pointer to the array or NULL if no memory is available
784 XXX This function does not do The Right Thing, because it uses a
785 classinfo pointer at runtime. builtin_newarray should be used
788 *****************************************************************************/
790 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
794 /* is class loaded */
795 assert(component->loaded);
797 /* is class linked */
798 if (!component->linked)
799 if (!link_class(component))
802 c = class_array_of(component,true);
805 return (java_objectarray *) builtin_newarray(size, c->vftbl);
809 /******************** Function: builtin_newarray_int ***********************
811 Creates an array of 32 bit Integers on the heap.
813 Return value: pointer to the array or NULL if no memory is available
815 *****************************************************************************/
817 java_intarray *builtin_newarray_int(s4 size)
819 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
823 /******************** Function: builtin_newarray_long ***********************
825 Creates an array of 64 bit Integers on the heap.
827 Return value: pointer to the array or NULL if no memory is available
829 *****************************************************************************/
831 java_longarray *builtin_newarray_long(s4 size)
833 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
837 /******************** function: builtin_newarray_float ***********************
839 Creates an array of 32 bit IEEE floats on the heap.
841 Return value: pointer to the array or NULL if no memory is available
843 *****************************************************************************/
845 java_floatarray *builtin_newarray_float(s4 size)
847 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
851 /******************** function: builtin_newarray_double ***********************
853 Creates an array of 64 bit IEEE floats on the heap.
855 Return value: pointer to the array or NULL if no memory is available
857 *****************************************************************************/
859 java_doublearray *builtin_newarray_double(s4 size)
861 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
865 /******************** function: builtin_newarray_byte ***********************
867 Creates an array of 8 bit Integers on the heap.
869 Return value: pointer to the array or NULL if no memory is available
871 *****************************************************************************/
873 java_bytearray *builtin_newarray_byte(s4 size)
875 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
879 /******************** function: builtin_newarray_char ************************
881 Creates an array of characters on the heap.
883 Return value: pointer to the array or NULL if no memory is available
885 *****************************************************************************/
887 java_chararray *builtin_newarray_char(s4 size)
889 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
893 /******************** function: builtin_newarray_short ***********************
895 Creates an array of 16 bit Integers on the heap.
897 Return value: pointer to the array or NULL if no memory is available
899 *****************************************************************************/
901 java_shortarray *builtin_newarray_short(s4 size)
903 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
907 /******************** function: builtin_newarray_boolean ************************
909 Creates an array of bytes on the heap. The array is designated as an array
910 of booleans (important for casts)
912 Return value: pointer to the array or NULL if no memory is available
914 *****************************************************************************/
916 java_booleanarray *builtin_newarray_boolean(s4 size)
918 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
922 /**************** function: builtin_nmultianewarray ***************************
924 Creates a multi-dimensional array on the heap. The dimensions are passed in
928 n............number of dimensions to create
929 arrayvftbl...vftbl of the array class
930 dims.........array containing the size of each dimension to create
932 Return value: pointer to the array or NULL if no memory is available
934 ******************************************************************************/
936 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
937 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
941 vftbl_t *componentvftbl;
943 /* utf_display(arrayclass->name); */
945 /* class_load(arrayclass); */
946 /* class_link(arrayclass); */
948 /* create this dimension */
950 a = builtin_newarray(size, arrayvftbl);
951 /* a = builtin_newarray(size, arrayclass->vftbl); */
956 /* if this is the last dimension return */
960 /* get the vftbl of the components to create */
961 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
962 /* component = arrayclass->vftbl->arraydesc; */
964 /* The verifier guarantees this. */
965 /* if (!componentvftbl) */
966 /* panic ("multianewarray with too many dimensions"); */
968 /* create the component arrays */
969 for (i = 0; i < size; i++) {
970 java_arrayheader *ea =
971 builtin_nmultianewarray(n, componentvftbl, dims + 1);
976 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
983 /*****************************************************************************
986 Various functions for printing a message at method entry or exit (for
989 *****************************************************************************/
993 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1003 log_text("WARNING: unmatched methodindent--");
1005 if (opt_verbose || runverbose || verboseexception) {
1007 printf("Exception ");
1008 utf_display_classname(xptr->vftbl->class->name);
1011 printf("Some Throwable");
1013 printf(" thrown in ");
1016 utf_display_classname(m->class->name);
1018 utf_display(m->name);
1019 if (m->flags & ACC_SYNCHRONIZED) {
1026 if (m->flags & ACC_NATIVE) {
1028 #if POINTERSIZE == 8
1029 printf(")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1031 printf(")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1035 #if POINTERSIZE == 8
1036 printf(")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1038 printf(")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1040 if (m->class->sourcefile == NULL) {
1041 printf("<NO CLASSFILE INFORMATION>");
1044 utf_display(m->class->sourcefile);
1046 printf(":%d)\n", line);
1050 printf("call_java_method\n");
1058 #ifdef TRACE_ARGS_NUM
1059 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1060 #if TRACE_ARGS_NUM >= 6
1063 #if TRACE_ARGS_NUM == 8
1069 char logtext[MAXLOGTEXT];
1070 for (i = 0; i < methodindent; i++)
1072 if (methodindent == 0)
1073 sprintf(logtext + methodindent, "1st_call: ");
1075 sprintf(logtext + methodindent, "called: ");
1077 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1078 sprintf(logtext + strlen(logtext), ".");
1079 utf_sprint(logtext + strlen(logtext), m->name);
1080 utf_sprint(logtext + strlen(logtext), m->descriptor);
1082 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1083 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1084 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1085 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1086 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1087 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1088 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1089 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1090 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1091 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1092 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1095 sprintf(logtext + strlen(logtext), "(");
1097 switch (m->paramcount) {
1101 #if defined(__I386__) || defined(__POWERPC__)
1103 sprintf(logtext+strlen(logtext), "%llx", a0);
1107 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1111 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1115 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1119 #if TRACE_ARGS_NUM >= 6
1121 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1122 a0, a1, a2, a3, a4);
1126 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1127 a0, a1, a2, a3, a4, a5);
1129 #endif /* TRACE_ARGS_NUM >= 6 */
1131 #if TRACE_ARGS_NUM == 8
1133 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1134 a0, a1, a2, a3, a4, a5, a6);
1138 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1139 a0, a1, a2, a3, a4, a5, a6, a7);
1143 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1144 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1146 #else /* TRACE_ARGS_NUM == 8 */
1148 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1149 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1151 #endif /* TRACE_ARGS_NUM == 8 */
1152 #else /* defined(__I386__) || defined(__POWERPC__) */
1154 sprintf(logtext+strlen(logtext), "%lx", a0);
1158 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1162 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1166 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1170 #if TRACE_ARGS_NUM >= 6
1172 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1173 a0, a1, a2, a3, a4);
1177 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1178 a0, a1, a2, a3, a4, a5);
1180 #endif /* TRACE_ARGS_NUM >= 6 */
1182 #if TRACE_ARGS_NUM == 8
1184 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1185 a0, a1, a2, a3, a4, a5, a6);
1189 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1190 a0, a1, a2, a3, a4, a5, a6, a7);
1192 #endif /* TRACE_ARGS_NUM == 8 */
1195 #if TRACE_ARGS_NUM == 4
1196 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1197 a0, a1, a2, a3, m->paramcount - 4);
1199 #elif TRACE_ARGS_NUM == 6
1200 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1201 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1203 #elif TRACE_ARGS_NUM == 8
1204 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1205 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1208 #endif /* defined(__I386__) || defined(__POWERPC__) */
1211 sprintf(logtext + strlen(logtext), ")");
1219 void builtin_displaymethodstart(methodinfo *m)
1221 char logtext[MAXLOGTEXT];
1222 sprintf(logtext, " ");
1223 sprintf(logtext + methodindent, "called: ");
1224 utf_sprint(logtext + strlen(logtext), m->class->name);
1225 sprintf(logtext + strlen(logtext), ".");
1226 utf_sprint(logtext + strlen(logtext), m->name);
1227 utf_sprint(logtext + strlen(logtext), m->descriptor);
1229 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1230 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1231 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1232 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1233 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1234 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1235 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1236 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1237 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1238 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1239 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1246 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1249 char logtext[MAXLOGTEXT];
1250 for (i = 0; i < methodindent; i++)
1255 log_text("WARNING: unmatched methodindent--");
1257 sprintf(logtext + methodindent, "finished: ");
1258 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1259 sprintf(logtext + strlen(logtext), ".");
1260 utf_sprint(logtext + strlen(logtext), m->name);
1261 utf_sprint(logtext + strlen(logtext), m->descriptor);
1263 switch (m->returntype) {
1265 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1269 #if defined(__I386__) || defined(__POWERPC__)
1270 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1272 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1277 #if defined(__I386__) || defined(__POWERPC__)
1278 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1280 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1285 sprintf(logtext + strlen(logtext), "->%g", f);
1289 sprintf(logtext + strlen(logtext), "->%g", d);
1296 /****************************************************************************
1297 SYNCHRONIZATION FUNCTIONS
1298 *****************************************************************************/
1300 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1302 * Lock the mutex of an object.
1304 void internal_lock_mutex_for_object(java_objectheader *object)
1306 mutexHashEntry *entry;
1309 assert(object != 0);
1311 hashValue = MUTEX_HASH_VALUE(object);
1312 entry = &mutexHashTable[hashValue];
1314 if (entry->object != 0) {
1315 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1317 entry->mutex.holder = 0;
1318 entry->mutex.count = 0;
1319 entry->mutex.muxWaiters = 0;
1322 while (entry->next != 0 && entry->object != object)
1323 entry = entry->next;
1325 if (entry->object != object) {
1326 entry->next = firstFreeOverflowEntry;
1327 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1329 entry = entry->next;
1332 assert(entry->conditionCount == 0);
1337 entry->mutex.holder = 0;
1338 entry->mutex.count = 0;
1339 entry->mutex.muxWaiters = 0;
1342 if (entry->object == 0)
1343 entry->object = object;
1345 internal_lock_mutex(&entry->mutex);
1350 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1352 * Unlocks the mutex of an object.
1354 void internal_unlock_mutex_for_object (java_objectheader *object)
1357 mutexHashEntry *entry;
1359 hashValue = MUTEX_HASH_VALUE(object);
1360 entry = &mutexHashTable[hashValue];
1362 if (entry->object == object) {
1363 internal_unlock_mutex(&entry->mutex);
1366 while (entry->next != 0 && entry->next->object != object)
1367 entry = entry->next;
1369 assert(entry->next != 0);
1371 internal_unlock_mutex(&entry->next->mutex);
1373 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1374 mutexHashEntry *unlinked = entry->next;
1376 entry->next = unlinked->next;
1377 unlinked->next = firstFreeOverflowEntry;
1378 firstFreeOverflowEntry = unlinked;
1385 #if defined(USE_THREADS)
1386 void builtin_monitorenter(java_objectheader *o)
1388 #if !defined(NATIVE_THREADS)
1393 hashValue = MUTEX_HASH_VALUE(o);
1394 if (mutexHashTable[hashValue].object == o
1395 && mutexHashTable[hashValue].mutex.holder == currentThread)
1396 ++mutexHashTable[hashValue].mutex.count;
1398 internal_lock_mutex_for_object(o);
1402 monitorEnter((threadobject *) THREADOBJECT, o);
1408 #if defined(USE_THREADS)
1410 * Locks the class object - needed for static synchronized methods.
1411 * The use_class_as_object call is needed in order to circumvent a
1412 * possible deadlock with builtin_monitorenter called by another
1413 * thread calling use_class_as_object.
1415 void builtin_staticmonitorenter(classinfo *c)
1417 use_class_as_object(c);
1418 builtin_monitorenter(&c->header);
1423 #if defined(USE_THREADS)
1424 void *builtin_monitorexit(java_objectheader *o)
1426 #if !defined(NATIVE_THREADS)
1431 hashValue = MUTEX_HASH_VALUE(o);
1432 if (mutexHashTable[hashValue].object == o) {
1433 if (mutexHashTable[hashValue].mutex.count == 1
1434 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1435 internal_unlock_mutex_for_object(o);
1437 --mutexHashTable[hashValue].mutex.count;
1440 internal_unlock_mutex_for_object(o);
1445 monitorExit((threadobject *) THREADOBJECT, o);
1452 /*****************************************************************************
1453 MISCELLANEOUS HELPER FUNCTIONS
1454 *****************************************************************************/
1458 /*********** Functions for integer divisions *****************************
1460 On some systems (eg. DEC ALPHA), integer division is not supported by the
1461 CPU. These helper functions implement the missing functionality.
1463 ******************************************************************************/
1465 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1466 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1469 /************** Functions for long arithmetics *******************************
1471 On systems where 64 bit Integers are not supported by the CPU, these
1472 functions are needed.
1474 ******************************************************************************/
1477 s8 builtin_ladd(s8 a, s8 b)
1482 return builtin_i2l(0);
1486 s8 builtin_lsub(s8 a, s8 b)
1491 return builtin_i2l(0);
1495 s8 builtin_lmul(s8 a, s8 b)
1500 return builtin_i2l(0);
1504 s8 builtin_ldiv(s8 a, s8 b)
1509 return builtin_i2l(0);
1513 s8 builtin_lrem(s8 a, s8 b)
1518 return builtin_i2l(0);
1522 s8 builtin_lshl(s8 a, s4 b)
1525 return a << (b & 63);
1527 return builtin_i2l(0);
1531 s8 builtin_lshr(s8 a, s4 b)
1534 return a >> (b & 63);
1536 return builtin_i2l(0);
1540 s8 builtin_lushr(s8 a, s4 b)
1543 return ((u8) a) >> (b & 63);
1545 return builtin_i2l(0);
1549 s8 builtin_land(s8 a, s8 b)
1554 return builtin_i2l(0);
1558 s8 builtin_lor(s8 a, s8 b)
1563 return builtin_i2l(0);
1567 s8 builtin_lxor(s8 a, s8 b)
1572 return builtin_i2l(0);
1576 s8 builtin_lneg(s8 a)
1581 return builtin_i2l(0);
1585 s4 builtin_lcmp(s8 a, s8 b)
1588 if (a < b) return -1;
1589 if (a > b) return 1;
1600 /*********** Functions for floating point operations *************************/
1602 float builtin_fadd(float a, float b)
1604 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1605 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1616 if (copysignf(1.0, a) == copysignf(1.0, b))
1619 return intBitsToFloat(FLT_NAN);
1625 float builtin_fsub(float a, float b)
1627 return builtin_fadd(a, builtin_fneg(b));
1631 float builtin_fmul(float a, float b)
1633 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1634 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1636 if (finitef(b)) return a * b;
1638 if (a == 0) return intBitsToFloat(FLT_NAN);
1639 else return copysignf(b, copysignf(1.0, b)*a);
1644 if (b == 0) return intBitsToFloat(FLT_NAN);
1645 else return copysignf(a, copysignf(1.0, a)*b);
1648 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1654 float builtin_fdiv(float a, float b)
1656 if (finitef(a) && finitef(b)) {
1661 return intBitsToFloat(FLT_POSINF);
1663 return intBitsToFloat(FLT_NEGINF);
1666 return intBitsToFloat(FLT_NAN);
1670 float builtin_frem(float a, float b)
1676 float builtin_fneg(float a)
1678 if (isnanf(a)) return a;
1680 if (finitef(a)) return -a;
1681 else return copysignf(a, -copysignf(1.0, a));
1686 s4 builtin_fcmpl(float a, float b)
1688 if (isnanf(a)) return -1;
1689 if (isnanf(b)) return -1;
1690 if (!finitef(a) || !finitef(b)) {
1691 a = finitef(a) ? 0 : copysignf(1.0, a);
1692 b = finitef(b) ? 0 : copysignf(1.0, b);
1694 if (a > b) return 1;
1695 if (a == b) return 0;
1700 s4 builtin_fcmpg(float a, float b)
1702 if (isnanf(a)) return 1;
1703 if (isnanf(b)) return 1;
1704 if (!finitef(a) || !finitef(b)) {
1705 a = finitef(a) ? 0 : copysignf(1.0, a);
1706 b = finitef(b) ? 0 : copysignf(1.0, b);
1708 if (a > b) return 1;
1709 if (a == b) return 0;
1715 /************************* Functions for doubles ****************************/
1717 double builtin_dadd(double a, double b)
1719 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1720 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1722 if (finite(b)) return a + b;
1726 if (finite(b)) return a;
1728 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1729 else return longBitsToDouble(DBL_NAN);
1735 double builtin_dsub(double a, double b)
1737 return builtin_dadd(a, builtin_dneg(b));
1741 double builtin_dmul(double a, double b)
1743 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1744 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1746 if (finite(b)) return a * b;
1748 if (a == 0) return longBitsToDouble(DBL_NAN);
1749 else return copysign(b, copysign(1.0, b) * a);
1754 if (b == 0) return longBitsToDouble(DBL_NAN);
1755 else return copysign(a, copysign(1.0, a) * b);
1758 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1764 double builtin_ddiv(double a, double b)
1772 return longBitsToDouble(DBL_NAN);
1774 return copysign(0.0, b);
1780 return longBitsToDouble(DBL_POSINF);
1782 return longBitsToDouble(DBL_NEGINF);
1785 return longBitsToDouble(DBL_NAN);
1788 /* if (finite(a) && finite(b)) { */
1793 /* return longBitsToDouble(DBL_POSINF); */
1794 /* else if (a < 0) */
1795 /* return longBitsToDouble(DBL_NEGINF); */
1799 /* keep compiler happy */
1804 double builtin_drem(double a, double b)
1810 double builtin_dneg(double a)
1812 if (isnan(a)) return a;
1814 if (finite(a)) return -a;
1815 else return copysign(a, -copysign(1.0, a));
1820 s4 builtin_dcmpl(double a, double b)
1822 if (isnan(a)) return -1;
1823 if (isnan(b)) return -1;
1824 if (!finite(a) || !finite(b)) {
1825 a = finite(a) ? 0 : copysign(1.0, a);
1826 b = finite(b) ? 0 : copysign(1.0, b);
1828 if (a > b) return 1;
1829 if (a == b) return 0;
1834 s4 builtin_dcmpg(double a, double b)
1836 if (isnan(a)) return 1;
1837 if (isnan(b)) return 1;
1838 if (!finite(a) || !finite(b)) {
1839 a = finite(a) ? 0 : copysign(1.0, a);
1840 b = finite(b) ? 0 : copysign(1.0, b);
1842 if (a > b) return 1;
1843 if (a == b) return 0;
1848 /*********************** Conversion operations ****************************/
1850 s8 builtin_i2l(s4 i)
1863 float builtin_i2f(s4 a)
1865 float f = (float) a;
1870 double builtin_i2d(s4 a)
1872 double d = (double) a;
1877 s4 builtin_l2i(s8 l)
1887 float builtin_l2f(s8 a)
1890 float f = (float) a;
1898 double builtin_l2d(s8 a)
1901 double d = (double) a;
1909 s4 builtin_f2i(float a)
1912 return builtin_d2i((double) a);
1921 if (a < (-2147483648))
1922 return (-2147483648);
1925 f = copysignf((float) 1.0, a);
1928 return (-2147483648); */
1932 s8 builtin_f2l(float a)
1935 return builtin_d2l((double) a);
1940 if (a > 9223372036854775807L)
1941 return 9223372036854775807L;
1942 if (a < (-9223372036854775808L))
1943 return (-9223372036854775808L);
1948 f = copysignf((float) 1.0, a);
1950 return 9223372036854775807L;
1951 return (-9223372036854775808L); */
1955 double builtin_f2d(float a)
1957 if (finitef(a)) return (double) a;
1960 return longBitsToDouble(DBL_NAN);
1962 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1967 s4 builtin_d2i(double a)
1972 if (a >= 2147483647)
1974 if (a <= (-2147483647-1))
1975 return (-2147483647-1);
1980 d = copysign(1.0, a);
1983 return (-2147483647-1);
1987 s8 builtin_d2l(double a)
1992 if (a >= 9223372036854775807LL)
1993 return 9223372036854775807LL;
1994 if (a <= (-9223372036854775807LL-1))
1995 return (-9223372036854775807LL-1);
2000 d = copysign(1.0, a);
2002 return 9223372036854775807LL;
2003 return (-9223372036854775807LL-1);
2007 float builtin_d2f(double a)
2013 return intBitsToFloat(FLT_NAN);
2015 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2020 /* used to convert FLT_xxx defines into float values */
2022 inline float intBitsToFloat(s4 i)
2031 /* used to convert DBL_xxx defines into double values */
2033 inline float longBitsToDouble(s8 l)
2042 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2044 return (java_arrayheader *)
2045 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2051 panic("Internal error: builtin_dummy called (native function is missing)");
2052 return 0; /* for the compiler */
2056 /* builtin_asm_get_exceptionptrptr *********************************************
2058 this is a wrapper for calls from asmpart
2060 *******************************************************************************/
2062 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2063 java_objectheader **builtin_asm_get_exceptionptrptr()
2065 return builtin_get_exceptionptrptr();
2070 methodinfo *builtin_asm_get_threadrootmethod()
2072 return *threadrootmethod;
2076 inline void* builtin_asm_get_stackframeinfo()
2078 /*log_text("builtin_asm_get_stackframeinfo()");*/
2079 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2080 return &THREADINFO->_stackframeinfo;
2082 #if defined(__GNUC__)
2083 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2085 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2089 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2090 /* stacktraceelement *el;*/
2093 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2094 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2096 *el=MNEW(stacktraceelement,s+1); /*GC*/
2098 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2100 #if defined(__GNUC__)
2101 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2103 (*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 */
2108 * These are local overrides for various environment variables in Emacs.
2109 * Please do not remove this and leave it at the end of the file, where
2110 * Emacs will automagically detect them.
2111 * ---------------------------------------------------------------------
2114 * indent-tabs-mode: t