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 2148 2005-03-30 16:49:40Z twisti $
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 */
683 if (!load_class_bootstrap(c))
686 /* is the class linked */
691 if (!c->initialized) {
693 log_message_class("Initialize class (from builtin_new): ", c);
699 o = heap_allocate(c->instancesize, true, c->finalizer);
704 MSET(o, 0, u1, c->instancesize);
708 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
716 /* builtin_newarray ************************************************************
718 Creates an array with the given vftbl on the heap.
720 Return value: pointer to the array or NULL if no memory is available
722 CAUTION: The given vftbl must be the vftbl of the *array* class,
723 not of the element class.
725 *******************************************************************************/
727 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
730 arraydescriptor *desc;
735 desc = arrayvftbl->arraydesc;
736 dataoffset = desc->dataoffset;
737 componentsize = desc->componentsize;
740 *exceptionptr = new_negativearraysizeexception();
744 actualsize = dataoffset + size * componentsize;
746 if (((u4) actualsize) < ((u4) size)) { /* overflow */
747 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
751 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
756 MSET(a, 0, u1, actualsize);
758 a->objheader.vftbl = arrayvftbl;
760 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
761 initObjectLock(&a->objheader);
770 /********************** Function: builtin_anewarray *************************
772 Creates an array of references to the given class type on the heap.
774 Return value: pointer to the array or NULL if no memory is available
776 XXX This function does not do The Right Thing, because it uses a
777 classinfo pointer at runtime. builtin_newarray should be used
780 *****************************************************************************/
782 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
784 /* is class loaded */
785 if (!component->loaded)
786 if (!load_class_bootstrap(component))
789 /* is class linked */
790 if (!component->linked)
791 if (!link_class(component))
794 return (java_objectarray *) builtin_newarray(size, class_array_of(component)->vftbl);
798 /******************** Function: builtin_newarray_int ***********************
800 Creates an array of 32 bit Integers on the heap.
802 Return value: pointer to the array or NULL if no memory is available
804 *****************************************************************************/
806 java_intarray *builtin_newarray_int(s4 size)
808 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
812 /******************** Function: builtin_newarray_long ***********************
814 Creates an array of 64 bit Integers on the heap.
816 Return value: pointer to the array or NULL if no memory is available
818 *****************************************************************************/
820 java_longarray *builtin_newarray_long(s4 size)
822 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
826 /******************** function: builtin_newarray_float ***********************
828 Creates an array of 32 bit IEEE floats on the heap.
830 Return value: pointer to the array or NULL if no memory is available
832 *****************************************************************************/
834 java_floatarray *builtin_newarray_float(s4 size)
836 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
840 /******************** function: builtin_newarray_double ***********************
842 Creates an array of 64 bit IEEE floats on the heap.
844 Return value: pointer to the array or NULL if no memory is available
846 *****************************************************************************/
848 java_doublearray *builtin_newarray_double(s4 size)
850 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
854 /******************** function: builtin_newarray_byte ***********************
856 Creates an array of 8 bit Integers on the heap.
858 Return value: pointer to the array or NULL if no memory is available
860 *****************************************************************************/
862 java_bytearray *builtin_newarray_byte(s4 size)
864 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
868 /******************** function: builtin_newarray_char ************************
870 Creates an array of characters on the heap.
872 Return value: pointer to the array or NULL if no memory is available
874 *****************************************************************************/
876 java_chararray *builtin_newarray_char(s4 size)
878 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
882 /******************** function: builtin_newarray_short ***********************
884 Creates an array of 16 bit Integers on the heap.
886 Return value: pointer to the array or NULL if no memory is available
888 *****************************************************************************/
890 java_shortarray *builtin_newarray_short(s4 size)
892 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
896 /******************** function: builtin_newarray_boolean ************************
898 Creates an array of bytes on the heap. The array is designated as an array
899 of booleans (important for casts)
901 Return value: pointer to the array or NULL if no memory is available
903 *****************************************************************************/
905 java_booleanarray *builtin_newarray_boolean(s4 size)
907 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
911 /**************** function: builtin_nmultianewarray ***************************
913 Creates a multi-dimensional array on the heap. The dimensions are passed in
917 n............number of dimensions to create
918 arrayvftbl...vftbl of the array class
919 dims.........array containing the size of each dimension to create
921 Return value: pointer to the array or NULL if no memory is available
923 ******************************************************************************/
925 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
926 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
930 vftbl_t *componentvftbl;
932 /* utf_display(arrayclass->name); */
934 /* class_load(arrayclass); */
935 /* class_link(arrayclass); */
937 /* create this dimension */
939 a = builtin_newarray(size, arrayvftbl);
940 /* a = builtin_newarray(size, arrayclass->vftbl); */
945 /* if this is the last dimension return */
949 /* get the vftbl of the components to create */
950 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
951 /* component = arrayclass->vftbl->arraydesc; */
953 /* The verifier guarantees this. */
954 /* if (!componentvftbl) */
955 /* panic ("multianewarray with too many dimensions"); */
957 /* create the component arrays */
958 for (i = 0; i < size; i++) {
959 java_arrayheader *ea =
960 builtin_nmultianewarray(n, componentvftbl, dims + 1);
965 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
972 /*****************************************************************************
975 Various functions for printing a message at method entry or exit (for
978 *****************************************************************************/
982 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
992 log_text("WARNING: unmatched methodindent--");
994 if (opt_verbose || runverbose || verboseexception) {
996 printf("Exception ");
997 utf_display_classname(xptr->vftbl->class->name);
1000 printf("Some Throwable");
1002 printf(" thrown in ");
1005 utf_display_classname(m->class->name);
1007 utf_display(m->name);
1008 if (m->flags & ACC_SYNCHRONIZED) {
1015 if (m->flags & ACC_NATIVE) {
1017 #if POINTERSIZE == 8
1018 printf(")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1020 printf(")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1024 #if POINTERSIZE == 8
1025 printf(")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1027 printf(")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1029 if (m->class->sourcefile == NULL) {
1030 printf("<NO CLASSFILE INFORMATION>");
1033 utf_display(m->class->sourcefile);
1035 printf(":%d)\n", line);
1039 printf("call_java_method\n");
1047 #ifdef TRACE_ARGS_NUM
1048 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1049 #if TRACE_ARGS_NUM >= 6
1052 #if TRACE_ARGS_NUM == 8
1058 char logtext[MAXLOGTEXT];
1059 for (i = 0; i < methodindent; i++)
1061 if (methodindent == 0)
1062 sprintf(logtext + methodindent, "1st_call: ");
1064 sprintf(logtext + methodindent, "called: ");
1066 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1067 sprintf(logtext + strlen(logtext), ".");
1068 utf_sprint(logtext + strlen(logtext), m->name);
1069 utf_sprint(logtext + strlen(logtext), m->descriptor);
1071 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1072 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1073 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1074 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1075 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1076 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1077 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1078 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1079 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1080 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1081 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1084 sprintf(logtext + strlen(logtext), "(");
1086 switch (m->paramcount) {
1090 #if defined(__I386__) || defined(__POWERPC__)
1092 sprintf(logtext+strlen(logtext), "%llx", a0);
1096 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1100 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1104 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1108 #if TRACE_ARGS_NUM >= 6
1110 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1111 a0, a1, a2, a3, a4);
1115 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1116 a0, a1, a2, a3, a4, a5);
1118 #endif /* TRACE_ARGS_NUM >= 6 */
1120 #if TRACE_ARGS_NUM == 8
1122 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1123 a0, a1, a2, a3, a4, a5, a6);
1127 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1128 a0, a1, a2, a3, a4, a5, a6, a7);
1132 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1133 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1135 #else /* TRACE_ARGS_NUM == 8 */
1137 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1138 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1140 #endif /* TRACE_ARGS_NUM == 8 */
1141 #else /* defined(__I386__) || defined(__POWERPC__) */
1143 sprintf(logtext+strlen(logtext), "%lx", a0);
1147 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1151 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1155 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1159 #if TRACE_ARGS_NUM >= 6
1161 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1162 a0, a1, a2, a3, a4);
1166 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1167 a0, a1, a2, a3, a4, a5);
1169 #endif /* TRACE_ARGS_NUM >= 6 */
1171 #if TRACE_ARGS_NUM == 8
1173 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1174 a0, a1, a2, a3, a4, a5, a6);
1178 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1179 a0, a1, a2, a3, a4, a5, a6, a7);
1181 #endif /* TRACE_ARGS_NUM == 8 */
1184 #if TRACE_ARGS_NUM == 4
1185 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1186 a0, a1, a2, a3, m->paramcount - 4);
1188 #elif TRACE_ARGS_NUM == 6
1189 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1190 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1192 #elif TRACE_ARGS_NUM == 8
1193 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1194 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1197 #endif /* defined(__I386__) || defined(__POWERPC__) */
1200 sprintf(logtext + strlen(logtext), ")");
1208 void builtin_displaymethodstart(methodinfo *m)
1210 char logtext[MAXLOGTEXT];
1211 sprintf(logtext, " ");
1212 sprintf(logtext + methodindent, "called: ");
1213 utf_sprint(logtext + strlen(logtext), m->class->name);
1214 sprintf(logtext + strlen(logtext), ".");
1215 utf_sprint(logtext + strlen(logtext), m->name);
1216 utf_sprint(logtext + strlen(logtext), m->descriptor);
1218 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1219 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1220 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1221 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1222 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1223 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1224 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1225 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1226 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1227 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1228 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1235 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1238 char logtext[MAXLOGTEXT];
1239 for (i = 0; i < methodindent; i++)
1244 log_text("WARNING: unmatched methodindent--");
1246 sprintf(logtext + methodindent, "finished: ");
1247 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1248 sprintf(logtext + strlen(logtext), ".");
1249 utf_sprint(logtext + strlen(logtext), m->name);
1250 utf_sprint(logtext + strlen(logtext), m->descriptor);
1252 switch (m->returntype) {
1254 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1258 #if defined(__I386__) || defined(__POWERPC__)
1259 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1261 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1266 #if defined(__I386__) || defined(__POWERPC__)
1267 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1269 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1274 sprintf(logtext + strlen(logtext), "->%g", f);
1278 sprintf(logtext + strlen(logtext), "->%g", d);
1285 /****************************************************************************
1286 SYNCHRONIZATION FUNCTIONS
1287 *****************************************************************************/
1289 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1291 * Lock the mutex of an object.
1293 void internal_lock_mutex_for_object(java_objectheader *object)
1295 mutexHashEntry *entry;
1298 assert(object != 0);
1300 hashValue = MUTEX_HASH_VALUE(object);
1301 entry = &mutexHashTable[hashValue];
1303 if (entry->object != 0) {
1304 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1306 entry->mutex.holder = 0;
1307 entry->mutex.count = 0;
1308 entry->mutex.muxWaiters = 0;
1311 while (entry->next != 0 && entry->object != object)
1312 entry = entry->next;
1314 if (entry->object != object) {
1315 entry->next = firstFreeOverflowEntry;
1316 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1318 entry = entry->next;
1321 assert(entry->conditionCount == 0);
1326 entry->mutex.holder = 0;
1327 entry->mutex.count = 0;
1328 entry->mutex.muxWaiters = 0;
1331 if (entry->object == 0)
1332 entry->object = object;
1334 internal_lock_mutex(&entry->mutex);
1339 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1341 * Unlocks the mutex of an object.
1343 void internal_unlock_mutex_for_object (java_objectheader *object)
1346 mutexHashEntry *entry;
1348 hashValue = MUTEX_HASH_VALUE(object);
1349 entry = &mutexHashTable[hashValue];
1351 if (entry->object == object) {
1352 internal_unlock_mutex(&entry->mutex);
1355 while (entry->next != 0 && entry->next->object != object)
1356 entry = entry->next;
1358 assert(entry->next != 0);
1360 internal_unlock_mutex(&entry->next->mutex);
1362 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1363 mutexHashEntry *unlinked = entry->next;
1365 entry->next = unlinked->next;
1366 unlinked->next = firstFreeOverflowEntry;
1367 firstFreeOverflowEntry = unlinked;
1374 #if defined(USE_THREADS)
1375 void builtin_monitorenter(java_objectheader *o)
1377 #if !defined(NATIVE_THREADS)
1382 hashValue = MUTEX_HASH_VALUE(o);
1383 if (mutexHashTable[hashValue].object == o
1384 && mutexHashTable[hashValue].mutex.holder == currentThread)
1385 ++mutexHashTable[hashValue].mutex.count;
1387 internal_lock_mutex_for_object(o);
1391 monitorEnter((threadobject *) THREADOBJECT, o);
1397 #if defined(USE_THREADS)
1399 * Locks the class object - needed for static synchronized methods.
1400 * The use_class_as_object call is needed in order to circumvent a
1401 * possible deadlock with builtin_monitorenter called by another
1402 * thread calling use_class_as_object.
1404 void builtin_staticmonitorenter(classinfo *c)
1406 use_class_as_object(c);
1407 builtin_monitorenter(&c->header);
1412 #if defined(USE_THREADS)
1413 void *builtin_monitorexit(java_objectheader *o)
1415 #if !defined(NATIVE_THREADS)
1420 hashValue = MUTEX_HASH_VALUE(o);
1421 if (mutexHashTable[hashValue].object == o) {
1422 if (mutexHashTable[hashValue].mutex.count == 1
1423 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1424 internal_unlock_mutex_for_object(o);
1426 --mutexHashTable[hashValue].mutex.count;
1429 internal_unlock_mutex_for_object(o);
1434 monitorExit((threadobject *) THREADOBJECT, o);
1441 /*****************************************************************************
1442 MISCELLANEOUS HELPER FUNCTIONS
1443 *****************************************************************************/
1447 /*********** Functions for integer divisions *****************************
1449 On some systems (eg. DEC ALPHA), integer division is not supported by the
1450 CPU. These helper functions implement the missing functionality.
1452 ******************************************************************************/
1454 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1455 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1458 /************** Functions for long arithmetics *******************************
1460 On systems where 64 bit Integers are not supported by the CPU, these
1461 functions are needed.
1463 ******************************************************************************/
1466 s8 builtin_ladd(s8 a, s8 b)
1471 return builtin_i2l(0);
1475 s8 builtin_lsub(s8 a, s8 b)
1480 return builtin_i2l(0);
1484 s8 builtin_lmul(s8 a, s8 b)
1489 return builtin_i2l(0);
1493 s8 builtin_ldiv(s8 a, s8 b)
1498 return builtin_i2l(0);
1502 s8 builtin_lrem(s8 a, s8 b)
1507 return builtin_i2l(0);
1511 s8 builtin_lshl(s8 a, s4 b)
1514 return a << (b & 63);
1516 return builtin_i2l(0);
1520 s8 builtin_lshr(s8 a, s4 b)
1523 return a >> (b & 63);
1525 return builtin_i2l(0);
1529 s8 builtin_lushr(s8 a, s4 b)
1532 return ((u8) a) >> (b & 63);
1534 return builtin_i2l(0);
1538 s8 builtin_land(s8 a, s8 b)
1543 return builtin_i2l(0);
1547 s8 builtin_lor(s8 a, s8 b)
1552 return builtin_i2l(0);
1556 s8 builtin_lxor(s8 a, s8 b)
1561 return builtin_i2l(0);
1565 s8 builtin_lneg(s8 a)
1570 return builtin_i2l(0);
1574 s4 builtin_lcmp(s8 a, s8 b)
1577 if (a < b) return -1;
1578 if (a > b) return 1;
1589 /*********** Functions for floating point operations *************************/
1591 float builtin_fadd(float a, float b)
1593 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1594 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1605 if (copysignf(1.0, a) == copysignf(1.0, b))
1608 return intBitsToFloat(FLT_NAN);
1614 float builtin_fsub(float a, float b)
1616 return builtin_fadd(a, builtin_fneg(b));
1620 float builtin_fmul(float a, float b)
1622 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1623 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1625 if (finitef(b)) return a * b;
1627 if (a == 0) return intBitsToFloat(FLT_NAN);
1628 else return copysignf(b, copysignf(1.0, b)*a);
1633 if (b == 0) return intBitsToFloat(FLT_NAN);
1634 else return copysignf(a, copysignf(1.0, a)*b);
1637 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1643 float builtin_fdiv(float a, float b)
1645 if (finitef(a) && finitef(b)) {
1650 return intBitsToFloat(FLT_POSINF);
1652 return intBitsToFloat(FLT_NEGINF);
1655 return intBitsToFloat(FLT_NAN);
1659 float builtin_frem(float a, float b)
1665 float builtin_fneg(float a)
1667 if (isnanf(a)) return a;
1669 if (finitef(a)) return -a;
1670 else return copysignf(a, -copysignf(1.0, a));
1675 s4 builtin_fcmpl(float a, float b)
1677 if (isnanf(a)) return -1;
1678 if (isnanf(b)) return -1;
1679 if (!finitef(a) || !finitef(b)) {
1680 a = finitef(a) ? 0 : copysignf(1.0, a);
1681 b = finitef(b) ? 0 : copysignf(1.0, b);
1683 if (a > b) return 1;
1684 if (a == b) return 0;
1689 s4 builtin_fcmpg(float a, float b)
1691 if (isnanf(a)) return 1;
1692 if (isnanf(b)) return 1;
1693 if (!finitef(a) || !finitef(b)) {
1694 a = finitef(a) ? 0 : copysignf(1.0, a);
1695 b = finitef(b) ? 0 : copysignf(1.0, b);
1697 if (a > b) return 1;
1698 if (a == b) return 0;
1704 /************************* Functions for doubles ****************************/
1706 double builtin_dadd(double a, double b)
1708 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1709 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1711 if (finite(b)) return a + b;
1715 if (finite(b)) return a;
1717 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1718 else return longBitsToDouble(DBL_NAN);
1724 double builtin_dsub(double a, double b)
1726 return builtin_dadd(a, builtin_dneg(b));
1730 double builtin_dmul(double a, double b)
1732 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1733 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1735 if (finite(b)) return a * b;
1737 if (a == 0) return longBitsToDouble(DBL_NAN);
1738 else return copysign(b, copysign(1.0, b) * a);
1743 if (b == 0) return longBitsToDouble(DBL_NAN);
1744 else return copysign(a, copysign(1.0, a) * b);
1747 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1753 double builtin_ddiv(double a, double b)
1761 return longBitsToDouble(DBL_NAN);
1763 return copysign(0.0, b);
1769 return longBitsToDouble(DBL_POSINF);
1771 return longBitsToDouble(DBL_NEGINF);
1774 return longBitsToDouble(DBL_NAN);
1777 /* if (finite(a) && finite(b)) { */
1782 /* return longBitsToDouble(DBL_POSINF); */
1783 /* else if (a < 0) */
1784 /* return longBitsToDouble(DBL_NEGINF); */
1788 /* keep compiler happy */
1793 double builtin_drem(double a, double b)
1799 double builtin_dneg(double a)
1801 if (isnan(a)) return a;
1803 if (finite(a)) return -a;
1804 else return copysign(a, -copysign(1.0, a));
1809 s4 builtin_dcmpl(double a, double b)
1811 if (isnan(a)) return -1;
1812 if (isnan(b)) return -1;
1813 if (!finite(a) || !finite(b)) {
1814 a = finite(a) ? 0 : copysign(1.0, a);
1815 b = finite(b) ? 0 : copysign(1.0, b);
1817 if (a > b) return 1;
1818 if (a == b) return 0;
1823 s4 builtin_dcmpg(double a, double b)
1825 if (isnan(a)) return 1;
1826 if (isnan(b)) return 1;
1827 if (!finite(a) || !finite(b)) {
1828 a = finite(a) ? 0 : copysign(1.0, a);
1829 b = finite(b) ? 0 : copysign(1.0, b);
1831 if (a > b) return 1;
1832 if (a == b) return 0;
1837 /*********************** Conversion operations ****************************/
1839 s8 builtin_i2l(s4 i)
1852 float builtin_i2f(s4 a)
1854 float f = (float) a;
1859 double builtin_i2d(s4 a)
1861 double d = (double) a;
1866 s4 builtin_l2i(s8 l)
1876 float builtin_l2f(s8 a)
1879 float f = (float) a;
1887 double builtin_l2d(s8 a)
1890 double d = (double) a;
1898 s4 builtin_f2i(float a)
1901 return builtin_d2i((double) a);
1910 if (a < (-2147483648))
1911 return (-2147483648);
1914 f = copysignf((float) 1.0, a);
1917 return (-2147483648); */
1921 s8 builtin_f2l(float a)
1924 return builtin_d2l((double) a);
1929 if (a > 9223372036854775807L)
1930 return 9223372036854775807L;
1931 if (a < (-9223372036854775808L))
1932 return (-9223372036854775808L);
1937 f = copysignf((float) 1.0, a);
1939 return 9223372036854775807L;
1940 return (-9223372036854775808L); */
1944 double builtin_f2d(float a)
1946 if (finitef(a)) return (double) a;
1949 return longBitsToDouble(DBL_NAN);
1951 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1956 s4 builtin_d2i(double a)
1961 if (a >= 2147483647)
1963 if (a <= (-2147483647-1))
1964 return (-2147483647-1);
1969 d = copysign(1.0, a);
1972 return (-2147483647-1);
1976 s8 builtin_d2l(double a)
1981 if (a >= 9223372036854775807LL)
1982 return 9223372036854775807LL;
1983 if (a <= (-9223372036854775807LL-1))
1984 return (-9223372036854775807LL-1);
1989 d = copysign(1.0, a);
1991 return 9223372036854775807LL;
1992 return (-9223372036854775807LL-1);
1996 float builtin_d2f(double a)
2002 return intBitsToFloat(FLT_NAN);
2004 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2009 /* used to convert FLT_xxx defines into float values */
2011 inline float intBitsToFloat(s4 i)
2020 /* used to convert DBL_xxx defines into double values */
2022 inline float longBitsToDouble(s8 l)
2031 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2033 return (java_arrayheader *)
2034 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2040 panic("Internal error: builtin_dummy called (native function is missing)");
2041 return 0; /* for the compiler */
2045 /* builtin_asm_get_exceptionptrptr *********************************************
2047 this is a wrapper for calls from asmpart
2049 *******************************************************************************/
2051 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2052 java_objectheader **builtin_asm_get_exceptionptrptr()
2054 return builtin_get_exceptionptrptr();
2059 methodinfo *builtin_asm_get_threadrootmethod()
2061 return *threadrootmethod;
2065 inline void* builtin_asm_get_stackframeinfo()
2067 /*log_text("builtin_asm_get_stackframeinfo()");*/
2068 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2069 return &THREADINFO->_stackframeinfo;
2071 #if defined(__GNUC__)
2072 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2074 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2078 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2079 /* stacktraceelement *el;*/
2082 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2083 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2085 *el=MNEW(stacktraceelement,s+1); /*GC*/
2087 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2089 #if defined(__GNUC__)
2090 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2092 (*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 */
2097 * These are local overrides for various environment variables in Emacs.
2098 * Please do not remove this and leave it at the end of the file, where
2099 * Emacs will automagically detect them.
2100 * ---------------------------------------------------------------------
2103 * indent-tabs-mode: t