diff --git a/.github/configs/base.yml b/.github/configs/base.yml index e848fe24..5a55b2bd 100644 --- a/.github/configs/base.yml +++ b/.github/configs/base.yml @@ -2,13 +2,16 @@ includes: - "$RUNNING_NG_PACKAGE_DATA/base/runbms.yml" suites: - dacapo-23.9-RC3-chopin-ci: + # We use the same suites name "dacapochopin" as defined in "running-ng/src/running/config/base/dacapo.yml". + # This will combine this definition with the existing "dacapochopin". + # This will also allow us to use modifiers such as "dacapochopin_jdk21" which expect the suites name "dacapochopin". + dacapochopin: type: DaCapo - # Need running-ng to support 23.9 - release: evaluation - path: "DACAPO_PATH/dacapo-23.9-RC3-chopin.jar" + release: "23.11" + path: "DACAPO_PATH/dacapo-23.11-MR2-chopin.jar" minheap: mmtk-openjdk-11-MarkCompact # Min heap values are from dacapo-evaluation-git-04132797 + # TODO: Use the values provided by the released version, and use G1 instead of MarkCompact. minheap_values: mmtk-openjdk-11-MarkCompact: avrora: 8 @@ -83,19 +86,19 @@ plugins: - "scratch/stderr.log" runtimes: - jdk11-master: + jdk21-master: type: OpenJDK - release: 11 + release: 21 home: "/home/runner/work/mmtk-openjdk/mmtk-openjdk/bundles/jdk" configs: - - "jdk11-master|ms|s|fail_on_oom|tph|preserve|mmtk_gc-SemiSpace" - - "jdk11-master|ms|s|fail_on_oom|tph|preserve|mmtk_gc-GenCopy" - - "jdk11-master|ms|s|fail_on_oom|tph|preserve|mmtk_gc-Immix" - - "jdk11-master|ms|s|fail_on_oom|tph|preserve|mmtk_gc-GenImmix" - - "jdk11-master|ms|s|fail_on_oom|tph|preserve|mmtk_gc-StickyImmix" - - "jdk11-master|ms|s|fail_on_oom|tph|preserve|mmtk_gc-MarkSweep" - - "jdk11-master|ms|s|fail_on_oom|tph|preserve|mmtk_gc-MarkCompact" + - "jdk21-master|dacapochopin_jdk21|ms|s|fail_on_oom|tph|preserve|mmtk_gc-SemiSpace" + - "jdk21-master|dacapochopin_jdk21|ms|s|fail_on_oom|tph|preserve|mmtk_gc-GenCopy" + - "jdk21-master|dacapochopin_jdk21|ms|s|fail_on_oom|tph|preserve|mmtk_gc-Immix" + - "jdk21-master|dacapochopin_jdk21|ms|s|fail_on_oom|tph|preserve|mmtk_gc-GenImmix" + - "jdk21-master|dacapochopin_jdk21|ms|s|fail_on_oom|tph|preserve|mmtk_gc-StickyImmix" + - "jdk21-master|dacapochopin_jdk21|ms|s|fail_on_oom|tph|preserve|mmtk_gc-MarkSweep" + - "jdk21-master|dacapochopin_jdk21|ms|s|fail_on_oom|tph|preserve|mmtk_gc-MarkCompact" benchmarks: - dacapo-23.9-RC3-chopin-ci: + dacapochopin: diff --git a/.github/scripts/ci-build.sh b/.github/scripts/ci-build.sh index 39ce2484..e8a7dd6e 100755 --- a/.github/scripts/ci-build.sh +++ b/.github/scripts/ci-build.sh @@ -13,4 +13,4 @@ build_target=$1 # Build product bundle cd $OPENJDK_PATH sh configure --disable-warnings-as-errors --with-debug-level=$DEBUG_LEVEL -make CONF=linux-x86_64-normal-server-$DEBUG_LEVEL THIRD_PARTY_HEAP=$BINDING_PATH/openjdk $OPENJDK_BUILD_TARGET +make CONF=linux-x86_64-server-$DEBUG_LEVEL THIRD_PARTY_HEAP=$BINDING_PATH/openjdk $OPENJDK_BUILD_TARGET diff --git a/.github/scripts/ci-check-lineends.sh b/.github/scripts/ci-check-lineends.sh index 573f6ce3..d875ab86 100755 --- a/.github/scripts/ci-check-lineends.sh +++ b/.github/scripts/ci-check-lineends.sh @@ -2,12 +2,20 @@ FN=$1 +ANY_ERRORS=0 + LAST_CHAR="$(tail -c 1 $FN | od -A n -t x1)" if test "$LAST_CHAR" != " 0a"; then echo "File does not end with newline:" $FN + ANY_ERRORS=1 fi LINEEND="$(dos2unix -i $FN | awk '{print $1 " " $3}')" if test "$LINEEND" != "0 0"; then echo "File contains non-UNIX line endings:" $FN + ANY_ERRORS=1 +fi + +if [[ $ANY_ERRORS -ne 0 ]]; then + exit 1 fi diff --git a/.github/scripts/ci-checkout.sh b/.github/scripts/ci-checkout.sh index 4e5048d0..fcea3131 100755 --- a/.github/scripts/ci-checkout.sh +++ b/.github/scripts/ci-checkout.sh @@ -1,4 +1,3 @@ -# ci-checkout.sh set -ex . $(dirname "$0")/common.sh @@ -6,9 +5,6 @@ set -ex OPENJDK_URL=`cargo read-manifest --manifest-path=$BINDING_PATH/mmtk/Cargo.toml | python3 -c 'import json,sys; print(json.load(sys.stdin)["metadata"]["openjdk"]["openjdk_repo"])'` OPENJDK_VERSION=`cargo read-manifest --manifest-path=$BINDING_PATH/mmtk/Cargo.toml | python3 -c 'import json,sys; print(json.load(sys.stdin)["metadata"]["openjdk"]["openjdk_version"])'` -# Use default openjdk path if it is not set (this is only need when MMTk core calls the script) -OPENJDK_PATH=${OPENJDK_PATH:="$BINDING_PATH/repos/openjdk"} - rm -rf $OPENJDK_PATH git clone $OPENJDK_URL $OPENJDK_PATH git -C $OPENJDK_PATH checkout $OPENJDK_VERSION diff --git a/.github/scripts/ci-setup.sh b/.github/scripts/ci-setup.sh index 8df050af..1176116f 100755 --- a/.github/scripts/ci-setup.sh +++ b/.github/scripts/ci-setup.sh @@ -2,7 +2,7 @@ set -xe . $(dirname "$0")/common.sh -# Install nightly rust +# Install the appropriate Rust toolchain rustup toolchain install $RUSTUP_TOOLCHAIN rustup target add i686-unknown-linux-gnu --toolchain $RUSTUP_TOOLCHAIN rustup component add clippy --toolchain $RUSTUP_TOOLCHAIN diff --git a/.github/scripts/ci-style.sh b/.github/scripts/ci-style.sh index ed0e5c1e..2072d18b 100755 --- a/.github/scripts/ci-style.sh +++ b/.github/scripts/ci-style.sh @@ -11,11 +11,26 @@ cargo clippy --release cargo fmt -- --check popd -find $BINDING_PATH/openjdk \ +# Allow all files to be checked, and exit if any went wrong. +set +xe + +ANY_LINE_END_ERRORS=0 +for FN in $(find $BINDING_PATH/openjdk \ $BINDING_PATH/mmtk \ + '(' \ -name '*.hpp' \ -o -name '*.cpp' \ -o -name '*.rs' \ -o -name '*.toml' \ -o -name '*.gmk' \ - -exec ./ci-check-lineends.sh '{}' \; + ')') +do + $(dirname "$0")/ci-check-lineends.sh "$FN" + if [[ $? -ne 0 ]]; then + ANY_LINE_END_ERRORS=1 + fi +done + +if [[ $ANY_LINE_END_ERRORS -ne 0 ]]; then + exit 1 +fi diff --git a/.github/scripts/ci-test-extended.sh b/.github/scripts/ci-test-extended.sh index 4d585d78..46410183 100755 --- a/.github/scripts/ci-test-extended.sh +++ b/.github/scripts/ci-test-extended.sh @@ -1,21 +1,10 @@ set -ex -. $(dirname "$0")/common.sh -cur=$BINDING_PATH/.github/scripts - -# This script is only used by MMTk core. -# OPENJDK_PATH is the default path set in ci-checkout.sh -export OPENJDK_PATH=$BINDING_PATH/repos/openjdk -export DEBUG_LEVEL=fastdebug -export TEST_JAVA_BIN=$OPENJDK_PATH/build/linux-x86_64-normal-server-$DEBUG_LEVEL/jdk/bin/java - -# Download dacapo -export DACAPO_PATH=$BINDING_PATH/dacapo -mkdir -p $DACAPO_PATH -wget https://downloads.sourceforge.net/project/dacapobench/archive/2006-10-MR2/dacapo-2006-10-MR2.jar -O $DACAPO_PATH/dacapo-2006-10-MR2.jar +. $(dirname "$0")/common-binding-test.sh # Normal build $cur/ci-build.sh + # Test $cur/ci-test-only-normal.sh $cur/ci-test-only-normal-no-compressed-oops.sh diff --git a/.github/scripts/ci-test-minimal.sh b/.github/scripts/ci-test-minimal.sh index 373f9852..77e484d1 100755 --- a/.github/scripts/ci-test-minimal.sh +++ b/.github/scripts/ci-test-minimal.sh @@ -1,21 +1,10 @@ set -ex -. $(dirname "$0")/common.sh -cur=$BINDING_PATH/.github/scripts - -# This script is only used by MMTk core. -# OPENJDK_PATH is the default path set in ci-checkout.sh -export OPENJDK_PATH=$BINDING_PATH/repos/openjdk -export DEBUG_LEVEL=fastdebug -export TEST_JAVA_BIN=$OPENJDK_PATH/build/linux-x86_64-normal-server-$DEBUG_LEVEL/jdk/bin/java - -# Download dacapo -export DACAPO_PATH=$BINDING_PATH/dacapo -mkdir -p $DACAPO_PATH -wget https://downloads.sourceforge.net/project/dacapobench/archive/2006-10-MR2/dacapo-2006-10-MR2.jar -O $DACAPO_PATH/dacapo-2006-10-MR2.jar +. $(dirname "$0")/common-binding-test.sh # Normal build $cur/ci-build.sh + # Test MMTK_PLAN=SemiSpace runbms_dacapo2006_with_heap_multiplier fop 4 MMTK_PLAN=Immix runbms_dacapo2006_with_heap_multiplier fop 4 diff --git a/.github/scripts/ci-test-only-normal-no-compressed-oops.sh b/.github/scripts/ci-test-only-normal-no-compressed-oops.sh index 3333984c..c5a68215 100755 --- a/.github/scripts/ci-test-only-normal-no-compressed-oops.sh +++ b/.github/scripts/ci-test-only-normal-no-compressed-oops.sh @@ -4,6 +4,10 @@ set -xe unset JAVA_TOOL_OPTIONS +# This script runs against a specific pre-built java binary, not OpenJDK source code. +ensure_env TEST_JAVA_BIN +unset OPENJDK_PATH + run_all_no_compressed_oop() { heap_multiplier=$1 diff --git a/.github/scripts/ci-test-only-normal.sh b/.github/scripts/ci-test-only-normal.sh index 8f834d1b..be37c252 100755 --- a/.github/scripts/ci-test-only-normal.sh +++ b/.github/scripts/ci-test-only-normal.sh @@ -4,6 +4,10 @@ set -xe unset JAVA_TOOL_OPTIONS +# This script runs against a specific pre-built java binary, not OpenJDK source code. +ensure_env TEST_JAVA_BIN +unset OPENJDK_PATH + run_all() { heap_multiplier=$1 diff --git a/.github/scripts/ci-test-only-weak-ref.sh b/.github/scripts/ci-test-only-weak-ref.sh index 7fe62fde..683f6907 100755 --- a/.github/scripts/ci-test-only-weak-ref.sh +++ b/.github/scripts/ci-test-only-weak-ref.sh @@ -3,7 +3,10 @@ set -xe . $(dirname "$0")/common.sh unset JAVA_TOOL_OPTIONS -cd $OPENJDK_PATH + +# This script runs against a specific pre-built java binary, not OpenJDK source code. +ensure_env TEST_JAVA_BIN +unset OPENJDK_PATH export MMTK_NO_REFERENCE_TYPES=false # Just test Immix and MarkCompact diff --git a/.github/scripts/common-binding-test.sh b/.github/scripts/common-binding-test.sh new file mode 100644 index 00000000..cddbd9d0 --- /dev/null +++ b/.github/scripts/common-binding-test.sh @@ -0,0 +1,19 @@ +# This is the common part of binding tests (minimal and extended) invoked from mmtk-core. + +set -xe + +. $(dirname "$0")/common.sh +cur=$BINDING_PATH/.github/scripts + +# Use fastdebug for binding tests +export DEBUG_LEVEL=fastdebug + +# We build OpenJDK with the "default" target, and this is the location of the Java binary. +# It's equivalent to invoking "make" without an explicit target, but it's better to be explicit. +export OPENJDK_BUILD_TARGET=default +export TEST_JAVA_BIN=$OPENJDK_PATH/build/linux-x86_64-server-$DEBUG_LEVEL/jdk/bin/java + +# Download dacapo +export DACAPO_PATH=$BINDING_PATH/dacapo +mkdir -p $DACAPO_PATH +wget https://downloads.sourceforge.net/project/dacapobench/archive/2006-10-MR2/dacapo-2006-10-MR2.jar -O $DACAPO_PATH/dacapo-2006-10-MR2.jar diff --git a/.github/scripts/common.sh b/.github/scripts/common.sh index a0150df8..d432c86e 100644 --- a/.github/scripts/common.sh +++ b/.github/scripts/common.sh @@ -1,6 +1,10 @@ BINDING_PATH=$(realpath $(dirname "$0"))/../.. RUSTUP_TOOLCHAIN=`cat $BINDING_PATH/mmtk/rust-toolchain` +# build.yml specifies the OPENJDK_PATH env var when calling ci-build.sh +# But other scripts expect a default path for OpenJDK. +OPENJDK_PATH=${OPENJDK_PATH:="$BINDING_PATH/repos/jdk"} + # dacapo2006 min heap for mark compact MINHEAP_ANTLR=5 MINHEAP_FOP=13 diff --git a/.github/scripts/pgo-build.sh b/.github/scripts/pgo-build.sh index 4e18f682..0285f45d 100755 --- a/.github/scripts/pgo-build.sh +++ b/.github/scripts/pgo-build.sh @@ -11,20 +11,20 @@ cargo clean popd # Compile with profiling support -RUSTFLAGS="-Cprofile-generate=/tmp/$USER/pgo-data" make CONF=linux-x86_64-normal-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images +RUSTFLAGS="-Cprofile-generate=/tmp/$USER/pgo-data" make CONF=linux-x86_64-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images # Remove extraneous profiling data rm -rf /tmp/$USER/pgo-data/* # Profile using fop -MMTK_PLAN=GenImmix MMTK_STRESS_FACTOR=16777216 MMTK_PRECISE_STRESS=false ./build/linux-x86_64-normal-server-release/images/jdk/bin/java -XX:MetaspaceSize=500M -XX:+DisableExplicitGC -XX:-TieredCompilation -Xcomp -XX:+UseThirdPartyHeap -Xms60M -Xmx60M -jar /usr/share/benchmarks/dacapo/dacapo-23.9-RC3-chopin.jar -n 5 fop +MMTK_PLAN=GenImmix MMTK_STRESS_FACTOR=4194304 MMTK_PRECISE_STRESS=false ./build/linux-x86_64-server-release/images/jdk/bin/java -XX:MetaspaceSize=500M -XX:+DisableExplicitGC -XX:-TieredCompilation -Xcomp -XX:+UseThirdPartyHeap -Xms60M -Xmx60M -jar /usr/share/benchmarks/dacapo/dacapo-23.11-chopin.jar -n 5 fop # Merge profiling data -/opt/rust/toolchains/1.71.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -o /tmp/$USER/pgo-data/merged.profdata /tmp/$USER/pgo-data +/opt/rust/toolchains/1.83.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -o /tmp/$USER/pgo-data/merged.profdata /tmp/$USER/pgo-data pushd ../mmtk-openjdk/mmtk cargo clean popd # Compile using profiling data -RUSTFLAGS="-Cprofile-use=/tmp/$USER/pgo-data/merged.profdata -Cllvm-args=-pgo-warn-missing-function" make CONF=linux-x86_64-normal-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images +RUSTFLAGS="-Cprofile-use=/tmp/$USER/pgo-data/merged.profdata -Cllvm-args=-pgo-warn-missing-function" make CONF=linux-x86_64-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ec12b7cb..039bf7d4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,24 +20,19 @@ jobs: build-linux-x64: name: linux-x64 runs-on: ubuntu-22.04 + env: + # This overrides OPENJDK_PATH in ci-common.sh + # Note: We cannot use default environment variables (GITHUB_*) in the "env" context. Use github.* instead. + # See: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables + OPENJDK_PATH: ${{ github.workspace }}/git/openjdk steps: - name: Checkout MMTk OpenJDK binding uses: actions/checkout@v4 with: path: ./git/mmtk-openjdk - - name: Extract OpenJDK revision - id: extract-openjdk-revision - run: | - OPENJDK_VERSION=`sed -n 's/^openjdk_version.=."\(.*\)"$/\1/p' < git/mmtk-openjdk/mmtk/Cargo.toml` - echo "openjdk-revision=$OPENJDK_VERSION" >> $GITHUB_OUTPUT - name: Checkout OpenJDK - uses: actions/checkout@v4 - with: - repository: mmtk/openjdk - path: ./git/openjdk - ref: ${{ steps.extract-openjdk-revision.outputs.openjdk-revision }} - # Patch mmtk-core version if needed - - name: Patch mmtk-core version + run: ./git/mmtk-openjdk/.github/scripts/ci-checkout.sh + - name: Patch mmtk-core version if needed if: ${{ inputs.mmtk-core-repo != '' || inputs.mmtk-core-ref != '' }} run: | pip3 install tomlkit @@ -60,14 +55,16 @@ jobs: echo "BUILD_SUFFIX=$escaped_build" >> $GITHUB_ENV fi - name: Build MMTk OpenJDK ${{ inputs.debug-level }} - run: | - OPENJDK_PATH=$GITHUB_WORKSPACE/git/openjdk DEBUG_LEVEL=${{ inputs.debug-level }} OPENJDK_BUILD_TARGET=product-bundles ./.github/scripts/ci-build.sh + env: + DEBUG_LEVEL: ${{ inputs.debug-level }} + OPENJDK_BUILD_TARGET: product-bundles + run: ./.github/scripts/ci-build.sh working-directory: ./git/mmtk-openjdk - name: Upload bundles uses: actions/upload-artifact@v4 with: name: linux-x86_64-server-${{ inputs.debug-level }}-bundles-${{ env.BUILD_SUFFIX }} path: | - ./git/openjdk/build/linux-x86_64-normal-server-${{ inputs.debug-level }}/bundles/*_bin.tar.gz - ./git/openjdk/build/linux-x86_64-normal-server-${{ inputs.debug-level }}/bundles/*_bin-debug.tar.gz + ./git/openjdk/build/linux-x86_64-server-${{ inputs.debug-level }}/bundles/*_bin.tar.gz + ./git/openjdk/build/linux-x86_64-server-${{ inputs.debug-level }}/bundles/*_bin-debug.tar.gz retention-days: 2 diff --git a/.github/workflows/run-dacapo-chopin.yml b/.github/workflows/run-dacapo-chopin.yml index d52ca267..f7ef88f9 100644 --- a/.github/workflows/run-dacapo-chopin.yml +++ b/.github/workflows/run-dacapo-chopin.yml @@ -4,9 +4,9 @@ on: workflow_call: env: - DACAPO_VERSION: dacapo-23.9-RC3-chopin - DACAPO_FILE: dacapo-23.9-RC3-chopin.zip - DACAPO_DOWNLOAD_URL: https://download.dacapobench.org/chopin/dacapo-23.9-RC3-chopin.zip + DACAPO_VERSION: dacapo-23.11-MR2-chopin + DACAPO_FILE: dacapo-23.11-MR2-chopin.zip + DACAPO_DOWNLOAD_URL: https://download.dacapobench.org/chopin/dacapo-23.11-MR2-chopin.zip jobs: cache-dacapo: diff --git a/README.md b/README.md index 0eeb6103..7773f2d9 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,9 @@ Please make sure your dev machine satisfies those prerequisites. ### Before you continue -The minimal supported Rust version for MMTk-OpenJDK binding is 1.61.0. Make sure your Rust version is higher than this. We test MMTk-OpenJDK -binding with Rust 1.66.1 (as specified in [`rust-toolchain`](mmtk/rust-toolchain)). +The minimal supported Rust version for MMTk-OpenJDK binding is defined by the `package.rust-version` attribute in [`Cargo.toml`](mmtk/Cargo.toml). +Make sure your Rust version is higher than this. +We test MMTk-OpenJDK binding with the Rust version specified in [`rust-toolchain`](mmtk/rust-toolchain). You may also need to use ssh-agent to authenticate with github (see [here](https://github.com/rust-lang/cargo/issues/3487) for more info): ```console @@ -34,7 +35,7 @@ Your working directory/ ├─ mmtk-openjdk/ │ ├─ openjdk/ │ └─ mmtk/ -├─ openjdk/ +├─ jdk/ └─ mmtk-core/ (optional) ``` @@ -51,13 +52,13 @@ The binding repo mainly consists of two folders, `mmtk` and `openjdk`. #### Checkout OpenJDK -You would need our OpenJDK fork which includes the support for a third party heap (like MMTk). We assume you put `openjdk` as a sibling of `mmtk-openjdk`. +You would need our OpenJDK fork which includes the support for a third party heap (like MMTk). We assume you put `jdk` as a sibling of `mmtk-openjdk`. [`Cargo.toml`](mmtk/Cargo.toml) defines the version of OpenJDK that works with the version of `mmtk-openjdk`. Assuming your current working directory is the parent folder of `mmtk-openjdk`, you can checkout out OpenJDK and the correct version using: ```console -$ git clone https://github.com/mmtk/openjdk.git -$ git -C openjdk checkout `sed -n 's/^openjdk_version.=."\(.*\)"$/\1/p' < mmtk-openjdk/mmtk/Cargo.toml` +$ git clone https://github.com/mmtk/jdk.git +$ git -C jdk checkout `sed -n 's/^openjdk_version.=."\(.*\)"$/\1/p' < mmtk-openjdk/mmtk/Cargo.toml` ``` #### Checkout MMTk core (optional) @@ -85,7 +86,7 @@ _**Note:** MMTk is only tested with the `server` build variant._ After cloned the OpenJDK repo, cd into the root directiory: ```console -$ cd openjdk +$ cd jdk ``` Then select a `DEBUG_LEVEL`, can be one of `release`, `fastdebug`, `slowdebug` and `optimized`. @@ -113,17 +114,17 @@ $ sh configure --disable-warnings-as-errors --with-debug-level=$DEBUG_LEVEL Then build OpenJDK (this will build MMTk as well): ```console -$ make CONF=linux-x86_64-normal-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images +$ make CONF=linux-x86_64-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images ``` -The output jdk is then found at `./build/linux-x86_64-normal-server-release/images/jdk`. +The output jdk is then found at `./build/linux-x86_64-server-release/images/jdk`. -> **Note:** The above `make` command will build the `images` target, which is a proper release build of OpenJDK. It is **essential** that you use this target if you are planning on evaluating your build (e.g. measuring performance, gathering minimum heap values, etc). However, if you are simply developing and building incremental changes often, you may want to use the [`default` target or "exploded image"](https://github.com/openjdk/jdk11u/blob/master/doc/building.md#Running-make), which has a marginally shorter build time. However, be wary, as the exploded image is the (roughly) minimal set of outputs required to run the built JDK and is not guaranteed to run all benchmarks. It may have bloated minimum heap values as well. +> **Note:** The above `make` command will build the `images` target, which is a proper release build of OpenJDK. It is **essential** that you use this target if you are planning on evaluating your build (e.g. measuring performance, gathering minimum heap values, etc). However, if you are simply developing and building incremental changes often, you may want to use the [`default` target or "exploded image"](https://github.com/openjdk/jdk21u/blob/master/doc/building.md#Running-make), which has a marginally shorter build time. However, be wary, as the exploded image is the (roughly) minimal set of outputs required to run the built JDK and is not guaranteed to run all benchmarks. It may have bloated minimum heap values as well. > -> The exploded image can be built as follows. The output jdk can be found at `./build/linux-x86_64-normal-server-$DEBUG_LEVEL/jdk`. +> The exploded image can be built as follows. The output jdk can be found at `./build/linux-x86_64-server-$DEBUG_LEVEL/jdk`. > > ```console -> $ make CONF=linux-x86_64-normal-server-$DEBUG_LEVEL THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk +> $ make CONF=linux-x86_64-server-$DEBUG_LEVEL THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk > ``` > > Again: **do not use the exploded image for performance analysis**. @@ -151,7 +152,7 @@ stress factor of 4 MB in order to trigger more GC events. First we compile MMTk with profiling support: ```console -$ RUSTFLAGS="-Cprofile-generate=/tmp/$USER/pgo-data" make CONF=linux-x86_64-normal-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images +$ RUSTFLAGS="-Cprofile-generate=/tmp/$USER/pgo-data" make CONF=linux-x86_64-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images $ rm -rf /tmp/$USER/pgo-data/* ``` We clear the `/tmp/$USER/pgo-data` directory as during compilation, the JVM we @@ -162,14 +163,14 @@ We then run `fop` in order to get some profiling data. Note that your location for the DaCapo benchmarks may be different: ```bash -MMTK_PLAN=GenImmix MMTK_STRESS_FACTOR=4194304 MMTK_PRECISE_STRESS=false ./build/linux-x86_64-normal-server-release/images/jdk/bin/java -XX:MetaspaceSize=500M -XX:+DisableExplicitGC -XX:-TieredCompilation -Xcomp -XX:+UseThirdPartyHeap -Xms60M -Xmx60M -jar /usr/share/benchmarks/dacapo/dacapo-evaluation-git-6e411f33.jar -n 5 fop +MMTK_PLAN=GenImmix MMTK_STRESS_FACTOR=4194304 MMTK_PRECISE_STRESS=false ./build/linux-x86_64-server-release/images/jdk/bin/java -XX:MetaspaceSize=500M -XX:+DisableExplicitGC -XX:-TieredCompilation -Xcomp -XX:+UseThirdPartyHeap -Xms60M -Xmx60M -jar /usr/share/benchmarks/dacapo/dacapo-23.11-chopin.jar -n 5 fop ``` We have to merge the profiling data into something we can feed into the Rust compiler using `llvm-profdata`: ```console -$ /opt/rust/toolchains/1.66.1-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -o /tmp/$USER/pgo-data/merged.profdata /tmp/$USER/pgo-data +$ /opt/rust/toolchains/1.83.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -o /tmp/$USER/pgo-data/merged.profdata /tmp/$USER/pgo-data ``` The location of your version of `llvm-profdata` may be different to what we @@ -179,11 +180,11 @@ your Rust version.* Finally, we build a new image using the profiling data as an input: ```console -$ RUSTFLAGS="-Cprofile-use=/tmp/$USER/pgo-data/merged.profdata -Cllvm-args=-pgo-warn-missing-function" make CONF=linux-x86_64-normal-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images +$ RUSTFLAGS="-Cprofile-use=/tmp/$USER/pgo-data/merged.profdata -Cllvm-args=-pgo-warn-missing-function" make CONF=linux-x86_64-server-release THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk images ``` We now have an OpenJDK build under -`./build/linux-x86_64-normal-server-release/images/jdk` with MMTk that has been +`./build/linux-x86_64-server-release/images/jdk` with MMTk that has been optimized using PGO. For ease of use, we have provided an example script which does the above in @@ -197,7 +198,7 @@ metadata), but by setting the environment variable `MMTK_MARK_IN_HEADER=1` while building OpenJDK, we can change its location to be in the object's header: ```console -$ MMTK_MARK_IN_HEADER=1 make CONF=linux-x86_64-normal-server-$DEBUG_LEVEL THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk +$ MMTK_MARK_IN_HEADER=1 make CONF=linux-x86_64-server-$DEBUG_LEVEL THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk ``` ### Valid object bit @@ -207,7 +208,7 @@ environment variable `MMTK_VO_BIT=1` when building OpenJDK. This will set the fe for mmtk-core, as well as compiling the fastpath for the VO bit. ```console -$ MMTK_VO_BIT=1 make CONF=linux-x86_64-normal-server-$DEBUG_LEVEL THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk +$ MMTK_VO_BIT=1 make CONF=linux-x86_64-server-$DEBUG_LEVEL THIRD_PARTY_HEAP=$PWD/../mmtk-openjdk/openjdk ``` ## Test @@ -221,8 +222,8 @@ class HelloWorld { System.out.println("Hello World!"); } } -$ ./build/linux-x86_64-normal-server-$DEBUG_LEVEL/jdk/bin/javac HelloWorld.java -$ ./build/linux-x86_64-normal-server-$DEBUG_LEVEL/jdk/bin/java HelloWorld +$ ./build/linux-x86_64-server-$DEBUG_LEVEL/jdk/bin/javac HelloWorld.java +$ ./build/linux-x86_64-server-$DEBUG_LEVEL/jdk/bin/java HelloWorld Hello World! ``` @@ -231,7 +232,7 @@ Hello World! Pass `-XX:+UseThirdPartyHeap` as java command line arguments to enable MMTk. ``` -$ ./build/linux-x86_64-normal-server-$DEBUG_LEVEL/jdk/bin/java -XX:+UseThirdPartyHeap HelloWorld +$ ./build/linux-x86_64-server-$DEBUG_LEVEL/jdk/bin/java -XX:+UseThirdPartyHeap HelloWorld ``` If `DEBUG_LEVEL` is `release`, you should just see @@ -266,7 +267,7 @@ $ wget https://sourceforge.net/projects/dacapobench/files/9.12-bach-MR1/dacapo-9 Run a DaCapo benchmark (e.g. `lusearch`): ```console -$ ./build/linux-x86_64-normal-server-$DEBUG_LEVEL/jdk/bin/java -XX:+UseThirdPartyHeap -Xms512M -Xmx512M -jar ./dacapo-9.12-MR1-bach.jar lusearch +$ ./build/linux-x86_64-server-$DEBUG_LEVEL/jdk/bin/java -XX:+UseThirdPartyHeap -Xms512M -Xmx512M -jar ./dacapo-9.12-MR1-bach.jar lusearch Using scaled threading model. 24 processors detected, 24 threads used to drive the workload, in a possible range of [1,64] ===== DaCapo 9.12-MR1 lusearch starting ===== 4 query batches completed diff --git a/TESTING-legacy.md b/TESTING-legacy.md index 17c8ccd5..1cf25548 100755 --- a/TESTING-legacy.md +++ b/TESTING-legacy.md @@ -34,8 +34,8 @@ cargo +nightly build cd .. # Build OpenJDK bash configure --disable-warnings-as-errors --with-debug-level= -CONF=linux-x86_64-normal-server- make -# JDK is at `build/linux-x86_64-normal-server-/jdk` +CONF=linux-x86_64-server- make +# JDK is at `build/linux-x86_64-server-/jdk` ``` ## Building (release) @@ -48,13 +48,13 @@ cargo +nightly build --release cd .. # Build OpenJDK bash configure --disable-warnings-as-errors -CONF=linux-x86_64-normal-server-release make -# JDK is at `build/linux-x86_64-normal-server-release/jdk` +CONF=linux-x86_64-server-release make +# JDK is at `build/linux-x86_64-server-release/jdk` ``` ## Testing -1. `java` binary is at `build/linux-x86_64-normal-server-/jdk/bin/java`. +1. `java` binary is at `build/linux-x86_64-server-/jdk/bin/java`. 2. Set env `LD_LIBRARY_PATH` to include `$PWD/mmtk/vmbindings/openjdk/target/debug` (or `$PWD/mmtk/vmbindings/openjdk/target/release` if openjdk is built with debug level `release`). 3. To enable MMTk, pass `-XX:+UseMMTk -XX:-UseCompressedOops` to `java`. @@ -63,13 +63,13 @@ e.g.: * If `DEBUG_LEVEL` = `fastdebug`, `slowdebug` or `optimized`: ```bash export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/mmtk/vmbindings/openjdk/target/debug -build/linux-x86_64-normal-server-fastdebug/jdk/bin/java -XX:+UseMMTk -XX:-UseCompressedOops HelloWorld +build/linux-x86_64-server-fastdebug/jdk/bin/java -XX:+UseMMTk -XX:-UseCompressedOops HelloWorld ``` * If `DEBUG_LEVEL` = `release`: ```bash export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/mmtk/vmbindings/openjdk/target/release -build/linux-x86_64-normal-server-release/jdk/bin/java -XX:+UseMMTk -XX:-UseCompressedOops HelloWorld +build/linux-x86_64-server-release/jdk/bin/java -XX:+UseMMTk -XX:-UseCompressedOops HelloWorld ``` > Original instructions by Abdullah Al Mamun and Tanveer Hannan diff --git a/mmtk/Cargo.lock b/mmtk/Cargo.lock index f8a85824..c76d463e 100644 --- a/mmtk/Cargo.lock +++ b/mmtk/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -28,35 +28,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys", ] @@ -87,15 +88,15 @@ checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "built" @@ -108,9 +109,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" dependencies = [ "bytemuck_derive", ] @@ -123,14 +124,14 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.101", ] [[package]] name = "cc" -version = "1.1.18" +version = "1.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a" dependencies = [ "jobserver", "libc", @@ -145,9 +146,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "core-foundation-sys" @@ -170,18 +171,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -198,18 +199,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "delegate" @@ -219,7 +220,7 @@ checksum = "b9b6483c2bbed26f97861cf57651d4f2b731964a28cd2257f934a4b452480d21" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.101", ] [[package]] @@ -230,9 +231,9 @@ checksum = "ea8a8b81cacc08888170eef4d13b775126db426d0b348bee9d18c2c1eaf123cf" [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "enum-map" @@ -251,14 +252,14 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.101", ] [[package]] name = "env_filter" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", @@ -266,14 +267,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff", "log", ] @@ -286,6 +287,18 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + [[package]] name = "git2" version = "0.20.1" @@ -313,15 +326,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "humantime" -version = "2.1.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" [[package]] name = "idna" @@ -356,11 +363,11 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi 0.5.0", "libc", "windows-sys", ] @@ -380,12 +387,37 @@ dependencies = [ "either", ] +[[package]] +name = "jiff" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom", "libc", ] @@ -415,9 +447,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" dependencies = [ "cc", "libc", @@ -437,9 +469,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" @@ -502,7 +534,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.101", ] [[package]] @@ -550,9 +582,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "percent-encoding" @@ -562,15 +594,24 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] [[package]] name = "probe" @@ -604,22 +645,28 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rayon" version = "1.10.0" @@ -642,9 +689,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -654,9 +701,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -665,9 +712,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc_version" @@ -680,9 +727,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "scopeguard" @@ -692,9 +739,29 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] [[package]] name = "shlex" @@ -739,7 +806,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.101", ] [[package]] @@ -754,9 +821,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -779,9 +846,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -794,15 +861,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-joining-type" @@ -812,9 +879,9 @@ checksum = "22f8cb47ccb8bc750808755af3071da4a10dcd147b68fc874b7ae4b12543f6f5" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] @@ -854,6 +921,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "winapi" version = "0.3.9" @@ -906,7 +982,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.101", ] [[package]] @@ -917,7 +993,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.101", ] [[package]] @@ -931,9 +1007,9 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] @@ -1001,3 +1077,12 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] diff --git a/mmtk/Cargo.toml b/mmtk/Cargo.toml index 12aa022e..e54cdf40 100644 --- a/mmtk/Cargo.toml +++ b/mmtk/Cargo.toml @@ -16,9 +16,9 @@ lto = true # Metadata for the OpenJDK repository [package.metadata.openjdk] -# Our CI matches the following line and extract mmtk/openjdk. If this line is updated, please check ci yaml files and make sure it works. -openjdk_repo = "https://github.com/mmtk/openjdk.git" -openjdk_version = "28e56ee32525c32c5a88391d0b01f24e5cd16c0f" +# Our CI matches the following line and extract mmtk/jdk. If this line is updated, please check ci yaml files and make sure it works. +openjdk_repo = "https://github.com/mmtk/jdk.git" +openjdk_version = "2632c4f7b5366bed4d0cb91ea5ffe93541a70e30" [dependencies] libc = "0.2" @@ -73,3 +73,4 @@ immix = [] genimmix = [] stickyimmix = [] markcompact = [] +jfr = [] diff --git a/mmtk/src/abi.rs b/mmtk/src/abi.rs index c950f305..0d5855b7 100644 --- a/mmtk/src/abi.rs +++ b/mmtk/src/abi.rs @@ -25,13 +25,15 @@ pub const BITS_IN_LONG: usize = 1 << LOG_BITS_IN_LONG; #[repr(i32)] #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[allow(dead_code)] -pub enum KlassID { +pub enum KlassKind { Instance, InstanceRef, InstanceMirror, InstanceClassLoader, + InstanceStackChunk, TypeArray, ObjArray, + Unknown, } #[repr(i32)] @@ -64,7 +66,8 @@ pub struct Klass { #[cfg(debug_assertions)] valid: i32, pub layout_helper: i32, - pub id: KlassID, + pub kind: KlassKind, + pub modifier_flags: i32, pub super_check_offset: u32, pub name: OpaquePointer, // Symbol* pub secondary_super_cache: &'static Klass, @@ -76,14 +79,13 @@ pub struct Klass { pub next_sibling: &'static Klass, pub next_link: &'static Klass, pub class_loader_data: OpaquePointer, // ClassLoaderData* - pub modifier_flags: i32, - pub access_flags: i32, // AccessFlags - pub trace_id: u64, // JFR_ONLY(traceid _trace_id;) - pub last_biased_lock_bulk_revocation_time: i64, - pub prototype_header: Oop, // markOop, - pub biased_lock_revocation_count: i32, pub vtable_len: i32, - pub shared_class_path_index: i16, + pub access_flags: i32, // AccessFlags + #[cfg(feature = "jfr")] + pub trace_id: u64, // JFR_ONLY(traceid _trace_id;) + pub shared_class_flags: u16, + pub archived_mirror_index: i32, + pub padding: i32, } impl Klass { @@ -120,50 +122,49 @@ pub struct InstanceKlass { pub constants: OpaquePointer, // ConstantPool* pub inner_classes: OpaquePointer, // Array* pub nest_members: OpaquePointer, // Array* - pub nest_host_index: u16, pub nest_host: &'static InstanceKlass, + pub permitted_subclasses: OpaquePointer, // Array* + pub record_components: OpaquePointer, // Array* pub source_debug_extension: OpaquePointer, // const char* - pub array_name: OpaquePointer, // Symbol* pub nonstatic_field_size: i32, pub static_field_size: i32, - pub generic_signature_index: u16, - pub source_file_name_index: u16, - pub static_oop_field_count: u16, - pub java_fields_count: u16, pub nonstatic_oop_map_size: i32, pub itable_len: i32, - pub is_marked_dependent: bool, // bool - pub is_being_redefined: bool, // bool + pub nest_host_index: u16, + pub this_class_index: u16, + pub static_oop_field_count: u16, + pub idnum_allocated_count: u16, + pub init_state: u8, + pub reference_type: ReferenceType, pub misc_flags: u16, - pub minor_version: u16, - pub major_version: u16, + pub init_monitor: OpaquePointer, // Monitor* pub init_thread: OpaquePointer, // Thread* pub oop_map_cache: OpaquePointer, // OopMapCache* pub jni_ids: OpaquePointer, // JNIid* pub methods_jmethod_ids: OpaquePointer, // jmethodID* - pub dep_context: usize, // intptr_t - pub osr_nmethods_head: OpaquePointer, // nmethod* + pub dep_context: OpaquePointer, // nmethodBucket* + pub dep_context_last_cleaned: u64, + pub osr_nmethods_head: OpaquePointer, // nmethod* // #if INCLUDE_JVMTI pub breakpoints: OpaquePointer, // BreakpointInfo* pub previous_versions: OpaquePointer, // InstanceKlass* pub cached_class_file: OpaquePointer, // JvmtiCachedClassFileData* // #endif - pub idnum_allocated_count: u16, - pub init_state: u8, - pub reference_type: ReferenceType, - pub this_class_index: u16, // #if INCLUDE_JVMTI pub jvmti_cached_class_field_map: OpaquePointer, // JvmtiCachedClassFieldMap* // #endif #[cfg(debug_assertions)] verify_count: i32, + #[cfg(debug_assertions)] + _shared_class_load_count: i32, pub methods: OpaquePointer, // Array* pub default_methods: OpaquePointer, // Array* pub local_interfaces: OpaquePointer, // Array* pub transitive_interfaces: OpaquePointer, // Array* pub method_ordering: OpaquePointer, // Array* pub default_vtable_indices: OpaquePointer, // Array* - pub fields: OpaquePointer, // Array* + pub fieldinfo_stream: OpaquePointer, // Array* + pub fields_status: OpaquePointer, // Array* } #[repr(u8)] @@ -237,7 +238,13 @@ impl InstanceMirrorKlass { #[repr(C)] pub struct ArrayKlass { pub klass: Klass, - pub dimension: i32, + // Note that dimension actually is i32 + // However. it shares the same machine word as the Klass.padding in the C++ + // abi + // While in Rust, dimension and padding occupy two separate words + // By changing dimension to have size zero, the remaining fields will + // Have the correct offset into the struct + dimension: (), pub higher_dimension: &'static Klass, pub lower_dimension: &'static Klass, } @@ -490,5 +497,18 @@ pub fn validate_memory_layouts() { ^ mem::size_of::() ^ mem::size_of::() }; + if vm_checksum != binding_checksum { + println!("Rust: Klass {} InstanceKlass {} InstanceRefKlass {} InstanceMirrorKlass {} InstanceClassLoaderKlass {} TypeArrayKlass {} ObjArrayKlass {} ArrayKlass {}", + mem::size_of::() + , mem::size_of::() + , mem::size_of::() + , mem::size_of::() + , mem::size_of::() + , mem::size_of::() + , mem::size_of::() + , mem::size_of::() + ); + panic!("Rust and C++ definitions don't match"); + } assert_eq!(vm_checksum, binding_checksum); } diff --git a/mmtk/src/gc_work.rs b/mmtk/src/gc_work.rs index bde3aff4..f504c3d1 100644 --- a/mmtk/src/gc_work.rs +++ b/mmtk/src/gc_work.rs @@ -35,18 +35,11 @@ macro_rules! scan_roots_work { }; } -scan_roots_work!(ScanUniverseRoots, scan_universe_roots); -scan_roots_work!(ScanJNIHandlesRoots, scan_jni_handle_roots); -scan_roots_work!(ScanObjectSynchronizerRoots, scan_object_synchronizer_roots); -scan_roots_work!(ScanManagementRoots, scan_management_roots); -scan_roots_work!(ScanJvmtiExportRoots, scan_jvmti_export_roots); -scan_roots_work!(ScanAOTLoaderRoots, scan_aot_loader_roots); -scan_roots_work!(ScanSystemDictionaryRoots, scan_system_dictionary_roots); -scan_roots_work!(ScanStringTableRoots, scan_string_table_roots); scan_roots_work!( ScanClassLoaderDataGraphRoots, scan_class_loader_data_graph_roots ); +scan_roots_work!(ScanOopStorageSetRoots, scan_oop_storage_set_roots); scan_roots_work!(ScanWeakProcessorRoots, scan_weak_processor_roots); scan_roots_work!(ScanVMThreadRoots, scan_vm_thread_roots); diff --git a/mmtk/src/lib.rs b/mmtk/src/lib.rs index 3b1f54a2..17917e22 100644 --- a/mmtk/src/lib.rs +++ b/mmtk/src/lib.rs @@ -103,16 +103,9 @@ pub struct OpenJDK_Upcalls { pub dump_object_string: extern "C" fn(object: ObjectReference) -> *const c_char, pub scan_roots_in_all_mutator_threads: extern "C" fn(closure: SlotsClosure), pub scan_roots_in_mutator_thread: extern "C" fn(closure: SlotsClosure, tls: VMMutatorThread), - pub scan_universe_roots: extern "C" fn(closure: SlotsClosure), - pub scan_jni_handle_roots: extern "C" fn(closure: SlotsClosure), - pub scan_object_synchronizer_roots: extern "C" fn(closure: SlotsClosure), - pub scan_management_roots: extern "C" fn(closure: SlotsClosure), - pub scan_jvmti_export_roots: extern "C" fn(closure: SlotsClosure), - pub scan_aot_loader_roots: extern "C" fn(closure: SlotsClosure), - pub scan_system_dictionary_roots: extern "C" fn(closure: SlotsClosure), pub scan_code_cache_roots: extern "C" fn(closure: SlotsClosure), - pub scan_string_table_roots: extern "C" fn(closure: SlotsClosure), pub scan_class_loader_data_graph_roots: extern "C" fn(closure: SlotsClosure), + pub scan_oop_storage_set_roots: extern "C" fn(closure: SlotsClosure), pub scan_weak_processor_roots: extern "C" fn(closure: SlotsClosure), pub scan_vm_thread_roots: extern "C" fn(closure: SlotsClosure), pub number_of_mutators: extern "C" fn() -> usize, diff --git a/mmtk/src/object_model.rs b/mmtk/src/object_model.rs index 09f1b9e0..945b20b2 100644 --- a/mmtk/src/object_model.rs +++ b/mmtk/src/object_model.rs @@ -1,4 +1,4 @@ -use crate::abi::Oop; +use crate::abi::{KlassKind, Oop}; use crate::UPCALLS; use crate::{vm_metadata, OpenJDK}; use mmtk::util::alloc::fill_alignment_gap; @@ -99,9 +99,8 @@ impl ObjectModel> for VMObjectModel< fn is_object_sane(object: ObjectReference) -> bool { let oop = Oop::from(object); - // It is only valid if klass.id is between 0 and 5 (see KlassID in openjdk/src/hotspot/share/oops/klass.hpp) - // If oop.klass is not a valid pointer, we may segfault here. - let klass_id = oop.klass::().id as i32; - (0..6).contains(&klass_id) + // The KlassKind must be one of the known variants, and cannot be InstanceStackChunk which we don't support. + let kind = oop.klass::().kind; + (kind as i32) < (KlassKind::Unknown as i32) && kind != KlassKind::InstanceStackChunk } } diff --git a/mmtk/src/object_scanning.rs b/mmtk/src/object_scanning.rs index c3143c8b..85e667b5 100644 --- a/mmtk/src/object_scanning.rs +++ b/mmtk/src/object_scanning.rs @@ -181,37 +181,43 @@ fn oop_iterate_slow>>( fn oop_iterate(oop: Oop, closure: &mut impl SlotVisitor>) { let klass = oop.klass::(); - let klass_id = klass.id; + let klass_id = klass.kind; assert!( - klass_id as i32 >= 0 && (klass_id as i32) < 6, + klass_id as i32 >= 0 && (klass_id as i32) < KlassKind::Unknown as i32, "Invalid klass-id: {:x} for oop: {:x}", klass_id as i32, unsafe { mem::transmute::(oop) } ); match klass_id { - KlassID::Instance => { + KlassKind::Instance => { let instance_klass = unsafe { klass.cast::() }; instance_klass.oop_iterate::(oop, closure); } - KlassID::InstanceClassLoader => { + KlassKind::InstanceClassLoader => { let instance_klass = unsafe { klass.cast::() }; instance_klass.oop_iterate::(oop, closure); } - KlassID::InstanceMirror => { + KlassKind::InstanceMirror => { let instance_klass = unsafe { klass.cast::() }; instance_klass.oop_iterate::(oop, closure); } - KlassID::ObjArray => { + KlassKind::ObjArray => { let array_klass = unsafe { klass.cast::() }; array_klass.oop_iterate::(oop, closure); } - KlassID::TypeArray => { + KlassKind::TypeArray => { // Skip scanning primitive arrays as they contain no reference fields. } - KlassID::InstanceRef => { + KlassKind::InstanceRef => { let instance_klass = unsafe { klass.cast::() }; instance_klass.oop_iterate::(oop, closure); } + KlassKind::InstanceStackChunk => { + unreachable!("StackChunkOop not supported!") + } + KlassKind::Unknown => { + unreachable!("Unknown KlassKind") + } } } diff --git a/mmtk/src/scanning.rs b/mmtk/src/scanning.rs index 3b0c4aac..33011a55 100644 --- a/mmtk/src/scanning.rs +++ b/mmtk/src/scanning.rs @@ -77,16 +77,9 @@ impl Scanning> for VMScanning { crate::singleton::(), WorkBucketStage::Prepare, vec![ - Box::new(ScanUniverseRoots::new(factory.clone())) as _, - Box::new(ScanJNIHandlesRoots::new(factory.clone())) as _, - Box::new(ScanObjectSynchronizerRoots::new(factory.clone())) as _, - Box::new(ScanManagementRoots::new(factory.clone())) as _, - Box::new(ScanJvmtiExportRoots::new(factory.clone())) as _, - Box::new(ScanAOTLoaderRoots::new(factory.clone())) as _, - Box::new(ScanSystemDictionaryRoots::new(factory.clone())) as _, Box::new(ScanCodeCacheRoots::new(factory.clone())) as _, - Box::new(ScanStringTableRoots::new(factory.clone())) as _, Box::new(ScanClassLoaderDataGraphRoots::new(factory.clone())) as _, + Box::new(ScanOopStorageSetRoots::new(factory.clone())) as _, // FIXME17: Several removed roots are all put to this work packet, may cause slowdown. Box::new(ScanWeakProcessorRoots::new(factory.clone())) as _, Box::new(ScanVMThreadRoots::new(factory)) as _, ], diff --git a/openjdk/CompileThirdPartyHeap.gmk b/openjdk/CompileThirdPartyHeap.gmk index 6897277a..c44ba301 100644 --- a/openjdk/CompileThirdPartyHeap.gmk +++ b/openjdk/CompileThirdPartyHeap.gmk @@ -51,6 +51,14 @@ ifeq ($(MMTK_EXTREME_ASSERTIONS), 1) endif endif +ifeq ($(call check-jvm-feature, jfr), true) + ifndef GC_FEATURES + GC_FEATURES=--features jfr + else + GC_FEATURES:=$(strip $(GC_FEATURES))",jfr" + endif +endif + ifeq ($(MMTK_MALLOC_MARK_SWEEP), 1) ifndef GC_FEATURES GC_FEATURES=--features malloc_mark_sweep @@ -76,15 +84,37 @@ else CARGO_PROFILE = debug endif +CARGO_EXECUTABLE = cargo +CARGO_TARGET = . +CARGO_TARGET_FLAG = + +ifeq ($(COMPILE_TYPE), cross) + ifneq ($(CREATING_BUILDJDK), true) + # Set the CARGO_TARGET based on the architecture + ifeq ($(OPENJDK_TARGET_CPU), riscv64) + CARGO_TARGET = riscv64gc-unknown-linux-gnu + else ifeq ($(OPENJDK_TARGET_CPU), aarch64) + CARGO_TARGET = aarch64-unknown-linux-gnu + else + CARGO_TARGET = UNSUPPORTED_MMTK_OPENJDK_TARGET_CPU + endif + CARGO_EXECUTABLE = cross + CARGO_TARGET_FLAG = --target $(CARGO_TARGET) + endif +endif $(LIB_MMTK): FORCE if [[ "$(OPENJDK_VERSION)" != "$(OPENJDK_LOCAL_VERSION)" ]]; then \ echo -e $(YELLOW)WARNING: Local OpenJDK version does not match version specified in mmtk/Cargo.toml$(NC); \ echo -e $(YELLOW)Local OpenJDK version $(OPENJDK_LOCAL_VERSION)$(NC); \ echo -e $(YELLOW)mmtk/Cargo.toml OpenJDK version $(OPENJDK_VERSION)$(NC); \ fi - echo "cd $(MMTK_RUST_ROOT) && cargo --version && cargo build $(CARGO_PROFILE_FLAG) --target $(HOST_TRIPLE) $(GC_FEATURES)" - cd $(MMTK_RUST_ROOT) && cargo --version && cargo build $(CARGO_PROFILE_FLAG) --target $(HOST_TRIPLE) $(GC_FEATURES) - cp $(MMTK_RUST_ROOT)/target/$(HOST_TRIPLE)/$(CARGO_PROFILE)/libmmtk_openjdk.so $(LIB_MMTK) + if [[ "$(OPENJDK_TARGET_CPU)" != "riscv64" ]] && [[ "$(OPENJDK_TARGET_CPU)" != "aarch64" ]] && [[ $(CARGO_EXECUTABLE) == "cross" ]]; then \ + echo -e "Only cross compiling to riscv64/aarch64 are supported"; \ + exit 1; \ + fi + echo "cd $(MMTK_RUST_ROOT) && $(CARGO_EXECUTABLE) --version && $(CARGO_EXECUTABLE) build $(CARGO_TARGET_FLAG) $(CARGO_PROFILE_FLAG) $(GC_FEATURES)" + cd $(MMTK_RUST_ROOT) && $(CARGO_EXECUTABLE) --version && $(CARGO_EXECUTABLE) build $(CARGO_TARGET_FLAG) $(CARGO_PROFILE_FLAG) $(GC_FEATURES) + mkdir -p $(JVM_LIB_OUTPUTDIR) && cp $(MMTK_RUST_ROOT)/target/$(CARGO_TARGET)/$(CARGO_PROFILE)/libmmtk_openjdk.so $(LIB_MMTK) JVM_LIBS += -L$(JVM_LIB_OUTPUTDIR) -lmmtk_openjdk JVM_LDFLAGS += '-Wl,-rpath,$$ORIGIN' @@ -92,8 +122,8 @@ JVM_LDFLAGS += '-Wl,-rpath,$$ORIGIN' FORCE: TARGETS += $(LIB_MMTK) -JVM_SRC_DIRS += $(MMTK_CPP_ROOT) $(MMTK_CPP_ROOT)/barriers -JVM_CFLAGS += -std=c++11 -DINCLUDE_THIRD_PARTY_HEAP -DTHIRD_PARTY_HEAP_SRC=$(MMTK_CPP_ROOT) +JVM_SRC_DIRS += $(MMTK_CPP_ROOT)/share $(MMTK_CPP_ROOT)/share/barriers $(MMTK_CPP_ROOT)/cpu/$(HOTSPOT_TARGET_CPU_ARCH) +JVM_CFLAGS += -std=c++14 -fpermissive -DINCLUDE_THIRD_PARTY_HEAP -DTHIRD_PARTY_HEAP_SRC=$(MMTK_CPP_ROOT)/share -I$(MMTK_CPP_ROOT)/share -I$(MMTK_CPP_ROOT)/cpu/$(HOTSPOT_TARGET_CPU_ARCH) ifeq ($(MMTK_VO_BIT), 1) JVM_CFLAGS += -DMMTK_ENABLE_VO_BIT endif diff --git a/openjdk/cpu/aarch64/mmtkBarrierSetAssembler_aarch64.cpp b/openjdk/cpu/aarch64/mmtkBarrierSetAssembler_aarch64.cpp new file mode 100644 index 00000000..62ac5b3e --- /dev/null +++ b/openjdk/cpu/aarch64/mmtkBarrierSetAssembler_aarch64.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2018, 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 + * 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 "asm/macroAssembler.inline.hpp" +#include "interpreter/interp_masm.hpp" +#include "mmtkBarrierSet.hpp" +#include "mmtkBarrierSetAssembler_aarch64.hpp" +#include "mmtkBarrierSetC1.hpp" +#include "mmtkMutator.hpp" +#include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" +#include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" + +#define __ masm-> + +void MMTkBarrierSetAssembler::eden_allocate(MacroAssembler* masm, Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register tmp1, Register tmp2, Label& slow_case) { + // XXX tmp1 seems to be -1 + assert_different_registers(obj, tmp2); + assert_different_registers(obj, var_size_in_bytes); + assert(tmp2->is_valid(), "need temp reg"); + + if (!MMTK_ENABLE_ALLOCATION_FASTPATH) { + __ b(slow_case); + } else { + // printf("generating mmtk allocation fast path\n"); + // MMTk size check. If the alloc size is larger than the allowed max size for non los, + // we jump to slow path and allodate with LOS in slowpath. + // Note that OpenJDK has a slow path check. Search for layout_helper_needs_slow_path and FastAllocateSizeLimit. + // I tried to set FastAllocateSizeLimit in MMTkHeap::initialize(). But there are still large objects allocated into the + // default space. + assert(MMTkMutatorContext::max_non_los_default_alloc_bytes != 0, "max_non_los_default_alloc_bytes hasn't been initialized"); + size_t max_non_los_bytes = MMTkMutatorContext::max_non_los_default_alloc_bytes; + size_t extra_header = 0; + // fastpath, we only use default allocator + Allocator allocator = AllocatorDefault; + // We need to figure out which allocator we are using by querying MMTk. + AllocatorSelector selector = get_allocator_mapping(allocator); + + // XXX riscv: disallow markcompact and global alloc bit for now + assert(selector.tag != TAG_MARK_COMPACT, "mark compact not supported for now"); + + if (var_size_in_bytes == noreg) { + // constant alloc size. If it is larger than max_non_los_bytes, we directly go to slowpath. + if ((size_t)con_size_in_bytes > max_non_los_bytes - extra_header) { + __ b(slow_case); + return; + } + } else { + // var alloc size. We compare with max_non_los_bytes and conditionally jump to slowpath. + // printf("max_non_los_bytes %lu\n",max_non_los_bytes); + __ movi(rscratch1, max_non_los_bytes - extra_header); + __ cmp(rscratch1, var_size_in_bytes); + __ br(Assembler::LT, slow_case); + } + + if (selector.tag == TAG_MALLOC || selector.tag == TAG_LARGE_OBJECT) { + __ b(slow_case); + return; + } + + // Calculate offsets of TLAB top and end + Address cursor, limit; + MMTkAllocatorOffsets alloc_offsets = get_tlab_top_and_end_offsets(selector); + + cursor = Address(rthread, alloc_offsets.tlab_top_offset); + limit = Address(rthread, alloc_offsets.tlab_end_offset); + + __ ldr(obj, cursor); + Register end = tmp2; + if (var_size_in_bytes == noreg) { + __ lea(end, Address(obj, con_size_in_bytes)); + } else { + __ lea(end, Address(obj, var_size_in_bytes)); + } + // slowpath if end < obj + __ cmp(end, obj); + __ br(Assembler::LS, slow_case); + // slowpath if end > lab.limit + __ ldr(rscratch1, limit); + // XXX debug use, force slow path + // __ cmp(end, zr); + __ cmp(end, rscratch1); + __ br(Assembler::HI, slow_case); + + // lab.cursor = end + __ str(end, cursor); + + // recover var_size_in_bytes if necessary + if (var_size_in_bytes == end) { + __ sub(var_size_in_bytes, var_size_in_bytes, obj); + } + // if the above is removed, and the register holding the object size is + // clobbered, operations that rely on the size, such as array copy will + // crash + + // XXX debug use, force segfault to disassemble in gdb + // __ ld(t0, zr); + + // XXX debug use, force double allocation + // __ j(slow_case); + + #ifdef MMTK_ENABLE_GLOBAL_ALLOC_BIT + assert(false, "global alloc bit not supported"); + #endif + } +} + +#undef __ + +#define __ sasm-> + +void MMTkBarrierSetAssembler::generate_c1_write_barrier_runtime_stub(StubAssembler* sasm) const { + // printf("xxx MMTkBarrierSetAssembler::generate_c1_write_barrier_runtime_stub\n"); + // See also void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) + __ prologue("mmtk_write_barrier", false); + + Label done, runtime; + + // void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) + // ld(reg, Address(fp, offset_in_words * BytesPerWord)); + // ra is free to use here, because call prologue/epilogue handles it + // Zheyuan: Code works by swaping rscratch2 and rscratch1, and I dont know why + const Register src = rscratch2; + const Register slot = rscratch1; + const Register new_val = lr; + __ load_parameter(0, src); + __ load_parameter(1, slot); + __ load_parameter(2, new_val); + + __ bind(runtime); + + // Push integer registers x7, x10-x17, x28-x31. + // t2, a0-a7, t3-t6 + __ push_call_clobbered_registers(); + +#if MMTK_ENABLE_BARRIER_FASTPATH + __ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_slow_call), src, slot, new_val); +#else + __ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_post_call), src, slot, new_val); +#endif + + __ pop_call_clobbered_registers(); + + __ bind(done); + + __ epilogue(); +} + +#undef __ + +#define __ ce->masm()-> + +void MMTkBarrierSetAssembler::generate_c1_write_barrier_stub_call(LIR_Assembler* ce, MMTkC1BarrierStub* stub) { + // printf("xxx MMTkBarrierSetAssembler::generate_c1_write_barrier_stub_call\n"); + // See also void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) + MMTkBarrierSetC1* bs = (MMTkBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1(); + __ bind(*stub->entry()); + assert(stub->src->is_register(), "Precondition"); + assert(stub->slot->is_register(), "Precondition"); + assert(stub->new_val->is_register(), "Precondition"); + ce->store_parameter(stub->src->as_pointer_register(), 0); + ce->store_parameter(stub->slot->as_pointer_register(), 1); + ce->store_parameter(stub->new_val->as_pointer_register(), 2); + __ far_call(RuntimeAddress(bs->_write_barrier_c1_runtime_code_blob->code_begin())); + __ b(*stub->continuation()); +} + +#undef __ diff --git a/openjdk/cpu/aarch64/mmtkBarrierSetAssembler_aarch64.hpp b/openjdk/cpu/aarch64/mmtkBarrierSetAssembler_aarch64.hpp new file mode 100644 index 00000000..db9b53d1 --- /dev/null +++ b/openjdk/cpu/aarch64/mmtkBarrierSetAssembler_aarch64.hpp @@ -0,0 +1,50 @@ +#ifndef MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_AARCH64_HPP +#define MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_AARCH64_HPP + +#include "asm/macroAssembler.hpp" +#include "gc/shared/barrierSetAssembler.hpp" + +class MMTkBarrierSetC1; +class MMTkC1BarrierStub; +class LIR_Assembler; +class StubAssembler; + +class MMTkBarrierSetAssembler: public BarrierSetAssembler { + friend class MMTkBarrierSetC1; + +protected: + /// Full pre-barrier + virtual void object_reference_write_pre(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const {} + /// Full post-barrier + virtual void object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const {} + + /// Barrier elision test + virtual bool can_remove_barrier(DecoratorSet decorators, Register val, bool skip_const_null) const { + bool in_heap = (decorators & IN_HEAP) != 0; + bool as_normal = (decorators & AS_NORMAL) != 0; + assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported"); + return !in_heap || (skip_const_null && val == noreg); + } + + /// Generate C1 write barrier slow-call assembly code + virtual void generate_c1_write_barrier_runtime_stub(StubAssembler* sasm) const; + +public: + virtual void eden_allocate(MacroAssembler* masm, + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register tmp1, // temp register + Register tmp2, // temp register + Label& slow_case // continuation point if fast allocation fails + ); + virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { + if (type == T_OBJECT || type == T_ARRAY) object_reference_write_pre(masm, decorators, dst, val, tmp1, tmp2); + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); + if (type == T_OBJECT || type == T_ARRAY) object_reference_write_post(masm, decorators, dst, val, tmp1, tmp2); + } + + /// Generate C1 write barrier slow-call stub + static void generate_c1_write_barrier_stub_call(LIR_Assembler* ce, MMTkC1BarrierStub* stub); +}; +#endif // MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_AARCH64_HPP diff --git a/openjdk/cpu/aarch64/mmtkNoBarrierSetAssembler_aarch64.hpp b/openjdk/cpu/aarch64/mmtkNoBarrierSetAssembler_aarch64.hpp new file mode 100644 index 00000000..6d61c267 --- /dev/null +++ b/openjdk/cpu/aarch64/mmtkNoBarrierSetAssembler_aarch64.hpp @@ -0,0 +1,5 @@ +#ifndef MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_AARCH64_HPP +#define MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_AARCH64_HPP + +class MMTkNoBarrierSetAssembler: public MMTkBarrierSetAssembler {}; +#endif // MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_AARCH64_HPP diff --git a/openjdk/cpu/aarch64/mmtkObjectBarrierSetAssembler_aarch64.cpp b/openjdk/cpu/aarch64/mmtkObjectBarrierSetAssembler_aarch64.cpp new file mode 100644 index 00000000..ebdc50ff --- /dev/null +++ b/openjdk/cpu/aarch64/mmtkObjectBarrierSetAssembler_aarch64.cpp @@ -0,0 +1,69 @@ +#include "precompiled.hpp" +#include "mmtkObjectBarrier.hpp" +#include "runtime/interfaceSupport.inline.hpp" + +#define __ masm-> + +void MMTkObjectBarrierSetAssembler::object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const { + // tmp1 and tmp2 is from MacroAssembler::access_store_at + // For do_oop_store, we have three tmps, x28/t3, x29/t4, x13/a3 + // printf("object_reference_write_post\n"); +// if (can_remove_barrier(decorators, val, /* skip_const_null */ true)) return; + if (can_remove_barrier(decorators, val, /* skip_const_null */ true)) return; + Register obj = dst.base(); + +#if MMTK_ENABLE_BARRIER_FASTPATH + Label done; + + assert_different_registers(obj, tmp1, tmp2); + assert_different_registers(val, tmp1, tmp2); + assert(tmp1->is_valid(), "need temp reg"); + assert(tmp2->is_valid(), "need temp reg"); + // tmp1 = load-byte (SIDE_METADATA_BASE_ADDRESS + (obj >> 6)); + __ mov(tmp1, obj); + __ lsr(tmp1, tmp1, 6); // tmp1 = obj >> 6; + __ mov(tmp2, SIDE_METADATA_BASE_ADDRESS); + __ add(tmp1, tmp1, tmp2); // tmp1 = SIDE_METADATA_BASE_ADDRESS + (obj >> 6); + __ ldrb(tmp1, Address(tmp1, 0)); + // tmp2 = (obj >> 3) & 7 + __ mov(tmp2, obj); + __ lsr(tmp2, tmp2, 3); + __ andr(tmp2, tmp2, 7); + // tmp1 = tmp1 >> tmp2 + __ lsrv(tmp1, tmp1, tmp2); + // if ((tmp1 & 1) == 1) fall through to slowpath; + // equivalently ((tmp1 & 1) == 0) go to done + __ andr(tmp1, tmp1, 1); + __ cbz(tmp1, done); + // setup calling convention + __ mov(c_rarg0, obj); + __ lea(c_rarg1, dst); + __ mov(c_rarg2, val == noreg ? zr : val); + __ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_slow_call), 3); + + __ bind(done); +#else + __ mov(c_rarg0, obj); + __ lea(c_rarg1, dst); + __ mov(c_rarg2, val == noreg ? zr : val); + __ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_post_call), 3); +#endif +} + +void MMTkObjectBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, Register tmp, RegSet saved_regs) { + // see also void G1BarrierSetAssembler::gen_write_ref_array_post_barrier + assert_different_registers(src, dst, count); + // const bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; + // if (is_oop && !dest_uninitialized) { + if (is_oop){ + __ push(saved_regs, sp); + __ mov(c_rarg1, dst); + __ mov(c_rarg2, count); + __ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_array_copy_post_call), 3); + __ pop(saved_regs, sp); + } +} + + +#undef __ diff --git a/openjdk/cpu/aarch64/mmtkObjectBarrierSetAssembler_aarch64.hpp b/openjdk/cpu/aarch64/mmtkObjectBarrierSetAssembler_aarch64.hpp new file mode 100644 index 00000000..c6334a49 --- /dev/null +++ b/openjdk/cpu/aarch64/mmtkObjectBarrierSetAssembler_aarch64.hpp @@ -0,0 +1,11 @@ +#ifndef MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_AARCH64_HPP +#define MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_AARCH64_HPP + +class MMTkObjectBarrierSetAssembler: public MMTkBarrierSetAssembler { +protected: + virtual void object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const override; +public: + virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, Register tmp, RegSet saved_regs) override; +}; +#endif // MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_AARCH64_HPP diff --git a/openjdk/cpu/riscv/mmtkBarrierSetAssembler_riscv.cpp b/openjdk/cpu/riscv/mmtkBarrierSetAssembler_riscv.cpp new file mode 100644 index 00000000..b60e3405 --- /dev/null +++ b/openjdk/cpu/riscv/mmtkBarrierSetAssembler_riscv.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2018, 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 + * 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 "asm/macroAssembler.inline.hpp" +#include "interpreter/interp_masm.hpp" +#include "mmtkBarrierSet.hpp" +#include "mmtkBarrierSetAssembler_riscv.hpp" +#include "mmtkBarrierSetC1.hpp" +#include "mmtkMutator.hpp" +#include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" +#include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" + +#define __ masm-> + +void MMTkBarrierSetAssembler::eden_allocate(MacroAssembler* masm, Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register tmp1, Register tmp2, Label& slow_case, bool is_far) { + // XXX tmp1 seems to be -1 + assert_different_registers(obj, tmp2); + assert_different_registers(obj, var_size_in_bytes); + assert(tmp2->is_valid(), "need temp reg"); + + if (!MMTK_ENABLE_ALLOCATION_FASTPATH) { + __ j(slow_case); + } else { + // printf("generating mmtk allocation fast path\n"); + // MMTk size check. If the alloc size is larger than the allowed max size for non los, + // we jump to slow path and allodate with LOS in slowpath. + // Note that OpenJDK has a slow path check. Search for layout_helper_needs_slow_path and FastAllocateSizeLimit. + // I tried to set FastAllocateSizeLimit in MMTkHeap::initialize(). But there are still large objects allocated into the + // default space. + assert(MMTkMutatorContext::max_non_los_default_alloc_bytes != 0, "max_non_los_default_alloc_bytes hasn't been initialized"); + size_t max_non_los_bytes = MMTkMutatorContext::max_non_los_default_alloc_bytes; + size_t extra_header = 0; + // fastpath, we only use default allocator + Allocator allocator = AllocatorDefault; + // We need to figure out which allocator we are using by querying MMTk. + AllocatorSelector selector = get_allocator_mapping(allocator); + + // XXX riscv: disallow markcompact and global alloc bit for now + assert(selector.tag != TAG_MARK_COMPACT, "mark compact not supported for now"); + + if (var_size_in_bytes == noreg) { + // constant alloc size. If it is larger than max_non_los_bytes, we directly go to slowpath. + if ((size_t)con_size_in_bytes > max_non_los_bytes - extra_header) { + __ j(slow_case); + return; + } + } else { + // var alloc size. We compare with max_non_los_bytes and conditionally jump to slowpath. + // printf("max_non_los_bytes %lu\n",max_non_los_bytes); + __ li(t0, max_non_los_bytes - extra_header); + __ bgeu(var_size_in_bytes, t0, slow_case, is_far); + } + + if (selector.tag == TAG_MALLOC || selector.tag == TAG_LARGE_OBJECT) { + __ j(slow_case); + return; + } + + // Calculate offsets of TLAB top and end + Address cursor, limit; + MMTkAllocatorOffsets alloc_offsets = get_tlab_top_and_end_offsets(selector); + + cursor = Address(xthread, alloc_offsets.tlab_top_offset); + limit = Address(xthread, alloc_offsets.tlab_end_offset); + + // XXX disassembly + // 0x7fffe85597e0: ld a0,688(s7) + // 0x7fffe85597e4: add a1,a0,a3 + // 0x7fffe85597e8: bltu a1,a0,0x7fffe8559878 + // 0x7fffe85597ec: ld t0,696(s7) + // 0x7fffe85597f0: bltu t0,a1,0x7fffe8559878 + // 0x7fffe85597f4: sd a1,688(s7) + + // obj = load lab.cursor + __ ld(obj, cursor); + // end = obj + size + Register end = tmp2; + if (var_size_in_bytes == noreg) { + __ la(end, Address(obj, con_size_in_bytes)); + } else { + __ add(end, obj, var_size_in_bytes); + } + // slowpath if end < obj + __ bltu(end, obj, slow_case, is_far); + // slowpath if end > lab.limit + __ ld(t0, limit); + // XXX debug use, force slow path + // __ bgtu(end, zr, slow_case, is_far); + __ bgtu(end, t0, slow_case, is_far); + // lab.cursor = end + __ sd(end, cursor); + + // recover var_size_in_bytes if necessary + if (var_size_in_bytes == end) { + __ sub(var_size_in_bytes, var_size_in_bytes, obj); + } + // if the above is removed, and the register holding the object size is + // clobbered, operations that rely on the size, such as array copy will + // crash + + // XXX debug use, force segfault to disassemble in gdb + // __ ld(t0, zr); + + // XXX debug use, force double allocation + // __ j(slow_case); + + #ifdef MMTK_ENABLE_GLOBAL_ALLOC_BIT + assert(false, "global alloc bit not supported"); + #endif + } +} + +#undef __ + +#define __ sasm-> + +void MMTkBarrierSetAssembler::generate_c1_write_barrier_runtime_stub(StubAssembler* sasm) const { + // printf("xxx MMTkBarrierSetAssembler::generate_c1_write_barrier_runtime_stub\n"); + // See also void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) + __ prologue("mmtk_write_barrier", false); + + Label done, runtime; + + // void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) + // ld(reg, Address(fp, offset_in_words * BytesPerWord)); + // ra is free to use here, because call prologue/epilogue handles it + const Register src = t0; + const Register slot = t1; + const Register new_val = ra; + __ load_parameter(0, src); + __ load_parameter(1, slot); + __ load_parameter(2, new_val); + + __ bind(runtime); + + // Push integer registers x7, x10-x17, x28-x31. + // t2, a0-a7, t3-t6 + __ push_call_clobbered_registers(); + +#if MMTK_ENABLE_BARRIER_FASTPATH + __ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_slow_call), src, slot, new_val); +#else + __ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_post_call), src, slot, new_val); +#endif + + __ pop_call_clobbered_registers(); + + __ bind(done); + + __ epilogue(); +} + +#undef __ + +#define __ ce->masm()-> + +void MMTkBarrierSetAssembler::generate_c1_write_barrier_stub_call(LIR_Assembler* ce, MMTkC1BarrierStub* stub) { + // printf("xxx MMTkBarrierSetAssembler::generate_c1_write_barrier_stub_call\n"); + // See also void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) + MMTkBarrierSetC1* bs = (MMTkBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1(); + __ bind(*stub->entry()); + assert(stub->src->is_register(), "Precondition"); + assert(stub->slot->is_register(), "Precondition"); + assert(stub->new_val->is_register(), "Precondition"); + // LIR_Assembler::store_parameter(Register r, int offset_from_rsp_in_words) + // __ sd(r, Address(sp, offset_from_rsp_in_bytes)); + ce->store_parameter(stub->src->as_pointer_register(), 0); + ce->store_parameter(stub->slot->as_pointer_register(), 1); + ce->store_parameter(stub->new_val->as_pointer_register(), 2); + __ far_call(RuntimeAddress(bs->_write_barrier_c1_runtime_code_blob->code_begin())); + __ j(*stub->continuation()); +} + +#undef __ diff --git a/openjdk/cpu/riscv/mmtkBarrierSetAssembler_riscv.hpp b/openjdk/cpu/riscv/mmtkBarrierSetAssembler_riscv.hpp new file mode 100644 index 00000000..8fa14e8c --- /dev/null +++ b/openjdk/cpu/riscv/mmtkBarrierSetAssembler_riscv.hpp @@ -0,0 +1,51 @@ +#ifndef MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_RISCV_HPP +#define MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_RISCV_HPP + +#include "asm/macroAssembler.hpp" +#include "gc/shared/barrierSetAssembler.hpp" + +class MMTkBarrierSetC1; +class MMTkC1BarrierStub; +class LIR_Assembler; +class StubAssembler; + +class MMTkBarrierSetAssembler: public BarrierSetAssembler { + friend class MMTkBarrierSetC1; + +protected: + /// Full pre-barrier + virtual void object_reference_write_pre(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const {} + /// Full post-barrier + virtual void object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const {} + + /// Barrier elision test + virtual bool can_remove_barrier(DecoratorSet decorators, Register val, bool skip_const_null) const { + bool in_heap = (decorators & IN_HEAP) != 0; + bool as_normal = (decorators & AS_NORMAL) != 0; + assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported"); + return !in_heap || (skip_const_null && val == noreg); + } + + /// Generate C1 write barrier slow-call assembly code + virtual void generate_c1_write_barrier_runtime_stub(StubAssembler* sasm) const; + +public: + virtual void eden_allocate(MacroAssembler* masm, + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register tmp1, // temp register + Register tmp2, // temp register + Label& slow_case, // continuation point if fast allocation fails + bool is_far = false + ) override; + virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { + if (type == T_OBJECT || type == T_ARRAY) object_reference_write_pre(masm, decorators, dst, val, tmp1, tmp2); + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); + if (type == T_OBJECT || type == T_ARRAY) object_reference_write_post(masm, decorators, dst, val, tmp1, tmp2); + } + + /// Generate C1 write barrier slow-call stub + static void generate_c1_write_barrier_stub_call(LIR_Assembler* ce, MMTkC1BarrierStub* stub); +}; +#endif // MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_RISCV_HPP diff --git a/openjdk/cpu/riscv/mmtkNoBarrierSetAssembler_riscv.hpp b/openjdk/cpu/riscv/mmtkNoBarrierSetAssembler_riscv.hpp new file mode 100644 index 00000000..ec851a6e --- /dev/null +++ b/openjdk/cpu/riscv/mmtkNoBarrierSetAssembler_riscv.hpp @@ -0,0 +1,5 @@ +#ifndef MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_RISCV_HPP +#define MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_RISCV_HPP + +class MMTkNoBarrierSetAssembler: public MMTkBarrierSetAssembler {}; +#endif // MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_RISCV_HPP diff --git a/openjdk/cpu/riscv/mmtkObjectBarrierSetAssembler_riscv.cpp b/openjdk/cpu/riscv/mmtkObjectBarrierSetAssembler_riscv.cpp new file mode 100644 index 00000000..4781c32e --- /dev/null +++ b/openjdk/cpu/riscv/mmtkObjectBarrierSetAssembler_riscv.cpp @@ -0,0 +1,100 @@ +#include "precompiled.hpp" +#include "mmtkObjectBarrier.hpp" +#include "runtime/interfaceSupport.inline.hpp" + +#define __ masm-> + +// extern void object_reference_write_slow_call(void* obj, void* dst, uint64_t val); + +// void write_post(char* SIDE_METADATA_BASE_ADDRESS, void* obj, uint64_t val) { +// char tmp2 = *(SIDE_METADATA_BASE_ADDRESS + ((uint64_t)obj >> 6)); +// char tmp3 = ((uint64_t)obj >> 3) & 7; +// tmp2 = tmp2 >> tmp3; +// if ((tmp2 & 1) == 1) { +// object_reference_write_slow_call(obj, 0, val); +// } +// } + +// write_post(char*, void*, unsigned long): +// srli a5,a1,6 +// add a0,a0,a5 +// lbu a5,0(a0) +// srli a3,a1,3 +// andi a3,a3,7 +// sraw a5,a5,a3 +// andi a5,a5,1 +// mv a4,a1 +// bne a5,zero,.L4 +// ret +// .L4: +// li a1,0 +// mv a0,a4 +// tail _Z32object_reference_write_slow_callPvS_m +void MMTkObjectBarrierSetAssembler::object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const { + // tmp1 and tmp2 is from MacroAssembler::access_store_at + // For do_oop_store, we have three tmps, x28/t3, x29/t4, x13/a3 + // printf("object_reference_write_post\n"); +// if (can_remove_barrier(decorators, val, /* skip_const_null */ true)) return; + Register obj = dst._obj_start; + assert(obj->is_valid(), "RISC-V template interpreter originally passes the slot instead of the object reference. MMTk barriers require the object reference."); + // see void G1BarrierSetAssembler::g1_write_barrier_post + // the slot is still alive after the post barrier + if (dst.base()->is_valid()) { + __ push_reg(dst.base()); + } + +#if MMTK_ENABLE_BARRIER_FASTPATH + Label done; + assert_different_registers(obj, tmp1, tmp2); + assert_different_registers(val, tmp1, tmp2); + assert(tmp1->is_valid(), "need temp reg"); + assert(tmp2->is_valid(), "need temp reg"); + // tmp1 = load-byte (SIDE_METADATA_BASE_ADDRESS + (obj >> 6)); + __ mv(tmp1, obj); + __ srli(tmp1, tmp1, 6); // tmp1 = obj >> 6; + __ li(tmp2, SIDE_METADATA_BASE_ADDRESS); + __ add(tmp1, tmp1, tmp2); // tmp1 = SIDE_METADATA_BASE_ADDRESS + (obj >> 6); + __ lbu(tmp1, Address(tmp1, 0)); + // tmp2 = (obj >> 3) & 7 + __ mv(tmp2, obj); + __ srli(tmp2, tmp2, 3); + __ andi(tmp2, tmp2, 7); + // tmp1 = tmp1 >> tmp2 + __ sraw(tmp1, tmp1, tmp2); + // if ((tmp1 & 1) == 1) fall through to slowpath; + // equivalently ((tmp1 & 1) == 0) go to done + __ andi(tmp1, tmp1, 1); + __ beqz(tmp1, done); + // setup calling convention + __ mv(c_rarg0, obj); + __ la(c_rarg1, dst); + __ mv(c_rarg2, val == noreg ? zr : val); + __ call_VM_leaf_base(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_slow_call), 3); + + __ bind(done); +#else + __ mv(c_rarg0, obj); + __ la(c_rarg1, dst); + __ mv(c_rarg2, val == noreg ? zr : val); + __ call_VM_leaf_base(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_post_call), 3); +#endif + if (dst.base()->is_valid()) { + __ pop_reg(dst.base()); + } +} + +void MMTkObjectBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, Register tmp, RegSet saved_regs) { + // see also void G1BarrierSetAssembler::gen_write_ref_array_post_barrier + assert_different_registers(src, dst, count); + // const bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; + // if (is_oop && !dest_uninitialized) { + if (is_oop) { + // in address generate_checkcast_copy, caller tells us to save count + __ push_reg(saved_regs, sp); + __ call_VM_leaf(FN_ADDR(MMTkBarrierSetRuntime::object_reference_array_copy_post_call), zr, dst, count); + __ pop_reg(saved_regs, sp); + } +} + +#undef __ diff --git a/openjdk/cpu/riscv/mmtkObjectBarrierSetAssembler_riscv.hpp b/openjdk/cpu/riscv/mmtkObjectBarrierSetAssembler_riscv.hpp new file mode 100644 index 00000000..ca7a9ca2 --- /dev/null +++ b/openjdk/cpu/riscv/mmtkObjectBarrierSetAssembler_riscv.hpp @@ -0,0 +1,11 @@ +#ifndef MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_RISCV_HPP +#define MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_RISCV_HPP + +class MMTkObjectBarrierSetAssembler: public MMTkBarrierSetAssembler { +protected: + virtual void object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2) const override; +public: + virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, Register tmp, RegSet saved_regs) override; +}; +#endif // MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_RISCV_HPP diff --git a/openjdk/mmtkBarrierSetAssembler_x86.cpp b/openjdk/cpu/x86/mmtkBarrierSetAssembler_x86.cpp similarity index 99% rename from openjdk/mmtkBarrierSetAssembler_x86.cpp rename to openjdk/cpu/x86/mmtkBarrierSetAssembler_x86.cpp index dc59274e..d810b7af 100644 --- a/openjdk/mmtkBarrierSetAssembler_x86.cpp +++ b/openjdk/cpu/x86/mmtkBarrierSetAssembler_x86.cpp @@ -21,7 +21,6 @@ * questions. * */ - #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "interpreter/interp_masm.hpp" @@ -32,6 +31,7 @@ #include "runtime/sharedRuntime.hpp" #include "utilities/macros.hpp" #include "c1/c1_LIRAssembler.hpp" +#include "c1/c1_MacroAssembler.hpp" #define __ masm-> diff --git a/openjdk/mmtkBarrierSetAssembler_x86.hpp b/openjdk/cpu/x86/mmtkBarrierSetAssembler_x86.hpp similarity index 97% rename from openjdk/mmtkBarrierSetAssembler_x86.hpp rename to openjdk/cpu/x86/mmtkBarrierSetAssembler_x86.hpp index 383b688f..0844ae35 100644 --- a/openjdk/mmtkBarrierSetAssembler_x86.hpp +++ b/openjdk/cpu/x86/mmtkBarrierSetAssembler_x86.hpp @@ -32,9 +32,9 @@ class MMTkBarrierSetAssembler: public BarrierSetAssembler { public: virtual void eden_allocate(MacroAssembler* masm, Register thread, Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Label& slow_case) override; - virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2) override { + virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { if (type == T_OBJECT || type == T_ARRAY) object_reference_write_pre(masm, decorators, dst, val, tmp1, tmp2); - BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); // BarrierSetAssembler::store_at modifies val and make it compressed if UseCompressedOops is true. // We need to compensate for this change and decode it in object_reference_write_post. if (type == T_OBJECT || type == T_ARRAY) object_reference_write_post(masm, decorators, dst, val, tmp1, tmp2, true); diff --git a/openjdk/cpu/x86/mmtkNoBarrierSetAssembler_x86.hpp b/openjdk/cpu/x86/mmtkNoBarrierSetAssembler_x86.hpp new file mode 100644 index 00000000..8340627b --- /dev/null +++ b/openjdk/cpu/x86/mmtkNoBarrierSetAssembler_x86.hpp @@ -0,0 +1,5 @@ +#ifndef MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_X86_HPP +#define MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_X86_HPP + +class MMTkNoBarrierSetAssembler: public MMTkBarrierSetAssembler {}; +#endif // MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_X86_HPP diff --git a/openjdk/cpu/x86/mmtkObjectBarrierSetAssembler_x86.cpp b/openjdk/cpu/x86/mmtkObjectBarrierSetAssembler_x86.cpp new file mode 100644 index 00000000..64fe6b95 --- /dev/null +++ b/openjdk/cpu/x86/mmtkObjectBarrierSetAssembler_x86.cpp @@ -0,0 +1,103 @@ +#include "precompiled.hpp" +#include "mmtkObjectBarrier.hpp" +#include "runtime/interfaceSupport.inline.hpp" + +#define __ masm-> + +void MMTkObjectBarrierSetAssembler::object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, bool compensate_val_reg) const { + if (can_remove_barrier(decorators, val, /* skip_const_null */ true)) return; + + bool is_not_null = (decorators & IS_NOT_NULL) != 0; + + Register obj = dst.base(); +#if MMTK_ENABLE_BARRIER_FASTPATH + Label done; + + Register tmp3 = rscratch1; + Register tmp4 = rscratch2; + assert_different_registers(obj, tmp2, tmp3); + assert_different_registers(tmp4, rcx); + + // tmp2 = load-byte (SIDE_METADATA_BASE_ADDRESS + (obj >> 6)); + __ movptr(tmp3, obj); + __ shrptr(tmp3, 6); + __ movptr(tmp2, SIDE_METADATA_BASE_ADDRESS); + __ movb(tmp2, Address(tmp2, tmp3)); + // tmp3 = (obj >> 3) & 7 + __ movptr(tmp3, obj); + __ shrptr(tmp3, 3); + __ andptr(tmp3, 7); + // tmp2 = tmp2 >> tmp3 + __ movptr(tmp4, rcx); + __ movl(rcx, tmp3); + __ shrptr(tmp2); + __ movptr(rcx, tmp4); + // if ((tmp2 & 1) == 1) goto slowpath; + __ andptr(tmp2, 1); + __ cmpptr(tmp2, 1); + __ jcc(Assembler::notEqual, done); +#endif + + __ movptr(c_rarg0, obj); + __ xorptr(c_rarg1, c_rarg1); + // Note: If `compensate_val_reg == true && UseCompressedOops === true`, the `val` register will be + // holding a compressed pointer to the target object. If the write barrier needs to know the + // target, we will need to decompress it before passing it to the barrier slow path. However, + // since we know the semantics of `mmtk::plan::barriers::ObjectBarrier`, i.e. it logs the object + // without looking at the `slot` or the `target` parameter at all, we simply pass nullptr to both + // parameters. + __ xorptr(c_rarg2, c_rarg2); + +#if MMTK_ENABLE_BARRIER_FASTPATH + __ call_VM_leaf_base(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_slow_call), 3); + __ bind(done); +#else + __ call_VM_leaf_base(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_post_call), 3); +#endif +} + +void MMTkObjectBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count) { + // `count` or `dst` register values may get overwritten after the array copy, and `arraycopy_epilogue` can receive invalid addresses. + // Save the register values here and restore them in `arraycopy_epilogue`. + // See https://github.com/openjdk/jdk/blob/jdk-11%2B19/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp#L37-L50 + bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0; + bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0; + bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops); + if (type == T_OBJECT || type == T_ARRAY) { + if (!checkcast) { + if (!obj_int) { + // Save count for barrier + __ movptr(r11, count); + } else if (disjoint) { + // Save dst in r11 in the disjoint case + __ movq(r11, dst); + } + } + } +} + +void MMTkObjectBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count) { + bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0; + bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0; + bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops); + const bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; + if ((type == T_OBJECT || type == T_ARRAY) && !dest_uninitialized) { + if (!checkcast) { + if (!obj_int) { + // Save count for barrier + count = r11; + } else if (disjoint) { + // Use the saved dst in the disjoint case + dst = r11; + } + } + __ pusha(); + __ movptr(c_rarg0, src); + __ movptr(c_rarg1, dst); + __ movptr(c_rarg2, count); + __ call_VM_leaf_base(FN_ADDR(MMTkBarrierSetRuntime::object_reference_array_copy_post_call), 3); + __ popa(); + } +} + +#undef __ diff --git a/openjdk/cpu/x86/mmtkObjectBarrierSetAssembler_x86.hpp b/openjdk/cpu/x86/mmtkObjectBarrierSetAssembler_x86.hpp new file mode 100644 index 00000000..18c098ae --- /dev/null +++ b/openjdk/cpu/x86/mmtkObjectBarrierSetAssembler_x86.hpp @@ -0,0 +1,11 @@ +#ifndef MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_X86_HPP +#define MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_X86_HPP + +class MMTkObjectBarrierSetAssembler: public MMTkBarrierSetAssembler { +protected: + virtual void object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, bool compensate_val_reg) const override; +public: + virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count) override; + virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count) override; +}; +#endif // MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_X86_HPP diff --git a/openjdk/cpu/zero/mmtkBarrierSetAssembler_zero.hpp b/openjdk/cpu/zero/mmtkBarrierSetAssembler_zero.hpp new file mode 100644 index 00000000..b41c3889 --- /dev/null +++ b/openjdk/cpu/zero/mmtkBarrierSetAssembler_zero.hpp @@ -0,0 +1,5 @@ +#ifndef MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_ZERO_HPP +#define MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_ZERO_HPP + +class MMTkBarrierSetAssembler; +#endif // MMTK_OPENJDK_MMTK_BARRIER_SET_ASSEMBLER_ZERO_HPP diff --git a/openjdk/cpu/zero/mmtkNoBarrierSetAssembler_zero.hpp b/openjdk/cpu/zero/mmtkNoBarrierSetAssembler_zero.hpp new file mode 100644 index 00000000..7ed51d73 --- /dev/null +++ b/openjdk/cpu/zero/mmtkNoBarrierSetAssembler_zero.hpp @@ -0,0 +1,5 @@ +#ifndef MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_ZERO_HPP +#define MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_ZERO_HPP + +class MMTkNoBarrierSetAssembler; +#endif // MMTK_OPENJDK_MMTK_NO_BARRIER_SET_ASSEMBLER_ZERO_HPP diff --git a/openjdk/cpu/zero/mmtkObjectBarrierSetAssembler_zero.hpp b/openjdk/cpu/zero/mmtkObjectBarrierSetAssembler_zero.hpp new file mode 100644 index 00000000..7fbfd37b --- /dev/null +++ b/openjdk/cpu/zero/mmtkObjectBarrierSetAssembler_zero.hpp @@ -0,0 +1,5 @@ +#ifndef MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_ZERO_HPP +#define MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_ZERO_HPP + +class MMTkObjectBarrierSetAssembler; +#endif // MMTK_OPENJDK_MMTK_OBJECT_BARRIER_SET_ASSEMBLER_ZERO_HPP diff --git a/openjdk/mmtkCollectorPolicy.hpp b/openjdk/mmtkCollectorPolicy.hpp deleted file mode 100644 index 9dddbbe4..00000000 --- a/openjdk/mmtkCollectorPolicy.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef MMTK_OPENJDK_MMTK_COLLECTOR_POLICY_HPP -#define MMTK_OPENJDK_MMTK_COLLECTOR_POLICY_HPP - -class MMTkCollectorPolicy : public CollectorPolicy { -protected: - virtual void initialize_alignments() { - _space_alignment = 1 << 19; - _heap_alignment = _space_alignment; - } -public: - MMTkCollectorPolicy() {} -}; -#endif // MMTK_OPENJDK_MMTK_COLLECTOR_POLICY_HPP diff --git a/openjdk/barriers/mmtkNoBarrier.hpp b/openjdk/share/barriers/mmtkNoBarrier.hpp similarity index 70% rename from openjdk/barriers/mmtkNoBarrier.hpp rename to openjdk/share/barriers/mmtkNoBarrier.hpp index 6652d8a0..79d8d27e 100644 --- a/openjdk/barriers/mmtkNoBarrier.hpp +++ b/openjdk/share/barriers/mmtkNoBarrier.hpp @@ -2,17 +2,24 @@ #define MMTK_OPENJDK_BARRIERS_MMTK_NO_BARRIER_HPP #include "../mmtkBarrierSet.hpp" -#include "../mmtkBarrierSetAssembler_x86.hpp" +#include "utilities/macros.hpp" +#include CPU_HEADER(mmtkBarrierSetAssembler) +#include CPU_HEADER(mmtkNoBarrierSetAssembler) +#ifdef COMPILER1 #include "../mmtkBarrierSetC1.hpp" -#include "../mmtkBarrierSetC2.hpp" - -class MMTkNoBarrierSetRuntime: public MMTkBarrierSetRuntime {}; - -class MMTkNoBarrierSetAssembler: public MMTkBarrierSetAssembler {}; - class MMTkNoBarrierSetC1: public MMTkBarrierSetC1 {}; +#else +class MMTkNoBarrierSetC1; +#endif +#ifdef COMPILER2 +#include "../mmtkBarrierSetC2.hpp" class MMTkNoBarrierSetC2: public MMTkBarrierSetC2 {}; +#else +class MMTkNoBarrierSetC2; +#endif + +class MMTkNoBarrierSetRuntime: public MMTkBarrierSetRuntime {}; struct MMTkNoBarrier: MMTkBarrierImpl< MMTkNoBarrierSetRuntime, diff --git a/openjdk/barriers/mmtkObjectBarrier.cpp b/openjdk/share/barriers/mmtkObjectBarrier.cpp similarity index 58% rename from openjdk/barriers/mmtkObjectBarrier.cpp rename to openjdk/share/barriers/mmtkObjectBarrier.cpp index fcf2b349..8e4278da 100644 --- a/openjdk/barriers/mmtkObjectBarrier.cpp +++ b/openjdk/share/barriers/mmtkObjectBarrier.cpp @@ -36,106 +36,7 @@ void MMTkObjectBarrierSetRuntime::object_reference_write_post(oop src, oop* slot #endif } -#define __ masm-> - -void MMTkObjectBarrierSetAssembler::object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, bool compensate_val_reg) const { - if (can_remove_barrier(decorators, val, /* skip_const_null */ true)) return; - - bool is_not_null = (decorators & IS_NOT_NULL) != 0; - - Register obj = dst.base(); -#if MMTK_ENABLE_BARRIER_FASTPATH - Label done; - - Register tmp3 = rscratch1; - Register tmp4 = rscratch2; - assert_different_registers(obj, tmp2, tmp3); - assert_different_registers(tmp4, rcx); - - // tmp2 = load-byte (SIDE_METADATA_BASE_ADDRESS + (obj >> 6)); - __ movptr(tmp3, obj); - __ shrptr(tmp3, 6); - __ movptr(tmp2, SIDE_METADATA_BASE_ADDRESS); - __ movb(tmp2, Address(tmp2, tmp3)); - // tmp3 = (obj >> 3) & 7 - __ movptr(tmp3, obj); - __ shrptr(tmp3, 3); - __ andptr(tmp3, 7); - // tmp2 = tmp2 >> tmp3 - __ movptr(tmp4, rcx); - __ movl(rcx, tmp3); - __ shrptr(tmp2); - __ movptr(rcx, tmp4); - // if ((tmp2 & 1) == 1) goto slowpath; - __ andptr(tmp2, 1); - __ cmpptr(tmp2, 1); - __ jcc(Assembler::notEqual, done); -#endif - - __ movptr(c_rarg0, obj); - __ xorptr(c_rarg1, c_rarg1); - // Note: If `compensate_val_reg == true && UseCompressedOops === true`, the `val` register will be - // holding a compressed pointer to the target object. If the write barrier needs to know the - // target, we will need to decompress it before passing it to the barrier slow path. However, - // since we know the semantics of `mmtk::plan::barriers::ObjectBarrier`, i.e. it logs the object - // without looking at the `slot` or the `target` parameter at all, we simply pass nullptr to both - // parameters. - __ xorptr(c_rarg2, c_rarg2); - -#if MMTK_ENABLE_BARRIER_FASTPATH - __ call_VM_leaf_base(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_slow_call), 3); - __ bind(done); -#else - __ call_VM_leaf_base(FN_ADDR(MMTkBarrierSetRuntime::object_reference_write_post_call), 3); -#endif -} - -void MMTkObjectBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count) { - // `count` or `dst` register values may get overwritten after the array copy, and `arraycopy_epilogue` can receive invalid addresses. - // Save the register values here and restore them in `arraycopy_epilogue`. - // See https://github.com/openjdk/jdk/blob/jdk-11%2B19/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp#L37-L50 - bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0; - bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0; - bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops); - if (type == T_OBJECT || type == T_ARRAY) { - if (!checkcast) { - if (!obj_int) { - // Save count for barrier - __ movptr(r11, count); - } else if (disjoint) { - // Save dst in r11 in the disjoint case - __ movq(r11, dst); - } - } - } -} - -void MMTkObjectBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count) { - bool checkcast = (decorators & ARRAYCOPY_CHECKCAST) != 0; - bool disjoint = (decorators & ARRAYCOPY_DISJOINT) != 0; - bool obj_int = type == T_OBJECT LP64_ONLY(&& UseCompressedOops); - const bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; - if ((type == T_OBJECT || type == T_ARRAY) && !dest_uninitialized) { - if (!checkcast) { - if (!obj_int) { - // Save count for barrier - count = r11; - } else if (disjoint) { - // Use the saved dst in the disjoint case - dst = r11; - } - } - __ pusha(); - __ movptr(c_rarg0, src); - __ movptr(c_rarg1, dst); - __ movptr(c_rarg2, count); - __ call_VM_leaf_base(FN_ADDR(MMTkBarrierSetRuntime::object_reference_array_copy_post_call), 3); - __ popa(); - } -} - -#undef __ - +#ifdef COMPILER1 #ifdef ASSERT #define __ gen->lir(__FILE__, __LINE__)-> #else @@ -200,7 +101,7 @@ void MMTkObjectBarrierSetC1::object_reference_write_post(LIRAccess& access, LIR_ __ unsigned_shift_right(result, shift, result, LIR_OprFact::illegalOpr); __ logical_and(result, LIR_OprFact::intConst(1), result); __ cmp(lir_cond_equal, result, LIR_OprFact::intConst(1)); - __ branch(lir_cond_equal, T_BYTE, slow); + __ branch(lir_cond_equal, slow); #else __ jump(slow); #endif @@ -209,7 +110,9 @@ void MMTkObjectBarrierSetC1::object_reference_write_post(LIRAccess& access, LIR_ } #undef __ +#endif +#ifdef COMPILER2 #define __ ideal. void MMTkObjectBarrierSetC2::object_reference_write_post(GraphKit* kit, Node* src, Node* slot, Node* val) const { @@ -242,3 +145,4 @@ void MMTkObjectBarrierSetC2::object_reference_write_post(GraphKit* kit, Node* sr } #undef __ +#endif diff --git a/openjdk/barriers/mmtkObjectBarrier.hpp b/openjdk/share/barriers/mmtkObjectBarrier.hpp similarity index 74% rename from openjdk/barriers/mmtkObjectBarrier.hpp rename to openjdk/share/barriers/mmtkObjectBarrier.hpp index 6baf7bae..78d4ac9d 100644 --- a/openjdk/barriers/mmtkObjectBarrier.hpp +++ b/openjdk/share/barriers/mmtkObjectBarrier.hpp @@ -3,14 +3,20 @@ #include "../mmtk.h" #include "../mmtkBarrierSet.hpp" -#include "../mmtkBarrierSetAssembler_x86.hpp" +#include "utilities/macros.hpp" +#include CPU_HEADER(mmtkBarrierSetAssembler) +#include CPU_HEADER(mmtkObjectBarrierSetAssembler) +#ifdef COMPILER1 #include "../mmtkBarrierSetC1.hpp" -#include "../mmtkBarrierSetC2.hpp" #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" -#include "gc/shared/barrierSet.hpp" +#endif +#ifdef COMPILER2 +#include "../mmtkBarrierSetC2.hpp" #include "opto/callnode.hpp" #include "opto/idealKit.hpp" +#endif +#include "gc/shared/barrierSet.hpp" #define SIDE_METADATA_WORST_CASE_RATIO_LOG 1 #define LOG_BYTES_IN_CHUNK 22 @@ -28,14 +34,7 @@ class MMTkObjectBarrierSetRuntime: public MMTkBarrierSetRuntime { virtual void object_probable_write(oop new_obj) const override; }; -class MMTkObjectBarrierSetAssembler: public MMTkBarrierSetAssembler { -protected: - virtual void object_reference_write_post(MacroAssembler* masm, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, bool compensate_val_reg) const override; -public: - virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count) override; - virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count) override; -}; - +#ifdef COMPILER1 class MMTkObjectBarrierSetC1: public MMTkBarrierSetC1 { protected: virtual void object_reference_write_post(LIRAccess& access, LIR_Opr src, LIR_Opr slot, LIR_Opr new_val) const override; @@ -44,11 +43,18 @@ class MMTkObjectBarrierSetC1: public MMTkBarrierSetC1 { return MMTkBarrierSetC1::resolve_address_in_register(access, resolve_in_register); } }; +#else +class MMTkObjectBarrierSetC1; +#endif +#ifdef COMPILER2 class MMTkObjectBarrierSetC2: public MMTkBarrierSetC2 { protected: virtual void object_reference_write_post(GraphKit* kit, Node* src, Node* slot, Node* val) const override; }; +#else +class MMTkObjectBarrierSetC2; +#endif struct MMTkObjectBarrier: MMTkBarrierImpl< MMTkObjectBarrierSetRuntime, diff --git a/openjdk/mmtk.h b/openjdk/share/mmtk.h similarity index 92% rename from openjdk/mmtk.h rename to openjdk/share/mmtk.h index 89930abd..abfe882b 100644 --- a/openjdk/mmtk.h +++ b/openjdk/share/mmtk.h @@ -103,7 +103,6 @@ extern bool process_bulk(char* options); extern void scan_region(); extern void handle_user_collection_request(void *tls); -extern void start_control_collector(void *tls, void *context); extern void start_worker(void *tls, void* worker); extern size_t mmtk_add_nmethod_oop(void* object); @@ -164,16 +163,9 @@ typedef struct { char* (*dump_object_string) (void* object); void (*scan_roots_in_all_mutator_threads)(SlotsClosure closure); void (*scan_roots_in_mutator_thread)(SlotsClosure closure, void* tls); - void (*scan_universe_roots) (SlotsClosure closure); - void (*scan_jni_handle_roots) (SlotsClosure closure); - void (*scan_object_synchronizer_roots) (SlotsClosure closure); - void (*scan_management_roots) (SlotsClosure closure); - void (*scan_jvmti_export_roots) (SlotsClosure closure); - void (*scan_aot_loader_roots) (SlotsClosure closure); - void (*scan_system_dictionary_roots) (SlotsClosure closure); void (*scan_code_cache_roots) (SlotsClosure closure); - void (*scan_string_table_roots) (SlotsClosure closure); void (*scan_class_loader_data_graph_roots) (SlotsClosure closure); + void (*scan_oop_storage_set_roots) (SlotsClosure closure); void (*scan_weak_processor_roots) (SlotsClosure closure); void (*scan_vm_thread_roots) (SlotsClosure closure); size_t (*number_of_mutators)(); diff --git a/openjdk/mmtkBarrierSet.cpp b/openjdk/share/mmtkBarrierSet.cpp similarity index 92% rename from openjdk/mmtkBarrierSet.cpp rename to openjdk/share/mmtkBarrierSet.cpp index 178b7011..231f6160 100644 --- a/openjdk/mmtkBarrierSet.cpp +++ b/openjdk/share/mmtkBarrierSet.cpp @@ -26,7 +26,8 @@ #include "barriers/mmtkNoBarrier.hpp" #include "barriers/mmtkObjectBarrier.hpp" #include "mmtkBarrierSet.hpp" -#include "mmtkBarrierSetAssembler_x86.hpp" +#include "utilities/macros.hpp" +#include CPU_HEADER(mmtkBarrierSetAssembler) #include "runtime/interfaceSupport.inline.hpp" #ifdef COMPILER1 #include "mmtkBarrierSetC1.hpp" @@ -77,6 +78,7 @@ MMTkBarrierBase* get_selected_barrier() { static MMTkBarrierBase* selected_barrier = NULL; if (selected_barrier) return selected_barrier; const char* barrier = mmtk_active_barrier(); + // printf("mmtk_active_barrier %s\n", barrier); if (strcmp(barrier, "NoBarrier") == 0) selected_barrier = new MMTkNoBarrier(); else if (strcmp(barrier, "ObjectBarrier") == 0) selected_barrier = new MMTkObjectBarrier(); else guarantee(false, "Unimplemented"); @@ -84,9 +86,11 @@ MMTkBarrierBase* get_selected_barrier() { } MMTkBarrierSet::MMTkBarrierSet(MemRegion whole_heap): - BarrierSet(get_selected_barrier()->create_assembler(), - get_selected_barrier()->create_c1(), - get_selected_barrier()->create_c2(), + BarrierSet((BarrierSetAssembler*) get_selected_barrier()->create_assembler(), + (BarrierSetC1*) get_selected_barrier()->create_c1(), + (BarrierSetC2*) get_selected_barrier()->create_c2(), + NULL, + NULL, BarrierSet::FakeRtti(BarrierSet::ThirdPartyHeapBarrierSet)), _whole_heap(whole_heap), _runtime(get_selected_barrier()->create_runtime()) {} @@ -108,11 +112,11 @@ void MMTkBarrierSet::on_thread_destroy(Thread* thread) { thread->third_party_heap_mutator.destroy(); } -void MMTkBarrierSet::on_thread_attach(JavaThread* thread) { +void MMTkBarrierSet::on_thread_attach(Thread* thread) { thread->third_party_heap_mutator.flush(); } -void MMTkBarrierSet::on_thread_detach(JavaThread* thread) { +void MMTkBarrierSet::on_thread_detach(Thread* thread) { thread->third_party_heap_mutator.flush(); } diff --git a/openjdk/mmtkBarrierSet.hpp b/openjdk/share/mmtkBarrierSet.hpp similarity index 90% rename from openjdk/mmtkBarrierSet.hpp rename to openjdk/share/mmtkBarrierSet.hpp index 07990706..e0094037 100644 --- a/openjdk/mmtkBarrierSet.hpp +++ b/openjdk/share/mmtkBarrierSet.hpp @@ -30,12 +30,14 @@ #include "gc/shared/barrierSetConfig.hpp" #include "memory/memRegion.hpp" #include "mmtk.h" -#include "mmtkBarrierSetAssembler_x86.hpp" #include "oops/access.hpp" #include "oops/arrayOop.hpp" #include "oops/accessBackend.hpp" +#include "oops/compressedOops.hpp" #include "oops/oopsHierarchy.hpp" #include "utilities/fakeRttiSupport.hpp" +#include "utilities/macros.hpp" +#include CPU_HEADER(mmtkBarrierSetAssembler) #define MMTK_ENABLE_ALLOCATION_FASTPATH true #define MMTK_ENABLE_BARRIER_FASTPATH true @@ -108,9 +110,9 @@ struct MMTkBarrierBase: public CHeapObj { template struct MMTkBarrierImpl: MMTkBarrierBase { virtual MMTkBarrierSetRuntime* create_runtime() const { return new Runtime(); } - virtual MMTkBarrierSetAssembler* create_assembler() const { return new Assembler(); } - virtual MMTkBarrierSetC1* create_c1() const { return new C1(); } - virtual MMTkBarrierSetC2* create_c2() const { return new C2(); } + virtual MMTkBarrierSetAssembler* create_assembler() const { return NOT_ZERO(new Assembler()) ZERO_ONLY(NULL); } + virtual MMTkBarrierSetC1* create_c1() const { return COMPILER1_PRESENT(new C1()) NOT_COMPILER1(NULL); } + virtual MMTkBarrierSetC2* create_c2() const { return COMPILER2_PRESENT(new C2()) NOT_COMPILER2(NULL); } }; // This class provides the interface between a barrier implementation and @@ -135,8 +137,8 @@ class MMTkBarrierSet : public BarrierSet { } virtual void on_thread_destroy(Thread* thread); - virtual void on_thread_attach(JavaThread* thread); - virtual void on_thread_detach(JavaThread* thread); + virtual void on_thread_attach(Thread* thread); + virtual void on_thread_detach(Thread* thread); virtual void on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) override { runtime()->object_probable_write(new_obj); @@ -185,27 +187,27 @@ class MMTkBarrierSet : public BarrierSet { } template - static oop oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value) { + static oop oop_atomic_cmpxchg_in_heap(T* addr, oop compare_value, oop new_value) { UNREACHABLE(); return NULL; } - static oop oop_atomic_cmpxchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value) { + static oop oop_atomic_cmpxchg_in_heap_at(oop base, ptrdiff_t offset, oop compare_value, oop new_value) { runtime()->object_reference_write_pre(base, (oop*) (size_t((void*) base) + offset), new_value); - oop result = Raw::oop_atomic_cmpxchg_at(new_value, base, offset, compare_value); + oop result = Raw::oop_atomic_cmpxchg_at(base, offset, compare_value, new_value); runtime()->object_reference_write_post(base, (oop*) (size_t((void*) base) + offset), new_value); return result; } template - static oop oop_atomic_xchg_in_heap(oop new_value, T* addr) { + static oop oop_atomic_xchg_in_heap(T* addr, oop new_value) { UNREACHABLE(); return NULL; } - static oop oop_atomic_xchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset) { + static oop oop_atomic_xchg_in_heap_at(oop base, ptrdiff_t offset, oop new_value) { runtime()->object_reference_write_pre(base, (oop*) (size_t((void*) base) + offset), new_value); - oop result = Raw::oop_atomic_xchg_at(new_value, base, offset); + oop result = Raw::oop_atomic_xchg_at(base, offset, new_value); runtime()->object_reference_write_post(base, (oop*) (size_t((void*) base) + offset), new_value); return result; } diff --git a/openjdk/mmtkBarrierSetC1.cpp b/openjdk/share/mmtkBarrierSetC1.cpp similarity index 90% rename from openjdk/mmtkBarrierSetC1.cpp rename to openjdk/share/mmtkBarrierSetC1.cpp index b2c9a683..11f55f3b 100644 --- a/openjdk/mmtkBarrierSetC1.cpp +++ b/openjdk/share/mmtkBarrierSetC1.cpp @@ -1,6 +1,8 @@ +#ifdef COMPILER1 #include "c1/c1_CodeStubs.hpp" #include "gc/shared/c1/barrierSetC1.hpp" -#include "mmtkBarrierSetAssembler_x86.hpp" +#include "utilities/macros.hpp" +#include CPU_HEADER(mmtkBarrierSetAssembler) #include "mmtkBarrierSetC1.hpp" void MMTkBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) { @@ -19,3 +21,4 @@ void MMTkC1BarrierStub::emit_code(LIR_Assembler* ce) { MMTkBarrierSetAssembler* bs = (MMTkBarrierSetAssembler*) BarrierSet::barrier_set()->barrier_set_assembler(); bs->generate_c1_write_barrier_stub_call(ce, this); } +#endif diff --git a/openjdk/mmtkBarrierSetC1.hpp b/openjdk/share/mmtkBarrierSetC1.hpp similarity index 94% rename from openjdk/mmtkBarrierSetC1.hpp rename to openjdk/share/mmtkBarrierSetC1.hpp index dea0712e..2f73ec95 100644 --- a/openjdk/mmtkBarrierSetC1.hpp +++ b/openjdk/share/mmtkBarrierSetC1.hpp @@ -1,6 +1,6 @@ #ifndef MMTK_OPENJDK_MMTK_BARRIER_SET_C1_HPP #define MMTK_OPENJDK_MMTK_BARRIER_SET_C1_HPP - +#ifdef COMPILER1 #include "c1/c1_CodeStubs.hpp" #include "gc/shared/c1/barrierSetC1.hpp" @@ -48,7 +48,7 @@ class MMTkBarrierSetC1 : public BarrierSetC1 { LIR_Opr resolve_address_in_register(LIRAccess& access, bool resolve_in_register) { DecoratorSet decorators = access.decorators(); bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0; - bool is_write = (decorators & C1_WRITE_ACCESS) != 0; + bool is_write = (decorators & ACCESS_WRITE) != 0; bool is_array = (decorators & IS_ARRAY) != 0; bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0; bool precise = is_array || on_anonymous; @@ -70,7 +70,10 @@ class MMTkBarrierSetC1 : public BarrierSetC1 { struct MMTkC1BarrierStub: CodeStub { LIR_Opr src, slot, new_val; - MMTkC1BarrierStub(LIR_Opr src, LIR_Opr slot, LIR_Opr new_val): src(src), slot(slot), new_val(new_val) {} + MMTkC1BarrierStub(LIR_Opr src, LIR_Opr slot, LIR_Opr new_val): src(src), slot(slot), new_val(new_val) { + FrameMap* f = Compilation::current()->frame_map(); + f->update_reserved_argument_area_size(3 * BytesPerWord); + } virtual void emit_code(LIR_Assembler* ce) override; @@ -83,5 +86,5 @@ struct MMTkC1BarrierStub: CodeStub { NOT_PRODUCT(virtual void print_name(outputStream* out) const { out->print("MMTkC1BarrierStub"); }); }; - +#endif #endif // MMTK_OPENJDK_MMTK_BARRIER_SET_C1_HPP diff --git a/openjdk/mmtkBarrierSetC2.cpp b/openjdk/share/mmtkBarrierSetC2.cpp similarity index 88% rename from openjdk/mmtkBarrierSetC2.cpp rename to openjdk/share/mmtkBarrierSetC2.cpp index b58e433d..8e71665c 100644 --- a/openjdk/mmtkBarrierSetC2.cpp +++ b/openjdk/share/mmtkBarrierSetC2.cpp @@ -22,6 +22,7 @@ * */ +#ifdef COMPILER2 #include "precompiled.hpp" #include "mmtk.h" #include "mmtkBarrierSet.hpp" @@ -46,7 +47,8 @@ void MMTkBarrierSetC2::expand_allocate(PhaseMacroExpand* x, AllocateNode* alloc, // allocation node to be expanded Node* length, // array length for an array allocation const TypeFunc* slow_call_type, // Type of slow call - address slow_call_address) { // Address of slow call + address slow_call_address, + Node* valid_length_test) { // Address of slow call Node* ctrl = alloc->in(TypeFunc::Control); Node* mem = alloc->in(TypeFunc::Memory); Node* i_o = alloc->in(TypeFunc::I_O); @@ -130,7 +132,7 @@ void MMTkBarrierSetC2::expand_allocate(PhaseMacroExpand* x, } } - if (x->C->env()->dtrace_alloc_probes() || !MMTK_ENABLE_ALLOCATION_FASTPATH + if (!MMTK_ENABLE_ALLOCATION_FASTPATH // Malloc allocator has no fastpath || (selector.tag == TAG_MALLOC || selector.tag == TAG_LARGE_OBJECT || selector.tag == TAG_FREE_LIST)) { // Force slow-path allocation @@ -409,11 +411,12 @@ void MMTkBarrierSetC2::expand_allocate(PhaseMacroExpand* x, } } - if (x->C->env()->dtrace_extended_probes()) { + if (x->C->env()->dtrace_alloc_probes()) { // Slow-path call int size = TypeFunc::Parms + 2; CallLeafNode *call = new CallLeafNode(OptoRuntime::dtrace_object_alloc_Type(), - CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc_base), + CAST_FROM_FN_PTR(address, + static_cast(SharedRuntime::dtrace_object_alloc)), "dtrace_object_alloc", TypeRawPtr::BOTTOM); @@ -448,7 +451,6 @@ void MMTkBarrierSetC2::expand_allocate(PhaseMacroExpand* x, // Generate slow-path call CallNode *call = new CallStaticJavaNode(slow_call_type, slow_call_address, OptoRuntime::stub_name(slow_call_address), - alloc->jvms()->bci(), TypePtr::BOTTOM); call->init_req( TypeFunc::Control, slow_region ); call->init_req( TypeFunc::I_O , x->top() ) ; // does no i/o @@ -463,7 +465,13 @@ void MMTkBarrierSetC2::expand_allocate(PhaseMacroExpand* x, // Copy debug information and adjust JVMState information, then replace // allocate node with the call - x->copy_call_debug_info((CallNode *) alloc, call); + call->copy_call_debug_info(&(x->_igvn), (SafePointNode*) alloc); + // For array allocations, copy the valid length check to the call node so Compile::final_graph_reshaping() can verify + // that the call has the expected number of CatchProj nodes (in case the allocation always fails and the fallthrough + // path dies). + if (valid_length_test != NULL) { + call->add_req(valid_length_test); + } if (!always_slow) { call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON. } else { @@ -484,37 +492,37 @@ void MMTkBarrierSetC2::expand_allocate(PhaseMacroExpand* x, // // We are interested in the CatchProj nodes. // - x->extract_call_projections(call); + call->extract_projections(&x->_callprojs, false, false); // An allocate node has separate memory projections for the uses on // the control and i_o paths. Replace the control memory projection with // result_phi_rawmem (unless we are only generating a slow call when // both memory projections are combined) - if (!always_slow && x->_memproj_fallthrough != NULL) { - for (DUIterator_Fast imax, i = x->_memproj_fallthrough->fast_outs(imax); i < imax; i++) { - Node *use = x->_memproj_fallthrough->fast_out(i); + if (!always_slow && x->_callprojs.fallthrough_memproj!= NULL) { + for (DUIterator_Fast imax, i = x->_callprojs.fallthrough_memproj->fast_outs(imax); i < imax; i++) { + Node *use = x->_callprojs.fallthrough_memproj->fast_out(i); x->_igvn.rehash_node_delayed(use); - imax -= x->replace_input(use, x->_memproj_fallthrough, result_phi_rawmem); + imax -= x->replace_input(use, x->_callprojs.fallthrough_memproj, result_phi_rawmem); // back up iterator --i; } } // Now change uses of _memproj_catchall to use _memproj_fallthrough and delete // _memproj_catchall so we end up with a call that has only 1 memory projection. - if (x->_memproj_catchall != NULL ) { - if (x->_memproj_fallthrough == NULL) { - x->_memproj_fallthrough = new ProjNode(call, TypeFunc::Memory); - x->transform_later(x->_memproj_fallthrough); + if (x->_callprojs.catchall_memproj != NULL ) { + if (x->_callprojs.fallthrough_memproj == NULL) { + x->_callprojs.fallthrough_memproj = new ProjNode(call, TypeFunc::Memory); + x->transform_later(x->_callprojs.fallthrough_memproj); } - for (DUIterator_Fast imax, i = x->_memproj_catchall->fast_outs(imax); i < imax; i++) { - Node *use = x->_memproj_catchall->fast_out(i); + for (DUIterator_Fast imax, i = x->_callprojs.catchall_memproj->fast_outs(imax); i < imax; i++) { + Node *use = x->_callprojs.catchall_memproj->fast_out(i); x->_igvn.rehash_node_delayed(use); - imax -= x->replace_input(use, x->_memproj_catchall, x->_memproj_fallthrough); + imax -= x->replace_input(use, x->_callprojs.catchall_memproj, x->_callprojs.fallthrough_memproj); // back up iterator --i; } - assert(x->_memproj_catchall->outcnt() == 0, "all uses must be deleted"); - x->_igvn.remove_dead_node(x->_memproj_catchall); + assert(x->_callprojs.catchall_memproj->outcnt() == 0, "all uses must be deleted"); + x->_igvn.remove_dead_node(x->_callprojs.catchall_memproj); } // An allocate node has separate i_o projections for the uses on the control @@ -522,31 +530,31 @@ void MMTkBarrierSetC2::expand_allocate(PhaseMacroExpand* x, // otherwise incoming i_o become dead when only a slow call is generated // (it is different from memory projections where both projections are // combined in such case). - if (x->_ioproj_fallthrough != NULL) { - for (DUIterator_Fast imax, i = x->_ioproj_fallthrough->fast_outs(imax); i < imax; i++) { - Node *use = x->_ioproj_fallthrough->fast_out(i); + if (x->_callprojs.fallthrough_ioproj != NULL) { + for (DUIterator_Fast imax, i = x->_callprojs.fallthrough_ioproj->fast_outs(imax); i < imax; i++) { + Node *use = x->_callprojs.fallthrough_ioproj->fast_out(i); x->_igvn.rehash_node_delayed(use); - imax -= x->replace_input(use, x->_ioproj_fallthrough, result_phi_i_o); + imax -= x->replace_input(use, x->_callprojs.fallthrough_ioproj, result_phi_i_o); // back up iterator --i; } } // Now change uses of _ioproj_catchall to use _ioproj_fallthrough and delete // _ioproj_catchall so we end up with a call that has only 1 i_o projection. - if (x->_ioproj_catchall != NULL ) { - if (x->_ioproj_fallthrough == NULL) { - x->_ioproj_fallthrough = new ProjNode(call, TypeFunc::I_O); - x->transform_later(x->_ioproj_fallthrough); + if (x->_callprojs.catchall_ioproj != NULL ) { + if (x->_callprojs.fallthrough_ioproj == NULL) { + x->_callprojs.fallthrough_ioproj = new ProjNode(call, TypeFunc::I_O); + x->transform_later(x->_callprojs.fallthrough_ioproj); } - for (DUIterator_Fast imax, i = x->_ioproj_catchall->fast_outs(imax); i < imax; i++) { - Node *use = x->_ioproj_catchall->fast_out(i); + for (DUIterator_Fast imax, i = x->_callprojs.catchall_ioproj->fast_outs(imax); i < imax; i++) { + Node *use = x->_callprojs.catchall_ioproj->fast_out(i); x->_igvn.rehash_node_delayed(use); - imax -= x->replace_input(use, x->_ioproj_catchall, x->_ioproj_fallthrough); + imax -= x->replace_input(use, x->_callprojs.catchall_ioproj, x->_callprojs.fallthrough_ioproj); // back up iterator --i; } - assert(x->_ioproj_catchall->outcnt() == 0, "all uses must be deleted"); - x->_igvn.remove_dead_node(x->_ioproj_catchall); + assert(x->_callprojs.catchall_ioproj->outcnt() == 0, "all uses must be deleted"); + x->_igvn.remove_dead_node(x->_callprojs.catchall_ioproj); } // if we generated only a slow call, we are done @@ -566,27 +574,27 @@ void MMTkBarrierSetC2::expand_allocate(PhaseMacroExpand* x, } - if (x->_fallthroughcatchproj != NULL) { - ctrl = x->_fallthroughcatchproj->clone(); + if (x->_callprojs.fallthrough_catchproj != NULL) { + ctrl = x->_callprojs.fallthrough_catchproj->clone(); x->transform_later(ctrl); - x->_igvn.replace_node(x->_fallthroughcatchproj, result_region); + x->_igvn.replace_node(x->_callprojs.fallthrough_catchproj, result_region); } else { ctrl = x->top(); } Node *slow_result; - if (x->_resproj == NULL) { + if (x->_callprojs.resproj == NULL) { // no uses of the allocation result slow_result = x->top(); } else { - slow_result = x->_resproj->clone(); + slow_result = x->_callprojs.resproj->clone(); x->transform_later(slow_result); - x->_igvn.replace_node(x->_resproj, result_phi_rawoop); + x->_igvn.replace_node(x->_callprojs.resproj, result_phi_rawoop); } // Plug slow-path into result merge point result_region ->init_req( slow_result_path, ctrl ); result_phi_rawoop->init_req( slow_result_path, slow_result); - result_phi_rawmem->init_req( slow_result_path, x->_memproj_fallthrough ); + result_phi_rawmem->init_req( slow_result_path, x->_callprojs.fallthrough_memproj ); x->transform_later(result_region); x->transform_later(result_phi_rawoop); x->transform_later(result_phi_rawmem); @@ -633,3 +641,4 @@ bool MMTkBarrierSetC2::can_remove_barrier(GraphKit* kit, PhaseTransform* phase, return false; } +#endif diff --git a/openjdk/mmtkBarrierSetC2.hpp b/openjdk/share/mmtkBarrierSetC2.hpp similarity index 80% rename from openjdk/mmtkBarrierSetC2.hpp rename to openjdk/share/mmtkBarrierSetC2.hpp index d8052d9a..7b359fb6 100644 --- a/openjdk/mmtkBarrierSetC2.hpp +++ b/openjdk/share/mmtkBarrierSetC2.hpp @@ -25,6 +25,7 @@ #ifndef MMTK_OPENJDK_MMTK_BARRIER_SET_C2_HPP #define MMTK_OPENJDK_MMTK_BARRIER_SET_C2_HPP +#ifdef COMPILER2 #include "gc/shared/c2/barrierSetC2.hpp" #include "opto/addnode.hpp" #include "opto/arraycopynode.hpp" @@ -54,24 +55,30 @@ class MMTkBarrierSetC2: public BarrierSetC2 { virtual void object_reference_write_post(GraphKit* kit, Node* src, Node* slot, Node* val) const {} virtual Node* store_at_resolved(C2Access& access, C2AccessValue& val) const { - if (access.is_oop()) object_reference_write_pre(access.kit(), access.base(), access.addr().node(), val.node()); + if (access.is_oop() && access.is_parse_access()) { + C2ParseAccess& parse_access = static_cast(access); + object_reference_write_pre(parse_access.kit(), access.base(), access.addr().node(), val.node()); + } Node* store = BarrierSetC2::store_at_resolved(access, val); - if (access.is_oop()) object_reference_write_post(access.kit(), access.base(), access.addr().node(), val.node()); + if (access.is_oop() && access.is_parse_access()) { + C2ParseAccess& parse_access = static_cast(access); + object_reference_write_post(parse_access.kit(), access.base(), access.addr().node(), val.node()); + } return store; } - virtual Node* atomic_cmpxchg_val_at_resolved(C2AtomicAccess& access, Node* expected_val, Node* new_val, const Type* value_type) const { + virtual Node* atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, Node* expected_val, Node* new_val, const Type* value_type) const { if (access.is_oop()) object_reference_write_pre(access.kit(), access.base(), access.addr().node(), new_val); Node* result = BarrierSetC2::atomic_cmpxchg_val_at_resolved(access, expected_val, new_val, value_type); if (access.is_oop()) object_reference_write_post(access.kit(), access.base(), access.addr().node(), new_val); return result; } - virtual Node* atomic_cmpxchg_bool_at_resolved(C2AtomicAccess& access, Node* expected_val, Node* new_val, const Type* value_type) const { + virtual Node* atomic_cmpxchg_bool_at_resolved(C2AtomicParseAccess& access, Node* expected_val, Node* new_val, const Type* value_type) const { if (access.is_oop()) object_reference_write_pre(access.kit(), access.base(), access.addr().node(), new_val); Node* load_store = BarrierSetC2::atomic_cmpxchg_bool_at_resolved(access, expected_val, new_val, value_type); if (access.is_oop()) object_reference_write_post(access.kit(), access.base(), access.addr().node(), new_val); return load_store; } - virtual Node* atomic_xchg_at_resolved(C2AtomicAccess& access, Node* new_val, const Type* value_type) const { + virtual Node* atomic_xchg_at_resolved(C2AtomicParseAccess& access, Node* new_val, const Type* value_type) const { if (access.is_oop()) object_reference_write_pre(access.kit(), access.base(), access.addr().node(), new_val); Node* result = BarrierSetC2::atomic_xchg_at_resolved(access, new_val, value_type); if (access.is_oop()) object_reference_write_post(access.kit(), access.base(), access.addr().node(), new_val); @@ -82,7 +89,7 @@ class MMTkBarrierSetC2: public BarrierSetC2 { virtual void clone(GraphKit* kit, Node* src, Node* dst, Node* size, bool is_array) const { BarrierSetC2::clone(kit, src, dst, size, is_array); } - virtual bool array_copy_requires_gc_barriers(BasicType type) const { + virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, bool is_clone_instance, ArrayCopyPhase phase) const { return true; } virtual bool is_gc_barrier_node(Node* node) const { @@ -94,7 +101,8 @@ class MMTkBarrierSetC2: public BarrierSetC2 { AllocateNode* alloc, // allocation node to be expanded Node* length, // array length for an array allocation const TypeFunc* slow_call_type, // Type of slow call - address slow_call_address); // Address of slow call + address slow_call_address, // Address of slow call + Node* valid_length_test); // whether length is valid or not }; class MMTkIdealKit: public IdealKit { @@ -125,5 +133,8 @@ class MMTkIdealKit: public IdealKit { return TypeFunc::make(domain, range); } }; +#else +class MMTkBarrierSetC2; +#endif #endif // MMTK_OPENJDK_MMTK_BARRIER_SET_C2_HPP diff --git a/openjdk/mmtkCollectorThread.cpp b/openjdk/share/mmtkCollectorThread.cpp similarity index 97% rename from openjdk/mmtkCollectorThread.cpp rename to openjdk/share/mmtkCollectorThread.cpp index 8333b2ff..7d22d35c 100644 --- a/openjdk/mmtkCollectorThread.cpp +++ b/openjdk/share/mmtkCollectorThread.cpp @@ -32,6 +32,5 @@ MMTkCollectorThread::MMTkCollectorThread(void* context): NamedThread() { } void MMTkCollectorThread::run() { - this->initialize_named_thread(); start_worker((void*) this, third_party_heap_collector); } diff --git a/openjdk/mmtkCollectorThread.hpp b/openjdk/share/mmtkCollectorThread.hpp similarity index 97% rename from openjdk/mmtkCollectorThread.hpp rename to openjdk/share/mmtkCollectorThread.hpp index 03548fcb..00b829ae 100644 --- a/openjdk/mmtkCollectorThread.hpp +++ b/openjdk/share/mmtkCollectorThread.hpp @@ -26,7 +26,7 @@ #define MMTK_OPENJDK_MMTK_COLLECTOR_THREAD_HPP #include "runtime/perfData.hpp" -#include "runtime/thread.hpp" +#include "runtime/nonJavaThread.hpp" class MMTkCollectorThread: public NamedThread { void* _context; diff --git a/openjdk/mmtkFinalizerThread.cpp b/openjdk/share/mmtkFinalizerThread.cpp similarity index 91% rename from openjdk/mmtkFinalizerThread.cpp rename to openjdk/share/mmtkFinalizerThread.cpp index f18f0e24..a5476bd1 100644 --- a/openjdk/mmtkFinalizerThread.cpp +++ b/openjdk/share/mmtkFinalizerThread.cpp @@ -30,6 +30,7 @@ #include "oops/oop.inline.hpp" #include "prims/jvmtiImpl.hpp" #include "runtime/interfaceSupport.inline.hpp" +#include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/mutex.hpp" #include "runtime/mutexLocker.hpp" @@ -45,14 +46,12 @@ MMTkFinalizerThread* MMTkFinalizerThread::instance = NULL; void MMTkFinalizerThread::initialize() { EXCEPTION_MARK; - HandleMark hm; - const char* name = "MMTk Finalizer Thread"; Handle string = java_lang_String::create_from_str(name, CHECK); // Initialize thread_oop to put it into the system threadGroup Handle thread_group (THREAD, Universe::system_thread_group()); - Handle thread_oop = JavaCalls::construct_new_instance(SystemDictionary::Thread_klass(), + Handle thread_oop = JavaCalls::construct_new_instance(vmClasses::Thread_klass(), vmSymbols::threadgroup_string_void_signature(), thread_group, string, @@ -74,7 +73,7 @@ void MMTkFinalizerThread::initialize() { java_lang_Thread::set_thread(thread_oop(), thread); java_lang_Thread::set_priority(thread_oop(), NearMaxPriority); java_lang_Thread::set_daemon(thread_oop()); - thread->set_threadObj(thread_oop()); + thread->set_threadOopHandles(thread_oop()); instance = thread; Threads::add(thread); @@ -88,9 +87,9 @@ void MMTkFinalizerThread::finalizer_thread_entry(JavaThread* thread, TRAPS) { // Wait until scheduled { ThreadBlockInVM tbivm(thread); - MutexLockerEx mu(this_thread->m, Mutex::_no_safepoint_check_flag); + MonitorLocker ml(this_thread->m, Mutex::_no_safepoint_check_flag); while (!this_thread->is_scheduled) { - this_thread->m->wait(Mutex::_no_safepoint_check_flag); + ml.wait(); } this_thread->is_scheduled = false; // Consume this request so we can accept the next. } @@ -103,10 +102,10 @@ void MMTkFinalizerThread::finalizer_thread_entry(JavaThread* thread, TRAPS) { // Invoke finalize() { - HandleMark hm; + HandleMark hm(this_thread); JavaValue ret(T_VOID); instanceHandle handle_obj(this_thread, obj); - TempNewSymbol finalize_method = SymbolTable::new_symbol("finalize", this_thread); + TempNewSymbol finalize_method = SymbolTable::new_symbol("finalize"); Symbol* sig = vmSymbols::void_method_signature(); JavaCalls::call_virtual(&ret, handle_obj, obj->klass(), finalize_method, sig, this_thread); @@ -120,12 +119,12 @@ void MMTkFinalizerThread::finalizer_thread_entry(JavaThread* thread, TRAPS) { MMTkFinalizerThread::MMTkFinalizerThread(ThreadFunction entry_point) : JavaThread(entry_point) { this->is_scheduled = false; - this->m = new Monitor(Mutex::suspend_resume, "mmtk-finalizer-monitor", true, Monitor::_safepoint_check_never); + this->m = new Monitor(Mutex::suspend_resume, "mmtk-finalizer-monitor", true); } void MMTkFinalizerThread::schedule() { assert(!Thread::current()->is_Java_thread(), "Supposed to be called by GC thread. Actually called by JavaThread."); - MutexLockerEx mu(this->m, Mutex::_no_safepoint_check_flag); + MutexLocker mu(this->m, Mutex::_no_safepoint_check_flag); if (!this->is_scheduled) { this->is_scheduled = true; this->m->notify(); diff --git a/openjdk/mmtkFinalizerThread.hpp b/openjdk/share/mmtkFinalizerThread.hpp similarity index 100% rename from openjdk/mmtkFinalizerThread.hpp rename to openjdk/share/mmtkFinalizerThread.hpp diff --git a/openjdk/mmtkHeap.cpp b/openjdk/share/mmtkHeap.cpp similarity index 75% rename from openjdk/mmtkHeap.cpp rename to openjdk/share/mmtkHeap.cpp index 09279351..d96dd54b 100644 --- a/openjdk/mmtkHeap.cpp +++ b/openjdk/share/mmtkHeap.cpp @@ -23,14 +23,18 @@ */ #include "precompiled.hpp" -#include "aot/aotLoader.hpp" #include "classfile/stringTable.hpp" +#include "classfile/classLoaderDataGraph.hpp" #include "code/codeCache.hpp" +#include "gc/shared/gcArguments.hpp" #include "gc/shared/gcHeapSummary.hpp" #include "gc/shared/gcLocker.inline.hpp" #include "gc/shared/gcWhen.hpp" +#include "gc/shared/oopStorageSet.inline.hpp" +#include "gc/shared/scavengableNMethods.hpp" #include "gc/shared/strongRootsScope.hpp" #include "gc/shared/weakProcessor.hpp" +#include "gc/shared/gcLocker.inline.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "mmtk.h" @@ -39,10 +43,17 @@ #include "mmtkUpcalls.hpp" #include "mmtkVMCompanionThread.hpp" #include "oops/oop.inline.hpp" +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif +#include "prims/jvmtiExport.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "runtime/thread.hpp" +#include "runtime/threads.hpp" #include "runtime/vmThread.hpp" #include "services/management.hpp" #include "services/memoryManager.hpp" @@ -58,28 +69,49 @@ last gc time object iterator??!! */ -//mmtkGCTaskManager* MMTkHeap::_mmtk_gc_task_manager = NULL; - +// ReservedHeapSpace will actually do the mmap when constructed. +// We reimplement it without mmaping, and fill in the fields manually using data from MMTk core. +class MMTkReservedHeapSpace : public ReservedHeapSpace { +public: + MMTkReservedHeapSpace(bool use_compressed_oops) + : ReservedHeapSpace(0, 0, 0) // When `size == 0`, the constructor of ReservedHeapSpace will return immediately. + { + uintptr_t start = (uintptr_t)starting_heap_address(); + uintptr_t end = (uintptr_t)last_heap_address(); + uintptr_t size = end - start; + + _base = (char*)start; + _size = size; + _noaccess_prefix = 0; + _alignment = HeapAlignment; + _page_size = 4096; // MMTk has been assuming 4096-byte pages, which is not always true. + _special = false; // from jfrVirtualMemory.cpp: "ReservedSpaces marked as special will have the entire memory pre-committed." + _fd_for_heap = -1; // The MMTk heap is not backed by a file descriptor. + } +}; MMTkHeap* MMTkHeap::_heap = NULL; -MMTkHeap::MMTkHeap(MMTkCollectorPolicy* policy) : +MMTkHeap::MMTkHeap() : CollectedHeap(), - _last_gc_time(0), - _collector_policy(policy), - _num_root_scan_tasks(0), + _mmtk_pool(nullptr), + _mmtk_manager(nullptr), _n_workers(0), - _gc_lock(new Monitor(Mutex::safepoint, "MMTkHeap::_gc_lock", true, Monitor::_safepoint_check_never)), - _soft_ref_policy() + _gc_lock(new Monitor(Mutex::nosafepoint, "MMTkHeap::_gc_lock", true)), + _num_root_scan_tasks(0), + _companion_thread(nullptr), + _soft_ref_policy(), + _last_gc_time(0) { _heap = this; } jint MMTkHeap::initialize() { assert(!UseTLAB , "should disable UseTLAB"); - const size_t min_heap_size = collector_policy()->min_heap_byte_size(); - const size_t max_heap_size = collector_policy()->max_heap_byte_size(); - // printf("policy max heap size %zu, min heap size %zu\n", heap_size, collector_policy()->min_heap_byte_size()); + assert(AllocateHeapAt == nullptr, "MMTk does not support file-backed heap."); + + const size_t min_heap_size = MinHeapSize; + const size_t max_heap_size = MaxHeapSize; if (UseCompressedOops) mmtk_enable_compressed_oops(); @@ -101,7 +133,7 @@ jint MMTkHeap::initialize() { set_mmtk_options(false); if (ThirdPartyHeapOptions != NULL) { - bool set_options = process_bulk(strdup(ThirdPartyHeapOptions)); + bool set_options = process_bulk(os::strdup(ThirdPartyHeapOptions)); guarantee(set_options, "Failed to set MMTk options. Please check if the options are valid: %s\n", ThirdPartyHeapOptions); } @@ -110,40 +142,31 @@ jint MMTkHeap::initialize() { guarantee(set_heap_size, "Failed to set MMTk heap size. Please check if the heap size is valid: min = %ld, max = %ld\n", min_heap_size, max_heap_size); openjdk_gc_init(&mmtk_upcalls); + // Cache the value here. It is a constant depending on the selected plan. The plan won't change from now, so value won't change. MMTkMutatorContext::max_non_los_default_alloc_bytes = get_max_non_los_default_alloc_bytes(); - //ReservedSpace heap_rs = Universe::reserve_heap(mmtk_heap_size, _collector_policy->heap_alignment()); - - //printf("inside mmtkHeap.cpp.. reserved base %x size %u \n", heap_rs.base(), heap_rs.size()); - - //os::trace_page_sizes("Heap", - // _collector_policy->min_heap_byte_size(), - // mmtk_heap_size, - // collector_policy()->space_alignment(), - // heap_rs.base(), - // heap_rs.size()); - - //_start = (HeapWord*)heap_rs.base(); - //_end = (HeapWord*)(heap_rs.base() + heap_rs.size()); + // Compute the memory range. + // Other GC in OpenJDK will do mmap when constructing ReservedHeapSpace, but MMTk does mmap internally. + // So we construct our special MMTkReservedHeapSpace which doesn't actually do mmap. + MMTkReservedHeapSpace heap_rs(UseCompressedOops); + initialize_reserved_region(heap_rs); // initializes this->_reserved - _start = (HeapWord*) starting_heap_address(); - _end = (HeapWord*) last_heap_address(); - // printf("start: %p, end: %p\n", _start, _end); if (UseCompressedOops) { - Universe::set_narrow_oop_base((address) mmtk_narrow_oop_base()); - Universe::set_narrow_oop_shift(mmtk_narrow_oop_shift()); - } - - initialize_reserved_region(_start, _end); + CompressedOops::initialize(heap_rs); + // Assert the base and the shift computed by MMTk and OpenJDK match. + address mmtk_base = (address)mmtk_narrow_oop_base(); + int mmtk_shift = mmtk_narrow_oop_shift(); + guarantee(mmtk_base == CompressedOops::base(), "MMTk and OpenJDK disagree with narrow oop base. MMTk: %p, OpenJDK: %p", mmtk_base, CompressedOops::base()); + guarantee(mmtk_shift == CompressedOops::shift(), "MMTk and OpenJDK disagree with narrow oop shift. MMTk: %d, OpenJDK: %d", mmtk_shift, CompressedOops::shift()); + } - MMTkBarrierSet* const barrier_set = new MMTkBarrierSet(reserved_region()); - //barrier_set->initialize(); + MMTkBarrierSet* const barrier_set = new MMTkBarrierSet(_reserved); BarrierSet::set_barrier_set(barrier_set); _companion_thread = new MMTkVMCompanionThread(); - if (!os::create_thread(_companion_thread, os::pgc_thread)) { + if (!os::create_thread(_companion_thread, os::gc_thread)) { fprintf(stderr, "Failed to create thread"); guarantee(false, "panic"); } @@ -175,10 +198,23 @@ void MMTkHeap::schedule_finalizer() { MMTkFinalizerThread::instance->schedule(); } +class MMTkIsScavengable : public BoolObjectClosure { + bool do_object_b(oop obj) { + return true; + } +}; + +static MMTkIsScavengable _is_scavengable; + void MMTkHeap::post_initialize() { CollectedHeap::post_initialize(); + + ScavengableNMethods::initialize(&_is_scavengable); + if (UseCompressedOops) { - mmtk_set_compressed_klass_base_and_shift((void*) Universe::narrow_klass_base(), (size_t) Universe::narrow_klass_shift()); + mmtk_set_compressed_klass_base_and_shift( + (void*)CompressedKlassPointers::base(), + (size_t)CompressedKlassPointers::shift()); } } @@ -295,9 +331,6 @@ void MMTkHeap::do_full_collection(bool clear_all_soft_refs) {//later when gc is } -// Return the CollectorPolicy for the heap -CollectorPolicy* MMTkHeap::collector_policy() const {return _collector_policy;}//OK - SoftRefPolicy* MMTkHeap::soft_ref_policy() {return &_soft_ref_policy;}//OK GrowableArray MMTkHeap::memory_managers() {//may cause error @@ -356,11 +389,9 @@ void MMTkHeap::prepare_for_verify() { void MMTkHeap::initialize_serviceability() {//OK + _mmtk_pool = new MMTkMemoryPool(_reserved, "MMTk pool", MinHeapSize, false); - - _mmtk_pool = new MMTkMemoryPool(_start, _end, "MMTk pool",collector_policy()->min_heap_byte_size(), false); - - _mmtk_manager = new GCMemoryManager("MMTk GC", "end of GC"); + _mmtk_manager = new GCMemoryManager("MMTk GC"); _mmtk_manager->add_pool(_mmtk_pool); } @@ -383,6 +414,11 @@ void MMTkHeap::print_tracing_info() const { //guarantee(false, "print tracing info not supported"); } +// Used to print information about locations in the hs_err file. +bool MMTkHeap::print_location(outputStream* st, void* addr) const { + guarantee(false, "print location not supported"); + return false; +} // Registering and unregistering an nmethod (compiled code) with the heap. // Override with specific mechanism for each specialized heap type. @@ -409,6 +445,11 @@ void MMTkHeap::register_nmethod(nmethod* nm) { // Register the nmethod mmtk_register_nmethod((void*) nm); } +// Callback for when nmethod is about to be deleted. +void MMTkHeap::flush_nmethod(nmethod* nm) { +} +void MMTkHeap::verify_nmethod(nmethod* nm) { +} void MMTkHeap::unregister_nmethod(nmethod* nm) { mmtk_unregister_nmethod((void*) nm); @@ -417,40 +458,21 @@ void MMTkHeap::unregister_nmethod(nmethod* nm) { // Heap verification void MMTkHeap::verify(VerifyOption option) {} -void MMTkHeap::scan_universe_roots(OopClosure& cl) { - Universe::oops_do(&cl); -} -void MMTkHeap::scan_jni_handle_roots(OopClosure& cl) { - JNIHandles::oops_do(&cl); -} -void MMTkHeap::scan_object_synchronizer_roots(OopClosure& cl) { - ObjectSynchronizer::oops_do(&cl); -} -void MMTkHeap::scan_management_roots(OopClosure& cl) { - Management::oops_do(&cl); -} -void MMTkHeap::scan_jvmti_export_roots(OopClosure& cl) { - JvmtiExport::oops_do(&cl); -} -void MMTkHeap::scan_aot_loader_roots(OopClosure& cl) { - AOTLoader::oops_do(&cl); -} -void MMTkHeap::scan_system_dictionary_roots(OopClosure& cl) { - SystemDictionary::oops_do(&cl); -} void MMTkHeap::scan_code_cache_roots(OopClosure& cl) { - MarkingCodeBlobClosure cb_cl(&cl, false); + MarkingCodeBlobClosure cb_cl(&cl, false, true); CodeCache::blobs_do(&cb_cl); } -void MMTkHeap::scan_string_table_roots(OopClosure& cl) { - StringTable::oops_do(&cl); -} void MMTkHeap::scan_class_loader_data_graph_roots(OopClosure& cl) { CLDToOopClosure cld_cl(&cl, false); ClassLoaderDataGraph::cld_do(&cld_cl); } +void MMTkHeap::scan_oop_storage_set_roots(OopClosure& cl) { + OopStorageSet::strong_oops_do(&cl); +} void MMTkHeap::scan_weak_processor_roots(OopClosure& cl) { - ResourceMark rm; + // XXX zixianc: I don't understand why this is removed in + // 24b90dd889da0ea58aaa2b2311ded6f262573830 + // ResourceMark rm; WeakProcessor::oops_do(&cl); // (really needed???) } void MMTkHeap::scan_vm_thread_roots(OopClosure& cl) { @@ -477,22 +499,12 @@ void MMTkHeap::scan_roots(OopClosure& cl) { Threads::possibly_parallel_oops_do(is_parallel, &cl, &cb_cl); // Global Roots - Universe::oops_do(&cl); - JNIHandles::oops_do(&cl); - ObjectSynchronizer::oops_do(&cl); - Management::oops_do(&cl); - JvmtiExport::oops_do(&cl); - if (UseAOT) AOTLoader::oops_do(&cl); - SystemDictionary::oops_do(&cl); { - MutexLockerEx lock(CodeCache_lock, Mutex::_no_safepoint_check_flag); + MutexLocker lock(CodeCache_lock, Mutex::_no_safepoint_check_flag); CodeCache::blobs_do(&cb_cl); } - if (is_parallel) { - StringTable::possibly_parallel_oops_do(NULL, &cl); - } else { - StringTable::oops_do(&cl); - } + + OopStorageSet::strong_oops_do(&cl); // Weak refs (really needed???) WeakProcessor::oops_do(&cl); @@ -507,6 +519,22 @@ HeapWord* MMTkHeap::mem_allocate_nonmove(size_t size, bool* gc_overhead_limit_wa return Thread::current()->third_party_heap_mutator.alloc(size << LogHeapWordSize, AllocatorLos); } +bool MMTkHeap::requires_barriers(stackChunkOop obj) const { + ShouldNotReachHere(); + return false; +} + +void MMTkHeap::pin_object(JavaThread* thread, oop obj) { + // TODO use mmtk-core pin_object + GCLocker::lock_critical(thread); +} + +void MMTkHeap::unpin_object(JavaThread* thread, oop obj) { + // TODO use mmtk-core unpin_object + GCLocker::unlock_critical(thread); +} + + /* * files with prints currently: * collectedHeap.inline.hpp, mmtkHeap.cpp, diff --git a/openjdk/mmtkHeap.hpp b/openjdk/share/mmtkHeap.hpp similarity index 85% rename from openjdk/mmtkHeap.hpp rename to openjdk/share/mmtkHeap.hpp index bc8d479d..8414b03d 100644 --- a/openjdk/mmtkHeap.hpp +++ b/openjdk/share/mmtkHeap.hpp @@ -27,16 +27,15 @@ #include "mmtkBarrierSet.hpp" #include "gc/shared/collectedHeap.hpp" -#include "gc/shared/collectorPolicy.hpp" #include "gc/shared/gcPolicyCounters.hpp" #include "gc/shared/gcWhen.hpp" #include "gc/shared/oopStorage.hpp" #include "gc/shared/oopStorageParState.hpp" +#include "gc/shared/space.hpp" #include "gc/shared/strongRootsScope.hpp" -#include "gc/shared/workgroup.hpp" +#include "gc/shared/softRefPolicy.hpp" #include "memory/iterator.hpp" #include "memory/metaspace.hpp" -#include "mmtkCollectorPolicy.hpp" #include "mmtkFinalizerThread.hpp" #include "mmtkMemoryPool.hpp" #include "utilities/growableArray.hpp" @@ -47,21 +46,23 @@ class MemoryPool; //class mmtkGCTaskManager; class MMTkVMCompanionThread; class MMTkHeap : public CollectedHeap { - MMTkCollectorPolicy* _collector_policy; - SoftRefPolicy _soft_ref_policy; MMTkMemoryPool* _mmtk_pool; GCMemoryManager* _mmtk_manager; - HeapWord* _start; - HeapWord* _end; - static MMTkHeap* _heap; size_t _n_workers; Monitor* _gc_lock; ContiguousSpace* _space; int _num_root_scan_tasks; MMTkVMCompanionThread* _companion_thread; + SoftRefPolicy _soft_ref_policy; + public: + jlong _last_gc_time; + +private: + static MMTkHeap* _heap; - MMTkHeap(MMTkCollectorPolicy* policy); +public: + MMTkHeap(); void schedule_finalizer(); @@ -132,9 +133,6 @@ class MMTkHeap : public CollectedHeap { void do_full_collection(bool clear_all_soft_refs); - // Return the CollectorPolicy for the heap - CollectorPolicy* collector_policy() const ; - SoftRefPolicy* soft_ref_policy(); GrowableArray memory_managers() ; @@ -143,6 +141,9 @@ class MMTkHeap : public CollectedHeap { // Iterate over all objects, calling "cl.do_object" on each. void object_iterate(ObjectClosure* cl); + void pin_object(JavaThread* thread, oop obj); + void unpin_object(JavaThread* thread, oop obj); + // Similar to object_iterate() except iterates only // over live objects. void safe_object_iterate(ObjectClosure* cl) ; @@ -181,14 +182,19 @@ class MMTkHeap : public CollectedHeap { // Default implementation does nothing. void print_tracing_info() const ; + bool print_location(outputStream* st, void* addr) const; + + bool requires_barriers(stackChunkOop obj) const; + + void register_nmethod(nmethod* nm); + void unregister_nmethod(nmethod* nm); + + void flush_nmethod(nmethod* nm); + void verify_nmethod(nmethod* nm); // An object is scavengable if its location may move during a scavenge. // (A scavenge is a GC which is not a full GC.) inline bool is_scavengable(oop obj) { return true; } - // Registering and unregistering an nmethod (compiled code) with the heap. - // Override with specific mechanism for each specialized heap type. - virtual void register_nmethod(nmethod* nm); - virtual void unregister_nmethod(nmethod* nm); // Heap verification void verify(VerifyOption option); @@ -199,20 +205,11 @@ class MMTkHeap : public CollectedHeap { void scan_roots_in_all_mutator_threads(OopClosure& cl); - void scan_universe_roots(OopClosure& cl); - void scan_jni_handle_roots(OopClosure& cl); - void scan_object_synchronizer_roots(OopClosure& cl); - void scan_management_roots(OopClosure& cl); - void scan_jvmti_export_roots(OopClosure& cl); - void scan_aot_loader_roots(OopClosure& cl); - void scan_system_dictionary_roots(OopClosure& cl); void scan_code_cache_roots(OopClosure& cl); - void scan_string_table_roots(OopClosure& cl); void scan_class_loader_data_graph_roots(OopClosure& cl); + void scan_oop_storage_set_roots(OopClosure& cl); void scan_weak_processor_roots(OopClosure& cl); void scan_vm_thread_roots(OopClosure& cl); - - jlong _last_gc_time; }; diff --git a/openjdk/mmtkMemoryPool.cpp b/openjdk/share/mmtkMemoryPool.cpp similarity index 78% rename from openjdk/mmtkMemoryPool.cpp rename to openjdk/share/mmtkMemoryPool.cpp index 1577b448..f3b6b682 100644 --- a/openjdk/mmtkMemoryPool.cpp +++ b/openjdk/share/mmtkMemoryPool.cpp @@ -25,19 +25,20 @@ #include "precompiled.hpp" #include "mmtkMemoryPool.hpp" -MMTkMemoryPool::MMTkMemoryPool(HeapWord* start, HeapWord* end, - const char* name, size_t init_size, +MMTkMemoryPool::MMTkMemoryPool(MemRegion region, + const char* name, + size_t init_size, bool support_usage_threshold) : - CollectedMemoryPool(name, init_size, - pointer_delta(start, end)*HeapWordSize, support_usage_threshold), - - _start(start), _end(end), _used_in_bytes(0){ + CollectedMemoryPool(name, init_size, region.byte_size(), support_usage_threshold), + _reserved(region), + _used_in_bytes(0) +{ } MemoryUsage MMTkMemoryPool::get_memory_usage() { size_t maxSize = (available_for_allocation() ? max_size() : 0); size_t used = used_in_bytes(); - size_t committed = pointer_delta(_start, _end)*HeapWordSize; + size_t committed = _reserved.byte_size(); return MemoryUsage(initial_size(), used, committed, maxSize); } diff --git a/openjdk/mmtkMemoryPool.hpp b/openjdk/share/mmtkMemoryPool.hpp similarity index 86% rename from openjdk/mmtkMemoryPool.hpp rename to openjdk/share/mmtkMemoryPool.hpp index 34e28e20..a0983f55 100644 --- a/openjdk/mmtkMemoryPool.hpp +++ b/openjdk/share/mmtkMemoryPool.hpp @@ -30,16 +30,15 @@ class MMTkMemoryPool : public CollectedMemoryPool { private: - HeapWord* _start; - HeapWord* _end; + MemRegion _reserved; size_t _used_in_bytes; public: - MMTkMemoryPool(HeapWord* start, HeapWord* end, const char* name, size_t init_size, bool support_usage_threshold); + MMTkMemoryPool(MemRegion region, const char* name, size_t init_size, bool support_usage_threshold); MemoryUsage get_memory_usage(); size_t used_in_bytes() { return _used_in_bytes; } - size_t max_size() const { return pointer_delta(_start, _end)*HeapWordSize; } + size_t max_size() const { return _reserved.byte_size(); } }; diff --git a/openjdk/mmtkMutator.cpp b/openjdk/share/mmtkMutator.cpp similarity index 91% rename from openjdk/mmtkMutator.cpp rename to openjdk/share/mmtkMutator.cpp index acad0a92..698acd7b 100644 --- a/openjdk/mmtkMutator.cpp +++ b/openjdk/share/mmtkMutator.cpp @@ -6,8 +6,8 @@ size_t MMTkMutatorContext::max_non_los_default_alloc_bytes = 0; MMTkMutatorContext MMTkMutatorContext::bind(::Thread* current) { - if (FREE_LIST_ALLOCATOR_SIZE != sizeof(FreeListAllocator)) { - printf("ERROR: Unmatched free list allocator size: rs=%zu cpp=%zu\n", FREE_LIST_ALLOCATOR_SIZE, sizeof(FreeListAllocator)); + if (FREE_LIST_ALLOCATOR_SIZE != sizeof(MMTkFreeListAllocator)) { + printf("ERROR: Unmatched free list allocator size: rs=%zu cpp=%zu\n", FREE_LIST_ALLOCATOR_SIZE, sizeof(MMTkFreeListAllocator)); guarantee(false, "ERROR"); } return *((MMTkMutatorContext*) ::bind_mutator((void*) current)); diff --git a/openjdk/mmtkMutator.hpp b/openjdk/share/mmtkMutator.hpp similarity index 96% rename from openjdk/mmtkMutator.hpp rename to openjdk/share/mmtkMutator.hpp index 5498df9c..33f079d3 100644 --- a/openjdk/mmtkMutator.hpp +++ b/openjdk/share/mmtkMutator.hpp @@ -69,7 +69,7 @@ struct FLBlockList { char lock; }; -struct FreeListAllocator { +struct MMTkFreeListAllocator { void* tls; void* space; void* context; @@ -94,7 +94,7 @@ struct Allocators { LargeObjectAllocator large_object[MAX_LARGE_OBJECT_ALLOCATORS]; MallocAllocator malloc[MAX_MALLOC_ALLOCATORS]; ImmixAllocator immix[MAX_IMMIX_ALLOCATORS]; - FreeListAllocator free_list[MAX_FREE_LIST_ALLOCATORS]; + MMTkFreeListAllocator free_list[MAX_FREE_LIST_ALLOCATORS]; MarkCompactAllocator markcompact[MAX_MARK_COMPACT_ALLOCATORS]; }; diff --git a/openjdk/mmtkRootsClosure.hpp b/openjdk/share/mmtkRootsClosure.hpp similarity index 90% rename from openjdk/mmtkRootsClosure.hpp rename to openjdk/share/mmtkRootsClosure.hpp index d9513d81..90ed2d46 100644 --- a/openjdk/mmtkRootsClosure.hpp +++ b/openjdk/share/mmtkRootsClosure.hpp @@ -14,7 +14,7 @@ class MMTkRootsClosure : public OopClosure { size_t _cursor; template - void do_oop_work(T* p, bool narrow) { + inline void do_oop_work(T* p, bool narrow) { T heap_oop = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(heap_oop)) { if (UseCompressedOops && !narrow) { @@ -100,4 +100,14 @@ class MMTkScanObjectClosure : public BasicOopIterateClosure { // } // }; +class CodeBlobFixRelocationClosure: public CodeBlobClosure { + public: + inline virtual void do_code_blob(CodeBlob* cb) { + nmethod* nm = cb->as_nmethod_or_null(); + if (nm != NULL) { + nm->fix_oop_relocations(); + } + } +}; + #endif // MMTK_OPENJDK_MMTK_ROOTS_CLOSURE_HPP diff --git a/openjdk/mmtkUpcalls.cpp b/openjdk/share/mmtkUpcalls.cpp similarity index 84% rename from openjdk/mmtkUpcalls.cpp rename to openjdk/share/mmtkUpcalls.cpp index ac1336b0..34c29b78 100644 --- a/openjdk/mmtkUpcalls.cpp +++ b/openjdk/share/mmtkUpcalls.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderDataGraph.hpp" #include "classfile/stringTable.hpp" #include "code/nmethod.hpp" #include "memory/iterator.inline.hpp" @@ -32,13 +33,18 @@ #include "mmtkRootsClosure.hpp" #include "mmtkUpcalls.hpp" #include "mmtkVMCompanionThread.hpp" +#include "oops/access.hpp" +#include "runtime/interfaceSupport.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.hpp" +#include "runtime/threads.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/threadSMR.hpp" #include "runtime/vmThread.hpp" +#include "runtime/osThread.hpp" #include "utilities/debug.hpp" // Note: This counter must be accessed using the Atomic class. @@ -46,7 +52,6 @@ static volatile size_t mmtk_start_the_world_count = 0; static void mmtk_stop_all_mutators(void *tls, MutatorClosure closure) { ClassLoaderDataGraph::clear_claimed_marks(); - CodeCache::gc_prologue(); #if COMPILER2_OR_JVMCI DerivedPointerTable::clear(); #endif @@ -67,11 +72,13 @@ static void mmtk_stop_all_mutators(void *tls, MutatorClosure closure) { static void mmtk_resume_mutators(void *tls) { nmethod::oops_do_marking_epilogue(); // ClassLoaderDataGraph::purge(); - CodeCache::gc_epilogue(); - JvmtiExport::gc_epilogue(); #if COMPILER2_OR_JVMCI DerivedPointerTable::update_pointers(); #endif + { + CodeBlobFixRelocationClosure cb_cl; + CodeCache::blobs_do(&cb_cl); + } // Note: we don't have to hold gc_lock to increment the counter. // The increment has to be done before mutators can be resumed (from `block_for_gc` or yieldpoints). @@ -84,14 +91,14 @@ static void mmtk_resume_mutators(void *tls) { log_debug(gc)("Notifying mutators blocking on the start-the-world counter..."); { - MutexLockerEx locker(MMTkHeap::heap()->gc_lock(), Mutex::_no_safepoint_check_flag); + MutexLocker locker(MMTkHeap::heap()->gc_lock(), Mutex::_no_safepoint_check_flag); MMTkHeap::heap()->gc_lock()->notify_all(); } log_debug(gc)("Notifying mutators blocking on Heap_lock for reference pending list..."); // Note: That's the ReferenceHandler thread. { - MutexLockerEx x(Heap_lock, Mutex::_no_safepoint_check_flag); + MutexLocker x(Heap_lock, Mutex::_no_safepoint_check_flag); if (Universe::has_reference_pending_list()) { Heap_lock->notify_all(); } @@ -104,7 +111,7 @@ static void mmtk_spawn_gc_thread(void* tls, int kind, void* ctx) { case GC_THREAD_KIND_WORKER: { MMTkHeap::heap()->new_collector_thread(); MMTkCollectorThread* t = new MMTkCollectorThread(ctx); - if (!os::create_thread(t, os::pgc_thread)) { + if (!os::create_thread(t, os::gc_thread)) { printf("Failed to create thread"); guarantee(false, "panic"); } @@ -142,12 +149,12 @@ static void mmtk_block_for_gc() { ThreadBlockInVM tbivm(thread); // No safepoint check. We are already in safepoint. - MutexLockerEx locker(MMTkHeap::heap()->gc_lock(), Mutex::_no_safepoint_check_flag); + MutexLocker locker(MMTkHeap::heap()->gc_lock(), Mutex::_no_safepoint_check_flag); while (Atomic::load(&mmtk_start_the_world_count) < next_count) { // wait() may wake up spuriously, but the authoritative condition for unblocking is // mmtk_start_the_world_count being incremented. - MMTkHeap::heap()->gc_lock()->wait(Mutex::_no_safepoint_check_flag); + MMTkHeap::heap()->gc_lock()->wait_without_safepoint_check(); } } log_debug(gc)("Resumed after GC finished."); @@ -197,6 +204,7 @@ static void mmtk_scan_roots_in_mutator_thread(SlotsClosure closure, void* tls) { ResourceMark rm; JavaThread* thread = (JavaThread*) tls; MMTkRootsClosure cl(closure); + MarkingCodeBlobClosure cb_cl(&cl, false, true); thread->oops_do(&cl, NULL); } @@ -247,6 +255,16 @@ static int static_oop_field_count_offset() { } static size_t compute_klass_mem_layout_checksum() { + // printf("C++: Klass %ld, InstanceKlass %ld, InstanceRefKlass %ld, InstanceMirrorKlass %ld, InstanceClassLoaderKlass %ld, TypeArrayKlass %ld, ObjArrayKlass %ld, ArrayKlass %ld\n", + // sizeof(Klass) + // , sizeof(InstanceKlass) + // , sizeof(InstanceRefKlass) + // , sizeof(InstanceMirrorKlass) + // , sizeof(InstanceClassLoaderKlass) + // , sizeof(TypeArrayKlass) + // , sizeof(ObjArrayKlass) + // , sizeof(ArrayKlass) + // ); return sizeof(Klass) ^ sizeof(InstanceKlass) ^ sizeof(InstanceRefKlass) @@ -257,11 +275,11 @@ static size_t compute_klass_mem_layout_checksum() { } static int referent_offset() { - return java_lang_ref_Reference::referent_offset; + return java_lang_ref_Reference::referent_offset(); } static int discovered_offset() { - return java_lang_ref_Reference::discovered_offset; + return java_lang_ref_Reference::discovered_offset(); } static char* dump_object_string(void* object) { @@ -273,16 +291,9 @@ static void mmtk_schedule_finalizer() { MMTkHeap::heap()->schedule_finalizer(); } -static void mmtk_scan_universe_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_universe_roots(cl); } -static void mmtk_scan_jni_handle_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_jni_handle_roots(cl); } -static void mmtk_scan_object_synchronizer_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_object_synchronizer_roots(cl); } -static void mmtk_scan_management_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_management_roots(cl); } -static void mmtk_scan_jvmti_export_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_jvmti_export_roots(cl); } -static void mmtk_scan_aot_loader_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_aot_loader_roots(cl); } -static void mmtk_scan_system_dictionary_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_system_dictionary_roots(cl); } static void mmtk_scan_code_cache_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_code_cache_roots(cl); } -static void mmtk_scan_string_table_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_string_table_roots(cl); } static void mmtk_scan_class_loader_data_graph_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_class_loader_data_graph_roots(cl); } +static void mmtk_scan_oop_storage_set_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_oop_storage_set_roots(cl); } static void mmtk_scan_weak_processor_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_weak_processor_roots(cl); } static void mmtk_scan_vm_thread_roots(SlotsClosure closure) { MMTkRootsClosure cl(closure); MMTkHeap::heap()->scan_vm_thread_roots(cl); } @@ -308,13 +319,13 @@ static void mmtk_enqueue_references(void** objects, size_t len) { for (size_t i = 0; i < len; i++) { oop reff = (oop) objects[i]; if (prev != NULL) { - HeapAccess::oop_store_at(prev, java_lang_ref_Reference::discovered_offset, reff); + HeapAccess::oop_store_at(prev, java_lang_ref_Reference::discovered_offset(), reff); } prev = reff; } oop old = Universe::swap_reference_pending_list(prev); - HeapAccess::oop_store_at(prev, java_lang_ref_Reference::discovered_offset, old); + HeapAccess::oop_store_at(prev, java_lang_ref_Reference::discovered_offset(), old); assert(Universe::has_reference_pending_list(), "Reference pending list is empty after swap"); } @@ -340,16 +351,9 @@ OpenJDK_Upcalls mmtk_upcalls = { dump_object_string, mmtk_scan_roots_in_all_mutator_threads, mmtk_scan_roots_in_mutator_thread, - mmtk_scan_universe_roots, - mmtk_scan_jni_handle_roots, - mmtk_scan_object_synchronizer_roots, - mmtk_scan_management_roots, - mmtk_scan_jvmti_export_roots, - mmtk_scan_aot_loader_roots, - mmtk_scan_system_dictionary_roots, mmtk_scan_code_cache_roots, - mmtk_scan_string_table_roots, mmtk_scan_class_loader_data_graph_roots, + mmtk_scan_oop_storage_set_roots, mmtk_scan_weak_processor_roots, mmtk_scan_vm_thread_roots, mmtk_number_of_mutators, diff --git a/openjdk/mmtkUpcalls.hpp b/openjdk/share/mmtkUpcalls.hpp similarity index 100% rename from openjdk/mmtkUpcalls.hpp rename to openjdk/share/mmtkUpcalls.hpp diff --git a/openjdk/mmtkVMCompanionThread.cpp b/openjdk/share/mmtkVMCompanionThread.cpp similarity index 92% rename from openjdk/mmtkVMCompanionThread.cpp rename to openjdk/share/mmtkVMCompanionThread.cpp index f0bd2fe3..16171987 100644 --- a/openjdk/mmtkVMCompanionThread.cpp +++ b/openjdk/share/mmtkVMCompanionThread.cpp @@ -33,10 +33,9 @@ MMTkVMCompanionThread::MMTkVMCompanionThread(): _desired_state(_threads_resumed), _reached_state(_threads_resumed) { set_name("MMTK VM Companion Thread"); - _lock = new Monitor(Monitor::nonleaf, + _lock = new Monitor(Mutex::nosafepoint, "MMTkVMCompanionThread::_lock", - true, - Monitor::_safepoint_check_never); + true); } MMTkVMCompanionThread::~MMTkVMCompanionThread() { @@ -44,16 +43,14 @@ MMTkVMCompanionThread::~MMTkVMCompanionThread() { } void MMTkVMCompanionThread::run() { - this->initialize_named_thread(); - for (;;) { // Wait for suspend request log_trace(gc)("MMTkVMCompanionThread: Waiting for suspend request..."); { - MutexLockerEx locker(_lock, Mutex::_no_safepoint_check_flag); + MutexLocker locker(_lock, Mutex::_no_safepoint_check_flag); assert(_reached_state == _threads_resumed, "Threads should be running at this moment."); while (_desired_state != _threads_suspended) { - _lock->wait(Mutex::_no_safepoint_check_flag); + _lock->wait_without_safepoint_check(); } assert(_reached_state == _threads_resumed, "Threads should still be running at this moment."); } @@ -84,14 +81,14 @@ void MMTkVMCompanionThread::request(stw_state desired_state, bool wait_until_rea assert(Thread::current() != this, "Requests can only be made by GC threads. Found companion thread."); assert(!Thread::current()->is_Java_thread(), "Requests can only be made by GC threads. Found Java thread."); - MutexLockerEx locker(_lock, Mutex::_no_safepoint_check_flag); + MutexLocker locker(_lock, Mutex::_no_safepoint_check_flag); assert(_desired_state != desired_state, "State %d already requested.", desired_state); _desired_state = desired_state; _lock->notify_all(); if (wait_until_reached) { while (_reached_state != desired_state) { - _lock->wait(Mutex::_no_safepoint_check_flag); + _lock->wait_without_safepoint_check(); } } } @@ -103,11 +100,11 @@ void MMTkVMCompanionThread::wait_for_reached(stw_state desired_state) { assert(Thread::current() != this, "Supposed to be called by GC threads. Found companion thread."); assert(!Thread::current()->is_Java_thread(), "Supposed to be called by GC threads. Found Java thread."); - MutexLockerEx locker(_lock, Mutex::_no_safepoint_check_flag); + MutexLocker locker(_lock, Mutex::_no_safepoint_check_flag); assert(_desired_state == desired_state, "State %d not requested.", desired_state); while (_reached_state != desired_state) { - _lock->wait(Mutex::_no_safepoint_check_flag); + _lock->wait_without_safepoint_check(); } } @@ -118,7 +115,7 @@ void MMTkVMCompanionThread::do_mmtk_stw_operation() { assert(Thread::current()->is_VM_thread(), "do_mmtk_stw_operation can only be executed by the VM thread"); { - MutexLockerEx locker(_lock, Mutex::_no_safepoint_check_flag); + MutexLocker locker(_lock, Mutex::_no_safepoint_check_flag); // Tell the waiter thread that Java threads have stopped at yieldpoints. _reached_state = _threads_suspended; @@ -127,7 +124,7 @@ void MMTkVMCompanionThread::do_mmtk_stw_operation() { // Wait until resume-the-world is requested while (_desired_state != _threads_resumed) { - _lock->wait(Mutex::_no_safepoint_check_flag); + _lock->wait_without_safepoint_check(); } // Tell the waiter thread that Java threads will eventually resume from yieldpoints. This diff --git a/openjdk/mmtkVMCompanionThread.hpp b/openjdk/share/mmtkVMCompanionThread.hpp similarity index 100% rename from openjdk/mmtkVMCompanionThread.hpp rename to openjdk/share/mmtkVMCompanionThread.hpp diff --git a/openjdk/mmtkVMOperation.cpp b/openjdk/share/mmtkVMOperation.cpp similarity index 100% rename from openjdk/mmtkVMOperation.cpp rename to openjdk/share/mmtkVMOperation.cpp diff --git a/openjdk/mmtkVMOperation.hpp b/openjdk/share/mmtkVMOperation.hpp similarity index 100% rename from openjdk/mmtkVMOperation.hpp rename to openjdk/share/mmtkVMOperation.hpp diff --git a/openjdk/thirdPartyHeap.cpp b/openjdk/share/thirdPartyHeap.cpp similarity index 100% rename from openjdk/thirdPartyHeap.cpp rename to openjdk/share/thirdPartyHeap.cpp diff --git a/openjdk/thirdPartyHeap.hpp b/openjdk/share/thirdPartyHeap.hpp similarity index 100% rename from openjdk/thirdPartyHeap.hpp rename to openjdk/share/thirdPartyHeap.hpp diff --git a/openjdk/thirdPartyHeapArguments.cpp b/openjdk/share/thirdPartyHeapArguments.cpp similarity index 86% rename from openjdk/thirdPartyHeapArguments.cpp rename to openjdk/share/thirdPartyHeapArguments.cpp index 39f5713c..a3acb3b2 100644 --- a/openjdk/thirdPartyHeapArguments.cpp +++ b/openjdk/share/thirdPartyHeapArguments.cpp @@ -24,9 +24,8 @@ #include "precompiled.hpp" #include "gc/shared/adaptiveSizePolicy.hpp" -#include "gc/shared/collectorPolicy.hpp" -#include "gc/shared/gcArguments.inline.hpp" -#include "mmtkCollectorPolicy.hpp" +#include "gc/shared/gcArguments.hpp" +#include "gc/shared/workerPolicy.hpp" #include "mmtkHeap.hpp" #include "runtime/globals_extension.hpp" #include "runtime/globals.hpp" @@ -36,7 +35,7 @@ #include "utilities/defaultStream.hpp" size_t ThirdPartyHeapArguments::conservative_max_heap_alignment() { - return CollectorPolicy::compute_heap_alignment(); + return compute_heap_alignment(); } void ThirdPartyHeapArguments::initialize() { @@ -44,7 +43,7 @@ void ThirdPartyHeapArguments::initialize() { assert(UseThirdPartyHeap , "Error, should UseThirdPartyHeap"); FLAG_SET_DEFAULT(UseTLAB, false); FLAG_SET_DEFAULT(UseCompressedClassPointers, UseCompressedOops); - FLAG_SET_DEFAULT(ParallelGCThreads, Abstract_VM_Version::parallel_worker_threads()); + FLAG_SET_DEFAULT(ParallelGCThreads, WorkerPolicy::parallel_worker_threads()); if (ParallelGCThreads == 0) { assert(!FLAG_IS_DEFAULT(ParallelGCThreads), "ParallelGCThreads should not be 0."); vm_exit_during_initialization("The flag -XX:+UseUseThirdPartyHeap can not be combined with -XX:ParallelGCThreads=0", NULL); @@ -53,6 +52,11 @@ void ThirdPartyHeapArguments::initialize() { // make sure to add appropriate code to MMTkHeap::set_mmtk_options. } +void ThirdPartyHeapArguments::initialize_alignments() { + SpaceAlignment = 1 << 19; + HeapAlignment = SpaceAlignment; +} + CollectedHeap* ThirdPartyHeapArguments::create_heap() { - return create_heap_with_policy(); + return new MMTkHeap(); } diff --git a/openjdk/thirdPartyHeapArguments.hpp b/openjdk/share/thirdPartyHeapArguments.hpp similarity index 96% rename from openjdk/thirdPartyHeapArguments.hpp rename to openjdk/share/thirdPartyHeapArguments.hpp index eb6fddc3..bb0bae3e 100644 --- a/openjdk/thirdPartyHeapArguments.hpp +++ b/openjdk/share/thirdPartyHeapArguments.hpp @@ -30,7 +30,8 @@ class CollectedHeap; class ThirdPartyHeapArguments : public GCArguments { -public: +private: + virtual void initialize_alignments(); virtual void initialize(); virtual size_t conservative_max_heap_alignment(); virtual CollectedHeap* create_heap(); diff --git a/openjdk/thirdPartyHeapBarrierSet.hpp b/openjdk/share/thirdPartyHeapBarrierSet.hpp similarity index 100% rename from openjdk/thirdPartyHeapBarrierSet.hpp rename to openjdk/share/thirdPartyHeapBarrierSet.hpp diff --git a/openjdk/thirdPartyHeapBarrierSetC2.hpp b/openjdk/share/thirdPartyHeapBarrierSetC2.hpp similarity index 100% rename from openjdk/thirdPartyHeapBarrierSetC2.hpp rename to openjdk/share/thirdPartyHeapBarrierSetC2.hpp diff --git a/openjdk/thirdPartyHeapMutator.hpp b/openjdk/share/thirdPartyHeapMutator.hpp similarity index 100% rename from openjdk/thirdPartyHeapMutator.hpp rename to openjdk/share/thirdPartyHeapMutator.hpp diff --git a/openjdk/thirdPartyHeapVMOperation.cpp b/openjdk/share/thirdPartyHeapVMOperation.cpp similarity index 96% rename from openjdk/thirdPartyHeapVMOperation.cpp rename to openjdk/share/thirdPartyHeapVMOperation.cpp index f0f97a57..8838eac1 100644 --- a/openjdk/thirdPartyHeapVMOperation.cpp +++ b/openjdk/share/thirdPartyHeapVMOperation.cpp @@ -23,4 +23,4 @@ */ #include "precompiled.hpp" -#include "thirdPartyHeapVMOperation.hpp" \ No newline at end of file +#include "thirdPartyHeapVMOperation.hpp" diff --git a/openjdk/thirdPartyHeapVMOperation.hpp b/openjdk/share/thirdPartyHeapVMOperation.hpp similarity index 96% rename from openjdk/thirdPartyHeapVMOperation.hpp rename to openjdk/share/thirdPartyHeapVMOperation.hpp index 2a0b6d91..163ebaff 100644 --- a/openjdk/thirdPartyHeapVMOperation.hpp +++ b/openjdk/share/thirdPartyHeapVMOperation.hpp @@ -33,4 +33,4 @@ class VM_ThirdPartyOperation : public VM_Operation { } }; -#endif // THIRD_PARTY_HEAP_VM_OPERATION_H \ No newline at end of file +#endif // THIRD_PARTY_HEAP_VM_OPERATION_H