mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
implement sun.misc.Unsafe raw memory access methods
The primitive get/put methods are implemented as intrinsics by the compiler for performance.
This commit is contained in:
parent
44277db2de
commit
e8e3c9066f
174
src/builtin.cpp
174
src/builtin.cpp
@ -327,3 +327,177 @@ Avian_avian_Singleton_getLong
|
||||
(t, reinterpret_cast<object>(arguments[0]), arguments[1]), 8);
|
||||
return v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_allocateMemory
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
void* p = malloc(arguments[1]);
|
||||
if (p) {
|
||||
return reinterpret_cast<int64_t>(p);
|
||||
} else {
|
||||
throwNew(t, Machine::OutOfMemoryErrorType);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_freeMemory
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
void* p = reinterpret_cast<void*>(arguments[1]);
|
||||
if (p) {
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_setMemory
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int64_t count; memcpy(&count, arguments + 3, 8);
|
||||
int8_t v = arguments[5];
|
||||
|
||||
memset(reinterpret_cast<int8_t*>(p), v, count);
|
||||
}
|
||||
|
||||
// NB: The following primitive get/put methods are only used by the
|
||||
// interpreter. The JIT/AOT compiler implements them as intrinsics,
|
||||
// so these versions will be ignored.
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putByte__JB
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int8_t v = arguments[3];
|
||||
|
||||
*reinterpret_cast<int8_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putShort__JS
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int16_t v = arguments[3];
|
||||
|
||||
*reinterpret_cast<int16_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putChar__JC
|
||||
(Thread* t, object method, uintptr_t* arguments)
|
||||
{
|
||||
Avian_sun_misc_Unsafe_putShort__JS(t, method, arguments);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putInt__JI
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int32_t v = arguments[3];
|
||||
|
||||
*reinterpret_cast<int32_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putFloat__JF
|
||||
(Thread* t, object method, uintptr_t* arguments)
|
||||
{
|
||||
Avian_sun_misc_Unsafe_putInt__JI(t, method, arguments);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putLong__JJ
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int64_t v; memcpy(&v, arguments + 3, 8);
|
||||
|
||||
*reinterpret_cast<int64_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putDouble__JD
|
||||
(Thread* t, object method, uintptr_t* arguments)
|
||||
{
|
||||
Avian_sun_misc_Unsafe_putLong__JJ(t, method, arguments);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putAddress__JJ
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int64_t v; memcpy(&v, arguments + 3, 8);
|
||||
|
||||
*reinterpret_cast<intptr_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getByte__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<int8_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getShort__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<int16_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getChar__J
|
||||
(Thread* t, object method, uintptr_t* arguments)
|
||||
{
|
||||
return Avian_sun_misc_Unsafe_getShort__J(t, method, arguments);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getInt__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<int32_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getFloat__J
|
||||
(Thread* t, object method, uintptr_t* arguments)
|
||||
{
|
||||
return Avian_sun_misc_Unsafe_getInt__J(t, method, arguments);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getLong__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<int64_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getDouble__J
|
||||
(Thread* t, object method, uintptr_t* arguments)
|
||||
{
|
||||
return Avian_sun_misc_Unsafe_getLong__J(t, method, arguments);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getAddress__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<intptr_t*>(p);
|
||||
}
|
||||
|
@ -2615,115 +2615,6 @@ Avian_sun_misc_Unsafe_compareAndSwapLong
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_allocateMemory
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
{
|
||||
void* p = malloc(arguments[1]);
|
||||
if (p) {
|
||||
return reinterpret_cast<int64_t>(p);
|
||||
} else {
|
||||
throwNew(t, Machine::OutOfMemoryErrorType);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_freeMemory
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
void* p = reinterpret_cast<void*>(arguments[1]);
|
||||
if (p) {
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_setMemory
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int64_t count; memcpy(&count, arguments + 3, 8);
|
||||
int8_t v = arguments[5];
|
||||
|
||||
memset(reinterpret_cast<int8_t*>(p), v, count);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putByte__JB
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int8_t v = arguments[3];
|
||||
|
||||
*reinterpret_cast<int8_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putShort__JS
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int16_t v = arguments[3];
|
||||
|
||||
*reinterpret_cast<int16_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putLong__JJ
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int64_t v; memcpy(&v, arguments + 3, 8);
|
||||
|
||||
*reinterpret_cast<int64_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Avian_sun_misc_Unsafe_putInt__JI
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
int32_t v = arguments[3];
|
||||
|
||||
*reinterpret_cast<int32_t*>(p) = v;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getByte__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<int8_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getInt__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<int32_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getLong__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<int64_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_getFloat__J
|
||||
(Thread*, object, uintptr_t* arguments)
|
||||
{
|
||||
int64_t p; memcpy(&p, arguments + 1, 8);
|
||||
|
||||
return *reinterpret_cast<int32_t*>(p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
Avian_sun_misc_Unsafe_pageSize
|
||||
(Thread*, object, uintptr_t*)
|
||||
|
186
src/compile.cpp
186
src/compile.cpp
@ -3809,6 +3809,13 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip,
|
||||
return true;
|
||||
}
|
||||
|
||||
Compiler::Operand*
|
||||
popLongAddress(Frame* frame)
|
||||
{
|
||||
return TargetBytesPerWord == 8 ? frame->popLong() : frame->c->load
|
||||
(8, 8, frame->popLong(), TargetBytesPerWord);
|
||||
}
|
||||
|
||||
bool
|
||||
intrinsic(MyThread* t, Frame* frame, object target)
|
||||
{
|
||||
@ -3837,6 +3844,127 @@ intrinsic(MyThread* t, Frame* frame, object target)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (UNLIKELY(MATCH(className, "sun/misc/Unsafe"))) {
|
||||
Compiler* c = frame->c;
|
||||
if (MATCH(methodName(t, target), "getByte")
|
||||
and MATCH(methodSpec(t, target), "(J)B"))
|
||||
{
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(1, 1, c->memory(address, Compiler::IntegerType, 0, 0, 1),
|
||||
TargetBytesPerWord));
|
||||
return true;
|
||||
} else if (MATCH(methodName(t, target), "putByte")
|
||||
and MATCH(methodSpec(t, target), "(JB)V"))
|
||||
{
|
||||
Compiler::Operand* value = frame->popInt();
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 1, c->memory
|
||||
(address, Compiler::IntegerType, 0, 0, 1));
|
||||
return true;
|
||||
} else if ((MATCH(methodName(t, target), "getShort")
|
||||
and MATCH(methodSpec(t, target), "(J)S"))
|
||||
or (MATCH(methodName(t, target), "getChar")
|
||||
and MATCH(methodSpec(t, target), "(J)C")))
|
||||
{
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(2, 2, c->memory(address, Compiler::IntegerType, 0, 0, 1),
|
||||
TargetBytesPerWord));
|
||||
return true;
|
||||
} else if ((MATCH(methodName(t, target), "putShort")
|
||||
and MATCH(methodSpec(t, target), "(JS)V"))
|
||||
or (MATCH(methodName(t, target), "putChar")
|
||||
and MATCH(methodSpec(t, target), "(JC)V")))
|
||||
{
|
||||
Compiler::Operand* value = frame->popInt();
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 2, c->memory
|
||||
(address, Compiler::IntegerType, 0, 0, 1));
|
||||
return true;
|
||||
} else if ((MATCH(methodName(t, target), "getInt")
|
||||
and MATCH(methodSpec(t, target), "(J)I"))
|
||||
or (MATCH(methodName(t, target), "getFloat")
|
||||
and MATCH(methodSpec(t, target), "(J)F")))
|
||||
{
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
frame->pushInt
|
||||
(c->load
|
||||
(4, 4, c->memory
|
||||
(address, MATCH(methodName(t, target), "getInt")
|
||||
? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1),
|
||||
TargetBytesPerWord));
|
||||
return true;
|
||||
} else if ((MATCH(methodName(t, target), "putInt")
|
||||
and MATCH(methodSpec(t, target), "(JI)V"))
|
||||
or (MATCH(methodName(t, target), "putFloat")
|
||||
and MATCH(methodSpec(t, target), "(JF)V")))
|
||||
{
|
||||
Compiler::Operand* value = frame->popInt();
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
c->store
|
||||
(TargetBytesPerWord, value, 4, c->memory
|
||||
(address, MATCH(methodName(t, target), "putInt")
|
||||
? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1));
|
||||
return true;
|
||||
} else if ((MATCH(methodName(t, target), "getLong")
|
||||
and MATCH(methodSpec(t, target), "(J)J"))
|
||||
or (MATCH(methodName(t, target), "getDouble")
|
||||
and MATCH(methodSpec(t, target), "(J)D")))
|
||||
{
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
frame->pushLong
|
||||
(c->load
|
||||
(8, 8, c->memory
|
||||
(address, MATCH(methodName(t, target), "getLong")
|
||||
? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1),
|
||||
8));
|
||||
return true;
|
||||
} else if ((MATCH(methodName(t, target), "putLong")
|
||||
and MATCH(methodSpec(t, target), "(JJ)V"))
|
||||
or (MATCH(methodName(t, target), "putDouble")
|
||||
and MATCH(methodSpec(t, target), "(JD)V")))
|
||||
{
|
||||
Compiler::Operand* value = frame->popLong();
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
c->store
|
||||
(8, value, 8, c->memory
|
||||
(address, MATCH(methodName(t, target), "putLong")
|
||||
? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1));
|
||||
return true;
|
||||
} else if (MATCH(methodName(t, target), "getAddress")
|
||||
and MATCH(methodSpec(t, target), "(J)J"))
|
||||
{
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
frame->pushLong
|
||||
(c->load
|
||||
(TargetBytesPerWord, TargetBytesPerWord,
|
||||
c->memory(address, Compiler::AddressType, 0, 0, 1), 8));
|
||||
return true;
|
||||
} else if (MATCH(methodName(t, target), "putAddress")
|
||||
and MATCH(methodSpec(t, target), "(JJ)V"))
|
||||
{
|
||||
Compiler::Operand* value = frame->popLong();
|
||||
Compiler::Operand* address = popLongAddress(frame);
|
||||
frame->popObject();
|
||||
c->store
|
||||
(8, value, TargetBytesPerWord, c->memory
|
||||
(address, Compiler::AddressType, 0, 0, 1));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -5022,43 +5150,45 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
|
||||
if (LIKELY(target)) {
|
||||
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
||||
|
||||
if (not intrinsic(t, frame, target)) {
|
||||
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
||||
|
||||
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
||||
if (LIKELY(methodVirtual(t, target))) {
|
||||
unsigned parameterFootprint = methodParameterFootprint(t, target);
|
||||
|
||||
if (LIKELY(methodVirtual(t, target))) {
|
||||
unsigned parameterFootprint = methodParameterFootprint(t, target);
|
||||
unsigned offset = TargetClassVtable
|
||||
+ (methodOffset(t, target) * TargetBytesPerWord);
|
||||
|
||||
unsigned offset = TargetClassVtable
|
||||
+ (methodOffset(t, target) * TargetBytesPerWord);
|
||||
Compiler::Operand* instance = c->peek(1, parameterFootprint - 1);
|
||||
|
||||
Compiler::Operand* instance = c->peek(1, parameterFootprint - 1);
|
||||
unsigned rSize = resultSize(t, methodReturnCode(t, target));
|
||||
|
||||
unsigned rSize = resultSize(t, methodReturnCode(t, target));
|
||||
Compiler::Operand* result = c->stackCall
|
||||
(c->memory
|
||||
(c->and_
|
||||
(TargetBytesPerWord, c->constant
|
||||
(TargetPointerMask, Compiler::IntegerType),
|
||||
c->memory(instance, Compiler::ObjectType, 0, 0, 1)),
|
||||
Compiler::ObjectType, offset, 0, 1),
|
||||
tailCall ? Compiler::TailJump : 0,
|
||||
frame->trace(0, 0),
|
||||
rSize,
|
||||
operandTypeForFieldCode(t, methodReturnCode(t, target)),
|
||||
parameterFootprint);
|
||||
|
||||
Compiler::Operand* result = c->stackCall
|
||||
(c->memory
|
||||
(c->and_
|
||||
(TargetBytesPerWord, c->constant
|
||||
(TargetPointerMask, Compiler::IntegerType),
|
||||
c->memory(instance, Compiler::ObjectType, 0, 0, 1)),
|
||||
Compiler::ObjectType, offset, 0, 1),
|
||||
tailCall ? Compiler::TailJump : 0,
|
||||
frame->trace(0, 0),
|
||||
rSize,
|
||||
operandTypeForFieldCode(t, methodReturnCode(t, target)),
|
||||
parameterFootprint);
|
||||
frame->pop(parameterFootprint);
|
||||
|
||||
frame->pop(parameterFootprint);
|
||||
if (rSize) {
|
||||
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
||||
}
|
||||
} else {
|
||||
// OpenJDK generates invokevirtual calls to private methods
|
||||
// (e.g. readObject and writeObject for serialization), so
|
||||
// we must handle such cases here.
|
||||
|
||||
if (rSize) {
|
||||
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
||||
compileDirectInvoke(t, frame, target, tailCall);
|
||||
}
|
||||
} else {
|
||||
// OpenJDK generates invokevirtual calls to private methods
|
||||
// (e.g. readObject and writeObject for serialization), so
|
||||
// we must handle such cases here.
|
||||
|
||||
compileDirectInvoke(t, frame, target, tailCall);
|
||||
}
|
||||
} else {
|
||||
PROTECT(t, reference);
|
||||
|
Loading…
Reference in New Issue
Block a user