Use System.arraycopy and Arrays.fill in CobolDataStorage.memcpy/memset - #877
Open
yutaro-sakamoto wants to merge 1 commit into
Open
Conversation
The remaining memcpy/memset overloads copied or filled the backing array one byte at a time through setByte/getByte. Replace those loops with System.arraycopy and Arrays.fill, which are JIT intrinsics and avoid the per-element bounds checks and call overhead. This matches memcpy(byte[], int, int), which already used System.arraycopy. The relative addressing based on this.index is preserved, so sub-fields and OCCURS items behave as before. System.arraycopy throws on a negative length while the per-byte loop silently did nothing, and that difference exposed one path that aborted. stringInit compares WITH POINTER against the destination size in bytes before doubling the offset for national items, so for a PIC N(n) item a pointer between n/2 and n leaves stringOffset past the end of the item and stringAppend computed a negative remaining size. Skip the copy when nothing fits and keep setting the overflow condition, which is what the previous implementation effectively did. Also fix the @PARAM offset of memcpy(byte[], int, int), which describes an offset into the source array, not the destination. Add unit tests for the changed overloads and for the STRING case above.
yutaro-sakamoto
marked this pull request as ready for review
August 5, 2026 12:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#844 への対応。
概要
CobolDataStorageのmemcpy/memsetのうち、setByte/getByteを使って1バイトずつコピー・フィルしていたオーバーロードをSystem.arraycopy/Arrays.fillに置き換えた。これらは JIT のイントリンシックであり、要素ごとの境界チェックとメソッド呼び出しのオーバーヘッドを避けられる。memcpy(byte[], int, int)はすでにSystem.arraycopyを使っており、今回の変更で他のオーバーロードもそれに揃う形になる。対象:
memcpy(byte[] buf, int size)memcpy(int offset, byte[] buf, int size)memcpy(CobolDataStorage buf, int size)memcpy(int offset, CobolDataStorage buf, int size)memset(byte ch, int size)memset(int offset, byte ch, int size)this.indexによる相対アドレッシングはそのまま維持しているため、部分項目やOCCURSの扱いは変わらない。公開APIの変更もない。付随する修正
System.arraycopyは長さが負の場合に例外を投げるが、置き換え前の for ループは何もしないだけだった。この差分によって、日本語項目へのSTRING ... WITH POINTERで異常終了する経路が1つ生じることが分かったため併せて修正した。stringInitはWITH POINTERの値を、日本語項目向けの2倍補正を行う 前 に連結先のバイト数と比較している。そのためPIC N(5)に対して POINTER が 7〜10 の場合、補正後のstringOffsetが連結先のバイト数(10)を超え、stringAppendで残り領域が負になっていた。従来はそのmemcpyが実質 no-op となりオーバーフロー状態になるだけだったが、System.arraycopyではArrayIndexOutOfBoundsExceptionで異常終了する。stringAppendで残り領域が0以下の場合はコピーを行わないようにし、従来と同じ結果(何も連結せずオーバーフロー条件を設定、文字位置は連結先の末尾)になるようにした。また、
memcpy(byte[] buf, int offset, int size)の@param offsetの説明が実装(コピー元buf内のオフセット)と食い違っていたため修正した。テスト
CobolDataStorageTestを新規追加。変更した各オーバーロードについて、相対位置(index)が維持されること、書き込み範囲外が変化しないことを確認する。CobolStringTestを新規追加。上記STRINGの回帰テストを含む(stringAppendのガードが無い状態では失敗することを確認済み)。Addresses #844.
Summary
Several
memcpy/memsetoverloads inCobolDataStoragecopied or filled the backing array one byte at a time throughsetByte/getByte. They now useSystem.arraycopyandArrays.fill, which are JIT intrinsics and avoid the per-element bounds checks and call overhead.memcpy(byte[], int, int)already usedSystem.arraycopy, so the remaining overloads are now consistent with it.Changed overloads:
memcpy(byte[] buf, int size)memcpy(int offset, byte[] buf, int size)memcpy(CobolDataStorage buf, int size)memcpy(int offset, CobolDataStorage buf, int size)memset(byte ch, int size)memset(int offset, byte ch, int size)Relative addressing through
this.indexis preserved, so sub-fields andOCCURSitems behave exactly as before. There is no public API change.Accompanying fix
System.arraycopythrows on a negative length, whereas the previousforloop simply did nothing. That difference exposed one path whereSTRING ... WITH POINTERinto a national item would abort.stringInitcompares theWITH POINTERvalue against the destination size in bytes before doubling the offset for national items. For aPIC N(5)item and a pointer of 7 through 10, the doubledstringOffsetends up past the item's 10 bytes, sostringAppendcomputed a negative remaining size. Previously thatmemcpywas effectively a no-op and the statement just raised the overflow condition; withSystem.arraycopyit aborted withArrayIndexOutOfBoundsException.stringAppendnow skips the copy when nothing fits, which reproduces the previous outcome: nothing is appended, the overflow condition is set, and the pointer ends at the end of the destination.The
@param offsetofmemcpy(byte[] buf, int offset, int size)also described the destination, while the implementation uses it as an offset into the source array; the Javadoc is corrected.Tests
CobolDataStorageTestcovering each changed overload: relative addressing viaindexis preserved and bytes outside the written range are untouched.CobolStringTest, including a regression test for theSTRINGcase above (verified to fail without thestringAppendguard).このPRの内容は yutaro-sakamoto#33 と同一です(ベースブランチのみ異なります)。
The contents of this pull request are identical to yutaro-sakamoto#33; only the base branch differs.