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 2498 2005-05-23 08:12:52Z 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_Object.h" /* required by VMObject */
57 #include "native/include/java_lang_VMObject.h"
59 #if defined(USE_THREADS)
60 # if defined(NATIVE_THREADS)
61 # include "threads/native/threads.h"
63 # include "threads/green/threads.h"
64 # include "threads/green/locks.h"
68 #include "toolbox/logging.h"
69 #include "toolbox/util.h"
70 #include "vm/builtin.h"
71 #include "vm/exceptions.h"
72 #include "vm/global.h"
73 #include "vm/initialize.h"
74 #include "vm/loader.h"
75 #include "vm/options.h"
76 #include "vm/stringlocal.h"
77 #include "vm/tables.h"
78 #include "vm/jit/asmpart.h"
79 #include "vm/jit/patcher.h"
82 #undef DEBUG /*define DEBUG 1*/
84 THREADSPECIFIC methodinfo* _threadrootmethod = NULL;
85 THREADSPECIFIC void *_thread_nativestackframeinfo = NULL;
88 #if defined(USEBUILTINTABLE)
91 stdopdescriptor builtintable[] = {
92 { ICMD_LCMP, TYPE_LONG, TYPE_LONG, TYPE_INT, ICMD_BUILTIN2,
93 (functionptr) builtin_lcmp , SUPPORT_LONG && SUPPORT_LONG_CMP, false },
94 { ICMD_LAND, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
95 (functionptr) builtin_land , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
96 { ICMD_LOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
97 (functionptr) builtin_lor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
98 { ICMD_LXOR, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
99 (functionptr) builtin_lxor , SUPPORT_LONG && SUPPORT_LONG_LOGICAL, false },
100 { ICMD_LSHL, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
101 (functionptr) builtin_lshl , SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
102 { ICMD_LSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
103 (functionptr) builtin_lshr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
104 { ICMD_LUSHR, TYPE_LONG, TYPE_INT, TYPE_LONG, ICMD_BUILTIN2,
105 (functionptr) builtin_lushr, SUPPORT_LONG && SUPPORT_LONG_SHIFT, false },
106 { ICMD_LADD, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
107 (functionptr) builtin_ladd , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
108 { ICMD_LSUB, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
109 (functionptr) builtin_lsub , SUPPORT_LONG && SUPPORT_LONG_ADD, false },
110 { ICMD_LNEG, TYPE_LONG, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
111 (functionptr) builtin_lneg, SUPPORT_LONG && SUPPORT_LONG_ADD, true },
112 { ICMD_LMUL, TYPE_LONG, TYPE_LONG, TYPE_LONG, ICMD_BUILTIN2,
113 (functionptr) builtin_lmul , SUPPORT_LONG && SUPPORT_LONG_MUL, false },
114 { ICMD_I2F, TYPE_INT, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
115 (functionptr) builtin_i2f, SUPPORT_FLOAT && SUPPORT_IFCVT, true },
116 { ICMD_I2D, TYPE_INT, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
117 (functionptr) builtin_i2d, SUPPORT_DOUBLE && SUPPORT_IFCVT, true },
118 { ICMD_L2F, TYPE_LONG, TYPE_VOID, TYPE_FLOAT, ICMD_BUILTIN1,
119 (functionptr) builtin_l2f, SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT, true },
120 { ICMD_L2D, TYPE_LONG, TYPE_VOID, TYPE_DOUBLE, ICMD_BUILTIN1,
121 (functionptr) builtin_l2d, SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT, true },
122 { ICMD_F2L, TYPE_FLOAT, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
123 (functionptr) builtin_f2l, SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
124 { ICMD_D2L, TYPE_DOUBLE, TYPE_VOID, TYPE_LONG, ICMD_BUILTIN1,
125 (functionptr) builtin_d2l, SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT, true },
126 { ICMD_F2I, TYPE_FLOAT, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
127 (functionptr) builtin_f2i, SUPPORT_FLOAT && SUPPORT_FICVT, true },
128 { ICMD_D2I, TYPE_DOUBLE, TYPE_VOID, TYPE_INT, ICMD_BUILTIN1,
129 (functionptr) builtin_d2i, SUPPORT_DOUBLE && SUPPORT_FICVT, true },
130 { 255, 0, 0, 0, 0, NULL, true, false },
135 static int builtintablelen;
137 #endif /* USEBUILTINTABLE */
140 /*****************************************************************************
141 TABLE OF BUILTIN FUNCTIONS
143 This table lists the builtin functions which are used inside
146 The first part of the table (up to the 255-marker) lists the
147 opcodes which are automatically replaced in stack.c.
149 The second part lists the builtin functions which are "manually"
150 used for BUILTIN* opcodes in parse.c and stack.c.
152 *****************************************************************************/
154 builtin_descriptor builtin_desc[] = {
155 #if defined(USEBUILTINTABLE)
156 {ICMD_LCMP , BUILTIN_lcmp ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_INT ,
157 SUPPORT_LONG && SUPPORT_LONG_CMP,false,"lcmp"},
159 {ICMD_LAND , BUILTIN_land ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
160 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"land"},
161 {ICMD_LOR , BUILTIN_lor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
162 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lor"},
163 {ICMD_LXOR , BUILTIN_lxor ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
164 SUPPORT_LONG && SUPPORT_LONG_LOGICAL,false,"lxor"},
166 {ICMD_LSHL , BUILTIN_lshl ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
167 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshl"},
168 {ICMD_LSHR , BUILTIN_lshr ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
169 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lshr"},
170 {ICMD_LUSHR, BUILTIN_lushr,ICMD_BUILTIN2,TYPE_LONG ,TYPE_INT ,TYPE_VOID ,TYPE_LONG ,
171 SUPPORT_LONG && SUPPORT_LONG_SHIFT,false,"lushr"},
173 {ICMD_LADD , BUILTIN_ladd ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
174 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"ladd"},
175 {ICMD_LSUB , BUILTIN_lsub ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
176 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lsub"},
177 {ICMD_LNEG , BUILTIN_lneg ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
178 SUPPORT_LONG && SUPPORT_LONG_ADD,false,"lneg"},
179 {ICMD_LMUL , BUILTIN_lmul ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,
180 SUPPORT_LONG && SUPPORT_LONG_MUL,false,"lmul"},
182 {ICMD_I2F , BUILTIN_i2f ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
183 SUPPORT_FLOAT && SUPPORT_IFCVT,true ,"i2f"},
184 {ICMD_I2D , BUILTIN_i2d ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
185 SUPPORT_DOUBLE && SUPPORT_IFCVT,true ,"i2d"},
186 {ICMD_L2F , BUILTIN_l2f ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_FLOAT ,
187 SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_LONG_FCVT,true ,"l2f"},
188 {ICMD_L2D , BUILTIN_l2d ,ICMD_BUILTIN1,TYPE_LONG ,TYPE_VOID ,TYPE_VOID ,TYPE_DOUBLE,
189 SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_LONG_FCVT,true ,"l2d"},
190 {ICMD_F2L , BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
191 SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"f2l"},
192 {ICMD_D2L , BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,
193 SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_LONG_ICVT,true ,"d2l"},
194 {ICMD_F2I , BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
195 SUPPORT_FLOAT && SUPPORT_FICVT,true ,"f2i"},
196 {ICMD_D2I , BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
197 SUPPORT_DOUBLE && SUPPORT_FICVT,true ,"d2i"},
199 { ICMD_FADD , BUILTIN_fadd , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fadd" },
200 { ICMD_FSUB , BUILTIN_fsub , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fsub" },
201 { ICMD_FMUL , BUILTIN_fmul , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fmul" },
202 { ICMD_FDIV , BUILTIN_fdiv , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fdiv" },
203 { ICMD_FNEG , BUILTIN_fneg , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT, true, "fneg" },
204 { ICMD_FCMPL, BUILTIN_fcmpl , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpl" },
205 { ICMD_FCMPG, BUILTIN_fcmpg , ICMD_BUILTIN2, TYPE_FLT, TYPE_FLT , TYPE_VOID , TYPE_INT, SUPPORT_FLOAT, true, "fcmpg" },
207 { ICMD_DADD , BUILTIN_dadd , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dadd" },
208 { ICMD_DSUB , BUILTIN_dsub , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dsub" },
209 { ICMD_DMUL , BUILTIN_dmul , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dmul" },
210 { ICMD_DDIV , BUILTIN_ddiv , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "ddiv" },
211 { ICMD_DNEG , BUILTIN_dneg , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_DOUBLE, true, "dneg" },
212 { ICMD_DCMPL, BUILTIN_dcmpl , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpl" },
213 { ICMD_DCMPG, BUILTIN_dcmpg , ICMD_BUILTIN2, TYPE_DBL, TYPE_DBL , TYPE_VOID , TYPE_INT, SUPPORT_DOUBLE, true, "dcmpg" },
215 { ICMD_F2D, BUILTIN_f2d , ICMD_BUILTIN1, TYPE_FLT, TYPE_VOID , TYPE_VOID , TYPE_DBL, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "f2d" },
216 { ICMD_D2F, BUILTIN_d2f , ICMD_BUILTIN1, TYPE_DBL, TYPE_VOID , TYPE_VOID , TYPE_FLT, SUPPORT_FLOAT && SUPPORT_DOUBLE, true, "d2f" },
219 /* this record marks the end of the automatically replaced opcodes */
220 {255,NULL,0,0,0,0,0,0,0,"<INVALID>"},
222 /* the following functions are not replaced automatically */
224 #if defined(__ALPHA__)
225 {255, BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"f2l"},
226 {255, BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"d2l"},
227 {255, BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"f2i"},
228 {255, BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"d2i"},
231 {255,BUILTIN_instanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"instanceof"},
232 {255,BUILTIN_arrayinstanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"arrayinstanceof"},
233 {255,BUILTIN_arraycheckcast ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,0,0,"arraycheckcast"},
234 {255,BUILTIN_aastore ,ICMD_BUILTIN3,TYPE_ADR ,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,0,0,"aastore"},
235 {255,BUILTIN_new ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"new"},
236 {255,BUILTIN_newarray ,ICMD_BUILTIN2,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray"},
237 {255,BUILTIN_newarray_boolean,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_boolean"},
238 {255,BUILTIN_newarray_char ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_char"},
239 {255,BUILTIN_newarray_float ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_float"},
240 {255,BUILTIN_newarray_double ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_double"},
241 {255,BUILTIN_newarray_byte ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_byte"},
242 {255,BUILTIN_newarray_short ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_short"},
243 {255,BUILTIN_newarray_int ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_int"},
244 {255,BUILTIN_newarray_long ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_long"},
245 #if defined(USE_THREADS)
246 {255,BUILTIN_monitorenter ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorenter"},
247 {255,BUILTIN_monitorexit ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_VOID ,0,0,"monitorexit"},
249 #if !SUPPORT_DIVISION
250 {255,BUILTIN_idiv ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"idiv"},
251 {255,BUILTIN_irem ,ICMD_BUILTIN2,TYPE_INT ,TYPE_INT ,TYPE_VOID ,TYPE_INT ,0,0,"irem"},
253 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
254 {255,BUILTIN_ldiv ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"ldiv"},
255 {255,BUILTIN_lrem ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_LONG ,0,0,"lrem"},
257 {255,BUILTIN_frem ,ICMD_BUILTIN2,TYPE_FLOAT ,TYPE_FLOAT ,TYPE_VOID ,TYPE_FLOAT ,0,0,"frem"},
258 {255,BUILTIN_drem ,ICMD_BUILTIN2,TYPE_DOUBLE,TYPE_DOUBLE,TYPE_VOID ,TYPE_DOUBLE,0,0,"drem"},
261 #if defined(__X86_64__) || defined(__I386__) || defined(__ALPHA__) || defined(__MIPS__)
262 /* assembler code patching functions */
264 { 255, PATCHER_builtin_new , ICMD_BUILTIN1, TYPE_ADR , TYPE_VOID , TYPE_VOID , TYPE_ADR , 0, 0, "new (calling patcher_builtin_new)" },
265 { 255, PATCHER_builtin_newarray , ICMD_BUILTIN1, TYPE_ADR , TYPE_VOID , TYPE_VOID , TYPE_ADR , 0, 0, "newarray (calling patcher_builtin_newarray)" },
266 { 255, PATCHER_builtin_arraycheckcast , ICMD_BUILTIN2, TYPE_ADR , TYPE_ADR , TYPE_VOID , TYPE_VOID , 0, 0, "arraycheckcast (calling patcher_builtin_arraycheckcast)" },
267 { 255, PATCHER_builtin_arrayinstanceof, ICMD_BUILTIN2, TYPE_ADR , TYPE_ADR , TYPE_VOID , TYPE_INT , 0, 0, "arrayinstanceof (calling patcher_builtin_arrayinstanceof)" },
271 /* this record marks the end of the list */
273 { 0, NULL, 0, 0, 0, 0, 0, 0, 0, "<END>" }
277 #if defined(USEBUILTINTABLE)
279 static int stdopcompare(const void *a, const void *b)
281 builtin_descriptor *o1 = (builtin_descriptor *) a;
282 builtin_descriptor *o2 = (builtin_descriptor *) b;
283 if (!o1->supported && o2->supported)
285 if (o1->supported && !o2->supported)
287 return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
291 void sort_builtintable(void)
296 while (builtin_desc[len].opcode != 255) len++;
297 qsort(builtin_desc, len, sizeof(builtin_descriptor), stdopcompare);
299 for (--len; len>=0 && builtin_desc[len].supported; len--);
300 builtintablelen = ++len;
304 builtin_descriptor *find_builtin(int icmd)
306 builtin_descriptor *first = builtin_desc;
307 builtin_descriptor *last = builtin_desc + builtintablelen;
308 int len = last - first;
310 builtin_descriptor *middle;
314 middle = first + half;
315 if (middle->opcode < icmd) {
321 return first != last ? first : NULL;
324 #endif /* defined(USEBUILTINTABLE) */
327 /*****************************************************************************
329 *****************************************************************************/
333 /*************** internal function: builtin_isanysubclass *********************
335 Checks a subclass relation between two classes. Implemented interfaces
336 are interpreted as super classes.
337 Return value: 1 ... sub is subclass of super
340 *****************************************************************************/
341 s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
344 castinfo classvalues;
349 if (super->flags & ACC_INTERFACE)
350 return (sub->vftbl->interfacetablelength > super->index) &&
351 (sub->vftbl->interfacetable[-super->index] != NULL);
353 asm_getclassvalues_atomic(super->vftbl, sub->vftbl, &classvalues);
355 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval) <=
356 (u4) classvalues.super_diffval;
362 s4 builtin_isanysubclass_vftbl(vftbl_t *sub, vftbl_t *super)
366 castinfo classvalues;
371 asm_getclassvalues_atomic(super, sub, &classvalues);
373 if ((base = classvalues.super_baseval) <= 0)
374 /* super is an interface */
375 res = (sub->interfacetablelength > -base) &&
376 (sub->interfacetable[base] != NULL);
378 res = (u4) (classvalues.sub_baseval - classvalues.super_baseval)
379 <= (u4) classvalues.super_diffval;
385 /****************** function: builtin_instanceof *****************************
387 Checks if an object is an instance of some given class (or subclass of
388 that class). If class is an interface, checks if the interface is
390 Return value: 1 ... obj is an instance of class or implements the interface
391 0 ... otherwise or if obj == NULL
393 *****************************************************************************/
395 /* XXX should use vftbl */
396 s4 builtin_instanceof(java_objectheader *obj, classinfo *class)
399 log_text ("builtin_instanceof called");
404 return builtin_isanysubclass(obj->vftbl->class, class);
409 /**************** function: builtin_checkcast *******************************
411 The same as builtin_instanceof except that 1 is returned when
414 ****************************************************************************/
416 /* XXX should use vftbl */
417 s4 builtin_checkcast(java_objectheader *obj, classinfo *class)
420 log_text("builtin_checkcast called");
425 if (builtin_isanysubclass(obj->vftbl->class, class))
429 printf("#### checkcast failed ");
430 utf_display(obj->vftbl->class->name);
432 utf_display(class->name);
440 /* builtin_descriptorscompatible ***********************************************
442 Checks if two array type descriptors are assignment compatible
444 Return value: 1 ... target = desc is possible
447 *******************************************************************************/
449 static s4 builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
454 if (desc->arraytype != target->arraytype)
457 if (desc->arraytype != ARRAYTYPE_OBJECT)
460 /* {both arrays are arrays of references} */
462 if (desc->dimension == target->dimension) {
463 /* an array which contains elements of interface types is allowed to be casted to Object (JOWENN)*/
464 if ( (desc->elementvftbl->baseval<0) && (target->elementvftbl->baseval==1) ) return 1;
465 return builtin_isanysubclass_vftbl(desc->elementvftbl,target->elementvftbl);
467 if (desc->dimension < target->dimension) return 0;
469 /* {desc has higher dimension than target} */
470 return builtin_isanysubclass_vftbl(pseudo_class_Arraystub->vftbl, target->elementvftbl);
474 /* builtin_arraycheckcast ******************************************************
476 Checks if an object is really a subtype of the requested array
477 type. The object has to be an array to begin with. For simple
478 arrays (int, short, double, etc.) the types have to match exactly.
479 For arrays of objects, the type of elements in the array has to be
480 a subtype (or the same type) of the requested element type. For
481 arrays of arrays (which in turn can again be arrays of arrays), the
482 types at the lowest level have to satisfy the corresponding sub
485 *******************************************************************************/
487 s4 builtin_arraycheckcast(java_objectheader *o, vftbl_t *target)
489 arraydescriptor *desc;
494 if ((desc = o->vftbl->arraydesc) == NULL)
497 return builtin_descriptorscompatible(desc, target->arraydesc);
501 s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl_t *target)
506 return builtin_arraycheckcast(obj, target);
510 /************************** exception functions *******************************
512 ******************************************************************************/
514 java_objectheader *builtin_throw_exception(java_objectheader *xptr)
516 java_lang_Throwable *t;
521 t = (java_lang_Throwable *) xptr;
523 /* calculate message length */
525 logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
529 utf_strlen(xptr->vftbl->class->name) +
531 javastring_strlen((java_objectheader *) t->detailMessage);
534 logtextlen += strlen("(nil)");
536 /* allocate memory */
538 logtext = MNEW(char, logtextlen);
540 strcpy(logtext, "Builtin exception thrown: ");
543 utf_sprint_classname(logtext + strlen(logtext),
544 xptr->vftbl->class->name);
546 if (t->detailMessage) {
549 buf = javastring_tochar((java_objectheader *) t->detailMessage);
550 strcat(logtext, ": ");
551 strcat(logtext, buf);
552 MFREE(buf, char, strlen(buf));
556 strcat(logtext, "(nil)");
563 MFREE(logtext, char, logtextlen);
566 *exceptionptr = xptr;
573 /******************* function: builtin_canstore *******************************
575 Checks, if an object can be stored in an array.
576 Return value: 1 ... possible
579 ******************************************************************************/
581 s4 builtin_canstore (java_objectarray *a, java_objectheader *o)
583 arraydescriptor *desc;
584 arraydescriptor *valuedesc;
585 vftbl_t *componentvftbl;
589 castinfo classvalues;
593 /* The following is guaranteed (by verifier checks):
595 * *) a->...vftbl->arraydesc != NULL
596 * *) a->...vftbl->arraydesc->componentvftbl != NULL
597 * *) o->vftbl is not an interface vftbl
600 desc = a->header.objheader.vftbl->arraydesc;
601 componentvftbl = desc->componentvftbl;
602 valuevftbl = o->vftbl;
604 if ((dim_m1 = desc->dimension - 1) == 0) {
607 /* {a is a one-dimensional array} */
608 /* {a is an array of references} */
610 if (valuevftbl == componentvftbl)
613 asm_getclassvalues_atomic(componentvftbl, valuevftbl, &classvalues);
615 if ((base = classvalues.super_baseval) <= 0)
616 /* an array of interface references */
617 return (valuevftbl->interfacetablelength > -base &&
618 valuevftbl->interfacetable[base] != NULL);
620 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
621 <= (unsigned) classvalues.super_diffval;
625 /* {a has dimension > 1} */
626 /* {componentvftbl->arraydesc != NULL} */
628 /* check if o is an array */
629 if ((valuedesc = valuevftbl->arraydesc) == NULL)
631 /* {o is an array} */
633 return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
637 /* This is an optimized version where a is guaranteed to be one-dimensional */
638 s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
640 arraydescriptor *desc;
641 vftbl_t *elementvftbl;
645 castinfo classvalues;
649 /* The following is guaranteed (by verifier checks):
651 * *) a->...vftbl->arraydesc != NULL
652 * *) a->...vftbl->arraydesc->elementvftbl != NULL
653 * *) a->...vftbl->arraydesc->dimension == 1
654 * *) o->vftbl is not an interface vftbl
657 desc = a->header.objheader.vftbl->arraydesc;
658 elementvftbl = desc->elementvftbl;
659 valuevftbl = o->vftbl;
661 /* {a is a one-dimensional array} */
663 if (valuevftbl == elementvftbl)
666 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
668 if ((base = classvalues.super_baseval) <= 0)
669 /* an array of interface references */
670 return (valuevftbl->interfacetablelength > -base &&
671 valuevftbl->interfacetable[base] != NULL);
673 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
674 <= (unsigned) classvalues.super_diffval;
680 /* This is an optimized version where a is guaranteed to be a
681 * one-dimensional array of a class type */
682 s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
684 vftbl_t *elementvftbl;
687 castinfo classvalues;
691 /* The following is guaranteed (by verifier checks):
693 * *) a->...vftbl->arraydesc != NULL
694 * *) a->...vftbl->arraydesc->elementvftbl != NULL
695 * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
696 * *) a->...vftbl->arraydesc->dimension == 1
697 * *) o->vftbl is not an interface vftbl
700 elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
701 valuevftbl = o->vftbl;
703 /* {a is a one-dimensional array} */
705 if (valuevftbl == elementvftbl)
708 asm_getclassvalues_atomic(elementvftbl, valuevftbl, &classvalues);
710 res = (unsigned) (classvalues.sub_baseval - classvalues.super_baseval)
711 <= (unsigned) classvalues.super_diffval;
717 /* builtin_new *****************************************************************
719 Creates a new instance of class c on the heap.
721 Return value: pointer to the object or NULL if no memory is
724 *******************************************************************************/
726 java_objectheader *builtin_new(classinfo *c)
728 java_objectheader *o;
730 /* is the class loaded */
731 /*utf_fprint(stderr,c->name);fprintf(stderr,"\n");*/
734 /* is the class linked */
739 if (!c->initialized) {
741 log_message_class("Initialize class (from builtin_new): ", c);
743 if (!initialize_class(c))
747 o = heap_allocate(c->instancesize, true, c->finalizer);
752 MSET(o, 0, u1, c->instancesize);
756 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
764 /* builtin_newarray ************************************************************
766 Creates an array with the given vftbl on the heap.
768 Return value: pointer to the array or NULL if no memory is available
770 CAUTION: The given vftbl must be the vftbl of the *array* class,
771 not of the element class.
773 *******************************************************************************/
775 java_arrayheader *builtin_newarray(s4 size, vftbl_t *arrayvftbl)
778 arraydescriptor *desc;
783 desc = arrayvftbl->arraydesc;
784 dataoffset = desc->dataoffset;
785 componentsize = desc->componentsize;
788 *exceptionptr = new_negativearraysizeexception();
792 actualsize = dataoffset + size * componentsize;
794 if (((u4) actualsize) < ((u4) size)) { /* overflow */
795 *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
799 a = heap_allocate(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL);
804 MSET(a, 0, u1, actualsize);
806 a->objheader.vftbl = arrayvftbl;
808 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
809 initObjectLock(&a->objheader);
818 /* builtin_anewarray ***********************************************************
820 Creates an array of references to the given class type on the heap.
822 Return value: pointer to the array or NULL if no memory is
825 *******************************************************************************/
827 java_objectarray *builtin_anewarray(s4 size, classinfo *component)
831 /* is class loaded */
832 assert(component->loaded);
834 /* is class linked */
835 if (!component->linked)
836 if (!link_class(component))
839 c = class_array_of(component, true);
844 return (java_objectarray *) builtin_newarray(size, c->vftbl);
848 /* builtin_newarray_int ********************************************************
850 Creates an array of 32 bit Integers on the heap.
852 Return value: pointer to the array or NULL if no memory is
855 *******************************************************************************/
857 java_intarray *builtin_newarray_int(s4 size)
859 return (java_intarray *)
860 builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
864 /* builtin_newarray_long *******************************************************
866 Creates an array of 64 bit Integers on the heap.
868 Return value: pointer to the array or NULL if no memory is
871 *******************************************************************************/
873 java_longarray *builtin_newarray_long(s4 size)
875 return (java_longarray *)
876 builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
880 /* builtin_newarray_float ******************************************************
882 Creates an array of 32 bit IEEE floats on the heap.
884 Return value: pointer to the array or NULL if no memory is
887 *******************************************************************************/
889 java_floatarray *builtin_newarray_float(s4 size)
891 return (java_floatarray *)
892 builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
896 /* builtin_newarray_double *****************************************************
898 Creates an array of 64 bit IEEE floats on the heap.
900 Return value: pointer to the array or NULL if no memory is
903 *******************************************************************************/
905 java_doublearray *builtin_newarray_double(s4 size)
907 return (java_doublearray *)
908 builtin_newarray(size,
909 primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
913 /* builtin_newarray_byte *******************************************************
915 Creates an array of 8 bit Integers on the heap.
917 Return value: pointer to the array or NULL if no memory is
920 *******************************************************************************/
922 java_bytearray *builtin_newarray_byte(s4 size)
924 return (java_bytearray *)
925 builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
929 /* builtin_newarray_char *******************************************************
931 Creates an array of characters on the heap.
933 Return value: pointer to the array or NULL if no memory is
936 *******************************************************************************/
938 java_chararray *builtin_newarray_char(s4 size)
940 return (java_chararray *)
941 builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
945 /* builtin_newarray_short ******************************************************
947 Creates an array of 16 bit Integers on the heap.
949 Return value: pointer to the array or NULL if no memory is
952 *******************************************************************************/
954 java_shortarray *builtin_newarray_short(s4 size)
956 return (java_shortarray *)
957 builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
961 /* builtin_newarray_boolean ****************************************************
963 Creates an array of bytes on the heap. The array is designated as
964 an array of booleans (important for casts)
966 Return value: pointer to the array or NULL if no memory is
969 *******************************************************************************/
971 java_booleanarray *builtin_newarray_boolean(s4 size)
973 return (java_booleanarray *)
974 builtin_newarray(size,
975 primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
979 /* builtin_multianewarray ******************************************************
981 Creates a multi-dimensional array on the heap. The dimensions are
982 passed in an array of longs.
985 n............number of dimensions to create
986 arrayvftbl...vftbl of the array class
987 dims.........array containing the size of each dimension to create
989 Return value: pointer to the array or NULL if no memory is
992 ******************************************************************************/
994 java_arrayheader *builtin_multianewarray(int n, vftbl_t *arrayvftbl, long *dims)
998 vftbl_t *componentvftbl;
1000 /* create this dimension */
1002 size = (s4) dims[0];
1003 a = builtin_newarray(size, arrayvftbl);
1008 /* if this is the last dimension return */
1013 /* get the vftbl of the components to create */
1015 componentvftbl = arrayvftbl->arraydesc->componentvftbl;
1017 /* The verifier guarantees that the dimension count is in the range. */
1019 /* create the component arrays */
1021 for (i = 0; i < size; i++) {
1022 java_arrayheader *ea =
1023 builtin_multianewarray(n, componentvftbl, dims + 1);
1028 ((java_objectarray *) a)->data[i] = (java_objectheader *) ea;
1035 /*****************************************************************************
1038 Various functions for printing a message at method entry or exit (for
1041 *****************************************************************************/
1043 u4 methodindent = 0;
1045 java_objectheader *builtin_trace_exception(java_objectheader *xptr,
1058 log_text("WARNING: unmatched methodindent--");
1061 if (opt_verbose || runverbose || verboseexception) {
1062 /* calculate message length */
1066 strlen("Exception ") +
1067 utf_strlen(xptr->vftbl->class->name);
1070 logtextlen = strlen("Some Throwable");
1072 logtextlen += strlen(" thrown in ");
1076 utf_strlen(m->class->name) +
1078 utf_strlen(m->name) +
1079 strlen("(NOSYNC,NATIVE");
1081 #if POINTERSIZE == 8
1083 get_variable_message_length(")(0x%016lx) at position 0x%016lx (",
1084 (ptrint) m->entrypoint,
1088 get_variable_message_length(")(0x%08x) at position 0x%08x (",
1089 (ptrint) m->entrypoint,
1093 if (m->class->sourcefile == NULL)
1094 logtextlen += strlen("<NO CLASSFILE INFORMATION>");
1096 logtextlen += utf_strlen(m->class->sourcefile);
1098 logtextlen += get_variable_message_length(":%d)", line);
1101 logtextlen += strlen("call_java_method");
1103 logtextlen += strlen("0");
1105 /* allocate memory */
1107 logtext = MNEW(char, logtextlen);
1110 strcpy(logtext, "Exception ");
1111 utf_strcat_classname(logtext, xptr->vftbl->class->name);
1114 strcpy(logtext, "Some Throwable");
1117 strcat(logtext, " thrown in ");
1120 utf_strcat_classname(logtext, m->class->name);
1121 strcat(logtext, ".");
1122 utf_strcat(logtext, m->name);
1124 if (m->flags & ACC_SYNCHRONIZED)
1125 strcat(logtext, "(SYNC");
1127 strcat(logtext, "(NOSYNC");
1129 if (m->flags & ACC_NATIVE) {
1130 strcat(logtext, ",NATIVE");
1132 #if POINTERSIZE == 8
1133 sprintf(logtext + strlen(logtext),
1134 ")(0x%016lx) at position 0x%016lx",
1135 (ptrint) m->entrypoint, (ptrint) pos);
1137 sprintf(logtext + strlen(logtext),
1138 ")(0x%08x) at position 0x%08x",
1139 (ptrint) m->entrypoint, (ptrint) pos);
1143 #if POINTERSIZE == 8
1144 sprintf(logtext + strlen(logtext),
1145 ")(0x%016lx) at position 0x%016lx (",
1146 (ptrint) m->entrypoint, (ptrint) pos);
1148 sprintf(logtext + strlen(logtext),
1149 ")(0x%08x) at position 0x%08x (",
1150 (ptrint) m->entrypoint, (ptrint) pos);
1153 if (m->class->sourcefile == NULL)
1154 strcat(logtext, "<NO CLASSFILE INFORMATION>");
1156 utf_strcat(logtext, m->class->sourcefile);
1158 sprintf(logtext + strlen(logtext), ":%d)", line);
1162 strcat(logtext, "call_java_method");
1166 /* release memory */
1168 MFREE(logtext, char, logtextlen);
1175 /* builtin_trace_args **********************************************************
1179 *******************************************************************************/
1181 #ifdef TRACE_ARGS_NUM
1182 void builtin_trace_args(s8 a0, s8 a1, s8 a2, s8 a3,
1183 #if TRACE_ARGS_NUM >= 6
1186 #if TRACE_ARGS_NUM == 8
1195 /* calculate message length */
1198 methodindent + strlen("called: ") +
1199 utf_strlen(m->class->name) +
1201 utf_strlen(m->name) +
1202 utf_strlen(m->descriptor) +
1203 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1205 /* add maximal argument length */
1207 logtextlen += get_variable_message_length("0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1208 -1, -1, -1, -1, -1, -1, -1, -1,
1211 /* allocate memory */
1213 logtext = MNEW(char, logtextlen);
1215 for (i = 0; i < methodindent; i++)
1218 strcpy(logtext + methodindent, "called: ");
1220 utf_strcat_classname(logtext, m->class->name);
1221 strcat(logtext, ".");
1222 utf_strcat(logtext, m->name);
1223 utf_strcat(logtext, m->descriptor);
1225 if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
1226 if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
1227 if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
1228 if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
1229 if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
1230 if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
1231 if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
1232 if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
1233 if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
1234 if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
1235 if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
1237 strcat(logtext, "(");
1239 switch (m->paramcount) {
1243 #if defined(__I386__) || defined(__POWERPC__)
1245 sprintf(logtext + strlen(logtext),
1251 sprintf(logtext + strlen(logtext),
1257 sprintf(logtext + strlen(logtext),
1258 "0x%llx, 0x%llx, 0x%llx",
1263 sprintf(logtext + strlen(logtext),
1264 "0x%llx, 0x%llx, 0x%llx, 0x%llx",
1268 #if TRACE_ARGS_NUM >= 6
1270 sprintf(logtext + strlen(logtext),
1271 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx",
1272 a0, a1, a2, a3, a4);
1276 sprintf(logtext + strlen(logtext),
1277 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx",
1278 a0, a1, a2, a3, a4, a5);
1280 #endif /* TRACE_ARGS_NUM >= 6 */
1282 #if TRACE_ARGS_NUM == 8
1284 sprintf(logtext + strlen(logtext),
1285 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx",
1286 a0, a1, a2, a3, a4, a5, a6);
1290 sprintf(logtext + strlen(logtext),
1291 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx",
1292 a0, a1, a2, a3, a4, a5, a6, a7);
1296 sprintf(logtext + strlen(logtext),
1297 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1298 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1300 #else /* TRACE_ARGS_NUM == 8 */
1302 sprintf(logtext + strlen(logtext),
1303 "0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, ...(%d)",
1304 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1306 #endif /* TRACE_ARGS_NUM == 8 */
1308 #else /* defined(__I386__) || defined(__POWERPC__) */
1310 sprintf(logtext + strlen(logtext),
1316 sprintf(logtext + strlen(logtext),
1322 sprintf(logtext + strlen(logtext),
1323 "0x%lx, 0x%lx, 0x%lx", a0, a1, a2);
1327 sprintf(logtext + strlen(logtext),
1328 "0x%lx, 0x%lx, 0x%lx, 0x%lx",
1332 #if TRACE_ARGS_NUM >= 6
1334 sprintf(logtext + strlen(logtext),
1335 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1336 a0, a1, a2, a3, a4);
1340 sprintf(logtext + strlen(logtext),
1341 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1342 a0, a1, a2, a3, a4, a5);
1344 #endif /* TRACE_ARGS_NUM >= 6 */
1346 #if TRACE_ARGS_NUM == 8
1348 sprintf(logtext + strlen(logtext),
1349 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1350 a0, a1, a2, a3, a4, a5, a6);
1354 sprintf(logtext + strlen(logtext),
1355 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx",
1356 a0, a1, a2, a3, a4, a5, a6, a7);
1358 #endif /* TRACE_ARGS_NUM == 8 */
1361 #if TRACE_ARGS_NUM == 4
1362 sprintf(logtext + strlen(logtext),
1363 "0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1364 a0, a1, a2, a3, m->paramcount - 4);
1366 #elif TRACE_ARGS_NUM == 6
1367 sprintf(logtext + strlen(logtext),
1368 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1369 a0, a1, a2, a3, a4, a5, m->paramcount - 6);
1371 #elif TRACE_ARGS_NUM == 8
1372 sprintf(logtext + strlen(logtext),
1373 "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, ...(%d)",
1374 a0, a1, a2, a3, a4, a5, a6, a7, m->paramcount - 8);
1377 #endif /* defined(__I386__) || defined(__POWERPC__) */
1380 strcat(logtext, ")");
1384 /* release memory */
1386 MFREE(logtext, char, logtextlen);
1393 /* builtin_displaymethodstop ***************************************************
1397 *******************************************************************************/
1399 void builtin_displaymethodstop(methodinfo *m, s8 l, double d, float f)
1405 /* calculate message length */
1408 methodindent + strlen("finished: ") +
1409 utf_strlen(m->class->name) +
1411 utf_strlen(m->name) +
1412 utf_strlen(m->descriptor) +
1413 strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
1415 /* add maximal argument length */
1417 logtextlen += get_variable_message_length("->0x%llx", -1);
1419 /* allocate memory */
1421 logtext = MNEW(char, logtextlen);
1423 /* generate the message */
1425 for (i = 0; i < methodindent; i++)
1431 log_text("WARNING: unmatched methodindent--");
1433 strcpy(logtext + methodindent, "finished: ");
1434 utf_strcat_classname(logtext, m->class->name);
1435 strcat(logtext, ".");
1436 utf_strcat(logtext, m->name);
1437 utf_strcat(logtext, m->descriptor);
1439 switch (m->returntype) {
1441 sprintf(logtext + strlen(logtext), "->%d", (s4) l);
1445 #if defined(__I386__) || defined(__POWERPC__)
1446 sprintf(logtext + strlen(logtext), "->%lld", (s8) l);
1448 sprintf(logtext + strlen(logtext), "->%ld", (s8) l);
1453 sprintf(logtext + strlen(logtext), "->%p", (void *) (ptrint) l);
1457 sprintf(logtext + strlen(logtext), "->%g", f);
1461 sprintf(logtext + strlen(logtext), "->%g", d);
1467 /* release memory */
1469 MFREE(logtext, char, logtextlen);
1473 /****************************************************************************
1474 SYNCHRONIZATION FUNCTIONS
1475 *****************************************************************************/
1477 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1479 * Lock the mutex of an object.
1481 void internal_lock_mutex_for_object(java_objectheader *object)
1483 mutexHashEntry *entry;
1486 assert(object != 0);
1488 hashValue = MUTEX_HASH_VALUE(object);
1489 entry = &mutexHashTable[hashValue];
1491 if (entry->object != 0) {
1492 if (entry->mutex.count == 0 && entry->conditionCount == 0) {
1494 entry->mutex.holder = 0;
1495 entry->mutex.count = 0;
1496 entry->mutex.muxWaiters = 0;
1499 while (entry->next != 0 && entry->object != object)
1500 entry = entry->next;
1502 if (entry->object != object) {
1503 entry->next = firstFreeOverflowEntry;
1504 firstFreeOverflowEntry = firstFreeOverflowEntry->next;
1506 entry = entry->next;
1509 assert(entry->conditionCount == 0);
1514 entry->mutex.holder = 0;
1515 entry->mutex.count = 0;
1516 entry->mutex.muxWaiters = 0;
1519 if (entry->object == 0)
1520 entry->object = object;
1522 internal_lock_mutex(&entry->mutex);
1527 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
1529 * Unlocks the mutex of an object.
1531 void internal_unlock_mutex_for_object (java_objectheader *object)
1534 mutexHashEntry *entry;
1536 hashValue = MUTEX_HASH_VALUE(object);
1537 entry = &mutexHashTable[hashValue];
1539 if (entry->object == object) {
1540 internal_unlock_mutex(&entry->mutex);
1543 while (entry->next != 0 && entry->next->object != object)
1544 entry = entry->next;
1546 assert(entry->next != 0);
1548 internal_unlock_mutex(&entry->next->mutex);
1550 if (entry->next->mutex.count == 0 && entry->conditionCount == 0) {
1551 mutexHashEntry *unlinked = entry->next;
1553 entry->next = unlinked->next;
1554 unlinked->next = firstFreeOverflowEntry;
1555 firstFreeOverflowEntry = unlinked;
1562 #if defined(USE_THREADS)
1563 void builtin_monitorenter(java_objectheader *o)
1565 #if !defined(NATIVE_THREADS)
1570 hashValue = MUTEX_HASH_VALUE(o);
1571 if (mutexHashTable[hashValue].object == o
1572 && mutexHashTable[hashValue].mutex.holder == currentThread)
1573 ++mutexHashTable[hashValue].mutex.count;
1575 internal_lock_mutex_for_object(o);
1579 monitorEnter((threadobject *) THREADOBJECT, o);
1585 #if defined(USE_THREADS)
1587 * Locks the class object - needed for static synchronized methods.
1588 * The use_class_as_object call is needed in order to circumvent a
1589 * possible deadlock with builtin_monitorenter called by another
1590 * thread calling use_class_as_object.
1592 void builtin_staticmonitorenter(classinfo *c)
1594 use_class_as_object(c);
1595 builtin_monitorenter(&c->header);
1600 #if defined(USE_THREADS)
1601 void builtin_monitorexit(java_objectheader *o)
1603 #if !defined(NATIVE_THREADS)
1608 hashValue = MUTEX_HASH_VALUE(o);
1609 if (mutexHashTable[hashValue].object == o) {
1610 if (mutexHashTable[hashValue].mutex.count == 1
1611 && mutexHashTable[hashValue].mutex.muxWaiters != 0)
1612 internal_unlock_mutex_for_object(o);
1614 --mutexHashTable[hashValue].mutex.count;
1617 internal_unlock_mutex_for_object(o);
1621 monitorExit((threadobject *) THREADOBJECT, o);
1627 /*****************************************************************************
1628 MISCELLANEOUS HELPER FUNCTIONS
1629 *****************************************************************************/
1633 /*********** Functions for integer divisions *****************************
1635 On some systems (eg. DEC ALPHA), integer division is not supported by the
1636 CPU. These helper functions implement the missing functionality.
1638 ******************************************************************************/
1640 s4 builtin_idiv(s4 a, s4 b) { return a / b; }
1641 s4 builtin_irem(s4 a, s4 b) { return a % b; }
1644 /************** Functions for long arithmetics *******************************
1646 On systems where 64 bit Integers are not supported by the CPU, these
1647 functions are needed.
1649 ******************************************************************************/
1652 s8 builtin_ladd(s8 a, s8 b)
1657 return builtin_i2l(0);
1661 s8 builtin_lsub(s8 a, s8 b)
1666 return builtin_i2l(0);
1670 s8 builtin_lmul(s8 a, s8 b)
1675 return builtin_i2l(0);
1679 s8 builtin_ldiv(s8 a, s8 b)
1684 return builtin_i2l(0);
1688 s8 builtin_lrem(s8 a, s8 b)
1693 return builtin_i2l(0);
1697 s8 builtin_lshl(s8 a, s4 b)
1700 return a << (b & 63);
1702 return builtin_i2l(0);
1706 s8 builtin_lshr(s8 a, s4 b)
1709 return a >> (b & 63);
1711 return builtin_i2l(0);
1715 s8 builtin_lushr(s8 a, s4 b)
1718 return ((u8) a) >> (b & 63);
1720 return builtin_i2l(0);
1724 s8 builtin_land(s8 a, s8 b)
1729 return builtin_i2l(0);
1733 s8 builtin_lor(s8 a, s8 b)
1738 return builtin_i2l(0);
1742 s8 builtin_lxor(s8 a, s8 b)
1747 return builtin_i2l(0);
1751 s8 builtin_lneg(s8 a)
1756 return builtin_i2l(0);
1760 s4 builtin_lcmp(s8 a, s8 b)
1763 if (a < b) return -1;
1764 if (a > b) return 1;
1775 /*********** Functions for floating point operations *************************/
1777 float builtin_fadd(float a, float b)
1779 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1780 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1791 if (copysignf(1.0, a) == copysignf(1.0, b))
1794 return intBitsToFloat(FLT_NAN);
1800 float builtin_fsub(float a, float b)
1802 return builtin_fadd(a, builtin_fneg(b));
1806 float builtin_fmul(float a, float b)
1808 if (isnanf(a)) return intBitsToFloat(FLT_NAN);
1809 if (isnanf(b)) return intBitsToFloat(FLT_NAN);
1811 if (finitef(b)) return a * b;
1813 if (a == 0) return intBitsToFloat(FLT_NAN);
1814 else return copysignf(b, copysignf(1.0, b)*a);
1819 if (b == 0) return intBitsToFloat(FLT_NAN);
1820 else return copysignf(a, copysignf(1.0, a)*b);
1823 return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
1829 float builtin_fdiv(float a, float b)
1831 if (finitef(a) && finitef(b)) {
1836 return intBitsToFloat(FLT_POSINF);
1838 return intBitsToFloat(FLT_NEGINF);
1841 return intBitsToFloat(FLT_NAN);
1845 float builtin_frem(float a, float b)
1851 float builtin_fneg(float a)
1853 if (isnanf(a)) return a;
1855 if (finitef(a)) return -a;
1856 else return copysignf(a, -copysignf(1.0, a));
1861 s4 builtin_fcmpl(float a, float b)
1863 if (isnanf(a)) return -1;
1864 if (isnanf(b)) return -1;
1865 if (!finitef(a) || !finitef(b)) {
1866 a = finitef(a) ? 0 : copysignf(1.0, a);
1867 b = finitef(b) ? 0 : copysignf(1.0, b);
1869 if (a > b) return 1;
1870 if (a == b) return 0;
1875 s4 builtin_fcmpg(float a, float b)
1877 if (isnanf(a)) return 1;
1878 if (isnanf(b)) return 1;
1879 if (!finitef(a) || !finitef(b)) {
1880 a = finitef(a) ? 0 : copysignf(1.0, a);
1881 b = finitef(b) ? 0 : copysignf(1.0, b);
1883 if (a > b) return 1;
1884 if (a == b) return 0;
1890 /************************* Functions for doubles ****************************/
1892 double builtin_dadd(double a, double b)
1894 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1895 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1897 if (finite(b)) return a + b;
1901 if (finite(b)) return a;
1903 if (copysign(1.0, a)==copysign(1.0, b)) return a;
1904 else return longBitsToDouble(DBL_NAN);
1910 double builtin_dsub(double a, double b)
1912 return builtin_dadd(a, builtin_dneg(b));
1916 double builtin_dmul(double a, double b)
1918 if (isnan(a)) return longBitsToDouble(DBL_NAN);
1919 if (isnan(b)) return longBitsToDouble(DBL_NAN);
1921 if (finite(b)) return a * b;
1923 if (a == 0) return longBitsToDouble(DBL_NAN);
1924 else return copysign(b, copysign(1.0, b) * a);
1929 if (b == 0) return longBitsToDouble(DBL_NAN);
1930 else return copysign(a, copysign(1.0, a) * b);
1933 return copysign(a, copysign(1.0, a) * copysign(1.0, b));
1939 double builtin_ddiv(double a, double b)
1947 return longBitsToDouble(DBL_NAN);
1949 return copysign(0.0, b);
1955 return longBitsToDouble(DBL_POSINF);
1957 return longBitsToDouble(DBL_NEGINF);
1960 return longBitsToDouble(DBL_NAN);
1963 /* if (finite(a) && finite(b)) { */
1968 /* return longBitsToDouble(DBL_POSINF); */
1969 /* else if (a < 0) */
1970 /* return longBitsToDouble(DBL_NEGINF); */
1974 /* keep compiler happy */
1979 double builtin_drem(double a, double b)
1985 double builtin_dneg(double a)
1987 if (isnan(a)) return a;
1989 if (finite(a)) return -a;
1990 else return copysign(a, -copysign(1.0, a));
1995 s4 builtin_dcmpl(double a, double b)
1997 if (isnan(a)) return -1;
1998 if (isnan(b)) return -1;
1999 if (!finite(a) || !finite(b)) {
2000 a = finite(a) ? 0 : copysign(1.0, a);
2001 b = finite(b) ? 0 : copysign(1.0, b);
2003 if (a > b) return 1;
2004 if (a == b) return 0;
2009 s4 builtin_dcmpg(double a, double b)
2011 if (isnan(a)) return 1;
2012 if (isnan(b)) return 1;
2013 if (!finite(a) || !finite(b)) {
2014 a = finite(a) ? 0 : copysign(1.0, a);
2015 b = finite(b) ? 0 : copysign(1.0, b);
2017 if (a > b) return 1;
2018 if (a == b) return 0;
2023 /*********************** Conversion operations ****************************/
2025 s8 builtin_i2l(s4 i)
2038 float builtin_i2f(s4 a)
2040 float f = (float) a;
2045 double builtin_i2d(s4 a)
2047 double d = (double) a;
2052 s4 builtin_l2i(s8 l)
2062 float builtin_l2f(s8 a)
2065 float f = (float) a;
2073 double builtin_l2d(s8 a)
2076 double d = (double) a;
2084 s4 builtin_f2i(float a)
2087 return builtin_d2i((double) a);
2096 if (a < (-2147483648))
2097 return (-2147483648);
2100 f = copysignf((float) 1.0, a);
2103 return (-2147483648); */
2107 s8 builtin_f2l(float a)
2110 return builtin_d2l((double) a);
2115 if (a > 9223372036854775807L)
2116 return 9223372036854775807L;
2117 if (a < (-9223372036854775808L))
2118 return (-9223372036854775808L);
2123 f = copysignf((float) 1.0, a);
2125 return 9223372036854775807L;
2126 return (-9223372036854775808L); */
2130 double builtin_f2d(float a)
2132 if (finitef(a)) return (double) a;
2135 return longBitsToDouble(DBL_NAN);
2137 return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
2142 s4 builtin_d2i(double a)
2147 if (a >= 2147483647)
2149 if (a <= (-2147483647-1))
2150 return (-2147483647-1);
2155 d = copysign(1.0, a);
2158 return (-2147483647-1);
2162 s8 builtin_d2l(double a)
2167 if (a >= 9223372036854775807LL)
2168 return 9223372036854775807LL;
2169 if (a <= (-9223372036854775807LL-1))
2170 return (-9223372036854775807LL-1);
2175 d = copysign(1.0, a);
2177 return 9223372036854775807LL;
2178 return (-9223372036854775807LL-1);
2182 float builtin_d2f(double a)
2188 return intBitsToFloat(FLT_NAN);
2190 return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
2195 /* used to convert FLT_xxx defines into float values */
2197 inline float intBitsToFloat(s4 i)
2206 /* used to convert DBL_xxx defines into double values */
2208 inline float longBitsToDouble(s8 l)
2217 java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
2219 return (java_arrayheader *)
2220 Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
2224 s4 builtin_dummy(void)
2226 log_text("Internal error: builtin_dummy called (native function is missing)");
2229 /* keep the compiler happy */
2235 /* builtin_asm_get_exceptionptrptr *********************************************
2237 this is a wrapper for calls from asmpart
2239 *******************************************************************************/
2241 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2242 java_objectheader **builtin_asm_get_exceptionptrptr()
2244 return builtin_get_exceptionptrptr();
2249 methodinfo *builtin_asm_get_threadrootmethod()
2251 return *threadrootmethod;
2255 inline void* builtin_asm_get_stackframeinfo()
2257 /*log_text("builtin_asm_get_stackframeinfo()");*/
2258 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2259 /*printf("stackframeinfo: %p,%p\n",&THREADINFO->_stackframeinfo,*(&THREADINFO->_stackframeinfo));*/
2260 return &THREADINFO->_stackframeinfo;
2262 /* XXX FIXME FOR OLD THREAD IMPL (jowenn) */
2264 return &_thread_nativestackframeinfo; /* no threading, at least no native*/
2268 stacktraceelement *builtin_stacktrace_copy(stacktraceelement **el,stacktraceelement *begin, stacktraceelement *end) {
2269 /* stacktraceelement *el;*/
2272 /*printf ("begin: %p, end: %p, diff: %ld, size :%ld\n",begin,end,s,s*sizeof(stacktraceelement));*/
2273 *el=heap_allocate(sizeof(stacktraceelement)*(s+1), true, 0);
2275 *el=MNEW(stacktraceelement,s+1); /*GC*/
2277 memcpy(*el,begin,(end-begin)*sizeof(stacktraceelement));
2280 /* XXX change this if line numbers bigger than u2 are allowed, the */
2281 /* currently supported class file format does no allow that */
2283 (*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 */
2288 * These are local overrides for various environment variables in Emacs.
2289 * Please do not remove this and leave it at the end of the file, where
2290 * Emacs will automagically detect them.
2291 * ---------------------------------------------------------------------
2294 * indent-tabs-mode: t