calls instead of machine instructions, using the C calling
convention.
- $Id: builtin.c 685 2003-12-04 01:25:54Z jowenn $
+ $Id: builtin.c 793 2003-12-16 18:50:39Z edwin $
*/
#include <assert.h>
#include <string.h>
+#include <math.h>
#include "main.h"
#include "global.h"
#include "builtin.h"
#include "loader.h"
#include "tables.h"
#include "asmpart.h"
+#include "mm/boehm.h"
#include "threads/thread.h"
#include "threads/locks.h"
#include "toolbox/loging.h"
#include "toolbox/memory.h"
+#include "nat/java_lang_Cloneable.h"
+#include "nat/java_lang_VMObject.h"
-#include "native-math.h"
#undef DEBUG /*define DEBUG 1*/
+/* XXX delete? */
+#if 0
builtin_descriptor builtin_desc[] = {
{(functionptr) builtin_instanceof, "instanceof"},
{(functionptr) builtin_checkcast, "checkcast"},
{(functionptr) builtin_d2f, "d2f"},
{(functionptr) NULL, "unknown"}
};
+#endif
/*****************************************************************************
0 ... otherwise
*****************************************************************************/
-
-s4 builtin_isanysubclass (classinfo *sub, classinfo *super)
+s4 builtin_isanysubclass(classinfo *sub, classinfo *super)
{
- classinfo *tmp;
+ s4 res;
+
+ /*classinfo *tmp;*/
if (super->flags & ACC_INTERFACE)
return (sub->vftbl->interfacetablelength > super->index) &&
(sub->vftbl->interfacetable[-super->index] != NULL);
sub->vftbl->baseval, super->vftbl->baseval, (unsigned)(sub->vftbl->baseval - super->vftbl->baseval),
super->vftbl->diffval); */
- return (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_lock();
+#endif
+
+ res = (unsigned) (sub->vftbl->baseval - super->vftbl->baseval) <=
(unsigned) (super->vftbl->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_unlock();
+#endif
+
+ return res;
}
/* XXX inline this? */
s4 builtin_isanysubclass_vftbl(vftbl *sub,vftbl *super)
{
int base;
+ s4 res;
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_lock();
+#endif
+
if ((base = super->baseval) <= 0)
/* super is an interface */
- return (sub->interfacetablelength > -base) &&
+ res = (sub->interfacetablelength > -base) &&
(sub->interfacetable[base] != NULL);
- return (unsigned) (sub->baseval - base)
- <= (unsigned) (super->diffval);
+ else
+ res = (unsigned) (sub->baseval - base)
+ <= (unsigned) (super->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_unlock();
+#endif
+
+ return res;
}
return builtin_isanysubclass_vftbl(pseudo_class_Arraystub_vftbl,target->elementvftbl);
}
+
/******************** function: builtin_checkarraycast ***********************
Checks if an object is really a subtype of the requested array type.
*****************************************************************************/
-s4 builtin_checkarraycast(java_objectheader *o,arraydescriptor *target)
+s4 builtin_checkarraycast(java_objectheader *o, vftbl *target)
{
arraydescriptor *desc;
if (!o) return 1;
if ((desc = o->vftbl->arraydesc) == NULL) return 0;
- return builtin_descriptorscompatible(desc,target);
+ return builtin_descriptorscompatible(desc, target->arraydesc);
}
-s4 builtin_arrayinstanceof(java_objectheader *obj,arraydescriptor *desc)
+
+s4 builtin_arrayinstanceof(java_objectheader *obj, vftbl *target)
{
if (!obj) return 1;
- return builtin_checkarraycast (obj, desc);
+ return builtin_checkarraycast(obj, target);
}
+
/************************** exception functions *******************************
******************************************************************************/
java_objectheader *builtin_throw_exception(java_objectheader *local_exceptionptr)
{
if (verbose) {
+ char logtext[MAXLOGTEXT];
sprintf(logtext, "Builtin exception thrown: ");
if (local_exceptionptr)
utf_sprint(logtext + strlen(logtext), local_exceptionptr->vftbl->class->name);
if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
if (!proto_java_lang_ThreadDeath) sprintf(logtext+strlen(logtext),"%s","proto_java_lang_ThreadDeath==0");
}
- dolog();
+ log_text(logtext);
}
exceptionptr = local_exceptionptr;
return local_exceptionptr;
valuevftbl = o->vftbl;
if ((dim_m1 = desc->dimension - 1) == 0) {
+ s4 res;
+
/* {a is a one-dimensional array} */
/* {a is an array of references} */
return (valuevftbl->interfacetablelength > -base &&
valuevftbl->interfacetable[base] != NULL);
- return (unsigned)(valuevftbl->baseval - base)
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_lock();
+#endif
+
+ res = (unsigned)(valuevftbl->baseval - base)
<= (unsigned)(componentvftbl->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_unlock();
+#endif
+
+ return res;
}
/* {a has dimension > 1} */
/* {componentvftbl->arraydesc != NULL} */
return builtin_descriptorscompatible(valuedesc,componentvftbl->arraydesc);
}
+
/* This is an optimized version where a is guaranteed to be one-dimensional */
s4 builtin_canstore_onedim (java_objectarray *a, java_objectheader *o)
{
vftbl *elementvftbl;
vftbl *valuevftbl;
int base;
+ s4 res;
if (!o) return 1;
return (valuevftbl->interfacetablelength > -base &&
valuevftbl->interfacetable[base] != NULL);
- return (unsigned)(valuevftbl->baseval - base)
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_lock();
+#endif
+
+ res = (unsigned)(valuevftbl->baseval - base)
<= (unsigned)(elementvftbl->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_unlock();
+#endif
+
+ return res;
}
+
/* This is an optimized version where a is guaranteed to be a
* one-dimensional array of a class type */
/* XXX this could be inlined by the code generator */
-s4 builtin_canstore_onedim_class (java_objectarray *a, java_objectheader *o)
+s4 builtin_canstore_onedim_class(java_objectarray *a, java_objectheader *o)
{
vftbl *elementvftbl;
vftbl *valuevftbl;
+ s4 res;
if (!o) return 1;
if (valuevftbl == elementvftbl)
return 1;
- return (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_lock();
+#endif
+
+ res = (unsigned)(valuevftbl->baseval - elementvftbl->baseval)
<= (unsigned)(elementvftbl->diffval);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ cast_unlock();
+#endif
+
+ return res;
}
*****************************************************************************/
-java_arrayheader *builtin_newarray(s4 size,vftbl *arrayvftbl)
+java_arrayheader *builtin_newarray(s4 size, vftbl *arrayvftbl)
{
- java_arrayheader *a;
- arraydescriptor *desc = arrayvftbl->arraydesc;
- s4 dataoffset = desc->dataoffset;
- s4 componentsize = desc->componentsize;
+ java_arrayheader *a;
+ arraydescriptor *desc = arrayvftbl->arraydesc;
+ s4 dataoffset = desc->dataoffset;
+ s4 componentsize = desc->componentsize;
+ s4 actualsize;
if (size<0) {
exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/NegativeArraySizeException")));
return NULL;
}
#ifdef SIZE_FROM_CLASSINFO
- s4 actualsize = align_size(dataoffset + size * componentsize);
+ actualsize = align_size(dataoffset + size * componentsize);
#else
- s4 actualsize = dataoffset + size * componentsize;
+ actualsize = dataoffset + size * componentsize;
#endif
- a = (java_arrayheader *)
- heap_allocate(actualsize,
- (desc->arraytype == ARRAYTYPE_OBJECT),
- NULL);
- if (!a) return NULL;
- memset(a,0,actualsize);
+ if (((u4)actualsize)<((u4)size)) { /* overflow */
+ exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/OutOfMemoryError")));
+ return NULL;
+ }
+ a = heap_allocate(actualsize,
+ (desc->arraytype == ARRAYTYPE_OBJECT),
+ NULL);
+
+ if (!a) return NULL;
+ memset(a, 0, actualsize);
/*printf("builtin_newarray: Created an array of size : %d\n",size);*/
- a->objheader.vftbl = arrayvftbl;
- a->size = size;
+ a->objheader.vftbl = arrayvftbl;
+ a->size = size;
#ifdef SIZE_FROM_CLASSINFO
- a->alignedsize = actualsize;
+ a->alignedsize = actualsize;
#endif
- return a;
+
+ return a;
}
+
/********************** Function: builtin_anewarray *************************
Creates an array of references to the given class type on the heap.
*****************************************************************************/
-java_objectarray *
-builtin_anewarray(s4 size,classinfo *component)
+java_objectarray *builtin_anewarray(s4 size, classinfo *component)
{
- return (java_objectarray*) builtin_newarray(size,class_array_of(component)->vftbl);
+ return (java_objectarray*) builtin_newarray(size, class_array_of(component)->vftbl);
}
+
/******************** Function: builtin_newarray_int ***********************
Creates an array of 32 bit Integers on the heap.
*****************************************************************************/
-java_intarray *builtin_newarray_int (s4 size)
+java_intarray *builtin_newarray_int(s4 size)
{
- return (java_intarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
+ return (java_intarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_INT].arrayvftbl);
}
+
/******************** Function: builtin_newarray_long ***********************
Creates an array of 64 bit Integers on the heap.
*****************************************************************************/
-java_longarray *builtin_newarray_long (s4 size)
+java_longarray *builtin_newarray_long(s4 size)
{
- return (java_longarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
+ return (java_longarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_LONG].arrayvftbl);
}
+
/******************** function: builtin_newarray_float ***********************
Creates an array of 32 bit IEEE floats on the heap.
*****************************************************************************/
-java_floatarray *builtin_newarray_float (s4 size)
+java_floatarray *builtin_newarray_float(s4 size)
{
- return (java_floatarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
+ return (java_floatarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_FLOAT].arrayvftbl);
}
+
/******************** function: builtin_newarray_double ***********************
Creates an array of 64 bit IEEE floats on the heap.
*****************************************************************************/
-java_doublearray *builtin_newarray_double (s4 size)
+java_doublearray *builtin_newarray_double(s4 size)
{
- return (java_doublearray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
+ return (java_doublearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_DOUBLE].arrayvftbl);
}
+
/******************** function: builtin_newarray_byte ***********************
Creates an array of 8 bit Integers on the heap.
*****************************************************************************/
-java_bytearray *builtin_newarray_byte (s4 size)
+java_bytearray *builtin_newarray_byte(s4 size)
{
- return (java_bytearray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
+ return (java_bytearray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BYTE].arrayvftbl);
}
+
/******************** function: builtin_newarray_char ************************
Creates an array of characters on the heap.
*****************************************************************************/
-java_chararray *builtin_newarray_char (s4 size)
+java_chararray *builtin_newarray_char(s4 size)
{
- return (java_chararray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
+ return (java_chararray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl);
}
+
/******************** function: builtin_newarray_short ***********************
Creates an array of 16 bit Integers on the heap.
*****************************************************************************/
-java_shortarray *builtin_newarray_short (s4 size)
+java_shortarray *builtin_newarray_short(s4 size)
{
- return (java_shortarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
+ return (java_shortarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_SHORT].arrayvftbl);
}
+
/******************** function: builtin_newarray_boolean ************************
Creates an array of bytes on the heap. The array is designated as an array
*****************************************************************************/
-java_booleanarray *builtin_newarray_boolean (s4 size)
+java_booleanarray *builtin_newarray_boolean(s4 size)
{
- return (java_booleanarray*) builtin_newarray(size,primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
+ return (java_booleanarray*) builtin_newarray(size, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayvftbl);
}
+
/**************** function: builtin_nmultianewarray ***************************
Creates a multi-dimensional array on the heap. The dimensions are passed in
******************************************************************************/
-java_arrayheader *builtin_nmultianewarray (int n,
- vftbl *arrayvftbl, long *dims)
+ /* Helper functions */
+
+java_arrayheader *builtin_nmultianewarray (int n, vftbl *arrayvftbl, long *dims)
{
int size, i;
java_arrayheader *a;
return a;
}
+
/*****************************************************************************
METHOD LOGGING
methodinfo *method, int *pos,
int noindent)
{
-
- if (!noindent)
- methodindent--;
+ if (!noindent) {
+ if (methodindent)
+ methodindent--;
+ else
+ log_text("WARNING: unmatched methodindent--");
+ }
if (verbose || runverbose) {
printf("Exception ");
if (exceptionptr) {
#endif
methodinfo *method)
{
-
int i;
+ char logtext[MAXLOGTEXT];
for (i = 0; i < methodindent; i++)
logtext[i] = '\t';
sprintf(logtext + methodindent, "called: ");
#endif
}
sprintf (logtext+strlen(logtext), ")");
- dolog ();
+ log_text(logtext);
methodindent++;
}
void builtin_displaymethodstart(methodinfo *method)
{
+ char logtext[MAXLOGTEXT];
sprintf(logtext, " ");
sprintf(logtext + methodindent, "called: ");
utf_sprint(logtext + strlen(logtext), method->class->name);
sprintf(logtext + strlen(logtext), ".");
utf_sprint(logtext + strlen(logtext), method->name);
utf_sprint(logtext + strlen(logtext), method->descriptor);
- dolog();
+ log_text(logtext);
methodindent++;
}
void builtin_displaymethodstop(methodinfo *method, s8 l, double d, float f)
{
int i;
+ char logtext[MAXLOGTEXT];
for (i = 0; i < methodindent; i++)
logtext[i] = '\t';
- methodindent--;
+ if (methodindent)
+ methodindent--;
+ else
+ log_text("WARNING: unmatched methodindent--");
sprintf(logtext + methodindent, "finished: ");
utf_sprint(logtext + strlen(logtext), method->class->name);
sprintf(logtext + strlen(logtext), ".");
sprintf(logtext + strlen(logtext), "->%g", d);
break;
}
- dolog();
+ log_text(logtext);
}
void builtin_displaymethodexception(methodinfo *method)
{
int i;
+ char logtext[MAXLOGTEXT];
for (i = 0; i < methodindent; i++)
logtext[i] = '\t';
sprintf(logtext + methodindent, "exception abort: ");
sprintf(logtext + strlen(logtext), ".");
utf_sprint(logtext + strlen(logtext), method->name);
utf_sprint(logtext + strlen(logtext), method->descriptor);
- dolog();
+ log_text(logtext);
}
/*
* Lock the mutex of an object.
*/
-#ifdef USE_THREADS
-void
-internal_lock_mutex_for_object (java_objectheader *object)
+void internal_lock_mutex_for_object(java_objectheader *object)
{
+#ifdef USE_THREADS
mutexHashEntry *entry;
int hashValue;
entry->object = object;
internal_lock_mutex(&entry->mutex);
-}
#endif
+}
/*
* Unlocks the mutex of an object.
*/
-#ifdef USE_THREADS
-void
-internal_unlock_mutex_for_object (java_objectheader *object)
+void internal_unlock_mutex_for_object (java_objectheader *object)
{
+#ifdef USE_THREADS
int hashValue;
mutexHashEntry *entry;
firstFreeOverflowEntry = unlinked;
}
}
-}
#endif
+}
void builtin_monitorenter(java_objectheader *o)
float builtin_fadd(float a, float b)
{
- if (isnanf(a)) return FLT_NAN;
- if (isnanf(b)) return FLT_NAN;
+ if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+ if (isnanf(b)) return intBitsToFloat(FLT_NAN);
if (finitef(a)) {
if (finitef(b))
return a + b;
if (copysignf(1.0, a) == copysignf(1.0, b))
return a;
else
- return FLT_NAN;
+ return intBitsToFloat(FLT_NAN);
}
}
}
float builtin_fmul(float a, float b)
{
- if (isnanf(a)) return FLT_NAN;
- if (isnanf(b)) return FLT_NAN;
+ if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+ if (isnanf(b)) return intBitsToFloat(FLT_NAN);
if (finitef(a)) {
- if (finitef(b)) return a*b;
+ if (finitef(b)) return a * b;
else {
- if (a == 0) return FLT_NAN;
+ if (a == 0) return intBitsToFloat(FLT_NAN);
else return copysignf(b, copysignf(1.0, b)*a);
}
}
else {
if (finitef(b)) {
- if (b == 0) return FLT_NAN;
+ if (b == 0) return intBitsToFloat(FLT_NAN);
else return copysignf(a, copysignf(1.0, a)*b);
}
else {
return a / b;
else {
if (a > 0)
- return FLT_POSINF;
+ return intBitsToFloat(FLT_POSINF);
else if (a < 0)
- return FLT_NEGINF;
+ return intBitsToFloat(FLT_NEGINF);
}
}
- return FLT_NAN;
+ return intBitsToFloat(FLT_NAN);
}
double builtin_dadd(double a, double b)
{
- if (isnan(a)) return DBL_NAN;
- if (isnan(b)) return DBL_NAN;
+ if (isnan(a)) return longBitsToDouble(DBL_NAN);
+ if (isnan(b)) return longBitsToDouble(DBL_NAN);
if (finite(a)) {
- if (finite(b)) return a+b;
+ if (finite(b)) return a + b;
else return b;
}
else {
if (finite(b)) return a;
else {
if (copysign(1.0, a)==copysign(1.0, b)) return a;
- else return DBL_NAN;
+ else return longBitsToDouble(DBL_NAN);
}
}
}
double builtin_dmul(double a, double b)
{
- if (isnan(a)) return DBL_NAN;
- if (isnan(b)) return DBL_NAN;
+ if (isnan(a)) return longBitsToDouble(DBL_NAN);
+ if (isnan(b)) return longBitsToDouble(DBL_NAN);
if (finite(a)) {
if (finite(b)) return a * b;
else {
- if (a == 0) return DBL_NAN;
+ if (a == 0) return longBitsToDouble(DBL_NAN);
else return copysign(b, copysign(1.0, b) * a);
}
}
else {
if (finite(b)) {
- if (b == 0) return DBL_NAN;
+ if (b == 0) return longBitsToDouble(DBL_NAN);
else return copysign(a, copysign(1.0, a) * b);
}
else {
double builtin_ddiv(double a, double b)
{
- if (finite(a) && finite(b)) {
- if (b != 0)
+ if (finite(a)) {
+ if (finite(b)) {
return a / b;
- else {
+
+ } else {
+ if (isnan(b))
+ return longBitsToDouble(DBL_NAN);
+ else
+ return copysign(0.0, b);
+ }
+
+ } else {
+ if (finite(b)) {
if (a > 0)
- return DBL_POSINF;
+ return longBitsToDouble(DBL_POSINF);
else if (a < 0)
- return DBL_NEGINF;
- }
+ return longBitsToDouble(DBL_NEGINF);
+
+ } else
+ return longBitsToDouble(DBL_NAN);
}
- return DBL_NAN;
+
+/* if (finite(a) && finite(b)) { */
+/* if (b != 0) */
+/* return a / b; */
+/* else { */
+/* if (a > 0) */
+/* return longBitsToDouble(DBL_POSINF); */
+/* else if (a < 0) */
+/* return longBitsToDouble(DBL_NEGINF); */
+/* } */
+/* } */
+
+ /* keep compiler happy */
+ return 0;
}
#if U8_AVAILABLE
return i;
#else
- s8 v; v.high = 0; v.low=i; return v;
+ s8 v;
+ v.high = 0;
+ v.low = i;
+ return v;
#endif
}
if (finitef(a)) return (double) a;
else {
if (isnanf(a))
- return DBL_NAN;
+ return longBitsToDouble(DBL_NAN);
else
- return copysign(DBL_POSINF, (double) copysignf(1.0, a) );
+ return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
}
}
return (float) a;
else {
if (isnan(a))
- return FLT_NAN;
+ return intBitsToFloat(FLT_NAN);
else
- return copysignf(FLT_POSINF, (float) copysign(1.0, a));
+ return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
}
}
-java_arrayheader *builtin_clone_array(void *env,java_arrayheader *o) {
- return Java_java_lang_VMObject_clone ( 0 , 0, o);
+/* used to convert FLT_xxx defines into float values */
+
+inline float intBitsToFloat(s4 i)
+{
+ imm_union imb;
+
+ imb.i = i;
+ return imb.f;
+}
+
+
+/* used to convert DBL_xxx defines into double values */
+
+inline float longBitsToDouble(s8 l)
+{
+ imm_union imb;
+
+ imb.l = l;
+ return imb.d;
+}
+
+
+java_arrayheader *builtin_clone_array(void *env, java_arrayheader *o)
+{
+ return (java_arrayheader *) Java_java_lang_VMObject_clone(0, 0, (java_lang_Cloneable *) o);
}