Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.apache.fory.builder;

import static org.apache.fory.codegen.Expression.Invoke.inlineInvoke;
import static org.apache.fory.platform.JdkVersion.JDK8_ARM;
import static org.apache.fory.type.TypeUtils.CLASS_TYPE;
import static org.apache.fory.type.TypeUtils.OBJECT_ARRAY_TYPE;
import static org.apache.fory.type.TypeUtils.OBJECT_TYPE;
Expand Down Expand Up @@ -59,6 +60,7 @@
import org.apache.fory.memory.NativeByteOrder;
import org.apache.fory.platform.GraalvmSupport;
import org.apache.fory.platform.JdkVersion;
import org.apache.fory.platform.internal._UnsafeUtils;
import org.apache.fory.reflect.ObjectInstantiator;
import org.apache.fory.reflect.ObjectInstantiators;
import org.apache.fory.reflect.ReflectionUtils;
Expand Down Expand Up @@ -787,27 +789,45 @@ protected Expression unsafePutBoolean(Expression base, Expression pos, Expressio
}

protected Expression unsafePutChar(Expression base, Expression pos, Expression value) {
if (JDK8_ARM) {
return new StaticInvoke(_UnsafeUtils.class, "putChar", base, pos, value);
}
return unsafeInvoke("putChar", base, pos, value);
}

protected Expression unsafePutShort(Expression base, Expression pos, Expression value) {
if (JDK8_ARM) {
return new StaticInvoke(_UnsafeUtils.class, "putShort", base, pos, value);
}
return unsafeInvoke("putShort", base, pos, value);
}

protected Expression unsafePutInt(Expression base, Expression pos, Expression value) {
if (JDK8_ARM) {
return new StaticInvoke(_UnsafeUtils.class, "putInt", base, pos, value);
}
return unsafeInvoke("putInt", base, pos, value);
}

protected Expression unsafePutLong(Expression base, Expression pos, Expression value) {
if (JDK8_ARM) {
return new StaticInvoke(_UnsafeUtils.class, "putLong", base, pos, value);
}
return unsafeInvoke("putLong", base, pos, value);
}

protected Expression unsafePutFloat(Expression base, Expression pos, Expression value) {
if (JDK8_ARM) {
return new StaticInvoke(_UnsafeUtils.class, "putFloat", base, pos, value);
}
return unsafeInvoke("putFloat", base, pos, value);
}

/** Build unsafePutDouble operation. */
protected Expression unsafePutDouble(Expression base, Expression pos, Expression value) {
if (JDK8_ARM) {
return new StaticInvoke(_UnsafeUtils.class, "putDouble", base, pos, value);
}
return unsafeInvoke("putDouble", base, pos, value);
}

Expand All @@ -821,47 +841,65 @@ protected Expression unsafeGetBoolean(Expression base, Expression pos) {
}

protected Expression unsafeGetChar(Expression base, Expression pos) {
Inlineable expr = unsafeInvoke("getChar", PRIMITIVE_CHAR_TYPE, base, pos);
Inlineable expr =
JDK8_ARM
? new StaticInvoke(_UnsafeUtils.class, "getChar", PRIMITIVE_CHAR_TYPE, base, pos)
: unsafeInvoke("getChar", PRIMITIVE_CHAR_TYPE, base, pos);
if (!NativeByteOrder.IS_LITTLE_ENDIAN) {
expr = new StaticInvoke(Character.class, "reverseBytes", PRIMITIVE_CHAR_TYPE, expr.inline());
}
return expr;
}

protected Expression unsafeGetShort(Expression base, Expression pos) {
Inlineable expr = unsafeInvoke("getShort", PRIMITIVE_SHORT_TYPE, base, pos);
Inlineable expr =
JDK8_ARM
? new StaticInvoke(_UnsafeUtils.class, "getShort", PRIMITIVE_SHORT_TYPE, base, pos)
: unsafeInvoke("getShort", PRIMITIVE_SHORT_TYPE, base, pos);
if (!NativeByteOrder.IS_LITTLE_ENDIAN) {
expr = new StaticInvoke(Short.class, "reverseBytes", PRIMITIVE_SHORT_TYPE, expr.inline());
}
return expr;
}

protected Expression unsafeGetInt(Expression base, Expression pos) {
Inlineable expr = unsafeInvoke("getInt", PRIMITIVE_INT_TYPE, base, pos);
Inlineable expr =
JDK8_ARM
? new StaticInvoke(_UnsafeUtils.class, "getInt", PRIMITIVE_INT_TYPE, base, pos)
: unsafeInvoke("getInt", PRIMITIVE_INT_TYPE, base, pos);
if (!NativeByteOrder.IS_LITTLE_ENDIAN) {
expr = new StaticInvoke(Integer.class, "reverseBytes", PRIMITIVE_INT_TYPE, expr.inline());
}
return expr;
}

protected Expression unsafeGetLong(Expression base, Expression pos) {
Inlineable expr = unsafeInvoke("getLong", PRIMITIVE_LONG_TYPE, base, pos);
Inlineable expr =
JDK8_ARM
? new StaticInvoke(_UnsafeUtils.class, "getLong", PRIMITIVE_LONG_TYPE, base, pos)
: unsafeInvoke("getLong", PRIMITIVE_LONG_TYPE, base, pos);
if (!NativeByteOrder.IS_LITTLE_ENDIAN) {
expr = new StaticInvoke(Long.class, "reverseBytes", PRIMITIVE_LONG_TYPE, expr.inline());
}
return expr;
}

protected Expression unsafeGetFloat(Expression base, Expression pos) {
Inlineable expr = unsafeInvoke("getInt", PRIMITIVE_INT_TYPE, base, pos);
Inlineable expr =
JDK8_ARM
? new StaticInvoke(_UnsafeUtils.class, "getInt", PRIMITIVE_INT_TYPE, base, pos)
: unsafeInvoke("getInt", PRIMITIVE_INT_TYPE, base, pos);
if (!NativeByteOrder.IS_LITTLE_ENDIAN) {
expr = new StaticInvoke(Integer.class, "reverseBytes", PRIMITIVE_INT_TYPE, expr.inline());
}
return new StaticInvoke(Float.class, "intBitsToFloat", PRIMITIVE_FLOAT_TYPE, expr.inline());
}

protected Expression unsafeGetDouble(Expression base, Expression pos) {
Inlineable expr = unsafeInvoke("getLong", PRIMITIVE_LONG_TYPE, base, pos);
Inlineable expr =
JDK8_ARM
? new StaticInvoke(_UnsafeUtils.class, "getLong", PRIMITIVE_LONG_TYPE, base, pos)
: unsafeInvoke("getLong", PRIMITIVE_LONG_TYPE, base, pos);
if (!NativeByteOrder.IS_LITTLE_ENDIAN) {
expr = new StaticInvoke(Long.class, "reverseBytes", PRIMITIVE_LONG_TYPE, expr.inline());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.apache.fory.memory;

import static org.apache.fory.platform.JdkVersion.JDK8_ARM;

import org.apache.fory.platform.AndroidSupport;
import org.apache.fory.platform.internal._UnsafeUtils;
import sun.misc.Unsafe;
Expand Down Expand Up @@ -80,17 +82,26 @@ public static long getInt64(byte[] o, int index) {
if (AndroidSupport.IS_ANDROID) {
return MemoryOps.getInt64(o, index);
}
// Unsafe object offsets are long. Keep the cast so JDK8-compiled bytecode calls
// getLong(Object, long) when the artifact runs on JDK9+.
long v = UNSAFE.getLong(o, (long) BYTE_ARRAY_OFFSET + index);
// Compute the absolute array offset in long so large indices cannot overflow the addition.
long v;
if (JDK8_ARM) {
v = _UnsafeUtils.getLongFromInts(o, (long) BYTE_ARRAY_OFFSET + index);
} else {
v = UNSAFE.getLong(o, (long) BYTE_ARRAY_OFFSET + index);
}
return NativeByteOrder.IS_LITTLE_ENDIAN ? v : Long.reverseBytes(v);
}

public static int getInt32(byte[] o, int index) {
if (AndroidSupport.IS_ANDROID) {
return MemoryOps.getInt32(o, index);
}
int v = UNSAFE.getInt(o, (long) BYTE_ARRAY_OFFSET + index);
int v;
if (JDK8_ARM) {
v = _UnsafeUtils.getIntFromShorts(o, (long) BYTE_ARRAY_OFFSET + index);
} else {
v = UNSAFE.getInt(o, (long) BYTE_ARRAY_OFFSET + index);
}
return NativeByteOrder.IS_LITTLE_ENDIAN ? v : Integer.reverseBytes(v);
}

Expand All @@ -102,7 +113,11 @@ public static void putInt32(byte[] o, int index, int value) {
if (!NativeByteOrder.IS_LITTLE_ENDIAN) {
value = Integer.reverseBytes(value);
}
UNSAFE.putInt(o, (long) BYTE_ARRAY_OFFSET + index, value);
if (JDK8_ARM) {
_UnsafeUtils.putIntAsShorts(o, (long) BYTE_ARRAY_OFFSET + index, value);
} else {
UNSAFE.putInt(o, (long) BYTE_ARRAY_OFFSET + index, value);
}
}

public static void putInt64(byte[] o, int index, long value) {
Expand All @@ -113,7 +128,11 @@ public static void putInt64(byte[] o, int index, long value) {
if (!NativeByteOrder.IS_LITTLE_ENDIAN) {
value = Long.reverseBytes(value);
}
// See getInt64: the cast controls the Unsafe method descriptor in bytecode.
UNSAFE.putLong(o, (long) BYTE_ARRAY_OFFSET + index, value);
// As in getInt64, widen before adding the array base offset.
if (JDK8_ARM) {
_UnsafeUtils.putLongAsInts(o, (long) BYTE_ARRAY_OFFSET + index, value);
} else {
UNSAFE.putLong(o, (long) BYTE_ARRAY_OFFSET + index, value);
}
}
}
Loading
Loading