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 2358 2005-04-22 22:01:51Z jowenn $
53 #include "mm/memory.h"
54 #include "native/native.h"
55 #include "native/include/java_lang_Cloneable.h"
56 #include "native/include/java_lang_VMObject.h"
58 #if defined(USE_THREADS)
59 # if defined(NATIVE_THREADS)
60 # include "threads/native/threads.h"
62 # include "threads/green/threads.h"
63 # include "threads/green/locks.h"
67 #include "toolbox/logging.h"
68 #include "vm/builtin.h"
69 #include "vm/exceptions.h"
70 #include "vm/global.h"
71 #include "vm/initialize.h"
72 #include "vm/loader.h"
73 #include "vm/options.h"
74 #include "vm/stringlocal.h"
75 #include "vm/tables.h"
76 #include "vm/jit/asmpart.h"
79 #undef DEBUG /*define DEBUG 1*/
81 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
82 THREADSPECIFIC void *_thread_nativestackframeinfo = NULL;
85 #if defined(USEBUILTINTABLE)
88 stdopdescriptor builtintable[] = {
89 { ICMD_LCMP, TYPE_LONG, TYPE_LONG, TYPE_INT, ICMD_BUILTIN2,
90 (functionptr) builtin_lcmp , SUPPORT_LONG && SUPPORT_LONG_CMP, false },
91 { ICMD_LAND, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
92 (functionptr) builtin_land , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
93 { ICMD_LOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
94 (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
95 { ICMD_LXOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
96 (functionptr) builtin_lxor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
97 { ICMD_LSHL, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
98 (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
99 { ICMD_LSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
100 (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
101 { ICMD_LUSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
102 (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
103 { ICMD_LADD, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
104 (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
105 { ICMD_LSUB, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
106 (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
107 { ICMD_LNEG, TYPE_LONG, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
108 (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, true },
109 { ICMD_LMUL, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
110 (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MUL, false },
111 { ICMD_I2F, TYPE_INT, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
112 (functionptr) builtin_i2f, SUPPORT_FLOAT && SUPPORT_IFCVT, true },
113 { ICMD_I2D, TYPE_INT, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
114 (functionptr) builtin_i2d, SUPPORT_DOUBLE && SUPPORT_IFCVT, true },
115 { ICMD_L2F, TYPE_LONG, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
116 (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
117 { ICMD_L2D, TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
118 (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
119 { ICMD_F2L, TYPE_FLOAT, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
120 (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
121 { ICMD_D2L, TYPE_DOUBLE, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
122 (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
123 { ICMD_F2I, TYPE_FLOAT, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
124 (functionptr) builtin_f2i, SUPPORT_FLOAT && SUPPORT_FICVT, true },
125 { ICMD_D2I, TYPE_DOUBLE, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
126 (functionptr) builtin_d2i, SUPPORT_DOUBLE && SUPPORT_FICVT, true },
127 { 255, 0, 0, 0, 0, NULL, true, false },
132 static int builtintablelen;
134 #endif /* USEBUILTINTABLE */
137 /*****************************************************************************
138 TABLE OF BUILTIN FUNCTIONS
140 This table lists the builtin functions which are used inside
143 The first part of the table (up to the 255-marker) lists the
144 opcodes which are automatically replaced in stack.c.
146 The second part lists the builtin functions which are "manually"
147 used for BUILTIN* opcodes in parse.c and stack.c.
149 *****************************************************************************/
151 builtin_descriptor builtin_desc[] = {
152 #if defined(USEBUILTINTABLE)
153 {ICMD_LCMP , BUILTIN_lcmp ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_INT ,
154 SUPPORT_LONG && SUPPORT_LONG_CMP,false,"lcmp"},
156 {ICMD_LAND , BUILTIN_land ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
157 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"land"},
158 {ICMD_LOR , BUILTIN_lor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
159 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lor"},
160 {ICMD_LXOR , BUILTIN_lxor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
161 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lxor"},
163 {ICMD_LSHL , BUILTIN_lshl ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
164 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshl"},
165 {ICMD_LSHR , BUILTIN_lshr ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
166 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshr"},
167 {ICMD_LUSHR, BUILTIN_lushr,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
168 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lushr"},
170 {ICMD_LADD , BUILTIN_ladd ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
171 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"ladd"},
172 {ICMD_LSUB , BUILTIN_lsub ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
173 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lsub"},
174 {ICMD_LNEG , BUILTIN_lneg ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
175 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lneg"},
176 {ICMD_LMUL , BUILTIN_lmul ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
177 SUPPORT_LONG && SUPPORT_LONG_MUL,false,"lmul"},
179 {ICMD_I2F , BUILTIN_i2f ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
180 SUPPORT_FLOAT && SUPPORT_IFCVT,true ,"i2f"},
181 {ICMD_I2D , BUILTIN_i2d ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
182 SUPPORT_DOUBLE && SUPPORT_IFCVT,true ,"i2d"},
183 {ICMD_L2F , BUILTIN_l2f ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
184 SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT,true ,"l2f"},
185 {ICMD_L2D , BUILTIN_l2d ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
186 SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT,true ,"l2d"},
187 {ICMD_F2L , BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
188 SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"f2l"},
189 {ICMD_D2L , BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
190 SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"d2l"},
191 {ICMD_F2I , BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
192 SUPPORT_FLOAT && SUPPORT_FICVT,true ,"f2i"},
193 {ICMD_D2I , BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
194 SUPPORT_DOUBLE && SUPPORT_FICVT,true ,"d2i"},
196 { ICMD_FADD , BUILTIN_fadd , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fadd" },
197 { ICMD_FSUB , BUILTIN_fsub , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fsub" },
198 { ICMD_FMUL , BUILTIN_fmul , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fmul" },
199 { ICMD_FDIV , BUILTIN_fdiv , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fdiv" },
200 { ICMD_FNEG , BUILTIN_fneg , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fneg" },
201 { ICMD_FCMPL, BUILTIN_fcmpl , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpl" },
202 { ICMD_FCMPG, BUILTIN_fcmpg , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpg" },
204 { ICMD_DADD , BUILTIN_dadd , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dadd" },
205 { ICMD_DSUB , BUILTIN_dsub , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dsub" },
206 { ICMD_DMUL , BUILTIN_dmul , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dmul" },
207 { ICMD_DDIV , BUILTIN_ddiv , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "ddiv" },
208 { ICMD_DNEG , BUILTIN_dneg , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dneg" },
209 { ICMD_DCMPL, BUILTIN_dcmpl , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpl" },
210 { ICMD_DCMPG, BUILTIN_dcmpg , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpg" },
212 { ICMD_F2D, BUILTIN_f2d , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "f2d" },
213 { ICMD_D2F, BUILTIN_d2f , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "d2f" },
216 /* this record marks the end of the automatically replaced opcodes */
217 {255,NULL,0,0,0,0,0,0,0,"<INVALID>"},
219 /* the following functions are not replaced automatically */
221 #if defined(__ALPHA__)
222 {255, BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"f2l"},
223 {255, BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"d2l"},
224 {255, BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"f2i"},
225 {255, BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"d2i"},
228 {255,BUILTIN_instanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"instanceof"},
229 {255,BUILTIN_arrayinstanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"arrayinstanceof"},
230 {255,BUILTIN_checkarraycast ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,0,0,"checkarraycast"},
231 {255,BUILTIN_aastore ,ICMD_BUILTIN3,TYPE_ADR ,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,0,0,"aastore"},
232 {255,BUILTIN_new ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"new"},
233 {255,BUILTIN_newarray ,ICMD_BUILTIN2,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray"},
234 {255,BUILTIN_newarray_boolean,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_boolean"},
235 {255,BUILTIN_newarray_char ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_char"},
236 {255,BUILTIN_newarray_float ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_float"},
237 {255,BUILTIN_newarray_double ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_double"},
238 {255,BUILTIN_newarray_byte ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_byte"},
239 {255,BUILTIN_newarray_short ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_short"},
240 {255,BUILTIN_newarray_int ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_int"},
241 {255,BUILTIN_newarray_long ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_long"},
242 #if defined(USE_THREADS)
243 {255,BUILTIN_monitorenter ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorenter"},
244 {255,BUILTIN_monitorexit ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorexit"},
246 #if !SUPPORT_DIVISION
247 {255,BUILTIN_idiv ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"idiv"},
248 {255,BUILTIN_irem ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"irem"},
250 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
251 {255,BUILTIN_ldiv ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"ldiv"},
252 {255,BUILTIN_lrem ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"lrem"},
254 {255,BUILTIN_frem ,ICMD_BUILTIN2,TYPE_FLOAT ,TYPE_FLOAT ,TYPE_VOID ,TYPE_FLOAT ,0,0,"frem"},
255 {255,BUILTIN_drem ,ICMD_BUILTIN2,TYPE_DOUBLE,TYPE_DOUBLE,TYPE_VOID ,TYPE_DOUBLE,0,0,"drem"},
258 #if defined(__X86_64__) || defined(__I386__)
259 /* assembler code patching functions */
261 { 255, asm_wrapper_patcher_BUILTIN_new , ICMD_BUILTIN1, TYPE_ADR , TYPE_VOID , TYPE_VOID , TYPE_ADR , 0, 0, "new (calling asm_wrapper_patcher_builtin_new)" },
263 #if defined(__X86_64__)
264 { 255, asm_wrapper_patcher_BUILTIN_newarray , ICMD_BUILTIN1, TYPE_ADR , TYPE_VOID , TYPE_VOID , TYPE_ADR , 0, 0, "newarray (calling asm_wrapper_patcher_builtin_newarray)" },
265 { 255, asm_wrapper_patcher_BUILTIN_checkarraycast , ICMD_BUILTIN2, TYPE_ADR , TYPE_ADR , TYPE_VOID , TYPE_VOID , 0, 0, "checkarraycast (calling asm_wrapper_patcher_builtin_checkarraycast)" },
266 { 255, asm_wrapper_patcher_BUILTIN_arrayinstanceof, ICMD_BUILTIN2, TYPE_ADR , TYPE_ADR , TYPE_VOID , TYPE_INT , 0, 0, "arrayinstanceof (calling asm_wrapper_patcher_builtin_arrayinstanceof)" },
270 /* this record marks the end of the list */
272 { 0, NULL, 0, 0, 0, 0, 0, 0, 0, "<END>" }
276 #if defined(USEBUILTINTABLE)
278 static int stdopcompare(const void *a, const void *b)
280 builtin_descriptor *o1 = (builtin_descriptor *) a;
281 builtin_descriptor *o2 = (builtin_descriptor *) b;
282 if (!o1->supported && o2->supported)
284 if (o1->supported && !o2->supported)
286 return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
290 void sort_builtintable(void)
295 while (builtin_desc[len].opcode != 255) len++;
296 qsort(builtin_desc, len, sizeof(builtin_descriptor), stdopcompare);
298 for (--len; len>=0 && builtin_desc[len].supported; len--);
299 builtintablelen = ++len;
303 builtin_descriptor *find_builtin(int icmd)
305 builtin_descriptor *first = builtin_desc;
306 builtin_descriptor *last = builtin_desc + builtintablelen;
307 int len = last - first;
309 builtin_descriptor *middle;
313 middle = first + half;
314 if (middle->opcode < icmd) {
320 return first != last ? first : NULL;
323 #endif /* defined(USEBUILTINTABLE) */
326 /*****************************************************************************
328 *****************************************************************************/
332 /*************** internal function: builtin_isanysubclass *********************
334 Checks a subclass relation between two classes. Implemented interfaces
335 are interpreted as super classes.
336 Return value: 1 ... sub is subclass of super
339 *****************************************************************************/
340 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
343 castinfo classvalues;
348 if (super->flags & ACC_INTERFACE)
349 return (sub->vftbl->interfacetablelength > super->index) &&
350 (sub->vftbl->interfacetable[-super->index] != NULL);
352 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
354 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
355 (u4) classvalues.super_diffval;
361 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
365 castinfo classvalues;
370 asm_getclassvalues_atomic(super, sub, &classvalues);
372 if ((base = classvalues.super_baseval) <= 0)
373 /* super is an interface */
374 res = (sub->interfacetablelength > -base) &&
375 (sub->interfacetable[base] != NULL);
377 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
378 <= (u4) classvalues.super_diffval;
384 /****************** function: builtin_instanceof *****************************
386 Checks if an object is an instance of some given class (or subclass of
387 that class). If class is an interface, checks if the interface is
389 Return value: 1 ... obj is an instance of class or implements the interface
390 0 ... otherwise or if obj == NULL
392 *****************************************************************************/
394 /* XXX should use vftbl */
395 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
398 log_text ("builtin_instanceof called");
403 return builtin_isanysubclass(obj->vftbl->class, class);
408 /**************** function: builtin_checkcast *******************************
410 The same as builtin_instanceof except that 1 is returned when
413 ****************************************************************************/
415 /* XXX should use vftbl */
416 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
419 log_text("builtin_checkcast called");
424 if (builtin_isanysubclass(obj->vftbl->class, class))
428 printf("#### checkcast failed ");
429 utf_display(obj->vftbl->class->name);
431 utf_display(class->name);
439 /*********** internal function: builtin_descriptorscompatible ******************
441 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)
449 if (desc==target) return 1;
450 if (desc->arraytype != target->arraytype) return 0;
451 if (desc->arraytype != ARRAYTYPE_OBJECT) return 1;
453 /* {both arrays are arrays of references} */
454 if (desc->dimension == target->dimension) {
455 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
456 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
457 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
459 if (desc->dimension < target->dimension) return 0;
461 /* {desc has higher dimension than target} */
462 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
466 /******************** function: builtin_checkarraycast ***********************
468 Checks if an object is really a subtype of the requested array type.
469 The object has to be an array to begin with. For simple arrays (int, short,
470 double, etc.) the types have to match exactly.
471 For arrays of objects, the type of elements in the array has to be a
472 subtype (or the same type) of the requested element type. For arrays of
473 arrays (which in turn can again be arrays of arrays), the types at the
474 lowest level have to satisfy the corresponding sub class relation.
476 Return value: 1 ... cast is possible
479 ATTENTION: a cast with a NULL pointer is always possible.
481 *****************************************************************************/
483 s4 builtin_checkarraycast(java_objectheader *o, vftbl_t *target)
485 arraydescriptor *desc;
488 if ((desc = o->vftbl->arraydesc) == NULL) return 0;
490 return builtin_descriptorscompatible(desc, target->arraydesc);
494 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
497 return builtin_checkarraycast(obj, target);
501 /************************** exception functions *******************************
503 ******************************************************************************/
505 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
508 char logtext[MAXLOGTEXT];
509 sprintf(logtext, "Builtin exception thrown: ");
512 java_lang_Throwable *t = (java_lang_Throwable *) xptr;
514 utf_sprint_classname(logtext + strlen(logtext),
515 xptr->vftbl->class->name);
517 if (t->detailMessage) {
520 buf = javastring_tochar((java_objectheader *) t->detailMessage);
521 sprintf(logtext + strlen(logtext), ": %s", buf);
522 MFREE(buf, char, strlen(buf));
526 sprintf(logtext + strlen(logtext), "Error: <Nullpointer instead of exception>");
532 *exceptionptr = xptr;
539 /******************* function: builtin_canstore *******************************
541 Checks, if an object can be stored in an array.
542 Return value: 1 ... possible
545 ******************************************************************************/
547 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
549 arraydescriptor *desc;
550 arraydescriptor *valuedesc;
551 vftbl_t *componentvftbl;
555 castinfo classvalues;
559 /* The following is guaranteed (by verifier checks):
561 * *) a->...vftbl->arraydesc != NULL
562 * *) a->...vftbl->arraydesc->componentvftbl != NULL
563 * *) o->vftbl is not an interface vftbl
566 desc = a->header.objheader.vftbl->arraydesc;
567 componentvftbl = desc->componentvftbl;
568 valuevftbl = o->vftbl;
570 if ((dim_m1 = desc->dimension - 1) == 0) {
573 /* {a is a one-dimensional array} */
574 /* {a is an array of references} */
576 if (valuevftbl == componentvftbl)
579 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
581 if ((base = classvalues.super_baseval) <= 0)
582 /* an array of interface references */
583 return (valuevftbl->interfacetablelength > -base &&
584 valuevftbl->interfacetable[base] != NULL);
586 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
587 <= (unsigned) classvalues.super_diffval;
591 /* {a has dimension > 1} */
592 /* {componentvftbl->arraydesc != NULL} */
594 /* check if o is an array */
595 if ((valuedesc = valuevftbl->arraydesc) == NULL)
597 /* {o is an array} */
599 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
603 /* This is an optimized version where a is guaranteed to be one-dimensional */
604 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
606 arraydescriptor *desc;
607 vftbl_t *elementvftbl;
611 castinfo classvalues;
615 /* The following is guaranteed (by verifier checks):
617 * *) a->...vftbl->arraydesc != NULL
618 * *) a->...vftbl->arraydesc->elementvftbl != NULL
619 * *) a->...vftbl->arraydesc->dimension == 1
620 * *) o->vftbl is not an interface vftbl
623 desc = a->header.objheader.vftbl->arraydesc;
624 elementvftbl = desc->elementvftbl;
625 valuevftbl = o->vftbl;
627 /* {a is a one-dimensional array} */
629 if (valuevftbl == elementvftbl)
632 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
634 if ((base = classvalues.super_baseval) <= 0)
635 /* an array of interface references */
636 return (valuevftbl->interfacetablelength > -base &&
637 valuevftbl->interfacetable[base] != NULL);
639 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
640 <= (unsigned) classvalues.super_diffval;
646 /* This is an optimized version where a is guaranteed to be a
647 * one-dimensional array of a class type */
648 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
650 vftbl_t *elementvftbl;
653 castinfo classvalues;
657 /* The following is guaranteed (by verifier checks):
659 * *) a->...vftbl->arraydesc != NULL
660 * *) a->...vftbl->arraydesc->elementvftbl != NULL
661 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
662 * *) a->...vftbl->arraydesc->dimension == 1
663 * *) o->vftbl is not an interface vftbl
666 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
667 valuevftbl = o->vftbl;
669 /* {a is a one-dimensional array} */
671 if (valuevftbl == elementvftbl)
674 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
676 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
677 <= (unsigned) classvalues.super_diffval;
683 /* builtin_new *****************************************************************
685 Creates a new instance of class c on the heap.
687 Return value: pointer to the object or NULL if no memory is
690 *******************************************************************************/
692 java_objectheader *builtin_new(classinfo *c)
694 java_objectheader *o;
696 /* is the class loaded */
697 /*utf_fprint(stderr,c->name);fprintf(stderr,"\n");*/
700 /* is the class linked */
705 if (!c->initialized) {
707 log_message_class("Initialize class (from builtin_new): ", c);
709 if (!initialize_class(c))
713 o = heap_allocate(c->instancesize, true, c->finalizer);
718 MSET(o, 0, u1, c->instancesize);
722 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
730 /* builtin_newarray ************************************************************
732 Creates an array with the given vftbl on the heap.
734 Return value: pointer to the array or NULL if no memory is available
736 CAUTION: The given vftbl must be the vftbl of the *array* class,
737 not of the element class.
739 *******************************************************************************/
741 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
744 arraydescriptor *desc;
749 desc = arrayvftbl->arraydesc;
750 dataoffset = desc->dataoffset;
751 componentsize = desc->componentsize;
754 *exceptionptr = new_negativearraysizeexception();
758 actualsize = dataoffset + size * componentsize;
760 if (((u4) actualsize) < ((u4) size)) { /* overflow */
761 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
765 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
770 MSET(a, 0, u1, actualsize);
772 a->objheader.vftbl = arrayvftbl;
774 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
775 initObjectLock(&a->objheader);
784 /* builtin_anewarray ***********************************************************
786 Creates an array of references to the given class type on the heap.
788 Return value: pointer to the array or NULL if no memory is
791 *******************************************************************************/
793 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
797 /* is class loaded */
798 assert(component->loaded);
800 /* is class linked */
801 if (!component->linked)
802 if (!link_class(component))
805 c = class_array_of(component, true);
810 return (java_objectarray *) builtin_newarray(size, c->vftbl);
814 /* builtin_newarray_int ********************************************************
816 Creates an array of 32 bit Integers on the heap.
818 Return value: pointer to the array or NULL if no memory is
821 *******************************************************************************/
823 java_intarray *builtin_newarray_int(s4 size)
825 return (java_intarray *)
826 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
830 /* builtin_newarray_long *******************************************************
832 Creates an array of 64 bit Integers on the heap.
834 Return value: pointer to the array or NULL if no memory is
837 *******************************************************************************/
839 java_longarray *builtin_newarray_long(s4 size)
841 return (java_longarray *)
842 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
846 /* builtin_newarray_float ******************************************************
848 Creates an array of 32 bit IEEE floats on the heap.
850 Return value: pointer to the array or NULL if no memory is
853 *******************************************************************************/
855 java_floatarray *builtin_newarray_float(s4 size)
857 return (java_floatarray *)
858 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
862 /* builtin_newarray_double *****************************************************
864 Creates an array of 64 bit IEEE floats on the heap.
866 Return value: pointer to the array or NULL if no memory is
869 *******************************************************************************/
871 java_doublearray *builtin_newarray_double(s4 size)
873 return (java_doublearray *)
874 builtin_newarray(size,
875 primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
879 /* builtin_newarray_byte *******************************************************
881 Creates an array of 8 bit Integers on the heap.
883 Return value: pointer to the array or NULL if no memory is
886 *******************************************************************************/
888 java_bytearray *builtin_newarray_byte(s4 size)
890 return (java_bytearray *)
891 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
895 /* builtin_newarray_char *******************************************************
897 Creates an array of characters on the heap.
899 Return value: pointer to the array or NULL if no memory is
902 *******************************************************************************/
904 java_chararray *builtin_newarray_char(s4 size)
906 return (java_chararray *)
907 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
911 /* builtin_newarray_short ******************************************************
913 Creates an array of 16 bit Integers on the heap.
915 Return value: pointer to the array or NULL if no memory is
918 *******************************************************************************/
920 java_shortarray *builtin_newarray_short(s4 size)
922 return (java_shortarray *)
923 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
927 /* builtin_newarray_boolean ****************************************************
929 Creates an array of bytes on the heap. The array is designated as
930 an array of booleans (important for casts)
932 Return value: pointer to the array or NULL if no memory is
935 *******************************************************************************/
937 java_booleanarray *builtin_newarray_boolean(s4 size)
939 return (java_booleanarray *)
940 builtin_newarray(size,
941 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
945 /* builtin_multianewarray ******************************************************
947 Creates a multi-dimensional array on the heap. The dimensions are
948 passed in an array of longs.
951 n............number of dimensions to create
952 arrayvftbl...vftbl of the array class
953 dims.........array containing the size of each dimension to create
955 Return value: pointer to the array or NULL if no memory is
958 ******************************************************************************/
960 java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims)
964 vftbl_t *componentvftbl;
966 /* create this dimension */
969 a = builtin_newarray(size, arrayvftbl);
974 /* if this is the last dimension return */
979 /* get the vftbl of the components to create */
981 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
983 /* The verifier guarantees this. */
984 /* if (!componentvftbl) */
985 /* panic ("multianewarray with too many dimensions"); */
987 /* create the component arrays */
989 for (i = 0; i < size; i++) {
990 java_arrayheader *ea =
991 builtin_multianewarray(n, componentvftbl, dims + 1);
996 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1003 /*****************************************************************************
1006 Various functions for printing a message at method entry or exit (for
1009 *****************************************************************************/
1011 u4 methodindent = 0;
1013 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1019 char logtext[MAXLOGTEXT];
1025 log_text("WARNING: unmatched methodindent--");
1027 if (opt_verbose || runverbose || verboseexception) {
1029 sprintf(logtext,"Exception ");
1030 utf_sprint_classname(logtext+strlen(logtext), xptr->vftbl->class->name);
1033 sprintf(logtext,"Some Throwable");
1035 sprintf(logtext+strlen(logtext), " thrown in ");
1038 utf_sprint_classname(logtext+strlen(logtext), m->class->name);
1039 sprintf(logtext+strlen(logtext), ".");
1040 utf_sprint(logtext+strlen(logtext), m->name);
1041 if (m->flags & ACC_SYNCHRONIZED) {
1042 sprintf(logtext+strlen(logtext), "(SYNC");
1045 sprintf(logtext+strlen(logtext), "(NOSYNC");
1048 if (m->flags & ACC_NATIVE) {
1049 sprintf(logtext+strlen(logtext), ",NATIVE");
1050 #if POINTERSIZE == 8
1051 sprintf(logtext+strlen(logtext), ")(0x%016lx) at position 0x%016lx\n", (ptrint) m->entrypoint, (ptrint) pos);
1053 sprintf(logtext+strlen(logtext), ")(0x%08x) at position 0x%08x\n", (ptrint) m->entrypoint, (ptrint) pos);
1057 #if POINTERSIZE == 8
1058 sprintf(logtext+strlen(logtext), ")(0x%016lx) at position 0x%016lx (", (ptrint) m->entrypoint, (ptrint) pos);
1060 sprintf(logtext+strlen(logtext), ")(0x%08x) at position 0x%08x (", (ptrint) m->entrypoint, (ptrint) pos);
1062 if (m->class->sourcefile == NULL) {
1063 sprintf(logtext+strlen(logtext), "<NO CLASSFILE INFORMATION>");
1066 utf_sprint(logtext+strlen(logtext), m->class->sourcefile);
1068 sprintf(logtext+strlen(logtext), ":%d)\n", line);
1072 sprintf(logtext+strlen(logtext), "call_java_method\n");
1081 #ifdef TRACE_ARGS_NUM
1082 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1083 #if TRACE_ARGS_NUM >= 6
1086 #if TRACE_ARGS_NUM == 8
1092 char logtext[MAXLOGTEXT];
1093 for (i = 0; i < methodindent; i++)
1095 if (methodindent == 0)
1096 sprintf(logtext + methodindent, "1st_call: ");
1098 sprintf(logtext + methodindent, "called: ");
1100 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1101 sprintf(logtext + strlen(logtext), ".");
1102 utf_sprint(logtext + strlen(logtext), m->name);
1103 utf_sprint(logtext + strlen(logtext), m->descriptor);
1105 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1106 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1107 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1108 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1109 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1110 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1111 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1112 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1113 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1114 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1115 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1118 sprintf(logtext + strlen(logtext), "(");
1120 switch (m->paramcount) {
1124 #if defined(__I386__) || defined(__POWERPC__)
1126 sprintf(logtext+strlen(logtext), "%llx", a0);
1130 sprintf(logtext+strlen(logtext), "%llx, %llx", a0, a1);
1134 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx", a0, a1, a2);
1138 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx",
1142 #if TRACE_ARGS_NUM >= 6
1144 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx",
1145 a0, a1, a2, a3, a4);
1149 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx",
1150 a0, a1, a2, a3, a4, a5);
1152 #endif /* TRACE_ARGS_NUM >= 6 */
1154 #if TRACE_ARGS_NUM == 8
1156 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx",
1157 a0, a1, a2, a3, a4, a5, a6);
1161 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx",
1162 a0, a1, a2, a3, a4, a5, a6, a7);
1166 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1167 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1169 #else /* TRACE_ARGS_NUM == 8 */
1171 sprintf(logtext+strlen(logtext), "%llx, %llx, %llx, %llx, %llx, %llx, ...(%d)",
1172 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1174 #endif /* TRACE_ARGS_NUM == 8 */
1175 #else /* defined(__I386__) || defined(__POWERPC__) */
1177 sprintf(logtext+strlen(logtext), "%lx", a0);
1181 sprintf(logtext+strlen(logtext), "%lx, %lx", a0, a1);
1185 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx", a0, a1, a2);
1189 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx",
1193 #if TRACE_ARGS_NUM >= 6
1195 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx",
1196 a0, a1, a2, a3, a4);
1200 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx",
1201 a0, a1, a2, a3, a4, a5);
1203 #endif /* TRACE_ARGS_NUM >= 6 */
1205 #if TRACE_ARGS_NUM == 8
1207 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx",
1208 a0, a1, a2, a3, a4, a5, a6);
1212 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx",
1213 a0, a1, a2, a3, a4, a5, a6, a7);
1215 #endif /* TRACE_ARGS_NUM == 8 */
1218 #if TRACE_ARGS_NUM == 4
1219 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, ...(%d)",
1220 a0, a1, a2, a3, m->paramcount - 4);
1222 #elif TRACE_ARGS_NUM == 6
1223 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1224 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1226 #elif TRACE_ARGS_NUM == 8
1227 sprintf(logtext+strlen(logtext), "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, ...(%d)",
1228 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1231 #endif /* defined(__I386__) || defined(__POWERPC__) */
1234 sprintf(logtext + strlen(logtext), ")");
1242 void builtin_displaymethodstart(methodinfo *m)
1244 char logtext[MAXLOGTEXT];
1245 sprintf(logtext, " ");
1246 sprintf(logtext + methodindent, "called: ");
1247 utf_sprint(logtext + strlen(logtext), m->class->name);
1248 sprintf(logtext + strlen(logtext), ".");
1249 utf_sprint(logtext + strlen(logtext), m->name);
1250 utf_sprint(logtext + strlen(logtext), m->descriptor);
1252 if (m->flags & ACC_PUBLIC) sprintf(logtext + strlen(logtext), " PUBLIC");
1253 if (m->flags & ACC_PRIVATE) sprintf(logtext + strlen(logtext), " PRIVATE");
1254 if (m->flags & ACC_PROTECTED) sprintf(logtext + strlen(logtext), " PROTECTED");
1255 if (m->flags & ACC_STATIC) sprintf(logtext + strlen(logtext), " STATIC");
1256 if (m->flags & ACC_FINAL) sprintf(logtext + strlen(logtext), " FINAL");
1257 if (m->flags & ACC_SYNCHRONIZED) sprintf(logtext + strlen(logtext), " SYNCHRONIZED");
1258 if (m->flags & ACC_VOLATILE) sprintf(logtext + strlen(logtext), " VOLATILE");
1259 if (m->flags & ACC_TRANSIENT) sprintf(logtext + strlen(logtext), " TRANSIENT");
1260 if (m->flags & ACC_NATIVE) sprintf(logtext + strlen(logtext), " NATIVE");
1261 if (m->flags & ACC_INTERFACE) sprintf(logtext + strlen(logtext), " INTERFACE");
1262 if (m->flags & ACC_ABSTRACT) sprintf(logtext + strlen(logtext), " ABSTRACT");
1269 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1272 char logtext[MAXLOGTEXT];
1273 for (i = 0; i < methodindent; i++)
1278 log_text("WARNING: unmatched methodindent--");
1280 sprintf(logtext + methodindent, "finished: ");
1281 utf_sprint_classname(logtext + strlen(logtext), m->class->name);
1282 sprintf(logtext + strlen(logtext), ".");
1283 utf_sprint(logtext + strlen(logtext), m->name);
1284 utf_sprint(logtext + strlen(logtext), m->descriptor);
1286 switch (m->returntype) {
1288 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1292 #if defined(__I386__) || defined(__POWERPC__)
1293 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1295 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1300 #if defined(__I386__) || defined(__POWERPC__)
1301 sprintf(logtext + strlen(logtext), "->%p", (u1*) ((s4) l));
1303 sprintf(logtext + strlen(logtext), "->%p", (u1*) l);
1308 sprintf(logtext + strlen(logtext), "->%g", f);
1312 sprintf(logtext + strlen(logtext), "->%g", d);
1319 /****************************************************************************
1320 SYNCHRONIZATION FUNCTIONS
1321 *****************************************************************************/
1323 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1325 * Lock the mutex of an object.
1327 void internal_lock_mutex_for_object(java_objectheader *object)
1329 mutexHashEntry *entry;
1332 assert(object != 0);
1334 hashValue = MUTEX_HASH_VALUE(object);
1335 entry = &mutexHashTable[hashValue];
1337 if (entry->object != 0) {
1338 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1340 entry->mutex.holder = 0;
1341 entry->mutex.count = 0;
1342 entry->mutex.muxWaiters = 0;
1345 while (entry->next != 0 && entry->object != object)
1346 entry = entry->next;
1348 if (entry->object != object) {
1349 entry->next = firstFreeOverflowEntry;
1350 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1352 entry = entry->next;
1355 assert(entry->conditionCount == 0);
1360 entry->mutex.holder = 0;
1361 entry->mutex.count = 0;
1362 entry->mutex.muxWaiters = 0;
1365 if (entry->object == 0)
1366 entry->object = object;
1368 internal_lock_mutex(&entry->mutex);
1373 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1375 * Unlocks the mutex of an object.
1377 void internal_unlock_mutex_for_object (java_objectheader *object)
1380 mutexHashEntry *entry;
1382 hashValue = MUTEX_HASH_VALUE(object);
1383 entry = &mutexHashTable[hashValue];
1385 if (entry->object == object) {
1386 internal_unlock_mutex(&entry->mutex);
1389 while (entry->next != 0 && entry->next->object != object)
1390 entry = entry->next;
1392 assert(entry->next != 0);
1394 internal_unlock_mutex(&entry->next->mutex);
1396 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1397 mutexHashEntry *unlinked = entry->next;
1399 entry->next = unlinked->next;
1400 unlinked->next = firstFreeOverflowEntry;
1401 firstFreeOverflowEntry = unlinked;
1408 #if defined(USE_THREADS)
1409 void builtin_monitorenter(java_objectheader *o)
1411 #if !defined(NATIVE_THREADS)
1416 hashValue = MUTEX_HASH_VALUE(o);
1417 if (mutexHashTable[hashValue].object == o
1418 && mutexHashTable[hashValue].mutex.holder == currentThread)
1419 ++mutexHashTable[hashValue].mutex.count;
1421 internal_lock_mutex_for_object(o);
1425 monitorEnter((threadobject *) THREADOBJECT, o);
1431 #if defined(USE_THREADS)
1433 * Locks the class object - needed for static synchronized methods.
1434 * The use_class_as_object call is needed in order to circumvent a
1435 * possible deadlock with builtin_monitorenter called by another
1436 * thread calling use_class_as_object.
1438 void builtin_staticmonitorenter(classinfo *c)
1440 use_class_as_object(c);
1441 builtin_monitorenter(&c->header);
1446 #if defined(USE_THREADS)
1447 void *builtin_monitorexit(java_objectheader *o)
1449 #if !defined(NATIVE_THREADS)
1454 hashValue = MUTEX_HASH_VALUE(o);
1455 if (mutexHashTable[hashValue].object == o) {
1456 if (mutexHashTable[hashValue].mutex.count == 1
1457 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1458 internal_unlock_mutex_for_object(o);
1460 --mutexHashTable[hashValue].mutex.count;
1463 internal_unlock_mutex_for_object(o);
1468 monitorExit((threadobject *) THREADOBJECT, o);
1475 /*****************************************************************************
1476 MISCELLANEOUS HELPER FUNCTIONS
1477 *****************************************************************************/
1481 /*********** Functions for integer divisions *****************************
1483 On some systems (eg. DEC ALPHA), integer division is not supported by the
1484 CPU. These helper functions implement the missing functionality.
1486 ******************************************************************************/
1488 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1489 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1492 /************** Functions for long arithmetics *******************************
1494 On systems where 64 bit Integers are not supported by the CPU, these
1495 functions are needed.
1497 ******************************************************************************/
1500 s8 builtin_ladd(s8 a, s8 b)
1505 return builtin_i2l(0);
1509 s8 builtin_lsub(s8 a, s8 b)
1514 return builtin_i2l(0);
1518 s8 builtin_lmul(s8 a, s8 b)
1523 return builtin_i2l(0);
1527 s8 builtin_ldiv(s8 a, s8 b)
1532 return builtin_i2l(0);
1536 s8 builtin_lrem(s8 a, s8 b)
1541 return builtin_i2l(0);
1545 s8 builtin_lshl(s8 a, s4 b)
1548 return a << (b & 63);
1550 return builtin_i2l(0);
1554 s8 builtin_lshr(s8 a, s4 b)
1557 return a >> (b & 63);
1559 return builtin_i2l(0);
1563 s8 builtin_lushr(s8 a, s4 b)
1566 return ((u8) a) >> (b & 63);
1568 return builtin_i2l(0);
1572 s8 builtin_land(s8 a, s8 b)
1577 return builtin_i2l(0);
1581 s8 builtin_lor(s8 a, s8 b)
1586 return builtin_i2l(0);
1590 s8 builtin_lxor(s8 a, s8 b)
1595 return builtin_i2l(0);
1599 s8 builtin_lneg(s8 a)
1604 return builtin_i2l(0);
1608 s4 builtin_lcmp(s8 a, s8 b)
1611 if (a < b) return -1;
1612 if (a > b) return 1;
1623 /*********** Functions for floating point operations *************************/
1625 float builtin_fadd(float a, float b)
1627 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1628 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1639 if (copysignf(1.0, a) == copysignf(1.0, b))
1642 return intBitsToFloat(FLT_NAN);
1648 float builtin_fsub(float a, float b)
1650 return builtin_fadd(a, builtin_fneg(b));
1654 float builtin_fmul(float a, float b)
1656 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1657 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1659 if (finitef(b)) return a * b;
1661 if (a == 0) return intBitsToFloat(FLT_NAN);
1662 else return copysignf(b, copysignf(1.0, b)*a);
1667 if (b == 0) return intBitsToFloat(FLT_NAN);
1668 else return copysignf(a, copysignf(1.0, a)*b);
1671 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1677 float builtin_fdiv(float a, float b)
1679 if (finitef(a) && finitef(b)) {
1684 return intBitsToFloat(FLT_POSINF);
1686 return intBitsToFloat(FLT_NEGINF);
1689 return intBitsToFloat(FLT_NAN);
1693 float builtin_frem(float a, float b)
1699 float builtin_fneg(float a)
1701 if (isnanf(a)) return a;
1703 if (finitef(a)) return -a;
1704 else return copysignf(a, -copysignf(1.0, a));
1709 s4 builtin_fcmpl(float a, float b)
1711 if (isnanf(a)) return -1;
1712 if (isnanf(b)) return -1;
1713 if (!finitef(a) || !finitef(b)) {
1714 a = finitef(a) ? 0 : copysignf(1.0, a);
1715 b = finitef(b) ? 0 : copysignf(1.0, b);
1717 if (a > b) return 1;
1718 if (a == b) return 0;
1723 s4 builtin_fcmpg(float a, float b)
1725 if (isnanf(a)) return 1;
1726 if (isnanf(b)) return 1;
1727 if (!finitef(a) || !finitef(b)) {
1728 a = finitef(a) ? 0 : copysignf(1.0, a);
1729 b = finitef(b) ? 0 : copysignf(1.0, b);
1731 if (a > b) return 1;
1732 if (a == b) return 0;
1738 /************************* Functions for doubles ****************************/
1740 double builtin_dadd(double a, double b)
1742 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1743 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1745 if (finite(b)) return a + b;
1749 if (finite(b)) return a;
1751 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1752 else return longBitsToDouble(DBL_NAN);
1758 double builtin_dsub(double a, double b)
1760 return builtin_dadd(a, builtin_dneg(b));
1764 double builtin_dmul(double a, double b)
1766 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1767 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1769 if (finite(b)) return a * b;
1771 if (a == 0) return longBitsToDouble(DBL_NAN);
1772 else return copysign(b, copysign(1.0, b) * a);
1777 if (b == 0) return longBitsToDouble(DBL_NAN);
1778 else return copysign(a, copysign(1.0, a) * b);
1781 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1787 double builtin_ddiv(double a, double b)
1795 return longBitsToDouble(DBL_NAN);
1797 return copysign(0.0, b);
1803 return longBitsToDouble(DBL_POSINF);
1805 return longBitsToDouble(DBL_NEGINF);
1808 return longBitsToDouble(DBL_NAN);
1811 /* if (finite(a) && finite(b)) { */
1816 /* return longBitsToDouble(DBL_POSINF); */
1817 /* else if (a < 0) */
1818 /* return longBitsToDouble(DBL_NEGINF); */
1822 /* keep compiler happy */
1827 double builtin_drem(double a, double b)
1833 double builtin_dneg(double a)
1835 if (isnan(a)) return a;
1837 if (finite(a)) return -a;
1838 else return copysign(a, -copysign(1.0, a));
1843 s4 builtin_dcmpl(double a, double b)
1845 if (isnan(a)) return -1;
1846 if (isnan(b)) return -1;
1847 if (!finite(a) || !finite(b)) {
1848 a = finite(a) ? 0 : copysign(1.0, a);
1849 b = finite(b) ? 0 : copysign(1.0, b);
1851 if (a > b) return 1;
1852 if (a == b) return 0;
1857 s4 builtin_dcmpg(double a, double b)
1859 if (isnan(a)) return 1;
1860 if (isnan(b)) return 1;
1861 if (!finite(a) || !finite(b)) {
1862 a = finite(a) ? 0 : copysign(1.0, a);
1863 b = finite(b) ? 0 : copysign(1.0, b);
1865 if (a > b) return 1;
1866 if (a == b) return 0;
1871 /*********************** Conversion operations ****************************/
1873 s8 builtin_i2l(s4 i)
1886 float builtin_i2f(s4 a)
1888 float f = (float) a;
1893 double builtin_i2d(s4 a)
1895 double d = (double) a;
1900 s4 builtin_l2i(s8 l)
1910 float builtin_l2f(s8 a)
1913 float f = (float) a;
1921 double builtin_l2d(s8 a)
1924 double d = (double) a;
1932 s4 builtin_f2i(float a)
1935 return builtin_d2i((double) a);
1944 if (a < (-2147483648))
1945 return (-2147483648);
1948 f = copysignf((float) 1.0, a);
1951 return (-2147483648); */
1955 s8 builtin_f2l(float a)
1958 return builtin_d2l((double) a);
1963 if (a > 9223372036854775807L)
1964 return 9223372036854775807L;
1965 if (a < (-9223372036854775808L))
1966 return (-9223372036854775808L);
1971 f = copysignf((float) 1.0, a);
1973 return 9223372036854775807L;
1974 return (-9223372036854775808L); */
1978 double builtin_f2d(float a)
1980 if (finitef(a)) return (double) a;
1983 return longBitsToDouble(DBL_NAN);
1985 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
1990 s4 builtin_d2i(double a)
1995 if (a >= 2147483647)
1997 if (a <= (-2147483647-1))
1998 return (-2147483647-1);
2003 d = copysign(1.0, a);
2006 return (-2147483647-1);
2010 s8 builtin_d2l(double a)
2015 if (a >= 9223372036854775807LL)
2016 return 9223372036854775807LL;
2017 if (a <= (-9223372036854775807LL-1))
2018 return (-9223372036854775807LL-1);
2023 d = copysign(1.0, a);
2025 return 9223372036854775807LL;
2026 return (-9223372036854775807LL-1);
2030 float builtin_d2f(double a)
2036 return intBitsToFloat(FLT_NAN);
2038 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2043 /* used to convert FLT_xxx defines into float values */
2045 inline float intBitsToFloat(s4 i)
2054 /* used to convert DBL_xxx defines into double values */
2056 inline float longBitsToDouble(s8 l)
2065 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2067 return (java_arrayheader *)
2068 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2074 panic("Internal error: builtin_dummy called (native function is missing)");
2075 return 0; /* for the compiler */
2079 /* builtin_asm_get_exceptionptrptr *********************************************
2081 this is a wrapper for calls from asmpart
2083 *******************************************************************************/
2085 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2086 java_objectheader **builtin_asm_get_exceptionptrptr()
2088 return builtin_get_exceptionptrptr();
2093 methodinfo *builtin_asm_get_threadrootmethod()
2095 return *threadrootmethod;
2099 inline void* builtin_asm_get_stackframeinfo()
2101 /*log_text("builtin_asm_get_stackframeinfo()");*/
2102 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2103 /*printf("stackframeinfo: %p,%p\n",&THREADINFO->_stackframeinfo,*(&THREADINFO->_stackframeinfo));*/
2104 return &THREADINFO->_stackframeinfo;
2106 #if defined(__GNUC__)
2107 #warning FIXME FOR OLD THREAD IMPL (jowenn)
2109 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2113 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2114 /* stacktraceelement *el;*/
2117 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2118 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2120 *el=MNEW(stacktraceelement,s+1); /*GC*/
2122 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2124 #if defined(__GNUC__)
2125 #warning change this if line numbers bigger than u2 are allowed, the currently supported class file format does no allow that
2127 (*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 */
2132 * These are local overrides for various environment variables in Emacs.
2133 * Please do not remove this and leave it at the end of the file, where
2134 * Emacs will automagically detect them.
2135 * ---------------------------------------------------------------------
2138 * indent-tabs-mode: t