mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +00:00
fix ARM64 iOS JNI crashes
As documented at https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html, the ARM64 iOS ABI differs from the generic ABI in a few important ways. Specifically, arguments passed via the stack are aligned according to their natural alignment instead of 8 bytes. The VM's dynamic call code was aligning each argument to 8 bytes, so native JNI code couldn't find them in their expected places. Also, we weren't setting the "os.arch" system property on ARM64, so I fixed that too.
This commit is contained in:
parent
a13e97ddf7
commit
c2a0210c7b
@ -853,6 +853,12 @@ extern "C" JNIEXPORT jobjectArray JNICALL
|
|||||||
#elif defined ARCH_arm
|
#elif defined ARCH_arm
|
||||||
e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.arch=arm"));
|
e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.arch=arm"));
|
||||||
|
|
||||||
|
#elif defined ARCH_arm64
|
||||||
|
e->SetObjectArrayElement(array, index++, e->NewStringUTF("os.arch=arm64"));
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "unknown architecture"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
|
@ -72,6 +72,8 @@ typedef unsigned __int64 uint64_t;
|
|||||||
#define ARCH_x86_64
|
#define ARCH_x86_64
|
||||||
#elif defined __arm__
|
#elif defined __arm__
|
||||||
#define ARCH_arm
|
#define ARCH_arm
|
||||||
|
#elif defined __aarch64__
|
||||||
|
#define ARCH_arm64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // not _MSC_VER
|
#endif // not _MSC_VER
|
||||||
|
@ -199,6 +199,72 @@ inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined __APPLE__) && (defined ARCH_arm64)
|
||||||
|
const bool AppleARM64 = true;
|
||||||
|
#else
|
||||||
|
const bool AppleARM64 = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void advance(unsigned* stackIndex,
|
||||||
|
unsigned* stackSubIndex,
|
||||||
|
unsigned newStackSubIndex)
|
||||||
|
{
|
||||||
|
if (AppleARM64) {
|
||||||
|
if (newStackSubIndex == BytesPerWord) {
|
||||||
|
*stackSubIndex = 0;
|
||||||
|
++(*stackIndex);
|
||||||
|
} else {
|
||||||
|
*stackSubIndex = newStackSubIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void push(uint8_t type,
|
||||||
|
uintptr_t* stack,
|
||||||
|
unsigned* stackIndex,
|
||||||
|
unsigned* stackSubIndex,
|
||||||
|
uintptr_t argument)
|
||||||
|
{
|
||||||
|
if (AppleARM64) {
|
||||||
|
// See
|
||||||
|
// https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html
|
||||||
|
// for how Apple diverges from the generic ARM64 ABI on iOS.
|
||||||
|
// Specifically, arguments passed on the stack are aligned to
|
||||||
|
// their natural alignment rather than 8.
|
||||||
|
switch (type) {
|
||||||
|
case INT8_TYPE:
|
||||||
|
reinterpret_cast<int8_t*>(stack + *stackIndex)[*stackSubIndex] = argument;
|
||||||
|
advance(stackIndex, stackSubIndex, *stackSubIndex + 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INT16_TYPE:
|
||||||
|
advance(stackIndex, stackSubIndex, pad(*stackSubIndex, 2));
|
||||||
|
reinterpret_cast<int16_t*>(stack + *stackIndex)[*stackSubIndex / 2]
|
||||||
|
= argument;
|
||||||
|
advance(stackIndex, stackSubIndex, *stackSubIndex + 2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INT32_TYPE:
|
||||||
|
case FLOAT_TYPE:
|
||||||
|
advance(stackIndex, stackSubIndex, pad(*stackSubIndex, 4));
|
||||||
|
reinterpret_cast<int32_t*>(stack + *stackIndex)[*stackSubIndex / 4]
|
||||||
|
= argument;
|
||||||
|
advance(stackIndex, stackSubIndex, *stackSubIndex + 4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case POINTER_TYPE:
|
||||||
|
advance(stackIndex, stackSubIndex, pad(*stackSubIndex));
|
||||||
|
stack[(*stackIndex)++] = argument;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stack[(*stackIndex)++] = argument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline uint64_t dynamicCall(void* function,
|
inline uint64_t dynamicCall(void* function,
|
||||||
uintptr_t* arguments,
|
uintptr_t* arguments,
|
||||||
uint8_t* argumentTypes,
|
uint8_t* argumentTypes,
|
||||||
@ -226,6 +292,7 @@ inline uint64_t dynamicCall(void* function,
|
|||||||
(argumentCount * 8)
|
(argumentCount * 8)
|
||||||
/ BytesPerWord); // is > argumentSize to account for padding
|
/ BytesPerWord); // is > argumentSize to account for padding
|
||||||
unsigned stackIndex = 0;
|
unsigned stackIndex = 0;
|
||||||
|
unsigned stackSubIndex = 0;
|
||||||
|
|
||||||
unsigned ai = 0;
|
unsigned ai = 0;
|
||||||
for (unsigned ati = 0; ati < argumentCount; ++ati) {
|
for (unsigned ati = 0; ati < argumentCount; ++ati) {
|
||||||
@ -242,6 +309,7 @@ inline uint64_t dynamicCall(void* function,
|
|||||||
memcpy(vfpTable + vfpIndex, arguments + ai, 8);
|
memcpy(vfpTable + vfpIndex, arguments + ai, 8);
|
||||||
vfpIndex += 8 / BytesPerWord;
|
vfpIndex += 8 / BytesPerWord;
|
||||||
} else {
|
} else {
|
||||||
|
advance(&stackIndex, &stackSubIndex, pad(stackSubIndex));
|
||||||
vfpIndex = VfpCount;
|
vfpIndex = VfpCount;
|
||||||
if (stackIndex % Alignment) {
|
if (stackIndex % Alignment) {
|
||||||
++stackIndex;
|
++stackIndex;
|
||||||
@ -260,7 +328,11 @@ inline uint64_t dynamicCall(void* function,
|
|||||||
} else if (vfpIndex < VfpCount) {
|
} else if (vfpIndex < VfpCount) {
|
||||||
vfpTable[vfpIndex++] = arguments[ai];
|
vfpTable[vfpIndex++] = arguments[ai];
|
||||||
} else {
|
} else {
|
||||||
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
push(argumentTypes[ati],
|
||||||
|
RUNTIME_ARRAY_BODY(stack),
|
||||||
|
&stackIndex,
|
||||||
|
&stackSubIndex,
|
||||||
|
arguments[ai]);
|
||||||
}
|
}
|
||||||
++ai;
|
++ai;
|
||||||
break;
|
break;
|
||||||
@ -280,6 +352,7 @@ inline uint64_t dynamicCall(void* function,
|
|||||||
gprIndex += 8 / BytesPerWord;
|
gprIndex += 8 / BytesPerWord;
|
||||||
}
|
}
|
||||||
} else { // pass argument on stack
|
} else { // pass argument on stack
|
||||||
|
advance(&stackIndex, &stackSubIndex, pad(stackSubIndex));
|
||||||
gprIndex = GprCount;
|
gprIndex = GprCount;
|
||||||
if (stackIndex % Alignment) {
|
if (stackIndex % Alignment) {
|
||||||
++stackIndex;
|
++stackIndex;
|
||||||
@ -295,7 +368,11 @@ inline uint64_t dynamicCall(void* function,
|
|||||||
if (gprIndex < GprCount) {
|
if (gprIndex < GprCount) {
|
||||||
gprTable[gprIndex++] = arguments[ai];
|
gprTable[gprIndex++] = arguments[ai];
|
||||||
} else {
|
} else {
|
||||||
RUNTIME_ARRAY_BODY(stack)[stackIndex++] = arguments[ai];
|
push(argumentTypes[ati],
|
||||||
|
RUNTIME_ARRAY_BODY(stack),
|
||||||
|
&stackIndex,
|
||||||
|
&stackSubIndex,
|
||||||
|
arguments[ai]);
|
||||||
}
|
}
|
||||||
++ai;
|
++ai;
|
||||||
} break;
|
} break;
|
||||||
|
Loading…
Reference in New Issue
Block a user