mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
886 lines
24 KiB
C
886 lines
24 KiB
C
/*
|
|
* @(#) $(JCGO)/include/jcgomem.c --
|
|
* a part of the JCGO runtime subsystem.
|
|
**
|
|
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
|
|
* Copyright (C) 2001-2012 Ivan Maidanski <ivmai@ivmaisoft.com>
|
|
* All rights reserved.
|
|
*/
|
|
|
|
/**
|
|
* This file is compiled together with the files produced by the JCGO
|
|
* translator (do not include and/or compile this file directly).
|
|
*/
|
|
|
|
/*
|
|
* This is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
**
|
|
* This software is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License (GPL) for more details.
|
|
**
|
|
* Linking this library statically or dynamically with other modules is
|
|
* making a combined work based on this library. Thus, the terms and
|
|
* conditions of the GNU General Public License cover the whole
|
|
* combination.
|
|
**
|
|
* As a special exception, the copyright holders of this library give you
|
|
* permission to link this library with independent modules to produce an
|
|
* executable, regardless of the license terms of these independent
|
|
* modules, and to copy and distribute the resulting executable under
|
|
* terms of your choice, provided that you also meet, for each linked
|
|
* independent module, the terms and conditions of the license of that
|
|
* module. An independent module is a module which is not derived from
|
|
* or based on this library. If you modify this library, you may extend
|
|
* this exception to your version of the library, but you are not
|
|
* obligated to do so. If you do not wish to do so, delete this
|
|
* exception statement from your version.
|
|
*/
|
|
|
|
#ifdef JCGO_VER
|
|
|
|
#define JCGO_DIMS_MAX 16
|
|
|
|
struct jcgo_refhidden_s
|
|
{
|
|
jvtable jcgo_methods;
|
|
JCGO_MON_DEFN /* second */
|
|
jObject obj; /* third */
|
|
#ifdef OBJT_java_lang_ref_SoftReference
|
|
struct jcgo_refkeeper_s *keeper;
|
|
#endif
|
|
};
|
|
|
|
#ifndef JCGO_FNLZDATA_OMITREFQUE
|
|
struct jcgo_refexthidden_s
|
|
{
|
|
struct jcgo_refhidden_s hidden; /* first */
|
|
#ifndef JCGO_NOGC
|
|
jObject ref;
|
|
#endif
|
|
};
|
|
#endif
|
|
|
|
STATICDATA CONST JCGO_ALLOCSIZE_T jcgo_arrayMaxLen[OBJT_void] =
|
|
{
|
|
(~(JCGO_ALLOCSIZE_T)sizeof(struct jcgo_jobjectarr_s)) / sizeof(jObject),
|
|
(~(JCGO_ALLOCSIZE_T)sizeof(struct jcgo_jbooleanarr_s)) / sizeof(jboolean),
|
|
~(JCGO_ALLOCSIZE_T)sizeof(struct jcgo_jbytearr_s),
|
|
(~(JCGO_ALLOCSIZE_T)sizeof(struct jcgo_jchararr_s)) / sizeof(jchar),
|
|
(~(JCGO_ALLOCSIZE_T)sizeof(struct jcgo_jshortarr_s)) / sizeof(jshort),
|
|
(~(JCGO_ALLOCSIZE_T)sizeof(struct jcgo_jintarr_s)) / sizeof(jint),
|
|
(~(JCGO_ALLOCSIZE_T)sizeof(struct jcgo_jlongarr_s)) / sizeof(jlong),
|
|
(~(JCGO_ALLOCSIZE_T)sizeof(struct jcgo_jfloatarr_s)) / sizeof(jfloat),
|
|
(~(JCGO_ALLOCSIZE_T)sizeof(struct jcgo_jdoublearr_s)) / sizeof(jdouble)
|
|
};
|
|
|
|
STATICDATA CONST unsigned jcgo_primitiveOffset[OBJT_void] =
|
|
{
|
|
JCGO_OFFSET_OF(struct jcgo_jobjectarr_s, jObject),
|
|
JCGO_OFFSET_OF(struct jcgo_jbooleanarr_s, jboolean),
|
|
JCGO_OFFSET_OF(struct jcgo_jbytearr_s, jbyte),
|
|
JCGO_OFFSET_OF(struct jcgo_jchararr_s, jchar),
|
|
JCGO_OFFSET_OF(struct jcgo_jshortarr_s, jshort),
|
|
JCGO_OFFSET_OF(struct jcgo_jintarr_s, jint),
|
|
JCGO_OFFSET_OF(struct jcgo_jlongarr_s, jlong),
|
|
JCGO_OFFSET_OF(struct jcgo_jfloatarr_s, jfloat),
|
|
JCGO_OFFSET_OF(struct jcgo_jdoublearr_s, jdouble)
|
|
};
|
|
|
|
STATICDATA CONST unsigned jcgo_primitiveSize[OBJT_void] =
|
|
{
|
|
sizeof(jObject),
|
|
sizeof(jboolean),
|
|
1,
|
|
sizeof(jchar),
|
|
sizeof(jshort),
|
|
sizeof(jint),
|
|
sizeof(jlong),
|
|
sizeof(jfloat),
|
|
sizeof(jdouble)
|
|
};
|
|
|
|
STATICDATA JCGO_THRD_VOLATILE jlong jcgo_allocatedBytesCnt = (jlong)0L;
|
|
|
|
#ifndef JCGO_NOGC
|
|
|
|
#ifdef OBJT_java_lang_VMRuntime
|
|
|
|
#ifndef JCGO_FNLZDATA_OMITREFQUE
|
|
struct jcgo_reffnlzdata_s
|
|
{
|
|
struct jcgo_refhidden_s hidden; /* first */
|
|
struct jcgo_refexthidden_s *pexthidden;
|
|
struct jcgo_reffnlzdata_s *next;
|
|
struct jcgo_reffnlzdata_s *prev;
|
|
};
|
|
#endif
|
|
|
|
STATIC void GC_CALLBACK jcgo_refFinalizer( void *objbase, void *client_data );
|
|
|
|
#endif /* OBJT_java_lang_VMRuntime */
|
|
|
|
#ifdef JCGO_THREADS
|
|
|
|
STATIC void *GC_CALLBACK jcgo_refGetPtr( void *client_data )
|
|
{
|
|
return *(void **)client_data;
|
|
}
|
|
|
|
#endif /* JCGO_THREADS */
|
|
|
|
#endif /* ! JCGO_NOGC */
|
|
|
|
#ifdef JCGO_HUGEARR
|
|
|
|
STATIC void CFASTCALL jcgo_hbzero( void JCGO_HPTR_MOD *dest,
|
|
JCGO_ALLOCSIZE_T size )
|
|
{
|
|
unsigned blocksize;
|
|
unsigned invofs;
|
|
if (size > 0)
|
|
for (;;)
|
|
{
|
|
blocksize = (((unsigned)-1) >> 1) - 0xfff;
|
|
if ((invofs = ~(unsigned)JCGO_CAST_PTRTONUM(dest)) < blocksize)
|
|
blocksize = invofs + 1;
|
|
if ((JCGO_ALLOCSIZE_T)blocksize >= size)
|
|
blocksize = (unsigned)size;
|
|
JCGO_MEM_ZERO(dest, blocksize);
|
|
if ((size -= blocksize) == 0)
|
|
break;
|
|
dest = (char JCGO_HPTR_MOD *)dest + blocksize;
|
|
}
|
|
}
|
|
|
|
STATIC void CFASTCALL jcgo_hmemmove( void JCGO_HPTR_MOD *dest,
|
|
CONST void JCGO_HPTR_MOD *src, JCGO_ALLOCSIZE_T size )
|
|
{
|
|
unsigned blocksize;
|
|
unsigned invofs;
|
|
if (size > 0 && dest != src)
|
|
{
|
|
if ((char JCGO_HPTR_MOD *)dest - (char JCGO_HPTR_MOD *)NULL <
|
|
(char JCGO_HPTR_MOD *)src - (char JCGO_HPTR_MOD *)NULL)
|
|
{
|
|
for (;;)
|
|
{
|
|
blocksize = (((unsigned)-1) >> 1) - 0xfff;
|
|
if ((invofs = ~(unsigned)JCGO_CAST_PTRTONUM(dest)) < blocksize)
|
|
blocksize = invofs + 1;
|
|
if ((invofs = ~(unsigned)JCGO_CAST_PTRTONUM(src)) < blocksize)
|
|
blocksize = invofs + 1;
|
|
if ((JCGO_ALLOCSIZE_T)blocksize >= size)
|
|
blocksize = (unsigned)size;
|
|
memmove(dest, src, blocksize);
|
|
if ((size -= blocksize) == 0)
|
|
break;
|
|
dest = (char JCGO_HPTR_MOD *)dest + blocksize;
|
|
src = (CONST char JCGO_HPTR_MOD *)src + blocksize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dest = (char JCGO_HPTR_MOD *)dest + size;
|
|
src = (CONST char JCGO_HPTR_MOD *)src + size;
|
|
do
|
|
{
|
|
blocksize = (((unsigned)-1) >> 1) - 0xfff;
|
|
if ((invofs = ~(unsigned)JCGO_CAST_PTRTONUM(dest)) < blocksize)
|
|
blocksize = invofs + 1;
|
|
if ((invofs = ~(unsigned)JCGO_CAST_PTRTONUM(src)) < blocksize)
|
|
blocksize = invofs + 1;
|
|
if ((JCGO_ALLOCSIZE_T)blocksize >= size)
|
|
blocksize = (unsigned)size;
|
|
dest = (char JCGO_HPTR_MOD *)dest - blocksize;
|
|
src = (CONST char JCGO_HPTR_MOD *)src - blocksize;
|
|
memmove(dest, src, blocksize);
|
|
} while ((size -= blocksize) > 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define JCGO_MEM_HMOVE(dest, src, size) jcgo_hmemmove(dest, src, size)
|
|
#define JCGO_MEM_HCOPY(dest, src, size) JCGO_MEM_HMOVE(dest, src, size)
|
|
|
|
#else /* JCGO_HUGEARR */
|
|
|
|
#define JCGO_MEM_HMOVE(dest, src, size) (void)memmove(dest, src, size)
|
|
#define JCGO_MEM_HCOPY(dest, src, size) JCGO_MEM_CPY(dest, src, size)
|
|
|
|
#endif /* ! JCGO_HUGEARR */
|
|
|
|
#ifdef OBJT_java_lang_ref_SoftReference
|
|
|
|
#ifndef JCGO_SOFTREF_MINAGE
|
|
#define JCGO_SOFTREF_MINAGE 1
|
|
#define JCGO_SOFTREF_MAXAGE 8
|
|
#define JCGO_SOFTREF_TOPAGE 32
|
|
#endif
|
|
|
|
#ifndef JCGO_MEMREFGDAT_LOCK
|
|
#define JCGO_MEMREFGDAT_LOCK(x) (void)0
|
|
#define JCGO_MEMREFGDAT_UNLOCK(x) (void)0
|
|
#endif
|
|
|
|
struct jcgo_refkeeper_s
|
|
{
|
|
jObject obj;
|
|
struct jcgo_refkeeper_s *next;
|
|
unsigned timestamp;
|
|
};
|
|
|
|
STATICDATA unsigned jcgo_gcCount = 0;
|
|
|
|
#ifndef JCGO_NOGC
|
|
|
|
#ifndef JCGO_SOFTREF_ALLOCBYTESMIN
|
|
#define JCGO_SOFTREF_ALLOCBYTESMIN 0x1000
|
|
#endif
|
|
|
|
STATICDATA unsigned jcgo_lastAllocBytesCnt = 0;
|
|
|
|
STATICDATA unsigned jcgo_heapExpandHist = 0;
|
|
|
|
STATICDATA unsigned long jcgo_heapLastSize = 0L;
|
|
|
|
STATICDATA u_jlong jcgo_heapCurMaxSize = 0L;
|
|
|
|
STATIC int CFASTCALL jcgo_softRefsProcess( int clearAll )
|
|
{
|
|
struct jcgo_refkeeper_s *keeper;
|
|
struct jcgo_refkeeper_s **pnextkeep;
|
|
u_jlong size;
|
|
long deltaSize;
|
|
int age;
|
|
unsigned hist = 0;
|
|
if (JCGO_EXPECT_TRUE(!clearAll))
|
|
{
|
|
size = (u_jlong)JCGO_MEM_HEAPCURSIZE(0);
|
|
deltaSize = (long)jcgo_heapLastSize;
|
|
jcgo_heapLastSize = (unsigned long)size;
|
|
hist = jcgo_heapExpandHist << 2;
|
|
if (jcgo_heapCurMaxSize < size)
|
|
{
|
|
clearAll = 1;
|
|
jcgo_heapCurMaxSize = size;
|
|
}
|
|
if ((deltaSize -= (long)size) != 0L)
|
|
{
|
|
if (deltaSize < 0L)
|
|
{
|
|
hist++;
|
|
if (jcgo_heapExpandHist == ~(unsigned)0)
|
|
clearAll = 1;
|
|
}
|
|
hist++;
|
|
}
|
|
jcgo_heapExpandHist = hist;
|
|
}
|
|
if ((keeper = jcgo_globData.refKeeperList) == NULL)
|
|
return 0;
|
|
if (JCGO_EXPECT_FALSE(clearAll))
|
|
{
|
|
jcgo_globData.refKeeperList = NULL;
|
|
do
|
|
{
|
|
keeper->obj = jnull;
|
|
} while ((keeper = keeper->next) != NULL);
|
|
return 1;
|
|
}
|
|
for (age = 0; hist; hist >>= 2)
|
|
if ((hist & 0x3) != 0)
|
|
age = ((hist & 0x3) << 1) + age - 3;
|
|
age = age > 0 ? (((sizeof(hist) << 2) - age) * (JCGO_SOFTREF_MAXAGE -
|
|
JCGO_SOFTREF_MINAGE + 1)) / (sizeof(hist) << 2) +
|
|
(JCGO_SOFTREF_MINAGE + 1) : JCGO_SOFTREF_TOPAGE + 1;
|
|
pnextkeep = &jcgo_globData.refKeeperList;
|
|
hist = jcgo_gcCount;
|
|
do
|
|
{
|
|
if (keeper->obj == jnull || (int)hist - (int)keeper->timestamp > age)
|
|
{
|
|
do
|
|
{
|
|
keeper->obj = jnull;
|
|
} while ((keeper = keeper->next) != NULL && (keeper->obj == jnull ||
|
|
(int)hist - (int)keeper->timestamp > age));
|
|
if ((*pnextkeep = keeper) == NULL)
|
|
break;
|
|
}
|
|
} while ((keeper = *(pnextkeep = &keeper->next)) != NULL);
|
|
return 1;
|
|
}
|
|
|
|
#endif /* ! JCGO_NOGC */
|
|
|
|
#endif /* OBJT_java_lang_ref_SoftReference */
|
|
|
|
STATIC void *CFASTCALL jcgo_memAlloc( JCGO_ALLOCSIZE_T size,
|
|
void *jcgo_methods )
|
|
{
|
|
void *ptr = NULL;
|
|
#ifdef OBJT_java_lang_ref_SoftReference
|
|
#ifdef JCGO_THREADS
|
|
#ifndef JCGO_PARALLEL
|
|
struct jcgo_tcb_s *tcb;
|
|
#endif
|
|
#endif
|
|
unsigned count = 0;
|
|
int changed;
|
|
for (;;)
|
|
#endif
|
|
{
|
|
if (JCGO_EXPECT_TRUE(size != 0))
|
|
{
|
|
JCGO_MEM_CALLOC(&ptr, size, jcgo_methods);
|
|
if (JCGO_EXPECT_TRUE(ptr != NULL))
|
|
{
|
|
#ifdef OBJT_java_lang_ref_SoftReference
|
|
#ifdef JCGO_NOGC
|
|
jcgo_allocatedBytesCnt += (jlong)size;
|
|
#else
|
|
if ((unsigned)(jcgo_allocatedBytesCnt += (jlong)size) -
|
|
jcgo_lastAllocBytesCnt < (unsigned)JCGO_SOFTREF_ALLOCBYTESMIN)
|
|
break;
|
|
#endif
|
|
if (JCGO_EXPECT_TRUE((unsigned)JCGO_MEM_GCGETCOUNT(0) == jcgo_gcCount))
|
|
{
|
|
#ifndef JCGO_NOGC
|
|
jcgo_lastAllocBytesCnt = (unsigned)jcgo_allocatedBytesCnt;
|
|
#endif
|
|
break;
|
|
}
|
|
#else
|
|
jcgo_allocatedBytesCnt += (jlong)size;
|
|
#endif
|
|
}
|
|
}
|
|
#ifdef OBJT_java_lang_ref_SoftReference
|
|
changed = 0;
|
|
JCGO_MEMREFGDAT_LOCK(0);
|
|
if ((count = (unsigned)JCGO_MEM_GCGETCOUNT(0)) ==
|
|
(unsigned)(*(volatile int *)&jcgo_gcCount))
|
|
{
|
|
if (ptr == NULL)
|
|
{
|
|
JCGO_MEMREFGDAT_UNLOCK(0);
|
|
JCGO_MEM_GCOLLECT(0);
|
|
changed = 1;
|
|
JCGO_MEMREFGDAT_LOCK(0);
|
|
jcgo_gcCount = (unsigned)JCGO_MEM_GCGETCOUNT(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
jcgo_gcCount = count;
|
|
changed = 1;
|
|
}
|
|
#ifndef JCGO_NOGC
|
|
if (changed)
|
|
count = (unsigned)jcgo_softRefsProcess(ptr == NULL);
|
|
jcgo_lastAllocBytesCnt = (unsigned)jcgo_allocatedBytesCnt;
|
|
#endif
|
|
JCGO_MEMREFGDAT_UNLOCK(0);
|
|
if (!changed)
|
|
break;
|
|
#ifdef JCGO_THREADS
|
|
#ifdef JCGO_PARALLEL
|
|
JCGO_THREAD_YIELD;
|
|
#else
|
|
JCGO_GET_CURTCB(&tcb);
|
|
(void)JCGO_MUTEX_UNLOCK(&jcgo_nonParallelMutex);
|
|
JCGO_THREAD_YIELD;
|
|
(void)JCGO_MUTEX_LOCK(&jcgo_nonParallelMutex);
|
|
jcgo_curTCB = tcb;
|
|
#endif
|
|
#endif
|
|
if (ptr != NULL || !count)
|
|
break;
|
|
#endif
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
JCGO_NOSEP_STATIC jObject CFASTCALL jcgo_newObject( jvtable jcgo_methods )
|
|
{
|
|
void *ptr = (void *)jcgo_methods;
|
|
#ifndef JCGO_NOGC
|
|
#ifdef OBJT_java_lang_VMRuntime
|
|
void *next;
|
|
#endif
|
|
#endif
|
|
int size;
|
|
if ((size = (int)jcgo_methods->jcgo_objsize) <= 0)
|
|
{
|
|
if (!size)
|
|
JCGO_FATAL_ABORT("Cannot create abstract class instance!");
|
|
ptr = NULL;
|
|
size = -size;
|
|
}
|
|
ptr = jcgo_memAlloc((unsigned)size, ptr);
|
|
if (JCGO_EXPECT_FALSE(ptr == NULL)
|
|
#ifndef JCGO_NOGC
|
|
#ifdef OBJT_java_lang_VMRuntime
|
|
|| (((CONST struct java_lang_Object_methods_s *)
|
|
jcgo_methods)->finalize__ != java_lang_Object__finalize__ &&
|
|
(next = JCGO_PTR_RESERVED, JCGO_MEM_REGJFINALIZER(ptr,
|
|
jcgo_refFinalizer, JCGO_PTR_RESERVED, &next), next != NULL))
|
|
#endif
|
|
#endif
|
|
)
|
|
{
|
|
#ifdef OBJT_java_lang_VMThrowable
|
|
java_lang_VMThrowable__throwOutOfMemoryError0X__();
|
|
#else
|
|
JCGO_MEM_HEAPDESTROY;
|
|
JCGO_FATAL_ABORT("Out of memory!");
|
|
#endif
|
|
}
|
|
*(jvtable *)&JCGO_METHODS_OF(JCGO_OBJREF_OF(*(jObject)ptr)) = jcgo_methods;
|
|
return JCGO_OBJREF_OF(*(jObject)ptr);
|
|
}
|
|
|
|
JCGO_NOSEP_STATIC jObject CFASTCALL jcgo_newArray( java_lang_Class aclass,
|
|
int dims, jint len )
|
|
{
|
|
JCGO_ALLOCSIZE_T size;
|
|
int typenum;
|
|
void *ptr = NULL;
|
|
if (JCGO_EXPECT_FALSE(aclass == jnull))
|
|
JCGO_THROW_EXC(jnull);
|
|
if ((typenum = ((jvtable)&JCGO_METHODS_OF(
|
|
JCGO_FIELD_NZACCESS(aclass, vmdata)))->jcgo_typeid) > OBJT_jarray &&
|
|
typenum < OBJT_jarray + OBJT_void + JCGO_DIMS_MAX)
|
|
{
|
|
if (typenum < OBJT_jarray + OBJT_void)
|
|
{
|
|
typenum -= OBJT_jarray;
|
|
aclass = JCGO_CORECLASS_FOR(typenum);
|
|
dims++;
|
|
}
|
|
else
|
|
{
|
|
dims = (typenum -= OBJT_jarray + OBJT_void - 1) + dims;
|
|
do
|
|
{
|
|
aclass = JCGO_FIELD_NZACCESS(aclass, superclass);
|
|
} while (--typenum);
|
|
typenum = ((jvtable)&JCGO_METHODS_OF(
|
|
JCGO_FIELD_NZACCESS(aclass, vmdata)))->jcgo_typeid;
|
|
}
|
|
}
|
|
if (JCGO_EXPECT_FALSE(typenum == OBJT_void ||
|
|
((jint)(((JCGO_DIMS_MAX - 1) - dims) | dims) | len) < 0))
|
|
{
|
|
#ifdef OBJT_java_lang_VMThrowable
|
|
java_lang_VMThrowable__throwNegativeArraySizeException0X__();
|
|
#else
|
|
JCGO_FATAL_ABORT("Negative array size specified!");
|
|
#endif
|
|
}
|
|
if (JCGO_EXPECT_TRUE(len != (jint)(((u_jint)-1) >> 1)))
|
|
{
|
|
ptr = JCGO_PTR_RESERVED;
|
|
typenum = dims > 0 ? (OBJT_jarray + OBJT_void) + dims :
|
|
typenum < OBJT_void ? OBJT_jarray + typenum :
|
|
OBJT_jarray + OBJT_void;
|
|
dims = 0;
|
|
if (typenum < OBJT_jarray + OBJT_void)
|
|
{
|
|
ptr = NULL;
|
|
dims = typenum - OBJT_jarray;
|
|
}
|
|
if (JCGO_EXPECT_TRUE(len != 0))
|
|
{
|
|
size = 0;
|
|
if (JCGO_EXPECT_TRUE(jcgo_arrayMaxLen[dims] >= (JCGO_ALLOCSIZE_T)len))
|
|
{
|
|
size = jcgo_primitiveSize[dims] * (JCGO_ALLOCSIZE_T)len +
|
|
jcgo_primitiveOffset[dims];
|
|
#ifdef JCGO_HUGEARR
|
|
if (size - (JCGO_ALLOCSIZE_T)1 > (unsigned)-1 &&
|
|
(((JCGO_OFFSET_OF(struct jcgo_jobjectarr_s, jObject) %
|
|
sizeof(jObject) == 0) |
|
|
((JCGO_OFFSET_OF(struct jcgo_jbooleanarr_s, jboolean) %
|
|
sizeof(jboolean) == 0) << OBJT_jboolean) | (1 << OBJT_jbyte) |
|
|
((JCGO_OFFSET_OF(struct jcgo_jchararr_s, jchar) %
|
|
sizeof(jchar) == 0) << OBJT_jchar) |
|
|
((JCGO_OFFSET_OF(struct jcgo_jshortarr_s, jshort) %
|
|
sizeof(jshort) == 0) << OBJT_jshort) |
|
|
((JCGO_OFFSET_OF(struct jcgo_jintarr_s, jint) %
|
|
sizeof(jint) == 0) << OBJT_jint) |
|
|
((JCGO_OFFSET_OF(struct jcgo_jlongarr_s, jlong) %
|
|
sizeof(jlong) == 0) << OBJT_jlong) |
|
|
((JCGO_OFFSET_OF(struct jcgo_jfloatarr_s, jfloat) %
|
|
sizeof(jfloat) == 0) << OBJT_jfloat) |
|
|
((JCGO_OFFSET_OF(struct jcgo_jdoublearr_s, jdouble) %
|
|
sizeof(jdouble) == 0) << OBJT_jdouble)) & (1 << dims)) == 0)
|
|
size = 0;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
size = jcgo_primitiveOffset[dims];
|
|
ptr = NULL;
|
|
}
|
|
ptr = jcgo_memAlloc(size, ptr);
|
|
}
|
|
if (JCGO_EXPECT_FALSE(ptr == NULL))
|
|
{
|
|
#ifdef OBJT_java_lang_VMThrowable
|
|
java_lang_VMThrowable__throwOutOfMemoryError0X__();
|
|
#else
|
|
JCGO_MEM_HEAPDESTROY;
|
|
JCGO_FATAL_ABORT("No memory for array!");
|
|
#endif
|
|
}
|
|
if (dims)
|
|
*(jvtable *)&JCGO_METHODS_OF(JCGO_OBJREF_OF(*(jObjectArr)ptr)) =
|
|
(jvtable)&JCGO_METHODS_OF(
|
|
jcgo_coreClasses[(unsigned)(typenum - 1)].vmdata);
|
|
else
|
|
{
|
|
*(jvtable *)&JCGO_METHODS_OF(JCGO_OBJREF_OF(*(jObjectArr)ptr)) =
|
|
(jvtable)&JCGO_METHODS_OF(
|
|
jcgo_objArrStubClasses[typenum - (OBJT_jarray + OBJT_void)].vmdata);
|
|
JCGO_FIELD_NZACCESS(JCGO_OBJREF_OF(*(jObjectArr)ptr), jcgo_component) =
|
|
aclass;
|
|
}
|
|
*(JCGO_ARRLENGTH_T *)&JCGO_FIELD_NZACCESS(JCGO_OBJREF_OF(*(jObjectArr)ptr),
|
|
length) = (JCGO_ARRLENGTH_T)len;
|
|
return JCGO_OBJREF_OF(*(jObject)ptr);
|
|
}
|
|
|
|
#ifndef JCGO_NOGC
|
|
|
|
#ifdef OBJT_java_lang_VMRuntime
|
|
|
|
#ifndef JCGO_FNLZDATA_OMITREFQUE
|
|
|
|
#ifdef OBJT_java_lang_ref_VMReference
|
|
|
|
#ifdef JCGO_PARALLEL
|
|
STATIC void *GC_CALLBACK
|
|
#else
|
|
JCGO_NOSEP_INLINE void *CFASTCALL
|
|
#endif
|
|
jcgo_fnlzDataGetRef( void *client_data )
|
|
{
|
|
struct jcgo_refexthidden_s *pexthidden =
|
|
((struct jcgo_reffnlzdata_s *)client_data)->pexthidden;
|
|
return pexthidden != NULL ? pexthidden->ref : jnull;
|
|
}
|
|
|
|
#ifdef JCGO_PARALLEL
|
|
#define JCGO_FNLZDATA_GETREF(pfnlzdata) (*(void *volatile *)&(pfnlzdata)->pexthidden != NULL ? (jObject)JCGO_MEM_CALLWITHSYNC(&jcgo_fnlzDataGetRef, pfnlzdata) : jnull)
|
|
#else
|
|
#define JCGO_FNLZDATA_GETREF(pfnlzdata) (jObject)jcgo_fnlzDataGetRef(pfnlzdata)
|
|
#endif
|
|
|
|
#endif /* OBJT_java_lang_ref_VMReference */
|
|
|
|
STATIC void *GC_CALLBACK jcgo_fnlzDataAttachNew( void *client_data )
|
|
{
|
|
struct jcgo_reffnlzdata_s *pfnlzdata =
|
|
((struct jcgo_reffnlzdata_s *)client_data)->next;
|
|
struct jcgo_reffnlzdata_s *next;
|
|
#ifdef JCGO_PARALLEL
|
|
if (JCGO_EXPECT_TRUE(pfnlzdata != NULL))
|
|
#endif
|
|
{
|
|
if (pfnlzdata->pexthidden != NULL)
|
|
pfnlzdata->prev = client_data;
|
|
else
|
|
{
|
|
next = pfnlzdata->next;
|
|
if ((((struct jcgo_reffnlzdata_s *)client_data)->next = next) != NULL &&
|
|
next != JCGO_PTR_RESERVED)
|
|
next->prev = client_data;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef JCGO_PARALLEL
|
|
STATIC void *GC_CALLBACK
|
|
#else
|
|
JCGO_NOSEP_INLINE void CFASTCALL
|
|
#endif
|
|
jcgo_fnlzDataExcludeAny( void *client_data )
|
|
{
|
|
struct jcgo_reffnlzdata_s *next =
|
|
((struct jcgo_reffnlzdata_s *)client_data)->next;
|
|
struct jcgo_reffnlzdata_s *prev;
|
|
if ((prev = ((struct jcgo_reffnlzdata_s *)client_data)->prev) != NULL)
|
|
prev->next = next;
|
|
if (next != NULL)
|
|
{
|
|
if (next != JCGO_PTR_RESERVED)
|
|
next->prev = prev;
|
|
((struct jcgo_reffnlzdata_s *)client_data)->next = NULL;
|
|
}
|
|
#ifdef JCGO_PARALLEL
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
STATIC void *CFASTCALL jcgo_fnlzDataProcess( void *objbase,
|
|
struct jcgo_reffnlzdata_s *pfnlzdata )
|
|
{
|
|
struct jcgo_refexthidden_s *pexthidden;
|
|
struct jcgo_reffnlzdata_s *pfnlzphantoms = NULL;
|
|
struct jcgo_reffnlzdata_s *lastphantom = NULL;
|
|
struct jcgo_reffnlzdata_s *next;
|
|
void *alivelastexthidden = NULL;
|
|
jObject refObj;
|
|
#ifdef OBJT_java_lang_ref_VMReference
|
|
struct jcgo_reffnlzdata_s *pfnlzhead = NULL;
|
|
#ifndef JCGO_NOJNI
|
|
int hasJniWeak = 0;
|
|
#endif
|
|
#endif
|
|
do
|
|
{
|
|
next = pfnlzdata->next;
|
|
if ((pexthidden = pfnlzdata->pexthidden) != NULL)
|
|
{
|
|
if (pexthidden->hidden.obj != jnull)
|
|
{
|
|
#ifdef JCGO_PARALLEL
|
|
JCGO_MEM_CALLWITHSYNC(&jcgo_fnlzDataExcludeAny, pfnlzdata);
|
|
#else
|
|
jcgo_fnlzDataExcludeAny(pfnlzdata);
|
|
#endif
|
|
if ((pfnlzdata->prev = lastphantom) != NULL)
|
|
lastphantom->next = pfnlzdata;
|
|
else pfnlzphantoms = pfnlzdata;
|
|
lastphantom = pfnlzdata;
|
|
*(void *volatile *)&alivelastexthidden = pexthidden;
|
|
#ifndef JCGO_NOJNI
|
|
#ifdef OBJT_java_lang_ref_VMReference
|
|
if (pexthidden->hidden.obj != (jObject)JCGO_PTR_RESERVED)
|
|
hasJniWeak = 1;
|
|
#endif
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
JCGO_MEM_REGJFINALIZER(pexthidden, 0, NULL, (void **)&refObj);
|
|
#ifdef OBJT_java_lang_ref_VMReference
|
|
if (pfnlzhead == NULL)
|
|
pfnlzhead = pfnlzdata;
|
|
#endif
|
|
}
|
|
}
|
|
} while ((pfnlzdata = next) != NULL && pfnlzdata != JCGO_PTR_RESERVED);
|
|
if (pfnlzphantoms != NULL && (pfnlzdata != NULL
|
|
#ifndef JCGO_NOJNI
|
|
#ifdef OBJT_java_lang_ref_VMReference
|
|
|| (hasJniWeak && pfnlzhead != NULL)
|
|
#endif
|
|
#endif
|
|
))
|
|
{
|
|
lastphantom->next = JCGO_PTR_RESERVED;
|
|
JCGO_MEM_REGJFINALIZER(objbase, jcgo_refFinalizer, pfnlzphantoms,
|
|
(void **)&lastphantom->next);
|
|
if ((next = lastphantom->next) != JCGO_PTR_RESERVED)
|
|
{
|
|
if (next != NULL)
|
|
{
|
|
#ifdef JCGO_PARALLEL
|
|
JCGO_MEM_CALLWITHSYNC(&jcgo_fnlzDataAttachNew, lastphantom);
|
|
#else
|
|
jcgo_fnlzDataAttachNew(lastphantom);
|
|
#endif
|
|
}
|
|
if (*(void *volatile *)&alivelastexthidden != NULL)
|
|
pfnlzphantoms = NULL;
|
|
}
|
|
else lastphantom->next = NULL;
|
|
}
|
|
for (next = pfnlzphantoms; next != NULL; next = next->next)
|
|
if ((pexthidden = next->pexthidden) != NULL)
|
|
{
|
|
JCGO_MEM_REGJFINALIZER(pexthidden, 0, NULL, (void **)&refObj);
|
|
#ifdef OBJT_java_lang_ref_VMReference
|
|
if (pexthidden->hidden.obj != (jObject)JCGO_PTR_RESERVED)
|
|
{
|
|
next->pexthidden = NULL;
|
|
pexthidden->hidden.obj = jnull;
|
|
}
|
|
#else
|
|
pexthidden->hidden.obj = jnull;
|
|
#endif
|
|
}
|
|
#ifdef OBJT_java_lang_ref_VMReference
|
|
if (pfnlzhead != NULL)
|
|
do
|
|
{
|
|
if ((refObj = JCGO_FNLZDATA_GETREF(pfnlzhead)) != jnull)
|
|
java_lang_ref_VMReference__enqueueByGC0X__LoLo((java_lang_Object)refObj,
|
|
jnull);
|
|
} while ((pfnlzhead = pfnlzhead->next) != NULL &&
|
|
pfnlzhead != JCGO_PTR_RESERVED);
|
|
while (pfnlzphantoms != NULL)
|
|
{
|
|
next = pfnlzphantoms->next;
|
|
if ((refObj = JCGO_FNLZDATA_GETREF(pfnlzphantoms)) != jnull)
|
|
{
|
|
pfnlzphantoms->hidden.obj = JCGO_OBJREF_OF(*(jObject)objbase);
|
|
pfnlzphantoms->pexthidden = NULL;
|
|
pfnlzphantoms->next = NULL;
|
|
pfnlzphantoms->prev = NULL;
|
|
java_lang_ref_VMReference__enqueueByGC0X__LoLo((java_lang_Object)refObj,
|
|
(java_lang_Object)pfnlzphantoms);
|
|
}
|
|
pfnlzphantoms = next;
|
|
}
|
|
#endif
|
|
return pfnlzdata;
|
|
}
|
|
|
|
#ifdef JCGO_PARALLEL
|
|
STATIC void *GC_CALLBACK
|
|
#else
|
|
JCGO_NOSEP_INLINE void CFASTCALL
|
|
#endif
|
|
jcgo_fnlzDataDelUnreach( void *client_data )
|
|
{
|
|
struct jcgo_reffnlzdata_s *next;
|
|
struct jcgo_reffnlzdata_s *prev;
|
|
if ((prev = ((struct jcgo_reffnlzdata_s *)client_data)->prev) != NULL)
|
|
{
|
|
next = ((struct jcgo_reffnlzdata_s *)client_data)->next;
|
|
((struct jcgo_reffnlzdata_s *)client_data)->prev = NULL;
|
|
if ((prev->next = next) != NULL && next != JCGO_PTR_RESERVED)
|
|
next->prev = prev;
|
|
}
|
|
#ifdef JCGO_PARALLEL
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
STATIC void GC_CALLBACK jcgo_refExtHiddenFnlz( void *objbase,
|
|
void *client_data )
|
|
{
|
|
#ifdef JCGO_PARALLEL
|
|
if (((struct jcgo_reffnlzdata_s *)client_data)->prev != NULL &&
|
|
((struct jcgo_reffnlzdata_s *)client_data)->pexthidden == NULL)
|
|
JCGO_MEM_CALLWITHSYNC(&jcgo_fnlzDataDelUnreach, client_data);
|
|
#else
|
|
if (((struct jcgo_reffnlzdata_s *)client_data)->pexthidden == NULL)
|
|
jcgo_fnlzDataDelUnreach(client_data);
|
|
#endif
|
|
}
|
|
|
|
#endif /* ! JCGO_FNLZDATA_OMITREFQUE */
|
|
|
|
STATIC void GC_CALLBACK jcgo_refFinalizer( void *objbase, void *client_data )
|
|
{
|
|
JCGO_CALLBACK_BEGIN
|
|
#ifndef JCGO_FNLZDATA_OMITREFQUE
|
|
if (client_data == JCGO_PTR_RESERVED || jcgo_fnlzDataProcess(objbase,
|
|
(struct jcgo_reffnlzdata_s *)client_data) != NULL)
|
|
#endif
|
|
{
|
|
java_lang_VMRuntime__finalizeObject0X__Lo(
|
|
JCGO_OBJREF_OF(*(java_lang_Object)objbase));
|
|
}
|
|
JCGO_CALLBACK_END
|
|
}
|
|
|
|
#endif /* OBJT_java_lang_VMRuntime */
|
|
|
|
#endif /* ! JCGO_NOGC */
|
|
|
|
#ifndef JCGO_FNLZDATA_OMITREFQUE
|
|
|
|
#ifdef OBJT_java_lang_ref_ReferenceQueue
|
|
STATIC
|
|
#else
|
|
JCGO_NOSEP_INLINE
|
|
#endif
|
|
struct jcgo_refexthidden_s *CFASTCALL jcgo_newWeakQueRef( jObject refObj,
|
|
jObject ownerObj, jObject referent, int noclear )
|
|
{
|
|
struct jcgo_refexthidden_s *pexthidden =
|
|
jcgo_memAlloc(sizeof(struct jcgo_refexthidden_s), NULL);
|
|
#ifndef JCGO_NOGC
|
|
#ifdef OBJT_java_lang_VMRuntime
|
|
struct jcgo_reffnlzdata_s *pfnlzdata;
|
|
struct jcgo_reffnlzdata_s *next;
|
|
#endif
|
|
#endif
|
|
if (JCGO_EXPECT_TRUE(pexthidden != NULL))
|
|
{
|
|
pexthidden->hidden.jcgo_methods = (jvtable)&java_lang_Object_methods;
|
|
#ifdef JCGO_NOGC
|
|
pexthidden->hidden.obj = referent;
|
|
#else
|
|
#ifdef OBJT_java_lang_VMRuntime
|
|
pfnlzdata = jcgo_memAlloc(sizeof(struct jcgo_reffnlzdata_s),
|
|
JCGO_PTR_RESERVED);
|
|
if (JCGO_EXPECT_FALSE(pfnlzdata == NULL))
|
|
return NULL;
|
|
if (noclear)
|
|
{
|
|
pexthidden->hidden.obj = refObj != jnull ? JCGO_PTR_RESERVED : referent;
|
|
pfnlzdata->hidden.jcgo_methods = (jvtable)&java_lang_Object_methods;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
pexthidden->hidden.obj = referent;
|
|
if (JCGO_MEM_SAFEREGWEAKLINK((void **)&pexthidden->hidden.obj,
|
|
(void *)&JCGO_METHODS_OF(referent),
|
|
JCGO_EXPECT_TRUE(JCGO_METHODS_OF(referent)->jcgo_typeid >
|
|
OBJT_java_lang_String)))
|
|
return NULL;
|
|
}
|
|
#ifdef OBJT_java_lang_VMRuntime
|
|
pfnlzdata->pexthidden = pexthidden;
|
|
if (JCGO_MEM_REGWEAKLINK((void **)&pfnlzdata->pexthidden,
|
|
(void *)&JCGO_METHODS_OF(ownerObj)))
|
|
return NULL;
|
|
next = JCGO_PTR_RESERVED;
|
|
JCGO_MEM_REGJFINALIZER(pexthidden, jcgo_refExtHiddenFnlz, pfnlzdata,
|
|
(void **)&next);
|
|
if (JCGO_EXPECT_FALSE(next != NULL))
|
|
return NULL;
|
|
pfnlzdata->next = pfnlzdata;
|
|
pexthidden->ref = refObj;
|
|
JCGO_MEM_SAFEREGJFINALIZER((void *)&JCGO_METHODS_OF(referent),
|
|
jcgo_refFinalizer, pfnlzdata, (void **)&pfnlzdata->next,
|
|
JCGO_EXPECT_TRUE(JCGO_METHODS_OF(referent)->jcgo_typeid >
|
|
OBJT_java_lang_String));
|
|
next = pfnlzdata->next;
|
|
if (JCGO_EXPECT_FALSE(next == pfnlzdata))
|
|
{
|
|
JCGO_MEM_REGJFINALIZER(pexthidden, 0, NULL, (void **)&next);
|
|
return NULL;
|
|
}
|
|
if (next != NULL && next != JCGO_PTR_RESERVED)
|
|
{
|
|
#ifdef JCGO_PARALLEL
|
|
JCGO_MEM_CALLWITHSYNC(&jcgo_fnlzDataAttachNew, pfnlzdata);
|
|
#else
|
|
jcgo_fnlzDataAttachNew(pfnlzdata);
|
|
#endif
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
return pexthidden;
|
|
}
|
|
|
|
#endif /* ! JCGO_FNLZDATA_OMITREFQUE */
|
|
|
|
#endif
|