From 336bbbe3895214a772e0f3aafb36277c46645ded Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Fri, 23 Feb 2024 10:05:25 +0000 Subject: [PATCH] 8139457: Relax alignment of array elements Co-authored-by: Fei Yang Co-authored-by: Thomas Stuefe Reviewed-by: stuefe, stefank, shade, coleenp, kdnilsen, aboldtch --- .../cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 2 +- .../cpu/aarch64/c1_MacroAssembler_aarch64.cpp | 15 ++- .../cpu/aarch64/c1_MacroAssembler_aarch64.hpp | 4 +- src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp | 2 +- src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp | 4 +- src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp | 20 +++- src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp | 4 +- .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 4 +- .../cpu/riscv/c1_MacroAssembler_riscv.cpp | 19 ++- .../cpu/riscv/c1_MacroAssembler_riscv.hpp | 4 +- src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp | 2 +- .../cpu/s390/c1_MacroAssembler_s390.cpp | 12 +- .../cpu/s390/c1_MacroAssembler_s390.hpp | 4 +- src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp | 4 +- src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 18 ++- src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp | 4 +- src/hotspot/share/gc/shared/collectedHeap.cpp | 13 +- src/hotspot/share/gc/x/xObjArrayAllocator.cpp | 14 ++- src/hotspot/share/gc/z/zObjArrayAllocator.cpp | 12 +- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 2 +- src/hotspot/share/oops/arrayOop.hpp | 65 +++++----- src/hotspot/share/oops/objArrayOop.hpp | 39 +----- src/hotspot/share/opto/runtime.cpp | 15 ++- src/hotspot/share/opto/type.cpp | 9 +- src/hotspot/share/prims/unsafe.cpp | 4 +- .../sun/jvm/hotspot/memory/Universe.java | 9 +- .../classes/sun/jvm/hotspot/oops/Array.java | 39 +++--- test/hotspot/gtest/oops/test_arrayOop.cpp | 56 +++++++-- test/hotspot/gtest/oops/test_objArrayOop.cpp | 57 +++++++++ test/hotspot/jtreg/gtest/ArrayTests.java | 56 +++++++++ test/hotspot/jtreg/gtest/ObjArrayTests.java | 85 +++++++++++++ .../runtime/FieldLayout/ArrayBaseOffsets.java | 113 ++++++++++++++++++ .../GetObjectSizeIntrinsicsTest.java | 21 ++-- 33 files changed, 560 insertions(+), 171 deletions(-) create mode 100644 test/hotspot/gtest/oops/test_objArrayOop.cpp create mode 100644 test/hotspot/jtreg/gtest/ArrayTests.java create mode 100644 test/hotspot/jtreg/gtest/ObjArrayTests.java create mode 100644 test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index ba613b62a3e..9bd8c6b8e9f 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -1209,7 +1209,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { len, tmp1, tmp2, - arrayOopDesc::header_size(op->type()), + arrayOopDesc::base_offset_in_bytes(op->type()), array_element_size(op->type()), op->klass()->as_register(), *op->stub()->entry()); diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp index 50d35f281e5..e48d64d9069 100644 --- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp @@ -188,6 +188,12 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register if (len->is_valid()) { strw(len, Address(obj, arrayOopDesc::length_offset_in_bytes())); + int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt; + if (!is_aligned(base_offset, BytesPerWord)) { + assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned"); + // Clear gap/first 4 bytes following the length field. + strw(zr, Address(obj, base_offset)); + } } else if (UseCompressedClassPointers) { store_klass_gap(obj, zr); } @@ -266,7 +272,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register verify_oop(obj); } -void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int header_size, int f, Register klass, Label& slow_case) { +void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int base_offset_in_bytes, int f, Register klass, Label& slow_case) { assert_different_registers(obj, len, t1, t2, klass); // determine alignment mask @@ -279,7 +285,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, const Register arr_size = t2; // okay to be the same // align object end - mov(arr_size, (int32_t)header_size * BytesPerWord + MinObjAlignmentInBytesMask); + mov(arr_size, (int32_t)base_offset_in_bytes + MinObjAlignmentInBytesMask); add(arr_size, arr_size, len, ext::uxtw, f); andr(arr_size, arr_size, ~MinObjAlignmentInBytesMask); @@ -287,8 +293,11 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, initialize_header(obj, klass, len, t1, t2); + // Align-up to word boundary, because we clear the 4 bytes potentially + // following the length field in initialize_header(). + int base_offset = align_up(base_offset_in_bytes, BytesPerWord); // clear rest of allocated space - initialize_body(obj, arr_size, header_size * BytesPerWord, t1, t2); + initialize_body(obj, arr_size, base_offset, t1, t2); if (Compilation::current()->bailed_out()) { return; } diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp index 4aa6206aa60..d210c21d12b 100644 --- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -100,7 +100,7 @@ using MacroAssembler::null_check; // header_size: size of object header in words // f : element scale factor // slow_case : exit to slow case implementation if fast allocation fails - void allocate_array(Register obj, Register len, Register t, Register t2, int header_size, int f, Register klass, Label& slow_case); + void allocate_array(Register obj, Register len, Register t, Register t2, int base_offset_in_bytes, int f, Register klass, Label& slow_case); int rsp_offset() const { return _rsp_offset; } void set_rsp_offset(int n) { _rsp_offset = n; } diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp index 16aeaa20c04..688790f07e5 100644 --- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp @@ -968,7 +968,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { op->tmp1()->as_register(), op->tmp2()->as_register(), op->tmp3()->as_register(), - arrayOopDesc::header_size(op->type()), + arrayOopDesc::base_offset_in_bytes(op->type()), type2aelembytes(op->type()), op->klass()->as_register(), *op->stub()->entry()); diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index 4b29bcf57e4..3ae35949b21 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2023 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -2298,7 +2298,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { op->tmp1()->as_register(), op->tmp2()->as_register(), op->tmp3()->as_register(), - arrayOopDesc::header_size(op->type()), + arrayOopDesc::base_offset_in_bytes(op->type()), type2aelembytes(op->type()), op->klass()->as_register(), *op->stub()->entry()); diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index b379d4141a3..ba0187d0363 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -310,7 +310,7 @@ void C1_MacroAssembler::allocate_array( Register t1, // temp register Register t2, // temp register Register t3, // temp register - int hdr_size, // object header size in words + int base_offset_in_bytes, // elements offset in bytes int elt_size, // element size in bytes Register klass, // object klass Label& slow_case // continuation point if fast allocation fails @@ -342,7 +342,7 @@ void C1_MacroAssembler::allocate_array( sldi(t1, len, log2_elt_size); arr_len_in_bytes = t1; } - addi(arr_size, arr_len_in_bytes, hdr_size * wordSize + MinObjAlignmentInBytesMask); // Add space for header & alignment. + addi(arr_size, arr_len_in_bytes, base_offset_in_bytes + MinObjAlignmentInBytesMask); // Add space for header & alignment. clrrdi(arr_size, arr_size, LogMinObjAlignmentInBytes); // Align array size. // Allocate space & initialize header. @@ -352,8 +352,18 @@ void C1_MacroAssembler::allocate_array( // Initialize body. const Register base = t2; const Register index = t3; - addi(base, obj, hdr_size * wordSize); // compute address of first element - addi(index, arr_size, -(hdr_size * wordSize)); // compute index = number of bytes to clear + addi(base, obj, base_offset_in_bytes); // compute address of first element + addi(index, arr_size, -(base_offset_in_bytes)); // compute index = number of bytes to clear + + // Zero first 4 bytes, if start offset is not word aligned. + if (!is_aligned(base_offset_in_bytes, BytesPerWord)) { + assert(is_aligned(base_offset_in_bytes, BytesPerInt), "must be 4-byte aligned"); + li(t1, 0); + stw(t1, 0, base); + addi(base, base, BytesPerInt); + // Note: initialize_body will align index down, no need to correct it here. + } + initialize_body(base, index); if (CURRENT_ENV->dtrace_alloc_probes()) { diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp index 5fa19d5fd5d..ab31431e67d 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -80,7 +80,7 @@ Register t1, // temp register Register t2, // temp register Register t3, // temp register - int hdr_size, // object header size in words + int base_offset_in_bytes, // elements offset in bytes int elt_size, // element size in bytes Register klass, // object klass Label& slow_case // continuation point if fast allocation fails diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index e3ec023aef2..5d0fa3fad3c 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -1020,7 +1020,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { len, tmp1, tmp2, - arrayOopDesc::header_size(op->type()), + arrayOopDesc::base_offset_in_bytes(op->type()), array_element_size(op->type()), op->klass()->as_register(), *op->stub()->entry()); diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp index 2961b1a91ce..770dd6a9d0f 100644 --- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -280,7 +280,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register verify_oop(obj); } -void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int header_size, int f, Register klass, Label& slow_case) { +void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int base_offset_in_bytes, int f, Register klass, Label& slow_case) { assert_different_registers(obj, len, tmp1, tmp2, klass); // determine alignment mask @@ -292,7 +292,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1 const Register arr_size = tmp2; // okay to be the same // align object end - mv(arr_size, (int32_t)header_size * BytesPerWord + MinObjAlignmentInBytesMask); + mv(arr_size, (int32_t)base_offset_in_bytes + MinObjAlignmentInBytesMask); shadd(arr_size, len, arr_size, t0, f); andi(arr_size, arr_size, ~(uint)MinObjAlignmentInBytesMask); @@ -300,9 +300,20 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1 initialize_header(obj, klass, len, tmp1, tmp2); + // Clear leading 4 bytes, if necessary. + // TODO: This could perhaps go into initialize_body() and also clear the leading 4 bytes + // for non-array objects, thereby replacing the klass-gap clearing code in initialize_header(). + int base_offset = base_offset_in_bytes; + if (!is_aligned(base_offset, BytesPerWord)) { + assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned"); + sw(zr, Address(obj, base_offset)); + base_offset += BytesPerInt; + } + assert(is_aligned(base_offset, BytesPerWord), "must be word-aligned"); + // clear rest of allocated space const Register len_zero = len; - initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero); + initialize_body(obj, arr_size, base_offset, len_zero); membar(MacroAssembler::StoreStore); diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp index b737a438511..2d7f8d7485d 100644 --- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -101,7 +101,7 @@ using MacroAssembler::null_check; // header_size: size of object header in words // f : element scale factor // slow_case : exit to slow case implementation if fast allocation fails - void allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int header_size, int f, Register klass, Label& slow_case); + void allocate_array(Register obj, Register len, Register tmp1, Register tmp2, int base_offset_in_bytes, int f, Register klass, Label& slow_case); int rsp_offset() const { return _rsp_offset; } diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index 13c45bb9fe7..503440a5fcc 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp @@ -2382,7 +2382,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { op->len()->as_register(), op->tmp1()->as_register(), op->tmp2()->as_register(), - arrayOopDesc::header_size(op->type()), + arrayOopDesc::base_offset_in_bytes(op->type()), type2aelembytes(op->type()), op->klass()->as_register(), *op->stub()->entry()); diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp index 5dddc7a756f..58bdcee5d5f 100644 --- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2023 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -271,7 +271,7 @@ void C1_MacroAssembler::allocate_array( Register len, // array length Register t1, // temp register Register t2, // temp register - int hdr_size, // object header size in words + int base_offset_in_bytes, // elements offset in bytes int elt_size, // element size in bytes Register klass, // object klass Label& slow_case // Continuation point if fast allocation fails. @@ -297,8 +297,8 @@ void C1_MacroAssembler::allocate_array( case 8: z_sllg(arr_size, len, 3); break; default: ShouldNotReachHere(); } - add2reg(arr_size, hdr_size * wordSize + MinObjAlignmentInBytesMask); // Add space for header & alignment. - z_nill(arr_size, (~MinObjAlignmentInBytesMask) & 0xffff); // Align array size. + add2reg(arr_size, base_offset_in_bytes + MinObjAlignmentInBytesMask); // Add space for header & alignment. + z_nill(arr_size, (~MinObjAlignmentInBytesMask) & 0xffff); // Align array size. try_allocate(obj, arr_size, 0, t1, slow_case); @@ -308,9 +308,9 @@ void C1_MacroAssembler::allocate_array( Label done; Register object_fields = t1; Register Rzero = Z_R1_scratch; - z_aghi(arr_size, -(hdr_size * BytesPerWord)); + z_aghi(arr_size, -base_offset_in_bytes); z_bre(done); // Jump if size of fields is zero. - z_la(object_fields, hdr_size * BytesPerWord, obj); + z_la(object_fields, base_offset_in_bytes, obj); z_xgr(Rzero, Rzero); initialize_body(object_fields, arr_size, Rzero); bind(done); diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp index 7a4f76af154..c77258509e1 100644 --- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2023 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -86,7 +86,7 @@ Register len, // array length Register t1, // temp register Register t2, // temp register - int hdr_size, // object header size in words + int base_offset_in_bytes, // elements offset in bytes int elt_size, // element size in bytes Register klass, // object klass Label& slow_case // Continuation point if fast allocation fails. diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index 3b7a3cec2d8..c279e3073af 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1618,7 +1618,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { len, tmp1, tmp2, - arrayOopDesc::header_size(op->type()), + arrayOopDesc::base_offset_in_bytes(op->type()), array_element_size(op->type()), op->klass()->as_register(), *op->stub()->entry()); diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp index 0c4544f5bc4..caca3a15282 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp @@ -186,6 +186,15 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register if (len->is_valid()) { movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len); +#ifdef _LP64 + int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt; + if (!is_aligned(base_offset, BytesPerWord)) { + assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned"); + // Clear gap/first 4 bytes following the length field. + xorl(t1, t1); + movl(Address(obj, base_offset), t1); + } +#endif } #ifdef _LP64 else if (UseCompressedClassPointers) { @@ -269,7 +278,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register verify_oop(obj); } -void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int header_size, Address::ScaleFactor f, Register klass, Label& slow_case) { +void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int base_offset_in_bytes, Address::ScaleFactor f, Register klass, Label& slow_case) { assert(obj == rax, "obj must be in rax, for cmpxchg"); assert_different_registers(obj, len, t1, t2, klass); @@ -282,7 +291,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, const Register arr_size = t2; // okay to be the same // align object end - movptr(arr_size, header_size * BytesPerWord + MinObjAlignmentInBytesMask); + movptr(arr_size, base_offset_in_bytes + MinObjAlignmentInBytesMask); lea(arr_size, Address(arr_size, len, f)); andptr(arr_size, ~MinObjAlignmentInBytesMask); @@ -292,7 +301,10 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, // clear rest of allocated space const Register len_zero = len; - initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero); + // Align-up to word boundary, because we clear the 4 bytes potentially + // following the length field in initialize_header(). + int base_offset = align_up(base_offset_in_bytes, BytesPerWord); + initialize_body(obj, arr_size, base_offset, len_zero); if (CURRENT_ENV->dtrace_alloc_probes()) { assert(obj == rax, "must be"); diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp index b3593feb056..ae340e64fb7 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,7 @@ // header_size: size of object header in words // f : element scale factor // slow_case : exit to slow case implementation if fast allocation fails - void allocate_array(Register obj, Register len, Register t, Register t2, int header_size, Address::ScaleFactor f, Register klass, Label& slow_case); + void allocate_array(Register obj, Register len, Register t, Register t2, int base_offset_in_bytes, Address::ScaleFactor f, Register klass, Label& slow_case); int rsp_offset() const { return _rsp_offset; } void set_rsp_offset(int n) { _rsp_offset = n; } diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index dbcef1ba575..02d20b92b5c 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -402,6 +402,13 @@ void CollectedHeap::set_gc_cause(GCCause::Cause v) { _gc_cause = v; } +// Returns the header size in words aligned to the requirements of the +// array object type. +static int int_array_header_size() { + size_t typesize_in_bytes = arrayOopDesc::header_size_in_bytes(); + return (int)align_up(typesize_in_bytes, HeapWordSize)/HeapWordSize; +} + size_t CollectedHeap::max_tlab_size() const { // TLABs can't be bigger than we can fill with a int[Integer.MAX_VALUE]. // This restriction could be removed by enabling filling with multiple arrays. @@ -411,14 +418,14 @@ size_t CollectedHeap::max_tlab_size() const { // We actually lose a little by dividing first, // but that just makes the TLAB somewhat smaller than the biggest array, // which is fine, since we'll be able to fill that. - size_t max_int_size = typeArrayOopDesc::header_size(T_INT) + + size_t max_int_size = int_array_header_size() + sizeof(jint) * ((juint) max_jint / (size_t) HeapWordSize); return align_down(max_int_size, MinObjAlignment); } size_t CollectedHeap::filler_array_hdr_size() { - return align_object_offset(arrayOopDesc::header_size(T_INT)); // align to Long + return align_object_offset(int_array_header_size()); // align to Long } size_t CollectedHeap::filler_array_min_size() { diff --git a/src/hotspot/share/gc/x/xObjArrayAllocator.cpp b/src/hotspot/share/gc/x/xObjArrayAllocator.cpp index 9408e027cbd..0950b886a9b 100644 --- a/src/hotspot/share/gc/x/xObjArrayAllocator.cpp +++ b/src/hotspot/share/gc/x/xObjArrayAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,17 @@ oop XObjArrayAllocator::initialize(HeapWord* mem) const { // time and time-to-safepoint const size_t segment_max = XUtils::bytes_to_words(64 * K); const BasicType element_type = ArrayKlass::cast(_klass)->element_type(); - const size_t header = arrayOopDesc::header_size(element_type); + + // Clear leading 32 bits, if necessary. + int base_offset = arrayOopDesc::base_offset_in_bytes(element_type); + if (!is_aligned(base_offset, HeapWordSize)) { + assert(is_aligned(base_offset, BytesPerInt), "array base must be 32 bit aligned"); + *reinterpret_cast(reinterpret_cast(mem) + base_offset) = 0; + base_offset += BytesPerInt; + } + assert(is_aligned(base_offset, HeapWordSize), "remaining array base must be 64 bit aligned"); + + const size_t header = heap_word_size(base_offset); const size_t payload_size = _word_size - header; if (payload_size <= segment_max) { diff --git a/src/hotspot/share/gc/z/zObjArrayAllocator.cpp b/src/hotspot/share/gc/z/zObjArrayAllocator.cpp index faa1290f37e..b5aaed3a274 100644 --- a/src/hotspot/share/gc/z/zObjArrayAllocator.cpp +++ b/src/hotspot/share/gc/z/zObjArrayAllocator.cpp @@ -50,7 +50,17 @@ oop ZObjArrayAllocator::initialize(HeapWord* mem) const { // time and time-to-safepoint const size_t segment_max = ZUtils::bytes_to_words(64 * K); const BasicType element_type = ArrayKlass::cast(_klass)->element_type(); - const size_t header = arrayOopDesc::header_size(element_type); + + // Clear leading 32 bits, if necessary. + int base_offset = arrayOopDesc::base_offset_in_bytes(element_type); + if (!is_aligned(base_offset, HeapWordSize)) { + assert(is_aligned(base_offset, BytesPerInt), "array base must be 32 bit aligned"); + *reinterpret_cast(reinterpret_cast(mem) + base_offset) = 0; + base_offset += BytesPerInt; + } + assert(is_aligned(base_offset, HeapWordSize), "remaining array base must be 64 bit aligned"); + + const size_t header = heap_word_size(base_offset); const size_t payload_size = _word_size - header; if (payload_size <= segment_max) { diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index ca375073313..efc47def021 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2442,7 +2442,7 @@ C2V_END C2V_VMENTRY_0(jint, arrayBaseOffset, (JNIEnv* env, jobject, jchar type_char)) BasicType type = JVMCIENV->typeCharToBasicType(type_char, JVMCI_CHECK_0); - return arrayOopDesc::header_size(type) * HeapWordSize; + return arrayOopDesc::base_offset_in_bytes(type); C2V_END C2V_VMENTRY_0(jint, arrayIndexScale, (JNIEnv* env, jobject, jchar type_char)) diff --git a/src/hotspot/share/oops/arrayOop.hpp b/src/hotspot/share/oops/arrayOop.hpp index a557268fe77..0aa26500bd8 100644 --- a/src/hotspot/share/oops/arrayOop.hpp +++ b/src/hotspot/share/oops/arrayOop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "oops/oop.hpp" #include "utilities/align.hpp" +#include "utilities/globalDefinitions.hpp" // arrayOopDesc is the abstract baseclass for all arrays. It doesn't // declare pure virtual to enforce this because that would allocate a vtbl @@ -45,13 +46,29 @@ class arrayOopDesc : public oopDesc { // Interpreter/Compiler offsets +private: + // Returns the address of the length "field". See length_offset_in_bytes(). + static int* length_addr_impl(void* obj_ptr) { + char* ptr = static_cast(obj_ptr); + return reinterpret_cast(ptr + length_offset_in_bytes()); + } + + // Given a type, return true if elements of that type must be aligned to 64-bit. + static bool element_type_should_be_aligned(BasicType type) { +#ifdef _LP64 + if (type == T_OBJECT || type == T_ARRAY) { + return !UseCompressedOops; + } +#endif + return type == T_DOUBLE || type == T_LONG; + } + + public: // Header size computation. // The header is considered the oop part of this type plus the length. - // Returns the aligned header_size_in_bytes. This is not equivalent to - // sizeof(arrayOopDesc) which should not appear in the code. + // This is not equivalent to sizeof(arrayOopDesc) which should not appear in the code. static int header_size_in_bytes() { - size_t hs = align_up(length_offset_in_bytes() + sizeof(int), - HeapWordSize); + size_t hs = length_offset_in_bytes() + sizeof(int); #ifdef ASSERT // make sure it isn't called before UseCompressedOops is initialized. static size_t arrayoopdesc_hs = 0; @@ -61,20 +78,6 @@ class arrayOopDesc : public oopDesc { return (int)hs; } - // Returns the address of the length "field". See length_offset_in_bytes(). - static int* length_addr_impl(void* obj_ptr) { - char* ptr = static_cast(obj_ptr); - return reinterpret_cast(ptr + length_offset_in_bytes()); - } - - // Check whether an element of a typeArrayOop with the given type must be - // aligned 0 mod 8. The typeArrayOop itself must be aligned at least this - // strongly. - static bool element_type_should_be_aligned(BasicType type) { - return type == T_DOUBLE || type == T_LONG; - } - - public: // The _length field is not declared in C++. It is allocated after the // declared nonstatic fields in arrayOopDesc if not compressed, otherwise // it occupies the second half of the _klass field in oopDesc. @@ -85,7 +88,8 @@ class arrayOopDesc : public oopDesc { // Returns the offset of the first element. static int base_offset_in_bytes(BasicType type) { - return header_size(type) * HeapWordSize; + size_t hs = header_size_in_bytes(); + return (int)(element_type_should_be_aligned(type) ? align_up(hs, BytesPerLong) : hs); } // Returns the address of the first element. The elements in the array will not @@ -122,18 +126,7 @@ class arrayOopDesc : public oopDesc { *length_addr_impl(mem) = length; } - // Should only be called with constants as argument - // (will not constant fold otherwise) - // Returns the header size in words aligned to the requirements of the - // array object type. - static int header_size(BasicType type) { - size_t typesize_in_bytes = header_size_in_bytes(); - return (int)(element_type_should_be_aligned(type) - ? align_object_offset(typesize_in_bytes/HeapWordSize) - : typesize_in_bytes/HeapWordSize); - } - - // Return the maximum length of an array of BasicType. The length can passed + // Return the maximum length of an array of BasicType. The length can be passed // to typeArrayOop::object_size(scale, length, header_size) without causing an // overflow. We also need to make sure that this will not overflow a size_t on // 32 bit platforms when we convert it to a byte size. @@ -141,8 +134,12 @@ class arrayOopDesc : public oopDesc { assert(type < T_CONFLICT, "wrong type"); assert(type2aelembytes(type) != 0, "wrong type"); + size_t hdr_size_in_bytes = base_offset_in_bytes(type); + // This is rounded-up and may overlap with the first array elements. + size_t hdr_size_in_words = align_up(hdr_size_in_bytes, HeapWordSize) / HeapWordSize; + const size_t max_element_words_per_size_t = - align_down((SIZE_MAX/HeapWordSize - header_size(type)), MinObjAlignment); + align_down((SIZE_MAX/HeapWordSize - hdr_size_in_words), MinObjAlignment); const size_t max_elements_per_size_t = HeapWordSize * max_element_words_per_size_t / type2aelembytes(type); if ((size_t)max_jint < max_elements_per_size_t) { @@ -150,7 +147,7 @@ class arrayOopDesc : public oopDesc { // (CollectedHeap, Klass::oop_oop_iterate(), and more) uses an int for // passing around the size (in words) of an object. So, we need to avoid // overflowing an int when we add the header. See CRs 4718400 and 7110613. - return align_down(max_jint - header_size(type), MinObjAlignment); + return align_down(max_jint - hdr_size_in_words, MinObjAlignment); } return (int32_t)max_elements_per_size_t; } diff --git a/src/hotspot/share/oops/objArrayOop.hpp b/src/hotspot/share/oops/objArrayOop.hpp index de6d4d3d042..20e2953fee9 100644 --- a/src/hotspot/share/oops/objArrayOop.hpp +++ b/src/hotspot/share/oops/objArrayOop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,32 +51,6 @@ class objArrayOopDesc : public arrayOopDesc { return base_offset_in_bytes() + sizeof(T) * index; } -private: - // Give size of objArrayOop in HeapWords minus the header - static int array_size(int length) { - const uint OopsPerHeapWord = HeapWordSize/heapOopSize; - assert(OopsPerHeapWord >= 1 && (HeapWordSize % heapOopSize == 0), - "Else the following (new) computation would be in error"); - uint res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord; -#ifdef ASSERT - // The old code is left in for sanity-checking; it'll - // go away pretty soon. XXX - // Without UseCompressedOops, this is simply: - // oop->length() * HeapWordsPerOop; - // With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer. - // The oop elements are aligned up to wordSize - const uint HeapWordsPerOop = heapOopSize/HeapWordSize; - uint old_res; - if (HeapWordsPerOop > 0) { - old_res = length * HeapWordsPerOop; - } else { - old_res = align_up((uint)length, OopsPerHeapWord)/OopsPerHeapWord; - } - assert(res == old_res, "Inconsistency between old and new."); -#endif // ASSERT - return res; - } - public: // Returns the offset of the first element. static int base_offset_in_bytes() { @@ -94,16 +68,15 @@ private: oop replace_if_null(int index, oop exchange_value); // Sizing - static int header_size() { return arrayOopDesc::header_size(T_OBJECT); } size_t object_size() { return object_size(length()); } static size_t object_size(int length) { // This returns the object size in HeapWords. - uint asz = array_size(length); - uint osz = align_object_size(header_size() + asz); - assert(osz >= asz, "no overflow"); - assert((int)osz > 0, "no overflow"); - return (size_t)osz; + size_t asz = (size_t)length * heapOopSize; + size_t size_words = heap_word_size(base_offset_in_bytes() + asz); + size_t osz = align_object_size(size_words); + assert(osz < max_jint, "no overflow"); + return osz; } Klass* element_klass(); diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index c5f22e8ebbb..65e99edba97 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -319,14 +319,17 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len // Zero array here if the caller is deoptimized. const size_t size = TypeArrayKlass::cast(array_type)->oop_size(result); BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type(); - const size_t hs = arrayOopDesc::header_size(elem_type); - // Align to next 8 bytes to avoid trashing arrays's length. - const size_t aligned_hs = align_object_offset(hs); + size_t hs_bytes = arrayOopDesc::base_offset_in_bytes(elem_type); + assert(is_aligned(hs_bytes, BytesPerInt), "must be 4 byte aligned"); HeapWord* obj = cast_from_oop(result); - if (aligned_hs > hs) { - Copy::zero_to_words(obj+hs, aligned_hs-hs); + if (!is_aligned(hs_bytes, BytesPerLong)) { + *reinterpret_cast(reinterpret_cast(obj) + hs_bytes) = 0; + hs_bytes += BytesPerInt; } + // Optimized zeroing. + assert(is_aligned(hs_bytes, BytesPerLong), "must be 8-byte aligned"); + const size_t aligned_hs = hs_bytes / BytesPerLong; Copy::fill_to_aligned_words(obj+aligned_hs, size-aligned_hs); } diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 84d092f2ffd..b042e79309e 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -5169,18 +5169,17 @@ void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const { } if( _offset != 0 ) { - int header_size = objArrayOopDesc::header_size() * wordSize; + BasicType basic_elem_type = elem()->basic_type(); + int header_size = arrayOopDesc::base_offset_in_bytes(basic_elem_type); if( _offset == OffsetTop ) st->print("+undefined"); else if( _offset == OffsetBot ) st->print("+any"); else if( _offset < header_size ) st->print("+%d", _offset); else { - BasicType basic_elem_type = elem()->basic_type(); if (basic_elem_type == T_ILLEGAL) { st->print("+any"); } else { - int array_base = arrayOopDesc::base_offset_in_bytes(basic_elem_type); int elem_size = type2aelembytes(basic_elem_type); - st->print("[%d]", (_offset - array_base)/elem_size); + st->print("[%d]", (_offset - header_size)/elem_size); } } } diff --git a/src/hotspot/share/prims/unsafe.cpp b/src/hotspot/share/prims/unsafe.cpp index 1a05c0fa13e..9540c98f6e0 100644 --- a/src/hotspot/share/prims/unsafe.cpp +++ b/src/hotspot/share/prims/unsafe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,7 @@ #define MAX_OBJECT_SIZE \ - ( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \ + ( arrayOopDesc::base_offset_in_bytes(T_DOUBLE) \ + ((julong)max_jint * sizeof(double)) ) #define UNSAFE_ENTRY(result_type, header) \ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java index f2f5422ad04..c4ab8e32c0b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -116,13 +116,6 @@ public class Universe { heap().printOn(tty); } - // Check whether an element of a typeArrayOop with the given type must be - // aligned 0 mod 8. The typeArrayOop itself must be aligned at least this - // strongly. - public static boolean elementTypeShouldBeAligned(BasicType type) { - return type == BasicType.T_DOUBLE || type == BasicType.T_LONG; - } - // Check whether an object field (static/non-static) of the given type must be // aligned 0 mod 8. public static boolean fieldTypeShouldBeAligned(BasicType type) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Array.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Array.java index 6ba23c9ea40..3f96f72cf04 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Array.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Array.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,28 +57,27 @@ public class Array extends Oop { private static long lengthOffsetInBytes=0; private static long typeSize; + // Check whether an element of a arrayOop with the given type must be + // aligned 0 mod 8. The arrayOop itself must be aligned at least this + // strongly. + private static boolean elementTypeShouldBeAligned(BasicType type) { + if (VM.getVM().isLP64()) { + if (type == BasicType.T_OBJECT || type == BasicType.T_ARRAY) { + return !VM.getVM().isCompressedOopsEnabled(); + } + } + return type == BasicType.T_DOUBLE || type == BasicType.T_LONG; + } + private static long headerSizeInBytes() { if (headerSize != 0) { return headerSize; } - if (VM.getVM().isCompressedKlassPointersEnabled()) { - headerSize = typeSize; - } else { - headerSize = VM.getVM().alignUp(typeSize + VM.getVM().getIntSize(), - VM.getVM().getHeapWordSize()); - } + headerSize = lengthOffsetInBytes() + VM.getVM().getIntSize(); return headerSize; } - private static long headerSize(BasicType type) { - if (Universe.elementTypeShouldBeAligned(type)) { - return alignObjectSize(headerSizeInBytes())/VM.getVM().getHeapWordSize(); - } else { - return headerSizeInBytes()/VM.getVM().getHeapWordSize(); - } - } - - private long lengthOffsetInBytes() { + private static long lengthOffsetInBytes() { if (lengthOffsetInBytes != 0) { return lengthOffsetInBytes; } @@ -108,7 +107,13 @@ public class Array extends Oop { } public static long baseOffsetInBytes(BasicType type) { - return headerSize(type) * VM.getVM().getHeapWordSize(); + long typeSizeInBytes = headerSizeInBytes(); + if (elementTypeShouldBeAligned(type)) { + VM vm = VM.getVM(); + return vm.alignUp(typeSizeInBytes, vm.getVM().getHeapWordSize()); + } else { + return typeSizeInBytes; + } } public boolean isArray() { return true; } diff --git a/test/hotspot/gtest/oops/test_arrayOop.cpp b/test/hotspot/gtest/oops/test_arrayOop.cpp index 84063813be3..e67e6e6c13b 100644 --- a/test/hotspot/gtest/oops/test_arrayOop.cpp +++ b/test/hotspot/gtest/oops/test_arrayOop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,19 +27,11 @@ #include "unittest.hpp" #include "utilities/globalDefinitions.hpp" -class arrayOopDescTest { - public: - - static int header_size_in_bytes() { - return arrayOopDesc::header_size_in_bytes(); - } -}; - static bool check_max_length_overflow(BasicType type) { julong length = arrayOopDesc::max_array_length(type); julong bytes_per_element = type2aelembytes(type); julong bytes = length * bytes_per_element - + arrayOopDescTest::header_size_in_bytes(); + + arrayOopDesc::base_offset_in_bytes(type); return (julong) (size_t) bytes == bytes; } @@ -87,3 +79,47 @@ TEST_VM(arrayOopDesc, narrowOop) { ASSERT_PRED1(check_max_length_overflow, T_NARROWOOP); } // T_VOID and T_ADDRESS are not supported by max_array_length() + +TEST_VM(arrayOopDesc, base_offset) { +#ifdef _LP64 + if (UseCompressedClassPointers) { + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BOOLEAN), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BYTE), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_SHORT), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_CHAR), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_INT), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_LONG), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 16); + } else { + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BOOLEAN), 20); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BYTE), 20); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_SHORT), 20); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_CHAR), 20); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_INT), 20); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 20); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_LONG), 24); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 24); + if (UseCompressedOops) { + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 20); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 20); + } else { + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 24); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 24); + } + } +#else + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BOOLEAN), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_BYTE), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_SHORT), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_CHAR), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_INT), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_LONG), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 16); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_OBJECT), 12); + EXPECT_EQ(arrayOopDesc::base_offset_in_bytes(T_ARRAY), 12); +#endif +} diff --git a/test/hotspot/gtest/oops/test_objArrayOop.cpp b/test/hotspot/gtest/oops/test_objArrayOop.cpp new file mode 100644 index 00000000000..60cf6242dd5 --- /dev/null +++ b/test/hotspot/gtest/oops/test_objArrayOop.cpp @@ -0,0 +1,57 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "oops/objArrayOop.hpp" +#include "unittest.hpp" +#include "utilities/globalDefinitions.hpp" + +TEST_VM(objArrayOop, osize) { + static const struct { + int objal; bool ccp; bool coops; int result; + } x[] = { +// ObjAligInB, UseCCP, UseCoops, object size in heap words +#ifdef _LP64 + { 8, false, false, 4 }, // 20 byte header, 8 byte oops + { 8, false, true, 3 }, // 20 byte header, 4 byte oops + { 8, true, false, 3 }, // 16 byte header, 8 byte oops + { 8, true, true, 3 }, // 16 byte header, 4 byte oops + { 16, false, false, 4 }, // 20 byte header, 8 byte oops, 16-byte align + { 16, false, true, 4 }, // 20 byte header, 4 byte oops, 16-byte align + { 16, true, false, 4 }, // 16 byte header, 8 byte oops, 16-byte align + { 16, true, true, 4 }, // 16 byte header, 4 byte oops, 16-byte align + { 256, false, false, 32 }, // 20 byte header, 8 byte oops, 256-byte align + { 256, false, true, 32 }, // 20 byte header, 4 byte oops, 256-byte align + { 256, true, false, 32 }, // 16 byte header, 8 byte oops, 256-byte align + { 256, true, true, 32 }, // 16 byte header, 4 byte oops, 256-byte align +#else + { 8, false, false, 4 }, // 12 byte header, 4 byte oops, wordsize 4 +#endif + { -1, false, false, -1 } + }; + for (int i = 0; x[i].result != -1; i++) { + if (x[i].objal == (int)ObjectAlignmentInBytes && x[i].ccp == UseCompressedClassPointers && x[i].coops == UseCompressedOops) { + EXPECT_EQ(objArrayOopDesc::object_size(1), (size_t)x[i].result); + } + } +} diff --git a/test/hotspot/jtreg/gtest/ArrayTests.java b/test/hotspot/jtreg/gtest/ArrayTests.java new file mode 100644 index 00000000000..b1afa4795d2 --- /dev/null +++ b/test/hotspot/jtreg/gtest/ArrayTests.java @@ -0,0 +1,56 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * This tests object array sizes by running gtests with different settings. + */ + +/* @test id=with-coops-with-ccp + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:+UseCompressedClassPointers -XX:+UseCompressedOops + */ +/* @test id=with-coops-no-ccp + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:-UseCompressedClassPointers -XX:+UseCompressedOops + */ +/* @test id=no-coops-with-ccp + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:+UseCompressedClassPointers -XX:-UseCompressedOops + */ +/* @test id=no-coops-no-ccp + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=arrayOop -XX:-UseCompressedClassPointers -XX:-UseCompressedOops + */ diff --git a/test/hotspot/jtreg/gtest/ObjArrayTests.java b/test/hotspot/jtreg/gtest/ObjArrayTests.java new file mode 100644 index 00000000000..baae1840417 --- /dev/null +++ b/test/hotspot/jtreg/gtest/ObjArrayTests.java @@ -0,0 +1,85 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * This tests object array sizes by running gtests with different settings. + */ + +/* @test id=with-coops-with-ccp + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedClassPointers -XX:+UseCompressedOops + */ +/* @test id=with-coops-no-ccp + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedClassPointers -XX:+UseCompressedOops + */ +/* @test id=no-coops-with-ccp + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedClassPointers -XX:-UseCompressedOops + */ +/* @test id=no-coops-no-ccp + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedClassPointers -XX:-UseCompressedOops + */ + +/* @test id=with-coops-with-ccp-large-align + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:ObjAlignmentInBytes=256 + */ +/* @test id=with-coops-no-ccp-large-align + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedClassPointers -XX:+UseCompressedOops -XX:ObjAlignmentInBytes=256 + */ +/* @test id=no-coops-with-ccp-large-align + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:+UseCompressedClassPointers -XX:-UseCompressedOops -XX:ObjAlignmentInBytes=256 + */ +/* @test id=no-coops-no-ccp-large-align + * @summary Run object array size tests with compressed oops and compressed class pointers + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.xml + * @run main/native GTestWrapper --gtest_filter=objArrayOop -XX:-UseCompressedClassPointers -XX:-UseCompressedOops -XX:ObjAlignmentInBytes=256 + */ diff --git a/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java b/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java new file mode 100644 index 00000000000..b679e866ac8 --- /dev/null +++ b/test/hotspot/jtreg/runtime/FieldLayout/ArrayBaseOffsets.java @@ -0,0 +1,113 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test id=with-coops-no-ccp + * @library /test/lib + * @requires vm.bits == "64" + * @modules java.base/jdk.internal.misc + * @run main/othervm -XX:+UseCompressedOops -XX:-UseCompressedClassPointers ArrayBaseOffsets + */ +/* + * @test id=with-coops-with-ccp + * @library /test/lib + * @requires vm.bits == "64" + * @requires vm.opt.UseCompressedClassPointers != false + * @modules java.base/jdk.internal.misc + * @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers ArrayBaseOffsets + */ +/* + * @test id=no-coops-no-ccp + * @library /test/lib + * @requires vm.bits == "64" + * @modules java.base/jdk.internal.misc + * @run main/othervm -XX:-UseCompressedOops -XX:-UseCompressedClassPointers ArrayBaseOffsets + */ +/* + * @test id=no-coops-with-ccp + * @library /test/lib + * @requires vm.bits == "64" + * @requires vm.opt.UseCompressedClassPointers != false + * @modules java.base/jdk.internal.misc + * @run main/othervm -XX:-UseCompressedOops -XX:+UseCompressedClassPointers ArrayBaseOffsets + */ +/* + * @test id=32bit + * @library /test/lib + * @requires vm.bits == "32" + * @modules java.base/jdk.internal.misc + * @run main/othervm ArrayBaseOffsets + */ + +import jdk.internal.misc.Unsafe; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.util.List; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; + +public class ArrayBaseOffsets { + + private static final boolean COOP; + private static final boolean CCP; + + static { + if (Platform.is64bit()) { + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + List vmargs = runtime.getInputArguments(); + CCP = !vmargs.contains("-XX:-UseCompressedClassPointers"); + COOP = System.getProperty("java.vm.compressedOopsMode") != null; + } else { + COOP = CCP = false; + } + } + + static public void main(String[] args) { + Unsafe unsafe = Unsafe.getUnsafe(); + int intOffset, longOffset; + if (Platform.is64bit()) { + if (CCP) { + intOffset = 16; + longOffset = 16; + } else { + intOffset = 20; + longOffset = 24; + } + } else { + intOffset = 12; + longOffset = 16; + } + Asserts.assertEquals(unsafe.arrayBaseOffset(boolean[].class), intOffset, "Misplaced boolean array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(byte[].class), intOffset, "Misplaced byte array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(char[].class), intOffset, "Misplaced char array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(short[].class), intOffset, "Misplaced short array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(int[].class), intOffset, "Misplaced int array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(long[].class), longOffset, "Misplaced long array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(float[].class), intOffset, "Misplaced float array base"); + Asserts.assertEquals(unsafe.arrayBaseOffset(double[].class), longOffset, "Misplaced double array base"); + int expectedObjArrayOffset = (COOP || !Platform.is64bit()) ? intOffset : longOffset; + Asserts.assertEquals(unsafe.arrayBaseOffset(Object[].class), expectedObjArrayOffset, "Misplaced object array base"); + } +} diff --git a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java index fc3b1a66d2a..22c5069f3e7 100644 --- a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java +++ b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Red Hat, Inc. All rights reserved. + * Copyright (c) 2020, 2024, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -313,6 +313,9 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase static final int LARGE_INT_ARRAY_SIZE = 1024*1024*1024 + 1024; static final int LARGE_OBJ_ARRAY_SIZE = (4096/(int)REF_SIZE)*1024*1024 + 1024; + static final boolean CCP = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedClassPointers"); + static final int ARRAY_HEADER_SIZE = CCP ? 16 : (Platform.is64bit() ? 20 : 16); + final String mode; public GetObjectSizeIntrinsicsTest(String name, String mode) { @@ -396,7 +399,7 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase } private void testSize_newSmallIntArray() { - long expected = roundUp(4L*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(4L*SMALL_ARRAY_SIZE + ARRAY_HEADER_SIZE, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(new int[SMALL_ARRAY_SIZE])); } @@ -404,7 +407,7 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase private void testSize_localSmallIntArray() { int[] arr = new int[SMALL_ARRAY_SIZE]; - long expected = roundUp(4L*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(4L*SMALL_ARRAY_SIZE + ARRAY_HEADER_SIZE, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(arr)); } @@ -413,14 +416,14 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase static int[] smallArr = new int[SMALL_ARRAY_SIZE]; private void testSize_fieldSmallIntArray() { - long expected = roundUp(4L*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(4L*SMALL_ARRAY_SIZE + ARRAY_HEADER_SIZE, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(smallArr)); } } private void testSize_newSmallObjArray() { - long expected = roundUp(REF_SIZE*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(REF_SIZE*SMALL_ARRAY_SIZE + ARRAY_HEADER_SIZE, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(new Object[SMALL_ARRAY_SIZE])); } @@ -428,7 +431,7 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase private void testSize_localSmallObjArray() { Object[] arr = new Object[SMALL_ARRAY_SIZE]; - long expected = roundUp(REF_SIZE*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(REF_SIZE*SMALL_ARRAY_SIZE + ARRAY_HEADER_SIZE, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(arr)); } @@ -437,7 +440,7 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase static Object[] smallObjArr = new Object[SMALL_ARRAY_SIZE]; private void testSize_fieldSmallObjArray() { - long expected = roundUp(REF_SIZE*SMALL_ARRAY_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(REF_SIZE*SMALL_ARRAY_SIZE + ARRAY_HEADER_SIZE, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(smallObjArr)); } @@ -445,7 +448,7 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase private void testSize_localLargeIntArray() { int[] arr = new int[LARGE_INT_ARRAY_SIZE]; - long expected = roundUp(4L*LARGE_INT_ARRAY_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(4L*LARGE_INT_ARRAY_SIZE + ARRAY_HEADER_SIZE, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(arr)); } @@ -453,7 +456,7 @@ public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase private void testSize_localLargeObjArray() { Object[] arr = new Object[LARGE_OBJ_ARRAY_SIZE]; - long expected = roundUp(REF_SIZE*LARGE_OBJ_ARRAY_SIZE + 16, OBJ_ALIGN); + long expected = roundUp(REF_SIZE*LARGE_OBJ_ARRAY_SIZE + ARRAY_HEADER_SIZE, OBJ_ALIGN); for (int c = 0; c < ITERS; c++) { assertEquals(expected, fInst.getObjectSize(arr)); }