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 2195 2005-04-03 16:53:16Z 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)
785 /* is class loaded */
786 assert(component->loaded);
788 /* is class linked */
789 if (!component->linked)
790 if (!link_class(component))
793 c = class_array_of(component,true);
796 return (java_objectarray *) builtin_newarray(size, c->vftbl);
800 /******************** Function: builtin_newarray_int ***********************
802 Creates an array of 32 bit Integers on the heap.
804 Return value: pointer to the array or NULL if no memory is available
806 *****************************************************************************/
808 java_intarray *builtin_newarray_int(s4 size)
810 return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
814 /******************** Function: builtin_newarray_long ***********************
816 Creates an array of 64 bit Integers on the heap.
818 Return value: pointer to the array or NULL if no memory is available
820 *****************************************************************************/
822 java_longarray *builtin_newarray_long(s4 size)
824 return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
828 /******************** function: builtin_newarray_float ***********************
830 Creates an array of 32 bit IEEE floats on the heap.
832 Return value: pointer to the array or NULL if no memory is available
834 *****************************************************************************/
836 java_floatarray *builtin_newarray_float(s4 size)
838 return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
842 /******************** function: builtin_newarray_double ***********************
844 Creates an array of 64 bit IEEE floats on the heap.
846 Return value: pointer to the array or NULL if no memory is available
848 *****************************************************************************/
850 java_doublearray *builtin_newarray_double(s4 size)
852 return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
856 /******************** function: builtin_newarray_byte ***********************
858 Creates an array of 8 bit Integers on the heap.
860 Return value: pointer to the array or NULL if no memory is available
862 *****************************************************************************/
864 java_bytearray *builtin_newarray_byte(s4 size)
866 return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
870 /******************** function: builtin_newarray_char ************************
872 Creates an array of characters on the heap.
874 Return value: pointer to the array or NULL if no memory is available
876 *****************************************************************************/
878 java_chararray *builtin_newarray_char(s4 size)
880 return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
884 /******************** function: builtin_newarray_short ***********************
886 Creates an array of 16 bit Integers on the heap.
888 Return value: pointer to the array or NULL if no memory is available
890 *****************************************************************************/
892 java_shortarray *builtin_newarray_short(s4 size)
894 return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
898 /******************** function: builtin_newarray_boolean ************************
900 Creates an array of bytes on the heap. The array is designated as an array
901 of booleans (important for casts)
903 Return value: pointer to the array or NULL if no memory is available
905 *****************************************************************************/
907 java_booleanarray *builtin_newarray_boolean(s4 size)
909 return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
913 /**************** function: builtin_nmultianewarray ***************************
915 Creates a multi-dimensional array on the heap. The dimensions are passed in
919 n............number of dimensions to create
920 arrayvftbl...vftbl of the array class
921 dims.........array containing the size of each dimension to create
923 Return value: pointer to the array or NULL if no memory is available
925 ******************************************************************************/
927 java_arrayheader *builtin_nmultianewarray(int n, vftbl_t *arrayvftbl, long *dims)
928 /* java_arrayheader *builtin_nmultianewarray(int n, classinfo *arrayclass, long *dims) */
932 vftbl_t *componentvftbl;
934 /* utf_display(arrayclass->name); */
936 /* class_load(arrayclass); */
937 /* class_link(arrayclass); */
939 /* create this dimension */
941 a = builtin_newarray(size, arrayvftbl);
942 /* a = builtin_newarray(size, arrayclass->vftbl); */
947 /* if this is the last dimension return */
951 /* get the vftbl of the components to create */
952 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
953 /* component = arrayclass->vftbl->arraydesc; */
955 /* The verifier guarantees this. */
956 /* if (!componentvftbl) */
957 /* panic ("multianewarray with too many dimensions"); */
959 /* create the component arrays */
960 for (i = 0; i < size; i++) {
961 java_arrayheader *ea =
962 builtin_nmultianewarray(n, componentvftbl, dims + 1);
967 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
974 /*****************************************************************************
977 Various functions for printing a message at method entry or exit (for
980 *****************************************************************************/
984 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
994 log_text("WARNING: unmatched methodindent--");
996 if (opt_verbose || runverbose || verboseexception) {
998 printf("Exception ");
999 utf_display_classname(xptr->vftbl->class->name);
1002 printf("Some Throwable");
1004 printf(" thrown in ");
1007 utf_display_classname(m->class->name);
1009 utf_display(m->name);
1010 if (m->flags & ACC_SYNCHRONIZED) {
1017 if (m->flags & ACC_NATIVE) {
1019 #if POINTERSIZE == 8
1020 printf(")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1022 printf(")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1026 #if POINTERSIZE == 8
1027 printf(")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1029 printf(")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1031 if (m->class->sourcefile == NULL) {
1032 printf("<NO CLASSFILE INFORMATION>");
1035 utf_display(m->class->sourcefile);
1037 printf(":%d)\n", line);
1041 printf("call_java_method\n");
1049 #ifdef TRACE_ARGS_NUM
1050 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1051 #if TRACE_ARGS_NUM >= 6
1054 #if TRACE_ARGS_NUM == 8
1060 char logtext[MAXLOGTEXT];
1061 for (i = 0; i < methodindent; i++)
1063 if (methodindent == 0)
1064 sprintf(logtext + methodindent, "1st_call: ");
1066 sprintf(logtext + methodindent, "called: ");
1068 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1069 sprintf(logtext + strlen(logtext), ".");
1070 utf_sprint(logtext + strlen(logtext), m->name);
1071 utf_sprint(logtext + strlen(logtext), m->descriptor);
1073 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1074 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1075 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1076 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1077 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1078 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1079 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1080 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1081 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1082 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1083 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1086 sprintf(logtext + strlen(logtext), "(");
1088 switch (m->paramcount) {
1092 #if defined(__I386__) || defined(__POWERPC__)
1094 sprintf(logtext+strlen(logtext), "%llx", a0);
1098 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1102 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1106 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1110 #if TRACE_ARGS_NUM >= 6
1112 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1113 a0, a1, a2, a3, a4);
1117 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1118 a0, a1, a2, a3, a4, a5);
1120 #endif /* TRACE_ARGS_NUM >= 6 */
1122 #if TRACE_ARGS_NUM == 8
1124 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1125 a0, a1, a2, a3, a4, a5, a6);
1129 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1130 a0, a1, a2, a3, a4, a5, a6, a7);
1134 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1135 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1137 #else /* TRACE_ARGS_NUM == 8 */
1139 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1140 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1142 #endif /* TRACE_ARGS_NUM == 8 */
1143 #else /* defined(__I386__) || defined(__POWERPC__) */
1145 sprintf(logtext+strlen(logtext), "%lx", a0);
1149 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1153 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1157 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1161 #if TRACE_ARGS_NUM >= 6
1163 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1164 a0, a1, a2, a3, a4);
1168 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1169 a0, a1, a2, a3, a4, a5);
1171 #endif /* TRACE_ARGS_NUM >= 6 */
1173 #if TRACE_ARGS_NUM == 8
1175 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1176 a0, a1, a2, a3, a4, a5, a6);
1180 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1181 a0, a1, a2, a3, a4, a5, a6, a7);
1183 #endif /* TRACE_ARGS_NUM == 8 */
1186 #if TRACE_ARGS_NUM == 4
1187 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1188 a0, a1, a2, a3, m->paramcount - 4);
1190 #elif TRACE_ARGS_NUM == 6
1191 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1192 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1194 #elif TRACE_ARGS_NUM == 8
1195 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1196 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1199 #endif /* defined(__I386__) || defined(__POWERPC__) */
1202 sprintf(logtext + strlen(logtext), ")");
1210 void builtin_displaymethodstart(methodinfo *m)
1212 char logtext[MAXLOGTEXT];
1213 sprintf(logtext, " ");
1214 sprintf(logtext + methodindent, "called: ");
1215 utf_sprint(logtext + strlen(logtext), m->class->name);
1216 sprintf(logtext + strlen(logtext), ".");
1217 utf_sprint(logtext + strlen(logtext), m->name);
1218 utf_sprint(logtext + strlen(logtext), m->descriptor);
1220 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1221 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1222 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1223 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1224 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1225 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1226 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1227 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1228 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1229 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1230 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1237 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1240 char logtext[MAXLOGTEXT];
1241 for (i = 0; i < methodindent; i++)
1246 log_text("WARNING: unmatched methodindent--");
1248 sprintf(logtext + methodindent, "finished: ");
1249 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1250 sprintf(logtext + strlen(logtext), ".");
1251 utf_sprint(logtext + strlen(logtext), m->name);
1252 utf_sprint(logtext + strlen(logtext), m->descriptor);
1254 switch (m->returntype) {
1256 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1260 #if defined(__I386__) || defined(__POWERPC__)
1261 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1263 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1268 #if defined(__I386__) || defined(__POWERPC__)
1269 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1271 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1276 sprintf(logtext + strlen(logtext), "->%g", f);
1280 sprintf(logtext + strlen(logtext), "->%g", d);
1287 /****************************************************************************
1288 SYNCHRONIZATION FUNCTIONS
1289 *****************************************************************************/
1291 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1293 * Lock the mutex of an object.
1295 void internal_lock_mutex_for_object(java_objectheader *object)
1297 mutexHashEntry *entry;
1300 assert(object != 0);
1302 hashValue = MUTEX_HASH_VALUE(object);
1303 entry = &mutexHashTable[hashValue];
1305 if (entry->object != 0) {
1306 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1308 entry->mutex.holder = 0;
1309 entry->mutex.count = 0;
1310 entry->mutex.muxWaiters = 0;
1313 while (entry->next != 0 && entry->object != object)
1314 entry = entry->next;
1316 if (entry->object != object) {
1317 entry->next = firstFreeOverflowEntry;
1318 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1320 entry = entry->next;
1323 assert(entry->conditionCount == 0);
1328 entry->mutex.holder = 0;
1329 entry->mutex.count = 0;
1330 entry->mutex.muxWaiters = 0;
1333 if (entry->object == 0)
1334 entry->object = object;
1336 internal_lock_mutex(&entry->mutex);
1341 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1343 * Unlocks the mutex of an object.
1345 void internal_unlock_mutex_for_object (java_objectheader *object)
1348 mutexHashEntry *entry;
1350 hashValue = MUTEX_HASH_VALUE(object);
1351 entry = &mutexHashTable[hashValue];
1353 if (entry->object == object) {
1354 internal_unlock_mutex(&entry->mutex);
1357 while (entry->next != 0 && entry->next->object != object)
1358 entry = entry->next;
1360 assert(entry->next != 0);
1362 internal_unlock_mutex(&entry->next->mutex);
1364 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1365 mutexHashEntry *unlinked = entry->next;
1367 entry->next = unlinked->next;
1368 unlinked->next = firstFreeOverflowEntry;
1369 firstFreeOverflowEntry = unlinked;
1376 #if defined(USE_THREADS)
1377 void builtin_monitorenter(java_objectheader *o)
1379 #if !defined(NATIVE_THREADS)
1384 hashValue = MUTEX_HASH_VALUE(o);
1385 if (mutexHashTable[hashValue].object == o
1386 && mutexHashTable[hashValue].mutex.holder == currentThread)
1387 ++mutexHashTable[hashValue].mutex.count;
1389 internal_lock_mutex_for_object(o);
1393 monitorEnter((threadobject *) THREADOBJECT, o);
1399 #if defined(USE_THREADS)
1401 * Locks the class object - needed for static synchronized methods.
1402 * The use_class_as_object call is needed in order to circumvent a
1403 * possible deadlock with builtin_monitorenter called by another
1404 * thread calling use_class_as_object.
1406 void builtin_staticmonitorenter(classinfo *c)
1408 use_class_as_object(c);
1409 builtin_monitorenter(&c->header);
1414 #if defined(USE_THREADS)
1415 void *builtin_monitorexit(java_objectheader *o)
1417 #if !defined(NATIVE_THREADS)
1422 hashValue = MUTEX_HASH_VALUE(o);
1423 if (mutexHashTable[hashValue].object == o) {
1424 if (mutexHashTable[hashValue].mutex.count == 1
1425 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1426 internal_unlock_mutex_for_object(o);
1428 --mutexHashTable[hashValue].mutex.count;
1431 internal_unlock_mutex_for_object(o);
1436 monitorExit((threadobject *) THREADOBJECT, o);
1443 /*****************************************************************************
1444 MISCELLANEOUS HELPER FUNCTIONS
1445 *****************************************************************************/
1449 /*********** Functions for integer divisions *****************************
1451 On some systems (eg. DEC ALPHA), integer division is not supported by the
1452 CPU. These helper functions implement the missing functionality.
1454 ******************************************************************************/
1456 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1457 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1460 /************** Functions for long arithmetics *******************************
1462 On systems where 64 bit Integers are not supported by the CPU, these
1463 functions are needed.
1465 ******************************************************************************/
1468 s8 builtin_ladd(s8 a, s8 b)
1473 return builtin_i2l(0);
1477 s8 builtin_lsub(s8 a, s8 b)
1482 return builtin_i2l(0);
1486 s8 builtin_lmul(s8 a, s8 b)
1491 return builtin_i2l(0);
1495 s8 builtin_ldiv(s8 a, s8 b)
1500 return builtin_i2l(0);
1504 s8 builtin_lrem(s8 a, s8 b)
1509 return builtin_i2l(0);
1513 s8 builtin_lshl(s8 a, s4 b)
1516 return a << (b & 63);
1518 return builtin_i2l(0);
1522 s8 builtin_lshr(s8 a, s4 b)
1525 return a >> (b & 63);
1527 return builtin_i2l(0);
1531 s8 builtin_lushr(s8 a, s4 b)
1534 return ((u8) a) >> (b & 63);
1536 return builtin_i2l(0);
1540 s8 builtin_land(s8 a, s8 b)
1545 return builtin_i2l(0);
1549 s8 builtin_lor(s8 a, s8 b)
1554 return builtin_i2l(0);
1558 s8 builtin_lxor(s8 a, s8 b)
1563 return builtin_i2l(0);
1567 s8 builtin_lneg(s8 a)
1572 return builtin_i2l(0);
1576 s4 builtin_lcmp(s8 a, s8 b)
1579 if (a < b) return -1;
1580 if (a > b) return 1;
1591 /*********** Functions for floating point operations *************************/
1593 float builtin_fadd(float a, float b)
1595 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1596 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1607 if (copysignf(1.0, a) == copysignf(1.0, b))
1610 return intBitsToFloat(FLT_NAN);
1616 float builtin_fsub(float a, float b)
1618 return builtin_fadd(a, builtin_fneg(b));
1622 float builtin_fmul(float a, float b)
1624 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1625 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1627 if (finitef(b)) return a * b;
1629 if (a == 0) return intBitsToFloat(FLT_NAN);
1630 else return copysignf(b, copysignf(1.0, b)*a);
1635 if (b == 0) return intBitsToFloat(FLT_NAN);
1636 else return copysignf(a, copysignf(1.0, a)*b);
1639 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1645 float builtin_fdiv(float a, float b)
1647 if (finitef(a) && finitef(b)) {
1652 return intBitsToFloat(FLT_POSINF);
1654 return intBitsToFloat(FLT_NEGINF);
1657 return intBitsToFloat(FLT_NAN);
1661 float builtin_frem(float a, float b)
1667 float builtin_fneg(float a)
1669 if (isnanf(a)) return a;
1671 if (finitef(a)) return -a;
1672 else return copysignf(a, -copysignf(1.0, a));
1677 s4 builtin_fcmpl(float a, float b)
1679 if (isnanf(a)) return -1;
1680 if (isnanf(b)) return -1;
1681 if (!finitef(a) || !finitef(b)) {
1682 a = finitef(a) ? 0 : copysignf(1.0, a);
1683 b = finitef(b) ? 0 : copysignf(1.0, b);
1685 if (a > b) return 1;
1686 if (a == b) return 0;
1691 s4 builtin_fcmpg(float a, float b)
1693 if (isnanf(a)) return 1;
1694 if (isnanf(b)) return 1;
1695 if (!finitef(a) || !finitef(b)) {
1696 a = finitef(a) ? 0 : copysignf(1.0, a);
1697 b = finitef(b) ? 0 : copysignf(1.0, b);
1699 if (a > b) return 1;
1700 if (a == b) return 0;
1706 /************************* Functions for doubles ****************************/
1708 double builtin_dadd(double a, double b)
1710 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1711 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1713 if (finite(b)) return a + b;
1717 if (finite(b)) return a;
1719 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1720 else return longBitsToDouble(DBL_NAN);
1726 double builtin_dsub(double a, double b)
1728 return builtin_dadd(a, builtin_dneg(b));
1732 double builtin_dmul(double a, double b)
1734 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1735 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1737 if (finite(b)) return a * b;
1739 if (a == 0) return longBitsToDouble(DBL_NAN);
1740 else return copysign(b, copysign(1.0, b) * a);
1745 if (b == 0) return longBitsToDouble(DBL_NAN);
1746 else return copysign(a, copysign(1.0, a) * b);
1749 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1755 double builtin_ddiv(double a, double b)
1763 return longBitsToDouble(DBL_NAN);
1765 return copysign(0.0, b);
1771 return longBitsToDouble(DBL_POSINF);
1773 return longBitsToDouble(DBL_NEGINF);
1776 return longBitsToDouble(DBL_NAN);
1779 /* if (finite(a) && finite(b)) { */
1784 /* return longBitsToDouble(DBL_POSINF); */
1785 /* else if (a < 0) */
1786 /* return longBitsToDouble(DBL_NEGINF); */
1790 /* keep compiler happy */
1795 double builtin_drem(double a, double b)
1801 double builtin_dneg(double a)
1803 if (isnan(a)) return a;
1805 if (finite(a)) return -a;
1806 else return copysign(a, -copysign(1.0, a));
1811 s4 builtin_dcmpl(double a, double b)
1813 if (isnan(a)) return -1;
1814 if (isnan(b)) return -1;
1815 if (!finite(a) || !finite(b)) {
1816 a = finite(a) ? 0 : copysign(1.0, a);
1817 b = finite(b) ? 0 : copysign(1.0, b);
1819 if (a > b) return 1;
1820 if (a == b) return 0;
1825 s4 builtin_dcmpg(double a, double b)
1827 if (isnan(a)) return 1;
1828 if (isnan(b)) return 1;
1829 if (!finite(a) || !finite(b)) {
1830 a = finite(a) ? 0 : copysign(1.0, a);
1831 b = finite(b) ? 0 : copysign(1.0, b);
1833 if (a > b) return 1;
1834 if (a == b) return 0;
1839 /*********************** Conversion operations ****************************/
1841 s8 builtin_i2l(s4 i)
1854 float builtin_i2f(s4 a)
1856 float f = (float) a;
1861 double builtin_i2d(s4 a)
1863 double d = (double) a;
1868 s4 builtin_l2i(s8 l)
1878 float builtin_l2f(s8 a)
1881 float f = (float) a;
1889 double builtin_l2d(s8 a)
1892 double d = (double) a;
1900 s4 builtin_f2i(float a)
1903 return builtin_d2i((double) a);
1912 if (a < (-2147483648))
1913 return (-2147483648);
1916 f = copysignf((float) 1.0, a);
1919 return (-2147483648); */
1923 s8 builtin_f2l(float a)
1926 return builtin_d2l((double) a);
1931 if (a > 9223372036854775807L)
1932 return 9223372036854775807L;
1933 if (a < (-9223372036854775808L))
1934 return (-9223372036854775808L);
1939 f = copysignf((float) 1.0, a);
1941 return 9223372036854775807L;
1942 return (-9223372036854775808L); */
1946 double builtin_f2d(float a)
1948 if (finitef(a)) return (double) a;
1951 return longBitsToDouble(DBL_NAN);
1953 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1958 s4 builtin_d2i(double a)
1963 if (a >= 2147483647)
1965 if (a <= (-2147483647-1))
1966 return (-2147483647-1);
1971 d = copysign(1.0, a);
1974 return (-2147483647-1);
1978 s8 builtin_d2l(double a)
1983 if (a >= 9223372036854775807LL)
1984 return 9223372036854775807LL;
1985 if (a <= (-9223372036854775807LL-1))
1986 return (-9223372036854775807LL-1);
1991 d = copysign(1.0, a);
1993 return 9223372036854775807LL;
1994 return (-9223372036854775807LL-1);
1998 float builtin_d2f(double a)
2004 return intBitsToFloat(FLT_NAN);
2006 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2011 /* used to convert FLT_xxx defines into float values */
2013 inline float intBitsToFloat(s4 i)
2022 /* used to convert DBL_xxx defines into double values */
2024 inline float longBitsToDouble(s8 l)
2033 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2035 return (java_arrayheader *)
2036 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2042 panic("Internal error: builtin_dummy called (native function is missing)");
2043 return 0; /* for the compiler */
2047 /* builtin_asm_get_exceptionptrptr *********************************************
2049 this is a wrapper for calls from asmpart
2051 *******************************************************************************/
2053 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2054 java_objectheader **builtin_asm_get_exceptionptrptr()
2056 return builtin_get_exceptionptrptr();
2061 methodinfo *builtin_asm_get_threadrootmethod()
2063 return *threadrootmethod;
2067 inline void* builtin_asm_get_stackframeinfo()
2069 /*log_text("builtin_asm_get_stackframeinfo()");*/
2070 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2071 return &THREADINFO->_stackframeinfo;
2073 #if defined(__GNUC__)
2074 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2076 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2080 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2081 /* stacktraceelement *el;*/
2084 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2085 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2087 *el=MNEW(stacktraceelement,s+1); /*GC*/
2089 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2091 #if defined(__GNUC__)
2092 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2094 (*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 */
2099 * These are local overrides for various environment variables in Emacs.
2100 * Please do not remove this and leave it at the end of the file, where
2101 * Emacs will automagically detect them.
2102 * ---------------------------------------------------------------------
2105 * indent-tabs-mode: t