#include #include #include #include #include #include #include #include "runtime-options.h" #include "layout!PTAjbyte.h" #include "layout!Pjbyte.h" #include "layout!Pjint.h" #include "layout!TAjbyte.h" #define checkIsArray(obj) \ if (!IS_JAVA_ARRAY_GLOBAL(obj)) \ tossArrayStoreException_str("argument to System.arraycopy() is not an array!") static void arrayCopyInner(PT6Object4lang4java src, jint src_pos, PT6Object4lang4java dst, jint dst_pos, jint length, T6Handle4lang2ti *handle); T6Handle4lang2ti m11arraycopyNBPT6Object4lang4javaIPT6Object4lang4javaIImT6System4lang4java( PT6Object4lang4java src, jint src_pos, PT6Object4lang4java dst, jint dst_pos, jint length) { T6Handle4lang2ti handle; TI_HANDLE_SETDONE(&handle); arrayCopyInner(src,src_pos,dst,dst_pos,length,&handle); return handle; } void m12arraycopyNBIPT6Object4lang4javaIPT6Object4lang4javaIImT6System4lang4java( PT6Object4lang4java src, jint src_pos, PT6Object4lang4java dst, jint dst_pos, jint length) { arrayCopyInner(src,src_pos,dst,dst_pos,length,HANDLE_NBI); } void m9arraycopyPT6Object4lang4javaIPT6Object4lang4javaIImT6System4lang4java( PT6Object4lang4java src, jint src_pos, PT6Object4lang4java dst, jint dst_pos, jint length) { arrayCopyInner(src,src_pos,dst,dst_pos,length,NULL); } static void arrayCopyInner(PT6Object4lang4java src, jint src_pos, PT6Object4lang4java dst, jint dst_pos, jint length, T6Handle4lang2ti *handle) { PTAjbyte src_array, dst_array; jint src_size, dst_size; jint src_isatomic, dst_isatomic; Pjbyte src_data, dst_data; int islocalsrc, islocaldest; ti_srcpos_freeze(); CHECK_NULL_GLOBAL(src); CHECK_NULL_GLOBAL(dst); islocalsrc = isDirectlyAddressable(src); islocaldest = isDirectlyAddressable(dst); src_array = * (PTAjbyte *) &src; dst_array = * (PTAjbyte *) &dst; if (!bounds_checking) { /* must be a dynamic check to reflect application bcheck setting */ jint length; /* checking is off, we assume both arguments are arrays and that element types match */ if (islocaldest) { /* get info from the array which is most convenient */ JAVA_ARRAY_INFO_GLOBAL( length, dst_size, dst_isatomic, dst_array ); src_size = dst_size; src_isatomic = dst_isatomic; } else { JAVA_ARRAY_INFO_GLOBAL( length, src_size, src_isatomic, src_array ); dst_size = src_size; dst_isatomic = src_isatomic; } } else { /* bounds checking and type-safety checking (which may require communication!) */ jint src_length, dst_length; checkIsArray( src ); checkIsArray( dst ); JAVA_ARRAY_INFO_GLOBAL( src_length, src_size, src_isatomic, src_array ); JAVA_ARRAY_INFO_GLOBAL( dst_length, dst_size, dst_isatomic, dst_array ); #if 0 JAVA_ARRAY_SIZE_GLOBAL( src_size, src_array ); JAVA_ARRAY_SIZE_GLOBAL( dst_size, dst_array ); JAVA_ARRAY_ISATOMIC_GLOBAL( src_isatomic, src_array ); JAVA_ARRAY_ISATOMIC_GLOBAL( dst_isatomic, dst_array ); #endif if ( src_size != dst_size || !!src_isatomic != !!dst_isatomic) { ti_srcpos_unfreeze(); tossArrayStoreException_str("array arguments to System.arraycopy() have incompatible element type"); } /* TODO: PR 349 still need to check that: * 1. primitive element types with same width are equal * 2. reference element types are assignment-compatible, and each element is assignment-compatible */ if (!src_isatomic) { /* region safety check */ if (!SHARED_REGIONID(PG2RegionId(src)) && SHARED_REGIONID(PG2RegionId(dst))) { ti_srcpos_unfreeze(); tossArrayStoreException_str("System.arraycopy() may not copy arrays with non-atomic element type" " from private region to shared region"); } } #if 0 JAVA_ARRAY_CHECK_GLOBAL( src_array, src_pos, length, "in System.arraycopy()" ); JAVA_ARRAY_CHECK_GLOBAL( dst_array, dst_pos, length, "in System.arraycopy()" ); #else /* use lengths we fetched above to save communication */ JAVA_ARRAY_LENCHECK( src_length, src_pos, length, "in System.arraycopy()" ); JAVA_ARRAY_LENCHECK( dst_length, dst_pos, length, "in System.arraycopy()" ); #endif } /* end of bounds checking */ if (length == 0) { ti_srcpos_unfreeze(); return; } /* a stupid case that actually happens */ /* We would like to use JAVA_ARRAY_ADDR_GLOBAL for the indexing computations below, but we cannot. The arrays might not really be arrays of bytes, and so the bounds check inside JAVA_ARRAY_ADDR_GLOBAL will fail inappropriately. */ FIELD_ADDR_GLOBAL( src_data, src_array, data[0] ); if (src_pos > 0) INDEX_GLOBAL( src_data, src_data, src_pos * src_size ); FIELD_ADDR_GLOBAL( dst_data, dst_array, data[0] ); if (dst_pos > 0) INDEX_GLOBAL( dst_data, dst_data, dst_pos * dst_size ); { int copy_sz = src_size * length; if (islocalsrc && islocaldest) { /* --- LOCAL --- */ jbyte *localdest = TO_LOCAL(dst_data); jbyte *localsrc = TO_LOCAL(src_data); int has_overlap = (localdest >= localsrc && localdest < localsrc + copy_sz) || (localsrc >= localdest && localsrc < localdest + copy_sz); if (localdest == localsrc) return; /* a stupid case that actually happens */ if (has_overlap) memmove(localdest, localsrc, copy_sz); else memcpy(localdest, localsrc, copy_sz); } else if (islocalsrc && !islocaldest) { /* --- PUT --- */ jbyte *localsrc = TO_LOCAL(src_data); if (!src_isatomic) { /* we may have some escaping pointers - inform distributed GC about them */ if (src_size == sizeof(jGPointer)) { /* elements are gp's */ GC_PTR_ESC(localsrc, length); } else { /* elements have embedded gp's */ /* TODO: use array type info to only pick up the real pointers */ GC_PTR_ESC_ALL_GPS(localsrc, copy_sz); } } if (handle == NULL) { ti_bulk_write(TO_BOX(dst_data), TO_LOCAL(dst_data), localsrc, copy_sz); } else if (handle == HANDLE_NBI) { TI_PUT_NBI_BULK(TO_BOX(dst_data), TO_LOCAL(dst_data), localsrc, copy_sz); } else { TI_PUT_NB_BULK(handle, TO_BOX(dst_data), TO_LOCAL(dst_data), localsrc, copy_sz); } } else if (!islocalsrc && islocaldest) { /* --- GET --- */ if (!src_isatomic) { ti_bulk_read(TO_LOCAL(dst_data), TO_BOX(src_data), TO_LOCAL(src_data), copy_sz, tic_gp_only); } else if (handle == NULL) { ti_bulk_read(TO_LOCAL(dst_data), TO_BOX(src_data), TO_LOCAL(src_data), copy_sz, tic_no_ptrs); } else if (handle == HANDLE_NBI) { TI_GET_NBI_BULK_NOPTRS(TO_LOCAL(dst_data), TO_BOX(src_data), TO_LOCAL(src_data), copy_sz); } else { TI_GET_NB_BULK_NOPTRS(handle, TO_LOCAL(dst_data), TO_BOX(src_data), TO_LOCAL(src_data), copy_sz); } } else { /* !islocalsrc && !islocaldest --- 3rd Party --- */ /* TODO: implement non-blocking for 3rd party transfers */ VARARRAY_DECLARE(jbyte, tmp_buf, copy_sz); VARARRAY_CREATE(jbyte, tmp_buf, copy_sz); ti_bulk_read(tmp_buf, TO_BOX(src_data), TO_LOCAL(src_data), copy_sz, (src_isatomic?tic_no_ptrs:tic_gp_only)); ti_bulk_write(TO_BOX(dst_data), TO_LOCAL(dst_data), tmp_buf, copy_sz); VARARRAY_DESTROY(tmp_buf); } } ti_srcpos_unfreeze(); } jlong m17currentTimeMillismT6System4lang4java() { struct timeval now; int retval = gettimeofday(&now, 0); if (retval) { perror("gettimeofday"); abort(); } /* We could round the usecs, but it does not seem worth it. */ return now.tv_sec * (jlong) 1000 + now.tv_usec / 1000; } static void addProperty( PT10Properties4util4java props, char const keyC[], char const valueC[] ) { if (valueC) { const LP_JString key = java_string_build_8( (char*)keyC ); const LP_JString value = java_string_build_8( (char*)valueC ); m11addPropertyPT10Properties4util4javaLT6String4lang4javaLT6String4lang4javamT11NativeUtils4lang2ti( props, key, value ); } } PT10Properties4util4java m14initPropertiesPT10Properties4util4javamT6System4lang4java( PT10Properties4util4java props ) { char cwdbuf[PATH_MAX+2]; char const * const cwd = getcwd( cwdbuf, PATH_MAX ); struct passwd pwbuf_struct; char pwbuf_data[1024]; char const * username = NULL; char const * homedir = NULL; #if 0 /* this is unthreadsafe and has been observed to cause deadlocks on Linux * it also causes things to be allocated using malloc, which may piss off * the GC */ const struct passwd * const user = getpwuid( getuid() ); username = user->pw_name; homedir = user->pw_dir; #else /* first try to get them the easy way */ username = getenvMaster("USER"); homedir = getenvMaster("HOME"); if (!username || !*username || !homedir || !*homedir) { /* a non-standard but common (and safe) option * DOB: this still causes segfaults on sequential backends on some * Linux kernels.. not sure why */ struct passwd * user = NULL; /* getpwuid_r is supposed to be re-entrant, but at least on Linux it * clearly is not, so enforce a critical section around it */ static ti_lock_t getpwuid_r_lock = ti_lock_decl_initializer; ti_lock(&getpwuid_r_lock); #if defined(LINUX) /* getpwuid* is WAY more trouble than it's worth on Linux */ user = &pwbuf_struct; user->pw_name = "unknown"; user->pw_dir = "/"; #elif defined(SOLARIS) && !defined(_POSIX_PTHREAD_SEMANTICS) user = getpwuid_r( getuid(), &pwbuf_struct, pwbuf_data, 1024 ); #else getpwuid_r( getuid(), &pwbuf_struct, pwbuf_data, 1024, &user ); #endif ti_unlock(&getpwuid_r_lock); username = user->pw_name; homedir = user->pw_dir; } #endif addProperty( props, "java.version", VERSION ); addProperty( props, "java.vm.version", VERSION ); addProperty( props, "java.specification.name", "Java Platform API Specification" ); addProperty( props, "java.specification.version", "Sun Microsystems Inc." ); addProperty( props, "java.specification.version", "1.0" ); addProperty( props, "java.vendor", "Titanium Project" ); addProperty( props, "java.vendor.url", "http://titanium.cs.berkeley.edu/" ); addProperty( props, "java.home", "/" ); addProperty( props, "java.class.version", "0" ); addProperty( props, "java.class.path", "/" ); addProperty( props, "os.name", "Titanium" ); addProperty( props, "os.arch", "Titanium" ); addProperty( props, "os.version", "0" ); addProperty( props, "file.separator", "/" ); addProperty( props, "path.separator", ":" ); addProperty( props, "line.separator", "\n" ); addProperty( props, "runtime.model", RUNTIME_MODEL); #ifdef MEMORY_DISTRIBUTED addProperty( props, "runtime.distributed", "true"); #else addProperty( props, "runtime.distributed", "false"); #endif #ifdef MEMORY_SHARED addProperty( props, "runtime.shared", "true"); #else addProperty( props, "runtime.shared", "false"); #endif if (bounds_checking) addProperty( props, "runtime.boundschecking", "true"); else addProperty( props, "runtime.boundschecking", "false"); #if !defined(USE_GC_NONE) if (!ti_never_gc) addProperty( props, "runtime.gc", "true"); else #endif addProperty( props, "runtime.gc", "false"); /* note: keep this line with above */ addProperty( props, "runtime.exesuffix", EXESUFFIX); addProperty( props, "compiler.flags", (char*)tcCompilerFlags); if (username) addProperty( props, "user.name", username ); if (homedir) addProperty( props, "user.home", homedir ); if (cwd) addProperty( props, "user.dir", cwd ); return props; } GP_JString m6getenvPT6String4lang4javamT6System4lang4java( GP_JString key ) { char *c_key = globalJstringToCstring(key); char *c_val = (char *)getenvMaster(c_key); GP_JString val; LP_JString lval = NULL; if (c_val) lval = java_string_build_8(c_val); globalize( val, lval ); return val; }