diff --git a/src/builtin.cpp b/src/builtin.cpp index eed2508564..f7f2c12d29 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -327,3 +327,177 @@ Avian_avian_Singleton_getLong (t, reinterpret_cast(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(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(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(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(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(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(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(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(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(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(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(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(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(p); +} diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index c2b8471dde..977d466c6d 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -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(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(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(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(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(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(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(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(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(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(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(p); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_pageSize (Thread*, object, uintptr_t*) diff --git a/src/compile.cpp b/src/compile.cpp index 214cc7ba2c..4963212feb 100644 --- a/src/compile.cpp +++ b/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);