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 2369 2005-04-25 14:06:16Z twisti $
53 #include "mm/memory.h"
54 #include "native/native.h"
55 #include "native/include/java_lang_Cloneable.h"
56 #include "native/include/java_lang_VMObject.h"
58 #if defined(USE_THREADS)
59 # if defined(NATIVE_THREADS)
60 # include "threads/native/threads.h"
62 # include "threads/green/threads.h"
63 # include "threads/green/locks.h"
67 #include "toolbox/logging.h"
68 #include "vm/builtin.h"
69 #include "vm/exceptions.h"
70 #include "vm/global.h"
71 #include "vm/initialize.h"
72 #include "vm/loader.h"
73 #include "vm/options.h"
74 #include "vm/stringlocal.h"
75 #include "vm/tables.h"
76 #include "vm/jit/asmpart.h"
77 #include "vm/jit/patcher.h"
80 #undef DEBUG /*define DEBUG 1*/
82 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
83 THREADSPECIFIC void *_thread_nativestackframeinfo = NULL;
86 #if defined(USEBUILTINTABLE)
89 stdopdescriptor builtintable[] = {
90 { ICMD_LCMP, TYPE_LONG, TYPE_LONG, TYPE_INT, ICMD_BUILTIN2,
91 (functionptr) builtin_lcmp , SUPPORT_LONG && SUPPORT_LONG_CMP, false },
92 { ICMD_LAND, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
93 (functionptr) builtin_land , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
94 { ICMD_LOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
95 (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
96 { ICMD_LXOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
97 (functionptr) builtin_lxor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
98 { ICMD_LSHL, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
99 (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
100 { ICMD_LSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
101 (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
102 { ICMD_LUSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
103 (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
104 { ICMD_LADD, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
105 (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
106 { ICMD_LSUB, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
107 (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
108 { ICMD_LNEG, TYPE_LONG, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
109 (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, true },
110 { ICMD_LMUL, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
111 (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MUL, false },
112 { ICMD_I2F, TYPE_INT, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
113 (functionptr) builtin_i2f, SUPPORT_FLOAT && SUPPORT_IFCVT, true },
114 { ICMD_I2D, TYPE_INT, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
115 (functionptr) builtin_i2d, SUPPORT_DOUBLE && SUPPORT_IFCVT, true },
116 { ICMD_L2F, TYPE_LONG, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
117 (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
118 { ICMD_L2D, TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
119 (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
120 { ICMD_F2L, TYPE_FLOAT, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
121 (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
122 { ICMD_D2L, TYPE_DOUBLE, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
123 (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
124 { ICMD_F2I, TYPE_FLOAT, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
125 (functionptr) builtin_f2i, SUPPORT_FLOAT && SUPPORT_FICVT, true },
126 { ICMD_D2I, TYPE_DOUBLE, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
127 (functionptr) builtin_d2i, SUPPORT_DOUBLE && SUPPORT_FICVT, true },
128 { 255, 0, 0, 0, 0, NULL, true, false },
133 static int builtintablelen;
135 #endif /* USEBUILTINTABLE */
138 /*****************************************************************************
139 TABLE OF BUILTIN FUNCTIONS
141 This table lists the builtin functions which are used inside
144 The first part of the table (up to the 255-marker) lists the
145 opcodes which are automatically replaced in stack.c.
147 The second part lists the builtin functions which are "manually"
148 used for BUILTIN* opcodes in parse.c and stack.c.
150 *****************************************************************************/
152 builtin_descriptor builtin_desc[] = {
153 #if defined(USEBUILTINTABLE)
154 {ICMD_LCMP , BUILTIN_lcmp ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_INT ,
155 SUPPORT_LONG && SUPPORT_LONG_CMP,false,"lcmp"},
157 {ICMD_LAND , BUILTIN_land ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
158 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"land"},
159 {ICMD_LOR , BUILTIN_lor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
160 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lor"},
161 {ICMD_LXOR , BUILTIN_lxor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
162 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lxor"},
164 {ICMD_LSHL , BUILTIN_lshl ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
165 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshl"},
166 {ICMD_LSHR , BUILTIN_lshr ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
167 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshr"},
168 {ICMD_LUSHR, BUILTIN_lushr,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
169 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lushr"},
171 {ICMD_LADD , BUILTIN_ladd ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
172 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"ladd"},
173 {ICMD_LSUB , BUILTIN_lsub ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
174 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lsub"},
175 {ICMD_LNEG , BUILTIN_lneg ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
176 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lneg"},
177 {ICMD_LMUL , BUILTIN_lmul ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
178 SUPPORT_LONG && SUPPORT_LONG_MUL,false,"lmul"},
180 {ICMD_I2F , BUILTIN_i2f ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
181 SUPPORT_FLOAT && SUPPORT_IFCVT,true ,"i2f"},
182 {ICMD_I2D , BUILTIN_i2d ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
183 SUPPORT_DOUBLE && SUPPORT_IFCVT,true ,"i2d"},
184 {ICMD_L2F , BUILTIN_l2f ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
185 SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT,true ,"l2f"},
186 {ICMD_L2D , BUILTIN_l2d ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
187 SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT,true ,"l2d"},
188 {ICMD_F2L , BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
189 SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"f2l"},
190 {ICMD_D2L , BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
191 SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"d2l"},
192 {ICMD_F2I , BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
193 SUPPORT_FLOAT && SUPPORT_FICVT,true ,"f2i"},
194 {ICMD_D2I , BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
195 SUPPORT_DOUBLE && SUPPORT_FICVT,true ,"d2i"},
197 { ICMD_FADD , BUILTIN_fadd , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fadd" },
198 { ICMD_FSUB , BUILTIN_fsub , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fsub" },
199 { ICMD_FMUL , BUILTIN_fmul , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fmul" },
200 { ICMD_FDIV , BUILTIN_fdiv , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fdiv" },
201 { ICMD_FNEG , BUILTIN_fneg , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fneg" },
202 { ICMD_FCMPL, BUILTIN_fcmpl , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpl" },
203 { ICMD_FCMPG, BUILTIN_fcmpg , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpg" },
205 { ICMD_DADD , BUILTIN_dadd , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dadd" },
206 { ICMD_DSUB , BUILTIN_dsub , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dsub" },
207 { ICMD_DMUL , BUILTIN_dmul , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dmul" },
208 { ICMD_DDIV , BUILTIN_ddiv , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "ddiv" },
209 { ICMD_DNEG , BUILTIN_dneg , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dneg" },
210 { ICMD_DCMPL, BUILTIN_dcmpl , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpl" },
211 { ICMD_DCMPG, BUILTIN_dcmpg , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpg" },
213 { ICMD_F2D, BUILTIN_f2d , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "f2d" },
214 { ICMD_D2F, BUILTIN_d2f , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "d2f" },
217 /* this record marks the end of the automatically replaced opcodes */
218 {255,NULL,0,0,0,0,0,0,0,"<INVALID>"},
220 /* the following functions are not replaced automatically */
222 #if defined(__ALPHA__)
223 {255, BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"f2l"},
224 {255, BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"d2l"},
225 {255, BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"f2i"},
226 {255, BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"d2i"},
229 {255,BUILTIN_instanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"instanceof"},
230 {255,BUILTIN_arrayinstanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"arrayinstanceof"},
231 {255,BUILTIN_checkarraycast ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,0,0,"checkarraycast"},
232 {255,BUILTIN_aastore ,ICMD_BUILTIN3,TYPE_ADR ,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,0,0,"aastore"},
233 {255,BUILTIN_new ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"new"},
234 {255,BUILTIN_newarray ,ICMD_BUILTIN2,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray"},
235 {255,BUILTIN_newarray_boolean,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_boolean"},
236 {255,BUILTIN_newarray_char ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_char"},
237 {255,BUILTIN_newarray_float ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_float"},
238 {255,BUILTIN_newarray_double ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_double"},
239 {255,BUILTIN_newarray_byte ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_byte"},
240 {255,BUILTIN_newarray_short ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_short"},
241 {255,BUILTIN_newarray_int ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_int"},
242 {255,BUILTIN_newarray_long ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_long"},
243 #if defined(USE_THREADS)
244 {255,BUILTIN_monitorenter ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorenter"},
245 {255,BUILTIN_monitorexit ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorexit"},
247 #if !SUPPORT_DIVISION
248 {255,BUILTIN_idiv ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"idiv"},
249 {255,BUILTIN_irem ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"irem"},
251 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
252 {255,BUILTIN_ldiv ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"ldiv"},
253 {255,BUILTIN_lrem ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"lrem"},
255 {255,BUILTIN_frem ,ICMD_BUILTIN2,TYPE_FLOAT ,TYPE_FLOAT ,TYPE_VOID ,TYPE_FLOAT ,0,0,"frem"},
256 {255,BUILTIN_drem ,ICMD_BUILTIN2,TYPE_DOUBLE,TYPE_DOUBLE,TYPE_VOID ,TYPE_DOUBLE,0,0,"drem"},
259 #if defined(__X86_64__) || defined(__I386__)
260 /* assembler code patching functions */
262 { 255, PATCHER_builtin_new , ICMD_BUILTIN1, TYPE_ADR , TYPE_VOID , TYPE_VOID , TYPE_ADR , 0, 0, "new (calling patcher_builtin_new)" },
263 { 255, PATCHER_builtin_newarray , ICMD_BUILTIN1, TYPE_ADR , TYPE_VOID , TYPE_VOID , TYPE_ADR , 0, 0, "newarray (calling patcher_builtin_newarray)" },
264 { 255, PATCHER_builtin_checkarraycast , ICMD_BUILTIN2, TYPE_ADR , TYPE_ADR , TYPE_VOID , TYPE_VOID , 0, 0, "checkarraycast (calling patcher_builtin_checkarraycast)" },
265 { 255, PATCHER_builtin_arrayinstanceof, ICMD_BUILTIN2, TYPE_ADR , TYPE_ADR , TYPE_VOID , TYPE_INT , 0, 0, "arrayinstanceof (calling patcher_builtin_arrayinstanceof)" },
269 /* this record marks the end of the list */
271 { 0, NULL, 0, 0, 0, 0, 0, 0, 0, "<END>" }
275 #if defined(USEBUILTINTABLE)
277 static int stdopcompare(const void *a, const void *b)
279 builtin_descriptor *o1 = (builtin_descriptor *) a;
280 builtin_descriptor *o2 = (builtin_descriptor *) b;
281 if (!o1->supported && o2->supported)
283 if (o1->supported && !o2->supported)
285 return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
289 void sort_builtintable(void)
294 while (builtin_desc[len].opcode != 255) len++;
295 qsort(builtin_desc, len, sizeof(builtin_descriptor), stdopcompare);
297 for (--len; len>=0 && builtin_desc[len].supported; len--);
298 builtintablelen = ++len;
302 builtin_descriptor *find_builtin(int icmd)
304 builtin_descriptor *first = builtin_desc;
305 builtin_descriptor *last = builtin_desc + builtintablelen;
306 int len = last - first;
308 builtin_descriptor *middle;
312 middle = first + half;
313 if (middle->opcode < icmd) {
319 return first != last ? first : NULL;
322 #endif /* defined(USEBUILTINTABLE) */
325 /*****************************************************************************
327 *****************************************************************************/
331 /*************** internal function: builtin_isanysubclass *********************
333 Checks a subclass relation between two classes. Implemented interfaces
334 are interpreted as super classes.
335 Return value: 1 ... sub is subclass of super
338 *****************************************************************************/
339 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
342 castinfo classvalues;
347 if (super->flags & ACC_INTERFACE)
348 return (sub->vftbl->interfacetablelength > super->index) &&
349 (sub->vftbl->interfacetable[-super->index] != NULL);
351 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
353 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
354 (u4) classvalues.super_diffval;
360 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
364 castinfo classvalues;
369 asm_getclassvalues_atomic(super, sub, &classvalues);
371 if ((base = classvalues.super_baseval) <= 0)
372 /* super is an interface */
373 res = (sub->interfacetablelength > -base) &&
374 (sub->interfacetable[base] != NULL);
376 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
377 <= (u4) classvalues.super_diffval;
383 /****************** function: builtin_instanceof *****************************
385 Checks if an object is an instance of some given class (or subclass of
386 that class). If class is an interface, checks if the interface is
388 Return value: 1 ... obj is an instance of class or implements the interface
389 0 ... otherwise or if obj == NULL
391 *****************************************************************************/
393 /* XXX should use vftbl */
394 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
397 log_text ("builtin_instanceof called");
402 return builtin_isanysubclass(obj->vftbl->class, class);
407 /**************** function: builtin_checkcast *******************************
409 The same as builtin_instanceof except that 1 is returned when
412 ****************************************************************************/
414 /* XXX should use vftbl */
415 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
418 log_text("builtin_checkcast called");
423 if (builtin_isanysubclass(obj->vftbl->class, class))
427 printf("#### checkcast failed ");
428 utf_display(obj->vftbl->class->name);
430 utf_display(class->name);
438 /* builtin_descriptorscompatible ***********************************************
440 Checks if two array type descriptors are assignment compatible
442 Return value: 1 ... target = desc is possible
445 *******************************************************************************/
447 static s4 builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
452 if (desc->arraytype != target->arraytype)
455 if (desc->arraytype != ARRAYTYPE_OBJECT)
458 /* {both arrays are arrays of references} */
460 if (desc->dimension == target->dimension) {
461 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
462 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
463 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
465 if (desc->dimension < target->dimension) return 0;
467 /* {desc has higher dimension than target} */
468 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
472 /* builtin_checkarraycast ******************************************************
474 Checks if an object is really a subtype of the requested array
475 type. The object has to be an array to begin with. For simple
476 arrays (int, short, double, etc.) the types have to match exactly.
477 For arrays of objects, the type of elements in the array has to be
478 a subtype (or the same type) of the requested element type. For
479 arrays of arrays (which in turn can again be arrays of arrays), the
480 types at the lowest level have to satisfy the corresponding sub
483 *******************************************************************************/
485 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
487 arraydescriptor *desc;
492 if ((desc = o->vftbl->arraydesc) == NULL)
495 return builtin_descriptorscompatible(desc, target->arraydesc);
499 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
502 return builtin_checkarraycast(obj, target);
506 /************************** exception functions *******************************
508 ******************************************************************************/
510 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
513 char logtext[MAXLOGTEXT];
514 sprintf(logtext, "Builtin exception thrown: ");
517 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
519 utf_sprint_classname(logtext + strlen(logtext),
520 xptr->vftbl->class->name);
522 if (t->detailMessage) {
525 buf = javastring_tochar((java_objectheader *) t->detailMessage);
526 sprintf(logtext + strlen(logtext), ": %s", buf);
527 MFREE(buf, char, strlen(buf));
531 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
537 *exceptionptr = xptr;
544 /******************* function: builtin_canstore *******************************
546 Checks, if an object can be stored in an array.
547 Return value: 1 ... possible
550 ******************************************************************************/
552 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
554 arraydescriptor *desc;
555 arraydescriptor *valuedesc;
556 vftbl_t *componentvftbl;
560 castinfo classvalues;
564 /* The following is guaranteed (by verifier checks):
566 * *) a->...vftbl->arraydesc != NULL
567 * *) a->...vftbl->arraydesc->componentvftbl != NULL
568 * *) o->vftbl is not an interface vftbl
571 desc = a->header.objheader.vftbl->arraydesc;
572 componentvftbl = desc->componentvftbl;
573 valuevftbl = o->vftbl;
575 if ((dim_m1 = desc->dimension - 1) == 0) {
578 /* {a is a one-dimensional array} */
579 /* {a is an array of references} */
581 if (valuevftbl == componentvftbl)
584 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
586 if ((base = classvalues.super_baseval) <= 0)
587 /* an array of interface references */
588 return (valuevftbl->interfacetablelength > -base &&
589 valuevftbl->interfacetable[base] != NULL);
591 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
592 <= (unsigned) classvalues.super_diffval;
596 /* {a has dimension > 1} */
597 /* {componentvftbl->arraydesc != NULL} */
599 /* check if o is an array */
600 if ((valuedesc = valuevftbl->arraydesc) == NULL)
602 /* {o is an array} */
604 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
608 /* This is an optimized version where a is guaranteed to be one-dimensional */
609 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
611 arraydescriptor *desc;
612 vftbl_t *elementvftbl;
616 castinfo classvalues;
620 /* The following is guaranteed (by verifier checks):
622 * *) a->...vftbl->arraydesc != NULL
623 * *) a->...vftbl->arraydesc->elementvftbl != NULL
624 * *) a->...vftbl->arraydesc->dimension == 1
625 * *) o->vftbl is not an interface vftbl
628 desc = a->header.objheader.vftbl->arraydesc;
629 elementvftbl = desc->elementvftbl;
630 valuevftbl = o->vftbl;
632 /* {a is a one-dimensional array} */
634 if (valuevftbl == elementvftbl)
637 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
639 if ((base = classvalues.super_baseval) <= 0)
640 /* an array of interface references */
641 return (valuevftbl->interfacetablelength > -base &&
642 valuevftbl->interfacetable[base] != NULL);
644 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
645 <= (unsigned) classvalues.super_diffval;
651 /* This is an optimized version where a is guaranteed to be a
652 * one-dimensional array of a class type */
653 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
655 vftbl_t *elementvftbl;
658 castinfo classvalues;
662 /* The following is guaranteed (by verifier checks):
664 * *) a->...vftbl->arraydesc != NULL
665 * *) a->...vftbl->arraydesc->elementvftbl != NULL
666 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
667 * *) a->...vftbl->arraydesc->dimension == 1
668 * *) o->vftbl is not an interface vftbl
671 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
672 valuevftbl = o->vftbl;
674 /* {a is a one-dimensional array} */
676 if (valuevftbl == elementvftbl)
679 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
681 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
682 <= (unsigned) classvalues.super_diffval;
688 /* builtin_new *****************************************************************
690 Creates a new instance of class c on the heap.
692 Return value: pointer to the object or NULL if no memory is
695 *******************************************************************************/
697 java_objectheader *builtin_new(classinfo *c)
699 java_objectheader *o;
701 /* is the class loaded */
702 /*utf_fprint(stderr,c->name);fprintf(stderr,"\n");*/
705 /* is the class linked */
710 if (!c->initialized) {
712 log_message_class("Initialize class (from builtin_new): ", c);
714 if (!initialize_class(c))
718 o = heap_allocate(c->instancesize, true, c->finalizer);
723 MSET(o, 0, u1, c->instancesize);
727 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
735 /* builtin_newarray ************************************************************
737 Creates an array with the given vftbl on the heap.
739 Return value: pointer to the array or NULL if no memory is available
741 CAUTION: The given vftbl must be the vftbl of the *array* class,
742 not of the element class.
744 *******************************************************************************/
746 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
749 arraydescriptor *desc;
754 desc = arrayvftbl->arraydesc;
755 dataoffset = desc->dataoffset;
756 componentsize = desc->componentsize;
759 *exceptionptr = new_negativearraysizeexception();
763 actualsize = dataoffset + size * componentsize;
765 if (((u4) actualsize) < ((u4) size)) { /* overflow */
766 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
770 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
775 MSET(a, 0, u1, actualsize);
777 a->objheader.vftbl = arrayvftbl;
779 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
780 initObjectLock(&a->objheader);
789 /* builtin_anewarray ***********************************************************
791 Creates an array of references to the given class type on the heap.
793 Return value: pointer to the array or NULL if no memory is
796 *******************************************************************************/
798 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
802 /* is class loaded */
803 assert(component->loaded);
805 /* is class linked */
806 if (!component->linked)
807 if (!link_class(component))
810 c = class_array_of(component, true);
815 return (java_objectarray *) builtin_newarray(size, c->vftbl);
819 /* builtin_newarray_int ********************************************************
821 Creates an array of 32 bit Integers on the heap.
823 Return value: pointer to the array or NULL if no memory is
826 *******************************************************************************/
828 java_intarray *builtin_newarray_int(s4 size)
830 return (java_intarray *)
831 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
835 /* builtin_newarray_long *******************************************************
837 Creates an array of 64 bit Integers on the heap.
839 Return value: pointer to the array or NULL if no memory is
842 *******************************************************************************/
844 java_longarray *builtin_newarray_long(s4 size)
846 return (java_longarray *)
847 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
851 /* builtin_newarray_float ******************************************************
853 Creates an array of 32 bit IEEE floats on the heap.
855 Return value: pointer to the array or NULL if no memory is
858 *******************************************************************************/
860 java_floatarray *builtin_newarray_float(s4 size)
862 return (java_floatarray *)
863 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
867 /* builtin_newarray_double *****************************************************
869 Creates an array of 64 bit IEEE floats on the heap.
871 Return value: pointer to the array or NULL if no memory is
874 *******************************************************************************/
876 java_doublearray *builtin_newarray_double(s4 size)
878 return (java_doublearray *)
879 builtin_newarray(size,
880 primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
884 /* builtin_newarray_byte *******************************************************
886 Creates an array of 8 bit Integers on the heap.
888 Return value: pointer to the array or NULL if no memory is
891 *******************************************************************************/
893 java_bytearray *builtin_newarray_byte(s4 size)
895 return (java_bytearray *)
896 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
900 /* builtin_newarray_char *******************************************************
902 Creates an array of characters on the heap.
904 Return value: pointer to the array or NULL if no memory is
907 *******************************************************************************/
909 java_chararray *builtin_newarray_char(s4 size)
911 return (java_chararray *)
912 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
916 /* builtin_newarray_short ******************************************************
918 Creates an array of 16 bit Integers on the heap.
920 Return value: pointer to the array or NULL if no memory is
923 *******************************************************************************/
925 java_shortarray *builtin_newarray_short(s4 size)
927 return (java_shortarray *)
928 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
932 /* builtin_newarray_boolean ****************************************************
934 Creates an array of bytes on the heap. The array is designated as
935 an array of booleans (important for casts)
937 Return value: pointer to the array or NULL if no memory is
940 *******************************************************************************/
942 java_booleanarray *builtin_newarray_boolean(s4 size)
944 return (java_booleanarray *)
945 builtin_newarray(size,
946 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
950 /* builtin_multianewarray ******************************************************
952 Creates a multi-dimensional array on the heap. The dimensions are
953 passed in an array of longs.
956 n............number of dimensions to create
957 arrayvftbl...vftbl of the array class
958 dims.........array containing the size of each dimension to create
960 Return value: pointer to the array or NULL if no memory is
963 ******************************************************************************/
965 java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims)
969 vftbl_t *componentvftbl;
971 /* create this dimension */
974 a = builtin_newarray(size, arrayvftbl);
979 /* if this is the last dimension return */
984 /* get the vftbl of the components to create */
986 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
988 /* The verifier guarantees this. */
989 /* if (!componentvftbl) */
990 /* panic ("multianewarray with too many dimensions"); */
992 /* create the component arrays */
994 for (i = 0; i < size; i++) {
995 java_arrayheader *ea =
996 builtin_multianewarray(n, componentvftbl, dims + 1);
1001 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1008 /*****************************************************************************
1011 Various functions for printing a message at method entry or exit (for
1014 *****************************************************************************/
1016 u4 methodindent = 0;
1018 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1024 char logtext[MAXLOGTEXT];
1030 log_text("WARNING: unmatched methodindent--");
1032 if (opt_verbose || runverbose || verboseexception) {
1034 sprintf(logtext,"Exception ");
1035 utf_sprint_classname(logtext+strlen(logtext), xptr->vftbl->class->name);
1038 sprintf(logtext,"Some Throwable");
1040 sprintf(logtext+strlen(logtext), " thrown in ");
1043 utf_sprint_classname(logtext+strlen(logtext), m->class->name);
1044 sprintf(logtext+strlen(logtext), ".");
1045 utf_sprint(logtext+strlen(logtext), m->name);
1046 if (m->flags & ACC_SYNCHRONIZED) {
1047 sprintf(logtext+strlen(logtext), "(SYNC");
1050 sprintf(logtext+strlen(logtext), "(NOSYNC");
1053 if (m->flags & ACC_NATIVE) {
1054 sprintf(logtext+strlen(logtext), ",NATIVE");
1055 #if POINTERSIZE == 8
1056 sprintf(logtext+strlen(logtext), ")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1058 sprintf(logtext+strlen(logtext), ")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1062 #if POINTERSIZE == 8
1063 sprintf(logtext+strlen(logtext), ")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1065 sprintf(logtext+strlen(logtext), ")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1067 if (m->class->sourcefile == NULL) {
1068 sprintf(logtext+strlen(logtext), "<NO CLASSFILE INFORMATION>");
1071 utf_sprint(logtext+strlen(logtext), m->class->sourcefile);
1073 sprintf(logtext+strlen(logtext), ":%d)\n", line);
1077 sprintf(logtext+strlen(logtext), "call_java_method\n");
1086 #ifdef TRACE_ARGS_NUM
1087 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1088 #if TRACE_ARGS_NUM >= 6
1091 #if TRACE_ARGS_NUM == 8
1097 char logtext[MAXLOGTEXT];
1098 for (i = 0; i < methodindent; i++)
1100 if (methodindent == 0)
1101 sprintf(logtext + methodindent, "1st_call: ");
1103 sprintf(logtext + methodindent, "called: ");
1105 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1106 sprintf(logtext + strlen(logtext), ".");
1107 utf_sprint(logtext + strlen(logtext), m->name);
1108 utf_sprint(logtext + strlen(logtext), m->descriptor);
1110 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1111 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1112 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1113 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1114 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1115 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1116 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1117 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1118 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1119 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1120 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1123 sprintf(logtext + strlen(logtext), "(");
1125 switch (m->paramcount) {
1129 #if defined(__I386__) || defined(__POWERPC__)
1131 sprintf(logtext+strlen(logtext), "%llx", a0);
1135 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1139 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1143 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1147 #if TRACE_ARGS_NUM >= 6
1149 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1150 a0, a1, a2, a3, a4);
1154 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1155 a0, a1, a2, a3, a4, a5);
1157 #endif /* TRACE_ARGS_NUM >= 6 */
1159 #if TRACE_ARGS_NUM == 8
1161 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1162 a0, a1, a2, a3, a4, a5, a6);
1166 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1167 a0, a1, a2, a3, a4, a5, a6, a7);
1171 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1172 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1174 #else /* TRACE_ARGS_NUM == 8 */
1176 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1177 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1179 #endif /* TRACE_ARGS_NUM == 8 */
1180 #else /* defined(__I386__) || defined(__POWERPC__) */
1182 sprintf(logtext+strlen(logtext), "%lx", a0);
1186 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1190 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1194 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1198 #if TRACE_ARGS_NUM >= 6
1200 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1201 a0, a1, a2, a3, a4);
1205 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1206 a0, a1, a2, a3, a4, a5);
1208 #endif /* TRACE_ARGS_NUM >= 6 */
1210 #if TRACE_ARGS_NUM == 8
1212 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1213 a0, a1, a2, a3, a4, a5, a6);
1217 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1218 a0, a1, a2, a3, a4, a5, a6, a7);
1220 #endif /* TRACE_ARGS_NUM == 8 */
1223 #if TRACE_ARGS_NUM == 4
1224 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1225 a0, a1, a2, a3, m->paramcount - 4);
1227 #elif TRACE_ARGS_NUM == 6
1228 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1229 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1231 #elif TRACE_ARGS_NUM == 8
1232 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1233 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1236 #endif /* defined(__I386__) || defined(__POWERPC__) */
1239 sprintf(logtext + strlen(logtext), ")");
1247 void builtin_displaymethodstart(methodinfo *m)
1249 char logtext[MAXLOGTEXT];
1250 sprintf(logtext, " ");
1251 sprintf(logtext + methodindent, "called: ");
1252 utf_sprint(logtext + strlen(logtext), m->class->name);
1253 sprintf(logtext + strlen(logtext), ".");
1254 utf_sprint(logtext + strlen(logtext), m->name);
1255 utf_sprint(logtext + strlen(logtext), m->descriptor);
1257 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1258 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1259 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1260 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1261 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1262 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1263 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1264 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1265 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1266 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1267 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1274 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1277 char logtext[MAXLOGTEXT];
1278 for (i = 0; i < methodindent; i++)
1283 log_text("WARNING: unmatched methodindent--");
1285 sprintf(logtext + methodindent, "finished: ");
1286 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1287 sprintf(logtext + strlen(logtext), ".");
1288 utf_sprint(logtext + strlen(logtext), m->name);
1289 utf_sprint(logtext + strlen(logtext), m->descriptor);
1291 switch (m->returntype) {
1293 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1297 #if defined(__I386__) || defined(__POWERPC__)
1298 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1300 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1305 #if defined(__I386__) || defined(__POWERPC__)
1306 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1308 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1313 sprintf(logtext + strlen(logtext), "->%g", f);
1317 sprintf(logtext + strlen(logtext), "->%g", d);
1324 /****************************************************************************
1325 SYNCHRONIZATION FUNCTIONS
1326 *****************************************************************************/
1328 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1330 * Lock the mutex of an object.
1332 void internal_lock_mutex_for_object(java_objectheader *object)
1334 mutexHashEntry *entry;
1337 assert(object != 0);
1339 hashValue = MUTEX_HASH_VALUE(object);
1340 entry = &mutexHashTable[hashValue];
1342 if (entry->object != 0) {
1343 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1345 entry->mutex.holder = 0;
1346 entry->mutex.count = 0;
1347 entry->mutex.muxWaiters = 0;
1350 while (entry->next != 0 && entry->object != object)
1351 entry = entry->next;
1353 if (entry->object != object) {
1354 entry->next = firstFreeOverflowEntry;
1355 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1357 entry = entry->next;
1360 assert(entry->conditionCount == 0);
1365 entry->mutex.holder = 0;
1366 entry->mutex.count = 0;
1367 entry->mutex.muxWaiters = 0;
1370 if (entry->object == 0)
1371 entry->object = object;
1373 internal_lock_mutex(&entry->mutex);
1378 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1380 * Unlocks the mutex of an object.
1382 void internal_unlock_mutex_for_object (java_objectheader *object)
1385 mutexHashEntry *entry;
1387 hashValue = MUTEX_HASH_VALUE(object);
1388 entry = &mutexHashTable[hashValue];
1390 if (entry->object == object) {
1391 internal_unlock_mutex(&entry->mutex);
1394 while (entry->next != 0 && entry->next->object != object)
1395 entry = entry->next;
1397 assert(entry->next != 0);
1399 internal_unlock_mutex(&entry->next->mutex);
1401 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1402 mutexHashEntry *unlinked = entry->next;
1404 entry->next = unlinked->next;
1405 unlinked->next = firstFreeOverflowEntry;
1406 firstFreeOverflowEntry = unlinked;
1413 #if defined(USE_THREADS)
1414 void builtin_monitorenter(java_objectheader *o)
1416 #if !defined(NATIVE_THREADS)
1421 hashValue = MUTEX_HASH_VALUE(o);
1422 if (mutexHashTable[hashValue].object == o
1423 && mutexHashTable[hashValue].mutex.holder == currentThread)
1424 ++mutexHashTable[hashValue].mutex.count;
1426 internal_lock_mutex_for_object(o);
1430 monitorEnter((threadobject *) THREADOBJECT, o);
1436 #if defined(USE_THREADS)
1438 * Locks the class object - needed for static synchronized methods.
1439 * The use_class_as_object call is needed in order to circumvent a
1440 * possible deadlock with builtin_monitorenter called by another
1441 * thread calling use_class_as_object.
1443 void builtin_staticmonitorenter(classinfo *c)
1445 use_class_as_object(c);
1446 builtin_monitorenter(&c->header);
1451 #if defined(USE_THREADS)
1452 void builtin_monitorexit(java_objectheader *o)
1454 #if !defined(NATIVE_THREADS)
1459 hashValue = MUTEX_HASH_VALUE(o);
1460 if (mutexHashTable[hashValue].object == o) {
1461 if (mutexHashTable[hashValue].mutex.count == 1
1462 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1463 internal_unlock_mutex_for_object(o);
1465 --mutexHashTable[hashValue].mutex.count;
1468 internal_unlock_mutex_for_object(o);
1472 monitorExit((threadobject *) THREADOBJECT, o);
1478 /*****************************************************************************
1479 MISCELLANEOUS HELPER FUNCTIONS
1480 *****************************************************************************/
1484 /*********** Functions for integer divisions *****************************
1486 On some systems (eg. DEC ALPHA), integer division is not supported by the
1487 CPU. These helper functions implement the missing functionality.
1489 ******************************************************************************/
1491 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1492 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1495 /************** Functions for long arithmetics *******************************
1497 On systems where 64 bit Integers are not supported by the CPU, these
1498 functions are needed.
1500 ******************************************************************************/
1503 s8 builtin_ladd(s8 a, s8 b)
1508 return builtin_i2l(0);
1512 s8 builtin_lsub(s8 a, s8 b)
1517 return builtin_i2l(0);
1521 s8 builtin_lmul(s8 a, s8 b)
1526 return builtin_i2l(0);
1530 s8 builtin_ldiv(s8 a, s8 b)
1535 return builtin_i2l(0);
1539 s8 builtin_lrem(s8 a, s8 b)
1544 return builtin_i2l(0);
1548 s8 builtin_lshl(s8 a, s4 b)
1551 return a << (b & 63);
1553 return builtin_i2l(0);
1557 s8 builtin_lshr(s8 a, s4 b)
1560 return a >> (b & 63);
1562 return builtin_i2l(0);
1566 s8 builtin_lushr(s8 a, s4 b)
1569 return ((u8) a) >> (b & 63);
1571 return builtin_i2l(0);
1575 s8 builtin_land(s8 a, s8 b)
1580 return builtin_i2l(0);
1584 s8 builtin_lor(s8 a, s8 b)
1589 return builtin_i2l(0);
1593 s8 builtin_lxor(s8 a, s8 b)
1598 return builtin_i2l(0);
1602 s8 builtin_lneg(s8 a)
1607 return builtin_i2l(0);
1611 s4 builtin_lcmp(s8 a, s8 b)
1614 if (a < b) return -1;
1615 if (a > b) return 1;
1626 /*********** Functions for floating point operations *************************/
1628 float builtin_fadd(float a, float b)
1630 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1631 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1642 if (copysignf(1.0, a) == copysignf(1.0, b))
1645 return intBitsToFloat(FLT_NAN);
1651 float builtin_fsub(float a, float b)
1653 return builtin_fadd(a, builtin_fneg(b));
1657 float builtin_fmul(float a, float b)
1659 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1660 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1662 if (finitef(b)) return a * b;
1664 if (a == 0) return intBitsToFloat(FLT_NAN);
1665 else return copysignf(b, copysignf(1.0, b)*a);
1670 if (b == 0) return intBitsToFloat(FLT_NAN);
1671 else return copysignf(a, copysignf(1.0, a)*b);
1674 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1680 float builtin_fdiv(float a, float b)
1682 if (finitef(a) && finitef(b)) {
1687 return intBitsToFloat(FLT_POSINF);
1689 return intBitsToFloat(FLT_NEGINF);
1692 return intBitsToFloat(FLT_NAN);
1696 float builtin_frem(float a, float b)
1702 float builtin_fneg(float a)
1704 if (isnanf(a)) return a;
1706 if (finitef(a)) return -a;
1707 else return copysignf(a, -copysignf(1.0, a));
1712 s4 builtin_fcmpl(float a, float b)
1714 if (isnanf(a)) return -1;
1715 if (isnanf(b)) return -1;
1716 if (!finitef(a) || !finitef(b)) {
1717 a = finitef(a) ? 0 : copysignf(1.0, a);
1718 b = finitef(b) ? 0 : copysignf(1.0, b);
1720 if (a > b) return 1;
1721 if (a == b) return 0;
1726 s4 builtin_fcmpg(float a, float b)
1728 if (isnanf(a)) return 1;
1729 if (isnanf(b)) return 1;
1730 if (!finitef(a) || !finitef(b)) {
1731 a = finitef(a) ? 0 : copysignf(1.0, a);
1732 b = finitef(b) ? 0 : copysignf(1.0, b);
1734 if (a > b) return 1;
1735 if (a == b) return 0;
1741 /************************* Functions for doubles ****************************/
1743 double builtin_dadd(double a, double b)
1745 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1746 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1748 if (finite(b)) return a + b;
1752 if (finite(b)) return a;
1754 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1755 else return longBitsToDouble(DBL_NAN);
1761 double builtin_dsub(double a, double b)
1763 return builtin_dadd(a, builtin_dneg(b));
1767 double builtin_dmul(double a, double b)
1769 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1770 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1772 if (finite(b)) return a * b;
1774 if (a == 0) return longBitsToDouble(DBL_NAN);
1775 else return copysign(b, copysign(1.0, b) * a);
1780 if (b == 0) return longBitsToDouble(DBL_NAN);
1781 else return copysign(a, copysign(1.0, a) * b);
1784 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1790 double builtin_ddiv(double a, double b)
1798 return longBitsToDouble(DBL_NAN);
1800 return copysign(0.0, b);
1806 return longBitsToDouble(DBL_POSINF);
1808 return longBitsToDouble(DBL_NEGINF);
1811 return longBitsToDouble(DBL_NAN);
1814 /* if (finite(a) && finite(b)) { */
1819 /* return longBitsToDouble(DBL_POSINF); */
1820 /* else if (a < 0) */
1821 /* return longBitsToDouble(DBL_NEGINF); */
1825 /* keep compiler happy */
1830 double builtin_drem(double a, double b)
1836 double builtin_dneg(double a)
1838 if (isnan(a)) return a;
1840 if (finite(a)) return -a;
1841 else return copysign(a, -copysign(1.0, a));
1846 s4 builtin_dcmpl(double a, double b)
1848 if (isnan(a)) return -1;
1849 if (isnan(b)) return -1;
1850 if (!finite(a) || !finite(b)) {
1851 a = finite(a) ? 0 : copysign(1.0, a);
1852 b = finite(b) ? 0 : copysign(1.0, b);
1854 if (a > b) return 1;
1855 if (a == b) return 0;
1860 s4 builtin_dcmpg(double a, double b)
1862 if (isnan(a)) return 1;
1863 if (isnan(b)) return 1;
1864 if (!finite(a) || !finite(b)) {
1865 a = finite(a) ? 0 : copysign(1.0, a);
1866 b = finite(b) ? 0 : copysign(1.0, b);
1868 if (a > b) return 1;
1869 if (a == b) return 0;
1874 /*********************** Conversion operations ****************************/
1876 s8 builtin_i2l(s4 i)
1889 float builtin_i2f(s4 a)
1891 float f = (float) a;
1896 double builtin_i2d(s4 a)
1898 double d = (double) a;
1903 s4 builtin_l2i(s8 l)
1913 float builtin_l2f(s8 a)
1916 float f = (float) a;
1924 double builtin_l2d(s8 a)
1927 double d = (double) a;
1935 s4 builtin_f2i(float a)
1938 return builtin_d2i((double) a);
1947 if (a < (-2147483648))
1948 return (-2147483648);
1951 f = copysignf((float) 1.0, a);
1954 return (-2147483648); */
1958 s8 builtin_f2l(float a)
1961 return builtin_d2l((double) a);
1966 if (a > 9223372036854775807L)
1967 return 9223372036854775807L;
1968 if (a < (-9223372036854775808L))
1969 return (-9223372036854775808L);
1974 f = copysignf((float) 1.0, a);
1976 return 9223372036854775807L;
1977 return (-9223372036854775808L); */
1981 double builtin_f2d(float a)
1983 if (finitef(a)) return (double) a;
1986 return longBitsToDouble(DBL_NAN);
1988 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1993 s4 builtin_d2i(double a)
1998 if (a >= 2147483647)
2000 if (a <= (-2147483647-1))
2001 return (-2147483647-1);
2006 d = copysign(1.0, a);
2009 return (-2147483647-1);
2013 s8 builtin_d2l(double a)
2018 if (a >= 9223372036854775807LL)
2019 return 9223372036854775807LL;
2020 if (a <= (-9223372036854775807LL-1))
2021 return (-9223372036854775807LL-1);
2026 d = copysign(1.0, a);
2028 return 9223372036854775807LL;
2029 return (-9223372036854775807LL-1);
2033 float builtin_d2f(double a)
2039 return intBitsToFloat(FLT_NAN);
2041 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2046 /* used to convert FLT_xxx defines into float values */
2048 inline float intBitsToFloat(s4 i)
2057 /* used to convert DBL_xxx defines into double values */
2059 inline float longBitsToDouble(s8 l)
2068 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2070 return (java_arrayheader *)
2071 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2077 panic("Internal error: builtin_dummy called (native function is missing)");
2078 return 0; /* for the compiler */
2082 /* builtin_asm_get_exceptionptrptr *********************************************
2084 this is a wrapper for calls from asmpart
2086 *******************************************************************************/
2088 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2089 java_objectheader **builtin_asm_get_exceptionptrptr()
2091 return builtin_get_exceptionptrptr();
2096 methodinfo *builtin_asm_get_threadrootmethod()
2098 return *threadrootmethod;
2102 inline void* builtin_asm_get_stackframeinfo()
2104 /*log_text("builtin_asm_get_stackframeinfo()");*/
2105 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2106 /*printf("stackframeinfo: %p,%p\n",&THREADINFO->_stackframeinfo,*(&THREADINFO->_stackframeinfo));*/
2107 return &THREADINFO->_stackframeinfo;
2109 #if defined(__GNUC__)
2110 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2112 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2116 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2117 /* stacktraceelement *el;*/
2120 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2121 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2123 *el=MNEW(stacktraceelement,s+1); /*GC*/
2125 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2127 #if defined(__GNUC__)
2128 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2130 (*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 */
2135 * These are local overrides for various environment variables in Emacs.
2136 * Please do not remove this and leave it at the end of the file, where
2137 * Emacs will automagically detect them.
2138 * ---------------------------------------------------------------------
2141 * indent-tabs-mode: t