//===-- ArrayCopy.inc - ArrayCopy implementation --------------------------===// // // The VMKit project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// void ArrayCopy(JavaObject* src, jint sstart, JavaObject* dst, jint dstart, jint len) { ArrayObject* arraySrc = 0; ArrayObject* arrayDest = 0; JavaObject* cur = 0; llvm_gcroot(src, 0); llvm_gcroot(dst, 0); llvm_gcroot(cur, 0); llvm_gcroot(arraySrc, 0); llvm_gcroot(arrayDest, 0); JavaThread* th = JavaThread::get(); Jnjvm *vm = th->getJVM(); if (src == NULL || dst == NULL) { th->throwException(vm->CreateNullPointerException()); UNREACHABLE(); } if (!(JavaObject::getClass(src)->isArray() && JavaObject::getClass(dst)->isArray())) { th->throwException(vm->CreateArrayStoreException( (JavaVirtualTable*)dst->getVirtualTable())); UNREACHABLE(); } assert(src->getVirtualTable()); assert(dst->getVirtualTable()); UserClassArray* ts = (UserClassArray*)JavaObject::getClass(src); UserClassArray* td = (UserClassArray*)JavaObject::getClass(dst); UserCommonClass* dstType = td->baseClass(); UserCommonClass* srcType = ts->baseClass(); sint32 srcSize = JavaArray::getSize(src); sint32 dstSize = JavaArray::getSize(dst); if (len > srcSize) { th->throwException(vm->CreateIndexOutOfBoundsException(len)); } else if (len > dstSize) { th->throwException(vm->CreateIndexOutOfBoundsException(len)); } else if (len + sstart > srcSize) { th->throwException(vm->CreateIndexOutOfBoundsException(len + sstart)); } else if (len + dstart > dstSize) { th->throwException(vm->CreateIndexOutOfBoundsException(len + dstart)); } else if (dstart < 0) { th->throwException(vm->CreateIndexOutOfBoundsException(dstart)); } else if (sstart < 0) { th->throwException(vm->CreateIndexOutOfBoundsException(sstart)); } else if (len < 0) { th->throwException(vm->CreateIndexOutOfBoundsException(len)); } else if ((dstType->isPrimitive() || srcType->isPrimitive()) && srcType != dstType) { th->throwException(vm->CreateArrayStoreException( (JavaVirtualTable*)dst->getVirtualTable())); } if (!(dstType->isPrimitive())) { // Scan to ensure element compatibility, recording the first item // that requires an exception be thrown. // Unfortunately in the case that an element can't be assigned, // System.arrayCopy is required to do the partial copy, hence this check. int copyLen = len; arraySrc = (ArrayObject*)src; for (int i = 0; i < len; i++) { cur = ArrayObject::getElement(arraySrc, i + sstart); if (cur) { if (!(JavaObject::getClass(cur)->isSubclassOf(dstType))) { copyLen = i; // copy up until this element break; } } } // If same array, then there's a potential for overlap. // Check this now, and use it to determine iteration order. arrayDest = (ArrayObject*)dst; bool backward = (src == dst) && (sstart < dstart) && (sstart + copyLen > dstart); if (backward) { for(int i = copyLen - 1; i >= 0; --i) { cur = ArrayObject::getElement((ArrayObject*)src, i + sstart); ArrayObject::setElement(arrayDest, cur, i + dstart); } } else { for(int i = 0; i < copyLen; ++i) { cur = ArrayObject::getElement(arraySrc, i + sstart); ArrayObject::setElement(arrayDest, cur, i + dstart); } } // TODO: Record the conflicting types in the exception message? if (copyLen != len) vm->arrayStoreException(); } else { uint32 logSize = dstType->asPrimitiveClass()->logSize; void* ptrDst = (void*)((int64_t)JavaArray::getElements(dst) + (dstart << logSize)); void* ptrSrc = (void*)((int64_t)JavaArray::getElements(src) + (sstart << logSize)); memmove(ptrDst, ptrSrc, len << logSize); } }