/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.jni;
import org.jikesrvm.VM;
import org.jikesrvm.runtime.VM_Magic;
import org.jikesrvm.runtime.VM_Memory;
import org.jikesrvm.runtime.VM_SysCall;
import org.jikesrvm.util.VM_StringUtilities;
import org.vmmagic.unboxed.Address;
/**
* Platform independent utility functions called from VM_JNIFunctions
* (cannot be placed in VM_JNIFunctions because methods
* there are specially compiled to be called from native).
*
* @see VM_JNIFunctions
*/
public abstract class VM_JNIGenericHelpers {
/**
* Given an address in C that points to a null-terminated string,
* create a new Java byte[] with a copy of the string.
*
* @param stringAddress an address in C space for a string
* @return a new Java byte[]
*/
public static byte[] createByteArrayFromC(Address stringAddress) {
// disable alignment checking for this method
if (VM.AlignmentChecking) {
VM_SysCall.sysCall.sysDisableAlignmentChecking();
}
// scan the memory for the null termination of the string
int length = 0;
for (Address addr = stringAddress; true; addr = addr.plus(4)) {
int word = addr.loadInt();
int byte0, byte1, byte2, byte3;
if (VM.LittleEndian) {
byte3 = ((word >> 24) & 0xFF);
byte2 = ((word >> 16) & 0xFF);
byte1 = ((word >> 8) & 0xFF);
byte0 = (word & 0xFF);
} else {
byte0 = ((word >> 24) & 0xFF);
byte1 = ((word >> 16) & 0xFF);
byte2 = ((word >> 8) & 0xFF);
byte3 = (word & 0xFF);
}
if (byte0 == 0) {
break;
}
length++;
if (byte1 == 0) {
break;
}
length++;
if (byte2 == 0) {
break;
}
length++;
if (byte3 == 0) {
break;
}
length++;
}
byte[] contents = new byte[length];
VM_Memory.memcopy(VM_Magic.objectAsAddress(contents), stringAddress, length);
// re-enable alignment checking
if (VM.AlignmentChecking) {
VM_SysCall.sysCall.sysEnableAlignmentChecking();
}
return contents;
}
/**
* Given an address in C that points to a null-terminated string,
* create a new Java String with a copy of the string.
*
* @param stringAddress an address in C space for a string
* @return a new Java String
*/
public static String createStringFromC(Address stringAddress) {
byte[] tmp = createByteArrayFromC(stringAddress);
if (VM.fullyBooted) {
return new String(tmp);
} else {
// Can't do real Char encoding until VM is fully booted.
// All Strings encountered during booting must be ascii
return VM_StringUtilities.asciiBytesToString(tmp);
}
}
/** A JNI helper function, to set the value pointed to by a C pointer
* of type (jboolean *).
* @param boolPtr Native pointer to a jboolean variable to be set. May be
* the NULL pointer, in which case we do nothing.
* @param val Value to set it to (usually TRUE)
*
* XXX There was a strange bug where calling this would crash the VM.
* That's why it's ifdef'd. So the dozen-odd places in VM_JNIFunctions
* where I would use it instead have this code inlined, guarded with an
* #if. --Steve Augart
*/
static void setBoolStar(Address boolPtr, boolean val) {
// VM.sysWriteln("Someone called setBoolStar");
if (boolPtr.isZero()) {
return;
}
int temp = boolPtr.loadInt();
int intval;
if (VM.LittleEndian) {
if (val) {
// set to true.
intval = (temp & 0xffffff00) | 0x00000001;
} else {
// set to false
intval = (temp & 0xffffff00);
}
} else {
/* Big Endian */
if (val) {
// set to true
intval = (temp & 0x00ffffff) | 0x01000000;
} else {
// set to false
intval = temp & 0x00ffffff;
}
}
boolPtr.store(intval);
}
}