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 2193 2005-04-02 19:33:43Z edwin $
52 #include "mm/memory.h"
53 #include "native/native.h"
54 #include "native/include/java_lang_Cloneable.h"
55 #include "native/include/java_lang_VMObject.h"
57 #if defined(USE_THREADS)
58 # if defined(NATIVE_THREADS)
59 # include "threads/native/threads.h"
61 # include "threads/green/threads.h"
62 # include "threads/green/locks.h"
66 #include "toolbox/logging.h"
67 #include "vm/builtin.h"
68 #include "vm/exceptions.h"
69 #include "vm/global.h"
70 #include "vm/loader.h"
71 #include "vm/options.h"
72 #include "vm/stringlocal.h"
73 #include "vm/tables.h"
74 #include "vm/jit/asmpart.h"
77 #undef DEBUG /*define DEBUG 1*/
79 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
80 THREADSPECIFIC void *_thread_nativestackframeinfo = NULL;
83 #if defined(USEBUILTINTABLE)
86 stdopdescriptor builtintable[] = {
87 { ICMD_LCMP, TYPE_LONG, TYPE_LONG, TYPE_INT, ICMD_BUILTIN2,
88 (functionptr) builtin_lcmp , SUPPORT_LONG && SUPPORT_LONG_CMP, false },
89 { ICMD_LAND, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
90 (functionptr) builtin_land , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
91 { ICMD_LOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
92 (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
93 { ICMD_LXOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
94 (functionptr) builtin_lxor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
95 { ICMD_LSHL, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
96 (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
97 { ICMD_LSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
98 (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
99 { ICMD_LUSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
100 (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
101 { ICMD_LADD, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
102 (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
103 { ICMD_LSUB, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
104 (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
105 { ICMD_LNEG, TYPE_LONG, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
106 (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, true },
107 { ICMD_LMUL, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
108 (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MUL, false },
109 { ICMD_I2F, TYPE_INT, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
110 (functionptr) builtin_i2f, SUPPORT_FLOAT && SUPPORT_IFCVT, true },
111 { ICMD_I2D, TYPE_INT, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
112 (functionptr) builtin_i2d, SUPPORT_DOUBLE && SUPPORT_IFCVT, true },
113 { ICMD_L2F, TYPE_LONG, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
114 (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
115 { ICMD_L2D, TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
116 (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
117 { ICMD_F2L, TYPE_FLOAT, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
118 (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
119 { ICMD_D2L, TYPE_DOUBLE, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
120 (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
121 { ICMD_F2I, TYPE_FLOAT, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
122 (functionptr) builtin_f2i, SUPPORT_FLOAT && SUPPORT_FICVT, true },
123 { ICMD_D2I, TYPE_DOUBLE, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
124 (functionptr) builtin_d2i, SUPPORT_DOUBLE && SUPPORT_FICVT, true },
125 { 255, 0, 0, 0, 0, NULL, true, false },
130 static int builtintablelen;
132 #endif /* USEBUILTINTABLE */
135 /*****************************************************************************
136 TABLE OF BUILTIN FUNCTIONS
138 This table lists the builtin functions which are used inside
141 The first part of the table (up to the 255-marker) lists the
142 opcodes which are automatically replaced in stack.c.
144 The second part lists the builtin functions which are "manually"
145 used for BUILTIN* opcodes in parse.c and stack.c.
147 *****************************************************************************/
149 builtin_descriptor builtin_desc[] = {
150 #if defined(USEBUILTINTABLE)
151 {ICMD_LCMP , BUILTIN_lcmp ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_INT ,
152 SUPPORT_LONG && SUPPORT_LONG_CMP,false,"lcmp"},
154 {ICMD_LAND , BUILTIN_land ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
155 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"land"},
156 {ICMD_LOR , BUILTIN_lor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
157 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lor"},
158 {ICMD_LXOR , BUILTIN_lxor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
159 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lxor"},
161 {ICMD_LSHL , BUILTIN_lshl ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
162 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshl"},
163 {ICMD_LSHR , BUILTIN_lshr ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
164 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshr"},
165 {ICMD_LUSHR, BUILTIN_lushr,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
166 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lushr"},
168 {ICMD_LADD , BUILTIN_ladd ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
169 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"ladd"},
170 {ICMD_LSUB , BUILTIN_lsub ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
171 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lsub"},
172 {ICMD_LNEG , BUILTIN_lneg ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
173 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lneg"},
174 {ICMD_LMUL , BUILTIN_lmul ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
175 SUPPORT_LONG && SUPPORT_LONG_MUL,false,"lmul"},
177 {ICMD_I2F , BUILTIN_i2f ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
178 SUPPORT_FLOAT && SUPPORT_IFCVT,true ,"i2f"},
179 {ICMD_I2D , BUILTIN_i2d ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
180 SUPPORT_DOUBLE && SUPPORT_IFCVT,true ,"i2d"},
181 {ICMD_L2F , BUILTIN_l2f ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
182 SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT,true ,"l2f"},
183 {ICMD_L2D , BUILTIN_l2d ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
184 SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT,true ,"l2d"},
185 {ICMD_F2L , BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
186 SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"f2l"},
187 {ICMD_D2L , BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
188 SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"d2l"},
189 {ICMD_F2I , BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
190 SUPPORT_FLOAT && SUPPORT_FICVT,true ,"f2i"},
191 {ICMD_D2I , BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
192 SUPPORT_DOUBLE && SUPPORT_FICVT,true ,"d2i"},
194 { ICMD_FADD , BUILTIN_fadd , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fadd" },
195 { ICMD_FSUB , BUILTIN_fsub , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fsub" },
196 { ICMD_FMUL , BUILTIN_fmul , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fmul" },
197 { ICMD_FDIV , BUILTIN_fdiv , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fdiv" },
198 { ICMD_FNEG , BUILTIN_fneg , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fneg" },
199 { ICMD_FCMPL, BUILTIN_fcmpl , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpl" },
200 { ICMD_FCMPG, BUILTIN_fcmpg , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpg" },
202 { ICMD_DADD , BUILTIN_dadd , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dadd" },
203 { ICMD_DSUB , BUILTIN_dsub , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dsub" },
204 { ICMD_DMUL , BUILTIN_dmul , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dmul" },
205 { ICMD_DDIV , BUILTIN_ddiv , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "ddiv" },
206 { ICMD_DNEG , BUILTIN_dneg , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dneg" },
207 { ICMD_DCMPL, BUILTIN_dcmpl , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpl" },
208 { ICMD_DCMPG, BUILTIN_dcmpg , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpg" },
210 { ICMD_F2D, BUILTIN_f2d , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "f2d" },
211 { ICMD_D2F, BUILTIN_d2f , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "d2f" },
214 /* this record marks the end of the automatically replaced opcodes */
215 {255,NULL,0,0,0,0,0,0,0,"<INVALID>"},
217 /* the following functions are not replaced automatically */
219 #if defined(__ALPHA__)
220 {255, BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"f2l"},
221 {255, BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"d2l"},
222 {255, BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"f2i"},
223 {255, BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"d2i"},
226 {255,BUILTIN_instanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"instanceof"},
227 {255,BUILTIN_arrayinstanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"arrayinstanceof"},
228 {255,BUILTIN_checkarraycast ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,0,0,"checkarraycast"},
229 {255,BUILTIN_aastore ,ICMD_BUILTIN3,TYPE_ADR ,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,0,0,"aastore"},
230 {255,BUILTIN_new ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"new"},
231 {255,BUILTIN_newarray ,ICMD_BUILTIN2,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray"},
232 {255,BUILTIN_newarray_boolean,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_boolean"},
233 {255,BUILTIN_newarray_char ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_char"},
234 {255,BUILTIN_newarray_float ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_float"},
235 {255,BUILTIN_newarray_double ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_double"},
236 {255,BUILTIN_newarray_byte ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_byte"},
237 {255,BUILTIN_newarray_short ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_short"},
238 {255,BUILTIN_newarray_int ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_int"},
239 {255,BUILTIN_newarray_long ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_long"},
240 {255,BUILTIN_anewarray ,ICMD_BUILTIN2,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,TYPE_ADR ,0,0,"anewarray"},
241 #if defined(USE_THREADS)
242 {255,BUILTIN_monitorenter ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorenter"},
243 {255,BUILTIN_monitorexit ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorexit"},
245 #if !SUPPORT_DIVISION
246 {255,BUILTIN_idiv ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"idiv"},
247 {255,BUILTIN_irem ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"irem"},
249 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
250 {255,BUILTIN_ldiv ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"ldiv"},
251 {255,BUILTIN_lrem ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"lrem"},
253 {255,BUILTIN_frem ,ICMD_BUILTIN2,TYPE_FLOAT ,TYPE_FLOAT ,TYPE_VOID ,TYPE_FLOAT ,0,0,"frem"},
254 {255,BUILTIN_drem ,ICMD_BUILTIN2,TYPE_DOUBLE,TYPE_DOUBLE,TYPE_VOID ,TYPE_DOUBLE,0,0,"drem"},
256 /* this record marks the end of the list */
257 { 0,NULL,0,0,0,0,0,0,0,"<END>"}
261 #if defined(USEBUILTINTABLE)
263 static int stdopcompare(const void *a, const void *b)
265 builtin_descriptor *o1 = (builtin_descriptor *) a;
266 builtin_descriptor *o2 = (builtin_descriptor *) b;
267 if (!o1->supported && o2->supported)
269 if (o1->supported && !o2->supported)
271 return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
275 void sort_builtintable(void)
280 while (builtin_desc[len].opcode != 255) len++;
281 qsort(builtin_desc, len, sizeof(builtin_descriptor), stdopcompare);
283 for (--len; len>=0 && builtin_desc[len].supported; len--);
284 builtintablelen = ++len;
288 builtin_descriptor *find_builtin(int icmd)
290 builtin_descriptor *first = builtin_desc;
291 builtin_descriptor *last = builtin_desc + builtintablelen;
292 int len = last - first;
294 builtin_descriptor *middle;
298 middle = first + half;
299 if (middle->opcode < icmd) {
305 return first != last ? first : NULL;
308 #endif /* defined(USEBUILTINTABLE) */
311 /*****************************************************************************
313 *****************************************************************************/
317 /*************** internal function: builtin_isanysubclass *********************
319 Checks a subclass relation between two classes. Implemented interfaces
320 are interpreted as super classes.
321 Return value: 1 ... sub is subclass of super
324 *****************************************************************************/
325 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
328 castinfo classvalues;
333 if (super->flags & ACC_INTERFACE)
334 return (sub->vftbl->interfacetablelength > super->index) &&
335 (sub->vftbl->interfacetable[-super->index] != NULL);
337 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
339 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
340 (u4) classvalues.super_diffval;
346 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
350 castinfo classvalues;
355 asm_getclassvalues_atomic(super, sub, &classvalues);
357 if ((base = classvalues.super_baseval) <= 0)
358 /* super is an interface */
359 res = (sub->interfacetablelength > -base) &&
360 (sub->interfacetable[base] != NULL);
362 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
363 <= (u4) classvalues.super_diffval;
369 /****************** function: builtin_instanceof *****************************
371 Checks if an object is an instance of some given class (or subclass of
372 that class). If class is an interface, checks if the interface is
374 Return value: 1 ... obj is an instance of class or implements the interface
375 0 ... otherwise or if obj == NULL
377 *****************************************************************************/
379 /* XXX should use vftbl */
380 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
383 log_text ("builtin_instanceof called");
388 return builtin_isanysubclass(obj->vftbl->class, class);
393 /**************** function: builtin_checkcast *******************************
395 The same as builtin_instanceof except that 1 is returned when
398 ****************************************************************************/
400 /* XXX should use vftbl */
401 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
404 log_text("builtin_checkcast called");
409 if (builtin_isanysubclass(obj->vftbl->class, class))
413 printf("#### checkcast failed ");
414 utf_display(obj->vftbl->class->name);
416 utf_display(class->name);
424 /*********** internal function: builtin_descriptorscompatible ******************
426 Checks if two array type descriptors are assignment compatible
427 Return value: 1 ... target = desc is possible
430 ******************************************************************************/
432 static s4 builtin_descriptorscompatible(arraydescriptor *desc,arraydescriptor *target)
434 if (desc==target) return 1;
435 if (desc->arraytype != target->arraytype) return 0;
436 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
438 /* {both arrays are arrays of references} */
439 if (desc->dimension == target->dimension) {
440 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
441 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
442 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
444 if (desc->dimension < target->dimension) return 0;
446 /* {desc has higher dimension than target} */
447 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
451 /******************** function: builtin_checkarraycast ***********************
453 Checks if an object is really a subtype of the requested array type.
454 The object has to be an array to begin with. For simple arrays (int, short,
455 double, etc.) the types have to match exactly.
456 For arrays of objects, the type of elements in the array has to be a
457 subtype (or the same type) of the requested element type. For arrays of
458 arrays (which in turn can again be arrays of arrays), the types at the
459 lowest level have to satisfy the corresponding sub class relation.
461 Return value: 1 ... cast is possible
464 ATTENTION: a cast with a NULL pointer is always possible.
466 *****************************************************************************/
468 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
470 arraydescriptor *desc;
473 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
475 return builtin_descriptorscompatible(desc, target->arraydesc);
479 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
482 return builtin_checkarraycast(obj, target);
486 /************************** exception functions *******************************
488 ******************************************************************************/
490 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
493 char logtext[MAXLOGTEXT];
494 sprintf(logtext, "Builtin exception thrown: ");
497 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
499 utf_sprint_classname(logtext + strlen(logtext),
500 xptr->vftbl->class->name);
502 if (t->detailMessage) {
505 buf = javastring_tochar((java_objectheader *) t->detailMessage);
506 sprintf(logtext + strlen(logtext), ": %s", buf);
507 MFREE(buf, char, strlen(buf));
511 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
517 *exceptionptr = xptr;
524 /******************* function: builtin_canstore *******************************
526 Checks, if an object can be stored in an array.
527 Return value: 1 ... possible
530 ******************************************************************************/
532 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
534 arraydescriptor *desc;
535 arraydescriptor *valuedesc;
536 vftbl_t *componentvftbl;
540 castinfo classvalues;
544 /* The following is guaranteed (by verifier checks):
546 * *) a->...vftbl->arraydesc != NULL
547 * *) a->...vftbl->arraydesc->componentvftbl != NULL
548 * *) o->vftbl is not an interface vftbl
551 desc = a->header.objheader.vftbl->arraydesc;
552 componentvftbl = desc->componentvftbl;
553 valuevftbl = o->vftbl;
555 if ((dim_m1 = desc->dimension - 1) == 0) {
558 /* {a is a one-dimensional array} */
559 /* {a is an array of references} */
561 if (valuevftbl == componentvftbl)
564 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
566 if ((base = classvalues.super_baseval) <= 0)
567 /* an array of interface references */
568 return (valuevftbl->interfacetablelength > -base &&
569 valuevftbl->interfacetable[base] != NULL);
571 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
572 <= (unsigned) classvalues.super_diffval;
576 /* {a has dimension > 1} */
577 /* {componentvftbl->arraydesc != NULL} */
579 /* check if o is an array */
580 if ((valuedesc = valuevftbl->arraydesc) == NULL)
582 /* {o is an array} */
584 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
588 /* This is an optimized version where a is guaranteed to be one-dimensional */
589 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
591 arraydescriptor *desc;
592 vftbl_t *elementvftbl;
596 castinfo classvalues;
600 /* The following is guaranteed (by verifier checks):
602 * *) a->...vftbl->arraydesc != NULL
603 * *) a->...vftbl->arraydesc->elementvftbl != NULL
604 * *) a->...vftbl->arraydesc->dimension == 1
605 * *) o->vftbl is not an interface vftbl
608 desc = a->header.objheader.vftbl->arraydesc;
609 elementvftbl = desc->elementvftbl;
610 valuevftbl = o->vftbl;
612 /* {a is a one-dimensional array} */
614 if (valuevftbl == elementvftbl)
617 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
619 if ((base = classvalues.super_baseval) <= 0)
620 /* an array of interface references */
621 return (valuevftbl->interfacetablelength > -base &&
622 valuevftbl->interfacetable[base] != NULL);
624 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
625 <= (unsigned) classvalues.super_diffval;
631 /* This is an optimized version where a is guaranteed to be a
632 * one-dimensional array of a class type */
633 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
635 vftbl_t *elementvftbl;
638 castinfo classvalues;
642 /* The following is guaranteed (by verifier checks):
644 * *) a->...vftbl->arraydesc != NULL
645 * *) a->...vftbl->arraydesc->elementvftbl != NULL
646 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
647 * *) a->...vftbl->arraydesc->dimension == 1
648 * *) o->vftbl is not an interface vftbl
651 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
652 valuevftbl = o->vftbl;
654 /* {a is a one-dimensional array} */
656 if (valuevftbl == elementvftbl)
659 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
661 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
662 <= (unsigned) classvalues.super_diffval;
668 /* builtin_new *****************************************************************
670 Creates a new instance of class c on the heap.
672 Return value: pointer to the object or NULL if no memory is
675 *******************************************************************************/
677 java_objectheader *builtin_new(classinfo *c)
679 java_objectheader *o;
681 /* is the class loaded */
682 /*utf_fprint(stderr,c->name);fprintf(stderr,"\n");*/
685 /* is the class linked */
690 if (!c->initialized) {
692 log_message_class("Initialize class (from builtin_new): ", c);
698 o = heap_allocate(c->instancesize, true, c->finalizer);
703 MSET(o, 0, u1, c->instancesize);
707 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
715 /* builtin_newarray ************************************************************
717 Creates an array with the given vftbl on the heap.
719 Return value: pointer to the array or NULL if no memory is available
721 CAUTION: The given vftbl must be the vftbl of the *array* class,
722 not of the element class.
724 *******************************************************************************/
726 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
729 arraydescriptor *desc;
734 desc = arrayvftbl->arraydesc;
735 dataoffset = desc->dataoffset;
736 componentsize = desc->componentsize;
739 *exceptionptr = new_negativearraysizeexception();
743 actualsize = dataoffset + size * componentsize;
745 if (((u4) actualsize) < ((u4) size)) { /* overflow */
746 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
750 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
755 MSET(a, 0, u1, actualsize);
757 a->objheader.vftbl = arrayvftbl;
759 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
760 initObjectLock(&a->objheader);
769 /********************** Function: builtin_anewarray *************************
771 Creates an array of references to the given class type on the heap.
773 Return value: pointer to the array or NULL if no memory is available
775 XXX This function does not do The Right Thing, because it uses a
776 classinfo pointer at runtime. builtin_newarray should be used
779 *****************************************************************************/
781 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
783 /* is class loaded */
784 assert(component->loaded);
786 /* is class linked */
787 if (!component->linked)
788 if (!link_class(component))
791 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
795 /******************** Function: builtin_newarray_int ***********************
797 Creates an array of 32 bit Integers on the heap.
799 Return value: pointer to the array or NULL if no memory is available
801 *****************************************************************************/
803 java_intarray *builtin_newarray_int(s4 size)
805 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
809 /******************** Function: builtin_newarray_long ***********************
811 Creates an array of 64 bit Integers on the heap.
813 Return value: pointer to the array or NULL if no memory is available
815 *****************************************************************************/
817 java_longarray *builtin_newarray_long(s4 size)
819 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
823 /******************** function: builtin_newarray_float ***********************
825 Creates an array of 32 bit IEEE floats on the heap.
827 Return value: pointer to the array or NULL if no memory is available
829 *****************************************************************************/
831 java_floatarray *builtin_newarray_float(s4 size)
833 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
837 /******************** function: builtin_newarray_double ***********************
839 Creates an array of 64 bit IEEE floats on the heap.
841 Return value: pointer to the array or NULL if no memory is available
843 *****************************************************************************/
845 java_doublearray *builtin_newarray_double(s4 size)
847 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
851 /******************** function: builtin_newarray_byte ***********************
853 Creates an array of 8 bit Integers on the heap.
855 Return value: pointer to the array or NULL if no memory is available
857 *****************************************************************************/
859 java_bytearray *builtin_newarray_byte(s4 size)
861 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
865 /******************** function: builtin_newarray_char ************************
867 Creates an array of characters on the heap.
869 Return value: pointer to the array or NULL if no memory is available
871 *****************************************************************************/
873 java_chararray *builtin_newarray_char(s4 size)
875 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
879 /******************** function: builtin_newarray_short ***********************
881 Creates an array of 16 bit Integers on the heap.
883 Return value: pointer to the array or NULL if no memory is available
885 *****************************************************************************/
887 java_shortarray *builtin_newarray_short(s4 size)
889 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
893 /******************** function: builtin_newarray_boolean ************************
895 Creates an array of bytes on the heap. The array is designated as an array
896 of booleans (important for casts)
898 Return value: pointer to the array or NULL if no memory is available
900 *****************************************************************************/
902 java_booleanarray *builtin_newarray_boolean(s4 size)
904 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
908 /**************** function: builtin_nmultianewarray ***************************
910 Creates a multi-dimensional array on the heap. The dimensions are passed in
914 n............number of dimensions to create
915 arrayvftbl...vftbl of the array class
916 dims.........array containing the size of each dimension to create
918 Return value: pointer to the array or NULL if no memory is available
920 ******************************************************************************/
922 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
923 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
927 vftbl_t *componentvftbl;
929 /* utf_display(arrayclass->name); */
931 /* class_load(arrayclass); */
932 /* class_link(arrayclass); */
934 /* create this dimension */
936 a = builtin_newarray(size, arrayvftbl);
937 /* a = builtin_newarray(size, arrayclass->vftbl); */
942 /* if this is the last dimension return */
946 /* get the vftbl of the components to create */
947 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
948 /* component = arrayclass->vftbl->arraydesc; */
950 /* The verifier guarantees this. */
951 /* if (!componentvftbl) */
952 /* panic ("multianewarray with too many dimensions"); */
954 /* create the component arrays */
955 for (i = 0; i < size; i++) {
956 java_arrayheader *ea =
957 builtin_nmultianewarray(n, componentvftbl, dims + 1);
962 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
969 /*****************************************************************************
972 Various functions for printing a message at method entry or exit (for
975 *****************************************************************************/
979 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
989 log_text("WARNING: unmatched methodindent--");
991 if (opt_verbose || runverbose || verboseexception) {
993 printf("Exception ");
994 utf_display_classname(xptr->vftbl->class->name);
997 printf("Some Throwable");
999 printf(" thrown in ");
1002 utf_display_classname(m->class->name);
1004 utf_display(m->name);
1005 if (m->flags & ACC_SYNCHRONIZED) {
1012 if (m->flags & ACC_NATIVE) {
1014 #if POINTERSIZE == 8
1015 printf(")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1017 printf(")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1021 #if POINTERSIZE == 8
1022 printf(")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1024 printf(")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1026 if (m->class->sourcefile == NULL) {
1027 printf("<NO CLASSFILE INFORMATION>");
1030 utf_display(m->class->sourcefile);
1032 printf(":%d)\n", line);
1036 printf("call_java_method\n");
1044 #ifdef TRACE_ARGS_NUM
1045 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1046 #if TRACE_ARGS_NUM >= 6
1049 #if TRACE_ARGS_NUM == 8
1055 char logtext[MAXLOGTEXT];
1056 for (i = 0; i < methodindent; i++)
1058 if (methodindent == 0)
1059 sprintf(logtext + methodindent, "1st_call: ");
1061 sprintf(logtext + methodindent, "called: ");
1063 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1064 sprintf(logtext + strlen(logtext), ".");
1065 utf_sprint(logtext + strlen(logtext), m->name);
1066 utf_sprint(logtext + strlen(logtext), m->descriptor);
1068 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1069 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1070 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1071 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1072 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1073 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1074 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1075 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1076 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1077 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1078 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1081 sprintf(logtext + strlen(logtext), "(");
1083 switch (m->paramcount) {
1087 #if defined(__I386__) || defined(__POWERPC__)
1089 sprintf(logtext+strlen(logtext), "%llx", a0);
1093 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1097 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1101 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1105 #if TRACE_ARGS_NUM >= 6
1107 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1108 a0, a1, a2, a3, a4);
1112 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1113 a0, a1, a2, a3, a4, a5);
1115 #endif /* TRACE_ARGS_NUM >= 6 */
1117 #if TRACE_ARGS_NUM == 8
1119 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1120 a0, a1, a2, a3, a4, a5, a6);
1124 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1125 a0, a1, a2, a3, a4, a5, a6, a7);
1129 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1130 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1132 #else /* TRACE_ARGS_NUM == 8 */
1134 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1135 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1137 #endif /* TRACE_ARGS_NUM == 8 */
1138 #else /* defined(__I386__) || defined(__POWERPC__) */
1140 sprintf(logtext+strlen(logtext), "%lx", a0);
1144 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1148 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1152 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1156 #if TRACE_ARGS_NUM >= 6
1158 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1159 a0, a1, a2, a3, a4);
1163 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1164 a0, a1, a2, a3, a4, a5);
1166 #endif /* TRACE_ARGS_NUM >= 6 */
1168 #if TRACE_ARGS_NUM == 8
1170 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1171 a0, a1, a2, a3, a4, a5, a6);
1175 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1176 a0, a1, a2, a3, a4, a5, a6, a7);
1178 #endif /* TRACE_ARGS_NUM == 8 */
1181 #if TRACE_ARGS_NUM == 4
1182 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1183 a0, a1, a2, a3, m->paramcount - 4);
1185 #elif TRACE_ARGS_NUM == 6
1186 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1187 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1189 #elif TRACE_ARGS_NUM == 8
1190 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1191 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1194 #endif /* defined(__I386__) || defined(__POWERPC__) */
1197 sprintf(logtext + strlen(logtext), ")");
1205 void builtin_displaymethodstart(methodinfo *m)
1207 char logtext[MAXLOGTEXT];
1208 sprintf(logtext, " ");
1209 sprintf(logtext + methodindent, "called: ");
1210 utf_sprint(logtext + strlen(logtext), m->class->name);
1211 sprintf(logtext + strlen(logtext), ".");
1212 utf_sprint(logtext + strlen(logtext), m->name);
1213 utf_sprint(logtext + strlen(logtext), m->descriptor);
1215 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1216 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1217 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1218 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1219 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1220 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1221 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1222 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1223 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1224 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1225 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1232 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1235 char logtext[MAXLOGTEXT];
1236 for (i = 0; i < methodindent; i++)
1241 log_text("WARNING: unmatched methodindent--");
1243 sprintf(logtext + methodindent, "finished: ");
1244 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1245 sprintf(logtext + strlen(logtext), ".");
1246 utf_sprint(logtext + strlen(logtext), m->name);
1247 utf_sprint(logtext + strlen(logtext), m->descriptor);
1249 switch (m->returntype) {
1251 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1255 #if defined(__I386__) || defined(__POWERPC__)
1256 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1258 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1263 #if defined(__I386__) || defined(__POWERPC__)
1264 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1266 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1271 sprintf(logtext + strlen(logtext), "->%g", f);
1275 sprintf(logtext + strlen(logtext), "->%g", d);
1282 /****************************************************************************
1283 SYNCHRONIZATION FUNCTIONS
1284 *****************************************************************************/
1286 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1288 * Lock the mutex of an object.
1290 void internal_lock_mutex_for_object(java_objectheader *object)
1292 mutexHashEntry *entry;
1295 assert(object != 0);
1297 hashValue = MUTEX_HASH_VALUE(object);
1298 entry = &mutexHashTable[hashValue];
1300 if (entry->object != 0) {
1301 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1303 entry->mutex.holder = 0;
1304 entry->mutex.count = 0;
1305 entry->mutex.muxWaiters = 0;
1308 while (entry->next != 0 && entry->object != object)
1309 entry = entry->next;
1311 if (entry->object != object) {
1312 entry->next = firstFreeOverflowEntry;
1313 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1315 entry = entry->next;
1318 assert(entry->conditionCount == 0);
1323 entry->mutex.holder = 0;
1324 entry->mutex.count = 0;
1325 entry->mutex.muxWaiters = 0;
1328 if (entry->object == 0)
1329 entry->object = object;
1331 internal_lock_mutex(&entry->mutex);
1336 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1338 * Unlocks the mutex of an object.
1340 void internal_unlock_mutex_for_object (java_objectheader *object)
1343 mutexHashEntry *entry;
1345 hashValue = MUTEX_HASH_VALUE(object);
1346 entry = &mutexHashTable[hashValue];
1348 if (entry->object == object) {
1349 internal_unlock_mutex(&entry->mutex);
1352 while (entry->next != 0 && entry->next->object != object)
1353 entry = entry->next;
1355 assert(entry->next != 0);
1357 internal_unlock_mutex(&entry->next->mutex);
1359 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1360 mutexHashEntry *unlinked = entry->next;
1362 entry->next = unlinked->next;
1363 unlinked->next = firstFreeOverflowEntry;
1364 firstFreeOverflowEntry = unlinked;
1371 #if defined(USE_THREADS)
1372 void builtin_monitorenter(java_objectheader *o)
1374 #if !defined(NATIVE_THREADS)
1379 hashValue = MUTEX_HASH_VALUE(o);
1380 if (mutexHashTable[hashValue].object == o
1381 && mutexHashTable[hashValue].mutex.holder == currentThread)
1382 ++mutexHashTable[hashValue].mutex.count;
1384 internal_lock_mutex_for_object(o);
1388 monitorEnter((threadobject *) THREADOBJECT, o);
1394 #if defined(USE_THREADS)
1396 * Locks the class object - needed for static synchronized methods.
1397 * The use_class_as_object call is needed in order to circumvent a
1398 * possible deadlock with builtin_monitorenter called by another
1399 * thread calling use_class_as_object.
1401 void builtin_staticmonitorenter(classinfo *c)
1403 use_class_as_object(c);
1404 builtin_monitorenter(&c->header);
1409 #if defined(USE_THREADS)
1410 void *builtin_monitorexit(java_objectheader *o)
1412 #if !defined(NATIVE_THREADS)
1417 hashValue = MUTEX_HASH_VALUE(o);
1418 if (mutexHashTable[hashValue].object == o) {
1419 if (mutexHashTable[hashValue].mutex.count == 1
1420 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1421 internal_unlock_mutex_for_object(o);
1423 --mutexHashTable[hashValue].mutex.count;
1426 internal_unlock_mutex_for_object(o);
1431 monitorExit((threadobject *) THREADOBJECT, o);
1438 /*****************************************************************************
1439 MISCELLANEOUS HELPER FUNCTIONS
1440 *****************************************************************************/
1444 /*********** Functions for integer divisions *****************************
1446 On some systems (eg. DEC ALPHA), integer division is not supported by the
1447 CPU. These helper functions implement the missing functionality.
1449 ******************************************************************************/
1451 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1452 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1455 /************** Functions for long arithmetics *******************************
1457 On systems where 64 bit Integers are not supported by the CPU, these
1458 functions are needed.
1460 ******************************************************************************/
1463 s8 builtin_ladd(s8 a, s8 b)
1468 return builtin_i2l(0);
1472 s8 builtin_lsub(s8 a, s8 b)
1477 return builtin_i2l(0);
1481 s8 builtin_lmul(s8 a, s8 b)
1486 return builtin_i2l(0);
1490 s8 builtin_ldiv(s8 a, s8 b)
1495 return builtin_i2l(0);
1499 s8 builtin_lrem(s8 a, s8 b)
1504 return builtin_i2l(0);
1508 s8 builtin_lshl(s8 a, s4 b)
1511 return a << (b & 63);
1513 return builtin_i2l(0);
1517 s8 builtin_lshr(s8 a, s4 b)
1520 return a >> (b & 63);
1522 return builtin_i2l(0);
1526 s8 builtin_lushr(s8 a, s4 b)
1529 return ((u8) a) >> (b & 63);
1531 return builtin_i2l(0);
1535 s8 builtin_land(s8 a, s8 b)
1540 return builtin_i2l(0);
1544 s8 builtin_lor(s8 a, s8 b)
1549 return builtin_i2l(0);
1553 s8 builtin_lxor(s8 a, s8 b)
1558 return builtin_i2l(0);
1562 s8 builtin_lneg(s8 a)
1567 return builtin_i2l(0);
1571 s4 builtin_lcmp(s8 a, s8 b)
1574 if (a < b) return -1;
1575 if (a > b) return 1;
1586 /*********** Functions for floating point operations *************************/
1588 float builtin_fadd(float a, float b)
1590 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1591 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1602 if (copysignf(1.0, a) == copysignf(1.0, b))
1605 return intBitsToFloat(FLT_NAN);
1611 float builtin_fsub(float a, float b)
1613 return builtin_fadd(a, builtin_fneg(b));
1617 float builtin_fmul(float a, float b)
1619 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1620 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1622 if (finitef(b)) return a * b;
1624 if (a == 0) return intBitsToFloat(FLT_NAN);
1625 else return copysignf(b, copysignf(1.0, b)*a);
1630 if (b == 0) return intBitsToFloat(FLT_NAN);
1631 else return copysignf(a, copysignf(1.0, a)*b);
1634 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1640 float builtin_fdiv(float a, float b)
1642 if (finitef(a) && finitef(b)) {
1647 return intBitsToFloat(FLT_POSINF);
1649 return intBitsToFloat(FLT_NEGINF);
1652 return intBitsToFloat(FLT_NAN);
1656 float builtin_frem(float a, float b)
1662 float builtin_fneg(float a)
1664 if (isnanf(a)) return a;
1666 if (finitef(a)) return -a;
1667 else return copysignf(a, -copysignf(1.0, a));
1672 s4 builtin_fcmpl(float a, float b)
1674 if (isnanf(a)) return -1;
1675 if (isnanf(b)) return -1;
1676 if (!finitef(a) || !finitef(b)) {
1677 a = finitef(a) ? 0 : copysignf(1.0, a);
1678 b = finitef(b) ? 0 : copysignf(1.0, b);
1680 if (a > b) return 1;
1681 if (a == b) return 0;
1686 s4 builtin_fcmpg(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;
1701 /************************* Functions for doubles ****************************/
1703 double builtin_dadd(double a, double b)
1705 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1706 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1708 if (finite(b)) return a + b;
1712 if (finite(b)) return a;
1714 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1715 else return longBitsToDouble(DBL_NAN);
1721 double builtin_dsub(double a, double b)
1723 return builtin_dadd(a, builtin_dneg(b));
1727 double builtin_dmul(double a, double b)
1729 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1730 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1732 if (finite(b)) return a * b;
1734 if (a == 0) return longBitsToDouble(DBL_NAN);
1735 else return copysign(b, copysign(1.0, b) * a);
1740 if (b == 0) return longBitsToDouble(DBL_NAN);
1741 else return copysign(a, copysign(1.0, a) * b);
1744 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1750 double builtin_ddiv(double a, double b)
1758 return longBitsToDouble(DBL_NAN);
1760 return copysign(0.0, b);
1766 return longBitsToDouble(DBL_POSINF);
1768 return longBitsToDouble(DBL_NEGINF);
1771 return longBitsToDouble(DBL_NAN);
1774 /* if (finite(a) && finite(b)) { */
1779 /* return longBitsToDouble(DBL_POSINF); */
1780 /* else if (a < 0) */
1781 /* return longBitsToDouble(DBL_NEGINF); */
1785 /* keep compiler happy */
1790 double builtin_drem(double a, double b)
1796 double builtin_dneg(double a)
1798 if (isnan(a)) return a;
1800 if (finite(a)) return -a;
1801 else return copysign(a, -copysign(1.0, a));
1806 s4 builtin_dcmpl(double a, double b)
1808 if (isnan(a)) return -1;
1809 if (isnan(b)) return -1;
1810 if (!finite(a) || !finite(b)) {
1811 a = finite(a) ? 0 : copysign(1.0, a);
1812 b = finite(b) ? 0 : copysign(1.0, b);
1814 if (a > b) return 1;
1815 if (a == b) return 0;
1820 s4 builtin_dcmpg(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 /*********************** Conversion operations ****************************/
1836 s8 builtin_i2l(s4 i)
1849 float builtin_i2f(s4 a)
1851 float f = (float) a;
1856 double builtin_i2d(s4 a)
1858 double d = (double) a;
1863 s4 builtin_l2i(s8 l)
1873 float builtin_l2f(s8 a)
1876 float f = (float) a;
1884 double builtin_l2d(s8 a)
1887 double d = (double) a;
1895 s4 builtin_f2i(float a)
1898 return builtin_d2i((double) a);
1907 if (a < (-2147483648))
1908 return (-2147483648);
1911 f = copysignf((float) 1.0, a);
1914 return (-2147483648); */
1918 s8 builtin_f2l(float a)
1921 return builtin_d2l((double) a);
1926 if (a > 9223372036854775807L)
1927 return 9223372036854775807L;
1928 if (a < (-9223372036854775808L))
1929 return (-9223372036854775808L);
1934 f = copysignf((float) 1.0, a);
1936 return 9223372036854775807L;
1937 return (-9223372036854775808L); */
1941 double builtin_f2d(float a)
1943 if (finitef(a)) return (double) a;
1946 return longBitsToDouble(DBL_NAN);
1948 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1953 s4 builtin_d2i(double a)
1958 if (a >= 2147483647)
1960 if (a <= (-2147483647-1))
1961 return (-2147483647-1);
1966 d = copysign(1.0, a);
1969 return (-2147483647-1);
1973 s8 builtin_d2l(double a)
1978 if (a >= 9223372036854775807LL)
1979 return 9223372036854775807LL;
1980 if (a <= (-9223372036854775807LL-1))
1981 return (-9223372036854775807LL-1);
1986 d = copysign(1.0, a);
1988 return 9223372036854775807LL;
1989 return (-9223372036854775807LL-1);
1993 float builtin_d2f(double a)
1999 return intBitsToFloat(FLT_NAN);
2001 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2006 /* used to convert FLT_xxx defines into float values */
2008 inline float intBitsToFloat(s4 i)
2017 /* used to convert DBL_xxx defines into double values */
2019 inline float longBitsToDouble(s8 l)
2028 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2030 return (java_arrayheader *)
2031 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2037 panic("Internal error: builtin_dummy called (native function is missing)");
2038 return 0; /* for the compiler */
2042 /* builtin_asm_get_exceptionptrptr *********************************************
2044 this is a wrapper for calls from asmpart
2046 *******************************************************************************/
2048 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2049 java_objectheader **builtin_asm_get_exceptionptrptr()
2051 return builtin_get_exceptionptrptr();
2056 methodinfo *builtin_asm_get_threadrootmethod()
2058 return *threadrootmethod;
2062 inline void* builtin_asm_get_stackframeinfo()
2064 /*log_text("builtin_asm_get_stackframeinfo()");*/
2065 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2066 return &THREADINFO->_stackframeinfo;
2068 #if defined(__GNUC__)
2069 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2071 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2075 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2076 /* stacktraceelement *el;*/
2079 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2080 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2082 *el=MNEW(stacktraceelement,s+1); /*GC*/
2084 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2086 #if defined(__GNUC__)
2087 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2089 (*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 */
2094 * These are local overrides for various environment variables in Emacs.
2095 * Please do not remove this and leave it at the end of the file, where
2096 * Emacs will automagically detect them.
2097 * ---------------------------------------------------------------------
2100 * indent-tabs-mode: t