// Use packed structures for access to unaligned data on targets with alignment restrictions. // The compiler will generate appropriate code to access these structures without // generating alignment exceptions. template <typename T> staticinline T get_unaligned(const T* address) { struct unaligned {
T v;
} __attribute__((packed)); const unaligned* p = reinterpret_cast<const unaligned*>(address); return p->v;
}
template <typename T> staticinlinevoid put_unaligned(T* address, T v) { struct unaligned {
T v;
} __attribute__((packed));
unaligned* p = reinterpret_cast<unaligned*>(address);
p->v = v;
}
template <typename T> static T cast(jlong address) { returnreinterpret_cast<T>(static_cast<uintptr_t>(address));
}
// Byte-swap 2 jshort values packed in a jint. staticinline jint bswap_2x16(jint v) { // v is initially ABCD
v = __builtin_bswap32(v); // v=DCBA
v = (v << 16) | ((v >> 16) & 0xffff); // v=BADC return v;
}
staticinlinevoid swapShorts(jshort* dstShorts, const jshort* srcShorts, size_t count) { // Do 32-bit swaps as long as possible...
jint* dst = reinterpret_cast<jint*>(dstShorts); const jint* src = reinterpret_cast<const jint*>(srcShorts); for (size_t i = 0; i < count / 2; ++i) {
jint v = get_unaligned<jint>(src++);
put_unaligned<jint>(dst++, bswap_2x16(v));
} if ((count % 2) != 0) {
jshort v = get_unaligned<jshort>(reinterpret_cast<const jshort*>(src));
put_unaligned<jshort>(reinterpret_cast<jshort*>(dst), __builtin_bswap16(v));
}
}
staticinlinevoid swapInts(jint* dstInts, const jint* srcInts, size_t count) { for (size_t i = 0; i < count; ++i) {
jint v = get_unaligned<int>(srcInts++);
put_unaligned<jint>(dstInts++, __builtin_bswap32(v));
}
}
// Implements the peekXArray methods: // - For unswapped access, we just use the JNI SetXArrayRegion functions. // - For swapped access, we use GetXArrayElements and our own copy-and-swap routines. // GetXArrayElements is disproportionately cheap on Dalvik because it doesn't copy (as opposed // to Hotspot, which always copies). The SWAP_FN copies and swaps in one pass, which is cheaper // than copying and then swapping in a second pass. Depending on future VM/GC changes, the // swapped case might need to be revisited. #define PEEKER(SCALAR_TYPE, JNI_NAME, SWAP_TYPE, SWAP_FN) \
{ \ if (swap) { \
Scoped##JNI_NAME##ArrayRW elements(env, dst); \ if (elements.get() == NULL) { \ return; \
} \ const SWAP_TYPE* src = cast<const SWAP_TYPE*>(srcAddress); \
SWAP_FN(reinterpret_cast<SWAP_TYPE*>(elements.get()) + dstOffset, src, count); /*NOLINT*/ \
} else { \ const SCALAR_TYPE* src = cast<const SCALAR_TYPE*>(srcAddress); \
env->Set##JNI_NAME##ArrayRegion(dst, dstOffset, count, src); \
} \
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.