void ObjArray::array_copy(ObjArray* src, jint src_pos, ObjArray* dst, jint dst_pos, jint length JVM_TRAPS) { // Special case. Boundary cases must be checked first // This allows the following call: copy_array(s, s.length(), // d.length(), 0). This is correct, since the position is supposed // to be an 'in between point', i.e., s.length(), points to the // right of the last element. if (length == 0) { return; } OopDesc** src_start = (OopDesc**) src->field_base(base_offset() + src_pos * oopSize); OopDesc** dst_start = (OopDesc**) dst->field_base(base_offset() + dst_pos * oopSize); if (src->equals(dst)) { // since source and destination are equal we do not need conversion checks. jvm_memmove(dst_start, src_start, length * oopSize); oop_write_barrier_range(dst_start, length); } else { // We have to make sure all elements conform to the destination array ObjArrayClass::Raw dst_class = dst->blueprint(); ObjArrayClass::Raw src_class = src->blueprint(); JavaClass::Raw bound = dst_class().element_class(); JavaClass::Raw stype = src_class().element_class(); if (stype.equals(&bound) || stype().is_subtype_of(&bound)) { // elements are guaranteed to be subtypes, so no check necessary jvm_memmove(dst_start, src_start, length * oopSize); oop_write_barrier_range(dst_start, length); return; } // Slow case: need individual subtype checks // Do store checks first so they're guaranteed to be done even if // an exception is thrown obj_at_put contains a write barrier already Oop::Raw element; JavaClass::Raw element_class; for (int index =0; index < length; index++) { element = src->obj_at( src_pos + index); if (element.is_null()) { dst->obj_at_put(dst_pos + index, &element); } else { element_class = element.blueprint(); if (element_class().is_subtype_of(&bound)) { dst->obj_at_put(dst_pos + index, &element); } else { Throw::array_store_exception(subtype_check_failed JVM_THROW); } } } } }
void CompiledMethod::shrink(jint code_size, jint relocation_size) { // The current implementation copies the relocation information down // and "shrinks" the compiled method object in place, allocating a // dummy filler object in the now unused end part. // // The compiled method object will generally not be the last object in // the heap, since the compiler allocates other objects and GC might // have occurred. However, if the GC always does sliding compaction // and the compiler *guarantees* not to hold on to any allocated // object other than the compiled method, we could simply move the // top of the object heap down! // Copy the relocation segment down void* src = field_base(end_offset() - relocation_size); void* dst = field_base(base_offset() + code_size); GUARANTEE(src >= dst, "should be copying down"); jvm_memmove(dst, src, relocation_size); // possibly overlapping regions // Shrink compiled method object size_t new_size = CompiledMethodDesc::allocation_size(code_size + relocation_size); Universe::shrink_object(this, new_size); ((CompiledMethodDesc*) obj())->set_size(code_size + relocation_size); GUARANTEE(object_size() == new_size, "invalid shrunk size"); }
bool CompiledMethod::expand_compiled_code_space(int delta, int relocation_size) { if (ObjectHeap::expand_current_compiled_method(delta)) { if (Verbose) { TTY_TRACE_CR(("Expanding compiled method from %d to %d bytes", size(), size() + delta)); } void* src = field_base(end_offset() - relocation_size); void* dst = DERIVED(void*, src, delta); GUARANTEE(src < dst, "should be copying up"); jvm_memmove(dst, src, relocation_size); // possibly overlapping regions // It's probably OK only to clear dst[-1], but let's just make sure. jvm_memset(src, 0, delta); ((CompiledMethodDesc*) obj())->set_size(size() + delta); if (VerifyGC > 2) { ObjectHeap::verify(); } return true; } else { return false;
bool JarFileParser::find_end_of_central_header() { DECLARE_STATIC_BUFFER(unsigned char, buffer, TMPBUFFERSIZE); BufferedFile::Raw bf = buffered_file(); /* Get the length of the file */ const jint length = (int) bf().file_size(); /* Calculate the smallest possible offset for the end header. It * can be at most 0xFFFF + ENDHDRSIZ bytes from the end of the file, but * the file must also have a local header and a central header */ jint minOffset = length - (0xFFFF + ENDHDRSIZ); if (minOffset < LOCHDRSIZ + CENHDRSIZ) { minOffset = LOCHDRSIZ + CENHDRSIZ; } /* We assume that "buffer" contains the contents * of part of the file. currentOffset contains the offset of buffer[0]. */ /* Read in the last ENDHDRSIZ bytes into the buffer. 99% of the time, * the file won't have a comment, and this is the only read we'll need */ if ( (bf().seek(-ENDHDRSIZ, SEEK_END) < 0) || (bf().get_bytes(buffer, ENDHDRSIZ) != ENDHDRSIZ)) { return false; } /* Set currentOffset to be the offset of buffer[0] */ jint currentOffset = length - ENDHDRSIZ; /* Set bp to be the location at which to start looking */ unsigned const char* bp = buffer; for (;;) { /* "buffer" contains a block of data from the file, starting at * currentOffset "position" in the file. * We investigate whether currentOffset + (bp - buffer) is the start * of the end header in the zip file. * * We use a simplified version of Knuth-Morris-Pratt search algorithm. * The header we're looking for is 'P' 'K' 5 6 */ switch(bp[0]) { case '\006': /* The header must start at least 3 bytes back */ bp -= 3; break; case '\005': /* The header must start at least 2 bytes back */ bp -= 2; break; case 'K': /* The header must start at least 1 byte back */ bp -= 1; break; case 'P': /* Either this is the header, or the header must * start at least 4 back */ if (bp[1] == 'K' && bp[2] == 5 && bp[3] == 6) { /* We have what may be a header. Let's make sure the * implied length of the jar file matches the actual * length. */ int endpos = (int) currentOffset + (bp - buffer); if (endpos + ENDHDRSIZ + ENDCOM(bp) == length) { juint cenOffset = endpos - ENDSIZ(bp); juint locOffset = cenOffset - ENDOFF(bp); unsigned char sig[4]; if (bf().seek(locOffset, SEEK_SET) >= 0 && bf().get_bytes(sig, 4) == 4 && sig[0] == (unsigned char)'P' && sig[1] == (unsigned char)'K' && sig[2] == (unsigned char) 3 && sig[3] == (unsigned char) 4) { raw_current_entry()->cenOffset = cenOffset; raw_current_entry()->nextCenOffset = cenOffset; raw_current_entry()->locOffset = locOffset; #if ENABLE_ROM_GENERATOR raw_current_entry()->totalEntryCount = ENDTOT(bp); #endif } return true; // Found central header } } /* FALL THROUGH */ default: /* The header must start at least four characters back, since * the current character isn't in the header */ bp -= 4; } if (bp < buffer) { /* We've moved outside our window into the file. We must * move the window backwards */ size_t count = (size_t) (currentOffset - minOffset); /* Bytes left in file */ if (((jint)count) <= 0) { /* Nothing left to read. Time to give up */ return false; } else { /* up to ((bp - buffer) + ENDHDRSIZ) bytes in the buffer might * still be part of the end header, so the most bytes we can * actually read are * TMPBUFFERSIZE - ((bp - buffer) + ENDHDRSIZE). */ size_t available = (TMPBUFFERSIZE - ENDHDRSIZ) + (buffer - bp); if (count > available) { count = available; } } /* Back up, while keeping our virtual currentOffset the same */ currentOffset -= count; bp += count; jvm_memmove(buffer + count, buffer, TMPBUFFERSIZE - count); if ( bf().seek(currentOffset, SEEK_SET) < 0 || bf().get_bytes(buffer, count) != size_t(count) ) { return false; } } } /* end of for loop */ }
KNIEXPORT void KNI_SetRawArrayRegion(jarray arrayHandle, jsize offset, jsize n, const jbyte* srcBuffer) { address ta_start = _KNI_GetRawArrayRegion_start_address(arrayHandle, offset); (void)jvm_memmove(ta_start, srcBuffer, n); }
KNIEXPORT void KNI_GetRawArrayRegion(jarray arrayHandle, jsize offset, jsize n, jbyte* dstBuffer) { address ta_start = _KNI_GetRawArrayRegion_start_address(arrayHandle, offset); (void)jvm_memmove(dstBuffer, ta_start, n); }