diff --git a/.github/workflows/IKVM.yml b/.github/workflows/IKVM.yml index 8abda51813..f44b1e07b2 100644 --- a/.github/workflows/IKVM.yml +++ b/.github/workflows/IKVM.yml @@ -22,89 +22,37 @@ env: NATIVE_SDK_VERSION: "20240614.1" jobs: - build-openjdk: - name: Build OpenJDK + build-jtreg: + name: Build OpenJDK Test Harness runs-on: ubuntu-latest steps: - name: Checkout Source uses: actions/checkout@v4 with: submodules: recursive - - name: Cache OpenJDK Build - uses: actions/cache@v4 - with: - path: openjdk/build/linux-x86_64-normal-server-release - key: openjdk-build-linux-x86_64-normal-server-release--${{ runner.os }}--${{ hashFiles('openjdk/**', '!openjdk/build') }}-10 - - name: Check OpenJDK Build Stamp - id: openjdk-build-stamp - uses: andstor/file-existence-action@v3 - with: - files: openjdk/build/linux-x86_64-normal-server-release/stamp - - name: Fetch OpenJDK 7 - if: steps.openjdk-build-stamp.outputs.files_exists != 'true' - run: | - mkdir -p openjdk/build && - curl -o openjdk/build/openjdk-7u75-b13-linux-x64-18_dec_2014.tar.gz "https://download.java.net/openjdk/jdk7u75/ri/openjdk-7u75-b13-linux-x64-18_dec_2014.tar.gz" && - tar xzvf openjdk/build/openjdk-7u75-b13-linux-x64-18_dec_2014.tar.gz -C openjdk/build - - name: Build OpenJDK - if: steps.openjdk-build-stamp.outputs.files_exists != 'true' - uses: docker://debian/eol:lenny - with: - args: > - /bin/bash -c " - echo 'deb http://archive.debian.org/debian/ lenny main' > /etc/apt/sources.list && - apt-get update && - apt-get install -y \ - build-essential \ - unzip \ - zip \ - curl \ - gcc-4.3 \ - g++-4.3 \ - libx11-dev \ - libxext-dev \ - libxrender-dev \ - libxtst-dev \ - libxt-dev \ - libxi-dev \ - libcups2-dev \ - libasound2-dev \ - libfreetype6-dev \ - libfontconfig1-dev && - cd openjdk && - JAVA_HOME=build/java-se-7u75-ri bash ./configure && - make DISABLE_HOTSPOT_OS_VERSION_CHECK=ok images && - touch build/linux-x86_64-normal-server-release/stamp" - - name: Update OpenJDK Attributes - run: | - sudo chown -R `id -u`:`id -g` linux-x86_64-normal-server-release && \ - sudo chmod -R +rwx linux-x86_64-normal-server-release/images/j2sdk-image/bin - working-directory: openjdk/build - - name: Package OpenJDK - run: zip -r /tmp/openjdk-build-linux-x86_64-normal-server-release.zip linux-x86_64-normal-server-release/* - working-directory: openjdk/build - - name: Upload OpenJDK - uses: actions/upload-artifact@v4 - with: - name: openjdk-build-linux-x86_64-normal-server-release - path: /tmp/openjdk-build-linux-x86_64-normal-server-release.zip - name: Cache OpenJDK Test Harness Build uses: actions/cache@v4 with: - path: jtreg/build - key: jtreg-build--${{ runner.os }}--${{ hashFiles('jtreg/**', 'openjdk/build/linux-x86_64-normal-server-release/images/j2sdk-image', '!jtreg/build') }}-6 + path: ext/jtreg/build + key: jtreg-build--${{ runner.os }}--${{ hashFiles('ext/jtreg/**') }}-8 - name: Check OpenJDK Test Harness Build Stamp id: jtreg-build-stamp uses: andstor/file-existence-action@v3 with: - files: jtreg/build/stamp + files: ext/jtreg/build/stamp + - name: Install Java + run: | + sudo apt-get update && \ + sudo apt-get install -y \ + openjdk-8-jdk-headless && \ + echo "JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64" >> $GITHUB_ENV - name: Build OpenJDK Test Harness if: steps.jtreg-build-stamp.outputs.files_exists != 'true' - run: WGET_OPTS='-U Mozilla/5.0' bash make/build-all.sh `realpath ../openjdk/build/linux-x86_64-normal-server-release/images/j2sdk-image` && touch build/stamp - working-directory: jtreg + run: WGET_OPTS='-U Mozilla/5.0' bash make/build-all.sh $JAVA_HOME && touch build/stamp + working-directory: ext/jtreg - name: Package OpenJDK Test Harness run: zip -r /tmp/jtreg-build.zip build - working-directory: jtreg + working-directory: ext/jtreg - name: Upload OpenJDK Test Harness uses: actions/upload-artifact@v4 with: @@ -113,7 +61,7 @@ jobs: build-ikvm: name: Build IKVM needs: - - build-openjdk + - build-jtreg timeout-minutes: 720 runs-on: ubuntu-24.04 env: @@ -181,6 +129,7 @@ jobs: with: crate: apple-codesign version: latest + locked: false - name: Install GitVersion uses: gittools/actions/gitversion/setup@v1 with: @@ -190,20 +139,13 @@ jobs: with: useConfigFile: true configFilePath: GitVersion.yml - - name: Download OpenJDK 8 Build - uses: actions/download-artifact@v4 - with: - name: openjdk-build-linux-x86_64-normal-server-release - path: /tmp - - name: Restore OpenJDK 8 Build - run: mkdir -p openjdk/build && cd openjdk/build && unzip /tmp/openjdk-build-linux-x86_64-normal-server-release.zip && rm /tmp/openjdk-build-linux-x86_64-normal-server-release.zip - name: Download JTReg Build uses: actions/download-artifact@v4 with: name: jtreg-build path: /tmp - name: Restore JTReg Build - run: mkdir -p jtreg && cd jtreg && unzip /tmp/jtreg-build.zip && rm /tmp/jtreg-build.zip + run: mkdir -p ext/jtreg && cd ext/jtreg && unzip /tmp/jtreg-build.zip && rm /tmp/jtreg-build.zip - name: Download Native SDKs uses: robinraju/release-downloader@v1.9 with: @@ -212,6 +154,12 @@ jobs: fileName: "*.tar.gz" out-file-path: ext/ikvm-native-sdk extract: true + - name: Add NuGet Source (GitHub) + shell: pwsh + run: dotnet nuget add source --username USERNAME --password $env:GITHUB_TOKEN --store-password-in-clear-text --name ikvm $env:GITHUB_REPOS + env: + GITHUB_REPOS: https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: NuGet Restore run: dotnet restore IKVM.sln - name: Build Artifacts @@ -282,16 +230,6 @@ jobs: path: /tmp/jdk.tar.gz - name: Delete JDK run: rm /tmp/jdk.tar.gz - - name: Package Tests (IKVM.ByteCode.Tests) - run: tar czvf /tmp/tests--IKVM.ByteCode.Tests.tar.gz tests/IKVM.ByteCode.Tests - working-directory: dist - - name: Upload Tests (IKVM.ByteCode.Tests) - uses: actions/upload-artifact@v4 - with: - name: tests--IKVM.ByteCode.Tests - path: /tmp/tests--IKVM.ByteCode.Tests.tar.gz - - name: Delete Tests (IKVM.ByteCode.Tests) - run: rm /tmp/tests--IKVM.ByteCode.Tests.tar.gz - name: Package Tests (IKVM.Reflection.Tests) run: tar czvf /tmp/tests--IKVM.Reflection.Tests.tar.gz tests/IKVM.Reflection.Tests working-directory: dist @@ -424,18 +362,23 @@ jobs: run: | $sys = @( "win-x64", - "linux-x64", - "osx-x64" + "linux-x64" ) + + if ($env:FULL_TEST -eq "true") { + $sys += @( "osx-x64", "osx-arm64" ) + } $tfm = @( "net472", - "net6.0", "net8.0" ) + if ($env:FULL_TEST -eq "true") { + $tfm += @( "net6.0" ) + } + $run = @( - "IKVM.ByteCode.Tests", "IKVM.Reflection.Tests", "IKVM.Tests", "IKVM.Java.Tests", @@ -459,6 +402,10 @@ jobs: "tfm" = "net472" "sys" = "osx-x64" }, + @{ + "tfm" = "net472" + "sys" = "osx-arm64" + }, @{ "run" = "IKVM.MSBuild.Tests" "tfm" = "net472" @@ -497,15 +444,6 @@ jobs: } ) - if ($env:FULL_TEST -ne "true") { - foreach ($_ in (0..15)) { - $exclude += @(@{ - "run" = "IKVM.OpenJDK.Tests?TestPartition=$_" - "tfm" = "net8.0" - }) - } - } - $include = @( @{ "run" = "IKVM.Tests" @@ -671,7 +609,7 @@ jobs: "--blame", "--blame-crash", "--blame-hang", - "--blame-hang-timeout", "60m", + "--blame-hang-timeout", "120m", "--blame-hang-dump-type", "full", "-v:diag", "--results-directory", "TestResults", diff --git a/.gitmodules b/.gitmodules index 01ae6b69aa..ff31f43f5a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,10 @@ -[submodule "openjdk"] - path = openjdk +[submodule "ext/openjdk"] + path = ext/openjdk url = https://github.com/ikvmnet/jdk8u.git ignore = dirty shallow = true -[submodule "jtreg"] - path = jtreg +[submodule "ext/jtreg"] + path = ext/jtreg url = https://github.com/ikvmnet/jtreg.git ignore = dirty shallow = true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c8da98f490..4e4984489b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,6 @@ Prerequisites for building the project: * A clone of the IKVM repository which includes submodules (e.g. `git clone --recurse-submodules https://github.com/ikvmnet/ikvm.git`) * Visual Studio configured for: .NET desktop development, Desktop development with C++ (including C++ Clang tools for Windows), Linux and Embedded Development with C++, and Windows SDK with the appropriate libraries for x86, AMD64 and ARM64 development. * A JDK 8 installation. The `JAVA_HOME` environment variable needs to be point to the JDK 8 directory, or the version of `javac` available on the path needs to be from JDK 8 (You can download a suitable JDK from [Adoptium](https://adoptium.net/)) -* The OpenJDK JDK8u build result for Linux/x64. This build artifact cannot be built on Windows, or modern Linux hosts. Instead, it must be built on a host with GCC 4.3 available. (Debian Lenny is known to work acceptably, the CI/CD GitHub action can serve as a demonstration of this). The easiest way to acquire this artifact without building it yourself is to use one generated by the IKVM respository's [GitHub Actions](https://github.com/ikvm-revived/ikvm/actions). Click on a build result for a relevant branch (typically you'll want to use `develop`) and scroll down to the bottom of the list to locate `openjdk-build-linux-x86_64-normal-server-release`. Download this zip file from this link and unzip into - `openjdk/build`. * SDK Toolkits: These are located in the `ext/ikvm-native-sdk/` directory, and consist of a Windows SDK (windows), Linux SDK (linux) and Mac OS X SDK (macosx). The SDKs can be retrieved from the releases of the `ikvm-native-sdk` project. * We use IKVM.Clang projects to build the native libraries. This project type supports inner builds for TargetMachine, much as .NET supports inner builds for TFMs. * There is an IKVM.Clang Visual Studio extension for these projects to load properly in Visual Studio: https://marketplace.visualstudio.com/items?itemName=ikvm.clang @@ -84,7 +82,7 @@ Increases in the major and minor version are accomplished manually by introducin # Package Layout -The main IKVM package is 'IKVM'. This package contains the IKVM.ByteCode, IKVM.Runtime, IKVM.Java assemblies, and the +The main IKVM package is 'IKVM'. This package contains the IKVM.Runtime, IKVM.Java assemblies, and the libikvm native library. This is the minimal set of files required to begin bootstrapping the JVM. However, the JVM itself requires additional files which are present in the IKVM.Image package hierarchy. diff --git a/Directory.Build.props b/Directory.Build.props index 3e7a69a4b0..bde86f5e56 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -16,12 +16,12 @@ - $(MSBuildThisFileDirectory)openjdk\ + $(MSBuildThisFileDirectory)ext\openjdk\ 1 8 0 - 275 - b01 + 422 + b05 OpenJDK $(OpenJdkMinorVersion)u$(OpenJdkUpdateVersion) $(OpenJdkBuildNumber) $(OpenJdkMajorVersion).$(OpenJdkMinorVersion).$(OpenJdkMicroVersion)_$(OpenJdkUpdateVersion)-$(OpenJdkBuildNumber) Oracle @@ -65,7 +65,7 @@ - 10.0 + 12.0 $(NoWarn);1591;1573;CS8002;NU5100;NU5118;NU5128;MSB3245;NETSDK1023 true true @@ -103,10 +103,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/IKVM.deps.targets b/IKVM.deps.targets index 1f8b2cd8bc..c343585479 100644 --- a/IKVM.deps.targets +++ b/IKVM.deps.targets @@ -1,5 +1,9 @@ + + + + @@ -7,7 +11,7 @@ - + @@ -27,13 +31,6 @@ - - - - - - - diff --git a/IKVM.refs.targets b/IKVM.refs.targets index b7f57fc247..35581bf4c8 100644 --- a/IKVM.refs.targets +++ b/IKVM.refs.targets @@ -4,12 +4,6 @@ $(TargetsForTfmSpecificContentInPackage);GetIkvmLibsTfmSpecificContent;GetIkvmLibsTfmSpecificDebugSymbols;GetIkvmJavaTfmSpecificContent;GetIkvmJavaTfmSpecificDebugSymbols - - - true - - - true @@ -33,14 +27,14 @@ IkvmJavaItem win - + false False all IkvmJavaItem linux - + false False all diff --git a/IKVM.sln b/IKVM.sln index 904f12b2d1..42bf046667 100644 --- a/IKVM.sln +++ b/IKVM.sln @@ -153,8 +153,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IKVM.Image.JDK.runtime.osx- EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IKVM.Image.JRE.runtime.osx-x64", "src\IKVM.Image.JRE.runtime.osx-x64\IKVM.Image.JRE.runtime.osx-x64.csproj", "{FD39DA19-C81E-4752-B308-43594CC201BB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IKVM.ByteCode", "src\IKVM.ByteCode\IKVM.ByteCode.csproj", "{032B77B4-199E-4077-841E-951BAD862050}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dist", "dist", "{F8B6B3D8-006C-4D8F-8883-EB48D9EB417F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dist-nuget", "src\dist-nuget\dist-nuget.csproj", "{6C106109-0131-4413-8D41-348256EADC7E}" @@ -193,8 +191,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IKVM.Tools.Importer", "src\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IKVM.Tools.Importer.Tests", "src\IKVM.Tools.Importer.Tests\IKVM.Tools.Importer.Tests.csproj", "{6C942D7C-654A-4CBE-B3A9-887A37D2FA4C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IKVM.ByteCode.Tests", "src\IKVM.ByteCode.Tests\IKVM.ByteCode.Tests.csproj", "{60E804E4-B25B-4C9A-A3E6-F83D618CFD26}" -EndProject Project("{6DE1C62B-E8D7-451A-8734-87EAEB46E35B}") = "libsunec", "src\libsunec\libsunec.clangproj", "{0714956B-BCE5-43DB-87A6-B58B57E0765B}" EndProject Project("{6DE1C62B-E8D7-451A-8734-87EAEB46E35B}") = "libsunmscapi", "src\libsunmscapi\libsunmscapi.clangproj", "{1658E7AC-0FC7-4527-A7CF-9E0FF752B368}" @@ -339,6 +335,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dist-jdk", "src\dist-jdk\di EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dist-jre", "src\dist-jre\dist-jre.csproj", "{B4C83452-7979-4102-A205-7FD2EE914AEF}" EndProject +Project("{6DE1C62B-E8D7-451A-8734-87EAEB46E35B}") = "libj2gss", "src\libj2gss\libj2gss.clangproj", "{723F8D26-F3CB-430D-B142-4AB89DBF1298}" +EndProject +Project("{6DE1C62B-E8D7-451A-8734-87EAEB46E35B}") = "libsspi_bridge", "src\libsspi_bridge\libsspi_bridge.clangproj", "{461D3F93-30AD-481E-B3D3-476A3CE2BF7B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -569,10 +569,6 @@ Global {FD39DA19-C81E-4752-B308-43594CC201BB}.Debug|Any CPU.Build.0 = Debug|Any CPU {FD39DA19-C81E-4752-B308-43594CC201BB}.Release|Any CPU.ActiveCfg = Release|Any CPU {FD39DA19-C81E-4752-B308-43594CC201BB}.Release|Any CPU.Build.0 = Release|Any CPU - {032B77B4-199E-4077-841E-951BAD862050}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {032B77B4-199E-4077-841E-951BAD862050}.Debug|Any CPU.Build.0 = Debug|Any CPU - {032B77B4-199E-4077-841E-951BAD862050}.Release|Any CPU.ActiveCfg = Release|Any CPU - {032B77B4-199E-4077-841E-951BAD862050}.Release|Any CPU.Build.0 = Release|Any CPU {6C106109-0131-4413-8D41-348256EADC7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6C106109-0131-4413-8D41-348256EADC7E}.Debug|Any CPU.Build.0 = Debug|Any CPU {6C106109-0131-4413-8D41-348256EADC7E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -645,10 +641,6 @@ Global {6C942D7C-654A-4CBE-B3A9-887A37D2FA4C}.Debug|Any CPU.Build.0 = Debug|Any CPU {6C942D7C-654A-4CBE-B3A9-887A37D2FA4C}.Release|Any CPU.ActiveCfg = Release|Any CPU {6C942D7C-654A-4CBE-B3A9-887A37D2FA4C}.Release|Any CPU.Build.0 = Release|Any CPU - {60E804E4-B25B-4C9A-A3E6-F83D618CFD26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {60E804E4-B25B-4C9A-A3E6-F83D618CFD26}.Debug|Any CPU.Build.0 = Debug|Any CPU - {60E804E4-B25B-4C9A-A3E6-F83D618CFD26}.Release|Any CPU.ActiveCfg = Release|Any CPU - {60E804E4-B25B-4C9A-A3E6-F83D618CFD26}.Release|Any CPU.Build.0 = Release|Any CPU {0714956B-BCE5-43DB-87A6-B58B57E0765B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0714956B-BCE5-43DB-87A6-B58B57E0765B}.Debug|Any CPU.Build.0 = Debug|Any CPU {0714956B-BCE5-43DB-87A6-B58B57E0765B}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -909,6 +901,14 @@ Global {B4C83452-7979-4102-A205-7FD2EE914AEF}.Debug|Any CPU.Build.0 = Debug|Any CPU {B4C83452-7979-4102-A205-7FD2EE914AEF}.Release|Any CPU.ActiveCfg = Release|Any CPU {B4C83452-7979-4102-A205-7FD2EE914AEF}.Release|Any CPU.Build.0 = Release|Any CPU + {723F8D26-F3CB-430D-B142-4AB89DBF1298}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {723F8D26-F3CB-430D-B142-4AB89DBF1298}.Debug|Any CPU.Build.0 = Debug|Any CPU + {723F8D26-F3CB-430D-B142-4AB89DBF1298}.Release|Any CPU.ActiveCfg = Release|Any CPU + {723F8D26-F3CB-430D-B142-4AB89DBF1298}.Release|Any CPU.Build.0 = Release|Any CPU + {461D3F93-30AD-481E-B3D3-476A3CE2BF7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {461D3F93-30AD-481E-B3D3-476A3CE2BF7B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {461D3F93-30AD-481E-B3D3-476A3CE2BF7B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {461D3F93-30AD-481E-B3D3-476A3CE2BF7B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ext/jtreg b/ext/jtreg new file mode 160000 index 0000000000..1839513331 --- /dev/null +++ b/ext/jtreg @@ -0,0 +1 @@ +Subproject commit 1839513331c2992181ee45a88c2383f505911dcd diff --git a/ext/openjdk b/ext/openjdk new file mode 160000 index 0000000000..e904cb939c --- /dev/null +++ b/ext/openjdk @@ -0,0 +1 @@ +Subproject commit e904cb939c7160f2551a41b1a344bdff4505e255 diff --git a/jtreg b/jtreg deleted file mode 160000 index 623975ee94..0000000000 --- a/jtreg +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 623975ee940078af770443d58cc2fa98abcee74f diff --git a/jtreg.props b/jtreg.props index 6c43e41faf..f087c1ef65 100644 --- a/jtreg.props +++ b/jtreg.props @@ -1,6 +1,6 @@  - $(MSBuildThisFileDirectory)jtreg\ + $(MSBuildThisFileDirectory)ext\jtreg\ diff --git a/nuget.config b/nuget.config index be31e09e59..5c2190fefc 100644 --- a/nuget.config +++ b/nuget.config @@ -1,6 +1,5 @@ - - + diff --git a/openjdk b/openjdk deleted file mode 160000 index 2918bfe1a4..0000000000 --- a/openjdk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2918bfe1a4ca241bbddbcecf5a25f09319813823 diff --git a/src/IKVM.ByteCode.Tests/0.class b/src/IKVM.ByteCode.Tests/0.class deleted file mode 100644 index b5b6c8f2b5..0000000000 Binary files a/src/IKVM.ByteCode.Tests/0.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/ClassFormatVersionTests.cs b/src/IKVM.ByteCode.Tests/ClassFormatVersionTests.cs deleted file mode 100644 index abf8c93637..0000000000 --- a/src/IKVM.ByteCode.Tests/ClassFormatVersionTests.cs +++ /dev/null @@ -1,69 +0,0 @@ -using FluentAssertions; - -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace IKVM.ByteCode.Tests -{ - - [TestClass] - public class ClassFormatVersionTests - { - - [TestMethod] - public void CompareToShouldBeZeroForEqual() - { - new ClassFormatVersion(1, 0).CompareTo(new ClassFormatVersion(1, 0)).Should().Be(0); - } - - [TestMethod] - public void CompareToShouldBeNegativeOneForGreaterMajor() - { - new ClassFormatVersion(1, 0).CompareTo(new ClassFormatVersion(2, 0)).Should().Be(-1); - } - - [TestMethod] - public void CompareToShouldBeNegativeOneForGreaterMinor() - { - new ClassFormatVersion(1, 0).CompareTo(new ClassFormatVersion(1, 1)).Should().Be(-1); - } - - [TestMethod] - public void CompareToShouldBeOneForGreaterMajor() - { - new ClassFormatVersion(2, 0).CompareTo(new ClassFormatVersion(1, 0)).Should().Be(1); - } - - [TestMethod] - public void CompareToShouldBeOneForGreaterMinor() - { - new ClassFormatVersion(1, 1).CompareTo(new ClassFormatVersion(1, 0)).Should().Be(1); - } - - [TestMethod] - public void ImplicitOperatorsShouldReturnCorrectValues() - { - (new ClassFormatVersion(1, 0) > new ClassFormatVersion(1, 0)).Should().BeFalse(); - (new ClassFormatVersion(1, 0) < new ClassFormatVersion(1, 0)).Should().BeFalse(); - (new ClassFormatVersion(1, 0) >= new ClassFormatVersion(1, 0)).Should().BeTrue(); - (new ClassFormatVersion(1, 0) <= new ClassFormatVersion(1, 0)).Should().BeTrue(); - (new ClassFormatVersion(1, 0) == new ClassFormatVersion(1, 0)).Should().BeTrue(); - (new ClassFormatVersion(1, 0) != new ClassFormatVersion(1, 0)).Should().BeFalse(); - - (new ClassFormatVersion(1, 1) > new ClassFormatVersion(1, 0)).Should().BeTrue(); - (new ClassFormatVersion(1, 1) < new ClassFormatVersion(1, 0)).Should().BeFalse(); - (new ClassFormatVersion(1, 1) >= new ClassFormatVersion(1, 0)).Should().BeTrue(); - (new ClassFormatVersion(1, 1) <= new ClassFormatVersion(1, 0)).Should().BeFalse(); - (new ClassFormatVersion(1, 1) == new ClassFormatVersion(1, 0)).Should().BeFalse(); - (new ClassFormatVersion(1, 1) != new ClassFormatVersion(1, 0)).Should().BeTrue(); - - (new ClassFormatVersion(2, 0) > new ClassFormatVersion(1, 0)).Should().BeTrue(); - (new ClassFormatVersion(2, 0) < new ClassFormatVersion(1, 0)).Should().BeFalse(); - (new ClassFormatVersion(2, 0) >= new ClassFormatVersion(1, 0)).Should().BeTrue(); - (new ClassFormatVersion(2, 0) <= new ClassFormatVersion(1, 0)).Should().BeFalse(); - (new ClassFormatVersion(2, 0) == new ClassFormatVersion(1, 0)).Should().BeFalse(); - (new ClassFormatVersion(2, 0) != new ClassFormatVersion(1, 0)).Should().BeTrue(); - } - - } - -} diff --git a/src/IKVM.ByteCode.Tests/IKVM.ByteCode.Tests.csproj b/src/IKVM.ByteCode.Tests/IKVM.ByteCode.Tests.csproj deleted file mode 100644 index 697e133d3d..0000000000 --- a/src/IKVM.ByteCode.Tests/IKVM.ByteCode.Tests.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - net472;net6.0;net7.0;net8.0 - true - - - - - - - - - - - - - - PreserveNewest - - - - diff --git a/src/IKVM.ByteCode.Tests/Parsing/TypeAnnotationRecordTests.cs b/src/IKVM.ByteCode.Tests/Parsing/TypeAnnotationRecordTests.cs deleted file mode 100644 index d9e21eb130..0000000000 --- a/src/IKVM.ByteCode.Tests/Parsing/TypeAnnotationRecordTests.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; - -using FluentAssertions; - -using IKVM.ByteCode.Parsing; - -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace IKVM.ByteCode.Tests.Parsing -{ - - [TestClass] - public class TypeAnnotationRecordTests - { - - [TestMethod] - public void CanRoundTripTypeAnnotation() - { - var a = new TypeAnnotationRecord( - TypeAnnotationTargetType.Field, - new TypeAnnotationEmptyTargetRecord(), - new TypePathRecord(new TypePathItemRecord(TypePathKind.ArrayType, 0)), - 1, - new ElementValuePairRecord(2, new ElementValueRecord(ElementValueTag.Integer, new ElementValueConstantValueRecord(3)))); - - var b1 = new byte[a.GetSize()]; - var w1 = new ClassFormatWriter(b1); - if (a.TryWrite(ref w1) == false) - throw new Exception(); - - var r = new ClassFormatReader(b1); - if (TypeAnnotationRecord.TryReadTypeAnnotation(ref r, out var b) == false) - throw new Exception(); - - var b2 = new byte[b.GetSize()]; - var w2 = new ClassFormatWriter(b2); - if (b.TryWrite(ref w2) == false) - throw new Exception(); - - b1.Should().BeEquivalentTo(b2); - } - - } - -} diff --git a/src/IKVM.ByteCode.Tests/Reading/ClassReaderTests.cs b/src/IKVM.ByteCode.Tests/Reading/ClassReaderTests.cs deleted file mode 100644 index b91f436e11..0000000000 --- a/src/IKVM.ByteCode.Tests/Reading/ClassReaderTests.cs +++ /dev/null @@ -1,264 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -using FluentAssertions; - -using IKVM.ByteCode.Parsing; - -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace IKVM.ByteCode.Reading.Tests -{ - - [TestClass] - public class ClassReaderTests - { - - [TestMethod] - [ExpectedException(typeof(InvalidClassException))] - public async Task ShouldThrowOnEmptyStream() - { - var stream = new MemoryStream(); - await ClassReader.ReadAsync(stream); - } - - [TestMethod] - [ExpectedException(typeof(InvalidClassMagicException))] - public async Task ShouldThrowOnSmallStream() - { - var stream = new MemoryStream(new byte[10]); - await ClassReader.ReadAsync(stream); - } - - [TestMethod] - [ExpectedException(typeof(InvalidClassMagicException))] - public async Task ShouldThrowOnBadStream() - { - var stream = new MemoryStream(new byte[35]); - await ClassReader.ReadAsync(stream); - } - - [TestMethod] - public void CanLoadClass() - { - var clazz = ClassReader.Read(Path.Combine(Path.GetDirectoryName(typeof(ClassReaderTests).Assembly.Location), "0.class")); - clazz.Should().NotBeNull(); - clazz.This.Name.Value.Should().Be("0"); - clazz.Constants.ToList(); - clazz.Interfaces.ToList(); - clazz.Fields.Should().HaveCount(0); - clazz.Fields.ToList(); - clazz.Methods.Should().HaveCount(2); - clazz.Methods.ToList(); - - clazz.Methods[0].Attributes.Code.Code.Should().NotBeNull(); - clazz.Methods[1].Attributes.Code.Code.Should().NotBeNull(); - } - - [TestMethod] - public void CanLoadTestClassFiles() - { - var d = Path.Combine(Path.GetDirectoryName(typeof(ClassReaderTests).Assembly.Location), "resources"); - var l = Directory.GetFiles(d, "*.class", SearchOption.AllDirectories); - - foreach (var i in l) - { - var c = ClassReader.Read(i); - c.This.Should().NotBeNull(); - c.Constants.ToList(); - - foreach (var constant in c.Constants) - TestConstant(constant); - - c.Interfaces.ToList(); - c.Interfaces.Should().OnlyHaveUniqueItems(); - c.Fields.ToList(); - c.Fields.Should().OnlyHaveUniqueItems(); - c.Methods.ToList(); - c.Methods.Should().OnlyHaveUniqueItems(); - - foreach (var iface in c.Interfaces) - iface.Class.Name.Value.Should().NotBeNull(); - - foreach (var field in c.Fields) - { - field.Should().NotBeNull(); - field.Name.Value.Should().NotBeNull(); - field.Descriptor.Value.Should().NotBeNull(); - field.Attributes.ToList(); - - foreach (var attribute in field.Attributes) - TestAttribute(attribute); - } - - foreach (var method in c.Methods) - { - method.Name.Should().NotBeNull(); - method.Descriptor.Should().NotBeNull(); - method.Attributes.ToList(); - - foreach (var attribute in method.Attributes) - TestAttribute(attribute); - } - - c.Attributes.ToList(); - foreach (var attribute in c.Attributes) - TestAttribute(attribute); - } - } - - void TestConstant(IConstantReader constant) - { - if (constant is Utf8ConstantReader utf8) - TestConstant(utf8); - if (constant is IntegerConstantReader integer) - TestConstant(integer); - if (constant is MethodHandleConstantReader methodHandle) - TestConstant(methodHandle); - } - - void TestConstant(Utf8ConstantReader utf8) - { - utf8.Value.Should().NotBeNull(); - } - - void TestConstant(IntegerConstantReader integer) - { - integer.Value.GetType().Should().Be(typeof(int)); - } - - void TestConstant(MethodHandleConstantReader methodHandle) - { - if (methodHandle.ReferenceKind is ReferenceKind.GetField or ReferenceKind.GetStatic or ReferenceKind.PutField or ReferenceKind.PutStatic) - methodHandle.Reference.Should().BeOfType(); - if (methodHandle.ReferenceKind is ReferenceKind.InvokeVirtual or ReferenceKind.NewInvokeSpecial) - methodHandle.Reference.Should().BeOfType(); - if (methodHandle.ReferenceKind is ReferenceKind.InvokeStatic or ReferenceKind.InvokeSpecial && methodHandle.DeclaringClass.Version < new ClassFormatVersion(52, 0)) - methodHandle.Reference.Should().BeOfType(); - if (methodHandle.ReferenceKind is ReferenceKind.InvokeStatic or ReferenceKind.InvokeSpecial && methodHandle.DeclaringClass.Version >= new ClassFormatVersion(52, 0)) - methodHandle.Reference.Should().Match(i => i is MethodrefConstantReader || i is InterfaceMethodrefConstantReader); - if (methodHandle.ReferenceKind is ReferenceKind.InvokeInterface) - methodHandle.Reference.Should().BeOfType(); - if (methodHandle.ReferenceKind is ReferenceKind.InvokeVirtual or ReferenceKind.InvokeStatic or ReferenceKind.InvokeSpecial or ReferenceKind.InvokeInterface && methodHandle.Reference is MethodrefConstantReader methodRef) - methodRef.NameAndType.Name.Value.Should().NotBe("").And.NotBe(""); - if (methodHandle.ReferenceKind is ReferenceKind.InvokeVirtual or ReferenceKind.InvokeStatic or ReferenceKind.InvokeSpecial or ReferenceKind.InvokeInterface && methodHandle.Reference is InterfaceMethodrefConstantReader interfaceMethodRef) - interfaceMethodRef.Class.Name.Value.Should().NotBe("").And.NotBe(""); - } - - void TestAttribute(AttributeReader attribute) - { - if (attribute is RuntimeVisibleAnnotationsAttributeReader runtimeVisibleAnnotationsAttributeReader) - TestAttribute(runtimeVisibleAnnotationsAttributeReader); - if (attribute is RuntimeInvisibleAnnotationsAttributeReader runtimeInvisibleAnnotationsAttributeReader) - TestAttribute(runtimeInvisibleAnnotationsAttributeReader); - if (attribute is RuntimeVisibleTypeAnnotationsAttributeReader runtimeVisibleTypeAnnotationsAttributeReader) - TestAttribute(runtimeVisibleTypeAnnotationsAttributeReader); - if (attribute is RuntimeInvisibleTypeAnnotationsAttributeReader runtimeInvisibleTypeAnnotationsAttributeReader) - TestAttribute(runtimeInvisibleTypeAnnotationsAttributeReader); - } - - void TestAttribute(RuntimeVisibleAnnotationsAttributeReader attribute) - { - attribute.Info.Name.Value.Should().NotBeEmpty(); - TestAnnotations(attribute.Annotations); - } - - void TestAttribute(RuntimeInvisibleAnnotationsAttributeReader attribute) - { - attribute.Info.Name.Value.Should().NotBeEmpty(); - TestAnnotations(attribute.Annotations); - } - - void TestAttribute(RuntimeVisibleTypeAnnotationsAttributeReader attribute) - { - attribute.Info.Name.Value.Should().NotBeEmpty(); - TestAnnotations(attribute.Annotations); - } - - void TestAttribute(RuntimeInvisibleTypeAnnotationsAttributeReader attribute) - { - attribute.Info.Name.Value.Should().NotBeEmpty(); - TestAnnotations(attribute.Annotations); - } - - void TestAnnotations(IReadOnlyList annotations) - { - foreach (var annotation in annotations) - TestAnnotation(annotation); - } - - void TestAnnotations(IReadOnlyList annotations) - { - foreach (var annotation in annotations) - TestAnnotation(annotation); - } - - void TestAnnotation(AnnotationReader annotation) - { - annotation.Type.Value.Should().NotBeEmpty(); - TestElementValuePair(annotation.Elements); - } - - void TestAnnotation(TypeAnnotationReader annotation) - { - annotation.Type.Value.Should().NotBeEmpty(); - TestElementValuePair(annotation.Elements); - } - - void TestElementValuePair(ElementValueKeyReaderCollection elements) - { - elements.Count.Should().BeLessThan(256); - - foreach (var element in elements) - TestElement(element.Key, element.Value); - } - - void TestElement(string name, ElementValueReader value) - { - name.Should().NotBeEmpty(); - value.Should().NotBeNull(); - - TestElementValue(value); - } - - void TestElementValue(ElementValueReader value) - { - if (value is ElementValueConstantReader elementValueConstantReader) - TestElementValue(elementValueConstantReader); - if (value is ElementValueAnnotationReader elementAnnotationValueReader) - TestElementValue(elementAnnotationValueReader); - if (value is ElementValueArrayReader elementArrayValueReader) - TestElementValue(elementArrayValueReader); - if (value is ElementValueClassReader elementClassInfoValueReader) - TestElementValue(elementClassInfoValueReader); - } - - void TestElementValue(ElementValueConstantReader elementValueConstantReader) - { - Enum.GetName(typeof(ElementValueTag), elementValueConstantReader.Tag).Should().NotBeNullOrEmpty(); - elementValueConstantReader.Value.Should().NotBeNull(); - TestConstant(elementValueConstantReader.Value); - } - - void TestElementValue(ElementValueClassReader elementClassInfoValueReader) - { - elementClassInfoValueReader.Class.Value.Should().NotBeEmpty(); - } - - void TestElementValue(ElementValueAnnotationReader elementAnnotationValueReader) - { - TestAnnotation(elementAnnotationValueReader.Annotation); - } - - void TestElementValue(ElementValueArrayReader elementArrayValueReader) - { - foreach (var value in elementArrayValueReader.Values) - TestElementValue(value); - } - - } - -} diff --git a/src/IKVM.ByteCode.Tests/Reading/ConstantReaderTests.class b/src/IKVM.ByteCode.Tests/Reading/ConstantReaderTests.class deleted file mode 100644 index e2af1771c0..0000000000 Binary files a/src/IKVM.ByteCode.Tests/Reading/ConstantReaderTests.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/Reading/ConstantReaderTests.cs b/src/IKVM.ByteCode.Tests/Reading/ConstantReaderTests.cs deleted file mode 100644 index 5e93337040..0000000000 --- a/src/IKVM.ByteCode.Tests/Reading/ConstantReaderTests.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.IO; -using System.Linq; - -using FluentAssertions; - -using IKVM.ByteCode.Reading; - -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace IKVM.ByteCode.Tests.Reading -{ - - [TestClass] - public class ConstantReaderTests - { - - ClassReader ReadClass() - { - return ClassReader.Read(Path.Combine(Path.GetDirectoryName(typeof(ConstantReaderTests).Assembly.Location), "Reading", "ConstantReaderTests.class")); - } - - [TestMethod] - public void CanReadIntegerConstant() - { - var c = ReadClass(); - c.Constants.OfType().Should().Contain(i => i.Value == 394892); - } - - [TestMethod] - public void CanReadLongConstant() - { - var c = ReadClass(); - c.Constants.OfType().Should().Contain(i => i.Value == 34182132); - } - - [TestMethod] - public void CanReadFloatConstant() - { - var c = ReadClass(); - c.Constants.OfType().Should().Contain(i => i.Value == 221.03f); - } - - [TestMethod] - public void CanReadDoubleConstant() - { - var c = ReadClass(); - c.Constants.OfType().Should().Contain(i => i.Value == 2212133.1d); - } - - [TestMethod] - public void CanReadStringConstant() - { - var c = ReadClass(); - c.Constants.OfType().Should().Contain(i => i.Value == "STRING"); - } - - [TestMethod] - public void CanReadClassConstant() - { - var c = ReadClass(); - c.Constants.OfType().Should().Contain(i => i.Name.Value == "java/lang/Object"); - } - - [TestMethod] - public void CanReadMethodrefConstant() - { - var c = ReadClass(); - c.Constants.OfType().Should().Contain(i => i.Class.Name.Value == "java/lang/Object" && i.NameAndType.Name.Value == "" && i.NameAndType.Type.Value == "()V"); - } - - } - -} diff --git a/src/IKVM.ByteCode.Tests/Reading/ConstantReaderTests.java b/src/IKVM.ByteCode.Tests/Reading/ConstantReaderTests.java deleted file mode 100644 index e0d8907c7a..0000000000 --- a/src/IKVM.ByteCode.Tests/Reading/ConstantReaderTests.java +++ /dev/null @@ -1,9 +0,0 @@ -final class ConstantReaderTests { - - static int i = 394892; - static long j = 34182132; - static float f = 221.03f; - static double d = 2212133.1; - static String o = "STRING"; - -} diff --git a/src/IKVM.ByteCode.Tests/Text/MUTF8EncodingTests.cs b/src/IKVM.ByteCode.Tests/Text/MUTF8EncodingTests.cs deleted file mode 100644 index 1b297c7227..0000000000 --- a/src/IKVM.ByteCode.Tests/Text/MUTF8EncodingTests.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Linq; - -using FluentAssertions; - -using IKVM.ByteCode.Text; - -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace IKVM.ByteCode.Tests.Text -{ - - [TestClass] - public class MUTF8EncodingTests - { - - string asciiChars = new string(Enumerable.Range(32, 126 - 32).Select(i => (char)i).ToArray()); - - [TestMethod] - public void CanRoundTripASCIICharactersForJDK_1_4() - { - var e = MUTF8Encoding.GetMUTF8(48); - var b = e.GetBytes(asciiChars); - var c = e.GetString(b); - c.Should().Be(asciiChars); - } - - [TestMethod] - public void CanRoundTripASCIICharactersForJDK_1_0() - { - var e = MUTF8Encoding.GetMUTF8(46); - var b = e.GetBytes(asciiChars); - var c = e.GetString(b); - c.Should().Be(asciiChars); - } - - [TestMethod] - public void CanEncodeNullByte() - { - var l = MUTF8Encoding.GetMUTF8(48).GetByteCount("\0"); - l.Should().Be(2); - var b = MUTF8Encoding.GetMUTF8(48).GetBytes("\0"); - b.Should().HaveCount(2); - b[0].Should().Be(0b11000000); - b[1].Should().Be(0b10000000); - } - - [TestMethod] - public void CanDecodeNullByte() - { - var s = MUTF8Encoding.GetMUTF8(48).GetChars(new byte[] { 0b11000000, 0b10000000 }); - s.Should().HaveCount(1); - s[0].Should().Be('\0'); - } - - [TestMethod] - public void CanEncodeNull() - { - MUTF8Encoding.GetMUTF8(48).GetBytes("\0").Should().HaveCount(2); - MUTF8Encoding.GetMUTF8(48).GetBytes("a\0").Should().HaveCount(3); - MUTF8Encoding.GetMUTF8(48).GetBytes("a\0a").Should().HaveCount(4); - MUTF8Encoding.GetMUTF8(48).GetBytes("\0\0").Should().HaveCount(4); - MUTF8Encoding.GetMUTF8(48).GetBytes("a\0\0").Should().HaveCount(5); - MUTF8Encoding.GetMUTF8(48).GetBytes("a\0\0a").Should().HaveCount(6); - } - - [TestMethod] - public void CanHandleEmptyString() - { - MUTF8Encoding.GetMUTF8(48).GetBytes("").Should().BeEmpty(); - MUTF8Encoding.GetMUTF8(48).GetString(Array.Empty()).Should().Be(""); - } - - } - -} diff --git a/src/IKVM.ByteCode.Tests/resources/CharSequence.class b/src/IKVM.ByteCode.Tests/resources/CharSequence.class deleted file mode 100644 index 29734d2c09..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/CharSequence.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/ColorEditor.class b/src/IKVM.ByteCode.Tests/resources/ColorEditor.class deleted file mode 100644 index 30132d7b9b..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/ColorEditor.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/Databinding$Builder.class b/src/IKVM.ByteCode.Tests/resources/Databinding$Builder.class deleted file mode 100644 index 8e35c60e98..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/Databinding$Builder.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/Databinding.class b/src/IKVM.ByteCode.Tests/resources/Databinding.class deleted file mode 100644 index 8d71ac405f..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/Databinding.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/DatabindingFactory.class b/src/IKVM.ByteCode.Tests/resources/DatabindingFactory.class deleted file mode 100644 index 2af6a40b1f..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/DatabindingFactory.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/DatabindingMode.class b/src/IKVM.ByteCode.Tests/resources/DatabindingMode.class deleted file mode 100644 index a7778f88f4..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/DatabindingMode.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/DatabindingModeFeature$Builder.class b/src/IKVM.ByteCode.Tests/resources/DatabindingModeFeature$Builder.class deleted file mode 100644 index 8d486c4107..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/DatabindingModeFeature$Builder.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/DatabindingModeFeature.class b/src/IKVM.ByteCode.Tests/resources/DatabindingModeFeature.class deleted file mode 100644 index 1d75b37720..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/DatabindingModeFeature.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/DefaultPackage.class b/src/IKVM.ByteCode.Tests/resources/DefaultPackage.class deleted file mode 100644 index 0e6cce8c66..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/DefaultPackage.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/Serializable.class b/src/IKVM.ByteCode.Tests/resources/Serializable.class deleted file mode 100644 index bde4e91583..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/Serializable.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/ThreadDeath.class b/src/IKVM.ByteCode.Tests/resources/ThreadDeath.class deleted file mode 100644 index 9b59f5237f..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/ThreadDeath.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/ICA.class b/src/IKVM.ByteCode.Tests/resources/annotations/ICA.class deleted file mode 100644 index bb479f5bc1..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/ICA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/IFA.class b/src/IKVM.ByteCode.Tests/resources/annotations/IFA.class deleted file mode 100644 index c3cd37f5be..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/IFA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/IMA.class b/src/IKVM.ByteCode.Tests/resources/annotations/IMA.class deleted file mode 100644 index cee7bd63f2..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/IMA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/IPA.class b/src/IKVM.ByteCode.Tests/resources/annotations/IPA.class deleted file mode 100644 index 816a37cb94..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/IPA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/ITA.class b/src/IKVM.ByteCode.Tests/resources/annotations/ITA.class deleted file mode 100644 index c05ccb2d97..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/ITA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/ITPA.class b/src/IKVM.ByteCode.Tests/resources/annotations/ITPA.class deleted file mode 100644 index 3734e57f70..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/ITPA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/ITUA.class b/src/IKVM.ByteCode.Tests/resources/annotations/ITUA.class deleted file mode 100644 index 374440360c..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/ITUA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/IVA.class b/src/IKVM.ByteCode.Tests/resources/annotations/IVA.class deleted file mode 100644 index e5de15cd48..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/IVA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/VCA.class b/src/IKVM.ByteCode.Tests/resources/annotations/VCA.class deleted file mode 100644 index 9cdf532bfb..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/VCA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/VFA.class b/src/IKVM.ByteCode.Tests/resources/annotations/VFA.class deleted file mode 100644 index 59ffcf8d0d..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/VFA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/VMA.class b/src/IKVM.ByteCode.Tests/resources/annotations/VMA.class deleted file mode 100644 index 82c909bebf..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/VMA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/VPA.class b/src/IKVM.ByteCode.Tests/resources/annotations/VPA.class deleted file mode 100644 index d9e6e5ba1c..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/VPA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/VTA.class b/src/IKVM.ByteCode.Tests/resources/annotations/VTA.class deleted file mode 100644 index 84c0a95772..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/VTA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/VTPA.class b/src/IKVM.ByteCode.Tests/resources/annotations/VTPA.class deleted file mode 100644 index 2d0b3b9281..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/VTPA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/VTUA.class b/src/IKVM.ByteCode.Tests/resources/annotations/VTUA.class deleted file mode 100644 index d532458a2f..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/VTUA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/annotations/VVA.class b/src/IKVM.ByteCode.Tests/resources/annotations/VVA.class deleted file mode 100644 index 378a3e73f8..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/annotations/VVA.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidBytecodeOffset.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidBytecodeOffset.clazz deleted file mode 100644 index bc5286cc2a..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidBytecodeOffset.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidClassVersion.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidClassVersion.clazz deleted file mode 100644 index 1ef8a0b116..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidClassVersion.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidCodeLength.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidCodeLength.clazz deleted file mode 100644 index 8378e4f4ec..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidCodeLength.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidConstantPoolIndex.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidConstantPoolIndex.clazz deleted file mode 100644 index 52360e85ab..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidConstantPoolIndex.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidConstantPoolReference.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidConstantPoolReference.clazz deleted file mode 100644 index f0a7874f3e..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidConstantPoolReference.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidCpInfoTag.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidCpInfoTag.clazz deleted file mode 100644 index 650e8ac121..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidCpInfoTag.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidElementValue.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidElementValue.clazz deleted file mode 100644 index c6cf72e044..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidElementValue.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidInsnTypeAnnotationTargetType.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidInsnTypeAnnotationTargetType.clazz deleted file mode 100644 index 5cbb5ac5c7..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidInsnTypeAnnotationTargetType.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidOpcode.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidOpcode.clazz deleted file mode 100644 index 3c94fceb23..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidOpcode.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidSourceDebugExtension.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidSourceDebugExtension.clazz deleted file mode 100644 index f7df0e823c..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidSourceDebugExtension.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidStackMapFrameType.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidStackMapFrameType.clazz deleted file mode 100644 index 3adc7b76d7..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidStackMapFrameType.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidTypeAnnotationTargetType.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidTypeAnnotationTargetType.clazz deleted file mode 100644 index 8859aa382c..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidTypeAnnotationTargetType.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidVerificationTypeInfo.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidVerificationTypeInfo.clazz deleted file mode 100644 index bea541c093..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidVerificationTypeInfo.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidWideOpcode.clazz b/src/IKVM.ByteCode.Tests/resources/invalid/InvalidWideOpcode.clazz deleted file mode 100644 index 59d01081b7..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/invalid/InvalidWideOpcode.clazz and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk11/AllInstructions.class b/src/IKVM.ByteCode.Tests/resources/jdk11/AllInstructions.class deleted file mode 100644 index 69aa44471c..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk11/AllInstructions.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk11/AllStructures$Nested.class b/src/IKVM.ByteCode.Tests/resources/jdk11/AllStructures$Nested.class deleted file mode 100644 index 9d31e7bed0..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk11/AllStructures$Nested.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk11/AllStructures.class b/src/IKVM.ByteCode.Tests/resources/jdk11/AllStructures.class deleted file mode 100644 index 3aa1138bf4..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk11/AllStructures.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk14/AllStructures$EmptyRecord.class b/src/IKVM.ByteCode.Tests/resources/jdk14/AllStructures$EmptyRecord.class deleted file mode 100644 index e2f8cb3ce4..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk14/AllStructures$EmptyRecord.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk14/AllStructures$RecordSubType.class b/src/IKVM.ByteCode.Tests/resources/jdk14/AllStructures$RecordSubType.class deleted file mode 100644 index 61d0a18030..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk14/AllStructures$RecordSubType.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk15/AllStructures.class b/src/IKVM.ByteCode.Tests/resources/jdk15/AllStructures.class deleted file mode 100644 index 851fc92f30..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk15/AllStructures.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk3/AllInstructions.class b/src/IKVM.ByteCode.Tests/resources/jdk3/AllInstructions.class deleted file mode 100644 index 283d41a0d0..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk3/AllInstructions.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk3/AllStructures$1.class b/src/IKVM.ByteCode.Tests/resources/jdk3/AllStructures$1.class deleted file mode 100644 index c21668ed12..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk3/AllStructures$1.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk3/AllStructures$InnerClass.class b/src/IKVM.ByteCode.Tests/resources/jdk3/AllStructures$InnerClass.class deleted file mode 100644 index 930cad3270..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk3/AllStructures$InnerClass.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk3/AllStructures.class b/src/IKVM.ByteCode.Tests/resources/jdk3/AllStructures.class deleted file mode 100644 index c5b7ba2c1c..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk3/AllStructures.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk3/ArtificialStructures.class b/src/IKVM.ByteCode.Tests/resources/jdk3/ArtificialStructures.class deleted file mode 100644 index 0ba4240b6d..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk3/ArtificialStructures.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk3/LargeMethod.class b/src/IKVM.ByteCode.Tests/resources/jdk3/LargeMethod.class deleted file mode 100644 index d2547710c4..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk3/LargeMethod.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk5/AllInstructions.class b/src/IKVM.ByteCode.Tests/resources/jdk5/AllInstructions.class deleted file mode 100644 index f3d08c37c7..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk5/AllInstructions.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$1LocalClass.class b/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$1LocalClass.class deleted file mode 100644 index b6ac40da4c..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$1LocalClass.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$EnumClass.class b/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$EnumClass.class deleted file mode 100644 index 23540f193b..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$EnumClass.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$GenericInnerClass.class b/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$GenericInnerClass.class deleted file mode 100644 index 5291fe7892..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$GenericInnerClass.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$InnerClass.class b/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$InnerClass.class deleted file mode 100644 index baeb6c4ad3..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$InnerClass.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$InvisibleAnnotation.class b/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$InvisibleAnnotation.class deleted file mode 100644 index 485df516a7..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures$InvisibleAnnotation.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures.class b/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures.class deleted file mode 100644 index a7de553e83..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk5/AllStructures.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk8/AllFrames.class b/src/IKVM.ByteCode.Tests/resources/jdk8/AllFrames.class deleted file mode 100644 index 90d79b8c5b..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk8/AllFrames.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk8/AllInstructions.class b/src/IKVM.ByteCode.Tests/resources/jdk8/AllInstructions.class deleted file mode 100644 index ecd224fb08..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk8/AllInstructions.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk8/AllStructures$1.class b/src/IKVM.ByteCode.Tests/resources/jdk8/AllStructures$1.class deleted file mode 100644 index 24a5d7e5dc..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk8/AllStructures$1.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk8/AllStructures$InnerClass.class b/src/IKVM.ByteCode.Tests/resources/jdk8/AllStructures$InnerClass.class deleted file mode 100644 index 2e05aa5dfa..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk8/AllStructures$InnerClass.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk8/AllStructures.class b/src/IKVM.ByteCode.Tests/resources/jdk8/AllStructures.class deleted file mode 100644 index 3069f601b5..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk8/AllStructures.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk8/Artificial$()$Structures.class b/src/IKVM.ByteCode.Tests/resources/jdk8/Artificial$()$Structures.class deleted file mode 100644 index 1cc843ec6b..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk8/Artificial$()$Structures.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk8/LargeMethod.class b/src/IKVM.ByteCode.Tests/resources/jdk8/LargeMethod.class deleted file mode 100644 index bace5c0c89..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk8/LargeMethod.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk9/module-info.class b/src/IKVM.ByteCode.Tests/resources/jdk9/module-info.class deleted file mode 100644 index e7418e67bd..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk9/module-info.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk9/pkg/A.class b/src/IKVM.ByteCode.Tests/resources/jdk9/pkg/A.class deleted file mode 100644 index d33ea1d335..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk9/pkg/A.class and /dev/null differ diff --git a/src/IKVM.ByteCode.Tests/resources/jdk9/pkg/internal/AImpl.class b/src/IKVM.ByteCode.Tests/resources/jdk9/pkg/internal/AImpl.class deleted file mode 100644 index 51a374f6c8..0000000000 Binary files a/src/IKVM.ByteCode.Tests/resources/jdk9/pkg/internal/AImpl.class and /dev/null differ diff --git a/src/IKVM.ByteCode/AccessFlag.cs b/src/IKVM.ByteCode/AccessFlag.cs deleted file mode 100644 index 26697481cd..0000000000 --- a/src/IKVM.ByteCode/AccessFlag.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace IKVM.ByteCode -{ - - [Flags] - internal enum AccessFlag : ushort - { - - ACC_PUBLIC = 0x0001, - ACC_FINAL = 0x0010, - ACC_SUPER = 0x0020, - ACC_INTERFACE = 0x0200, - ACC_ABSTRACT = 0x0400, - ACC_SYNTHETIC = 0x1000, - ACC_ANNOTATION = 0x2000, - ACC_ENUM = 0x4000, - ACC_MODULE = 0x8000, - - } - - -} diff --git a/src/IKVM.ByteCode/Buffers/RawBitConverter.cs b/src/IKVM.ByteCode/Buffers/RawBitConverter.cs deleted file mode 100644 index 05699b8f5b..0000000000 --- a/src/IKVM.ByteCode/Buffers/RawBitConverter.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Runtime.CompilerServices; - -#if NETCOREAPP3_1 -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; -#endif - -namespace IKVM.ByteCode.Buffers -{ - - static class RawBitConverter - { - -#if NETFRAMEWORK || NETCOREAPP3_1 - - /// - /// Converts the specified 32-bit signed integer to a single-precision floating point number. - /// - /// The number to convert. - /// A single-precision floating point number whose bits are identical to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe float Int32BitsToSingle(int value) - { -#if NETCOREAPP3_1 - // Workaround for https://github.com/dotnet/runtime/issues/11413 - if (Sse2.IsSupported) - { - Vector128 vec = Vector128.CreateScalarUnsafe(value).AsSingle(); - return vec.ToScalar(); - } -#endif - - return *((float*)&value); - } - - /// - /// Converts the specified 32-bit signed integer to a single-precision floating point number. - /// - /// The number to convert. - /// A single-precision floating point number whose bits are identical to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe double Int64BitsToDouble(long value) - { -#if NETCOREAPP3_1 - // Workaround for https://github.com/dotnet/runtime/issues/11413 - if (Sse2.X64.IsSupported) - { - Vector128 vec = Vector128.CreateScalarUnsafe(value).AsDouble(); - return vec.ToScalar(); - } -#endif - - return *((double*)&value); - } - -#endif - -#if NETFRAMEWORK || NETCOREAPP3_1 - - /// - /// Converts the specified 32-bit unsigned integer to a single-precision floating point number. - /// - /// The number to convert. - /// A single-precision floating point number whose bits are identical to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe float UInt32BitsToSingle(uint value) => Int32BitsToSingle((int)value); - - /// - /// Converts the specified 32-bit unsigned integer to a single-precision floating point number. - /// - /// The number to convert. - /// A single-precision floating point number whose bits are identical to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe double UInt64BitsToDouble(ulong value) => Int64BitsToDouble((long)value); - -#endif - - } - -} diff --git a/src/IKVM.ByteCode/Buffers/SequenceReader.cs b/src/IKVM.ByteCode/Buffers/SequenceReader.cs deleted file mode 100644 index c93fd648a8..0000000000 --- a/src/IKVM.ByteCode/Buffers/SequenceReader.cs +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright (c) All contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -/* Licensed to the .NET Foundation under one or more agreements. - * The .NET Foundation licenses this file to you under the MIT license. - * See the LICENSE file in the project root for more information. */ - -using System; -using System.Buffers; -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace IKVM.ByteCode.Buffers -{ - -#if NETFRAMEWORK - - public ref partial struct SequenceReader - where T : unmanaged, IEquatable - { - - /// - /// A value indicating whether we're using (as opposed to . - /// - private bool usingSequence; - - /// - /// Backing for the entire sequence when we're not using . - /// - private ReadOnlySequence sequence; - - /// - /// The position at the start of the . - /// - private SequencePosition currentPosition; - - /// - /// The position at the end of the . - /// - private SequencePosition nextPosition; - - /// - /// Backing for the entire sequence when we're not using . - /// - private ReadOnlyMemory memory; - - /// - /// A value indicating whether there is unread data remaining. - /// - private bool moreData; - - /// - /// The total number of elements in the sequence. - /// - private long length; - - /// - /// Initializes a new instance of the struct - /// over the given . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SequenceReader(ReadOnlySequence sequence) - { - this.usingSequence = true; - this.CurrentSpanIndex = 0; - this.Consumed = 0; - this.sequence = sequence; - this.memory = default; - this.currentPosition = sequence.Start; - this.length = -1; - - ReadOnlySpan first = sequence.First.Span; - this.nextPosition = sequence.GetPosition(first.Length); - this.CurrentSpan = first; - this.moreData = first.Length > 0; - - if (!this.moreData && !sequence.IsSingleSegment) - { - this.moreData = true; - this.GetNextSpan(); - } - } - - /// - /// Initializes a new instance of the struct - /// over the given . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SequenceReader(ReadOnlyMemory memory) - { - this.usingSequence = false; - this.CurrentSpanIndex = 0; - this.Consumed = 0; - this.memory = memory; - this.CurrentSpan = memory.Span; - this.length = memory.Length; - this.moreData = memory.Length > 0; - - this.currentPosition = default; - this.nextPosition = default; - this.sequence = default; - } - - /// - /// Gets a value indicating whether there is no more data in the . - /// - public bool End => !this.moreData; - - /// - /// Gets the underlying for the reader. - /// - public ReadOnlySequence Sequence - { - get - { - if (this.sequence.IsEmpty && !this.memory.IsEmpty) - { - // We're in memory mode (instead of sequence mode). - // Lazily fill in the sequence data. - this.sequence = new ReadOnlySequence(this.memory); - this.currentPosition = this.sequence.Start; - this.nextPosition = this.sequence.End; - } - - return this.sequence; - } - } - - /// - /// Gets the current position in the . - /// - public SequencePosition Position - => this.Sequence.GetPosition(this.CurrentSpanIndex, this.currentPosition); - - /// - /// Gets the current segment in the as a span. - /// - public ReadOnlySpan CurrentSpan { get; private set; } - - /// - /// Gets the index in the . - /// - public int CurrentSpanIndex { get; private set; } - - /// - /// Gets the unread portion of the . - /// - public ReadOnlySpan UnreadSpan - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => this.CurrentSpan.Slice(this.CurrentSpanIndex); - } - - /// - /// Gets the total number of 's processed by the reader. - /// - public long Consumed { get; private set; } - - /// - /// Gets remaining 's in the reader's . - /// - public long Remaining => this.Length - this.Consumed; - - /// - /// Gets count of in the reader's . - /// - public long Length - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if (this.length < 0) - { - // Cache the length - this.length = this.Sequence.Length; - } - - return this.length; - } - } - - /// - /// Peeks at the next value without advancing the reader. - /// - /// The next value or default if at the end. - /// False if at the end of the reader. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryPeek(out T value) - { - if (this.moreData) - { - value = this.CurrentSpan[this.CurrentSpanIndex]; - return true; - } - else - { - value = default; - return false; - } - } - - /// - /// Read the next value and advance the reader. - /// - /// The next value or default if at the end. - /// False if at the end of the reader. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryRead(out T value) - { - if (this.End) - { - value = default; - return false; - } - - value = this.CurrentSpan[this.CurrentSpanIndex]; - this.CurrentSpanIndex++; - this.Consumed++; - - if (this.CurrentSpanIndex >= this.CurrentSpan.Length) - { - if (this.usingSequence) - { - this.GetNextSpan(); - } - else - { - this.moreData = false; - } - } - - return true; - } - - /// - /// Move the reader back the specified number of items. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Rewind(long count) - { - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count)); - } - - this.Consumed -= count; - - if (this.CurrentSpanIndex >= count) - { - this.CurrentSpanIndex -= (int)count; - this.moreData = true; - } - else if (this.usingSequence) - { - // Current segment doesn't have enough data, scan backward through segments - this.RetreatToPreviousSpan(this.Consumed); - } - else - { - throw new ArgumentOutOfRangeException("Rewind went past the start of the memory."); - } - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private void RetreatToPreviousSpan(long consumed) - { - Debug.Assert(this.usingSequence, "usingSequence"); - this.ResetReader(); - this.Advance(consumed); - } - - private void ResetReader() - { - Debug.Assert(this.usingSequence, "usingSequence"); - this.CurrentSpanIndex = 0; - this.Consumed = 0; - this.currentPosition = this.Sequence.Start; - this.nextPosition = this.currentPosition; - - if (this.Sequence.TryGet(ref this.nextPosition, out ReadOnlyMemory memory, advance: true)) - { - this.moreData = true; - - if (memory.Length == 0) - { - this.CurrentSpan = default; - - // No data in the first span, move to one with data - this.GetNextSpan(); - } - else - { - this.CurrentSpan = memory.Span; - } - } - else - { - // No data in any spans and at end of sequence - this.moreData = false; - this.CurrentSpan = default; - } - } - - /// - /// Get the next segment with available data, if any. - /// - private void GetNextSpan() - { - Debug.Assert(this.usingSequence, "usingSequence"); - if (!this.Sequence.IsSingleSegment) - { - SequencePosition previousNextPosition = this.nextPosition; - while (this.Sequence.TryGet(ref this.nextPosition, out ReadOnlyMemory memory, advance: true)) - { - this.currentPosition = previousNextPosition; - if (memory.Length > 0) - { - this.CurrentSpan = memory.Span; - this.CurrentSpanIndex = 0; - return; - } - else - { - this.CurrentSpan = default; - this.CurrentSpanIndex = 0; - previousNextPosition = this.nextPosition; - } - } - } - - this.moreData = false; - } - - /// - /// Move the reader ahead the specified number of items. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Advance(long count) - { - const long TooBigOrNegative = unchecked((long)0xFFFFFFFF80000000); - if ((count & TooBigOrNegative) == 0 && this.CurrentSpan.Length - this.CurrentSpanIndex > (int)count) - { - this.CurrentSpanIndex += (int)count; - this.Consumed += count; - } - else if (this.usingSequence) - { - // Can't satisfy from the current span - this.AdvanceToNextSpan(count); - } - else if (this.CurrentSpan.Length - this.CurrentSpanIndex == (int)count) - { - this.CurrentSpanIndex += (int)count; - this.Consumed += count; - this.moreData = false; - } - else - { - throw new ArgumentOutOfRangeException(nameof(count)); - } - } - - /// - /// Unchecked helper to avoid unnecessary checks where you know count is valid. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void AdvanceCurrentSpan(long count) - { - Debug.Assert(count >= 0, "count >= 0"); - - this.Consumed += count; - this.CurrentSpanIndex += (int)count; - if (this.usingSequence && this.CurrentSpanIndex >= this.CurrentSpan.Length) - { - this.GetNextSpan(); - } - } - - /// - /// Only call this helper if you know that you are advancing in the current span - /// with valid count and there is no need to fetch the next one. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void AdvanceWithinSpan(long count) - { - Debug.Assert(count >= 0, "count >= 0"); - - this.Consumed += count; - this.CurrentSpanIndex += (int)count; - - Debug.Assert(this.CurrentSpanIndex < this.CurrentSpan.Length, "this.CurrentSpanIndex < this.CurrentSpan.Length"); - } - - /// - /// Move the reader ahead the specified number of items - /// if there are enough elements remaining in the sequence. - /// - /// true if there were enough elements to advance; otherwise false. - internal bool TryAdvance(long count) - { - if (this.Remaining < count) - { - return false; - } - - this.Advance(count); - return true; - } - - private void AdvanceToNextSpan(long count) - { - Debug.Assert(this.usingSequence, "usingSequence"); - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count)); - } - - this.Consumed += count; - while (this.moreData) - { - int remaining = this.CurrentSpan.Length - this.CurrentSpanIndex; - - if (remaining > count) - { - this.CurrentSpanIndex += (int)count; - count = 0; - break; - } - - // As there may not be any further segments we need to - // push the current index to the end of the span. - this.CurrentSpanIndex += remaining; - count -= remaining; - Debug.Assert(count >= 0, "count >= 0"); - - this.GetNextSpan(); - - if (count == 0) - { - break; - } - } - - if (count != 0) - { - // Not enough data left- adjust for where we actually ended and throw - this.Consumed -= count; - throw new ArgumentOutOfRangeException(nameof(count)); - } - } - - /// - /// Copies data from the current to the given span. - /// - /// Destination to copy to. - /// True if there is enough data to copy to the . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryCopyTo(Span destination) - { - ReadOnlySpan firstSpan = this.UnreadSpan; - if (firstSpan.Length >= destination.Length) - { - firstSpan.Slice(0, destination.Length).CopyTo(destination); - return true; - } - - return this.TryCopyMultisegment(destination); - } - - internal bool TryCopyMultisegment(Span destination) - { - if (this.Remaining < destination.Length) - { - return false; - } - - ReadOnlySpan firstSpan = this.UnreadSpan; - Debug.Assert(firstSpan.Length < destination.Length, "firstSpan.Length < destination.Length"); - firstSpan.CopyTo(destination); - int copied = firstSpan.Length; - - SequencePosition next = this.nextPosition; - while (this.Sequence.TryGet(ref next, out ReadOnlyMemory nextSegment, true)) - { - if (nextSegment.Length > 0) - { - ReadOnlySpan nextSpan = nextSegment.Span; - int toCopy = Math.Min(nextSpan.Length, destination.Length - copied); - nextSpan.Slice(0, toCopy).CopyTo(destination.Slice(copied)); - copied += toCopy; - if (copied >= destination.Length) - { - break; - } - } - } - - return true; - } - - } - -#endif - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Buffers/SequenceReaderExtensions.cs b/src/IKVM.ByteCode/Buffers/SequenceReaderExtensions.cs deleted file mode 100644 index e60681a68f..0000000000 --- a/src/IKVM.ByteCode/Buffers/SequenceReaderExtensions.cs +++ /dev/null @@ -1,284 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Binary; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace IKVM.ByteCode.Buffers -{ - - static partial class SequenceReaderExtensions - { - - /// - /// Try to read the given type out of the buffer if possible. Warning: this is dangerous to use with arbitrary - /// structs- see remarks for full details. - /// - /// - /// IMPORTANT: The read is a straight copy of bits. If a struct depends on specific state of its members to - /// behave correctly this can lead to exceptions, etc. If reading endian specific integers, use the explicit - /// overloads such as . - /// - /// - /// True if successful. will be default if failed (due to lack of space). - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe bool TryRead(ref this SequenceReader reader, out T value) - where T : unmanaged - { - var span = reader.UnreadSpan; - if (span.Length < sizeof(T)) - return TryReadMultisegment(ref reader, out value); - - value = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(span)); - reader.Advance(sizeof(T)); - return true; - } - - static unsafe bool TryReadMultisegment(ref SequenceReader reader, out T value) - where T : unmanaged - { - Debug.Assert(reader.UnreadSpan.Length < sizeof(T), "reader.UnreadSpan.Length < sizeof(T)"); - - // Not enough data in the current segment, try to peek for the data we need. - var buffer = default(T); - var tempSpan = new Span(&buffer, sizeof(T)); - - if (!reader.TryCopyTo(tempSpan)) - { - value = default; - return false; - } - - value = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(tempSpan)); - reader.Advance(sizeof(T)); - return true; - } - - /// - /// Reads an from the next position in the sequence. - /// - /// The reader to read from. - /// Receives the value read. - /// true if there was another byte in the sequence; false otherwise. - public static bool TryRead(ref this SequenceReader reader, out sbyte value) - { - if (TryRead(ref reader, out byte byteValue)) - { - value = unchecked((sbyte)byteValue); - return true; - } - - value = default; - return false; - } - -#if NETFRAMEWORK - - /// - /// Reads an as big endian. - /// - /// False if there wasn't enough data for an . - public static bool TryReadBigEndian(ref this SequenceReader reader, out short value) - { - if (!BitConverter.IsLittleEndian) - { - return reader.TryRead(out value); - } - - return TryReadReverseEndianness(ref reader, out value); - } - -#endif - - /// - /// Reads an as big endian. - /// - /// False if there wasn't enough data for an . - public static bool TryReadBigEndian(ref this SequenceReader reader, out ushort value) - { - if (reader.TryReadBigEndian(out short shortValue)) - { - value = unchecked((ushort)shortValue); - return true; - } - - value = default; - return false; - } - - private static bool TryReadReverseEndianness(ref SequenceReader reader, out short value) - { - if (reader.TryRead(out value)) - { - value = BinaryPrimitives.ReverseEndianness(value); - return true; - } - - return false; - } - -#if NETFRAMEWORK - - /// - /// Reads an as big endian. - /// - /// False if there wasn't enough data for an . - public static bool TryReadBigEndian(ref this SequenceReader reader, out int value) - { - return BitConverter.IsLittleEndian ? TryReadReverseEndianness(ref reader, out value) : reader.TryRead(out value); - } - -#endif - - /// - /// Reads an as big endian. - /// - /// False if there wasn't enough data for an . - public static bool TryReadBigEndian(ref this SequenceReader reader, out uint value) - { - if (reader.TryReadBigEndian(out int intValue)) - { - value = unchecked((uint)intValue); - return true; - } - - value = default; - return false; - } - - static bool TryReadReverseEndianness(ref SequenceReader reader, out int value) - { - if (reader.TryRead(out value)) - { - value = BinaryPrimitives.ReverseEndianness(value); - return true; - } - - return false; - } - -#if NETFRAMEWORK - - /// - /// Reads an as big endian. - /// - /// False if there wasn't enough data for an . - public static bool TryReadBigEndian(ref this SequenceReader reader, out long value) - { - return BitConverter.IsLittleEndian ? TryReadReverseEndianness(ref reader, out value) : reader.TryRead(out value); - } - -#endif - - /// - /// Reads an as big endian. - /// - /// False if there wasn't enough data for an . - public static bool TryReadBigEndian(ref this SequenceReader reader, out ulong value) - { - if (reader.TryReadBigEndian(out long longValue)) - { - value = unchecked((ulong)longValue); - return true; - } - - value = default; - return false; - } - - static bool TryReadReverseEndianness(ref SequenceReader reader, out long value) - { - if (reader.TryRead(out value)) - { - value = BinaryPrimitives.ReverseEndianness(value); - return true; - } - - return false; - } - - /// - /// Reads a as big endian. - /// - /// False if there wasn't enough data for a . - public static unsafe bool TryReadBigEndian(ref this SequenceReader reader, out float value) - { - if (reader.TryReadBigEndian(out int intValue)) - { - value = *(float*)&intValue; - return true; - } - - value = default; - return false; - } - - /// - /// Reads a as big endian. - /// - /// False if there wasn't enough data for a . - public static unsafe bool TryReadBigEndian(ref this SequenceReader reader, out double value) - { - if (reader.TryReadBigEndian(out long longValue)) - { - value = *(double*)&longValue; - return true; - } - - value = default; - return false; - } - - /// - /// Try to read data with given . - /// - /// Read count. - /// The read data, if successfully read requested data. - /// true if remaining items in current is enough for . - public static bool TryReadExact(ref this SequenceReader reader, int count, out ReadOnlySequence sequence) - { - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count)); - - if (count > reader.Remaining) - { - sequence = default; - return false; - } - - sequence = reader.Sequence.Slice(reader.Position, count); - if (count != 0) - reader.Advance(count); - - return true; - } - - /// - /// Try to read data with given . - /// - /// Read count. - /// The read data, if successfully read requested data. - /// true if remaining items in current is enough for . - public static bool TryReadExact(ref this SequenceReader reader, long count, out ReadOnlySequence sequence) - { - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count)); - - if (count > reader.Remaining) - { - sequence = default; - return false; - } - - sequence = reader.Sequence.Slice(reader.Position, count); - if (count != 0) - reader.Advance(count); - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Buffers/UnsafeMemoryManager.cs b/src/IKVM.ByteCode/Buffers/UnsafeMemoryManager.cs deleted file mode 100644 index 45495f1436..0000000000 --- a/src/IKVM.ByteCode/Buffers/UnsafeMemoryManager.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Buffers; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace IKVM.ByteCode.Buffers -{ - - /// - /// A over a raw pointer. - /// - sealed unsafe class UnmanagedMemoryManager : MemoryManager - { - - readonly void* pointer; - readonly int length; - - /// - /// Create a new UnmanagedMemoryManager instance at the given pointer and size - /// - /// It is assumed that the span provided is already unmanaged or externally pinned - public UnmanagedMemoryManager(Span span) - { - pointer = Unsafe.AsPointer(ref MemoryMarshal.GetReference(span)); - length = span.Length; - } - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public UnmanagedMemoryManager(byte* pointer, int length) - { - if (length < 0) - throw new ArgumentOutOfRangeException(nameof(length)); - - this.pointer = pointer; - this.length = length; - } - - /// - public override Span GetSpan() => new(pointer, length); - - /// - public override MemoryHandle Pin(int elementIndex = 0) - { - if (elementIndex < 0 || elementIndex >= length) - throw new ArgumentOutOfRangeException(nameof(elementIndex)); - - return new MemoryHandle(Unsafe.Add(pointer, elementIndex)); - } - - /// - public override void Unpin() - { - } - - /// - protected override void Dispose(bool disposing) - { - - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/ByteCodeException.cs b/src/IKVM.ByteCode/ByteCodeException.cs deleted file mode 100644 index d63f635f7b..0000000000 --- a/src/IKVM.ByteCode/ByteCodeException.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace IKVM.ByteCode -{ - - /// - /// Represents an error that occurred with manipulation of Java byte code or class formats. - /// - [Serializable] - public class ByteCodeException : Exception - { - - /// - /// Initializes a new instance. - /// - internal ByteCodeException() - { - - } - - /// - /// Initializes a new instance. - /// - /// - internal ByteCodeException(string message) : - base(message) - { - - } - - /// - /// Initializes a new instance. - /// - /// - internal ByteCodeException(Exception innerException) : - base(innerException.Message, innerException) - { - - } - - /// - /// Initializes a new instance. - /// - /// - /// - internal ByteCodeException(string message, Exception innerException) : - base(message, innerException) - { - - } - - /// - /// Initializes a new instance. - /// - /// - /// - protected ByteCodeException(SerializationInfo info, StreamingContext context) : - base(info, context) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/ClassFormatVersion.cs b/src/IKVM.ByteCode/ClassFormatVersion.cs deleted file mode 100644 index 33896b9e9d..0000000000 --- a/src/IKVM.ByteCode/ClassFormatVersion.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; - -namespace IKVM.ByteCode -{ - - /// - /// Describes a Java Class file format version number, consisting of a major and minor pair. - /// - /// - /// - internal record struct ClassFormatVersion(int Major, int Minor) : IComparable - { - - public static implicit operator ClassFormatVersion(int major) - { - return new ClassFormatVersion(major, 0); - } - - public static implicit operator string(ClassFormatVersion version) - { - return version.ToString(); - } - - public static bool operator >(ClassFormatVersion a, ClassFormatVersion b) - { - return a.CompareTo(b) is 1; - } - - public static bool operator <(ClassFormatVersion a, ClassFormatVersion b) - { - return a.CompareTo(b) is -1; - } - - public static bool operator >=(ClassFormatVersion a, ClassFormatVersion b) - { - return a.CompareTo(b) is 0 or 1; - } - - public static bool operator <=(ClassFormatVersion a, ClassFormatVersion b) - { - return a.CompareTo(b) is 0 or -1; - } - - public int CompareTo(ClassFormatVersion other) - { - if (Major < other.Major) - return -1; - else if (Major > other.Major) - return 1; - - if (Minor < other.Minor) - return -1; - else if (Minor > other.Minor) - return 1; - - return 0; - } - - public override string ToString() - { - return $"{Major}.{Minor}"; - } - - } - -} diff --git a/src/IKVM.ByteCode/Compiler/IsExternalInit.cs b/src/IKVM.ByteCode/Compiler/IsExternalInit.cs deleted file mode 100644 index e251a1ef91..0000000000 --- a/src/IKVM.ByteCode/Compiler/IsExternalInit.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#if NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2 || NETCOREAPP3_0 || NETCOREAPP3_1 || NET45 || NET451 || NET452 || NET6 || NET461 || NET462 || NET47 || NET471 || NET472 || NET48 - -using System.ComponentModel; - -// ReSharper disable once CheckNamespace -namespace System.Runtime.CompilerServices -{ - /// - /// Reserved to be used by the compiler for tracking metadata. - /// This class should not be used by developers in source code. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - internal static class IsExternalInit - { - } -} - -#endif diff --git a/src/IKVM.ByteCode/IKVM.ByteCode.csproj b/src/IKVM.ByteCode/IKVM.ByteCode.csproj deleted file mode 100644 index 5c4203f6ac..0000000000 --- a/src/IKVM.ByteCode/IKVM.ByteCode.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - net472;net6.0;net7.0;net8.0 - 11 - true - true - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/IKVM.ByteCode/InvalidClassException.cs b/src/IKVM.ByteCode/InvalidClassException.cs deleted file mode 100644 index 75246f0684..0000000000 --- a/src/IKVM.ByteCode/InvalidClassException.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace IKVM.ByteCode -{ - - /// - /// Describes an attempt to parse an unsupported class file. - /// - internal class InvalidClassException : - ByteCodeException - { - - /// - /// Initializes a new instance. - /// - /// - internal InvalidClassException(string message) : - base(message) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/InvalidClassMagicException.cs b/src/IKVM.ByteCode/InvalidClassMagicException.cs deleted file mode 100644 index 8a8146980a..0000000000 --- a/src/IKVM.ByteCode/InvalidClassMagicException.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace IKVM.ByteCode -{ - - /// - /// Describes an attempt to parse an unsupported class magic value. - /// - internal sealed class InvalidClassMagicException : - InvalidClassException - { - - readonly uint magic; - - /// - /// Initializes a new instance. - /// - /// - internal InvalidClassMagicException(uint magic) : - base($"Invalid class magic value {magic}.") - { - this.magic = magic; - } - - /// - /// Gets the magic that was found in the class file. - /// - public uint Magic => magic; - - } - -} diff --git a/src/IKVM.ByteCode/LICENSE.md b/src/IKVM.ByteCode/LICENSE.md deleted file mode 100644 index 474cf1932b..0000000000 --- a/src/IKVM.ByteCode/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 Jerome Haltom, etc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/src/IKVM.ByteCode/ModuleExportsFlag.cs b/src/IKVM.ByteCode/ModuleExportsFlag.cs deleted file mode 100644 index 791f2b0085..0000000000 --- a/src/IKVM.ByteCode/ModuleExportsFlag.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace IKVM.ByteCode -{ - - [Flags] - internal enum ModuleExportsFlag : ushort - { - - Synthetic = 0x1000, - Mandated = 0x8000, - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/ModuleFlag.cs b/src/IKVM.ByteCode/ModuleFlag.cs deleted file mode 100644 index 711ea82db7..0000000000 --- a/src/IKVM.ByteCode/ModuleFlag.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace IKVM.ByteCode -{ - - [Flags] - internal enum ModuleFlag : ushort - { - - Open = 0x0020, - Synthetic = 0x1000, - Mandated = 0x8000, - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/ModuleOpensFlag.cs b/src/IKVM.ByteCode/ModuleOpensFlag.cs deleted file mode 100644 index ea6ade7d54..0000000000 --- a/src/IKVM.ByteCode/ModuleOpensFlag.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace IKVM.ByteCode -{ - - [Flags] - internal enum ModuleOpensFlag : ushort - { - - Synthetic = 0x1000, - Mandated = 0x8000, - - } - -} diff --git a/src/IKVM.ByteCode/ModuleRequiresFlag.cs b/src/IKVM.ByteCode/ModuleRequiresFlag.cs deleted file mode 100644 index da6dc0457c..0000000000 --- a/src/IKVM.ByteCode/ModuleRequiresFlag.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace IKVM.ByteCode -{ - - [Flags] - internal enum ModuleRequiresFlag : ushort - { - - Transitive = 0x0020, - StaticPhase = 0x0040, - Synthetic = 0x1000, - Mandated = 0x8000, - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/AnnotationDefaultAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/AnnotationDefaultAttributeRecord.cs deleted file mode 100644 index a714c0a5be..0000000000 --- a/src/IKVM.ByteCode/Parsing/AnnotationDefaultAttributeRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record AnnotationDefaultAttributeRecord(ElementValueRecord DefaultValue) : AttributeRecord - { - - public static bool TryReadAnnotationDefaultAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (ElementValueRecord.TryRead(ref reader, out var defaultValue) == false) - return false; - - attribute = new AnnotationDefaultAttributeRecord(defaultValue); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/AnnotationRecord.cs b/src/IKVM.ByteCode/Parsing/AnnotationRecord.cs deleted file mode 100644 index c7da556b50..0000000000 --- a/src/IKVM.ByteCode/Parsing/AnnotationRecord.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct AnnotationRecord(ushort TypeIndex, ElementValuePairRecord[] Elements) - { - - public static bool TryReadAnnotation(ref ClassFormatReader reader, out AnnotationRecord annotation) - { - annotation = default; - - if (reader.TryReadU2(out ushort typeIndex) == false) - return false; - if (reader.TryReadU2(out ushort pairCount) == false) - return false; - - var elements = new ElementValuePairRecord[pairCount]; - for (int i = 0; i < pairCount; i++) - { - if (ElementValuePairRecord.TryRead(ref reader, out var element) == false) - return false; - - elements[i] = element; - } - - annotation = new AnnotationRecord(typeIndex, elements); - return true; - } - - public int GetSize() - { - var size = 0; - size += sizeof(ushort); - size += sizeof(ushort); - - foreach (var element in Elements) - size += element.GetSize(); - - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(TypeIndex) == false) - return false; - if (writer.TryWriteU2((ushort)Elements.Length) == false) - return false; - - foreach (var element in Elements) - if (element.TryWrite(ref writer) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/AppendStackMapFrameRecord.cs b/src/IKVM.ByteCode/Parsing/AppendStackMapFrameRecord.cs deleted file mode 100644 index 255022276a..0000000000 --- a/src/IKVM.ByteCode/Parsing/AppendStackMapFrameRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record AppendStackMapFrameRecord(byte Tag, ushort OffsetDelta, VerificationTypeInfoRecord[] Locals) : StackMapFrameRecord(Tag) - { - - public static bool TryReadAppendStackMapFrame(ref ClassFormatReader reader, byte tag, out StackMapFrameRecord frame) - { - frame = null; - - if (reader.TryReadU2(out ushort offsetDelta) == false) - return false; - - var locals = new VerificationTypeInfoRecord[tag - 251]; - for (int i = 0; i < tag - 251; i++) - { - if (VerificationTypeInfoRecord.TryReadVerificationTypeInfo(ref reader, out var local) == false) - return false; - - locals[i] = local; - } - - frame = new AppendStackMapFrameRecord(tag, offsetDelta, locals); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/AttributeInfoRecord.cs b/src/IKVM.ByteCode/Parsing/AttributeInfoRecord.cs deleted file mode 100644 index a60786bd8b..0000000000 --- a/src/IKVM.ByteCode/Parsing/AttributeInfoRecord.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Buffers; - -namespace IKVM.ByteCode.Parsing -{ - - internal record struct AttributeInfoRecord(ushort NameIndex, byte[] Data) - { - - /// - /// Parses an attribute. - /// - /// - /// - public static bool TryReadAttribute(ref ClassFormatReader reader, out AttributeInfoRecord attribute) - { - attribute = default; - - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - if (reader.TryReadU4(out uint length) == false) - return false; - if (reader.TryReadManyU1(length, out var info) == false) - return false; - - var infoBuffer = new byte[info.Length]; - info.CopyTo(infoBuffer); - - attribute = new AttributeInfoRecord(nameIndex, infoBuffer); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/AttributeRecord.cs b/src/IKVM.ByteCode/Parsing/AttributeRecord.cs deleted file mode 100644 index bc302ef9a8..0000000000 --- a/src/IKVM.ByteCode/Parsing/AttributeRecord.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Buffers; - -using IKVM.ByteCode.Reading; - -namespace IKVM.ByteCode.Parsing -{ - - internal abstract record AttributeRecord - { - - /// - /// Attempts to read an attribute data record from the specified . - /// - /// - /// - /// - public static bool TryRead(AttributeInfoReader info, out AttributeRecord attribute) - { - return TryRead(info.Name.Value, new ReadOnlySequence(info.Data), out attribute); - } - - /// - /// Attempts to read an attribute data record from the specified . - /// - /// - /// - /// - /// - public static bool TryRead(string name, ReadOnlySequence data, out AttributeRecord attribute) - { - var reader = new ClassFormatReader(data); - if (TryReadAttribute(name, ref reader, out attribute) == false) - return false; - - return true; - } - - /// - /// Attempts to read a class record starting at the current position. - /// - /// - /// - /// - /// - /// - public static bool TryReadAttribute(string name, ref ClassFormatReader reader, out AttributeRecord attribute) => name switch - { - "ConstantValue" => ConstantValueAttributeRecord.TryReadConstantValueAttribute(ref reader, out attribute), - "Code" => CodeAttributeRecord.TryReadCodeAttribute(ref reader, out attribute), - "StackMapTable" => StackMapTableAttributeRecord.TryRead(ref reader, out attribute), - "Exceptions" => ExceptionsAttributeRecord.TryReadExceptionsAttribute(ref reader, out attribute), - "InnerClasses" => InnerClassesAttributeRecord.TryReadInnerClassesAttribute(ref reader, out attribute), - "EnclosingMethod" => EnclosingMethodAttributeRecord.TryReadEnclosingMethodAttribute(ref reader, out attribute), - "Synthetic" => SyntheticAttributeRecord.TryReadSyntheticAttribute(ref reader, out attribute), - "Signature" => SignatureAttributeRecord.TryReadSignatureAttribute(ref reader, out attribute), - "SourceFile" => SourceFileAttributeRecord.TryReadSourceFileAttribute(ref reader, out attribute), - "SourceDebugExtension" => SourceDebugExtensionAttributeRecord.TryReadSourceDebugExtensionAttribute(ref reader, out attribute), - "LineNumberTable" => LineNumberTableAttributeRecord.TryReadLineNumberTableAttribute(ref reader, out attribute), - "LocalVariableTable" => LocalVariableTableAttributeRecord.TryReadLocalVariableTableAttribute(ref reader, out attribute), - "LocalVariableTypeTable" => LocalVariableTypeTableAttributeRecord.TryReadLocalVariableTypeTableAttribute(ref reader, out attribute), - "Deprecated" => DeprecatedAttributeRecord.TryReadDeprecatedAttribute(ref reader, out attribute), - "RuntimeVisibleAnnotations" => RuntimeVisibleAnnotationsAttributeRecord.TryReadRuntimeVisibleAnnotationsAttribute(ref reader, out attribute), - "RuntimeInvisibleAnnotations" => RuntimeInvisibleAnnotationsAttributeRecord.TryReadRuntimeInvisibleAnnotationsAttribute(ref reader, out attribute), - "RuntimeVisibleParameterAnnotations" => RuntimeVisibleParameterAnnotationsAttributeRecord.TryReadRuntimeVisibleParameterAnnotationsAttribute(ref reader, out attribute), - "RuntimeInvisibleParameterAnnotations" => RuntimeInvisibleParameterAnnotationsAttributeRecord.TryReadRuntimeInvisibleParameterAnnotationsAttribute(ref reader, out attribute), - "RuntimeVisibleTypeAnnotations" => RuntimeVisibleTypeAnnotationsAttributeRecord.TryReadRuntimeVisibleTypeAnnotationsAttribute(ref reader, out attribute), - "RuntimeInvisibleTypeAnnotations" => RuntimeInvisibleTypeAnnotationsAttributeRecord.TryReadRuntimeInvisibleTypeAnnotationsAttribute(ref reader, out attribute), - "AnnotationDefault" => AnnotationDefaultAttributeRecord.TryReadAnnotationDefaultAttribute(ref reader, out attribute), - "BootstrapMethods" => BootstrapMethodsAttributeRecord.TryReadBootstrapMethodsAttribute(ref reader, out attribute), - "MethodParameters" => MethodParametersAttributeRecord.TryReadMethodParametersAttribute(ref reader, out attribute), - "Module" => ModuleAttributeRecord.TryReadModuleAttribute(ref reader, out attribute), - "ModulePackages" => ModulePackagesAttributeRecord.TryReadModulePackagesAttribute(ref reader, out attribute), - "ModuleMainClass" => ModuleMainClassAttributeRecord.TryReadModuleMainClassAttribute(ref reader, out attribute), - "NestHost" => NestHostAttributeRecord.TryReadNestHostAttribute(ref reader, out attribute), - "NestMembers" => NestMembersAttributeRecord.TryReadNestMembersAttribute(ref reader, out attribute), - "Record" => RecordAttributeRecord.TryReadRecordAttribute(ref reader, out attribute), - "PermittedSubclasses" => PermittedSubclassesAttributeRecord.TryReadPermittedSubclassesAttribute(ref reader, out attribute), - _ => UnknownAttributeRecord.TryReadCustomAttribute(ref reader, out attribute), - }; - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/BootstrapMethodsAttributeMethodRecord.cs b/src/IKVM.ByteCode/Parsing/BootstrapMethodsAttributeMethodRecord.cs deleted file mode 100644 index b40529a97b..0000000000 --- a/src/IKVM.ByteCode/Parsing/BootstrapMethodsAttributeMethodRecord.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct BootstrapMethodsAttributeMethodRecord(ushort MethodRefIndex, ushort[] Arguments) - { - - public static bool TryReadBootstrapMethod(ref ClassFormatReader reader, out BootstrapMethodsAttributeMethodRecord method) - { - method = default; - - if (reader.TryReadU2(out ushort methodRefIndex) == false) - return false; - if (reader.TryReadU2(out ushort argumentCount) == false) - return false; - - var arguments = new ushort[argumentCount]; - for (int i = 0; i < argumentCount; i++) - { - if (reader.TryReadU2(out ushort argumentIndex) == false) - return false; - - arguments[i] = argumentIndex; - } - - method = new BootstrapMethodsAttributeMethodRecord(methodRefIndex, arguments); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/BootstrapMethodsAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/BootstrapMethodsAttributeRecord.cs deleted file mode 100644 index 5fa5c4e554..0000000000 --- a/src/IKVM.ByteCode/Parsing/BootstrapMethodsAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record BootstrapMethodsAttributeRecord(BootstrapMethodsAttributeMethodRecord[] Methods) : AttributeRecord - { - - public static bool TryReadBootstrapMethodsAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var methods = new BootstrapMethodsAttributeMethodRecord[count]; - for (int i = 0; i < count; i++) - { - if (BootstrapMethodsAttributeMethodRecord.TryReadBootstrapMethod(ref reader, out var method) == false) - return false; - - methods[i] = method; - } - - attribute = new BootstrapMethodsAttributeRecord(methods); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ChopStackMapFrameRecord.cs b/src/IKVM.ByteCode/Parsing/ChopStackMapFrameRecord.cs deleted file mode 100644 index cd7a52c5a6..0000000000 --- a/src/IKVM.ByteCode/Parsing/ChopStackMapFrameRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ChopStackMapFrameRecord(byte Tag, ushort OffsetDelta) : StackMapFrameRecord(Tag) - { - - public static bool TryReadChopStackMapFrame(ref ClassFormatReader reader, byte tag, out StackMapFrameRecord frame) - { - frame = null; - - if (reader.TryReadU2(out ushort offsetDelta) == false) - return false; - - frame = new ChopStackMapFrameRecord(tag, offsetDelta); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ClassConstantRecord.cs b/src/IKVM.ByteCode/Parsing/ClassConstantRecord.cs deleted file mode 100644 index 67502749e5..0000000000 --- a/src/IKVM.ByteCode/Parsing/ClassConstantRecord.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ClassConstantRecord(ushort NameIndex) : ConstantRecord - { - - /// - /// Parses a Class constant in the constant pool. - /// - /// - /// - public static bool TryReadClassConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - - constant = new ClassConstantRecord(nameIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ClassFormatReader.cs b/src/IKVM.ByteCode/Parsing/ClassFormatReader.cs deleted file mode 100644 index 7e9247dc8d..0000000000 --- a/src/IKVM.ByteCode/Parsing/ClassFormatReader.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Buffers; - -using IKVM.ByteCode.Buffers; - -namespace IKVM.ByteCode.Parsing -{ - - /// - /// Provides common methods to read through memory of a Class file. - /// - internal ref struct ClassFormatReader - { - - SequenceReader reader; - - /// - /// Initializes a new instance. - /// - /// - public ClassFormatReader(ReadOnlyMemory buffer) : - this(new ReadOnlySequence(buffer)) - { - - } - - /// - /// Initializes a new instance. - /// - /// - public ClassFormatReader(ReadOnlySequence sequence) - { - reader = new SequenceReader(sequence); - } - - /// - /// Gets the count of bytes in the reader. - /// - public readonly long Length => reader.Length; - - /// - /// Gets the current position in the reader. - /// - public readonly SequencePosition Position => reader.Position; - - /// - /// Attempts to read a value defined as a 'u1'. - /// - /// - /// - public bool TryReadU1(out byte u1) - { - return reader.TryRead(out u1); - } - - /// - /// Attempts to read a value defined as a 'u2'. - /// - /// - /// - public bool TryReadU2(out ushort u2) - { - return reader.TryReadBigEndian(out u2); - } - - /// - /// Attempts to read a value defined as a 'u4'. - /// - /// - /// - public bool TryReadU4(out uint u4) - { - return reader.TryReadBigEndian(out u4); - } - - /// - /// Attempts to read the exact given number of bytes. - /// - /// - /// - /// - public bool TryReadManyU1(uint count, out ReadOnlySequence sequence) - { - return reader.TryReadExact(count, out sequence); - } - - /// - /// Attempts to read the exact given number of bytes. - /// - /// - /// - /// - public bool TryReadManyU1(long count, out ReadOnlySequence sequence) - { - return reader.TryReadExact(count, out sequence); - } - - /// - /// Attempts to copy available data at the current position to the destination. - /// - /// - /// - public bool TryCopyTo(Span destination) - { - return reader.TryCopyTo(destination); - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ClassFormatWriter.cs b/src/IKVM.ByteCode/Parsing/ClassFormatWriter.cs deleted file mode 100644 index eba9ddc1fe..0000000000 --- a/src/IKVM.ByteCode/Parsing/ClassFormatWriter.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Buffers.Binary; - -namespace IKVM.ByteCode.Parsing -{ - - /// - /// Provides a forward-only writer of big-endian values. - /// - internal ref struct ClassFormatWriter - { - - Span span; - Span next; - long size = 0; - - /// - /// Initializes a new instance. - /// - /// - public ClassFormatWriter(Span span) - { - this.span = next = span; - } - - /// - /// Gets the span being written to. - /// - public Span Span => span; - - /// - /// Gets the total number of written bytes. - /// - public long Size => size; - - /// - /// Writes a value defined as a 'u1' in the class format specification. - /// - /// - /// - public bool TryWriteU1(byte value) - { - if (next.Length < sizeof(byte)) - return false; - - next[0] = value; - next = next.Slice(sizeof(byte)); - size += sizeof(byte); - return true; - } - - /// - /// Writes a value defined as a 'u2' in the class format specification. - /// - /// - /// - public bool TryWriteU2(ushort value) - { - if (next.Length < sizeof(ushort)) - return false; - - BinaryPrimitives.WriteUInt16BigEndian(next, value); - next = next.Slice(sizeof(ushort)); - size += sizeof(ushort); - return true; - } - - /// - /// Writes a value defined as a 'u4' in the class format specification. - /// - /// - /// - public bool TryWriteU4(uint value) - { - if (next.Length < sizeof(uint)) - return false; - - BinaryPrimitives.WriteUInt32BigEndian(next, value); - next = next.Slice(sizeof(uint)); - size += sizeof(uint); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ClassRecord.cs b/src/IKVM.ByteCode/Parsing/ClassRecord.cs deleted file mode 100644 index f5cae1370e..0000000000 --- a/src/IKVM.ByteCode/Parsing/ClassRecord.cs +++ /dev/null @@ -1,187 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct ClassRecord(ushort MinorVersion, ushort MajorVersion, ConstantRecord[] Constants, AccessFlag AccessFlags, ushort ThisClassIndex, ushort SuperClassIndex, InterfaceRecord[] Interfaces, FieldRecord[] Fields, MethodRecord[] Methods, AttributeInfoRecord[] Attributes) - { - - const uint MAGIC = 0xCAFEBABE; - - /// - /// Attempts to read a class record starting at the current position. - /// - /// - /// - /// - public static bool TryRead(ref ClassFormatReader reader, out ClassRecord clazz) - { - clazz = default; - - if (reader.TryReadU4(out uint magic) == false) - return false; - if (magic != MAGIC) - throw new InvalidClassMagicException(magic); - - if (reader.TryReadU2(out ushort minorVersion) == false) - return false; - if (reader.TryReadU2(out ushort majorVersion) == false) - return false; - - if (majorVersion > 63) - throw new UnsupportedClassVersionException(new ClassFormatVersion(majorVersion, minorVersion)); - - if (TryReadConstants(ref reader, out var constants) == false) - return false; - - if (reader.TryReadU2(out ushort accessFlags) == false) - return false; - - if (reader.TryReadU2(out ushort thisClass) == false) - return false; - - if (reader.TryReadU2(out ushort superClass) == false) - return false; - - if (TryReadInterfaces(ref reader, out var interfaces) == false) - return false; - - if (TryReadFields(ref reader, out var fields) == false) - return false; - - if (TryReadMethods(ref reader, out var methods) == false) - return false; - - if (TryReadAttributes(ref reader, out var attributes) == false) - return false; - - clazz = new ClassRecord(minorVersion, majorVersion, constants, (AccessFlag)accessFlags, thisClass, superClass, interfaces, fields, methods, attributes); - return true; - } - - /// - /// Attempts to read the set of constants at the current position. - /// - /// - /// - /// - static bool TryReadConstants(ref ClassFormatReader reader, out ConstantRecord[] constants) - { - constants = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - constants = new ConstantRecord[count]; - for (int i = 1; i < count; i++) - { - if (ConstantRecord.TryRead(ref reader, out var constant, out var skip) == false) - return false; - - constants[i] = constant; - i += skip; - } - - return true; - } - - /// - /// Attempts to read the set of interfaces starting from the current position. - /// - /// - /// - /// - static bool TryReadInterfaces(ref ClassFormatReader reader, out InterfaceRecord[] interfaces) - { - interfaces = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - interfaces = new InterfaceRecord[count]; - for (int i = 0; i < count; i++) - { - if (InterfaceRecord.TryRead(ref reader, out InterfaceRecord iface) == false) - return false; - - interfaces[i] = iface; - } - - return true; - } - - /// - /// Attempts to read the set of fields starting from the current position. - /// - /// - /// - /// - static bool TryReadFields(ref ClassFormatReader reader, out FieldRecord[] fields) - { - fields = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - fields = new FieldRecord[count]; - for (int i = 0; i < count; i++) - { - if (FieldRecord.TryRead(ref reader, out FieldRecord field) == false) - return false; - - fields[i] = field; - } - - return true; - } - - /// - /// Attempts to read the set of methods starting from the current position. - /// - /// - /// - /// - static bool TryReadMethods(ref ClassFormatReader reader, out MethodRecord[] methods) - { - methods = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - methods = new MethodRecord[count]; - for (int i = 0; i < count; i++) - { - if (MethodRecord.TryRead(ref reader, out MethodRecord method) == false) - return false; - - methods[i] = method; - } - - return true; - } - - /// - /// Parses an attributes count followed by a sequence of attributes. - /// - /// - /// - internal static bool TryReadAttributes(ref ClassFormatReader reader, out AttributeInfoRecord[] attributes) - { - attributes = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - attributes = new AttributeInfoRecord[count]; - for (int i = 0; i < count; i++) - { - if (AttributeInfoRecord.TryReadAttribute(ref reader, out var attribute) == false) - return false; - - attributes[i] = attribute; - } - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/CodeAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/CodeAttributeRecord.cs deleted file mode 100644 index e8bd677a31..0000000000 --- a/src/IKVM.ByteCode/Parsing/CodeAttributeRecord.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Buffers; - -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record CodeAttributeRecord(ushort MaxStack, ushort MaxLocals, ReadOnlyMemory Code, ExceptionHandlerRecord[] ExceptionTable, AttributeInfoRecord[] Attributes) : AttributeRecord - { - - public static bool TryReadCodeAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort maxStack) == false) - return false; - if (reader.TryReadU2(out ushort maxLocals) == false) - return false; - if (reader.TryReadU4(out uint codeLength) == false) - return false; - if (reader.TryReadManyU1(codeLength, out ReadOnlySequence code) == false) - return false; - - var codeBuffer = new byte[code.Length]; - code.CopyTo(codeBuffer); - - if (reader.TryReadU2(out ushort exceptionTableLength) == false) - return false; - - var exceptionTable = new ExceptionHandlerRecord[(int)exceptionTableLength]; - for (int i = 0; i < exceptionTableLength; i++) - { - if (reader.TryReadU2(out ushort startOffset) == false) - return false; - if (reader.TryReadU2(out ushort endOffset) == false) - return false; - if (reader.TryReadU2(out ushort handlerOffset) == false) - return false; - if (reader.TryReadU2(out ushort catchTypeIndex) == false) - return false; - - exceptionTable[i] = new ExceptionHandlerRecord(startOffset, endOffset, handlerOffset, catchTypeIndex); - } - - if (ClassRecord.TryReadAttributes(ref reader, out var attributes) == false) - return false; - - attribute = new CodeAttributeRecord(maxStack, maxLocals, codeBuffer, exceptionTable, attributes); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ConstantRecord.cs b/src/IKVM.ByteCode/Parsing/ConstantRecord.cs deleted file mode 100644 index 3986e4cb61..0000000000 --- a/src/IKVM.ByteCode/Parsing/ConstantRecord.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - /// - /// Base type for constant records. - /// - internal abstract record ConstantRecord - { - - /// - /// Attempts to read the constant at the current position. Returns the the number of index positions to skip. - /// - /// - /// - /// - /// - public static bool TryRead(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU1(out byte tag) == false) - return false; - - return (ConstantTag)tag switch - { - ConstantTag.Utf8 => Utf8ConstantRecord.TryReadUtf8Constant(ref reader, out constant, out skip), - ConstantTag.Integer => IntegerConstantRecord.TryReadIntegerConstant(ref reader, out constant, out skip), - ConstantTag.Float => FloatConstantRecord.TryReadFloatConstant(ref reader, out constant, out skip), - ConstantTag.Long => LongConstantRecord.TryReadLongConstant(ref reader, out constant, out skip), - ConstantTag.Double => DoubleConstantRecord.TryReadDoubleConstant(ref reader, out constant, out skip), - ConstantTag.Class => ClassConstantRecord.TryReadClassConstant(ref reader, out constant, out skip), - ConstantTag.String => StringConstantRecord.TryReadStringConstant(ref reader, out constant, out skip), - ConstantTag.Fieldref => FieldrefConstantRecord.TryReadFieldrefConstant(ref reader, out constant, out skip), - ConstantTag.Methodref => MethodrefConstantRecord.TryReadMethodrefConstant(ref reader, out constant, out skip), - ConstantTag.InterfaceMethodref => InterfaceMethodrefConstantRecord.TryReadInterfaceMethodrefConstant(ref reader, out constant, out skip), - ConstantTag.NameAndType => NameAndTypeConstantRecord.TryReadNameAndTypeConstant(ref reader, out constant, out skip), - ConstantTag.MethodHandle => MethodHandleConstantRecord.TryReadMethodHandleConstant(ref reader, out constant, out skip), - ConstantTag.MethodType => MethodTypeConstantRecord.TryReadMethodTypeConstant(ref reader, out constant, out skip), - ConstantTag.Dynamic => DynamicConstantRecord.TryReadDynamicConstant(ref reader, out constant, out skip), - ConstantTag.InvokeDynamic => InvokeDynamicConstantRecord.TryReadInvokeDynamicConstant(ref reader, out constant, out skip), - ConstantTag.Module => ModuleConstantRecord.TryReadModuleConstant(ref reader, out constant, out skip), - ConstantTag.Package => PackageConstantRecord.TryReadPackageConstant(ref reader, out constant, out skip), - _ => throw new ByteCodeException($"Encountered an unknown constant tag: '0x{tag:X}'."), - }; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ConstantTag.cs b/src/IKVM.ByteCode/Parsing/ConstantTag.cs deleted file mode 100644 index 94a712c1d3..0000000000 --- a/src/IKVM.ByteCode/Parsing/ConstantTag.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal enum ConstantTag : byte - { - - Utf8 = 1, - Integer = 3, - Float = 4, - Long = 5, - Double = 6, - Class = 7, - String = 8, - Fieldref = 9, - Methodref = 10, - InterfaceMethodref = 11, - NameAndType = 12, - MethodHandle = 15, - MethodType = 16, - Dynamic = 17, - InvokeDynamic = 18, - Module = 19, - Package = 20, - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ConstantValueAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/ConstantValueAttributeRecord.cs deleted file mode 100644 index 1859a13d23..0000000000 --- a/src/IKVM.ByteCode/Parsing/ConstantValueAttributeRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ConstantValueAttributeRecord(ushort ValueIndex) : AttributeRecord - { - - public static bool TryReadConstantValueAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort valueIndex) == false) - return false; - - attribute = new ConstantValueAttributeRecord(valueIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/DeprecatedAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/DeprecatedAttributeRecord.cs deleted file mode 100644 index eb835d2106..0000000000 --- a/src/IKVM.ByteCode/Parsing/DeprecatedAttributeRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record DeprecatedAttributeRecord : AttributeRecord - { - - public static bool TryReadDeprecatedAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = new DeprecatedAttributeRecord(); - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/DoubleConstantRecord.cs b/src/IKVM.ByteCode/Parsing/DoubleConstantRecord.cs deleted file mode 100644 index 420e4564eb..0000000000 --- a/src/IKVM.ByteCode/Parsing/DoubleConstantRecord.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; - -using IKVM.ByteCode.Buffers; - -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record DoubleConstantRecord(double Value) : ConstantRecord - { - - /// - /// Parses a Double constant in the constant pool. - /// - /// - /// - public static bool TryReadDoubleConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 1; - - if (reader.TryReadU4(out uint a) == false) - return false; - if (reader.TryReadU4(out uint b) == false) - return false; - -#if NETFRAMEWORK || NETCOREAPP3_1 - var v = RawBitConverter.UInt64BitsToDouble(((ulong)a << 32) | b); -#else - var v = BitConverter.UInt64BitsToDouble(((ulong)a << 32) | b); -#endif - - constant = new DoubleConstantRecord(v); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/DoubleVariableInfoRecord.cs b/src/IKVM.ByteCode/Parsing/DoubleVariableInfoRecord.cs deleted file mode 100644 index 3363bcad60..0000000000 --- a/src/IKVM.ByteCode/Parsing/DoubleVariableInfoRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record DoubleVariableInfoRecord : VerificationTypeInfoRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = new DoubleVariableInfoRecord(); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/DynamicConstantRecord.cs b/src/IKVM.ByteCode/Parsing/DynamicConstantRecord.cs deleted file mode 100644 index c5e003142e..0000000000 --- a/src/IKVM.ByteCode/Parsing/DynamicConstantRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record DynamicConstantRecord(ushort BootstrapMethodAttributeIndex, ushort NameAndTypeIndex) : ConstantRecord - { - - /// - /// Parses a Dynamic constant in the constant pool. - /// - /// - /// - /// - public static bool TryReadDynamicConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skipIndex) - { - constant = null; - skipIndex = 0; - - if (reader.TryReadU2(out ushort bootstrapMethodAttrIndex) == false) - return false; - if (reader.TryReadU2(out ushort nameAndTypeIndex) == false) - return false; - - constant = new DynamicConstantRecord(bootstrapMethodAttrIndex, nameAndTypeIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ElementValueAnnotationValueRecord.cs b/src/IKVM.ByteCode/Parsing/ElementValueAnnotationValueRecord.cs deleted file mode 100644 index 229f263559..0000000000 --- a/src/IKVM.ByteCode/Parsing/ElementValueAnnotationValueRecord.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ElementValueAnnotationValueRecord(AnnotationRecord Annotation) : ElementValueValueRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out ElementValueValueRecord value) - { - value = null; - - if (AnnotationRecord.TryReadAnnotation(ref reader, out var annotation) == false) - return false; - - value = new ElementValueAnnotationValueRecord(annotation); - return true; - } - - public override int GetSize() - { - var size = 0; - size += Annotation.GetSize(); - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (Annotation.TryWrite(ref writer) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ElementValueArrayValueRecord.cs b/src/IKVM.ByteCode/Parsing/ElementValueArrayValueRecord.cs deleted file mode 100644 index d1c6b664c9..0000000000 --- a/src/IKVM.ByteCode/Parsing/ElementValueArrayValueRecord.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ElementValueArrayValueRecord(ElementValueRecord[] Values) : ElementValueValueRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out ElementValueValueRecord value) - { - value = null; - - if (reader.TryReadU2(out ushort length) == false) - return false; - - var values = new ElementValueRecord[length]; - for (int i = 0; i < length; i++) - { - if (ElementValueRecord.TryRead(ref reader, out var j) == false) - return false; - - values[i] = j; - } - - value = new ElementValueArrayValueRecord(values); - return true; - } - - public override int GetSize() - { - var size = 0; - size += sizeof(ushort); - - foreach (var value in Values) - size += value.GetSize(); - - return size; - } - - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2((ushort)Values.Length) == false) - return false; - - foreach (var value in Values) - if (value.TryWrite(ref writer) == false) - return false; - - return true; - } - - } - - -} diff --git a/src/IKVM.ByteCode/Parsing/ElementValueClassValueRecord.cs b/src/IKVM.ByteCode/Parsing/ElementValueClassValueRecord.cs deleted file mode 100644 index 8267ae8a46..0000000000 --- a/src/IKVM.ByteCode/Parsing/ElementValueClassValueRecord.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ElementValueClassValueRecord(ushort ClassIndex) : ElementValueValueRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out ElementValueValueRecord value) - { - value = null; - - if (reader.TryReadU2(out ushort classInfoIndex) == false) - return false; - - value = new ElementValueClassValueRecord(classInfoIndex); - return true; - } - - public override int GetSize() - { - var size = 0; - size += sizeof(ushort); - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(ClassIndex) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/ElementValueConstantValueRecord.cs b/src/IKVM.ByteCode/Parsing/ElementValueConstantValueRecord.cs deleted file mode 100644 index 6d791c6d00..0000000000 --- a/src/IKVM.ByteCode/Parsing/ElementValueConstantValueRecord.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ElementValueConstantValueRecord(ushort Index) : ElementValueValueRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out ElementValueValueRecord value) - { - value = null; - - if (reader.TryReadU2(out ushort index) == false) - return false; - - value = new ElementValueConstantValueRecord(index); - return true; - } - - public override int GetSize() - { - var size = 0; - size += sizeof(ushort); - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(Index) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ElementValueEnumConstantValueRecord.cs b/src/IKVM.ByteCode/Parsing/ElementValueEnumConstantValueRecord.cs deleted file mode 100644 index 15b3717f24..0000000000 --- a/src/IKVM.ByteCode/Parsing/ElementValueEnumConstantValueRecord.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ElementValueEnumConstantValueRecord(ushort TypeNameIndex, ushort ConstantNameIndex) : ElementValueValueRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out ElementValueValueRecord value) - { - value = null; - - if (reader.TryReadU2(out ushort typeNameIndex) == false) - return false; - if (reader.TryReadU2(out ushort constantNameIndex) == false) - return false; - - value = new ElementValueEnumConstantValueRecord(typeNameIndex, constantNameIndex); - return true; - } - - public override int GetSize() - { - var size = 0; - size += sizeof(ushort); - size += sizeof(ushort); - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(TypeNameIndex) == false) - return false; - if (writer.TryWriteU2(ConstantNameIndex) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ElementValuePairRecord.cs b/src/IKVM.ByteCode/Parsing/ElementValuePairRecord.cs deleted file mode 100644 index f94ed0427a..0000000000 --- a/src/IKVM.ByteCode/Parsing/ElementValuePairRecord.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct ElementValuePairRecord(ushort NameIndex, ElementValueRecord Value) - { - - public static bool TryRead(ref ClassFormatReader reader, out ElementValuePairRecord record) - { - record = default; - - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - if (ElementValueRecord.TryRead(ref reader, out var elementValue) == false) - return false; - - record = new ElementValuePairRecord(nameIndex, elementValue); - return true; - } - - public int GetSize() - { - var size = 0; - size += sizeof(ushort); - size += Value.GetSize(); - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(NameIndex) == false) - return false; - if (Value.TryWrite(ref writer) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ElementValueRecord.cs b/src/IKVM.ByteCode/Parsing/ElementValueRecord.cs deleted file mode 100644 index 4014a0f920..0000000000 --- a/src/IKVM.ByteCode/Parsing/ElementValueRecord.cs +++ /dev/null @@ -1,64 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct ElementValueRecord(ElementValueTag Tag, ElementValueValueRecord Value) - { - - public static bool TryRead(ref ClassFormatReader reader, out ElementValueRecord record) - { - record = default; - - if (reader.TryReadU1(out byte tag) == false) - return false; - if (TryReadValue(ref reader, (ElementValueTag)tag, out var value) == false) - return false; - - record = new ElementValueRecord((ElementValueTag)tag, value); - return true; - } - - static bool TryReadValue(ref ClassFormatReader reader, ElementValueTag tag, out ElementValueValueRecord value) => tag switch - { - ElementValueTag.Byte => ElementValueConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.Char => ElementValueConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.Double => ElementValueConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.Float => ElementValueConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.Integer => ElementValueConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.Long => ElementValueConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.Short => ElementValueConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.Boolean => ElementValueConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.String => ElementValueConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.Enum => ElementValueEnumConstantValueRecord.TryRead(ref reader, out value), - ElementValueTag.Class => ElementValueClassValueRecord.TryRead(ref reader, out value), - ElementValueTag.Annotation => ElementValueAnnotationValueRecord.TryRead(ref reader, out value), - ElementValueTag.Array => ElementValueArrayValueRecord.TryRead(ref reader, out value), - _ => throw new ByteCodeException($"Invalid element value tag: '{(char)tag}'."), - }; - - public int GetSize() - { - var size = 0; - size += sizeof(byte); - size += Value.GetSize(); - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU1((byte)Tag) == false) - return false; - - if (Value.TryWrite(ref writer) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ElementValueTag.cs b/src/IKVM.ByteCode/Parsing/ElementValueTag.cs deleted file mode 100644 index 76e388b5e6..0000000000 --- a/src/IKVM.ByteCode/Parsing/ElementValueTag.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal enum ElementValueTag : byte - { - - Byte = (byte)'B', - Char = (byte)'C', - Double = (byte)'D', - Float = (byte)'F', - Integer = (byte)'I', - Long = (byte)'J', - Short = (byte)'S', - Boolean = (byte)'Z', - String = (byte)'s', - Enum = (byte)'e', - Class = (byte)'c', - Annotation = (byte)'@', - Array = (byte)'[', - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ElementValueValueRecord.cs b/src/IKVM.ByteCode/Parsing/ElementValueValueRecord.cs deleted file mode 100644 index e1d51b57c1..0000000000 --- a/src/IKVM.ByteCode/Parsing/ElementValueValueRecord.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal abstract record ElementValueValueRecord - { - - /// - /// Gets the size of the record if written. - /// - /// - public abstract int GetSize(); - - /// - /// Attempts to write the record to the . - /// - /// - /// - public abstract bool TryWrite(ref ClassFormatWriter writer); - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/EnclosingMethodAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/EnclosingMethodAttributeRecord.cs deleted file mode 100644 index 0d19202ea7..0000000000 --- a/src/IKVM.ByteCode/Parsing/EnclosingMethodAttributeRecord.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record EnclosingMethodAttributeRecord(ushort ClassIndex, ushort MethodIndex) : AttributeRecord - { - - public static bool TryReadEnclosingMethodAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort classIndex) == false) - return false; - if (reader.TryReadU2(out ushort methodIndex) == false) - return false; - - attribute = new EnclosingMethodAttributeRecord(classIndex, methodIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ExceptionHandlerRecord.cs b/src/IKVM.ByteCode/Parsing/ExceptionHandlerRecord.cs deleted file mode 100644 index e17b4ef97f..0000000000 --- a/src/IKVM.ByteCode/Parsing/ExceptionHandlerRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct ExceptionHandlerRecord(ushort StartOffset, ushort EndOffset, ushort HandlerOffset, ushort CatchTypeIndex); - -} diff --git a/src/IKVM.ByteCode/Parsing/ExceptionsAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/ExceptionsAttributeRecord.cs deleted file mode 100644 index e000b4f5ec..0000000000 --- a/src/IKVM.ByteCode/Parsing/ExceptionsAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ExceptionsAttributeRecord(ushort[] ExceptionsIndexes) : AttributeRecord - { - - public static bool TryReadExceptionsAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var entries = new ushort[count]; - for (int i = 0; i < count; i++) - { - if (reader.TryReadU2(out ushort index) == false) - return false; - - entries[i] = index; - } - - attribute = new ExceptionsAttributeRecord(entries); - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/FieldRecord.cs b/src/IKVM.ByteCode/Parsing/FieldRecord.cs deleted file mode 100644 index 5471982603..0000000000 --- a/src/IKVM.ByteCode/Parsing/FieldRecord.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct FieldRecord(AccessFlag AccessFlags, ushort NameIndex, ushort DescriptorIndex, AttributeInfoRecord[] Attributes) - { - - /// - /// Parses a field. - /// - /// - /// - public static bool TryRead(ref ClassFormatReader reader, out FieldRecord field) - { - field = default; - - if (reader.TryReadU2(out ushort accessFlags) == false) - return false; - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - if (reader.TryReadU2(out ushort descriptorIndex) == false) - return false; - if (ClassRecord.TryReadAttributes(ref reader, out var attributes) == false) - return false; - - field = new FieldRecord((AccessFlag)accessFlags, nameIndex, descriptorIndex, attributes); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/FieldrefConstantRecord.cs b/src/IKVM.ByteCode/Parsing/FieldrefConstantRecord.cs deleted file mode 100644 index da7a9c03b6..0000000000 --- a/src/IKVM.ByteCode/Parsing/FieldrefConstantRecord.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record FieldrefConstantRecord(ushort ClassIndex, ushort NameAndTypeIndex) : RefConstantRecord(ClassIndex, NameAndTypeIndex) - { - - /// - /// Parses a Fieldref constant in the constant pool. - /// - /// - /// - public static bool TryReadFieldrefConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort classIndex) == false) - return false; - if (reader.TryReadU2(out ushort nameAndTypeIndex) == false) - return false; - - constant = new FieldrefConstantRecord(classIndex, nameAndTypeIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/FloatConstantRecord.cs b/src/IKVM.ByteCode/Parsing/FloatConstantRecord.cs deleted file mode 100644 index 7078cff4ef..0000000000 --- a/src/IKVM.ByteCode/Parsing/FloatConstantRecord.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; - -using IKVM.ByteCode.Buffers; - -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record FloatConstantRecord(float Value) : ConstantRecord - { - - /// - /// Parses a Float constant in the constant pool. - /// - /// - /// - public static bool TryReadFloatConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU4(out uint value) == false) - return false; - -#if NETFRAMEWORK || NETCOREAPP3_1 - var v = RawBitConverter.UInt32BitsToSingle(value); -#else - var v = BitConverter.UInt32BitsToSingle(value); -#endif - - constant = new FloatConstantRecord(v); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/FloatVariableInfoRecord.cs b/src/IKVM.ByteCode/Parsing/FloatVariableInfoRecord.cs deleted file mode 100644 index 538ab9bf7e..0000000000 --- a/src/IKVM.ByteCode/Parsing/FloatVariableInfoRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record FloatVariableInfoRecord : VerificationTypeInfoRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = new FloatVariableInfoRecord(); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/FullStackMapFrameRecord.cs b/src/IKVM.ByteCode/Parsing/FullStackMapFrameRecord.cs deleted file mode 100644 index 0a933c5247..0000000000 --- a/src/IKVM.ByteCode/Parsing/FullStackMapFrameRecord.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record FullStackMapFrameRecord(byte Tag, ushort OffsetDelta, VerificationTypeInfoRecord[] Locals, VerificationTypeInfoRecord[] Stack) : StackMapFrameRecord(Tag) - { - - public static bool TryReadFullStackMapFrame(ref ClassFormatReader reader, byte tag, out StackMapFrameRecord frame) - { - frame = null; - - if (reader.TryReadU2(out ushort offsetDelta) == false) - return false; - - if (reader.TryReadU2(out ushort localsCount) == false) - return false; - - var locals = new VerificationTypeInfoRecord[localsCount]; - for (int i = 0; i < localsCount; i++) - if (VerificationTypeInfoRecord.TryReadVerificationTypeInfo(ref reader, out locals[i]) == false) - return false; - - if (reader.TryReadU2(out ushort stackCount) == false) - return false; - - var stack = new VerificationTypeInfoRecord[stackCount]; - for (int i = 0; i < stackCount; i++) - if (VerificationTypeInfoRecord.TryReadVerificationTypeInfo(ref reader, out stack[i]) == false) - return false; - - frame = new FullStackMapFrameRecord(tag, offsetDelta, locals, stack); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/InnerClassesAttributeItemRecord.cs b/src/IKVM.ByteCode/Parsing/InnerClassesAttributeItemRecord.cs deleted file mode 100644 index 03d245a23e..0000000000 --- a/src/IKVM.ByteCode/Parsing/InnerClassesAttributeItemRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct InnerClassesAttributeItemRecord(ushort InnerClassIndex, ushort OuterClassIndex, ushort InnerNameIndex, AccessFlag InnerClassAccessFlags); - -} diff --git a/src/IKVM.ByteCode/Parsing/InnerClassesAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/InnerClassesAttributeRecord.cs deleted file mode 100644 index eec2f9ee6c..0000000000 --- a/src/IKVM.ByteCode/Parsing/InnerClassesAttributeRecord.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record InnerClassesAttributeRecord(InnerClassesAttributeItemRecord[] Items) : AttributeRecord - { - - public static bool TryReadInnerClassesAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var items = new InnerClassesAttributeItemRecord[count]; - for (int i = 0; i < count; i++) - { - if (reader.TryReadU2(out ushort innerClassInfoIndex) == false) - return false; - if (reader.TryReadU2(out ushort outerClassInfoIndex) == false) - return false; - if (reader.TryReadU2(out ushort innerNameIndex) == false) - return false; - if (reader.TryReadU2(out ushort innerClassAccessFlags) == false) - return false; - - items[i] = new InnerClassesAttributeItemRecord(innerClassInfoIndex, outerClassInfoIndex, innerNameIndex, (AccessFlag)innerClassAccessFlags); - } - - attribute = new InnerClassesAttributeRecord(items); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/IntegerConstantRecord.cs b/src/IKVM.ByteCode/Parsing/IntegerConstantRecord.cs deleted file mode 100644 index 1f07772f39..0000000000 --- a/src/IKVM.ByteCode/Parsing/IntegerConstantRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record IntegerConstantRecord(int Value) : ConstantRecord - { - - /// - /// Parses a Integer constant in the constant pool. - /// - /// - /// - /// - public static bool TryReadIntegerConstant(ref ClassFormatReader reader, out ConstantRecord record, out int skip) - { - record = null; - skip = 0; - - if (reader.TryReadU4(out uint value) == false) - return false; - - var v = unchecked((int)value); - - record = new IntegerConstantRecord(v); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/IntegerVariableInfoRecord.cs b/src/IKVM.ByteCode/Parsing/IntegerVariableInfoRecord.cs deleted file mode 100644 index 978c79e69d..0000000000 --- a/src/IKVM.ByteCode/Parsing/IntegerVariableInfoRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record IntegerVariableInfoRecord : VerificationTypeInfoRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = new IntegerVariableInfoRecord(); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/InterfaceMethodrefConstantRecord.cs b/src/IKVM.ByteCode/Parsing/InterfaceMethodrefConstantRecord.cs deleted file mode 100644 index 8a4f8df66a..0000000000 --- a/src/IKVM.ByteCode/Parsing/InterfaceMethodrefConstantRecord.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record InterfaceMethodrefConstantRecord(ushort ClassIndex, ushort NameAndTypeIndex) : RefConstantRecord(ClassIndex, NameAndTypeIndex) - { - - /// - /// Parses a InterfaceMethodref constant in the constant pool. - /// - /// - /// - public static bool TryReadInterfaceMethodrefConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort classIndex) == false) - return false; - if (reader.TryReadU2(out ushort nameAndTypeIndex) == false) - return false; - - constant = new InterfaceMethodrefConstantRecord(classIndex, nameAndTypeIndex); - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/InterfaceRecord.cs b/src/IKVM.ByteCode/Parsing/InterfaceRecord.cs deleted file mode 100644 index 6044da7dd1..0000000000 --- a/src/IKVM.ByteCode/Parsing/InterfaceRecord.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct InterfaceRecord(ushort ClassIndex) - { - - /// - /// Parses an interface. - /// - /// - /// - public static bool TryRead(ref ClassFormatReader reader, out InterfaceRecord iface) - { - iface = default; - - if (reader.TryReadU2(out ushort classIndex) == false) - return false; - - iface = new InterfaceRecord(classIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/InvokeDynamicConstantRecord.cs b/src/IKVM.ByteCode/Parsing/InvokeDynamicConstantRecord.cs deleted file mode 100644 index fe82591c34..0000000000 --- a/src/IKVM.ByteCode/Parsing/InvokeDynamicConstantRecord.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record InvokeDynamicConstantRecord(ushort BootstrapMethodAttributeIndex, ushort NameAndTypeIndex) : ConstantRecord - { - - /// - /// Parses a InvokeDynamic constant in the constant pool. - /// - /// - /// - public static bool TryReadInvokeDynamicConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort bootstrapMethodAttrIndex) == false) - return false; - if (reader.TryReadU2(out ushort nameAndTypeIndex) == false) - return false; - - constant = new InvokeDynamicConstantRecord(bootstrapMethodAttrIndex, nameAndTypeIndex); - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/LineNumberTableAttributeItemRecord.cs b/src/IKVM.ByteCode/Parsing/LineNumberTableAttributeItemRecord.cs deleted file mode 100644 index cba1871c9f..0000000000 --- a/src/IKVM.ByteCode/Parsing/LineNumberTableAttributeItemRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct LineNumberTableAttributeItemRecord(ushort CodeOffset, ushort LineNumber); - -} diff --git a/src/IKVM.ByteCode/Parsing/LineNumberTableAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/LineNumberTableAttributeRecord.cs deleted file mode 100644 index b4ef48d0c0..0000000000 --- a/src/IKVM.ByteCode/Parsing/LineNumberTableAttributeRecord.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record LineNumberTableAttributeRecord(LineNumberTableAttributeItemRecord[] Items) : AttributeRecord - { - - public static bool TryReadLineNumberTableAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort itemCount) == false) - return false; - - var items = new LineNumberTableAttributeItemRecord[itemCount]; - for (int i = 0; i < itemCount; i++) - { - if (reader.TryReadU2(out ushort codeOffset) == false) - return false; - if (reader.TryReadU2(out ushort lineNumber) == false) - return false; - - items[i] = new LineNumberTableAttributeItemRecord(codeOffset, lineNumber); - } - - attribute = new LineNumberTableAttributeRecord(items); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/LocalVariableTableAttributeItemRecord.cs b/src/IKVM.ByteCode/Parsing/LocalVariableTableAttributeItemRecord.cs deleted file mode 100644 index 38ffc6a6ee..0000000000 --- a/src/IKVM.ByteCode/Parsing/LocalVariableTableAttributeItemRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct LocalVariableTableAttributeItemRecord(ushort CodeOffset, ushort CodeLength, ushort NameIndex, ushort DescriptorIndex, ushort Index); - -} diff --git a/src/IKVM.ByteCode/Parsing/LocalVariableTableAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/LocalVariableTableAttributeRecord.cs deleted file mode 100644 index 3d0ab69e7e..0000000000 --- a/src/IKVM.ByteCode/Parsing/LocalVariableTableAttributeRecord.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record LocalVariableTableAttributeRecord(LocalVariableTableAttributeItemRecord[] Items) : AttributeRecord - { - - public static bool TryReadLocalVariableTableAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort length) == false) - return false; - - var items = new LocalVariableTableAttributeItemRecord[length]; - for (int i = 0; i < length; i++) - { - if (reader.TryReadU2(out ushort codeOffset) == false) - return false; - if (reader.TryReadU2(out ushort codeLength) == false) - return false; - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - if (reader.TryReadU2(out ushort descriptorIndex) == false) - return false; - if (reader.TryReadU2(out ushort index) == false) - return false; - - items[i] = new LocalVariableTableAttributeItemRecord(codeOffset, codeLength, nameIndex, descriptorIndex, index); - } - - attribute = new LocalVariableTableAttributeRecord(items); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/LocalVariableTypeTableAttributeItemRecord.cs b/src/IKVM.ByteCode/Parsing/LocalVariableTypeTableAttributeItemRecord.cs deleted file mode 100644 index 7acdf2c994..0000000000 --- a/src/IKVM.ByteCode/Parsing/LocalVariableTypeTableAttributeItemRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct LocalVariableTypeTableAttributeItemRecord(ushort CodeOffset, ushort CodeLength, ushort NameIndex, ushort SignatureIndex, ushort Index); - -} diff --git a/src/IKVM.ByteCode/Parsing/LocalVariableTypeTableAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/LocalVariableTypeTableAttributeRecord.cs deleted file mode 100644 index c1c8108f7e..0000000000 --- a/src/IKVM.ByteCode/Parsing/LocalVariableTypeTableAttributeRecord.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record LocalVariableTypeTableAttributeRecord(LocalVariableTypeTableAttributeItemRecord[] Items) : AttributeRecord - { - - public static bool TryReadLocalVariableTypeTableAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort length) == false) - return false; - - var items = new LocalVariableTypeTableAttributeItemRecord[length]; - for (int i = 0; i < length; i++) - { - if (reader.TryReadU2(out ushort codeOffset) == false) - return false; - if (reader.TryReadU2(out ushort codeLength) == false) - return false; - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - if (reader.TryReadU2(out ushort signatureIndex) == false) - return false; - if (reader.TryReadU2(out ushort index) == false) - return false; - - items[i] = new LocalVariableTypeTableAttributeItemRecord(codeOffset, codeLength, nameIndex, signatureIndex, index); - } - - attribute = new LocalVariableTypeTableAttributeRecord(items); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/LongConstantRecord.cs b/src/IKVM.ByteCode/Parsing/LongConstantRecord.cs deleted file mode 100644 index f20548c10b..0000000000 --- a/src/IKVM.ByteCode/Parsing/LongConstantRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record LongConstantRecord(long Value) : ConstantRecord - { - - /// - /// Parses a Long constant in the constant pool. - /// - /// - /// - /// - public static bool TryReadLongConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 1; - - if (reader.TryReadU4(out uint a) == false) - return false; - if (reader.TryReadU4(out uint b) == false) - return false; - - constant = new LongConstantRecord((long)(((ulong)a << 32) | b)); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/LongVariableInfoRecord.cs b/src/IKVM.ByteCode/Parsing/LongVariableInfoRecord.cs deleted file mode 100644 index a37b596569..0000000000 --- a/src/IKVM.ByteCode/Parsing/LongVariableInfoRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record LongVariableInfoRecord : VerificationTypeInfoRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = new LongVariableInfoRecord(); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/MethodHandleConstantRecord.cs b/src/IKVM.ByteCode/Parsing/MethodHandleConstantRecord.cs deleted file mode 100644 index 43e73a6ec3..0000000000 --- a/src/IKVM.ByteCode/Parsing/MethodHandleConstantRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record MethodHandleConstantRecord(ReferenceKind Kind, ushort Index) : ConstantRecord - { - - /// - /// Parses a MethodHandle constant in the constant pool. - /// - /// - /// - /// - public static bool TryReadMethodHandleConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU1(out byte kind) == false) - return false; - if (reader.TryReadU2(out ushort index) == false) - return false; - - constant = new MethodHandleConstantRecord((ReferenceKind)kind, index); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/MethodParametersAttributeParameterRecord.cs b/src/IKVM.ByteCode/Parsing/MethodParametersAttributeParameterRecord.cs deleted file mode 100644 index 508b687cdd..0000000000 --- a/src/IKVM.ByteCode/Parsing/MethodParametersAttributeParameterRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct MethodParametersAttributeParameterRecord(ushort NameIndex, AccessFlag AccessFlags); - -} diff --git a/src/IKVM.ByteCode/Parsing/MethodParametersAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/MethodParametersAttributeRecord.cs deleted file mode 100644 index 15e006ddef..0000000000 --- a/src/IKVM.ByteCode/Parsing/MethodParametersAttributeRecord.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record MethodParametersAttributeRecord(MethodParametersAttributeParameterRecord[] Parameters) : AttributeRecord - { - - public static bool TryReadMethodParametersAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU1(out byte count) == false) - return false; - - var arguments = new MethodParametersAttributeParameterRecord[count]; - for (int i = 0; i < count; i++) - { - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - if (reader.TryReadU2(out ushort accessFlags) == false) - return false; - - arguments[i] = new MethodParametersAttributeParameterRecord(nameIndex, (AccessFlag)accessFlags); - } - - attribute = new MethodParametersAttributeRecord(arguments); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/MethodRecord.cs b/src/IKVM.ByteCode/Parsing/MethodRecord.cs deleted file mode 100644 index 96bdb9d3b5..0000000000 --- a/src/IKVM.ByteCode/Parsing/MethodRecord.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct MethodRecord(AccessFlag AccessFlags, ushort NameIndex, ushort DescriptorIndex, AttributeInfoRecord[] Attributes) - { - - /// - /// Parses a method. - /// - /// - /// - public static bool TryRead(ref ClassFormatReader reader, out MethodRecord method) - { - method = default; - - if (reader.TryReadU2(out ushort accessFlags) == false) - return false; - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - if (reader.TryReadU2(out ushort descriptorIndex) == false) - return false; - if (ClassRecord.TryReadAttributes(ref reader, out var attributes) == false) - return false; - - method = new MethodRecord((AccessFlag)accessFlags, nameIndex, descriptorIndex, attributes); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/MethodTypeConstantRecord.cs b/src/IKVM.ByteCode/Parsing/MethodTypeConstantRecord.cs deleted file mode 100644 index c8f2e38cc3..0000000000 --- a/src/IKVM.ByteCode/Parsing/MethodTypeConstantRecord.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record MethodTypeConstantRecord(ushort DescriptorIndex) : ConstantRecord - { - - /// - /// Parses a MethodType constant in the constant pool. - /// - /// - /// - /// - public static bool TryReadMethodTypeConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort descriptorIndex) == false) - return false; - - constant = new MethodTypeConstantRecord(descriptorIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/MethodrefConstantRecord.cs b/src/IKVM.ByteCode/Parsing/MethodrefConstantRecord.cs deleted file mode 100644 index 41d1e08d5c..0000000000 --- a/src/IKVM.ByteCode/Parsing/MethodrefConstantRecord.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record MethodrefConstantRecord(ushort ClassIndex, ushort NameAndTypeIndex) : RefConstantRecord(ClassIndex, NameAndTypeIndex) - { - - /// - /// Parses a Methodref constant in the constant pool. - /// - /// - /// - public static bool TryReadMethodrefConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort classIndex) == false) - return false; - if (reader.TryReadU2(out ushort nameAndTypeIndex) == false) - return false; - - constant = new MethodrefConstantRecord(classIndex, nameAndTypeIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ModuleAttributeExportsRecord.cs b/src/IKVM.ByteCode/Parsing/ModuleAttributeExportsRecord.cs deleted file mode 100644 index 33f3803fd0..0000000000 --- a/src/IKVM.ByteCode/Parsing/ModuleAttributeExportsRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct ModuleAttributeExportsRecord(ushort Index, ModuleExportsFlag Flags, ushort[] Modules); - -} diff --git a/src/IKVM.ByteCode/Parsing/ModuleAttributeOpensRecord.cs b/src/IKVM.ByteCode/Parsing/ModuleAttributeOpensRecord.cs deleted file mode 100644 index 0bafd0d9cf..0000000000 --- a/src/IKVM.ByteCode/Parsing/ModuleAttributeOpensRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct ModuleAttributeOpensRecord(ushort Index, ModuleOpensFlag Flags, ushort[] Modules); - -} diff --git a/src/IKVM.ByteCode/Parsing/ModuleAttributeProvidesRecord.cs b/src/IKVM.ByteCode/Parsing/ModuleAttributeProvidesRecord.cs deleted file mode 100644 index b7bd3adb70..0000000000 --- a/src/IKVM.ByteCode/Parsing/ModuleAttributeProvidesRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct ModuleAttributeProvidesRecord(ushort Index, ushort[] Modules); - -} diff --git a/src/IKVM.ByteCode/Parsing/ModuleAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/ModuleAttributeRecord.cs deleted file mode 100644 index 30689d1b84..0000000000 --- a/src/IKVM.ByteCode/Parsing/ModuleAttributeRecord.cs +++ /dev/null @@ -1,128 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ModuleAttributeRecord(ushort NameIndex, ModuleFlag Flags, ushort VersionIndex, ModuleAttributeRequiresRecord[] Requires, ModuleAttributeExportsRecord[] Exports, ModuleAttributeOpensRecord[] Opens, ushort[] Uses, ModuleAttributeProvidesRecord[] Provides) : AttributeRecord - { - - public static bool TryReadModuleAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort moduleNameIndex) == false) - return false; - if (reader.TryReadU2(out ushort moduleFlags) == false) - return false; - if (reader.TryReadU2(out ushort moduleVersionIndex) == false) - return false; - - if (reader.TryReadU2(out ushort requiresCount) == false) - return false; - - var requires = new ModuleAttributeRequiresRecord[requiresCount]; - for (int i = 0; i < requiresCount; i++) - { - if (reader.TryReadU2(out ushort requiresIndex) == false) - return false; - if (reader.TryReadU2(out ushort requiresFlags) == false) - return false; - if (reader.TryReadU2(out ushort requiresVersionIndex) == false) - return false; - - requires[i] = new ModuleAttributeRequiresRecord(requiresIndex, (ModuleRequiresFlag)requiresFlags, requiresVersionIndex); - } - - if (reader.TryReadU2(out ushort exportsCount) == false) - return false; - - var exports = new ModuleAttributeExportsRecord[exportsCount]; - for (int i = 0; i < exportsCount; i++) - { - if (reader.TryReadU2(out ushort exportsIndex) == false) - return false; - if (reader.TryReadU2(out ushort exportsFlags) == false) - return false; - - if (reader.TryReadU2(out ushort exportsModuleCount) == false) - return false; - - var exportsModules = new ushort[exportsModuleCount]; - for (int j = 0; j < exportsModuleCount; j++) - { - if (reader.TryReadU2(out ushort exportsToModuleIndex) == false) - return false; - - exportsModules[j] = exportsToModuleIndex; - } - - exports[i] = new ModuleAttributeExportsRecord(exportsIndex, (ModuleExportsFlag)exportsFlags, exportsModules); - } - - if (reader.TryReadU2(out ushort opensCount) == false) - return false; - - var opens = new ModuleAttributeOpensRecord[opensCount]; - for (int i = 0; i < opensCount; i++) - { - if (reader.TryReadU2(out ushort opensIndex) == false) - return false; - if (reader.TryReadU2(out ushort opensFlags) == false) - return false; - - if (reader.TryReadU2(out ushort opensModulesCount) == false) - return false; - - var opensModules = new ushort[opensModulesCount]; - for (int j = 0; j < opensModulesCount; j++) - { - if (reader.TryReadU2(out ushort opensModuleIndex) == false) - return false; - - opensModules[j] = opensModuleIndex; - } - - opens[i] = new ModuleAttributeOpensRecord(opensIndex, (ModuleOpensFlag)opensFlags, opensModules); - } - - if (reader.TryReadU2(out ushort usesCount) == false) - return false; - - var uses = new ushort[usesCount]; - for (int i = 0; i < usesCount; i++) - { - if (reader.TryReadU2(out ushort usesIndex) == false) - return false; - - uses[i] = usesIndex; - } - - if (reader.TryReadU2(out ushort providesCount) == false) - return false; - - var provides = new ModuleAttributeProvidesRecord[providesCount]; - for (int i = 0; i < providesCount; i++) - { - if (reader.TryReadU2(out ushort providesIndex) == false) - return false; - - if (reader.TryReadU2(out ushort providesModulesCount) == false) - return false; - - var providesModules = new ushort[providesModulesCount]; - for (int j = 0; j < providesModulesCount; j++) - { - if (reader.TryReadU2(out ushort providesModuleIndex) == false) - return false; - - providesModules[j] = providesModuleIndex; - } - - provides[i] = new ModuleAttributeProvidesRecord(providesIndex, providesModules); - } - - attribute = new ModuleAttributeRecord(moduleNameIndex, (ModuleFlag)moduleFlags, moduleVersionIndex, requires, exports, opens, uses, provides); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ModuleAttributeRequiresRecord.cs b/src/IKVM.ByteCode/Parsing/ModuleAttributeRequiresRecord.cs deleted file mode 100644 index 5aa439ad2b..0000000000 --- a/src/IKVM.ByteCode/Parsing/ModuleAttributeRequiresRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct ModuleAttributeRequiresRecord(ushort Index, ModuleRequiresFlag Flag, ushort VersionIndex); - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/ModuleConstantRecord.cs b/src/IKVM.ByteCode/Parsing/ModuleConstantRecord.cs deleted file mode 100644 index 2a1651c5c3..0000000000 --- a/src/IKVM.ByteCode/Parsing/ModuleConstantRecord.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ModuleConstantRecord(ushort NameIndex) : ConstantRecord - { - - /// - /// Parses a Module constant in the constant pool. - /// - /// - /// - /// - public static bool TryReadModuleConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - - constant = new ModuleConstantRecord(nameIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ModuleMainClassAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/ModuleMainClassAttributeRecord.cs deleted file mode 100644 index 068ab4f8e9..0000000000 --- a/src/IKVM.ByteCode/Parsing/ModuleMainClassAttributeRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ModuleMainClassAttributeRecord(ushort MainClassIndex) : AttributeRecord - { - - public static bool TryReadModuleMainClassAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort mainClassIndex) == false) - return false; - - attribute = new ModuleMainClassAttributeRecord(mainClassIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ModulePackagesAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/ModulePackagesAttributeRecord.cs deleted file mode 100644 index 14ccf63703..0000000000 --- a/src/IKVM.ByteCode/Parsing/ModulePackagesAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ModulePackagesAttributeRecord(ushort[] Packages) : AttributeRecord - { - - public static bool TryReadModulePackagesAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var packages = new ushort[count]; - for (int i = 0; i < count; i++) - { - if (reader.TryReadU2(out ushort packageIndex) == false) - return false; - - packages[i] = packageIndex; - } - - attribute = new ModulePackagesAttributeRecord(packages); - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/NameAndTypeConstantRecord.cs b/src/IKVM.ByteCode/Parsing/NameAndTypeConstantRecord.cs deleted file mode 100644 index 4a591055c1..0000000000 --- a/src/IKVM.ByteCode/Parsing/NameAndTypeConstantRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record NameAndTypeConstantRecord(ushort NameIndex, ushort DescriptorIndex) : ConstantRecord - { - - /// - /// Parses a NameAndType constant in the constant pool. - /// - /// - /// - /// - public static bool TryReadNameAndTypeConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - if (reader.TryReadU2(out ushort descriptorIndex) == false) - return false; - - constant = new NameAndTypeConstantRecord(nameIndex, descriptorIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/NestHostAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/NestHostAttributeRecord.cs deleted file mode 100644 index ff62be73c7..0000000000 --- a/src/IKVM.ByteCode/Parsing/NestHostAttributeRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record NestHostAttributeRecord(ushort HostClassIndex) : AttributeRecord - { - - public static bool TryReadNestHostAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort hostClassIndex) == false) - return false; - - attribute = new NestHostAttributeRecord(hostClassIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/NestMembersAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/NestMembersAttributeRecord.cs deleted file mode 100644 index b004fa52ad..0000000000 --- a/src/IKVM.ByteCode/Parsing/NestMembersAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record NestMembersAttributeRecord(ushort[] ClassIndexes) : AttributeRecord - { - - public static bool TryReadNestMembersAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var classes = new ushort[count]; - for (int i = 0; i < count; i++) - { - if (reader.TryReadU2(out ushort classIndex) == false) - return false; - - classes[i] = classIndex; - } - - attribute = new NestMembersAttributeRecord(classes); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/NullVariableInfoRecord.cs b/src/IKVM.ByteCode/Parsing/NullVariableInfoRecord.cs deleted file mode 100644 index 00c3b00c03..0000000000 --- a/src/IKVM.ByteCode/Parsing/NullVariableInfoRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record NullVariableInfoRecord : VerificationTypeInfoRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = new NullVariableInfoRecord(); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ObjectVariableInfoRecord.cs b/src/IKVM.ByteCode/Parsing/ObjectVariableInfoRecord.cs deleted file mode 100644 index e8d5667ea7..0000000000 --- a/src/IKVM.ByteCode/Parsing/ObjectVariableInfoRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record ObjectVariableInfoRecord(ushort ClassIndex) : VerificationTypeInfoRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = null; - - if (reader.TryReadU2(out ushort classIndex) == false) - return false; - - record = new ObjectVariableInfoRecord(classIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/PackageConstantRecord.cs b/src/IKVM.ByteCode/Parsing/PackageConstantRecord.cs deleted file mode 100644 index e98d5f2d75..0000000000 --- a/src/IKVM.ByteCode/Parsing/PackageConstantRecord.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record PackageConstantRecord(ushort NameIndex) : ConstantRecord - { - - /// - /// Parses a Package constant in the constant pool. - /// - /// - /// - /// - public static bool TryReadPackageConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - - constant = new PackageConstantRecord(nameIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/ParameterAnnotationRecord.cs b/src/IKVM.ByteCode/Parsing/ParameterAnnotationRecord.cs deleted file mode 100644 index 6157f2bcde..0000000000 --- a/src/IKVM.ByteCode/Parsing/ParameterAnnotationRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct ParameterAnnotationRecord(AnnotationRecord[] Annotations) - { - - public static bool TryReadParameterAnnotation(ref ClassFormatReader reader, out ParameterAnnotationRecord record) - { - record = default; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var annotations = new AnnotationRecord[count]; - for (int i = 0; i < count; i++) - { - if (AnnotationRecord.TryReadAnnotation(ref reader, out var annotation) == false) - return false; - - annotations[i] = annotation; - } - - record = new ParameterAnnotationRecord(annotations); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/PermittedSubclassesAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/PermittedSubclassesAttributeRecord.cs deleted file mode 100644 index b1bd98046d..0000000000 --- a/src/IKVM.ByteCode/Parsing/PermittedSubclassesAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record PermittedSubclassesAttributeRecord(ushort[] ClassIndexes) : AttributeRecord - { - - public static bool TryReadPermittedSubclassesAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var classes = new ushort[count]; - for (int i = 0; i < count; i++) - { - if (reader.TryReadU2(out ushort classIndex) == false) - return false; - - classes[i] = classIndex; - } - - attribute = new PermittedSubclassesAttributeRecord(classes); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/RecordAttributeComponentRecord.cs b/src/IKVM.ByteCode/Parsing/RecordAttributeComponentRecord.cs deleted file mode 100644 index 1fb3ff2162..0000000000 --- a/src/IKVM.ByteCode/Parsing/RecordAttributeComponentRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct RecordAttributeComponentRecord(ushort NameIndex, ushort DescriptorIndex, AttributeInfoRecord[] Attributes); - -} diff --git a/src/IKVM.ByteCode/Parsing/RecordAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/RecordAttributeRecord.cs deleted file mode 100644 index 192bc8ae94..0000000000 --- a/src/IKVM.ByteCode/Parsing/RecordAttributeRecord.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record RecordAttributeRecord(RecordAttributeComponentRecord[] Components) : AttributeRecord - { - - public static bool TryReadRecordAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort componentsCount) == false) - return false; - - var components = new RecordAttributeComponentRecord[componentsCount]; - for (int i = 0; i < componentsCount; i++) - { - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - if (reader.TryReadU2(out ushort descriptorIndex) == false) - return false; - if (ClassRecord.TryReadAttributes(ref reader, out var attributes) == false) - return false; - - components[i] = new RecordAttributeComponentRecord(nameIndex, descriptorIndex, attributes); - } - - attribute = new RecordAttributeRecord(components); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/RefConstantRecord.cs b/src/IKVM.ByteCode/Parsing/RefConstantRecord.cs deleted file mode 100644 index 1df9453358..0000000000 --- a/src/IKVM.ByteCode/Parsing/RefConstantRecord.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal abstract record RefConstantRecord(ushort ClassIndex, ushort NameAndTypeIndex) : - ConstantRecord - { - - - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/RuntimeInvisibleAnnotationsAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/RuntimeInvisibleAnnotationsAttributeRecord.cs deleted file mode 100644 index 7354beb0f1..0000000000 --- a/src/IKVM.ByteCode/Parsing/RuntimeInvisibleAnnotationsAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record RuntimeInvisibleAnnotationsAttributeRecord(AnnotationRecord[] Annotations) : AttributeRecord - { - - public static bool TryReadRuntimeInvisibleAnnotationsAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var items = new AnnotationRecord[count]; - for (int i = 0; i < count; i++) - { - if (AnnotationRecord.TryReadAnnotation(ref reader, out var annotation) == false) - return false; - - items[i] = annotation; - } - - attribute = new RuntimeInvisibleAnnotationsAttributeRecord(items); - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/RuntimeInvisibleParameterAnnotationsAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/RuntimeInvisibleParameterAnnotationsAttributeRecord.cs deleted file mode 100644 index 77cac86d7e..0000000000 --- a/src/IKVM.ByteCode/Parsing/RuntimeInvisibleParameterAnnotationsAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record RuntimeInvisibleParameterAnnotationsAttributeRecord(ParameterAnnotationRecord[] Parameters) : AttributeRecord - { - - public static bool TryReadRuntimeInvisibleParameterAnnotationsAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU1(out byte count) == false) - return false; - - var parameters = new ParameterAnnotationRecord[count]; - for (int i = 0; i < count; i++) - { - if (ParameterAnnotationRecord.TryReadParameterAnnotation(ref reader, out var parameter) == false) - return false; - - parameters[i] = parameter; - } - - attribute = new RuntimeInvisibleParameterAnnotationsAttributeRecord(parameters); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/RuntimeInvisibleTypeAnnotationsAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/RuntimeInvisibleTypeAnnotationsAttributeRecord.cs deleted file mode 100644 index 81cc47298f..0000000000 --- a/src/IKVM.ByteCode/Parsing/RuntimeInvisibleTypeAnnotationsAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record RuntimeInvisibleTypeAnnotationsAttributeRecord(TypeAnnotationRecord[] Annotations) : AttributeRecord - { - - public static bool TryReadRuntimeInvisibleTypeAnnotationsAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var annotations = new TypeAnnotationRecord[count]; - for (int i = 0; i < count; i++) - { - if (TypeAnnotationRecord.TryReadTypeAnnotation(ref reader, out var annotation) == false) - return false; - - annotations[i] = annotation; - } - - attribute = new RuntimeInvisibleTypeAnnotationsAttributeRecord(annotations); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/RuntimeVisibleAnnotationsAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/RuntimeVisibleAnnotationsAttributeRecord.cs deleted file mode 100644 index 7fb6dd7793..0000000000 --- a/src/IKVM.ByteCode/Parsing/RuntimeVisibleAnnotationsAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record RuntimeVisibleAnnotationsAttributeRecord(AnnotationRecord[] Annotations) : AttributeRecord - { - - public static bool TryReadRuntimeVisibleAnnotationsAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var items = new AnnotationRecord[count]; - for (int i = 0; i < count; i++) - { - if (AnnotationRecord.TryReadAnnotation(ref reader, out var annotation) == false) - return false; - - items[i] = annotation; - } - - attribute = new RuntimeVisibleAnnotationsAttributeRecord(items); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/RuntimeVisibleParameterAnnotationsAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/RuntimeVisibleParameterAnnotationsAttributeRecord.cs deleted file mode 100644 index 5990ba25da..0000000000 --- a/src/IKVM.ByteCode/Parsing/RuntimeVisibleParameterAnnotationsAttributeRecord.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record RuntimeVisibleParameterAnnotationsAttributeRecord(ParameterAnnotationRecord[] Parameters) : AttributeRecord - { - - public static bool TryReadRuntimeVisibleParameterAnnotationsAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU1(out byte count) == false) - return false; - - var items = new ParameterAnnotationRecord[count]; - for (int i = 0; i < count; i++) - { - if (ParameterAnnotationRecord.TryReadParameterAnnotation(ref reader, out var parameter) == false) - return false; - - items[i] = parameter; - } - - attribute = new RuntimeVisibleParameterAnnotationsAttributeRecord(items); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/RuntimeVisibleTypeAnnotationsAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/RuntimeVisibleTypeAnnotationsAttributeRecord.cs deleted file mode 100644 index fde2094726..0000000000 --- a/src/IKVM.ByteCode/Parsing/RuntimeVisibleTypeAnnotationsAttributeRecord.cs +++ /dev/null @@ -1,61 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record RuntimeVisibleTypeAnnotationsAttributeRecord(TypeAnnotationRecord[] Annotations) : AttributeRecord - { - - public static bool TryReadRuntimeVisibleTypeAnnotationsAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var annotations = new TypeAnnotationRecord[count]; - for (int i = 0; i < count; i++) - { - if (TypeAnnotationRecord.TryReadTypeAnnotation(ref reader, out var annotation) == false) - return false; - - annotations[i] = annotation; - } - - attribute = new RuntimeVisibleTypeAnnotationsAttributeRecord(annotations); - return true; - } - - /// - /// Gets the number of bytes required to write the record. - /// - /// - public int GetSize() - { - var size = 0; - size += sizeof(ushort); - - foreach (var element in Annotations) - size += element.GetSize(); - - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2((ushort)Annotations.Length) == false) - return false; - - foreach (var record in Annotations) - if (record.TryWrite(ref writer) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/SameExtendedStackMapFrameRecord.cs b/src/IKVM.ByteCode/Parsing/SameExtendedStackMapFrameRecord.cs deleted file mode 100644 index 00e8a0f50b..0000000000 --- a/src/IKVM.ByteCode/Parsing/SameExtendedStackMapFrameRecord.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record SameExtendedStackMapFrameRecord(byte Tag, ushort OffsetDelta) : StackMapFrameRecord(Tag) - { - - public static bool TryReadSameExtendedStackMapFrame(ref ClassFormatReader reader, byte tag, out StackMapFrameRecord frame) - { - frame = null; - - if (reader.TryReadU2(out ushort offsetDelta) == false) - return false; - - frame = new SameExtendedStackMapFrameRecord(tag, offsetDelta); - return true; - } - - } - - -} diff --git a/src/IKVM.ByteCode/Parsing/SameLocalsOneExtendedStackMapFrameRecord.cs b/src/IKVM.ByteCode/Parsing/SameLocalsOneExtendedStackMapFrameRecord.cs deleted file mode 100644 index 60009a85b9..0000000000 --- a/src/IKVM.ByteCode/Parsing/SameLocalsOneExtendedStackMapFrameRecord.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record SameLocalsOneExtendedStackMapFrameRecord(byte FrameType, ushort OffsetDelta, VerificationTypeInfoRecord Stack) : StackMapFrameRecord(FrameType) - { - - public static bool TryReadSameLocalsOneStackItemExtendedStackMapFrame(ref ClassFormatReader reader, byte tag, out StackMapFrameRecord frame) - { - frame = null; - - if (reader.TryReadU2(out ushort offsetDelta) == false) - return false; - if (VerificationTypeInfoRecord.TryReadVerificationTypeInfo(ref reader, out var verificationTypeInfo) == false) - return false; - - frame = new SameLocalsOneExtendedStackMapFrameRecord(tag, offsetDelta, verificationTypeInfo); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/SameLocalsOneStackMapFrameRecord.cs b/src/IKVM.ByteCode/Parsing/SameLocalsOneStackMapFrameRecord.cs deleted file mode 100644 index 7ee6b0a890..0000000000 --- a/src/IKVM.ByteCode/Parsing/SameLocalsOneStackMapFrameRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record SameLocalsOneStackMapFrameRecord(byte FrameType, VerificationTypeInfoRecord Stack) : StackMapFrameRecord(FrameType) - { - - public static bool TryReadSameLocalsOneStackItemStackMapFrame(ref ClassFormatReader reader, byte tag, out StackMapFrameRecord frame) - { - frame = null; - - if (VerificationTypeInfoRecord.TryReadVerificationTypeInfo(ref reader, out var verificationTypeInfo) == false) - return false; - - frame = new SameLocalsOneStackMapFrameRecord(tag, verificationTypeInfo); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/SameStackMapFrameRecord.cs b/src/IKVM.ByteCode/Parsing/SameStackMapFrameRecord.cs deleted file mode 100644 index f5e61a2ec7..0000000000 --- a/src/IKVM.ByteCode/Parsing/SameStackMapFrameRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record SameStackMapFrameRecord(byte Tag) : StackMapFrameRecord(Tag) - { - - public static bool TryReadSameStackMapFrame(ref ClassFormatReader reader, byte tag, out StackMapFrameRecord frame) - { - frame = new SameStackMapFrameRecord(tag); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/SignatureAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/SignatureAttributeRecord.cs deleted file mode 100644 index 5416870050..0000000000 --- a/src/IKVM.ByteCode/Parsing/SignatureAttributeRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record SignatureAttributeRecord(ushort SignatureIndex) : AttributeRecord - { - - public static bool TryReadSignatureAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort signatureIndex) == false) - return false; - - attribute = new SignatureAttributeRecord(signatureIndex); - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/SourceDebugExtensionAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/SourceDebugExtensionAttributeRecord.cs deleted file mode 100644 index 34ffa8e832..0000000000 --- a/src/IKVM.ByteCode/Parsing/SourceDebugExtensionAttributeRecord.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Buffers; - -namespace IKVM.ByteCode.Parsing -{ - - internal record SourceDebugExtensionAttributeRecord(byte[] Data) : AttributeRecord - { - - public static bool TryReadSourceDebugExtensionAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadManyU1(reader.Length, out ReadOnlySequence data) == false) - return false; - - var dataBuffer = new byte[data.Length]; - data.CopyTo(dataBuffer); - - attribute = new SourceDebugExtensionAttributeRecord(dataBuffer); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/SourceFileAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/SourceFileAttributeRecord.cs deleted file mode 100644 index 22d3357814..0000000000 --- a/src/IKVM.ByteCode/Parsing/SourceFileAttributeRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record SourceFileAttributeRecord(ushort SourceFileIndex) : AttributeRecord - { - - public static bool TryReadSourceFileAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort sourceFileIndex) == false) - return false; - - attribute = new SourceFileAttributeRecord(sourceFileIndex); - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/StackMapFrameRecord.cs b/src/IKVM.ByteCode/Parsing/StackMapFrameRecord.cs deleted file mode 100644 index dbc5cb6613..0000000000 --- a/src/IKVM.ByteCode/Parsing/StackMapFrameRecord.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal abstract record StackMapFrameRecord(byte FrameType) - { - - public static bool TryRead(ref ClassFormatReader reader, out StackMapFrameRecord frame) - { - frame = null; - - if (reader.TryReadU1(out byte tag) == false) - return false; - - if (TryRead(ref reader, tag, out frame) == false) - return false; - - return true; - } - - public static bool TryRead(ref ClassFormatReader reader, byte tag, out StackMapFrameRecord frame) - { - if (tag >= 0 && tag <= 63) - return SameStackMapFrameRecord.TryReadSameStackMapFrame(ref reader, tag, out frame); - else if (tag >= 64 && tag <= 127) - return SameLocalsOneStackMapFrameRecord.TryReadSameLocalsOneStackItemStackMapFrame(ref reader, tag, out frame); - else if (tag == 247) - return SameLocalsOneExtendedStackMapFrameRecord.TryReadSameLocalsOneStackItemExtendedStackMapFrame(ref reader, tag, out frame); - else if (tag >= 248 && tag <= 250) - return ChopStackMapFrameRecord.TryReadChopStackMapFrame(ref reader, tag, out frame); - else if (tag == 251) - return SameExtendedStackMapFrameRecord.TryReadSameExtendedStackMapFrame(ref reader, tag, out frame); - else if (tag >= 252 && tag <= 254) - return AppendStackMapFrameRecord.TryReadAppendStackMapFrame(ref reader, tag, out frame); - else if (tag == 255) - return FullStackMapFrameRecord.TryReadFullStackMapFrame(ref reader, tag, out frame); - else - throw new ByteCodeException($"Invalid stack map frame tag value: '{tag}'."); - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/StackMapTableAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/StackMapTableAttributeRecord.cs deleted file mode 100644 index 925e394091..0000000000 --- a/src/IKVM.ByteCode/Parsing/StackMapTableAttributeRecord.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record StackMapTableAttributeRecord(StackMapFrameRecord[] Frames) : AttributeRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = null; - - if (reader.TryReadU2(out ushort count) == false) - return false; - - var frames = new StackMapFrameRecord[count]; - for (int i = 0; i < count; i++) - if (StackMapFrameRecord.TryRead(ref reader, out frames[i]) == false) - return false; - - attribute = new StackMapTableAttributeRecord(frames); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/StringConstantRecord.cs b/src/IKVM.ByteCode/Parsing/StringConstantRecord.cs deleted file mode 100644 index 19330f9330..0000000000 --- a/src/IKVM.ByteCode/Parsing/StringConstantRecord.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record StringConstantRecord(ushort ValueIndex) : ConstantRecord - { - - /// - /// Parses a Class constant in the constant pool. - /// - /// - /// - public static bool TryReadStringConstant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort nameIndex) == false) - return false; - - constant = new StringConstantRecord(nameIndex); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/SyntheticAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/SyntheticAttributeRecord.cs deleted file mode 100644 index cc1846404d..0000000000 --- a/src/IKVM.ByteCode/Parsing/SyntheticAttributeRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record SyntheticAttributeRecord : AttributeRecord - { - - public static bool TryReadSyntheticAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - attribute = new SyntheticAttributeRecord(); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/TopVariableInfoRecord.cs b/src/IKVM.ByteCode/Parsing/TopVariableInfoRecord.cs deleted file mode 100644 index bcbecce5c2..0000000000 --- a/src/IKVM.ByteCode/Parsing/TopVariableInfoRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TopVariableInfoRecord : VerificationTypeInfoRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = new TopVariableInfoRecord(); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/TypeAndNameConstantRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAndNameConstantRecord.cs deleted file mode 100644 index c797079829..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAndNameConstantRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAndNameConstantRecord(ushort NameIndex, ushort DescriptorIndex) : ConstantRecord; - -} diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationCatchTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationCatchTargetRecord.cs deleted file mode 100644 index 8b0210b532..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationCatchTargetRecord.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationCatchTargetRecord(ushort ExceptionTableIndex) : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = null; - - if (reader.TryReadU2(out ushort exceptionTableIndex) == false) - return false; - - targetInfo = new TypeAnnotationCatchTargetRecord(exceptionTableIndex); - return true; - } - - /// - /// Gets the size of the record if written. - /// - /// - public override int GetSize() - { - var length = 0; - length += sizeof(ushort); - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(ExceptionTableIndex) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationEmptyTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationEmptyTargetRecord.cs deleted file mode 100644 index 99fe7fcff6..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationEmptyTargetRecord.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationEmptyTargetRecord : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = new TypeAnnotationEmptyTargetRecord(); - return true; - } - - public override int GetSize() - { - return 0; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationFormalParameterTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationFormalParameterTargetRecord.cs deleted file mode 100644 index 90c9e095e6..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationFormalParameterTargetRecord.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationFormalParameterTargetRecord(byte ParameterIndex) : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = null; - - if (reader.TryReadU1(out byte parameterIndex) == false) - return false; - - targetInfo = new TypeAnnotationFormalParameterTargetRecord(parameterIndex); - return true; - } - - public override int GetSize() - { - var length = 0; - length += sizeof(byte); - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU1(ParameterIndex) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationLocalVarTargetItemRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationLocalVarTargetItemRecord.cs deleted file mode 100644 index e76d10bafe..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationLocalVarTargetItemRecord.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct TypeAnnotationLocalVarTargetItemRecord(ushort Offset, ushort Length, ushort Index) - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationLocalVarTargetItemRecord record) - { - record = default; - - if (reader.TryReadU2(out ushort offset) == false) - return false; - - if (reader.TryReadU2(out ushort length) == false) - return false; - - if (reader.TryReadU2(out ushort index) == false) - return false; - - record = new TypeAnnotationLocalVarTargetItemRecord(offset, length, index); - return true; - } - - /// - /// Gets the size of the record if written. - /// - /// - public int GetSize() - { - var length = 0; - length += sizeof(ushort); - length += sizeof(ushort); - length += sizeof(ushort); - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(Offset) == false) - return false; - if (writer.TryWriteU2(Length) == false) - return false; - if (writer.TryWriteU2(Index) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationLocalVarTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationLocalVarTargetRecord.cs deleted file mode 100644 index ef82fc5c03..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationLocalVarTargetRecord.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationLocalVarTargetRecord(TypeAnnotationLocalVarTargetItemRecord[] Items) : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = null; - - if (reader.TryReadU2(out ushort length) == false) - return false; - - var items = new TypeAnnotationLocalVarTargetItemRecord[length]; - for (int i = 0; i < length; i++) - if (TypeAnnotationLocalVarTargetItemRecord.TryRead(ref reader, out items[i]) == false) - return false; - - targetInfo = new TypeAnnotationLocalVarTargetRecord(items); - return true; - } - - /// - /// Gets the size of the record if written. - /// - /// - public override int GetSize() - { - var length = 0; - length += sizeof(ushort); - - foreach (var item in Items) - length += item.GetSize(); - - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2((ushort)Items.Length) == false) - return false; - - foreach (var item in Items) - if (item.TryWrite(ref writer) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationOffsetTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationOffsetTargetRecord.cs deleted file mode 100644 index 4babfae72c..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationOffsetTargetRecord.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationOffsetTargetRecord(ushort Offset) : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = null; - - if (reader.TryReadU2(out ushort offset) == false) - return false; - - targetInfo = new TypeAnnotationCatchTargetRecord(offset); - return true; - } - - /// - /// Gets the size of the record if written. - /// - /// - public override int GetSize() - { - var length = 0; - length += sizeof(ushort); - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(Offset) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationParameterBoundTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationParameterBoundTargetRecord.cs deleted file mode 100644 index c11930bfb8..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationParameterBoundTargetRecord.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationParameterBoundTargetRecord(byte ParameterIndex, byte BoundIndex) : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = null; - - if (reader.TryReadU1(out byte parameterIndex) == false) - return false; - if (reader.TryReadU1(out byte boundIndex) == false) - return false; - - targetInfo = new TypeAnnotationParameterBoundTargetRecord(parameterIndex, boundIndex); - return true; - } - - public override int GetSize() - { - var length = 0; - length += sizeof(byte); - length += sizeof(byte); - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU1(ParameterIndex) == false) - return false; - if (writer.TryWriteU1(BoundIndex) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationParameterTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationParameterTargetRecord.cs deleted file mode 100644 index 37e31c886d..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationParameterTargetRecord.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationParameterTargetRecord(byte ParameterIndex) : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = null; - - if (reader.TryReadU1(out byte parameterIndex) == false) - return false; - - targetInfo = new TypeAnnotationParameterTargetRecord( parameterIndex); - return true; - } - - public override int GetSize() - { - var length = 0; - length += sizeof(byte); - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU1(ParameterIndex) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationRecord.cs deleted file mode 100644 index 01fa9b68e3..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationRecord.cs +++ /dev/null @@ -1,104 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct TypeAnnotationRecord(TypeAnnotationTargetType TargetType, TypeAnnotationTargetRecord Target, TypePathRecord TargetPath, ushort TypeIndex, params ElementValuePairRecord[] Elements) - { - - public static bool TryReadTypeAnnotation(ref ClassFormatReader reader, out TypeAnnotationRecord annotation) - { - annotation = default; - - if (reader.TryReadU1(out byte targetType) == false) - return false; - if (TryReadTarget(ref reader, (TypeAnnotationTargetType)targetType, out var target) == false) - return false; - if (TypePathRecord.TryRead(ref reader, out var targetPath) == false) - return false; - if (reader.TryReadU2(out ushort typeIndex) == false) - return false; - if (reader.TryReadU2(out ushort pairCount) == false) - return false; - - var elements = new ElementValuePairRecord[pairCount]; - for (int i = 0; i < pairCount; i++) - if (ElementValuePairRecord.TryRead(ref reader, out elements[i]) == false) - return false; - - annotation = new TypeAnnotationRecord((TypeAnnotationTargetType)targetType, target, targetPath, typeIndex, elements); - return true; - } - - public static bool TryReadTarget(ref ClassFormatReader reader, TypeAnnotationTargetType targetType, out TypeAnnotationTargetRecord targetInfo) => targetType switch - { - TypeAnnotationTargetType.ClassTypeParameter => TypeAnnotationParameterTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.MethodTypeParameter => TypeAnnotationParameterTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.ClassExtends => TypeAnnotationSuperTypeTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.ClassTypeParameterBound => TypeAnnotationParameterBoundTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.MethodTypeParameterBound => TypeAnnotationParameterBoundTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.Field => TypeAnnotationEmptyTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.MethodReturn => TypeAnnotationEmptyTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.MethodReceiver => TypeAnnotationEmptyTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.MethodFormalParameter => TypeAnnotationFormalParameterTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.Throws => TypeAnnotationThrowsTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.LocalVariable => TypeAnnotationLocalVarTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.ResourceVariable => TypeAnnotationLocalVarTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.ExceptionParameter => TypeAnnotationCatchTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.InstanceOf => TypeAnnotationOffsetTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.New => TypeAnnotationOffsetTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.ConstructorReference => TypeAnnotationOffsetTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.MethodReference => TypeAnnotationOffsetTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.Cast => TypeAnnotationTypeArgumentTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.ConstructorInvocationTypeArgument => TypeAnnotationTypeArgumentTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.MethodInvocationTypeArgument => TypeAnnotationTypeArgumentTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.ConstructorReferenceTypeArgument => TypeAnnotationTypeArgumentTargetRecord.TryRead(ref reader, out targetInfo), - TypeAnnotationTargetType.MethodReferenceTypeArgument => TypeAnnotationTypeArgumentTargetRecord.TryRead(ref reader, out targetInfo), - _ => throw new ByteCodeException($"Invalid type annotation target type: '0x{targetType:X}'."), - }; - - /// - /// Gets the number of bytes required to write the record. - /// - /// - public int GetSize() - { - var size = 0; - size += sizeof(byte); - size += Target.GetSize(); - size += TargetPath.GetSize(); - size += sizeof(ushort); - size += sizeof(ushort); - - for (int i = 0; i < Elements.Length; i++) - size += Elements[i].GetSize(); - - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU1((byte)TargetType) == false) - return false; - if (Target.TryWrite(ref writer) == false) - return false; - if (TargetPath.TryWrite(ref writer) == false) - return false; - if (writer.TryWriteU2(TypeIndex) == false) - return false; - if (writer.TryWriteU2((ushort)Elements.Length) == false) - return false; - - foreach (var record in Elements) - if (record.TryWrite(ref writer) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationSuperTypeTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationSuperTypeTargetRecord.cs deleted file mode 100644 index bfe06378a0..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationSuperTypeTargetRecord.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationSuperTypeTargetRecord(ushort SuperTypeIndex) : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = null; - - if (reader.TryReadU2(out ushort superTypeIndex) == false) - return false; - - targetInfo = new TypeAnnotationSuperTypeTargetRecord(superTypeIndex); - return true; - } - - public override int GetSize() - { - var length = 0; - length += sizeof(ushort); - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(SuperTypeIndex) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationTargetRecord.cs deleted file mode 100644 index 71df0c3a77..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationTargetRecord.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal abstract record TypeAnnotationTargetRecord - { - - /// - /// Returns the size of the record when written. - /// - /// - public abstract int GetSize(); - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public abstract bool TryWrite(ref ClassFormatWriter writer); - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationTargetType.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationTargetType.cs deleted file mode 100644 index 4c9fbba312..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationTargetType.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal enum TypeAnnotationTargetType : byte - { - - ClassTypeParameter = 0x00, - MethodTypeParameter = 0x01, - ClassExtends = 0x10, - ClassTypeParameterBound = 0x11, - MethodTypeParameterBound = 0x12, - Field = 0x13, - MethodReturn = 0x14, - MethodReceiver = 0x15, - MethodFormalParameter = 0x16, - Throws = 0x17, - LocalVariable = 0x40, - ResourceVariable = 0x41, - ExceptionParameter = 0x42, - InstanceOf = 0x43, - New = 0x44, - ConstructorReference = 0x45, - MethodReference = 0x46, - Cast = 0x47, - ConstructorInvocationTypeArgument = 0x48, - MethodInvocationTypeArgument = 0x49, - ConstructorReferenceTypeArgument = 0x4A, - MethodReferenceTypeArgument = 0x4B, - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationThrowsTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationThrowsTargetRecord.cs deleted file mode 100644 index cd5aa44d8f..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationThrowsTargetRecord.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationThrowsTargetRecord(ushort ThrowsTypeIndex) : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = null; - - if (reader.TryReadU2(out ushort throwsTypeIndex) == false) - return false; - - targetInfo = new TypeAnnotationThrowsTargetRecord(throwsTypeIndex); - return true; - } - - public override int GetSize() - { - var length = 0; - length += sizeof(ushort); - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(ThrowsTypeIndex) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypeAnnotationTypeArgumentTargetRecord.cs b/src/IKVM.ByteCode/Parsing/TypeAnnotationTypeArgumentTargetRecord.cs deleted file mode 100644 index bc0f3453b0..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypeAnnotationTypeArgumentTargetRecord.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record TypeAnnotationTypeArgumentTargetRecord(ushort Offset, byte TypeArgumentIndex) : TypeAnnotationTargetRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out TypeAnnotationTargetRecord targetInfo) - { - targetInfo = null; - - if (reader.TryReadU2(out ushort offset) == false) - return false; - if (reader.TryReadU1(out byte typeArgumentIndex) == false) - return false; - - targetInfo = new TypeAnnotationTypeArgumentTargetRecord(offset, typeArgumentIndex); - return true; - } - - /// - /// Gets the size of the record if written. - /// - /// - public override int GetSize() - { - var length = 0; - length += sizeof(ushort); - length += sizeof(byte); - return length; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public override bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU2(Offset) == false) - return false; - if (writer.TryWriteU1(TypeArgumentIndex) == false) - return false; - - return true; - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Parsing/TypePathItemRecord.cs b/src/IKVM.ByteCode/Parsing/TypePathItemRecord.cs deleted file mode 100644 index f67f1baebe..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypePathItemRecord.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct TypePathItemRecord(TypePathKind Kind, byte ArgumentIndex) - { - - public static bool TryRead(ref ClassFormatReader reader, out TypePathItemRecord record) - { - record = default; - - if (reader.TryReadU1(out byte kind) == false) - return false; - if (reader.TryReadU1(out byte argumentIndex) == false) - return false; - - record = new TypePathItemRecord((TypePathKind)kind, argumentIndex); - return true; - } - - public int GetSize() - { - var size = 0; - size += sizeof(byte); - size += sizeof(byte); - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU1((byte)Kind) == false) - return false; - if (writer.TryWriteU1(ArgumentIndex) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/TypePathRecord.cs b/src/IKVM.ByteCode/Parsing/TypePathRecord.cs deleted file mode 100644 index b351bc464a..0000000000 --- a/src/IKVM.ByteCode/Parsing/TypePathRecord.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal record struct TypePathRecord(params TypePathItemRecord[] Path) - { - - public static bool TryRead(ref ClassFormatReader reader, out TypePathRecord typePath) - { - typePath = default; - - if (reader.TryReadU1(out byte length) == false) - return false; - - var path = new TypePathItemRecord[length]; - for (int i = 0; i < length; i++) - { - if (TypePathItemRecord.TryRead(ref reader, out var item) == false) - return false; - - path[i] = item; - } - - typePath = new TypePathRecord(path); - return true; - } - - public int GetSize() - { - var size = 0; - size += sizeof(byte); - - foreach (var item in Path) - size += item.GetSize(); - - return size; - } - - /// - /// Attempts to write the record to the given . - /// - /// - /// - public bool TryWrite(ref ClassFormatWriter writer) - { - if (writer.TryWriteU1((byte)Path.Length) == false) - return false; - - foreach (var item in Path) - if (item.TryWrite(ref writer) == false) - return false; - - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/UninitializedThisVariableInfoRecord.cs b/src/IKVM.ByteCode/Parsing/UninitializedThisVariableInfoRecord.cs deleted file mode 100644 index 6b52843f36..0000000000 --- a/src/IKVM.ByteCode/Parsing/UninitializedThisVariableInfoRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record UninitializedThisVariableInfoRecord : VerificationTypeInfoRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = new UninitializedThisVariableInfoRecord(); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/UninitializedVariableInfoRecord.cs b/src/IKVM.ByteCode/Parsing/UninitializedVariableInfoRecord.cs deleted file mode 100644 index 8a16e8df7c..0000000000 --- a/src/IKVM.ByteCode/Parsing/UninitializedVariableInfoRecord.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record UninitializedVariableInfoRecord(ushort Offset) : VerificationTypeInfoRecord - { - - public static bool TryRead(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = null; - - if (reader.TryReadU2(out ushort offset) == false) - return false; - - record = new UninitializedVariableInfoRecord(offset); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/UnknownAttributeRecord.cs b/src/IKVM.ByteCode/Parsing/UnknownAttributeRecord.cs deleted file mode 100644 index 50d2949772..0000000000 --- a/src/IKVM.ByteCode/Parsing/UnknownAttributeRecord.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal sealed record UnknownAttributeRecord(byte[] Data) : AttributeRecord - { - - public static bool TryReadCustomAttribute(ref ClassFormatReader reader, out AttributeRecord attribute) - { - var data = new byte[reader.Length]; - reader.TryCopyTo(data); - - attribute = new UnknownAttributeRecord(data); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/Utf8ConstantRecord.cs b/src/IKVM.ByteCode/Parsing/Utf8ConstantRecord.cs deleted file mode 100644 index 548db6b53f..0000000000 --- a/src/IKVM.ByteCode/Parsing/Utf8ConstantRecord.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Buffers; - -namespace IKVM.ByteCode.Parsing -{ - - internal record class Utf8ConstantRecord(byte[] Value) : ConstantRecord - { - - /// - /// Parses a UTF8 constant in the constant pool. - /// - /// - /// - public static bool TryReadUtf8Constant(ref ClassFormatReader reader, out ConstantRecord constant, out int skip) - { - constant = null; - skip = 0; - - if (reader.TryReadU2(out ushort length) == false) - return false; - if (reader.TryReadManyU1(length, out ReadOnlySequence value) == false) - return false; - - var valueBuffer = new byte[value.Length]; - value.CopyTo(valueBuffer); - - constant = new Utf8ConstantRecord(valueBuffer); - return true; - } - - } - -} diff --git a/src/IKVM.ByteCode/Parsing/VerificationTypeInfoRecord.cs b/src/IKVM.ByteCode/Parsing/VerificationTypeInfoRecord.cs deleted file mode 100644 index 51a5e5c7c0..0000000000 --- a/src/IKVM.ByteCode/Parsing/VerificationTypeInfoRecord.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace IKVM.ByteCode.Parsing -{ - - internal abstract record VerificationTypeInfoRecord - { - - public static bool TryReadVerificationTypeInfo(ref ClassFormatReader reader, out VerificationTypeInfoRecord record) - { - record = null; - - if (reader.TryReadU1(out byte tag) == false) - return false; - - return tag switch - { - 0 => TopVariableInfoRecord.TryRead(ref reader, out record), - 1 => IntegerVariableInfoRecord.TryRead(ref reader, out record), - 2 => FloatVariableInfoRecord.TryRead(ref reader, out record), - 3 => DoubleVariableInfoRecord.TryRead(ref reader, out record), - 4 => LongVariableInfoRecord.TryRead(ref reader, out record), - 5 => NullVariableInfoRecord.TryRead(ref reader, out record), - 6 => UninitializedThisVariableInfoRecord.TryRead(ref reader, out record), - 7 => ObjectVariableInfoRecord.TryRead(ref reader, out record), - 8 => UninitializedVariableInfoRecord.TryRead(ref reader, out record), - _ => throw new ByteCodeException($"Invalid verification info tag: '{tag}'."), - }; - } - - } - -} diff --git a/src/IKVM.ByteCode/README.md b/src/IKVM.ByteCode/README.md deleted file mode 100644 index 22312bf091..0000000000 --- a/src/IKVM.ByteCode/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# IKVM.ByteCode - -Provides a Java class file parser, reader and writer implementation used by the IKVM project. - -The project is organized into three related sections. - -## IKVM.ByteCode.Parsing - -Contains Record structures and classes that represent the raw values that might appear in a Java class file. These -types are not blittable, but do contain a TryRead method and TryWrite method, targeting a ClassFormatReader and -ClassFormatWriter respectively. - -## IVKM.ByteCode.Reading - -Contains Reader classes that wrap Record structures. The main top-level class is ClassReader. ClassReader operates on -a ClassRecord. ClassReader exposes collections and properties which allow navigation through a parsed class file. An -attempt is made to only initialize data from the underlying records on demand. - -The Readers allow you to navigate through the constant pool, resolve constant values, and navigate through the -interfaces, fields, methods and attributes of the class. diff --git a/src/IKVM.ByteCode/Reading/AnnotationDefaultAttributeReader.cs b/src/IKVM.ByteCode/Reading/AnnotationDefaultAttributeReader.cs deleted file mode 100644 index fe036cbef3..0000000000 --- a/src/IKVM.ByteCode/Reading/AnnotationDefaultAttributeReader.cs +++ /dev/null @@ -1,29 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class AnnotationDefaultAttributeReader : AttributeReader - { - - ElementValueReader defaultValue; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal AnnotationDefaultAttributeReader(ClassReader declaringClass, AttributeInfoReader info, AnnotationDefaultAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - public ElementValueReader DefaultValue => LazyGet(ref defaultValue, () => ElementValueReader.Resolve(DeclaringClass, Record.DefaultValue)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/AnnotationReader.cs b/src/IKVM.ByteCode/Reading/AnnotationReader.cs deleted file mode 100644 index 5a9b50c55a..0000000000 --- a/src/IKVM.ByteCode/Reading/AnnotationReader.cs +++ /dev/null @@ -1,37 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class AnnotationReader : ReaderBase - { - - Utf8ConstantReader type; - ElementValueKeyReaderCollection elements; - - /// - /// Initializes a new instance. - /// - /// - /// - public AnnotationReader(ClassReader declaringClass, AnnotationRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the type of the annotation. - /// - public Utf8ConstantReader Type => LazyGet(ref type, () => DeclaringClass.Constants.Get(Record.TypeIndex)); - - /// - /// Gets the element values of the annotation. - /// - public ElementValueKeyReaderCollection Elements => LazyGet(ref elements, () => new ElementValueKeyReaderCollection(DeclaringClass, Record.Elements)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/AnnotationReaderCollection.cs b/src/IKVM.ByteCode/Reading/AnnotationReaderCollection.cs deleted file mode 100644 index b132856a6e..0000000000 --- a/src/IKVM.ByteCode/Reading/AnnotationReaderCollection.cs +++ /dev/null @@ -1,36 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of annotation data. - /// - internal sealed class AnnotationReaderCollection : LazyReaderList - { - - /// - /// Initializes a new instance. - /// - /// - /// - public AnnotationReaderCollection(ClassReader declaringClass, AnnotationRecord[] records) : - base(declaringClass, records) - { - - } - - /// - /// Creates a new reader. - /// - /// - /// - /// - protected override AnnotationReader CreateReader(int index, AnnotationRecord record) - { - return new AnnotationReader(DeclaringClass, record); - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/AttributeInfoReader.cs b/src/IKVM.ByteCode/Reading/AttributeInfoReader.cs deleted file mode 100644 index dc6403d415..0000000000 --- a/src/IKVM.ByteCode/Reading/AttributeInfoReader.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; - -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class AttributeInfoReader : ReaderBase - { - - Utf8ConstantReader name; - - /// - /// Initializes a new instance. - /// - /// - /// - internal AttributeInfoReader(ClassReader declaringClass, AttributeInfoRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the name of the attribute. - /// - public Utf8ConstantReader Name => name ??= DeclaringClass.Constants.Get(Record.NameIndex); - - /// - /// Gets the data of the attribute. - /// - public ReadOnlyMemory Data => Record.Data; - - } - -} diff --git a/src/IKVM.ByteCode/Reading/AttributeReader.cs b/src/IKVM.ByteCode/Reading/AttributeReader.cs deleted file mode 100644 index a87b5ecaaf..0000000000 --- a/src/IKVM.ByteCode/Reading/AttributeReader.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; - -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal abstract class AttributeReader : ReaderBase - { - - readonly AttributeInfoReader info; - readonly AttributeRecord record; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal AttributeReader(ClassReader declaringClass, AttributeInfoReader info, AttributeRecord record) : - base(declaringClass) - { - this.info = info ?? throw new ArgumentNullException(nameof(info)); - this.record = record ?? throw new ArgumentNullException(nameof(record)); - } - - /// - /// Gets the information about the attribute. - /// - public AttributeInfoReader Info => info; - - /// - /// Gets the underlying record of the attribute. - /// - public AttributeRecord Record => record; - - } - - internal abstract class AttributeReader : AttributeReader - where TRecord : AttributeRecord - { - - readonly TRecord record; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal AttributeReader(ClassReader declaringClass, AttributeInfoReader info, TRecord record) : - base(declaringClass, info, record) - { - this.record = record ?? throw new ArgumentNullException(nameof(record)); - } - - /// - /// Gets the underlying data record of the attribute. - /// - public new TRecord Record => record; - - } - -} diff --git a/src/IKVM.ByteCode/Reading/AttributeReaderCollection.cs b/src/IKVM.ByteCode/Reading/AttributeReaderCollection.cs deleted file mode 100644 index f5356e78f9..0000000000 --- a/src/IKVM.ByteCode/Reading/AttributeReaderCollection.cs +++ /dev/null @@ -1,196 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of attribute data. - /// - internal sealed class AttributeReaderCollection : LazyReaderList - { - - ConstantValueAttributeReader constantValueAttribute; - CodeAttributeReader codeAttribute; - StackMapTableAttributeReader stackMapTableAttribute; - ExceptionsAttributeReader exceptionsAttribute; - InnerClassesAttributeReader innerClassesAttribute; - EnclosingMethodAttributeReader enclosingMethodAttribute; - SyntheticAttributeReader syntheticAttribute; - SignatureAttributeReader signatureAttribute; - SourceFileAttributeReader sourceFileAttribute; - SourceDebugExtensionAttributeReader sourceDebugExtensionAttribute; - LineNumberTableAttributeReader lineNumberTableAttribute; - LocalVariableTableAttributeReader localVariableTableAttribute; - LocalVariableTypeTableAttributeReader localVariableTypeTableAttribute; - DeprecatedAttributeReader deprecatedAttribute; - RuntimeVisibleAnnotationsAttributeReader runtimeVisibleAnnotationsAttribute; - RuntimeInvisibleAnnotationsAttributeReader runtimeInvisibleAnnotationsAttribute; - RuntimeVisibleParameterAnnotationsAttributeReader runtimeVisibleParameterAnnotationsAttribute; - RuntimeInvisibleParameterAnnotationsAttributeReader runtimeInvisibleParameterAnnotationsAttribute; - RuntimeVisibleTypeAnnotationsAttributeReader runtimeVisibleTypeAnnotationsAttribute; - RuntimeInvisibleTypeAnnotationsAttributeReader runtimeInvisibleTypeAnnotationsAttribute; - AnnotationDefaultAttributeReader annotationDefaultAttribute; - BootstrapMethodsAttributeReader bootstrapMethodsAttribute; - MethodParametersAttributeReader methodParametersAttribute; - ModuleAttributeReader moduleAttribute; - ModulePackagesAttributeReader modulePackagesAttribute; - ModuleMainClassAttributeReader moduleMainClassAttribute; - NestHostAttributeReader nestHostAttribute; - NestMembersAttributeReader nestMembersAttribute; - RecordAttributeReader recordAttribute; - PermittedSubclassesAttributeReader permittedSubclassesAttribute; - - /// - /// Initializes a new instance. - /// - /// - /// - public AttributeReaderCollection(ClassReader declaringClass, AttributeInfoRecord[] records) : - base(declaringClass, records) - { - - } - - /// - /// Creates a new reader. - /// - /// - /// - /// - /// - protected override AttributeReader CreateReader(int index, AttributeInfoRecord record) - { - var info = new AttributeInfoReader(DeclaringClass, record); - if (AttributeRecord.TryRead(info, out var attribute) == false) - throw new ByteCodeException("Unable to read attribute data."); - - return attribute switch - { - ConstantValueAttributeRecord d => new ConstantValueAttributeReader(DeclaringClass, info, d), - CodeAttributeRecord d => new CodeAttributeReader(DeclaringClass, info, d), - StackMapTableAttributeRecord d => new StackMapTableAttributeReader(DeclaringClass, info, d), - ExceptionsAttributeRecord d => new ExceptionsAttributeReader(DeclaringClass, info, d), - InnerClassesAttributeRecord d => new InnerClassesAttributeReader(DeclaringClass, info, d), - EnclosingMethodAttributeRecord d => new EnclosingMethodAttributeReader(DeclaringClass, info, d), - SyntheticAttributeRecord d => new SyntheticAttributeReader(DeclaringClass, info, d), - SignatureAttributeRecord d => new SignatureAttributeReader(DeclaringClass, info, d), - SourceFileAttributeRecord d => new SourceFileAttributeReader(DeclaringClass, info, d), - SourceDebugExtensionAttributeRecord d => new SourceDebugExtensionAttributeReader(DeclaringClass, info, d), - LineNumberTableAttributeRecord d => new LineNumberTableAttributeReader(DeclaringClass, info, d), - LocalVariableTableAttributeRecord d => new LocalVariableTableAttributeReader(DeclaringClass, info, d), - LocalVariableTypeTableAttributeRecord d => new LocalVariableTypeTableAttributeReader(DeclaringClass, info, d), - DeprecatedAttributeRecord d => new DeprecatedAttributeReader(DeclaringClass, info, d), - RuntimeVisibleAnnotationsAttributeRecord d => new RuntimeVisibleAnnotationsAttributeReader(DeclaringClass, info, d), - RuntimeInvisibleAnnotationsAttributeRecord d => new RuntimeInvisibleAnnotationsAttributeReader(DeclaringClass, info, d), - RuntimeVisibleParameterAnnotationsAttributeRecord d => new RuntimeVisibleParameterAnnotationsAttributeReader(DeclaringClass, info, d), - RuntimeInvisibleParameterAnnotationsAttributeRecord d => new RuntimeInvisibleParameterAnnotationsAttributeReader(DeclaringClass, info, d), - RuntimeVisibleTypeAnnotationsAttributeRecord d => new RuntimeVisibleTypeAnnotationsAttributeReader(DeclaringClass, info, d), - RuntimeInvisibleTypeAnnotationsAttributeRecord d => new RuntimeInvisibleTypeAnnotationsAttributeReader(DeclaringClass, info, d), - AnnotationDefaultAttributeRecord d => new AnnotationDefaultAttributeReader(DeclaringClass, info, d), - BootstrapMethodsAttributeRecord d => new BootstrapMethodsAttributeReader(DeclaringClass, info, d), - MethodParametersAttributeRecord d => new MethodParametersAttributeReader(DeclaringClass, info, d), - ModuleAttributeRecord d => new ModuleAttributeReader(DeclaringClass, info, d), - ModulePackagesAttributeRecord d => new ModulePackagesAttributeReader(DeclaringClass, info, d), - ModuleMainClassAttributeRecord d => new ModuleMainClassAttributeReader(DeclaringClass, info, d), - NestHostAttributeRecord d => new NestHostAttributeReader(DeclaringClass, info, d), - NestMembersAttributeRecord d => new NestMembersAttributeReader(DeclaringClass, info, d), - RecordAttributeRecord d => new RecordAttributeReader(DeclaringClass, info, d), - PermittedSubclassesAttributeRecord d => new PermittedSubclassesAttributeReader(DeclaringClass, info, d), - UnknownAttributeRecord d => new UnknownAttributeReader(DeclaringClass, info, d), - _ => throw new ByteCodeException("Cannot resolve attribute data."), - }; - } - - /// - /// Gets the attribute with the specified name. - /// - /// - /// - public AttributeReader this[string name] => this.FirstOrDefault(i => i.Info.Name.Value == name) ?? throw new KeyNotFoundException(); - - /// - /// Returns true if an attribute with the specified name exists. - /// - /// - /// - public bool Contains(string name) => this.Any(i => i.Info.Name.Value == name); - - /// - /// Attempts to get the attribute with the specified name. - /// - /// - /// - public bool TryGet(out TAttribute value) - { - value = this.OfType().FirstOrDefault(); - return value != null; - } - - public ConstantValueAttributeReader ConstantValue => LazyGet(ref constantValueAttribute, () => TryGet(out var attribute) ? attribute : null); - - public CodeAttributeReader Code => LazyGet(ref codeAttribute, () => TryGet(out var attribute) ? attribute : null); - - public StackMapTableAttributeReader StackMapTable => LazyGet(ref stackMapTableAttribute, () => TryGet(out var attribute) ? attribute : null); - - public ExceptionsAttributeReader Exceptions => LazyGet(ref exceptionsAttribute, () => TryGet(out var attribute) ? attribute : null); - - public InnerClassesAttributeReader InnerClasses => LazyGet(ref innerClassesAttribute, () => TryGet(out var attribute) ? attribute : null); - - public EnclosingMethodAttributeReader EnclosingMethod => LazyGet(ref enclosingMethodAttribute, () => TryGet(out var attribute) ? attribute : null); - - public SyntheticAttributeReader Synthetic => LazyGet(ref syntheticAttribute, () => TryGet(out var attribute) ? attribute : null); - - public SignatureAttributeReader Signature => LazyGet(ref signatureAttribute, () => TryGet(out var attribute) ? attribute : null); - - public SourceFileAttributeReader SourceFile => LazyGet(ref sourceFileAttribute, () => TryGet(out var attribute) ? attribute : null); - - public SourceDebugExtensionAttributeReader SourceDebugExtension => LazyGet(ref sourceDebugExtensionAttribute, () => TryGet(out var attribute) ? attribute : null); - - public LineNumberTableAttributeReader LineNumberTable => LazyGet(ref lineNumberTableAttribute, () => TryGet(out var attribute) ? attribute : null); - - public LocalVariableTableAttributeReader LocalVariableTable => LazyGet(ref localVariableTableAttribute, () => TryGet(out var attribute) ? attribute : null); - - public LocalVariableTypeTableAttributeReader LocalVariableTypeTable => LazyGet(ref localVariableTypeTableAttribute, () => TryGet(out var attribute) ? attribute : null); - - public DeprecatedAttributeReader Deprecated => LazyGet(ref deprecatedAttribute, () => TryGet(out var attribute) ? attribute : null); - - public RuntimeVisibleAnnotationsAttributeReader RuntimeVisibleAnnotations => LazyGet(ref runtimeVisibleAnnotationsAttribute, () => TryGet(out var attribute) ? attribute : null); - - public RuntimeInvisibleAnnotationsAttributeReader RuntimeInvisibleAnnotations => LazyGet(ref runtimeInvisibleAnnotationsAttribute, () => TryGet(out var attribute) ? attribute : null); - - public RuntimeVisibleParameterAnnotationsAttributeReader RuntimeVisibleParameterAnnotations => LazyGet(ref runtimeVisibleParameterAnnotationsAttribute, () => TryGet(out var attribute) ? attribute : null); - - public RuntimeInvisibleParameterAnnotationsAttributeReader RuntimeInvisibleParameterAnnotations => LazyGet(ref runtimeInvisibleParameterAnnotationsAttribute, () => TryGet(out var attribute) ? attribute : null); - - public RuntimeVisibleTypeAnnotationsAttributeReader RuntimeVisibleTypeAnnotations => LazyGet(ref runtimeVisibleTypeAnnotationsAttribute, () => TryGet(out var attribute) ? attribute : null); - - public RuntimeInvisibleTypeAnnotationsAttributeReader RuntimeInvisibleTypeAnnotations => LazyGet(ref runtimeInvisibleTypeAnnotationsAttribute, () => TryGet(out var attribute) ? attribute : null); - - public AnnotationDefaultAttributeReader AnnotationDefault => LazyGet(ref annotationDefaultAttribute, () => TryGet(out var attribute) ? attribute : null); - - public BootstrapMethodsAttributeReader BootstrapMethods => LazyGet(ref bootstrapMethodsAttribute, () => TryGet(out var attribute) ? attribute : null); - - public MethodParametersAttributeReader MethodParameters => LazyGet(ref methodParametersAttribute, () => TryGet(out var attribute) ? attribute : null); - - public ModuleAttributeReader Module => LazyGet(ref moduleAttribute, () => TryGet(out var attribute) ? attribute : null); - - public ModulePackagesAttributeReader ModulePackages => LazyGet(ref modulePackagesAttribute, () => TryGet(out var attribute) ? attribute : null); - - public ModuleMainClassAttributeReader ModuleMainClass => LazyGet(ref moduleMainClassAttribute, () => TryGet(out var attribute) ? attribute : null); - - public NestHostAttributeReader NestHost => LazyGet(ref nestHostAttribute, () => TryGet(out var attribute) ? attribute : null); - - public NestMembersAttributeReader NestMembers => LazyGet(ref nestMembersAttribute, () => TryGet(out var attribute) ? attribute : null); - - public RecordAttributeReader Record => LazyGet(ref recordAttribute, () => TryGet(out var attribute) ? attribute : null); - - public PermittedSubclassesAttributeReader PermittedSubclasses => LazyGet(ref permittedSubclassesAttribute, () => TryGet(out var attribute) ? attribute : null); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/BootstrapMethodsAttributeMethodReader.cs b/src/IKVM.ByteCode/Reading/BootstrapMethodsAttributeMethodReader.cs deleted file mode 100644 index 9d8be36f51..0000000000 --- a/src/IKVM.ByteCode/Reading/BootstrapMethodsAttributeMethodReader.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; - -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class BootstrapMethodsAttributeMethodReader : ReaderBase - { - - MethodrefConstantReader methodref; - IReadOnlyList arguments; - - /// - /// Initializes a new instance. - /// - /// - /// - public BootstrapMethodsAttributeMethodReader(ClassReader declaringClass, BootstrapMethodsAttributeMethodRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the method being referenced. - /// - public MethodrefConstantReader Methodref => LazyGet(ref methodref, () => DeclaringClass.Constants.Get(Record.MethodRefIndex)); - - /// - /// Gets the arguments bound to the method reference. - /// - public IReadOnlyList Arguments => LazyGet(ref arguments, () => new DelegateLazyReaderList(DeclaringClass, Record.Arguments, (_, index) => DeclaringClass.Constants[index])); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/BootstrapMethodsAttributeReader.cs b/src/IKVM.ByteCode/Reading/BootstrapMethodsAttributeReader.cs deleted file mode 100644 index ee487fb355..0000000000 --- a/src/IKVM.ByteCode/Reading/BootstrapMethodsAttributeReader.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; - -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal class BootstrapMethodsAttributeReader : AttributeReader - { - - IReadOnlyList methods; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal BootstrapMethodsAttributeReader(ClassReader declaringClass, AttributeInfoReader info, BootstrapMethodsAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - /// - /// Gets the set of methods described by this bootstrap attribute. - /// - public IReadOnlyList Methods => LazyGet(ref methods, () => new DelegateLazyReaderList(DeclaringClass, Record.Methods, (_, record) => new BootstrapMethodsAttributeMethodReader(DeclaringClass, record))); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ClassConstantReader.cs b/src/IKVM.ByteCode/Reading/ClassConstantReader.cs deleted file mode 100644 index de2ae10291..0000000000 --- a/src/IKVM.ByteCode/Reading/ClassConstantReader.cs +++ /dev/null @@ -1,37 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ClassConstantReader : ConstantReader - { - - Utf8ConstantReader name; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public ClassConstantReader(ClassReader declaringClass, ushort index, ClassConstantRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the name of the class. - /// - public Utf8ConstantReader Name => LazyGet(ref name, () => DeclaringClass.Constants.Get(Record.NameIndex)); - - /// - /// Returns whether or not this constant is loadable. - /// - public override bool IsLoadable => DeclaringClass.Version >= new ClassFormatVersion(49, 0); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/ClassReader.cs b/src/IKVM.ByteCode/Reading/ClassReader.cs deleted file mode 100644 index b45b60600d..0000000000 --- a/src/IKVM.ByteCode/Reading/ClassReader.cs +++ /dev/null @@ -1,307 +0,0 @@ -using System; -using System.Buffers; -using System.IO; -using System.IO.MemoryMappedFiles; -using System.IO.Pipelines; -using System.Threading; -using System.Threading.Tasks; - -using IKVM.ByteCode.Buffers; -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Provides stateful operations for reading a class file. - /// - internal sealed class ClassReader : ReaderBase - { - - const int MIN_CLASS_SIZE = 30; - - /// - /// Attempts to read a class from the given memory position. - /// - /// - /// - /// - /// - public static unsafe bool TryRead(byte* pointer, int length, out ClassReader clazz) - { - using var mmap = new UnmanagedMemoryManager(pointer, length); - return TryRead(mmap.Memory, out clazz); - } - - /// - /// Attempts to read a class from the given memory location. - /// - /// - /// - /// - /// - public static unsafe ClassReader Read(byte* pointer, int length) - { - return TryRead(pointer, length, out var clazz) ? clazz : throw new InvalidClassException("Failed to open ClassReader. Incomplete class data."); - } - - /// - /// Attempts to read a class from the given file. - /// - /// - /// - /// - public static unsafe bool TryRead(string path, out ClassReader clazz) - { - using var mmap = MemoryMappedFile.CreateFromFile(path, FileMode.Open, null, 0, MemoryMappedFileAccess.Read); - using var view = mmap.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); - - try - { - byte* pntr = null; - view.SafeMemoryMappedViewHandle.AcquirePointer(ref pntr); - return TryRead(pntr, checked((int)view.SafeMemoryMappedViewHandle.ByteLength), out clazz); - } - finally - { - view.SafeMemoryMappedViewHandle.ReleasePointer(); - } - } - - /// - /// Attempts to read a class from the given file. - /// - /// - /// - /// - /// - public static unsafe ClassReader Read(string path) - { - return TryRead(path, out var clazz) ? clazz : throw new InvalidClassException("Failed to open ClassReader. Incomplete class data."); - } - - /// - /// Attempts to read a class from the given buffer. - /// - /// - /// - /// - public static bool TryRead(ReadOnlyMemory buffer, out ClassReader clazz) - { - return TryRead(new ReadOnlySequence(buffer), out clazz); - } - - /// - /// Attempts to read a class from the given buffer. - /// - /// - /// - /// - public static ClassReader Read(ReadOnlyMemory buffer) - { - return TryRead(buffer, out var clazz) ? clazz : throw new InvalidClassException("Failed to open ClassReader. Incomplete class data."); - } - - /// - /// Attempts to read a class from the given buffer. - /// - /// - /// - /// - public static bool TryRead(in ReadOnlySequence buffer, out ClassReader clazz) - { - return TryRead(buffer, out clazz, out _, out _); - } - - /// - /// Attempts to read a class from the given buffer, returning information about the number of consumed and examined bytes. - /// - /// - /// - /// - /// - /// - /// - public static bool TryRead(in ReadOnlySequence buffer, out ClassReader clazz, out SequencePosition consumed, out SequencePosition examined) - { - consumed = buffer.Start; - - var reader = new ClassFormatReader(buffer); - if (TryRead(ref reader, out clazz) == false) - { - // examined up to the position of the reader, but consumed nothing - examined = reader.Position; - return false; - } - else - { - // examined up to the point of the reader, consumed the same - consumed = reader.Position; - examined = reader.Position; - return true; - } - } - - /// - /// Attempts to read a class from the given buffer. - /// - /// - /// - /// - public static ClassReader Read(in ReadOnlySequence buffer) - { - return TryRead(buffer, out var clazz) ? clazz : throw new InvalidClassException("Failed to open ClassReader. Incomplete class data."); - } - - /// - /// Attempts to read a class from the given reader. - /// - /// - /// - /// - /// - public static bool TryRead(ref ClassFormatReader reader, out ClassReader clazz) - { - clazz = null; - - if (ClassRecord.TryRead(ref reader, out var record) == false) - return false; - - clazz = new ClassReader(record); - return true; - } - - /// - /// Reads the next class from the stream. - /// - /// - public static async ValueTask ReadAsync(Stream stream, CancellationToken cancellationToken = default) - { - if (stream is null) - throw new ArgumentNullException(nameof(stream)); - - var reader = PipeReader.Create(stream, new StreamPipeReaderOptions(minimumReadSize: 1, leaveOpen: true)); - - try - { - return await ReadAsync(reader, cancellationToken); - } - catch (Exception e) - { - await reader.CompleteAsync(e); - throw; - } - finally - { - await reader.CompleteAsync(); - } - } - - /// - /// Reads the next class from the stream. - /// - /// - public static ClassReader Read(Stream stream, CancellationToken cancellationToken = default) - { - return ReadAsync(stream, cancellationToken).AsTask().GetAwaiter().GetResult(); - } - - /// - /// Reads the next class from the stream. - /// - /// - public static async ValueTask ReadAsync(PipeReader reader, CancellationToken cancellationToken = default) - { - while (true) - { - var result = await reader.ReadAtLeastAsync(MIN_CLASS_SIZE, cancellationToken); - if (result.IsCanceled) - throw new OperationCanceledException(); - - // attempt to read at least one class - if (TryRead(result.Buffer, out var clazz, out var consumed, out var examined) == false) - { - reader.AdvanceTo(consumed, examined); - - // we couldn't read a full class, and the pipe is at the end - if (result.IsCompleted) - throw new InvalidClassException("End of stream reached before valid class."); - - continue; - } - - reader.AdvanceTo(consumed, examined); - return clazz; - } - } - - internal int MAX_STACK_ALLOC = 1024; - - ClassConstantReader @this; - ClassConstantReader super; - ConstantReaderCollection constants; - InterfaceReaderCollection interfaces; - FieldReaderCollection fields; - MethodReaderCollection methods; - AttributeReaderCollection attributes; - - /// - /// Initializes a new instance. - /// - /// - internal ClassReader(ClassRecord record) : - base(null, record) - { - - } - - /// - /// Gets the version of the class. - /// - public ClassFormatVersion Version => new ClassFormatVersion(Record.MajorVersion, Record.MinorVersion); - - /// - /// Gets the set of constants declared by the class. - /// - public ConstantReaderCollection Constants => LazyGet(ref constants, () => new ConstantReaderCollection(this, Record.Constants)); - - /// - /// Gets the access flags of the class. - /// - public AccessFlag AccessFlags => Record.AccessFlags; - - /// - /// Gets the name of the class. - /// - public ClassConstantReader This => LazyGet(ref @this, () => Constants.Get(Record.ThisClassIndex)); - - /// - /// Gets the name of the super class. - /// - public ClassConstantReader Super => LazyGet(ref super, () => Constants.Get(Record.SuperClassIndex)); - - /// - /// Gets the set of the interfaces implemented by this class. - /// - public InterfaceReaderCollection Interfaces => LazyGet(ref interfaces, () => new InterfaceReaderCollection(this, Record.Interfaces)); - - /// - /// Gets the set of fields declared by the class. - /// - public FieldReaderCollection Fields => LazyGet(ref fields, () => new FieldReaderCollection(this, Record.Fields)); - - /// - /// Gets the set of methods declared by the class. - /// - public MethodReaderCollection Methods => LazyGet(ref methods, () => new MethodReaderCollection(this, Record.Methods)); - - /// - /// Gets the dictionary of attributes declared by the class. - /// - public AttributeReaderCollection Attributes => LazyGet(ref attributes, () => new AttributeReaderCollection(this, Record.Attributes)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/CodeAttributeReader.cs b/src/IKVM.ByteCode/Reading/CodeAttributeReader.cs deleted file mode 100644 index e311b7ff24..0000000000 --- a/src/IKVM.ByteCode/Reading/CodeAttributeReader.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; - -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class CodeAttributeReader : AttributeReader - { - - AttributeReaderCollection attributes; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal CodeAttributeReader(ClassReader declaringClass, AttributeInfoReader info, CodeAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - public ushort MaxStack => Record.MaxStack; - - public ushort MaxLocals => Record.MaxLocals; - - /// - /// Gets the byte code. - /// - public ReadOnlyMemory Code => Record.Code; - - public IReadOnlyList ExceptionTable => Record.ExceptionTable; - - /// - /// Gets the set of attributes applied to this attribute. - /// - public AttributeReaderCollection Attributes => LazyGet(ref attributes, () => new AttributeReaderCollection(DeclaringClass, Record.Attributes)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ConstantReader.cs b/src/IKVM.ByteCode/Reading/ConstantReader.cs deleted file mode 100644 index b3c17646a6..0000000000 --- a/src/IKVM.ByteCode/Reading/ConstantReader.cs +++ /dev/null @@ -1,83 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Provides static methods for reading constants. - /// - internal static class ConstantReader - { - - /// - /// Initializes a from a . - /// - /// - /// - /// - /// - /// - internal static IConstantReader Read(ClassReader declaringClass, ushort index, ConstantRecord record) => record switch - { - Utf8ConstantRecord c => new Utf8ConstantReader(declaringClass, index, c), - IntegerConstantRecord c => new IntegerConstantReader(declaringClass, index, c), - FloatConstantRecord c => new FloatConstantReader(declaringClass, index, c), - LongConstantRecord c => new LongConstantReader(declaringClass, index, c), - DoubleConstantRecord c => new DoubleConstantReader(declaringClass, index, c), - ClassConstantRecord c => new ClassConstantReader(declaringClass, index, c), - StringConstantRecord c => new StringConstantReader(declaringClass, index, c), - FieldrefConstantRecord c => new FieldrefConstantReader(declaringClass, index, c), - MethodrefConstantRecord c => new MethodrefConstantReader(declaringClass, index, c), - InterfaceMethodrefConstantRecord c => new InterfaceMethodrefConstantReader(declaringClass, index, c), - NameAndTypeConstantRecord c => new NameAndTypeConstantReader(declaringClass, index, c), - MethodHandleConstantRecord c => new MethodHandleConstantReader(declaringClass, index, c), - MethodTypeConstantRecord c => new MethodTypeConstantReader(declaringClass, index, c), - DynamicConstantRecord c => new DynamicConstantReader(declaringClass, index, c), - InvokeDynamicConstantRecord c => new InvokeDynamicConstantReader(declaringClass, index, c), - ModuleConstantRecord c => new ModuleConstantReader(declaringClass, index, c), - PackageConstantRecord c => new PackageConstantReader(declaringClass, index, c), - _ => throw new ByteCodeException($"Invalid constant type: {record.GetType().Name}"), - }; - - } - - /// - /// Base type for constant readers. - /// - /// - internal abstract class ConstantReader : ReaderBase, IConstantReader - where TRecord : ConstantRecord - { - - readonly ushort index; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - protected ConstantReader(ClassReader declaringClass, ushort index, TRecord record) : - base(declaringClass, record) - { - this.index = index; - } - - /// - /// Gets the index of the constant. - /// - public ushort Index => index; - - /// - /// Returns true if the constant is considered loadable according to the JVM specification. - /// - public virtual bool IsLoadable => false; - - /// - /// Gets the underlying constant being read. - /// - TRecord IConstantReader.Record => Record; - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ConstantReaderCollection.cs b/src/IKVM.ByteCode/Reading/ConstantReaderCollection.cs deleted file mode 100644 index 94ab8206a5..0000000000 --- a/src/IKVM.ByteCode/Reading/ConstantReaderCollection.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; - -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of constants. - /// - internal sealed class ConstantReaderCollection : LazyReaderList - { - - readonly ClassReader declaringClass; - - /// - /// Initializes a new instance. - /// - /// - /// - internal ConstantReaderCollection(ClassReader declaringClass, ConstantRecord[] records) : - base(declaringClass, records, 0) - { - this.declaringClass = declaringClass ?? throw new ArgumentNullException(nameof(declaringClass)); - } - - /// - /// Creates a new reader for the given record. - /// - /// - /// - /// - protected override IConstantReader CreateReader(int index, ConstantRecord record) - { - return record is not null ? ConstantReader.Read(declaringClass, (ushort)index, record) : null; - } - - /// - /// Attempts to get the constant reader at the specified index. - /// - /// - /// - /// - public TReader Get(int index) - where TReader : class, IConstantReader - { - if (index == 0) - return null; - - try - { - return this[index] as TReader ?? throw new ByteCodeException($"Invalid constant resolution. Reader at index {index} is not a {typeof(TReader).Name}."); - } - catch (ArgumentOutOfRangeException e) - { - throw new ByteCodeException($"Invalid constant resolution. Reader at index {index} is not valid.", e); - } - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ConstantValueAttributeReader.cs b/src/IKVM.ByteCode/Reading/ConstantValueAttributeReader.cs deleted file mode 100644 index 71f6d074a0..0000000000 --- a/src/IKVM.ByteCode/Reading/ConstantValueAttributeReader.cs +++ /dev/null @@ -1,37 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ConstantValueAttributeReader : AttributeReader - { - - object value; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal ConstantValueAttributeReader(ClassReader declaringClass, AttributeInfoReader info, ConstantValueAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - public object Value => value ??= ResolveValue(); - - object ResolveValue() => DeclaringClass.Constants.Get(Record.ValueIndex) switch - { - LongConstantReader l => l.Value, - FloatConstantReader f => f.Value, - DoubleConstantReader d => d.Value, - IntegerConstantReader i => i.Value, - StringConstantReader s => s.Value, - _ => throw new ByteCodeException("Invalid constant type for constant attribute."), - }; - - } - -} diff --git a/src/IKVM.ByteCode/Reading/DelegateLazyReaderList.cs b/src/IKVM.ByteCode/Reading/DelegateLazyReaderList.cs deleted file mode 100644 index 390811aa1d..0000000000 --- a/src/IKVM.ByteCode/Reading/DelegateLazyReaderList.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Concrete lazy list implementation that creates readers lazily based on a delegate. - /// - /// - /// - internal sealed class DelegateLazyReaderList : LazyReaderList - where TReader : class - { - - readonly Func create; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - /// - public DelegateLazyReaderList(ClassReader declaringClass, TSource[] sources, Func create) : - base(declaringClass, sources) - { - this.create = create ?? throw new ArgumentNullException(nameof(create)); - } - - /// - /// Creates the new reader. - /// - /// - /// - /// - protected override TReader CreateReader(int index, TSource source) => create(index, source); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/DeprecatedAttributeReader.cs b/src/IKVM.ByteCode/Reading/DeprecatedAttributeReader.cs deleted file mode 100644 index e3c1d966d4..0000000000 --- a/src/IKVM.ByteCode/Reading/DeprecatedAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal class DeprecatedAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal DeprecatedAttributeReader(ClassReader declaringClass, AttributeInfoReader info, DeprecatedAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/DoubleConstantReader.cs b/src/IKVM.ByteCode/Reading/DoubleConstantReader.cs deleted file mode 100644 index 78e4fbfb65..0000000000 --- a/src/IKVM.ByteCode/Reading/DoubleConstantReader.cs +++ /dev/null @@ -1,33 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class DoubleConstantReader : ConstantReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public DoubleConstantReader(ClassReader declaringClass, ushort index, DoubleConstantRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the value of the constant. - /// - public double Value => Record.Value; - - /// - /// Returns whether or not this constant is loadable. - /// - public override bool IsLoadable => DeclaringClass.Version >= new ClassFormatVersion(45, 3); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/DynamicConstantReader.cs b/src/IKVM.ByteCode/Reading/DynamicConstantReader.cs deleted file mode 100644 index b0e9d83b5e..0000000000 --- a/src/IKVM.ByteCode/Reading/DynamicConstantReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class DynamicConstantReader : ConstantReader - { - - NameAndTypeConstantReader nameAndType; - - /// - /// Initializes a new instance. - /// - /// - /// - public DynamicConstantReader(ClassReader declaringClass, ushort index, DynamicConstantRecord record) : - base(declaringClass, index, record) - { - - } - - public ushort BootstrapMethodAttributeIndex => Record.BootstrapMethodAttributeIndex; - - public NameAndTypeConstantReader NameAndType => LazyGet(ref nameAndType, () => DeclaringClass.Constants.Get(Record.NameAndTypeIndex)); - - public override bool IsLoadable => DeclaringClass.Version >= new ClassFormatVersion(55, 0); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ElementValueAnnotationReader.cs b/src/IKVM.ByteCode/Reading/ElementValueAnnotationReader.cs deleted file mode 100644 index f5987d5f47..0000000000 --- a/src/IKVM.ByteCode/Reading/ElementValueAnnotationReader.cs +++ /dev/null @@ -1,31 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ElementValueAnnotationReader : ElementValueReader - { - - AnnotationReader annotation; - - /// - /// Initializes a new instance. - /// - /// - /// - public ElementValueAnnotationReader(ClassReader declaringClass, ElementValueRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the annotation included with this element value. - /// - public AnnotationReader Annotation => LazyGet(ref annotation, () => new AnnotationReader(DeclaringClass, ValueRecord.Annotation)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/ElementValueArrayReader.cs b/src/IKVM.ByteCode/Reading/ElementValueArrayReader.cs deleted file mode 100644 index ef7a28b56b..0000000000 --- a/src/IKVM.ByteCode/Reading/ElementValueArrayReader.cs +++ /dev/null @@ -1,28 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ElementValueArrayReader : ElementValueReader - { - - ElementValueReaderCollection values; - - /// - /// Initializes a new instance. - /// - /// - /// - public ElementValueArrayReader(ClassReader declaringClass, ElementValueRecord record) : - base(declaringClass, record) - { - - } - - public ElementValueReaderCollection Values => LazyGet(ref values, () => new ElementValueReaderCollection(DeclaringClass, ValueRecord.Values)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ElementValueClassReader.cs b/src/IKVM.ByteCode/Reading/ElementValueClassReader.cs deleted file mode 100644 index 69a780d5da..0000000000 --- a/src/IKVM.ByteCode/Reading/ElementValueClassReader.cs +++ /dev/null @@ -1,31 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ElementValueClassReader : ElementValueReader - { - - Utf8ConstantReader clazz; - - /// - /// Initializes a new instance. - /// - /// - /// - public ElementValueClassReader(ClassReader declaringClass, ElementValueRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the class included with this element value. - /// - public Utf8ConstantReader Class => LazyGet(ref clazz, () => DeclaringClass.Constants.Get(ValueRecord.ClassIndex)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/ElementValueConstantReader.cs b/src/IKVM.ByteCode/Reading/ElementValueConstantReader.cs deleted file mode 100644 index 1abc7f9c87..0000000000 --- a/src/IKVM.ByteCode/Reading/ElementValueConstantReader.cs +++ /dev/null @@ -1,55 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ElementValueConstantReader : ElementValueReader - { - - IConstantReader value; - - /// - /// Initializes a new instance. - /// - /// - /// - public ElementValueConstantReader(ClassReader declaringClass, ElementValueRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the type of the element value. - /// - public ElementValueTag Tag => Record.Tag; - - /// - /// Gets the constant value. - /// - public IConstantReader Value => LazyGet(ref value, ResolveValue); - - /// - /// Gets the value of the constant element. - /// - /// - /// - IConstantReader ResolveValue() => Record.Tag switch - { - ElementValueTag.Byte => DeclaringClass.Constants.Get(ValueRecord.Index), - ElementValueTag.Char => DeclaringClass.Constants.Get(ValueRecord.Index), - ElementValueTag.Double => DeclaringClass.Constants.Get(ValueRecord.Index), - ElementValueTag.Float => DeclaringClass.Constants.Get(ValueRecord.Index), - ElementValueTag.Integer => DeclaringClass.Constants.Get(ValueRecord.Index), - ElementValueTag.Long => DeclaringClass.Constants.Get(ValueRecord.Index), - ElementValueTag.Short => DeclaringClass.Constants.Get(ValueRecord.Index), - ElementValueTag.Boolean => DeclaringClass.Constants.Get(ValueRecord.Index), - ElementValueTag.String => DeclaringClass.Constants.Get(ValueRecord.Index), - _ => throw new ByteCodeException($"Unknown element value constant tag '{Record.Tag}'.") - }; - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/ElementValueEnumConstantReader.cs b/src/IKVM.ByteCode/Reading/ElementValueEnumConstantReader.cs deleted file mode 100644 index 46c3f9d31e..0000000000 --- a/src/IKVM.ByteCode/Reading/ElementValueEnumConstantReader.cs +++ /dev/null @@ -1,31 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ElementValueEnumConstantReader : ElementValueReader - { - - Utf8ConstantReader typeName; - Utf8ConstantReader constantName; - - /// - /// Initializes a new instance. - /// - /// - /// - public ElementValueEnumConstantReader(ClassReader declaringClass, ElementValueRecord record) : - base(declaringClass, record) - { - - } - - public Utf8ConstantReader TypeName => LazyGet(ref typeName, () => DeclaringClass.Constants.Get(ValueRecord.TypeNameIndex)); - - public Utf8ConstantReader ConstantName => LazyGet(ref constantName, () => DeclaringClass.Constants.Get(ValueRecord.ConstantNameIndex)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/ElementValuePairReaderCollection.cs b/src/IKVM.ByteCode/Reading/ElementValuePairReaderCollection.cs deleted file mode 100644 index 74b528ce5b..0000000000 --- a/src/IKVM.ByteCode/Reading/ElementValuePairReaderCollection.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Collections.Generic; - -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of element value data. - /// - internal sealed class ElementValueKeyReaderCollection : LazyNamedReaderDictionary - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public ElementValueKeyReaderCollection(ClassReader declaringClass, ElementValuePairRecord[] records, int minIndex = 0) : - base(declaringClass, records, minIndex) - { - - } - - /// - /// Creates a new reader for the given record at the specified index. - /// - /// - /// - /// - protected override ElementValueReader CreateReader(int index, ElementValuePairRecord record) - { - return ElementValueReader.Resolve(DeclaringClass, record.Value); - } - - /// - /// Gets the key for the given record and the specified index. - /// - /// - /// - /// - protected override string GetName(int index, ElementValuePairRecord record) - { - return DeclaringClass.Constants.Get(record.NameIndex).Value; - } - - /// - /// Gets an enumerator over the items in this collection. - /// - /// - public new IEnumerator> GetEnumerator() => ((IEnumerable>)this).GetEnumerator(); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ElementValueReaderCollection.cs b/src/IKVM.ByteCode/Reading/ElementValueReaderCollection.cs deleted file mode 100644 index 50423c6bc2..0000000000 --- a/src/IKVM.ByteCode/Reading/ElementValueReaderCollection.cs +++ /dev/null @@ -1,30 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of attribute data. - /// - internal sealed class ElementValueReaderCollection : LazyReaderList - { - - /// - /// Initializes a new instance. - /// - /// - /// - public ElementValueReaderCollection(ClassReader delcaringClass, ElementValueRecord[] records) : - base(delcaringClass, records) - { - - } - - protected override ElementValueReader CreateReader(int index, ElementValueRecord record) - { - return ElementValueReader.Resolve(DeclaringClass, record); - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ElementValueValueReader.cs b/src/IKVM.ByteCode/Reading/ElementValueValueReader.cs deleted file mode 100644 index eab07860dd..0000000000 --- a/src/IKVM.ByteCode/Reading/ElementValueValueReader.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; - -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal abstract class ElementValueReader : ReaderBase - { - - /// - /// Resolves the given element value record to a reader type. - /// - /// - /// - /// - /// - public static ElementValueReader Resolve(ClassReader declaringClass, ElementValueRecord record) => record.Value switch - { - ElementValueAnnotationValueRecord => new ElementValueAnnotationReader(declaringClass, record), - ElementValueArrayValueRecord => new ElementValueArrayReader(declaringClass, record), - ElementValueClassValueRecord => new ElementValueClassReader(declaringClass, record), - ElementValueConstantValueRecord => new ElementValueConstantReader(declaringClass, record), - ElementValueEnumConstantValueRecord => new ElementValueEnumConstantReader(declaringClass, record), - _ => throw new ByteCodeException("Cannot resolve element value reader."), - }; - - /// - /// Initializes a new instance. - /// - /// - /// - protected ElementValueReader(ClassReader declaringClass, ElementValueRecord record) : - base(declaringClass, record) - { - - } - - } - - internal abstract class ElementValueReader : ElementValueReader - where TValueRecord : ElementValueValueRecord - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - protected ElementValueReader(ClassReader declaringClass, ElementValueRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the underlying value record. - /// - public TValueRecord ValueRecord => (TValueRecord)Record.Value; - - } - -} diff --git a/src/IKVM.ByteCode/Reading/EnclosingMethodAttributeReader.cs b/src/IKVM.ByteCode/Reading/EnclosingMethodAttributeReader.cs deleted file mode 100644 index 83f98567c5..0000000000 --- a/src/IKVM.ByteCode/Reading/EnclosingMethodAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class EnclosingMethodAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal EnclosingMethodAttributeReader(ClassReader declaringClass, AttributeInfoReader info, EnclosingMethodAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ExceptionsAttributeReader.cs b/src/IKVM.ByteCode/Reading/ExceptionsAttributeReader.cs deleted file mode 100644 index 5b115ba3fc..0000000000 --- a/src/IKVM.ByteCode/Reading/ExceptionsAttributeReader.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; - -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ExceptionsAttributeReader : AttributeReader - { - - DelegateLazyReaderList exceptions; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal ExceptionsAttributeReader(ClassReader declaringClass, AttributeInfoReader info, ExceptionsAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - /// - /// Gets the names of the exceptions. - /// - public IReadOnlyList Exceptions => LazyGet(ref exceptions, () => new DelegateLazyReaderList(DeclaringClass, Record.ExceptionsIndexes, (_, index) => DeclaringClass.Constants.Get(index))); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/FieldOrMethodReader.cs b/src/IKVM.ByteCode/Reading/FieldOrMethodReader.cs deleted file mode 100644 index 2edbe9e5bd..0000000000 --- a/src/IKVM.ByteCode/Reading/FieldOrMethodReader.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace IKVM.ByteCode.Reading -{ - - internal abstract class FieldOrMethodReader : ReaderBase - { - - /// - /// Initializes a new instance. - /// - /// - /// - protected FieldOrMethodReader(ClassReader declaringClass, TRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the access flags of this field or method. - /// - public abstract AccessFlag AccessFlags { get; } - - /// - /// Gets the name of this field or method. - /// - public abstract Utf8ConstantReader Name { get; } - - /// - /// Gets the descriptor of this field or method. - /// - public abstract Utf8ConstantReader Descriptor { get; } - - /// - /// Gets the attributes of this field or method. - /// - public abstract AttributeReaderCollection Attributes { get; } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/FieldReader.cs b/src/IKVM.ByteCode/Reading/FieldReader.cs deleted file mode 100644 index d86faf7b21..0000000000 --- a/src/IKVM.ByteCode/Reading/FieldReader.cs +++ /dev/null @@ -1,48 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal class FieldReader : FieldOrMethodReader - { - - Utf8ConstantReader name; - Utf8ConstantReader descriptor; - AttributeReaderCollection attributes; - - /// - /// Initializes a new instance. - /// - /// - /// - internal FieldReader(ClassReader declaringClass, FieldRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the access flags of the field. - /// - public override AccessFlag AccessFlags => Record.AccessFlags; - - /// - /// Gets the name of the field. - /// - public override Utf8ConstantReader Name => LazyGet(ref name, () => DeclaringClass.Constants.Get(Record.NameIndex)); - - /// - /// Gets the descriptor of the field. - /// - public override Utf8ConstantReader Descriptor => LazyGet(ref descriptor, () => DeclaringClass.Constants.Get(Record.DescriptorIndex)); - - /// - /// Gets the attributes of the field. - /// - public override AttributeReaderCollection Attributes => LazyGet(ref attributes, () => new AttributeReaderCollection(DeclaringClass, Record.Attributes)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/FieldReaderCollection.cs b/src/IKVM.ByteCode/Reading/FieldReaderCollection.cs deleted file mode 100644 index a257f86613..0000000000 --- a/src/IKVM.ByteCode/Reading/FieldReaderCollection.cs +++ /dev/null @@ -1,47 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of fields. - /// - internal sealed class FieldReaderCollection : LazyNamedReaderDictionary - { - - /// - /// Initializes a new instance. - /// - /// - /// - internal FieldReaderCollection(ClassReader declaringClass, FieldRecord[] records) : - base(declaringClass, records) - { - - } - - /// - /// Creates a new field reader. - /// - /// - /// - /// - protected override FieldReader CreateReader(int index, FieldRecord record) - { - return new FieldReader(DeclaringClass, record); - } - - /// - /// Gets the key for the specified record. - /// - /// - /// - /// - protected override string GetName(int index, FieldRecord record) - { - return DeclaringClass.Constants.Get(record.NameIndex).Value; - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/FieldrefConstantReader.cs b/src/IKVM.ByteCode/Reading/FieldrefConstantReader.cs deleted file mode 100644 index 689d36bc45..0000000000 --- a/src/IKVM.ByteCode/Reading/FieldrefConstantReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal class FieldrefConstantReader : RefConstantReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public FieldrefConstantReader(ClassReader declaringClass, ushort index, FieldrefConstantRecord record) : - base(declaringClass, index, record) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/FloatConstantReader.cs b/src/IKVM.ByteCode/Reading/FloatConstantReader.cs deleted file mode 100644 index 6cd95da0c5..0000000000 --- a/src/IKVM.ByteCode/Reading/FloatConstantReader.cs +++ /dev/null @@ -1,33 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class FloatConstantReader : ConstantReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public FloatConstantReader(ClassReader declaringClass, ushort index, FloatConstantRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the value of the constant. - /// - public float Value => Record.Value; - - /// - /// Returns true if this constant is loadable. - /// - public override bool IsLoadable => DeclaringClass.Version >= new ClassFormatVersion(45, 3); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/IConstantReader.cs b/src/IKVM.ByteCode/Reading/IConstantReader.cs deleted file mode 100644 index d9f1b8b516..0000000000 --- a/src/IKVM.ByteCode/Reading/IConstantReader.cs +++ /dev/null @@ -1,38 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Interface supported by all of the constant readers. - /// - internal interface IConstantReader - { - - /// - /// Gets the index of this constant. - /// - ushort Index { get; } - - /// - /// Returns true if this constant is loadable. - /// - bool IsLoadable { get; } - - } - - /// - /// Interface supported by all of the constant readers. - /// - internal interface IConstantReader : IConstantReader - where TRecord : ConstantRecord - { - - /// - /// Gets the record. - /// - TRecord Record { get; } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/IRefConstantReader.cs b/src/IKVM.ByteCode/Reading/IRefConstantReader.cs deleted file mode 100644 index 1e97bffcef..0000000000 --- a/src/IKVM.ByteCode/Reading/IRefConstantReader.cs +++ /dev/null @@ -1,24 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Interface supported by all of the readers for Ref constants. - /// - internal interface IRefConstantReader : IConstantReader - { - - /// - /// Gets the class name of the reference. - /// - ClassConstantReader Class { get; } - - /// - /// Gets the name and type reference. - /// - NameAndTypeConstantReader NameAndType { get; } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/InnerClassesAttributeItemReader.cs b/src/IKVM.ByteCode/Reading/InnerClassesAttributeItemReader.cs deleted file mode 100644 index 393ac5bbe9..0000000000 --- a/src/IKVM.ByteCode/Reading/InnerClassesAttributeItemReader.cs +++ /dev/null @@ -1,48 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class InnerClassesAttributeItemReader : ReaderBase - { - - ClassConstantReader innerClass; - ClassConstantReader outerClass; - Utf8ConstantReader innerName; - - /// - /// Initializes a new instance. - /// - /// - /// - public InnerClassesAttributeItemReader(ClassReader declaringClass, InnerClassesAttributeItemRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the name of the inner class. - /// - public ClassConstantReader InnerClass => LazyGet(ref innerClass, () => DeclaringClass.Constants.Get(Record.InnerClassIndex)); - - /// - /// Gets the name of the outer class. - /// - public ClassConstantReader OuterClass => LazyGet(ref outerClass, () => DeclaringClass.Constants.Get(Record.OuterClassIndex)); - - /// - /// Gets the inner name. - /// - public Utf8ConstantReader InnerName => LazyGet(ref innerName, () => DeclaringClass.Constants.Get(Record.InnerNameIndex)); - - /// - /// Gets the access flags of the inner class. - /// - public AccessFlag InnerClassAccessFlags => Record.InnerClassAccessFlags; - - } - -} diff --git a/src/IKVM.ByteCode/Reading/InnerClassesAttributeReader.cs b/src/IKVM.ByteCode/Reading/InnerClassesAttributeReader.cs deleted file mode 100644 index b26ebcff26..0000000000 --- a/src/IKVM.ByteCode/Reading/InnerClassesAttributeReader.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; - -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class InnerClassesAttributeReader : AttributeReader - { - - IReadOnlyList items; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public InnerClassesAttributeReader(ClassReader declaringClass, AttributeInfoReader info, InnerClassesAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - /// - /// Gets the items on the attribute. - /// - public IReadOnlyList Items => LazyGet(ref items, () => new DelegateLazyReaderList(DeclaringClass, Record.Items, (_, record) => new InnerClassesAttributeItemReader(DeclaringClass, record))); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/IntegerConstantReader.cs b/src/IKVM.ByteCode/Reading/IntegerConstantReader.cs deleted file mode 100644 index a0c172008b..0000000000 --- a/src/IKVM.ByteCode/Reading/IntegerConstantReader.cs +++ /dev/null @@ -1,31 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class IntegerConstantReader : ConstantReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public IntegerConstantReader(ClassReader declaringClass, ushort index, IntegerConstantRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the value of the constant. - /// - public int Value => Record.Value; - - /// - public override bool IsLoadable => DeclaringClass.Version >= new ClassFormatVersion(45, 3); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/InterfaceMethodrefConstantReader.cs b/src/IKVM.ByteCode/Reading/InterfaceMethodrefConstantReader.cs deleted file mode 100644 index c1a9d9fa9d..0000000000 --- a/src/IKVM.ByteCode/Reading/InterfaceMethodrefConstantReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class InterfaceMethodrefConstantReader : RefConstantReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public InterfaceMethodrefConstantReader(ClassReader declaringClass, ushort index, InterfaceMethodrefConstantRecord record) : - base(declaringClass, index, record) - { - - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/InterfaceReader.cs b/src/IKVM.ByteCode/Reading/InterfaceReader.cs deleted file mode 100644 index 05b01b1f76..0000000000 --- a/src/IKVM.ByteCode/Reading/InterfaceReader.cs +++ /dev/null @@ -1,31 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class InterfaceReader : ReaderBase - { - - ClassConstantReader clazz; - - /// - /// Initializes a new instance. - /// - /// - /// - internal InterfaceReader(ClassReader declaringClass, InterfaceRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the name of the interface. - /// - public ClassConstantReader Class => LazyGet(ref clazz, () => DeclaringClass.Constants.Get(Record.ClassIndex)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/InterfaceReaderCollection.cs b/src/IKVM.ByteCode/Reading/InterfaceReaderCollection.cs deleted file mode 100644 index 023d3c3126..0000000000 --- a/src/IKVM.ByteCode/Reading/InterfaceReaderCollection.cs +++ /dev/null @@ -1,46 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of method data. - /// - internal sealed class InterfaceReaderCollection : LazyNamedReaderDictionary - { - - /// - /// Initializes a new instance. - /// - /// - /// - internal InterfaceReaderCollection(ClassReader declaringClass, InterfaceRecord[] records) : - base(declaringClass, records) - { - - } - - /// - /// Creates a new interface reader. - /// - /// - /// - protected override InterfaceReader CreateReader(int index, InterfaceRecord record) - { - return new InterfaceReader(DeclaringClass, record); - } - - /// - /// Gets the name of the interface. - /// - /// - /// - /// - protected override string GetName(int index, InterfaceRecord record) - { - return DeclaringClass.Constants.Get(record.ClassIndex).Name.Value; - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/InvokeDynamicConstantReader.cs b/src/IKVM.ByteCode/Reading/InvokeDynamicConstantReader.cs deleted file mode 100644 index 6fb3584726..0000000000 --- a/src/IKVM.ByteCode/Reading/InvokeDynamicConstantReader.cs +++ /dev/null @@ -1,37 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class InvokeDynamicConstantReader : ConstantReader - { - - NameAndTypeConstantReader nameAndType; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public InvokeDynamicConstantReader(ClassReader owner, ushort index, InvokeDynamicConstantRecord record) : - base(owner, index, record) - { - - } - - /// - /// Gets the index into the BootstrapMethod table that is referenced by this constant. - /// - public ushort BootstrapMethodAttributeIndex => Record.BootstrapMethodAttributeIndex; - - /// - /// Gets the name of the InvokeDynamic constant. - /// - public NameAndTypeConstantReader NameAndType => LazyGet(ref nameAndType, () => DeclaringClass.Constants.Get(Record.NameAndTypeIndex)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/LazyNamedReaderDictionary.cs b/src/IKVM.ByteCode/Reading/LazyNamedReaderDictionary.cs deleted file mode 100644 index 17fb0dbe96..0000000000 --- a/src/IKVM.ByteCode/Reading/LazyNamedReaderDictionary.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Base implementation of a dictionary that generates reader instances on demand. - /// - /// - /// - internal abstract class LazyNamedReaderDictionary : IReadOnlyDictionary - where TReader : class - { - - readonly ClassReader declaringClass; - readonly TRecord[] records; - readonly int minIndex; - - TReader[] readers; - string[] names; - - /// - /// Initializes a new instance. - /// - /// - /// - public LazyNamedReaderDictionary(ClassReader declaringClass, TRecord[] records, int minIndex = 0) - { - this.declaringClass = declaringClass ?? throw new ArgumentNullException(nameof(declaringClass)); - this.records = records ?? throw new ArgumentNullException(nameof(records)); - this.minIndex = minIndex; - } - - /// - /// Gets the underlying records that make up the list. - /// - protected IReadOnlyList Records => records; - - /// - /// Creates the appropriate reader. - /// - /// - /// - /// - protected abstract TReader CreateReader(int index, TRecord record); - - /// - /// Gets the name for the given record. - /// - /// - /// - /// - protected abstract string GetName(int index, TRecord record); - - /// - /// Resolves the specified reader at the given index. - /// - /// - TReader ResolveReader(int index) - { - if (index < minIndex || index >= records.Length) - throw new ArgumentOutOfRangeException(nameof(index)); - - // initialize cache if not initialized - if (readers == null) - Interlocked.CompareExchange(ref readers, new TReader[records.Length], null); - - // consult cache - if (readers[index] is TReader reader) - return reader; - - // atomic set, only one winner - Interlocked.CompareExchange(ref readers[index], CreateReader(index, records[index]), null); - return readers[index]; - } - - /// - /// Resolves the specified name at the given index. - /// - /// - /// - /// - string ResolveName(int index) - { - if (index < minIndex || index >= records.Length) - throw new ArgumentOutOfRangeException(nameof(index)); - - // initialize cache if not initialized - if (names == null) - Interlocked.CompareExchange(ref names, new string[records.Length], null); - - // consult cache - if (names[index] is string name) - return name; - - // atomic set, only one winner - Interlocked.CompareExchange(ref names[index], GetName(index, records[index]), null); - return names[index]; - } - - /// - /// Gets the class that declared this list. - /// - public ClassReader DeclaringClass => declaringClass; - - /// - /// Gets the reader at the specified index. - /// - /// - /// - public TReader this[int index] => ResolveReader(index); - - /// - /// Gets the reader with the specified name. - /// - /// - /// - public TReader this[string name] => Enumerable.Range(minIndex, records.Length).Where(i => ResolveName(i) == name).Select(ResolveReader).FirstOrDefault() ?? throw new KeyNotFoundException(); - - /// - /// Gets the count of readers. - /// - public int Count => records.Length; - - /// - /// Attempts to get the value at the specified index, or returns the default value if out of range. - /// - /// - /// - /// - public bool TryGet(int index, out TReader value) - { - value = default; - - if (index < minIndex || index >= records.Length) - return false; - - value = this[index]; - return true; - } - - /// - /// Attempts to get the value at the specified index, or returns the default value if out of range. - /// - /// - /// - /// - public bool TryGet(string name, out TReader value) => (value = Enumerable.Range(minIndex, records.Length).Where(i => ResolveName(i) == name).Select(ResolveReader).FirstOrDefault()) != null; - - /// - /// Returns true if the collection contains a reader with the specified name. - /// - /// - /// - public bool Contains(string name) => Enumerable.Range(minIndex, records.Length).Any(i => ResolveName(i) == name); - - /// - /// Gets an enumerator over each reader. - /// - /// - public IEnumerator GetEnumerator() => Enumerable.Range(minIndex, records.Length).Select(i => this[i]).GetEnumerator(); - - /// - /// Gets an enumerator over each reader. - /// - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - /// Gets an enumerator over each reader. - /// - /// - IEnumerator> IEnumerable>.GetEnumerator() => Enumerable.Range(minIndex, records.Length).Select(i => new KeyValuePair(ResolveName(i), ResolveReader(i))).GetEnumerator(); - - /// - /// Gets all of the available keys. - /// - IEnumerable IReadOnlyDictionary.Keys => Enumerable.Range(minIndex, records.Length).Select(ResolveName); - - /// - /// Gets all of the available values. - /// - IEnumerable IReadOnlyDictionary.Values => Enumerable.Range(minIndex, records.Length).Select(ResolveReader); - - /// - /// Attempts to retrieve the reader with the specified key. - /// - /// - /// - /// - bool IReadOnlyDictionary.TryGetValue(string key, out TReader value) => TryGet(key, out value); - - /// - /// Returns true if the collection contains the specified key. - /// - /// - /// - bool IReadOnlyDictionary.ContainsKey(string key) => Contains(key); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/LazyReaderList.cs b/src/IKVM.ByteCode/Reading/LazyReaderList.cs deleted file mode 100644 index 2d66ecb31f..0000000000 --- a/src/IKVM.ByteCode/Reading/LazyReaderList.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Base implementation of a list that generates reader instances on demand. - /// - /// - /// - internal abstract class LazyReaderList : IReadOnlyList - where TReader : class - { - - readonly ClassReader declaringClass; - readonly TRecord[] records; - readonly uint minIndex; - - TReader[] readers; - - /// - /// Initializes a new instance. - /// - /// - /// - public LazyReaderList(ClassReader declaringClass, TRecord[] records, uint minIndex = 0) - { - this.declaringClass = declaringClass ?? throw new ArgumentNullException(nameof(declaringClass)); - this.records = records ?? throw new ArgumentNullException(nameof(records)); - this.minIndex = minIndex; - } - - /// - /// Gets the underlying records that make up the list. - /// - protected IReadOnlyList Records => records; - - /// - /// Creates the appropriate reader. - /// - /// - /// - /// - protected abstract TReader CreateReader(int index, TRecord record); - - /// - /// Resolves the specified reader at the given index. - /// - /// - TReader ResolveReader(int index) - { - if (index < minIndex || index >= records.Length) - throw new ArgumentOutOfRangeException(nameof(index)); - - // initialize cache if not initialized - if (readers == null) - Interlocked.CompareExchange(ref readers, new TReader[records.Length], null); - - // consult cache - if (readers[index] is TReader reader) - return reader; - - // atomic set, only one winner - Interlocked.CompareExchange(ref readers[index], CreateReader(index, records[index]), null); - return readers[index]; - } - - /// - /// Gets the class that declared this list. - /// - public ClassReader DeclaringClass => declaringClass; - - /// - /// Gets the reader at the specified index. - /// - /// - /// - public TReader this[int index] => ResolveReader(index); - - /// - /// Gets the count of readers. - /// - public int Count => records.Length; - - /// - /// Gets an enumerator over each reader. - /// - /// - public IEnumerator GetEnumerator() => Enumerable.Range(0, records.Length).Select(i => this[i]).GetEnumerator(); - - /// - /// Gets an enumerator over each reader. - /// - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/LineNumberTableAttributeReader.cs b/src/IKVM.ByteCode/Reading/LineNumberTableAttributeReader.cs deleted file mode 100644 index 35d5977a06..0000000000 --- a/src/IKVM.ByteCode/Reading/LineNumberTableAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class LineNumberTableAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal LineNumberTableAttributeReader(ClassReader declaringClass, AttributeInfoReader info, LineNumberTableAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/LocalVariableTableAttributeReader.cs b/src/IKVM.ByteCode/Reading/LocalVariableTableAttributeReader.cs deleted file mode 100644 index 24876f5b9a..0000000000 --- a/src/IKVM.ByteCode/Reading/LocalVariableTableAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class LocalVariableTableAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal LocalVariableTableAttributeReader(ClassReader declaringClass, AttributeInfoReader info, LocalVariableTableAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/LocalVariableTypeTableAttributeReader.cs b/src/IKVM.ByteCode/Reading/LocalVariableTypeTableAttributeReader.cs deleted file mode 100644 index 6b0794f772..0000000000 --- a/src/IKVM.ByteCode/Reading/LocalVariableTypeTableAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class LocalVariableTypeTableAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal LocalVariableTypeTableAttributeReader(ClassReader declaringClass, AttributeInfoReader info, LocalVariableTypeTableAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/LongConstantReader.cs b/src/IKVM.ByteCode/Reading/LongConstantReader.cs deleted file mode 100644 index 4cf3ee55fb..0000000000 --- a/src/IKVM.ByteCode/Reading/LongConstantReader.cs +++ /dev/null @@ -1,34 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class LongConstantReader : ConstantReader - { - - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public LongConstantReader(ClassReader declaringClass, ushort index, LongConstantRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the value of the constant. - /// - public long Value => Record.Value; - - /// - /// Returns true if this constant is loadable. - /// - public override bool IsLoadable => DeclaringClass.Version >= new ClassFormatVersion(45, 3); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/MethodHandleConstantReader.cs b/src/IKVM.ByteCode/Reading/MethodHandleConstantReader.cs deleted file mode 100644 index 0c1d7bfe30..0000000000 --- a/src/IKVM.ByteCode/Reading/MethodHandleConstantReader.cs +++ /dev/null @@ -1,42 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class MethodHandleConstantReader : ConstantReader - { - - IRefConstantReader reference; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public MethodHandleConstantReader(ClassReader declaringClass, ushort index, MethodHandleConstantRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the kind of this reference. - /// - public ReferenceKind ReferenceKind => Record.Kind; - - /// - /// Gets the constant refered to by this MethodHandle. - /// - public IRefConstantReader Reference => LazyGet(ref reference, () => DeclaringClass.Constants.Get(Record.Index)); - - /// - /// Returns true if this constant type is loadable. - /// - public override bool IsLoadable => DeclaringClass.Version >= new ClassFormatVersion(51, 0); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/MethodParametersAttributeParameterReader.cs b/src/IKVM.ByteCode/Reading/MethodParametersAttributeParameterReader.cs deleted file mode 100644 index f6b070bbce..0000000000 --- a/src/IKVM.ByteCode/Reading/MethodParametersAttributeParameterReader.cs +++ /dev/null @@ -1,35 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class MethodParametersAttributeParameterReader : ReaderBase - { - - Utf8ConstantReader name; - - /// - /// Initializes a new instance. - /// - /// - public MethodParametersAttributeParameterReader(ClassReader declaringClass, MethodParametersAttributeParameterRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the name of the parameters. - /// - public Utf8ConstantReader Name => LazyGet(ref name, () => DeclaringClass.Constants.Get(Record.NameIndex)); - - /// - /// Gets the access flags of the parameter. - /// - public AccessFlag AccessFlags => Record.AccessFlags; - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/MethodParametersAttributeReader.cs b/src/IKVM.ByteCode/Reading/MethodParametersAttributeReader.cs deleted file mode 100644 index cd0e72ff96..0000000000 --- a/src/IKVM.ByteCode/Reading/MethodParametersAttributeReader.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; - -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class MethodParametersAttributeReader : AttributeReader - { - - IReadOnlyList parameters; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal MethodParametersAttributeReader(ClassReader declaringClass, AttributeInfoReader info, MethodParametersAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - /// - /// Gets the set of annotations described by this attribute. - /// - public IReadOnlyList Parameters => LazyGet(ref parameters, () => new DelegateLazyReaderList(DeclaringClass, Record.Parameters, (_, record) => new MethodParametersAttributeParameterReader(DeclaringClass, record))); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/MethodReader.cs b/src/IKVM.ByteCode/Reading/MethodReader.cs deleted file mode 100644 index f33b567c71..0000000000 --- a/src/IKVM.ByteCode/Reading/MethodReader.cs +++ /dev/null @@ -1,48 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class MethodReader : FieldOrMethodReader - { - - Utf8ConstantReader name; - Utf8ConstantReader descriptor; - AttributeReaderCollection attributes; - - /// - /// Initializes a new instance. - /// - /// - /// - internal MethodReader(ClassReader declaringClass, MethodRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the access flags of the method. - /// - public override AccessFlag AccessFlags => Record.AccessFlags; - - /// - /// Gets the name of the method. - /// - public override Utf8ConstantReader Name => LazyGet(ref name, () => DeclaringClass.Constants.Get(Record.NameIndex)); - - /// - /// Gets the descriptor of the method. - /// - public override Utf8ConstantReader Descriptor => LazyGet(ref descriptor, () => DeclaringClass.Constants.Get(Record.DescriptorIndex)); - - /// - /// Gets the attributes of the method. - /// - public override AttributeReaderCollection Attributes => LazyGet(ref attributes, () => new AttributeReaderCollection(DeclaringClass, Record.Attributes)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/MethodReaderCollection.cs b/src/IKVM.ByteCode/Reading/MethodReaderCollection.cs deleted file mode 100644 index d7aa27772d..0000000000 --- a/src/IKVM.ByteCode/Reading/MethodReaderCollection.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of methods. - /// - internal sealed class MethodReaderCollection : LazyNamedReaderDictionary - { - - /// - /// Initializes a new instance. - /// - /// - /// - internal MethodReaderCollection(ClassReader declaringClass, MethodRecord[] records) : - base(declaringClass, records) - { - - } - - /// - /// Creates a new method reader. - /// - /// - /// - /// - protected override MethodReader CreateReader(int index, MethodRecord record) - { - return new MethodReader(DeclaringClass, record); - } - - /// - /// Gets the name ofr the given record. - /// - /// - /// - /// - protected override string GetName(int index, MethodRecord record) - { - return DeclaringClass.Constants.Get(record.NameIndex).Value; - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/MethodTypeConstantReader.cs b/src/IKVM.ByteCode/Reading/MethodTypeConstantReader.cs deleted file mode 100644 index 6b5b06ee39..0000000000 --- a/src/IKVM.ByteCode/Reading/MethodTypeConstantReader.cs +++ /dev/null @@ -1,37 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class MethodTypeConstantReader : ConstantReader - { - - Utf8ConstantReader type; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public MethodTypeConstantReader(ClassReader owner, ushort index, MethodTypeConstantRecord record) : - base(owner, index, record) - { - - } - - /// - /// Gets the type of this MethodType constant. - /// - public Utf8ConstantReader Type => LazyGet(ref type, () => DeclaringClass.Constants.Get(Record.DescriptorIndex)); - - /// - /// Returns true if this constant is loadable. - /// - public override bool IsLoadable => DeclaringClass.Version >= new ClassFormatVersion(51, 0); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/MethodrefConstantReader.cs b/src/IKVM.ByteCode/Reading/MethodrefConstantReader.cs deleted file mode 100644 index 6c505f4b24..0000000000 --- a/src/IKVM.ByteCode/Reading/MethodrefConstantReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class MethodrefConstantReader : RefConstantReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public MethodrefConstantReader(ClassReader declaringClass, ushort index, MethodrefConstantRecord record) : - base(declaringClass, index, record) - { - - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/ModuleAttributeReader.cs b/src/IKVM.ByteCode/Reading/ModuleAttributeReader.cs deleted file mode 100644 index 068bb57d9b..0000000000 --- a/src/IKVM.ByteCode/Reading/ModuleAttributeReader.cs +++ /dev/null @@ -1,38 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ModuleAttributeReader : AttributeReader - { - - ModuleConstantReader name; - Utf8ConstantReader version; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public ModuleAttributeReader(ClassReader declaringClass, AttributeInfoReader info, ModuleAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - /// - /// Gets the module name. - /// - public ModuleConstantReader Name => LazyGet(ref name, () => DeclaringClass.Constants.Get(Record.NameIndex)); - - /// - /// Gets the module version. - /// - public Utf8ConstantReader Version => LazyGet(ref version, () => DeclaringClass.Constants.Get(Record.VersionIndex)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ModuleConstantReader.cs b/src/IKVM.ByteCode/Reading/ModuleConstantReader.cs deleted file mode 100644 index fd9df1a926..0000000000 --- a/src/IKVM.ByteCode/Reading/ModuleConstantReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ModuleConstantReader : ConstantReader - { - - Utf8ConstantReader name; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public ModuleConstantReader(ClassReader owner, ushort index, ModuleConstantRecord record) : - base(owner, index, record) - { - - } - - /// - /// Gets the name of this module. - /// - public Utf8ConstantReader Name => LazyGet(ref name, () => DeclaringClass.Constants.Get(Record.NameIndex)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ModuleMainClassAttributeReader.cs b/src/IKVM.ByteCode/Reading/ModuleMainClassAttributeReader.cs deleted file mode 100644 index c1b5c8bf31..0000000000 --- a/src/IKVM.ByteCode/Reading/ModuleMainClassAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ModuleMainClassAttributeReader : AttributeReader - { - - /// - /// initializes a new instance. - /// - /// - /// - /// - public ModuleMainClassAttributeReader(ClassReader declaringClass, AttributeInfoReader info, ModuleMainClassAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ModulePackagesAttributeReader.cs b/src/IKVM.ByteCode/Reading/ModulePackagesAttributeReader.cs deleted file mode 100644 index a4604a1b16..0000000000 --- a/src/IKVM.ByteCode/Reading/ModulePackagesAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ModulePackagesAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal ModulePackagesAttributeReader(ClassReader declaringClass, AttributeInfoReader info, ModulePackagesAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/NameAndTypeConstantReader.cs b/src/IKVM.ByteCode/Reading/NameAndTypeConstantReader.cs deleted file mode 100644 index 1f82d0b2e9..0000000000 --- a/src/IKVM.ByteCode/Reading/NameAndTypeConstantReader.cs +++ /dev/null @@ -1,38 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class NameAndTypeConstantReader : ConstantReader - { - - Utf8ConstantReader name; - Utf8ConstantReader type; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public NameAndTypeConstantReader(ClassReader declaringClass, ushort index, NameAndTypeConstantRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the name of this name and type constant. - /// - public Utf8ConstantReader Name => LazyGet(ref name, () => DeclaringClass.Constants.Get(Record.NameIndex)); - - /// - /// Gets the type of this name and type constant. - /// - public Utf8ConstantReader Type => LazyGet(ref type, () => DeclaringClass.Constants.Get(Record.DescriptorIndex)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/NestHostAttributeReader.cs b/src/IKVM.ByteCode/Reading/NestHostAttributeReader.cs deleted file mode 100644 index 12f992a857..0000000000 --- a/src/IKVM.ByteCode/Reading/NestHostAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class NestHostAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public NestHostAttributeReader(ClassReader declaringClass, AttributeInfoReader info, NestHostAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/NestMembersAttributeReader.cs b/src/IKVM.ByteCode/Reading/NestMembersAttributeReader.cs deleted file mode 100644 index ac739175ec..0000000000 --- a/src/IKVM.ByteCode/Reading/NestMembersAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class NestMembersAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public NestMembersAttributeReader(ClassReader declaringClass, AttributeInfoReader info, NestMembersAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/PackageConstantReader.cs b/src/IKVM.ByteCode/Reading/PackageConstantReader.cs deleted file mode 100644 index de63935076..0000000000 --- a/src/IKVM.ByteCode/Reading/PackageConstantReader.cs +++ /dev/null @@ -1,31 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class PackageConstantReader : ConstantReader - { - - Utf8ConstantReader name; - - /// - /// Initializes a new instance. - /// - /// - /// - public PackageConstantReader(ClassReader owner, ushort index, PackageConstantRecord record) : - base(owner, index, record) - { - - } - - /// - /// Gest the name of this package. - /// - public Utf8ConstantReader Name => LazyGet(ref name, () => DeclaringClass.Constants.Get(Record.NameIndex)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ParameterAnnotationReader.cs b/src/IKVM.ByteCode/Reading/ParameterAnnotationReader.cs deleted file mode 100644 index 60c1b292b4..0000000000 --- a/src/IKVM.ByteCode/Reading/ParameterAnnotationReader.cs +++ /dev/null @@ -1,31 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class ParameterAnnotationReader : ReaderBase - { - - AnnotationReaderCollection annotations; - - /// - /// Initializes a new instance. - /// - /// - /// - public ParameterAnnotationReader(ClassReader declaringClass, ParameterAnnotationRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the element values of the annotation. - /// - public AnnotationReaderCollection Annotations => LazyGet(ref annotations, () => new AnnotationReaderCollection(DeclaringClass, Record.Annotations)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ParameterAnnotationReaderCollection.cs b/src/IKVM.ByteCode/Reading/ParameterAnnotationReaderCollection.cs deleted file mode 100644 index 73db31c4a8..0000000000 --- a/src/IKVM.ByteCode/Reading/ParameterAnnotationReaderCollection.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading; - -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of annotation data. - /// - internal sealed class ParameterAnnotationReaderCollection : IReadOnlyList - { - - readonly ClassReader ownerClass; - readonly ParameterAnnotationRecord[] records; - ParameterAnnotationReader[] cache; - - /// - /// Initializes a new instance. - /// - /// - /// - public ParameterAnnotationReaderCollection(ClassReader ownerClass, ParameterAnnotationRecord[] records) - { - this.ownerClass = ownerClass ?? throw new ArgumentNullException(nameof(ownerClass)); - this.records = records ?? throw new ArgumentNullException(nameof(records)); - } - /// - /// Resolves the specified annotation of the class from the records. - /// - /// - ParameterAnnotationReader ResolveAnnotation(int index) - { - if (index < 0 || index >= records.Length) - throw new ArgumentOutOfRangeException(nameof(index)); - - // initialize cache if not initialized - if (cache == null) - Interlocked.CompareExchange(ref cache, new ParameterAnnotationReader[records.Length], null); - - // consult cache - if (cache[index] is ParameterAnnotationReader reader) - return reader; - - reader = new ParameterAnnotationReader(ownerClass, records[index]); - - // atomic set, only one winner - Interlocked.CompareExchange(ref cache[index], reader, null); - return cache[index]; - } - - /// - /// Gets the annotation at the specified index. - /// - /// - /// - public ParameterAnnotationReader this[int index] => ResolveAnnotation(index); - - /// - /// Gets the count of annotations. - /// - public int Count => records.Length; - - /// - /// Gets an enumerator over each annotation. - /// - /// - public IEnumerator GetEnumerator() => Enumerable.Range(0, records.Length).Select(ResolveAnnotation).GetEnumerator(); - - /// - /// Gets an enumerator over each annotation. - /// - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/PermittedSubclassesAttributeReader.cs b/src/IKVM.ByteCode/Reading/PermittedSubclassesAttributeReader.cs deleted file mode 100644 index 2a4721bf1c..0000000000 --- a/src/IKVM.ByteCode/Reading/PermittedSubclassesAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class PermittedSubclassesAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public PermittedSubclassesAttributeReader(ClassReader declaringClass, AttributeInfoReader info, PermittedSubclassesAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/ReaderBase.cs b/src/IKVM.ByteCode/Reading/ReaderBase.cs deleted file mode 100644 index 4ec6dcf9cf..0000000000 --- a/src/IKVM.ByteCode/Reading/ReaderBase.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Threading; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Base class for a reader. - /// - internal abstract class ReaderBase - { - - readonly ClassReader declaringClass; - - /// - /// Initializes a new instance. - /// - /// - /// - protected ReaderBase(ClassReader declaringClass) - { - this.declaringClass = declaringClass ?? (this is ClassReader self ? self : throw new ArgumentNullException(nameof(declaringClass))); - } - - /// - /// Gets the class reader from which this entity is being read. - /// - public ClassReader DeclaringClass => declaringClass; - - } - - /// - /// Base class for a reader of a specific record type. - /// - /// - internal abstract class ReaderBase : ReaderBase - { - - readonly TRecord record; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public ReaderBase(ClassReader declaringClass, TRecord record) : - base(declaringClass) - { - this.record = record; - } - - /// - /// Gets the underlying method being read. - /// - public TRecord Record => record; - - } -} diff --git a/src/IKVM.ByteCode/Reading/RecordAttributeReader.cs b/src/IKVM.ByteCode/Reading/RecordAttributeReader.cs deleted file mode 100644 index 11114a7c13..0000000000 --- a/src/IKVM.ByteCode/Reading/RecordAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class RecordAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public RecordAttributeReader(ClassReader declaringClass, AttributeInfoReader info, RecordAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/RefConstantReader.cs b/src/IKVM.ByteCode/Reading/RefConstantReader.cs deleted file mode 100644 index 6e73785236..0000000000 --- a/src/IKVM.ByteCode/Reading/RefConstantReader.cs +++ /dev/null @@ -1,48 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Base type for a ref constant reader. - /// - /// - internal abstract class RefConstantReader : ConstantReader, IRefConstantReader - where TRecord : RefConstantRecord - { - - ClassConstantReader clazz; - NameAndTypeConstantReader name; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public RefConstantReader(ClassReader declaringClass, ushort index, TRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the underlying record. - /// - RefConstantRecord IConstantReader.Record => Record; - - /// - /// Gets the class name of the reference. - /// - public ClassConstantReader Class => LazyGet(ref clazz, () => DeclaringClass.Constants.Get(Record.ClassIndex)); - - /// - /// Gets the name and type of the reference. - /// - public NameAndTypeConstantReader NameAndType => LazyGet(ref name, () => DeclaringClass.Constants.Get(Record.NameAndTypeIndex)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/RuntimeInvisibleAnnotationsAttributeReader.cs b/src/IKVM.ByteCode/Reading/RuntimeInvisibleAnnotationsAttributeReader.cs deleted file mode 100644 index c6612e93ab..0000000000 --- a/src/IKVM.ByteCode/Reading/RuntimeInvisibleAnnotationsAttributeReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class RuntimeInvisibleAnnotationsAttributeReader : AttributeReader - { - - AnnotationReaderCollection annotations; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal RuntimeInvisibleAnnotationsAttributeReader(ClassReader declaringClass, AttributeInfoReader info, RuntimeInvisibleAnnotationsAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - /// - /// Gets the set of annotations described by this attribute. - /// - public AnnotationReaderCollection Annotations => LazyGet(ref annotations, () => new AnnotationReaderCollection(DeclaringClass, Record.Annotations)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/RuntimeInvisibleParameterAnnotationsAttributeReader.cs b/src/IKVM.ByteCode/Reading/RuntimeInvisibleParameterAnnotationsAttributeReader.cs deleted file mode 100644 index b8bb5158c7..0000000000 --- a/src/IKVM.ByteCode/Reading/RuntimeInvisibleParameterAnnotationsAttributeReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class RuntimeInvisibleParameterAnnotationsAttributeReader : AttributeReader - { - - ParameterAnnotationReaderCollection annotations; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public RuntimeInvisibleParameterAnnotationsAttributeReader(ClassReader declaringClass, AttributeInfoReader info, RuntimeInvisibleParameterAnnotationsAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - /// - /// Gets the set of annotations described by this attribute. - /// - public ParameterAnnotationReaderCollection Annotations => LazyGet(ref annotations, () => new ParameterAnnotationReaderCollection(DeclaringClass, Record.Parameters)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/RuntimeInvisibleTypeAnnotationsAttributeReader.cs b/src/IKVM.ByteCode/Reading/RuntimeInvisibleTypeAnnotationsAttributeReader.cs deleted file mode 100644 index 1295b8d997..0000000000 --- a/src/IKVM.ByteCode/Reading/RuntimeInvisibleTypeAnnotationsAttributeReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class RuntimeInvisibleTypeAnnotationsAttributeReader : AttributeReader - { - - TypeAnnotationReaderCollection annotations; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal RuntimeInvisibleTypeAnnotationsAttributeReader(ClassReader declaringClass, AttributeInfoReader info, RuntimeInvisibleTypeAnnotationsAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - /// - /// Gets the set of annotations described by this attribute. - /// - public TypeAnnotationReaderCollection Annotations => LazyGet(ref annotations, () => new TypeAnnotationReaderCollection(DeclaringClass, Record.Annotations)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/RuntimeVisibleAnnotationsAttributeReader.cs b/src/IKVM.ByteCode/Reading/RuntimeVisibleAnnotationsAttributeReader.cs deleted file mode 100644 index e306a8ff8e..0000000000 --- a/src/IKVM.ByteCode/Reading/RuntimeVisibleAnnotationsAttributeReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal class RuntimeVisibleAnnotationsAttributeReader : AttributeReader - { - - AnnotationReaderCollection annotations; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal RuntimeVisibleAnnotationsAttributeReader(ClassReader declaringClass, AttributeInfoReader info, RuntimeVisibleAnnotationsAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - /// - /// Gets the set of annotations described by this attribute. - /// - public AnnotationReaderCollection Annotations => LazyGet(ref annotations, () => new AnnotationReaderCollection(DeclaringClass, Record.Annotations)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/RuntimeVisibleParameterAnnotationsAttributeReader.cs b/src/IKVM.ByteCode/Reading/RuntimeVisibleParameterAnnotationsAttributeReader.cs deleted file mode 100644 index fdf2ad7dbb..0000000000 --- a/src/IKVM.ByteCode/Reading/RuntimeVisibleParameterAnnotationsAttributeReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal class RuntimeVisibleParameterAnnotationsAttributeReader : AttributeReader - { - - ParameterAnnotationReaderCollection annotations; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal RuntimeVisibleParameterAnnotationsAttributeReader(ClassReader declaringClass, AttributeInfoReader info, RuntimeVisibleParameterAnnotationsAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - /// - /// Gets the set of annotations described by this attribute. - /// - public ParameterAnnotationReaderCollection Parameters => LazyGet(ref annotations, () => new ParameterAnnotationReaderCollection(DeclaringClass, Record.Parameters)); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/RuntimeVisibleTypeAnnotationsAttributeReader.cs b/src/IKVM.ByteCode/Reading/RuntimeVisibleTypeAnnotationsAttributeReader.cs deleted file mode 100644 index 79295f21a8..0000000000 --- a/src/IKVM.ByteCode/Reading/RuntimeVisibleTypeAnnotationsAttributeReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal class RuntimeVisibleTypeAnnotationsAttributeReader : AttributeReader - { - - TypeAnnotationReaderCollection annotations; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal RuntimeVisibleTypeAnnotationsAttributeReader(ClassReader declaringClass, AttributeInfoReader info, RuntimeVisibleTypeAnnotationsAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - /// - /// Gets the set of annotations described by this attribute. - /// - public TypeAnnotationReaderCollection Annotations => LazyGet(ref annotations, () => new TypeAnnotationReaderCollection(DeclaringClass, Record.Annotations)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/SignatureAttributeReader.cs b/src/IKVM.ByteCode/Reading/SignatureAttributeReader.cs deleted file mode 100644 index 245e629275..0000000000 --- a/src/IKVM.ByteCode/Reading/SignatureAttributeReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal class SignatureAttributeReader : AttributeReader - { - - string value; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal SignatureAttributeReader(ClassReader declaringClass, AttributeInfoReader info, SignatureAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - /// - /// Gets the signature value. - /// - public string Value => LazyGet(ref value, () => DeclaringClass.Constants.Get(Record.SignatureIndex).Value); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/SourceDebugExtensionAttributeReader.cs b/src/IKVM.ByteCode/Reading/SourceDebugExtensionAttributeReader.cs deleted file mode 100644 index 3fca5d2484..0000000000 --- a/src/IKVM.ByteCode/Reading/SourceDebugExtensionAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal class SourceDebugExtensionAttributeReader : AttributeReader - { - - /// - /// Initalizes a new instance. - /// - /// - /// - /// - internal SourceDebugExtensionAttributeReader(ClassReader declaringClass, AttributeInfoReader info, SourceDebugExtensionAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/SourceFileAttributeReader.cs b/src/IKVM.ByteCode/Reading/SourceFileAttributeReader.cs deleted file mode 100644 index 5a64683f8e..0000000000 --- a/src/IKVM.ByteCode/Reading/SourceFileAttributeReader.cs +++ /dev/null @@ -1,32 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal class SourceFileAttributeReader : AttributeReader - { - - Utf8ConstantReader sourceFile; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal SourceFileAttributeReader(ClassReader declaringClass, AttributeInfoReader info, SourceFileAttributeRecord record) : - base(declaringClass, info, record) - { - - } - - /// - /// Gets the path to the source file. - /// - public Utf8ConstantReader SourceFile => LazyGet(ref sourceFile, () => DeclaringClass.Constants.Get(Record.SourceFileIndex)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/StackMapTableAttributeReader.cs b/src/IKVM.ByteCode/Reading/StackMapTableAttributeReader.cs deleted file mode 100644 index c71fad15d4..0000000000 --- a/src/IKVM.ByteCode/Reading/StackMapTableAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal class StackMapTableAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal StackMapTableAttributeReader(ClassReader declaringClass, AttributeInfoReader info, StackMapTableAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/StringConstantReader.cs b/src/IKVM.ByteCode/Reading/StringConstantReader.cs deleted file mode 100644 index fd8efbfbf1..0000000000 --- a/src/IKVM.ByteCode/Reading/StringConstantReader.cs +++ /dev/null @@ -1,37 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class StringConstantReader : ConstantReader - { - - Utf8ConstantReader value; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public StringConstantReader(ClassReader declaringClass, ushort index, StringConstantRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the value of the string constant. Result may not actually be a string object as overrides can apply. - /// - public Utf8ConstantReader Value => LazyGet(ref value, () => DeclaringClass.Constants.Get(Record.ValueIndex)); - - /// - /// Returns true if this class is loadable according to the Java specification. - /// - public override bool IsLoadable => DeclaringClass.Version >= new ClassFormatVersion(45, 3); - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/SyntheticAttributeReader.cs b/src/IKVM.ByteCode/Reading/SyntheticAttributeReader.cs deleted file mode 100644 index 78a9b13d17..0000000000 --- a/src/IKVM.ByteCode/Reading/SyntheticAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal class SyntheticAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal SyntheticAttributeReader(ClassReader declaringClass, AttributeInfoReader info, SyntheticAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} \ No newline at end of file diff --git a/src/IKVM.ByteCode/Reading/TypeAnnotationReader.cs b/src/IKVM.ByteCode/Reading/TypeAnnotationReader.cs deleted file mode 100644 index d39691d44e..0000000000 --- a/src/IKVM.ByteCode/Reading/TypeAnnotationReader.cs +++ /dev/null @@ -1,37 +0,0 @@ -using IKVM.ByteCode.Parsing; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class TypeAnnotationReader : ReaderBase - { - - Utf8ConstantReader type; - ElementValueKeyReaderCollection elements; - - /// - /// Initializes a new instance. - /// - /// - /// - public TypeAnnotationReader(ClassReader declaringClass, TypeAnnotationRecord record) : - base(declaringClass, record) - { - - } - - /// - /// Gets the type of the annotation. - /// - public Utf8ConstantReader Type => LazyGet(ref type, () => DeclaringClass.Constants.Get(Record.TypeIndex)); - - /// - /// Gets the element values of the annotation. - /// - public ElementValueKeyReaderCollection Elements => LazyGet(ref elements, () => new ElementValueKeyReaderCollection(DeclaringClass, Record.Elements)); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/TypeAnnotationReaderCollection.cs b/src/IKVM.ByteCode/Reading/TypeAnnotationReaderCollection.cs deleted file mode 100644 index def805764b..0000000000 --- a/src/IKVM.ByteCode/Reading/TypeAnnotationReaderCollection.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading; - -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - /// - /// Lazy init collection of annotation data. - /// - internal sealed class TypeAnnotationReaderCollection : IReadOnlyList - { - - readonly ClassReader ownerClass; - readonly TypeAnnotationRecord[] records; - - TypeAnnotationReader[] cache; - - /// - /// Initializes a new instance. - /// - /// - /// - public TypeAnnotationReaderCollection(ClassReader ownerClass, TypeAnnotationRecord[] records) - { - this.ownerClass = ownerClass ?? throw new ArgumentNullException(nameof(ownerClass)); - this.records = records ?? throw new ArgumentNullException(nameof(records)); - } - /// - /// Resolves the specified annotation of the class from the records. - /// - /// - TypeAnnotationReader ResolveAnnotation(int index) - { - if (index < 0 || index >= records.Length) - throw new ArgumentOutOfRangeException(nameof(index)); - - // initialize cache if not initialized - if (cache == null) - Interlocked.CompareExchange(ref cache, new TypeAnnotationReader[records.Length], null); - - // consult cache - if (cache[index] is TypeAnnotationReader reader) - return reader; - - reader = new TypeAnnotationReader(ownerClass, records[index]); - - // atomic set, only one winner - Interlocked.CompareExchange(ref cache[index], reader, null); - return cache[index]; - } - - /// - /// Gets the annotation at the specified index. - /// - /// - /// - public TypeAnnotationReader this[int index] => ResolveAnnotation(index); - - /// - /// Gets the count of annotations. - /// - public int Count => records.Length; - - /// - /// Gets an enumerator over each annotation. - /// - /// - public IEnumerator GetEnumerator() => Enumerable.Range(0, records.Length).Select(ResolveAnnotation).GetEnumerator(); - - /// - /// Gets an enumerator over each annotation. - /// - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - } - -} diff --git a/src/IKVM.ByteCode/Reading/UnknownAttributeReader.cs b/src/IKVM.ByteCode/Reading/UnknownAttributeReader.cs deleted file mode 100644 index 3dd6867488..0000000000 --- a/src/IKVM.ByteCode/Reading/UnknownAttributeReader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using IKVM.ByteCode.Parsing; - -namespace IKVM.ByteCode.Reading -{ - - internal class UnknownAttributeReader : AttributeReader - { - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public UnknownAttributeReader(ClassReader declaringClass, AttributeInfoReader info, UnknownAttributeRecord data) : - base(declaringClass, info, data) - { - - } - - } - -} diff --git a/src/IKVM.ByteCode/Reading/Utf8ConstantReader.cs b/src/IKVM.ByteCode/Reading/Utf8ConstantReader.cs deleted file mode 100644 index cee7fa7461..0000000000 --- a/src/IKVM.ByteCode/Reading/Utf8ConstantReader.cs +++ /dev/null @@ -1,33 +0,0 @@ -using IKVM.ByteCode.Parsing; -using IKVM.ByteCode.Text; - -using static IKVM.ByteCode.Util; - -namespace IKVM.ByteCode.Reading -{ - - internal sealed class Utf8ConstantReader : ConstantReader - { - - string value; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - public Utf8ConstantReader(ClassReader declaringClass, ushort index, Utf8ConstantRecord record) : - base(declaringClass, index, record) - { - - } - - /// - /// Gets the value of the constant. Result is interned. - /// - public string Value => LazyGet(ref value, () => MUTF8Encoding.GetMUTF8(DeclaringClass.Version.Major).GetString(Record.Value)); - - } - -} diff --git a/src/IKVM.ByteCode/ReferenceKind.cs b/src/IKVM.ByteCode/ReferenceKind.cs deleted file mode 100644 index ecb1e3d960..0000000000 --- a/src/IKVM.ByteCode/ReferenceKind.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace IKVM.ByteCode -{ - - internal enum ReferenceKind : byte - { - - GetField = 1, - GetStatic = 2, - PutField = 3, - PutStatic = 4, - InvokeVirtual = 5, - InvokeStatic = 6, - InvokeSpecial = 7, - NewInvokeSpecial = 8, - InvokeInterface = 9, - - } - -} diff --git a/src/IKVM.ByteCode/Text/EncodingExtensions.cs b/src/IKVM.ByteCode/Text/EncodingExtensions.cs deleted file mode 100644 index 623cf019b0..0000000000 --- a/src/IKVM.ByteCode/Text/EncodingExtensions.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Text; - -namespace IKVM.ByteCode.Text -{ - - static class EncodingExtensions - { - -#if NETFRAMEWORK - - public static unsafe string GetString(this Encoding self, ReadOnlySpan bytes) - { - fixed (byte* bytesPtr = bytes) - return self.GetString(bytesPtr, bytes.Length); - } - -#endif - - } - -} diff --git a/src/IKVM.ByteCode/Text/MUTF8Decoder.cs b/src/IKVM.ByteCode/Text/MUTF8Decoder.cs deleted file mode 100644 index 5697cbeef6..0000000000 --- a/src/IKVM.ByteCode/Text/MUTF8Decoder.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Text; - -namespace IKVM.ByteCode.Text -{ - - internal class MUTF8Decoder : Decoder - { - - readonly MUTF8Encoding encoding; - - /// - /// Initializes a new instance. - /// - /// - /// - public MUTF8Decoder(MUTF8Encoding encoding) - { - this.encoding = encoding ?? throw new ArgumentNullException(nameof(encoding)); - } - - public override int GetCharCount(byte[] bytes, int index, int count) - { - return encoding.GetCharCount(bytes, index, count); - } - - public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) - { - return encoding.GetChars(bytes, byteIndex, byteCount, chars, charIndex); - } - - } - -} diff --git a/src/IKVM.ByteCode/Text/MUTF8Encoder.cs b/src/IKVM.ByteCode/Text/MUTF8Encoder.cs deleted file mode 100644 index 8b13e041e1..0000000000 --- a/src/IKVM.ByteCode/Text/MUTF8Encoder.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Text; - -namespace IKVM.ByteCode.Text -{ - - internal class MUTF8Encoder : Encoder - { - - readonly MUTF8Encoding encoding; - - /// - /// Initializes a new instance. - /// - /// - /// - public MUTF8Encoder(MUTF8Encoding encoding) - { - this.encoding = encoding ?? throw new ArgumentNullException(nameof(encoding)); - } - - public override int GetByteCount(char[] chars, int index, int count, bool flush) - { - return encoding.GetByteCount(chars, index, count); - } - - public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, bool flush) - { - return encoding.GetBytes(chars, charIndex, charCount, bytes, byteIndex); - } - - } - -} diff --git a/src/IKVM.ByteCode/Text/MUTF8Encoding.cs b/src/IKVM.ByteCode/Text/MUTF8Encoding.cs deleted file mode 100644 index f926faeac5..0000000000 --- a/src/IKVM.ByteCode/Text/MUTF8Encoding.cs +++ /dev/null @@ -1,369 +0,0 @@ -using System; -using System.Text; - -namespace IKVM.ByteCode.Text -{ - - /// - /// Implements an for Sun's modified UTF-8. - /// - internal class MUTF8Encoding : Encoding - { - - readonly static MUTF8Encoding JavaSE_1_0 = new MUTF8Encoding(0); - readonly static MUTF8Encoding JavaSE_1_4 = new MUTF8Encoding(48); - - /// - /// Gets an instance of the Sun modified UTF8 encoding targeting the specified JavaSE version. - /// - public static MUTF8Encoding GetMUTF8(int majorVersion) => majorVersion >= 48 ? JavaSE_1_4 : JavaSE_1_0; - - readonly int majorVersion; - - /// - /// Initializes a new instance. - /// - /// - public MUTF8Encoding(int majorVersion = 52) - { - this.majorVersion = majorVersion; - } - - /// - public override int GetByteCount(char[] chars, int index, int count) - { - if (chars is null) - throw new ArgumentNullException(nameof(chars)); - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index)); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(index)); - - return GetByteCount(chars.AsSpan(index, count)); - } - -#if NETFRAMEWORK - - public unsafe int GetByteCount(ReadOnlySpan chars) - { - if (chars.Length == 0) - return 0; - - fixed (char* c = chars) - return GetByteCount(c, chars.Length); - } - -#endif - - /// - public override unsafe int GetByteCount(char* chars, int count) - { - if (chars is null) - throw new ArgumentNullException(nameof(chars)); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count)); - - var len = 0; - - for (int i = 0, e = count; i < e; i++) - { - var c = chars[i]; - if (c > 0 && c <= 0x007F) - len += 1; - else if (c <= 0x07FF) - len += 2; - else - len += 3; - } - - return len; - } - - /// - public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex) - { - if (s is null) - throw new ArgumentNullException(nameof(s)); - if (charIndex < 0) - throw new ArgumentOutOfRangeException(nameof(charIndex)); - if (charCount < 0) - throw new ArgumentOutOfRangeException(nameof(charCount)); - if (bytes is null) - throw new ArgumentNullException(nameof(bytes)); - if (byteIndex < 0) - throw new ArgumentOutOfRangeException(nameof(byteIndex)); - - return GetBytes(s.AsSpan(charIndex, charCount), bytes.AsSpan(byteIndex)); - } - - /// - public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) - { - if (chars is null) - throw new ArgumentNullException(nameof(chars)); - if (charIndex < 0) - throw new ArgumentOutOfRangeException(nameof(charIndex)); - if (charCount < 0) - throw new ArgumentOutOfRangeException(nameof(charCount)); - if (bytes is null) - throw new ArgumentNullException(nameof(chars)); - if (byteIndex < 0) - throw new ArgumentOutOfRangeException(nameof(byteIndex)); - - return GetBytes(chars.AsSpan(charIndex, charCount), bytes.AsSpan(byteIndex)); - } - -#if NETFRAMEWORK - - public unsafe int GetBytes(ReadOnlySpan chars, Span bytes) - { - if (chars.Length == 0) - return 0; - - fixed (char* cptr = chars) - fixed (byte* bptr = bytes) - return GetBytes(cptr, chars.Length, bptr, bytes.Length); - } - -#endif - - /// - public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) - { - if (chars is null) - throw new ArgumentNullException(nameof(chars)); - if (charCount < 0) - throw new ArgumentOutOfRangeException(nameof(charCount)); - if (bytes is null) - throw new ArgumentNullException(nameof(bytes)); - if (byteCount < 0) - throw new ArgumentOutOfRangeException(nameof(byteCount)); - - int j = 0; - - for (int i = 0; i < charCount; i++) - { - var ch = chars[i]; - if ((ch != 0) && (ch <= 0x7F)) - { - if (j + 1 > byteCount) - throw new EncoderFallbackException("Out of memory."); - - bytes[j++] = (byte)ch; - } - else if (ch <= 0x7FF) - { - if (j + 2 > byteCount) - throw new EncoderFallbackException("Out of memory."); - - bytes[j++] = (byte)((ch >> 6) | 0xC0); - bytes[j++] = (byte)((ch & 0x3F) | 0x80); - } - else - { - if (j + 3 > byteCount) - throw new EncoderFallbackException("Out of memory."); - - bytes[j++] = (byte)((ch >> 12) | 0xE0); - bytes[j++] = (byte)(((ch >> 6) & 0x3F) | 0x80); - bytes[j++] = (byte)((ch & 0x3F) | 0x80); - } - } - - return j; - } - -#if NETFRAMEWORK - - public unsafe int GetCharCount(ReadOnlySpan bytes) - { - if (bytes.Length == 0) - return 0; - - fixed (byte* ptr = bytes) - return GetCharCount(ptr, bytes.Length); - } - -#endif - - /// - public override int GetCharCount(byte[] bytes, int index, int count) - { - if (bytes is null) - throw new ArgumentNullException(nameof(bytes)); - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index)); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count)); - if (index + count > bytes.Length) - throw new ArgumentOutOfRangeException(nameof(count)); - - return GetCharCount(bytes.AsSpan(index, count)); - } - - /// - public override unsafe int GetCharCount(byte* bytes, int count) - { - if (bytes is null) - throw new ArgumentNullException(nameof(bytes)); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count)); - - int n = count; - for (int i = 0; i < count; i++) - if ((bytes[i] & 0xC0) == 0x80) - --n; - - return n; - } - - /// - public unsafe override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) - { - return GetChars(bytes.AsSpan(byteIndex, byteCount), chars.AsSpan(charIndex)); - } - -#if NETFRAMEWORK - - /// - public unsafe int GetChars(ReadOnlySpan bytes, Span chars) - { - // avoid problems with empty buffer - if (bytes.Length == 0) - return 0; - - fixed (byte* bptr = bytes) - fixed (char* cptr = chars) - return GetChars(bptr, bytes.Length, cptr, chars.Length); - } - -#endif - - /// - /// Copied from UTF8.cpp in OpenJDK. - /// - /// Takes a pointer to a character of a given modified UTF8 string and decodes the character into the pointer - /// given by value. Returns a pointer to the next character. - /// - /// - /// - /// - static unsafe byte* Next(byte* str, char* value) - { - var ptr = str; - int length = -1; // bad length - int result = 0; - - byte ch, ch2, ch3; - switch ((ch = ptr[0]) >> 4) - { - default: - result = ch; - length = 1; - break; - case 0x8: - case 0x9: - case 0xA: - case 0xB: - case 0xF: - // shouldn't happen - break; - case 0xC: - case 0xD: - /* 110xxxxx 10xxxxxx */ - if (((ch2 = ptr[1]) & 0xC0) == 0x80) - { - var high_five = ch & 0x1F; - var low_six = ch2 & 0x3F; - result = (high_five << 6) + low_six; - length = 2; - break; - } - break; - case 0xE: - /* 1110xxxx 10xxxxxx 10xxxxxx */ - if (((ch2 = ptr[1]) & 0xC0) == 0x80) - { - if (((ch3 = ptr[2]) & 0xC0) == 0x80) - { - var high_four = ch & 0x0f; - var mid_six = ch2 & 0x3f; - var low_six = ch3 & 0x3f; - result = (((high_four << 6) + mid_six) << 6) + low_six; - length = 3; - } - } - break; - } - - if (length <= 0) - { - *value = (char)ptr[0]; // default bad result - return ptr + 1; // make progress somehow - } - - *value = (char)result; - - // The assert is correct but the .class file is wrong - // assert(UNICODE::utf8_size(result) == length, "checking reverse computation"); - return ptr + length; - } - - /// - public override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount) - { - if (bytes is null) - throw new ArgumentNullException(nameof(bytes)); - if (byteCount < 0) - throw new ArgumentOutOfRangeException(nameof(byteCount)); - if (chars is null) - throw new ArgumentNullException(nameof(chars)); - if (charCount < 0) - throw new ArgumentOutOfRangeException(nameof(byteCount)); - - var ptr = bytes; - int index = 0; - - // ASCII case loop optimization - for (; index < charCount; index++) - { - byte ch; - if ((ch = ptr[0]) > 0x7F) break; - chars[index] = (char)ch; - ptr++; - } - - // up until max char count is reached, advance over next character - for (; index < charCount; index++) - ptr = Next(ptr, &chars[index]); - - return index; - } - - /// - public override int GetMaxByteCount(int charCount) - { - return charCount * 3; - } - - /// - public override int GetMaxCharCount(int byteCount) - { - return byteCount; - } - - /// - public override Decoder GetDecoder() - { - return new MUTF8Decoder(this); - } - - /// - public override Encoder GetEncoder() - { - return new MUTF8Encoder(this); - } - - } - -} diff --git a/src/IKVM.ByteCode/TypePathKind.cs b/src/IKVM.ByteCode/TypePathKind.cs deleted file mode 100644 index 82d99bdaa2..0000000000 --- a/src/IKVM.ByteCode/TypePathKind.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace IKVM.ByteCode -{ - - internal enum TypePathKind : byte - { - - ArrayType = 0, - NestedType = 1, - ParameterizedWildcardTypeArgument = 2, - ParameterizedType = 3, - - } - -} diff --git a/src/IKVM.ByteCode/UnsupportedClassVersionException.cs b/src/IKVM.ByteCode/UnsupportedClassVersionException.cs deleted file mode 100644 index 6a81541dc9..0000000000 --- a/src/IKVM.ByteCode/UnsupportedClassVersionException.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace IKVM.ByteCode -{ - - /// - /// Describes an attempt to parse an unsupported class file version. - /// - internal sealed class UnsupportedClassVersionException : - InvalidClassException - { - - readonly ClassFormatVersion version; - - /// - /// Initializes a new instance. - /// - /// - internal UnsupportedClassVersionException(ClassFormatVersion version) : - base($"Unsupported class version {version}.") - { - this.version = version; - } - - /// - /// Gets the version that was found in the class file. - /// - public ClassFormatVersion Version => version; - - } - -} diff --git a/src/IKVM.ByteCode/Util.cs b/src/IKVM.ByteCode/Util.cs deleted file mode 100644 index 95a096c801..0000000000 --- a/src/IKVM.ByteCode/Util.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Threading; - -namespace IKVM.ByteCode -{ - - internal static class Util - { - - /// - /// Gets the value at the given location or initializes it if null. - /// - /// - /// - /// - /// - public static T LazyGet(ref T location, Func create) - where T : class - { - if (create is null) - throw new ArgumentNullException(nameof(create)); - - if (location == null) - Interlocked.CompareExchange(ref location, create(), null); - - return location; - } - - } - -} diff --git a/src/IKVM.Image-bin/IKVM.Image-bin.csproj b/src/IKVM.Image-bin/IKVM.Image-bin.csproj index fb0341f813..de1f1e880e 100644 --- a/src/IKVM.Image-bin/IKVM.Image-bin.csproj +++ b/src/IKVM.Image-bin/IKVM.Image-bin.csproj @@ -9,7 +9,6 @@ - @@ -40,6 +39,8 @@ + + diff --git a/src/IKVM.Image/IKVM.Image.csproj b/src/IKVM.Image/IKVM.Image.csproj index 804cd11da8..a9b47afdfe 100644 --- a/src/IKVM.Image/IKVM.Image.csproj +++ b/src/IKVM.Image/IKVM.Image.csproj @@ -54,11 +54,6 @@ - - - - - @@ -69,16 +64,16 @@ - + - + - + @@ -92,13 +87,13 @@ $(IntermediateOutputPath)currency.data - + - + @@ -117,13 +112,13 @@ $(IntermediateOutputPath)cacerts - + - + @@ -143,6 +138,128 @@ + + $(OpenJdkDir)jdk\src\share\lib\security\blacklisted.certs + $(IntermediateOutputPath)blacklisted.certs + + + + + + + + + + + + + + GenerateBlacklistedCerts; + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)US_export_policy.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + GenerateUSExportPolicy; + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)limited_local_policy.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + GenerateLimitedLocalPolicy; + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)unlimited_local_policy.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + GenerateUnlimitedLocalPolicy; + $(GenerateDependsOn); + + + $(GenerateDependsOn); diff --git a/src/IKVM.Image/IKVM.Image.project.targets b/src/IKVM.Image/IKVM.Image.project.targets index af686ea628..282cc2a17b 100644 --- a/src/IKVM.Image/IKVM.Image.project.targets +++ b/src/IKVM.Image/IKVM.Image.project.targets @@ -39,6 +39,18 @@ + + + + $([System.IO.Path]::GetFullPath('$(JAVA_HOME)\bin\jar')) + $([System.IO.Path]::GetFullPath('$(JAVA_HOME)\bin\jar.exe')) + + "$(JarPath)" $(JarArgs) + + + + + <_PackageFiles Include="@(IkvmImageItem)"> diff --git a/src/IKVM.Image/IKVM.Image.runtime.targets b/src/IKVM.Image/IKVM.Image.runtime.targets index 6b020c9809..d632f7f79a 100644 --- a/src/IKVM.Image/IKVM.Image.runtime.targets +++ b/src/IKVM.Image/IKVM.Image.runtime.targets @@ -100,13 +100,13 @@ $(IntermediateOutputPath)fontconfig.bfc - + - - + + @@ -129,13 +129,13 @@ $(IntermediateOutputPath)java.security - + - - + + diff --git a/src/IKVM.JTReg.TestAdapter.Core/JTRegTestManager.cs b/src/IKVM.JTReg.TestAdapter.Core/JTRegTestManager.cs index a8531d4cf8..6c2e70b908 100644 --- a/src/IKVM.JTReg.TestAdapter.Core/JTRegTestManager.cs +++ b/src/IKVM.JTReg.TestAdapter.Core/JTRegTestManager.cs @@ -496,7 +496,7 @@ internal void RunTestsImpl(string source, dynamic testManager, dynamic testSuite // set parameters on pool var opts = context.Options; - var pool = JTRegTypes.Agent.Pool.Instance(); + var pool = JTRegTypes.Agent.Pool.Instance(parameters); pool.setTimeoutFactor(opts.TimeoutFactor); pool.setSecurityPolicy(policyFile); diff --git a/src/IKVM.JTReg.TestAdapter.Core/JTRegTypes.cs b/src/IKVM.JTReg.TestAdapter.Core/JTRegTypes.cs index b7ee23182b..cd24bff1c7 100644 --- a/src/IKVM.JTReg.TestAdapter.Core/JTRegTypes.cs +++ b/src/IKVM.JTReg.TestAdapter.Core/JTRegTypes.cs @@ -51,8 +51,8 @@ public static class Pool public static readonly Class Class = Class.forName("com.sun.javatest.regtest.exec.Agent$Pool", true, ClassLoader); public static readonly Type Type = ikvm.runtime.Util.getInstanceTypeFromClass(Class); - public static readonly Method InstanceMethod = Class.getMethod("instance"); - public static dynamic Instance() => InstanceMethod.invoke(null); + public static readonly Method InstanceMethod = Class.getMethod("instance", new Class[] { RegressionParameters.Class }); + public static dynamic Instance(object @params) => InstanceMethod.invoke(null, @params); } diff --git a/src/IKVM.Java.Extensions/java/util/function/DelegateConsumer.cs b/src/IKVM.Java.Extensions/java/util/function/DelegateConsumer.cs index 34a38cc1c2..339ae0f71d 100644 --- a/src/IKVM.Java.Extensions/java/util/function/DelegateConsumer.cs +++ b/src/IKVM.Java.Extensions/java/util/function/DelegateConsumer.cs @@ -11,39 +11,6 @@ namespace java.util.function public class DelegateConsumer : Consumer { - /// - /// Joins two consumers into one. - /// - sealed class JoinConsumer : Consumer - { - - readonly Consumer arg1; - readonly Consumer arg2; - - /// - /// Initializes a new instance. - /// - /// - /// - internal JoinConsumer(Consumer arg1, Consumer arg2) - { - this.arg1 = arg1 ?? throw new ArgumentNullException(nameof(arg1)); - this.arg2 = arg2 ?? throw new ArgumentNullException(nameof(arg2)); - } - - public void accept(object obj0) - { - arg1.accept(obj0); - arg2.accept(obj0); - } - - public Consumer andThen(Consumer other) - { - return new JoinConsumer(this, other); - } - - } - readonly Action action; /// @@ -63,7 +30,7 @@ public void accept(object t) public Consumer andThen(Consumer other) { - return new JoinConsumer(this, other); + return Consumer.__DefaultMethods.andThen(this, other); } } diff --git a/src/IKVM.Java.runtime.linux/IKVM.Java.runtime.linux.csproj b/src/IKVM.Java.runtime.linux/IKVM.Java.runtime.linux.csproj index 04840cb4cd..de4dc3acd8 100644 --- a/src/IKVM.Java.runtime.linux/IKVM.Java.runtime.linux.csproj +++ b/src/IKVM.Java.runtime.linux/IKVM.Java.runtime.linux.csproj @@ -2,7 +2,7 @@ - net472;net6.0;net8.0 + net6.0;net8.0 IKVM.Java.runtime.linux linux diff --git a/src/IKVM.Java.runtime.osx/IKVM.Java.runtime.osx.csproj b/src/IKVM.Java.runtime.osx/IKVM.Java.runtime.osx.csproj index 34c26082bd..caa18872f4 100644 --- a/src/IKVM.Java.runtime.osx/IKVM.Java.runtime.osx.csproj +++ b/src/IKVM.Java.runtime.osx/IKVM.Java.runtime.osx.csproj @@ -2,7 +2,7 @@ - net472;net6.0;net8.0 + net6.0;net8.0 IKVM.Java.runtime.osx osx diff --git a/src/IKVM.Java/IKVM.Java.csproj b/src/IKVM.Java/IKVM.Java.csproj index 3f4fba07c5..4a566f1bd7 100644 --- a/src/IKVM.Java/IKVM.Java.csproj +++ b/src/IKVM.Java/IKVM.Java.csproj @@ -5,8 +5,26 @@ net472;net6.0;net8.0 IKVM.Java ref + false + none + $(TargetsTriggeredByCompilation);ConvertRefAssembly + + + all + all + true + + + + + + + + + + diff --git a/src/IKVM.Java/IKVM.Java.runtime.corba.props b/src/IKVM.Java/IKVM.Java.runtime.corba.props index 5a1f5ee13e..56fd74fbc2 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.corba.props +++ b/src/IKVM.Java/IKVM.Java.runtime.corba.props @@ -12,26 +12,25 @@ - - - + + + + + + + + + + - - - - - - - - + - - - + + diff --git a/src/IKVM.Java/IKVM.Java.runtime.corba.targets b/src/IKVM.Java/IKVM.Java.runtime.corba.targets new file mode 100644 index 0000000000..bc2ce9c8d8 --- /dev/null +++ b/src/IKVM.Java/IKVM.Java.runtime.corba.targets @@ -0,0 +1,491 @@ + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + $(IntermediateOutputPath)corba_btclasses\ + $(IntermediateOutputPath)corba_btclasses.javac.rsp + $(CorbaBuildToolsOutputPath)stamp + + + + + + + + + <_CorbaBuildToolsJavaCompilerArgs Include="-nowarn" /> + <_CorbaBuildToolsJavaCompilerArgs Include="-d" /> + <_CorbaBuildToolsJavaCompilerArgs Include="$(CorbaBuildToolsOutputPath)" /> + <_CorbaBuildToolsJavaCompilerArgs Include="@(CorbaBuildToolsSource->'%(FullPath)')" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(IntermediateOutputPath)corba_idlj\ + $(IntermediateOutputPath)corba_idlj.javac.rsp + $(CorbaIDLJOutputPath)stamp + + + + + + + + + <_CorbaIDLJJavaCompilerArgs Include="-nowarn" /> + <_CorbaIDLJJavaCompilerArgs Include="-d" /> + <_CorbaIDLJJavaCompilerArgs Include="$(CorbaIDLJOutputPath)" /> + <_CorbaIDLJJavaCompilerArgs Include="@(CorbaIDLJSource->'%(FullPath)')" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(IntermediateOutputPath)corba_logutil\ + $(IntermediateOutputPath)corba_logutil.javac.rsp + $(CorbaLogUtilOutputPath)stamp + + + + + + + + + <_CorbaIDLJJavaCompilerArgs Include="-nowarn" /> + <_CorbaIDLJJavaCompilerArgs Include="-d" /> + <_CorbaIDLJJavaCompilerArgs Include="$(CorbaLogUtilOutputPath)" /> + <_CorbaIDLJJavaCompilerArgs Include="@(CorbaLogUtilSource->'%(FullPath)')" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(IntermediateOutputPath)corba_logwrappers\ + + + + + + + + + + + + + <_BuildCorbaLogWrappersDir Remove="@(_BuildCorbaLogWrappersDir)" /> + <_BuildCorbaLogWrappersDir Include="$(CorbaLogWrappersOutputPath)com\sun\corba\se\impl\logging" /> + + + + + + + + + + + + + + + + GenerateCorbaLogWrapperSources; + $(GenerateDependsOn); + + + + + + + + + + <_BuildCorbaLogWrappersDir Remove="@(_BuildCorbaLogWrappersDir)" /> + <_BuildCorbaLogWrappersDir Include="$(CorbaLogWrappersOutputPath)com\sun\corba\se\impl\logging" /> + + + + + + + + + + + + + + + $(CorbaLogWrappersOutputPath)com/sun/corba/se/impl/logging/LogStrings.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + GenerateCorbaLogWrapperResources; + GenerateCorbaLogWrapperProperties; + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)corba_idls\ + $(OpenJdkDir)corba\src\share\classes\ + $(IntermediateOutputPath)corba_idls_tmp\ + $(CorbaIDLOutputPath)stamp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)DYNANYDELETEFILES" /> + <__CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\DynamicAny\*.java" /> + <_CorbaIDLsDelete Include="@(__CorbaIDLsDelete)" Condition="$([System.String]::Copy('%(Filename)').Contains('POA'))" /> + <_CorbaIDLsDelete Include="@(__CorbaIDLsDelete)" Condition="$([System.String]::Copy('%(Filename)').Contains('Holder'))" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\DynamicAny\DynValueBoxHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\DynamicAny\DynValueCommonHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\DynamicAny\_DynValueCommonStub.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\DynamicAny\_DynValueBoxStub.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\DynamicAny\DynAnyPackage\TypeMismatchHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\DynamicAny\DynAnyPackage\InvalidValueHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\DynamicAny\DynAnyFactoryPackage\InconsistentTypeCodeHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)IOPDELETEFILES" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\BI_DIR_IIOP.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\ChainBypassCheck.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\ChainBypassInfo.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\FORWARDED_IDENTITY.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\INVOCATION_POLICIES.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\LogicalThreadId.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\SendingContextRunTime.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\UnknownExceptionInfo.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\TaggedComponentSeqHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)POAHELHOLFILES" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\CurrentPackage\NoContextHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ForwardRequestHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\IdAssignmentPolicyValueHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\IdAssignmentPolicyValueHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\IdUniquenessPolicyValueHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\IdUniquenessPolicyValueHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ImplicitActivationPolicyValueHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ImplicitActivationPolicyValueHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\LifespanPolicyValueHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\LifespanPolicyValueHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ServantRetentionPolicyValueHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ServantRetentionPolicyValueHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ObjectIdHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ObjectIdHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAListHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAListHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAManagerPackage\AdapterInactiveHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAManagerPackage\StateHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAManagerPackage\StateHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\AdapterAlreadyExistsHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\AdapterNonExistentHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\InvalidPolicyHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\NoServantHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\ObjectAlreadyActiveHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\ObjectNotActiveHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\ServantAlreadyActiveHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\ServantNotActiveHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\WrongAdapterHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\POAPackage\WrongPolicyHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\RequestProcessingPolicyValueHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\RequestProcessingPolicyValueHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ServantActivatorHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ServantLocatorHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ThreadPolicyValueHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableServer\ThreadPolicyValueHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)PIHELHOLFILES" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ClientRequestInfoHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ClientRequestInterceptorHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\IORInfoHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\IORInterceptorHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\InterceptorHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ORBInitInfoHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ORBInitializerHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\PolicyFactoryHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ReplyStatusHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\RequestInfoHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ServerRequestInfoHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ServerRequestInterceptorHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\SlotIdHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ClientRequestInfoHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ClientRequestInterceptorHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\CurrentHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ForwardRequestHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\IORInfoHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\IORInterceptorHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\InterceptorHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\InvalidSlotHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ORBInitInfoHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ORBInitializerHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\PolicyFactoryHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\RequestInfoHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ServerRequestInfoHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ServerRequestInterceptorHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\TaggedComponentSeqHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ORBInitInfoPackage\DuplicateNameHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\PortableInterceptor\ORBInitInfoPackage\InvalidNameHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\CodecPackage\FormatMismatchHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\CodecPackage\InvalidTypeForEncodingHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\CodecPackage\TypeMismatchHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\CodecHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\EncodingFormatHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\EncodingHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\CodecFactoryPackage\UnknownEncodingHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\CodecFactoryHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\CodecHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\EncodingHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\IOP\TaggedComponentSeqHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\Dynamic\ContextListHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\Dynamic\ExceptionListHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\Dynamic\ParameterHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\Dynamic\ParameterListHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\Dynamic\ExceptionListHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\Dynamic\ParameterHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\Dynamic\ParameterListHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\Dynamic\RequestContextHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)CORBAX" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\CORBA\OctetSeqHelper.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\CORBA\OctetSeqHolder.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\CORBA\PolicyError.java" /> + <_CorbaIDLsDelete Include="$(CorbaIDLOutputPath)org\omg\CORBA\RepositoryIdHelper.java" /> + + + + + + + + + + + + + + + + GenerateCorbaIDLs; + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)corba_cleanprop\ + + + + + + + + + + + + + + + + + + + + + + + + <_Dest>$(CorbaCleanPropertiesFilesOutputPath)%(PackagePath)\%(ResourceName).properties + + <_CleanCorbaPropertiesFilesArgs Remove="@(_CleanCorbaPropertiesFilesArgs)" /> + + + + + + + + + + + + + + + + + + + + + CleanCorbaPropertiesFiles; + $(GenerateDependsOn); + + + + diff --git a/src/IKVM.Java/IKVM.Java.runtime.jaxp.props b/src/IKVM.Java/IKVM.Java.runtime.jaxp.props index 5b0f7fd686..a7a5ae027b 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.jaxp.props +++ b/src/IKVM.Java/IKVM.Java.runtime.jaxp.props @@ -13,10 +13,7 @@ - - - - + diff --git a/src/IKVM.Java/IKVM.Java.runtime.jaxws.props b/src/IKVM.Java/IKVM.Java.runtime.jaxws.props index 7a706e2a41..de608f09b0 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.jaxws.props +++ b/src/IKVM.Java/IKVM.Java.runtime.jaxws.props @@ -12,13 +12,20 @@ - - - + + - - - + + + + + + + + + + + diff --git a/src/IKVM.Java/IKVM.Java.runtime.jdk.props b/src/IKVM.Java/IKVM.Java.runtime.jdk.props index 3b2d8fc142..b144b9ac98 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.jdk.props +++ b/src/IKVM.Java/IKVM.Java.runtime.jdk.props @@ -12,265 +12,221 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + @@ -343,14 +299,14 @@ - - - - - - - - + + + + + + + + @@ -370,41 +326,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + @@ -412,38 +368,38 @@ - - + + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - + + + + diff --git a/src/IKVM.Java/IKVM.Java.runtime.jdk.targets b/src/IKVM.Java/IKVM.Java.runtime.jdk.targets index c8653bdab1..64f9046737 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.jdk.targets +++ b/src/IKVM.Java/IKVM.Java.runtime.jdk.targets @@ -46,10 +46,10 @@ $(IntermediateOutputPath)rmistubs\ - <_BuildRmiStubsCoreStampFile>$(RmiStubsOutputPath)stamp + $(RmiStubsOutputPath)stamp - + <_RmiCompilerClasspath Include="@(Classpath);$(ClassOutputPath)" /> <_RmiCompilerArgs Include="@(RmiCompilerArgs)" /> @@ -59,14 +59,21 @@ <_RmiCompilerArgs Include="-d" /> <_RmiCompilerArgs Include="$(RmiStubsOutputPath)" /> + <_RmiCompilerArgs>@(_RmiCompilerArgs, ' ') + - + + + + + + @@ -79,13 +86,11 @@ - - - + - + @@ -104,6 +109,7 @@ + $(IntermediateOutputPath)jdk_chardat\ $(OpenJdkDir)jdk\make\data\characterdata\ $(OpenJdkDir)jdk\make\data\unicodedata\ @@ -116,7 +122,7 @@ - + @@ -130,7 +136,7 @@ <_SpecialCasingArg>$(_SpecialCasingArg.Replace('\', '\\')) <_PropListArg>$(UnicodeDataDir)PropList.txt <_PropListArg>$(_PropListArg.Replace('\', '\\')) - <_OutputArg>$(IntermediateOutputPath)genchardat\java\lang\%(CharacterDataItem.Identity).java.tmp + <_OutputArg>$(CharacterDataOutputPath)java\lang\%(CharacterDataItem.Identity).java.tmp <_OutputArg>$(_OutputArg.Replace('\', '\\')) @@ -151,15 +157,15 @@ <_GenerateCharacterArgs Include="%(CharacterDataItem.Arg3)" /> - + - - + + - - - + + + @@ -168,27 +174,31 @@ - - + + - - + + - - + + - + GenerateCharacterData; GenerateCharacterDataStatic; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)jdk_chardec\ - + @@ -221,14 +231,14 @@ <_GenerateCharsetDecoderArgs Include="-Dotypes-per-itype="chars-per-byte"" /> <_GenerateCharsetDecoderArgs Include="-DoutSequence="Unicode character"" /> <_GenerateCharsetDecoderTmpl Include="$(OpenJdkDir)jdk\src\share\classes\java\nio\charset\Charset-X-Coder.java.template" /> - <_GenerateCharsetDecoderTemp Include="$(IntermediateOutputPath)genchardec\java\nio\charset\CharsetDecoder.java.tmp" /> - <_GenerateCharsetDecoderFile Include="$(IntermediateOutputPath)genchardec\java\nio\charset\CharsetDecoder.java" /> + <_GenerateCharsetDecoderTemp Include="$(CharsetDecoderOutputPath)java\nio\charset\CharsetDecoder.java.tmp" /> + <_GenerateCharsetDecoderFile Include="$(CharsetDecoderOutputPath)java\nio\charset\CharsetDecoder.java" /> - - - - + + + + @@ -238,7 +248,11 @@ - + + $(IntermediateOutputPath)jdk_charenc\ + + + @@ -270,14 +284,14 @@ <_GenerateCharsetEncoderArgs Include="-Dotypes-per-itype="bytes-per-char"" /> <_GenerateCharsetEncoderArgs Include="-DoutSequence="byte sequence in the given charset"" /> <_GenerateCharsetEncoderTmpl Include="$(OpenJdkDir)jdk\src\share\classes\java\nio\charset\Charset-X-Coder.java.template" /> - <_GenerateCharsetEncoderTemp Include="$(IntermediateOutputPath)gencharenc\java\nio\charset\CharsetEncoder.java.tmp" /> - <_GenerateCharsetEncoderFile Include="$(IntermediateOutputPath)gencharenc\java\nio\charset\CharsetEncoder.java" /> + <_GenerateCharsetEncoderTemp Include="$(CharsetEncoderOutputPath)java\nio\charset\CharsetEncoder.java.tmp" /> + <_GenerateCharsetEncoderFile Include="$(CharsetEncoderOutputPath)java\nio\charset\CharsetEncoder.java" /> - - - - + + + + @@ -288,55 +302,56 @@ - + GenerateCharsetDecoder; GenerateCharsetEncoder; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + - $(OpenJdkDir)jdk\make\data\charsetmapping\ - $(OpenJdkDir)jdk\make\src\classes\build\tools\charsetmapping\ + $(IntermediateOutputPath)\jdk_charmap\ + $(OpenJdkDir)jdk\make\data\charsetmapping\ + $(OpenJdkDir)jdk\make\src\classes\build\tools\charsetmapping\ - - + + - - - - - - + + + + + + - + - <_GenerateCharsetMappingArgs Include="%(GenerateCharsetMappingItem.Source)" /> - <_GenerateCharsetMappingArgs Include="$(IntermediateOutputPath)gencharmap_%(GenerateCharsetMappingItem.Identity)\%(GenerateCharsetMappingItem.Destination)" /> - <_GenerateCharsetMappingArgs Include="%(GenerateCharsetMappingItem.Identity)" /> - <_GenerateCharsetMappingArgs Include="%(GenerateCharsetMappingItem.Copyright)" Condition=" '%(GenerateCharsetMappingItem.Copyright)' != '' " /> + <_GenerateCharsetMappingArgs Include="%(CharsetMappingItem.Source)" /> + <_GenerateCharsetMappingArgs Include="$(CharsetMappingOutputPath)%(CharsetMappingItem.Identity)\%(CharsetMappingItem.Destination)" /> + <_GenerateCharsetMappingArgs Include="%(CharsetMappingItem.Identity)" /> + <_GenerateCharsetMappingArgs Include="%(CharsetMappingItem.Copyright)" Condition=" '%(CharsetMappingItem.Copyright)' != '' " /> - - - - - - + + + + + + <_GenerateCharsetMappingsItems Remove="@(_GenerateCharsetMappingsItems)" /> - <_GenerateCharsetMappingsItems Include="$(IntermediateOutputPath)gencharmap_%(GenerateCharsetMappingItem.Identity)\**\*" /> - + <_GenerateCharsetMappingsItems Include="$(CharsetMappingOutputPath)%(CharsetMappingItem.Identity)\**\*" /> + @@ -569,65 +584,74 @@ public class WriteStandardCharsets : Task - + + $(IntermediateOutputPath)jdk_stdchar\ + $(IntermediateOutputPath)jdk_stdchar_tmp\ + + + - + + + + - - - + + + - + + + AliasesClassFile="$(StandardCharsetsTempPath)Aliases.java" + ClassesClassFile="$(StandardCharsetsTempPath)Classes.java" + CacheClassFile="$(StandardCharsetsTempPath)Cache.java" /> + - - - - - - + - + GenerateCharsetMappings; GenerateStandardCharsets; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)jdk_html32dtd\ - + <_DtdHome Include="$(OpenJdkDir)jdk\make\data\dtdbuilder" /> - <_BdtdTemp Include="$(IntermediateOutputPath)genhtml32dtd\javax\swing\text\html\parser\html32.bdtd.tmp" /> - <_Bdtd Include="$(IntermediateOutputPath)genhtml32dtd\javax\swing\text\html\parser\html32.bdtd" /> + <_BdtdTemp Include="$(Html32DTDOutputPath)javax\swing\text\html\parser\html32.bdtd.tmp" /> + <_Bdtd Include="$(Html32DTDOutputPath)javax\swing\text\html\parser\html32.bdtd" /> - - - + + + @@ -638,10 +662,10 @@ public class WriteStandardCharsets : Task - + GenerateHtml32DTD; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + - + GenerateExceptions; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + + + $(IntermediateOutputPath)jdk_buffers\ + + @@ -1024,12 +1052,12 @@ File.WriteAllLines(Path, File.ReadAllLines(Path).TakeWhile(i => i.Contains("#BIN - + - + <_Src Remove="@(_Src)" /> @@ -1037,23 +1065,23 @@ File.WriteAllLines(Path, File.ReadAllLines(Path).TakeWhile(i => i.Contains("#BIN <_Bin Remove="@(_Bin)" /> <_Bin Include="$(OpenJdkDir)jdk\src\share\classes\java\nio\%(_GenBufferCommand.Template)-bin.java.template" /> <_Tmp Remove="@(_Tmp)" /> - <_Tmp Include="$(IntermediateOutputPath)genbuf\java\nio\%(_GenBufferCommand.Identity).java.tmp" /> + <_Tmp Include="$(BufferOutputPath)java\nio\%(_GenBufferCommand.Identity).java.tmp" /> <_Dst Remove="@(_Dst)" /> - <_Dst Include="$(IntermediateOutputPath)genbuf\java\nio\%(_GenBufferCommand.Identity).java" /> + <_Dst Include="$(BufferOutputPath)java\nio\%(_GenBufferCommand.Identity).java" /> - + - - + + - - - - - - + + + + + + @@ -1065,45 +1093,50 @@ File.WriteAllLines(Path, File.ReadAllLines(Path).TakeWhile(i => i.Contains("#BIN - + GenerateBuffersSetup; GenerateBuffers; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + 21.0.1 + $(IntermediateOutputPath)jdk_cldr\ - - - - + + + + - + - - - - + + + + - - + + - + GenerateCalendarData; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)jdk_icons\ @@ -1134,28 +1167,28 @@ File.WriteAllLines(Path, File.ReadAllLines(Path).TakeWhile(i => i.Contains("#BIN - + - + <_Src Remove="@(_Src)" /> <_Src Include="%(AwtIcons.Identity)" /> <_Tmp Remove="@(_Tmp)" /> - <_Tmp Include="$(IntermediateOutputPath)genico\sun\awt\%(AwtIcons.ClassName).java.tmp" /> + <_Tmp Include="$(IconsOutputPath)sun\awt\%(AwtIcons.ClassName).java.tmp" /> <_Dst Remove="@(_Dst)" /> - <_Dst Include="$(IntermediateOutputPath)genico\sun\awt\%(AwtIcons.ClassName).java" /> + <_Dst Include="$(IconsOutputPath)sun\awt\%(AwtIcons.ClassName).java" /> - + - + @@ -1168,52 +1201,53 @@ File.WriteAllLines(Path, File.ReadAllLines(Path).TakeWhile(i => i.Contains("#BIN - + GenerateIcons; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + + $(IntermediateOutputPath)jdk_nimbus\ $(OpenJdkDir)jdk\src\share\classes\javax\swing\plaf\nimbus $(OpenJdkDir)jdk\src\share\classes\javax\swing\plaf\nimbus\skin.laf - + - - - - + + + + - - - + + - + GenerateNimbus; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + - $(IntermediateOutputPath)genx11_tmp\ - $(IntermediateOutputPath)genx11\sun\awt\X11\ + $(IntermediateOutputPath)jdk_x11wrappers\ + $(IntermediateOutputPath)jdk_x11wrappers_tmp\ $(OpenJdkDir)jdk\src\solaris\classes\sun\awt\X11\generator\xlibtypes.txt $(OpenJdkDir)jdk\src\solaris\classes\sun\awt\X11\generator\sizes.32 $(OpenJdkDir)jdk\src\solaris\classes\sun\awt\X11\generator\sizes.64 + $(X11WrapperOutputPath)stamp - + @@ -1221,97 +1255,97 @@ File.WriteAllLines(Path, File.ReadAllLines(Path).TakeWhile(i => i.Contains("#BIN <_X11WrapperSizePath Remove="@(_X11WrapperTempPath)" /> <_X11WrapperSizePath Include="$(X11WrapperTempPath)sizes" /> - <_X11WrapperDestPath Remove="@(_X11WrapperDestPath)" /> - <_X11WrapperDestPath Include="$(X11WrapperDestPath)" /> + <_X11WrapperOutputPath Remove="@(_X11WrapperOutputPath)" /> + <_X11WrapperOutputPath Include="$(X11WrapperOutputPath)" /> <_XLibTypes Remove="@(_XLibTypes)" /> <_XLibTypes Include="$(XLibTypes)" /> - + - + - - + + + - - - - + + - + GenerateX11Wrappers; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + - $(OpenJdkDir)jdk\make\data\unicodedata\UnicodeData.txt - $(IntermediateOutputPath)uniName.dat + $(OpenJdkDir)jdk\make\data\unicodedata\UnicodeData.txt + $(IntermediateOutputPath)jdk_uniname\uniName.dat - + - - - - + + + + + - - - + + + - + GenerateUniName; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + - $(OpenJdkDir)jdk\make\data\lsrdata\language-subtag-registry.txt - $(IntermediateOutputPath)LocaleEquivalentMaps.java + $(OpenJdkDir)jdk\make\data\lsrdata\language-subtag-registry.txt + $(IntermediateOutputPath)jdk_lsrequivmaps\LocaleEquivalentMaps.java - + - - + + + - - + + - + GenerateLocaleEquivalentMaps; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + - $(IntermediateOutputPath)break_iterator\classes\ - $(IntermediateOutputPath)break_iterator\gendata\ - sun\text\resources + $(IntermediateOutputPath)jdk_breakiterator\ + sun/text/resources @@ -1319,16 +1353,16 @@ File.WriteAllLines(Path, File.ReadAllLines(Path).TakeWhile(i => i.Contains("#BIN - - - - - - - - - - + + + + + + + + + + @@ -1336,27 +1370,40 @@ File.WriteAllLines(Path, File.ReadAllLines(Path).TakeWhile(i => i.Contains("#BIN - - - + + <_BreakIteratorOutputPath Remove="@(_BreakIteratorOutputPath)" /> + <_BreakIteratorOutputPath Include="$(BreakIteratorOutputPath)" /> + + + + + + - + - - - - - - - + + <_BreakIteratorClasspath Remove="@(_BreakIteratorClasspath)" /> + <_BreakIteratorClasspath Include="$(BreakIteratorOutputPath)" /> + <_BreakIteratorOutputArg Remove="@(_BreakIteratorOutputArg)" /> + <_BreakIteratorOutputArg Include="$(BreakIteratorOutputPath)$(BreakIteratorPackage)" /> + + + + + + + + + @@ -1365,11 +1412,392 @@ File.WriteAllLines(Path, File.ReadAllLines(Path).TakeWhile(i => i.Contains("#BIN - + GenerateBreakIteratorClasses; - GenerateBreakIteratorData; - $(GenerateSourceDependsOn); - + GenerateBreakIteratorResources; + $(GenerateDependsOn); + + + + + $(OpenJdkDir)jdk\src\share\classes\sun\util\CoreResourceBundleControl-XLocales.java.template + $(IntermediateOutputPath)jdk_crbc\CoreResourceBundleControl.java + + + + + + + + + + + + + + + + + (); + + var o = new Dictionary(); + o["en"] = "ENGLISH"; + o["fr"] = "FRENCH"; + o["de"] = "GERMAN"; + o["it"] = "ITALIAN"; + o["ja"] = "JAPANESE"; + o["ko"] = "KOREAN"; + o["zh"] = "CHINESE"; + o["zh_CN"] = "SIMPLIFIED_CHINESE"; + o["zh_TW"] = "TRADITIONAL_CHINESE"; + o["fr_FR"] = "FRANCE"; + o["de_DE"] = "GERMANY"; + o["it_IT"] = "ITALY"; + o["ja_JP"] = "JAPAN"; + o["ko_KR"] = "KOREA"; + o["en_GB"] = "UK"; + o["en_US"] = "US"; + o["en_CA"] = "CANADA"; + o["fr_CA"] = "CANADA_FRENCH"; + + foreach (var locale in LocaleList) + l.Add(o.ContainsKey(locale.ItemSpec) ? "Locale." + o[locale.ItemSpec] : "new Locale(\"" + string.Join("\", \"", locale.ItemSpec.Split('_')) + "\")"); + + Directory.CreateDirectory(Path.GetDirectoryName(OutputFile)); + using var src = File.OpenText(SourceFile); + using var dst = new StreamWriter(File.Open(OutputFile, FileMode.Create)); + + string line; + while ((line = src.ReadLine()) != null) + if (line.StartsWith("#warn") == false) + dst.WriteLine(line.Replace("#LOCALE_LIST#", string.Join(", ", l))); + + ]]> + + + + + + + + + + + + + + + + GenerateCoreResourceBundleControl; + $(GenerateDependsOn); + + + + + $(OpenJdkDir)jdk\src\share\classes\sun\util\locale\provider\LocaleDataMetaInfo-XLocales.java.template + $(IntermediateOutputPath)jdk_locales\LocaleDataMetaInfo.java + + + + + + + + + + + + + + (); + var all_non_en = new HashSet() { "ja-JP-JP", "th-TH-TH" }; + var resources = new HashSet(); + var locale_en = new Dictionary>(); + var locale_non_en = new Dictionary>(); + + // deconstruct Filename_LOCAL.ext into a list of en and non-en locales + foreach (var i in LocaleResourceList) + { + var f = i.GetMetadata("Filename"); + var a = f.Split(new[] { '_' }, 2); + var n = a[0]; + resources.Add(n); + + var l = a[1].Replace("_", "-"); + if (l.StartsWith("en")) + { + if (locale_en.TryGetValue(n, out var en) == false) + locale_en[n] = en = new HashSet(); + + en.Add(l); + all_en.Add(l); + } + else + { + if (locale_non_en.TryGetValue(n, out var non_en) == false) + locale_non_en[n] = non_en = new HashSet(); + + non_en.Add(l); + all_non_en.Add(l); + } + } + + Directory.CreateDirectory(Path.GetDirectoryName(OutputFile)); + using var src = File.OpenText(SourceFile); + using var dst = new StreamWriter(File.Open(OutputFile, FileMode.Create)); + + string line; + while ((line = src.ReadLine()) != null) + { + if (line.StartsWith("#")) + continue; + + foreach (var resource in resources) + { + var en = locale_en.TryGetValue(resource, out var _en) ? _en.OrderBy(i => i) : Enumerable.Empty(); + line = line.Replace($"#{resource}_ENLocales#", string.Join(" ", en)); + + var non_en = locale_non_en.TryGetValue(resource, out var _non_en) ? _non_en.OrderBy(i => i) : Enumerable.Empty(); + line = line.Replace($"#{resource}_NonENLocales#", string.Join(" ", non_en)); + } + + line = line.Replace("#AvailableLocales_ENLocales#", string.Join(" ", all_en.OrderBy(i => i))); + line = line.Replace("#AvailableLocales_NonENLocales#", string.Join(" ", all_non_en.OrderBy(i => i))); + dst.WriteLine(line); + } + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GenerateLocaleDataMetaInfo; + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)jdk_cleanprop\ + + + + + + + + + + + + + + + + + + + + + + + + <_Dest>$(JdkCleanPropertiesFilesOutputPath)%(PackagePath)\%(ResourceName).properties + + <_CleanJdkPropertiesFilesArgs Remove="@(_CleanJdkPropertiesFilesArgs)" /> + + + + + + + + + + + + + + + + + + + + + CleanJdkPropertiesFiles; + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)jdk_duplicateprop\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RemoveExistingDuplicateJdkPropertiesFiles; + DuplicateJdkPropertiesFiles; + $(GenerateDependsOn); + + + + + $(IntermediateOutputPath)jdk_compileprop\ + + + + + + + + + + + + + + + + + + + + + + + + <_Dest>$(JdkCompilePropertiesFilesOutputPath)%(PackagePath)\%(ClassName).java + + <_CompileJdkPropertiesFilesArgs Remove="@(_CompileJdkPropertiesFilesArgs)" /> + + + + + + + + + + + + + + + + + + + + + CompileJdkPropertiesFiles; + $(GenerateDependsOn); + diff --git a/src/IKVM.Java/IKVM.Java.runtime.langtools.props b/src/IKVM.Java/IKVM.Java.runtime.langtools.props index 9ee066b4f5..307dac2849 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.langtools.props +++ b/src/IKVM.Java/IKVM.Java.runtime.langtools.props @@ -12,22 +12,22 @@ - + - - - - + + + + - + - + diff --git a/src/IKVM.Java/IKVM.Java.runtime.langtools.targets b/src/IKVM.Java/IKVM.Java.runtime.langtools.targets index 1d67a5df13..9be80e5aa2 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.langtools.targets +++ b/src/IKVM.Java/IKVM.Java.runtime.langtools.targets @@ -11,7 +11,7 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - + <_GenerateVersionPropertiesLines Include="jdk=$(OpenJdkMajorVersion).$(OpenJdkMinorVersion).$(OpenJdkMicroVersion)" /> <_GenerateVersionPropertiesLines Include="full=$(OpenJdkMajorVersion).$(OpenJdkMinorVersion).$(OpenJdkMicroVersion)_$(OpenJdkUpdateVersion)-$(OpenJdkBuildNumber)" /> @@ -33,19 +33,19 @@ - - - - - + + + + + - + GenerateLangtoolsVersionProperties; - $(GenerateSourceDependsOn); - + $(GenerateDependsOn); + diff --git a/src/IKVM.Java/IKVM.Java.runtime.nashorn.props b/src/IKVM.Java/IKVM.Java.runtime.nashorn.props index 27591c1f4f..55fecd6f8d 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.nashorn.props +++ b/src/IKVM.Java/IKVM.Java.runtime.nashorn.props @@ -12,17 +12,14 @@ - + + + - - - - - - - + + diff --git a/src/IKVM.Java/IKVM.Java.runtime.nashorn.targets b/src/IKVM.Java/IKVM.Java.runtime.nashorn.targets new file mode 100644 index 0000000000..1c93e1a0c5 --- /dev/null +++ b/src/IKVM.Java/IKVM.Java.runtime.nashorn.targets @@ -0,0 +1,169 @@ + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + $(IntermediateOutputPath)nashorn_tmp\ + $(IntermediateOutputPath)nashorn_tmp.javac.rsp + $(NashornTempPath)stamp + $(IntermediateOutputPath)nashorn_classes\ + $(NashornOutputPath)stamp + + + + + + + + + <_NashornTempJavaCompilerClasspath Include="$([System.IO.Path]::GetFullPath('$(ClassOutputPath)'))" /> + + + <_NashornTempJavaCompilerClasspathArg>@(_NashornTempJavaCompilerClasspath, '$([System.IO.Path]::PathSeparator)') + <_NashornTempJavaCompilerClasspathArg>$(_NashornTempJavaCompilerClasspathArg.Replace('\', '\\')) + + + + <_NashornTempJavaCompilerArgs Include="-cp" /> + <_NashornTempJavaCompilerArgs Include=""$([MSBuild]::Escape('$(_NashornTempJavaCompilerClasspathArg)'))"" /> + <_NashornTempJavaCompilerArgs Include="-g" /> + <_NashornTempJavaCompilerArgs Include="-source" /> + <_NashornTempJavaCompilerArgs Include="7" /> + <_NashornTempJavaCompilerArgs Include="-target" /> + <_NashornTempJavaCompilerArgs Include="7" /> + <_NashornTempJavaCompilerArgs Include="-nowarn" /> + <_NashornTempJavaCompilerArgs Include="-d" /> + <_NashornTempJavaCompilerArgs Include="$(NashornTempPath)" /> + <_NashornTempJavaCompilerArgs Include="@(NashornSource->'%(FullPath)')" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(IntermediateOutputPath)nashorn_nasgen\ + $(IntermediateOutputPath)nashorn_nasgen.javac.rsp + $(NasgenOutputPath)stamp + + + + + + + + + <_NasgenJavaCompilerClasspath Include="$([System.IO.Path]::GetFullPath('$(ClassOutputPath)'))" /> + <_NasgenJavaCompilerClasspath Include="$([System.IO.Path]::GetFullPath('$(NashornOutputPath)'))" /> + + + <_NasgenJavaCompilerClasspathArg>@(_NasgenJavaCompilerClasspath, '$([System.IO.Path]::PathSeparator)') + <_NasgenJavaCompilerClasspathArg>$(_NasgenJavaCompilerClasspathArg.Replace('\', '\\')) + + + + <_NasgenJavaCompilerArgs Include="-bootclasspath" /> + <_NasgenJavaCompilerArgs Include=""$([MSBuild]::Escape('$(_NasgenJavaCompilerClasspathArg)'))"" /> + <_NasgenJavaCompilerArgs Include="-g" /> + <_NasgenJavaCompilerArgs Include="-source" /> + <_NasgenJavaCompilerArgs Include="7" /> + <_NasgenJavaCompilerArgs Include="-target" /> + <_NasgenJavaCompilerArgs Include="7" /> + <_NasgenJavaCompilerArgs Include="-nowarn" /> + <_NasgenJavaCompilerArgs Include="-d" /> + <_NasgenJavaCompilerArgs Include="$(NasgenOutputPath)" /> + <_NasgenJavaCompilerArgs Include="@(NasgenSource->'%(FullPath)')" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_NasgenClasspath Include="$([System.IO.Path]::GetFullPath('$(NasgenOutputPath)'))" /> + <_NasgenClasspath Include="$([System.IO.Path]::GetFullPath('$(NashornTempPath)'))" /> + + + + <_NasgenClasspathArg>@(_NasgenClasspath, '$([System.IO.Path]::PathSeparator)') + <_NasgenClasspathArg>$(_NasgenClasspathArg.Replace('\', '\\')) + + + + + + + + + + + + + + + + + + + RunNasgen; + $(CoreCompileDependsOn); + + + + diff --git a/src/IKVM.Java/IKVM.Java.runtime.props b/src/IKVM.Java/IKVM.Java.runtime.props index a11735371f..7de4381491 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.props +++ b/src/IKVM.Java/IKVM.Java.runtime.props @@ -65,7 +65,7 @@ - + diff --git a/src/IKVM.Java/IKVM.Java.runtime.targets b/src/IKVM.Java/IKVM.Java.runtime.targets index 0b718e46a3..99eab65c94 100644 --- a/src/IKVM.Java/IKVM.Java.runtime.targets +++ b/src/IKVM.Java/IKVM.Java.runtime.targets @@ -39,294 +39,118 @@ - - OpenJdkBuildTools; - $(GenerateSourceDependsOn); - + + BuildJdkBuildTools; + $(GenerateDependsOn); + - - - - - - - - - - - - - - - - - - - - - - - <_Dest>$(IntermediateOutputPath)genprop\%(PackagePath)\%(ClassName).java - - <_Args Remove="@(_Args)" /> - - - - - - - - - - - - - - - - - - - - - GenerateResourceBundles; - $(GenerateSourceDependsOn); - - - - - - - - - - - - - - - - - - - - - - - - - <_Dest>$(IntermediateOutputPath)genprop\%(PackagePath)\%(ResourceName).properties - - <_Args Remove="@(_Args)" /> - - - - - - - - - - - - - - - - - - - - CleanProperties; - $(GenerateSourceDependsOn); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - FilterDuplicateProperties; - DuplicateProperties; - $(GenerateSourceDependsOn); - + $(IntermediateOutputPath)gensvc\ - - - - - - - - - - - i.GetMetadata("ServiceName")).Select(i => i.First()).ToArray(); - ]]> - - - - - - + + + + + + >(); - foreach (var f in SourceFiles) + foreach (var file in SourceFile) { - var n = f.GetMetadata("ServiceName"); - var o = f.GetMetadata("OutputPath"); - Directory.CreateDirectory(Path.GetDirectoryName(o)); - - using var r = File.OpenText(f.ItemSpec); - using var w = new StreamWriter(File.Open(o, FileMode.Create)); - + var name = file.GetMetadata("ServiceName"); + if (string.IsNullOrEmpty(name)) + name = file.GetMetadata("Filename") + file.GetMetadata("Extension"); + + var list = svcs.GetOrAdd(name, _ => new List()); + + using var r = File.OpenText(file.ItemSpec); string line; while ((line = r.ReadLine()) != null) { - if (line.StartsWith(p)) - line = line.Substring(p.Length); - - w.WriteLine(line); + if (line.StartsWith(keep)) + line = line.Substring(keep.Length); + if (line.StartsWith("#")) + continue; + if (string.IsNullOrWhiteSpace(line)) + continue; + + list.Add(line); } } + + var o = new List(); + + foreach (var kvp in svcs) + { + // assemble new version of file + var text = new StringBuilder(); + foreach (var line in kvp.Value) + text.AppendLine(line); + + var path = Path.Combine(TargetPath, kvp.Key); + var orig = File.Exists(path) ? File.ReadAllText(path) : ""; + var curr = text.ToString(); + if (curr != orig || File.Exists(path) == false) + File.WriteAllText(path, curr); + + o.Add(new TaskItem(path)); + } + + OutputFile = o.ToArray(); ]]> - - - - - $(IntermediateOutputPath)gensvc\%(ServiceName) - - - - - - - - - + + + - - - - + + - - UpdateServiceFiles; + GenerateServiceFiles; - CollectServiceFiles; - $(GenerateSourceDependsOn); - + $(CompileJavaDependsOn); + - - $(GenerateSourceDependsOn); - + + $(GenerateDependsOn); + - + - GenerateSource; + Generate; $(CompileJavaDependsOn); - - - $(CoreCleanDependsOn); - CleanGenerateSource; - - - @@ -345,5 +169,7 @@ File.WriteAllBytes(Path, Encoding.UTF8.GetBytes(Text)); + + diff --git a/src/IKVM.Java/local/ikvm/internal/io/FileStreamExtensions.java b/src/IKVM.Java/local/ikvm/internal/io/FileStreamExtensions.java deleted file mode 100644 index 9e724a7755..0000000000 --- a/src/IKVM.Java/local/ikvm/internal/io/FileStreamExtensions.java +++ /dev/null @@ -1,23 +0,0 @@ -package ikvm.internal.io; - -import cli.System.IO.FileAccess; -import cli.System.IO.FileMode; -import cli.System.IO.FileOptions; -import cli.System.IO.FileShare; -import cli.System.IO.FileStream; -import cli.System.Security.AccessControl.FileSystemRights; - -import ikvm.lang.Internal; - -@Internal -public final class FileStreamExtensions -{ - - public static FileStream create(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options) throws java.io.IOException - { - return createInternal(path, mode, rights, share, bufferSize, options); - } - - static native FileStream createInternal(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options) throws java.io.IOException; - -} diff --git a/src/IKVM.Java/local/ikvm/runtime/Startup.java b/src/IKVM.Java/local/ikvm/runtime/Startup.java index d68a5dd102..a39ca947b3 100644 --- a/src/IKVM.Java/local/ikvm/runtime/Startup.java +++ b/src/IKVM.Java/local/ikvm/runtime/Startup.java @@ -8,7 +8,7 @@ private Startup() { @ikvm.lang.ModuleInitializer public static void init() { - cli.System.GC.KeepAlive(cli.IKVM.Runtime.JVM.class); + cli.System.GC.KeepAlive(cli.IKVM.Runtime.RuntimeUtil.get_RuntimeIdentifier()); }; /** diff --git a/src/IKVM.Java/local/java/lang/System.java b/src/IKVM.Java/local/java/lang/System.java index 12c7cad6ab..275726b9dd 100644 --- a/src/IKVM.Java/local/java/lang/System.java +++ b/src/IKVM.Java/local/java/lang/System.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, 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 @@ -43,6 +43,8 @@ import sun.security.util.SecurityConstants; import sun.reflect.annotation.AnnotationType; +import jdk.internal.util.StaticProperty; + /** * The System class contains several useful class fields * and methods. It cannot be instantiated. @@ -578,6 +580,10 @@ public static native void arraycopy(Object src, int srcPos, * Java installation directory * java.vm.specification.version * Java Virtual Machine specification version + * java.specification.maintenance.version + * Java Runtime Environment specification maintenance + * version, may be interpreted as a positive integer + * (optional, see below) * java.vm.specification.vendor * Java Virtual Machine specification vendor * java.vm.specification.name @@ -629,6 +635,16 @@ public static native void arraycopy(Object src, int srcPos, * User's current working directory * *

+ * The {@code java.specification.maintenance.version} property is + * defined if the specification implemented by this runtime at the + * time of its construction had undergone a maintenance + * release. When defined, its value identifies that + * maintenance release. To indicate the first maintenance release + * this property will have the value {@code "1"}, to indicate the + * second maintenance release this property will have the value + * {@code "2"}, and so on. + *

* Multiple paths in a system property value are separated by the path * separator character of the platform. *

@@ -1037,29 +1053,27 @@ public static void runFinalization() { } /** - * Enable or disable finalization on exit; doing so specifies that the - * finalizers of all objects that have finalizers that have not yet been - * automatically invoked are to be run before the Java runtime exits. - * By default, finalization on exit is disabled. - * - *

If there is a security manager, - * its checkExit method is first called - * with 0 as its argument to ensure the exit is allowed. - * This could result in a SecurityException. - * - * @deprecated This method is inherently unsafe. It may result in - * finalizers being called on live objects while other threads are - * concurrently manipulating those objects, resulting in erratic - * behavior or deadlock. - * @param value indicating enabling or disabling of finalization - * @throws SecurityException - * if a security manager exists and its checkExit - * method doesn't allow the exit. + * Throws {@code UnsupportedOperationException}. * - * @see java.lang.Runtime#exit(int) - * @see java.lang.Runtime#gc() - * @see java.lang.SecurityManager#checkExit(int) - * @since JDK1.1 + *

The call {@code System.runFinalizersOnExit()} is effectively + * equivalent to the call: + *

+     * Runtime.runFinalizersOnExit()
+     * 
+ * + * @param value ignored + * + * @deprecated This method was originally designed to enable or disable + * running finalizers on exit. Running finalizers on exit was disabled + * by default. If enabled, then the finalizers of all objects whose + * finalizers had not yet been automatically invoked were to be run before + * the Java runtime exits. That behavior is inherently unsafe. It may + * result in finalizers being called on live objects while other threads + * are concurrently manipulating those objects, resulting in erratic + * behavior or deadlock. + * + * @see java.lang.Runtime#runFinalizersOnExit(boolean) + * @since JDK1.1 */ @Deprecated public static void runFinalizersOnExit(boolean value) { @@ -1204,6 +1218,7 @@ private static void initializeSystemClass() { lineSeparator = props.getProperty("line.separator"); + StaticProperty.jdkSerialFilter(); // Load StaticProperty to cache the property values sun.misc.Version.init(); FileInputStream fdIn = new FileInputStream(FileDescriptor.in); diff --git a/src/IKVM.Java/local/java/lang/Thread.java b/src/IKVM.Java/local/java/lang/Thread.java index 706922e9d1..75e854a3bd 100644 --- a/src/IKVM.Java/local/java/lang/Thread.java +++ b/src/IKVM.Java/local/java/lang/Thread.java @@ -36,6 +36,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.LockSupport; + +import jdk.internal.misc.TerminatingThreadLocal; import sun.nio.ch.Interruptible; import sun.reflect.CallerSensitive; import sun.reflect.Reflection; @@ -1040,6 +1042,9 @@ public void Invoke(Object thread) { * a chance to clean up before it actually exits. */ private void exit() { + if (threadLocals != null && TerminatingThreadLocal.REGISTRY.isPresent()) { + TerminatingThreadLocal.threadTerminated(); + } if (group != null) { group.threadTerminated(this); group = null; diff --git a/src/IKVM.Java/local/java/lang/ref/Reference.java b/src/IKVM.Java/local/java/lang/ref/Reference.java index 441659d358..5a3ce95204 100644 --- a/src/IKVM.Java/local/java/lang/ref/Reference.java +++ b/src/IKVM.Java/local/java/lang/ref/Reference.java @@ -27,43 +27,20 @@ public abstract class Reference { + private final cli.System.WeakReference weakRef; T strongRef; - ReferenceQueue queue; + + volatile ReferenceQueue queue; + + /* When active: NULL + * pending: this + * Enqueued: next reference in queue (or this if last) + * Inactive: this + */ + @SuppressWarnings("rawtypes") volatile Reference next; - Reference(T referent) - { - this(referent, null); - } - - Reference(T referent, ReferenceQueue queue) - { - this.queue = queue == null ? ReferenceQueue.NULL : queue; - if (referent instanceof Class && noclassgc()) - { - // We don't do Class gc, so no point in using a weak reference for classes. - weakRef = null; - strongRef = referent; - } - else if (referent == null) - { - weakRef = null; - } - else - { - weakRef = new cli.System.WeakReference(referent, this instanceof PhantomReference); - if (queue != null) - { - queue.addToActiveList(this); - } - if (this instanceof Cleaner) - { - new CleanerGuard(); - } - } - } - private final class CleanerGuard { protected void finalize() @@ -76,6 +53,28 @@ protected void finalize() } } + final boolean isActive() + { + return strongRef != null || (weakRef != null && weakRef.get_IsAlive()); + } + + final boolean isStrongOrNullRef() + { + return weakRef == null; + } + + static native boolean noclassgc(); + + /* -- Referent accessor and setters -- */ + + /** + * Returns this reference object's referent. If this reference object has + * been cleared, either by the program or by the garbage collector, then + * this method returns null. + * + * @return The object to which this reference refers, or + * null if this reference object has been cleared + */ public T get() { if (weakRef == null) @@ -84,7 +83,14 @@ public T get() } return (T)weakRef.get_Target(); } - + + /** + * Clears this reference object. Invoking this method will not cause this + * object to be enqueued. + * + *

This method is invoked only by Java code; when the garbage collector + * clears references it does so directly, without invoking this method. + */ public void clear() { if (weakRef != null) @@ -103,6 +109,15 @@ public void clear() queue.clear(this); } + /** + * Tells whether or not this reference object has been enqueued, either by + * the program or by the garbage collector. If this reference object was + * not registered with a queue when it was created, then this method will + * always return false. + * + * @return true if and only if this reference object has + * been enqueued + */ public boolean isEnqueued() { if (queue == ReferenceQueue.ENQUEUED) { @@ -114,24 +129,86 @@ public boolean isEnqueued() if (isStrongOrNullRef() || isActive()) { return false; } - queue.enqueue(this); + queue.enqueue((Reference)this); return queue == ReferenceQueue.ENQUEUED; } - public boolean enqueue() - { - return queue.enqueue(this); + /** + * Clears this reference object and adds it to the queue with which + * it is registered, if any. + * + *

This method is invoked only by Java code; when the garbage collector + * enqueues references it does so directly, without invoking this method. + * + * @return true if this reference object was successfully + * enqueued; false if it was already enqueued or if + * it was not registered with a queue when it was created + */ + public boolean enqueue() { + if (weakRef != null) + { + try + { + if (false) throw new cli.System.InvalidOperationException(); + weakRef.set_Target(null); + } + catch (cli.System.InvalidOperationException x) + { + // we were already finalized + } + } + strongRef = null; + return this.queue.enqueue((Reference)this); } - final boolean isActive() + /** + * Throws {@link CloneNotSupportedException}. A {@code Reference} cannot be + * meaningfully cloned. Construct a new {@code Reference} instead. + * + * @apiNote This method is defined in Java SE 8 Maintenance Release 4. + * + * @return never returns normally + * @throws CloneNotSupportedException always + * + * @since 8 + */ + @Override + protected Object clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } + + /* -- Constructors -- */ + + Reference(T referent) { - return strongRef != null || (weakRef != null && weakRef.get_IsAlive()); + this(referent, null); } - final boolean isStrongOrNullRef() + Reference(T referent, ReferenceQueue queue) { - return weakRef == null; + this.queue = queue == null ? ReferenceQueue.NULL : queue; + if (referent instanceof Class && noclassgc()) + { + // We don't do Class gc, so no point in using a weak reference for classes. + weakRef = null; + strongRef = referent; + } + else if (referent == null) + { + weakRef = null; + } + else + { + weakRef = new cli.System.WeakReference(referent, this instanceof PhantomReference); + if (queue != null) + { + queue.addToActiveList(this); + } + if (this instanceof Cleaner) + { + new CleanerGuard(); + } + } } - static native boolean noclassgc(); } diff --git a/src/IKVM.Java/local/java/lang/reflect/Proxy.java b/src/IKVM.Java/local/java/lang/reflect/Proxy.java deleted file mode 100644 index de7416db1b..0000000000 --- a/src/IKVM.Java/local/java/lang/reflect/Proxy.java +++ /dev/null @@ -1,843 +0,0 @@ -/* - * Copyright (c) 1999, 2013, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package java.lang.reflect; - -import java.lang.ref.WeakReference; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Arrays; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.BiFunction; -import sun.misc.ProxyGenerator; -import sun.misc.VM; -import sun.reflect.CallerSensitive; -import sun.reflect.Reflection; -import sun.reflect.misc.ReflectUtil; -import sun.security.util.SecurityConstants; - -/** - * {@code Proxy} provides static methods for creating dynamic proxy - * classes and instances, and it is also the superclass of all - * dynamic proxy classes created by those methods. - * - *

To create a proxy for some interface {@code Foo}: - *

- *     InvocationHandler handler = new MyInvocationHandler(...);
- *     Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
- *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
- *                     newInstance(handler);
- * 
- * or more simply: - *
- *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- *                                          new Class<?>[] { Foo.class },
- *                                          handler);
- * 
- * - *

A dynamic proxy class (simply referred to as a proxy - * class below) is a class that implements a list of interfaces - * specified at runtime when the class is created, with behavior as - * described below. - * - * A proxy interface is such an interface that is implemented - * by a proxy class. - * - * A proxy instance is an instance of a proxy class. - * - * Each proxy instance has an associated invocation handler - * object, which implements the interface {@link InvocationHandler}. - * A method invocation on a proxy instance through one of its proxy - * interfaces will be dispatched to the {@link InvocationHandler#invoke - * invoke} method of the instance's invocation handler, passing the proxy - * instance, a {@code java.lang.reflect.Method} object identifying - * the method that was invoked, and an array of type {@code Object} - * containing the arguments. The invocation handler processes the - * encoded method invocation as appropriate and the result that it - * returns will be returned as the result of the method invocation on - * the proxy instance. - * - *

A proxy class has the following properties: - * - *

    - *
  • Proxy classes are public, final, and not abstract if - * all proxy interfaces are public.
  • - * - *
  • Proxy classes are non-public, final, and not abstract if - * any of the proxy interfaces is non-public.
  • - * - *
  • The unqualified name of a proxy class is unspecified. The space - * of class names that begin with the string {@code "$Proxy"} - * should be, however, reserved for proxy classes. - * - *
  • A proxy class extends {@code java.lang.reflect.Proxy}. - * - *
  • A proxy class implements exactly the interfaces specified at its - * creation, in the same order. - * - *
  • If a proxy class implements a non-public interface, then it will - * be defined in the same package as that interface. Otherwise, the - * package of a proxy class is also unspecified. Note that package - * sealing will not prevent a proxy class from being successfully defined - * in a particular package at runtime, and neither will classes already - * defined by the same class loader and the same package with particular - * signers. - * - *
  • Since a proxy class implements all of the interfaces specified at - * its creation, invoking {@code getInterfaces} on its - * {@code Class} object will return an array containing the same - * list of interfaces (in the order specified at its creation), invoking - * {@code getMethods} on its {@code Class} object will return - * an array of {@code Method} objects that include all of the - * methods in those interfaces, and invoking {@code getMethod} will - * find methods in the proxy interfaces as would be expected. - * - *
  • The {@link Proxy#isProxyClass Proxy.isProxyClass} method will - * return true if it is passed a proxy class-- a class returned by - * {@code Proxy.getProxyClass} or the class of an object returned by - * {@code Proxy.newProxyInstance}-- and false otherwise. - * - *
  • The {@code java.security.ProtectionDomain} of a proxy class - * is the same as that of system classes loaded by the bootstrap class - * loader, such as {@code java.lang.Object}, because the code for a - * proxy class is generated by trusted system code. This protection - * domain will typically be granted - * {@code java.security.AllPermission}. - * - *
  • Each proxy class has one public constructor that takes one argument, - * an implementation of the interface {@link InvocationHandler}, to set - * the invocation handler for a proxy instance. Rather than having to use - * the reflection API to access the public constructor, a proxy instance - * can be also be created by calling the {@link Proxy#newProxyInstance - * Proxy.newProxyInstance} method, which combines the actions of calling - * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the - * constructor with an invocation handler. - *
- * - *

A proxy instance has the following properties: - * - *

    - *
  • Given a proxy instance {@code proxy} and one of the - * interfaces implemented by its proxy class {@code Foo}, the - * following expression will return true: - *
    - *     {@code proxy instanceof Foo}
    - * 
    - * and the following cast operation will succeed (rather than throwing - * a {@code ClassCastException}): - *
    - *     {@code (Foo) proxy}
    - * 
    - * - *
  • Each proxy instance has an associated invocation handler, the one - * that was passed to its constructor. The static - * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method - * will return the invocation handler associated with the proxy instance - * passed as its argument. - * - *
  • An interface method invocation on a proxy instance will be - * encoded and dispatched to the invocation handler's {@link - * InvocationHandler#invoke invoke} method as described in the - * documentation for that method. - * - *
  • An invocation of the {@code hashCode}, - * {@code equals}, or {@code toString} methods declared in - * {@code java.lang.Object} on a proxy instance will be encoded and - * dispatched to the invocation handler's {@code invoke} method in - * the same manner as interface method invocations are encoded and - * dispatched, as described above. The declaring class of the - * {@code Method} object passed to {@code invoke} will be - * {@code java.lang.Object}. Other public methods of a proxy - * instance inherited from {@code java.lang.Object} are not - * overridden by a proxy class, so invocations of those methods behave - * like they do for instances of {@code java.lang.Object}. - *
- * - *

Methods Duplicated in Multiple Proxy Interfaces

- * - *

When two or more interfaces of a proxy class contain a method with - * the same name and parameter signature, the order of the proxy class's - * interfaces becomes significant. When such a duplicate method - * is invoked on a proxy instance, the {@code Method} object passed - * to the invocation handler will not necessarily be the one whose - * declaring class is assignable from the reference type of the interface - * that the proxy's method was invoked through. This limitation exists - * because the corresponding method implementation in the generated proxy - * class cannot determine which interface it was invoked through. - * Therefore, when a duplicate method is invoked on a proxy instance, - * the {@code Method} object for the method in the foremost interface - * that contains the method (either directly or inherited through a - * superinterface) in the proxy class's list of interfaces is passed to - * the invocation handler's {@code invoke} method, regardless of the - * reference type through which the method invocation occurred. - * - *

If a proxy interface contains a method with the same name and - * parameter signature as the {@code hashCode}, {@code equals}, - * or {@code toString} methods of {@code java.lang.Object}, - * when such a method is invoked on a proxy instance, the - * {@code Method} object passed to the invocation handler will have - * {@code java.lang.Object} as its declaring class. In other words, - * the public, non-final methods of {@code java.lang.Object} - * logically precede all of the proxy interfaces for the determination of - * which {@code Method} object to pass to the invocation handler. - * - *

Note also that when a duplicate method is dispatched to an - * invocation handler, the {@code invoke} method may only throw - * checked exception types that are assignable to one of the exception - * types in the {@code throws} clause of the method in all of - * the proxy interfaces that it can be invoked through. If the - * {@code invoke} method throws a checked exception that is not - * assignable to any of the exception types declared by the method in one - * of the proxy interfaces that it can be invoked through, then an - * unchecked {@code UndeclaredThrowableException} will be thrown by - * the invocation on the proxy instance. This restriction means that not - * all of the exception types returned by invoking - * {@code getExceptionTypes} on the {@code Method} object - * passed to the {@code invoke} method can necessarily be thrown - * successfully by the {@code invoke} method. - * - * @author Peter Jones - * @see InvocationHandler - * @since 1.3 - */ -public class Proxy implements java.io.Serializable { - - private static final long serialVersionUID = -2222568056686623797L; - - /** parameter types of a proxy class constructor */ - private static final Class[] constructorParams = - { InvocationHandler.class }; - - /** - * a cache of proxy classes - */ - private static final WeakCache[], Class> - proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); - - /** - * the invocation handler for this proxy instance. - * @serial - */ - protected InvocationHandler h; - - /** - * Prohibits instantiation. - */ - private Proxy() { - } - - /** - * Constructs a new {@code Proxy} instance from a subclass - * (typically, a dynamic proxy class) with the specified value - * for its invocation handler. - * - * @param h the invocation handler for this proxy instance - * - * @throws NullPointerException if the given invocation handler, {@code h}, - * is {@code null}. - */ - protected Proxy(InvocationHandler h) { - Objects.requireNonNull(h); - this.h = h; - } - - /** - * Returns the {@code java.lang.Class} object for a proxy class - * given a class loader and an array of interfaces. The proxy class - * will be defined by the specified class loader and will implement - * all of the supplied interfaces. If any of the given interfaces - * is non-public, the proxy class will be non-public. If a proxy class - * for the same permutation of interfaces has already been defined by the - * class loader, then the existing proxy class will be returned; otherwise, - * a proxy class for those interfaces will be generated dynamically - * and defined by the class loader. - * - *

There are several restrictions on the parameters that may be - * passed to {@code Proxy.getProxyClass}: - * - *

    - *
  • All of the {@code Class} objects in the - * {@code interfaces} array must represent interfaces, not - * classes or primitive types. - * - *
  • No two elements in the {@code interfaces} array may - * refer to identical {@code Class} objects. - * - *
  • All of the interface types must be visible by name through the - * specified class loader. In other words, for class loader - * {@code cl} and every interface {@code i}, the following - * expression must be true: - *
    -     *     Class.forName(i.getName(), false, cl) == i
    -     * 
    - * - *
  • All non-public interfaces must be in the same package; - * otherwise, it would not be possible for the proxy class to - * implement all of the interfaces, regardless of what package it is - * defined in. - * - *
  • For any set of member methods of the specified interfaces - * that have the same signature: - *
      - *
    • If the return type of any of the methods is a primitive - * type or void, then all of the methods must have that same - * return type. - *
    • Otherwise, one of the methods must have a return type that - * is assignable to all of the return types of the rest of the - * methods. - *
    - * - *
  • The resulting proxy class must not exceed any limits imposed - * on classes by the virtual machine. For example, the VM may limit - * the number of interfaces that a class may implement to 65535; in - * that case, the size of the {@code interfaces} array must not - * exceed 65535. - *
- * - *

If any of these restrictions are violated, - * {@code Proxy.getProxyClass} will throw an - * {@code IllegalArgumentException}. If the {@code interfaces} - * array argument or any of its elements are {@code null}, a - * {@code NullPointerException} will be thrown. - * - *

Note that the order of the specified proxy interfaces is - * significant: two requests for a proxy class with the same combination - * of interfaces but in a different order will result in two distinct - * proxy classes. - * - * @param loader the class loader to define the proxy class - * @param interfaces the list of interfaces for the proxy class - * to implement - * @return a proxy class that is defined in the specified class loader - * and that implements the specified interfaces - * @throws IllegalArgumentException if any of the restrictions on the - * parameters that may be passed to {@code getProxyClass} - * are violated - * @throws SecurityException if a security manager, s, is present - * and any of the following conditions is met: - *

    - *
  • the given {@code loader} is {@code null} and - * the caller's class loader is not {@code null} and the - * invocation of {@link SecurityManager#checkPermission - * s.checkPermission} with - * {@code RuntimePermission("getClassLoader")} permission - * denies access.
  • - *
  • for each proxy interface, {@code intf}, - * the caller's class loader is not the same as or an - * ancestor of the class loader for {@code intf} and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to {@code intf}.
  • - *
- - * @throws NullPointerException if the {@code interfaces} array - * argument or any of its elements are {@code null} - */ - @CallerSensitive - public static Class getProxyClass(ClassLoader loader, - Class... interfaces) - throws IllegalArgumentException - { - final Class[] intfs = interfaces.clone(); - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkProxyAccess(Reflection.getCallerClass(), loader, intfs); - } - - return getProxyClass0(loader, intfs); - } - - /* - * Check permissions required to create a Proxy class. - * - * To define a proxy class, it performs the access checks as in - * Class.forName (VM will invoke ClassLoader.checkPackageAccess): - * 1. "getClassLoader" permission check if loader == null - * 2. checkPackageAccess on the interfaces it implements - * - * To get a constructor and new instance of a proxy class, it performs - * the package access check on the interfaces it implements - * as in Class.getConstructor. - * - * If an interface is non-public, the proxy class must be defined by - * the defining loader of the interface. If the caller's class loader - * is not the same as the defining loader of the interface, the VM - * will throw IllegalAccessError when the generated proxy class is - * being defined via the defineClass0 method. - */ - private static void checkProxyAccess(Class caller, - ClassLoader loader, - Class... interfaces) - { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ClassLoader ccl = caller.getClassLoader(); - if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } - ReflectUtil.checkProxyPackageAccess(ccl, interfaces); - } - } - - /** - * Generate a proxy class. Must call the checkProxyAccess method - * to perform permission checks before calling this. - */ - private static Class getProxyClass0(ClassLoader loader, - Class... interfaces) { - if (interfaces.length > 65535) { - throw new IllegalArgumentException("interface limit exceeded"); - } - - // If the proxy class defined by the given loader implementing - // the given interfaces exists, this will simply return the cached copy; - // otherwise, it will create the proxy class via the ProxyClassFactory - return proxyClassCache.get(loader, interfaces); - } - - /* - * a key used for proxy class with 0 implemented interfaces - */ - private static final Object key0 = new Object(); - - /* - * Key1 and Key2 are optimized for the common use of dynamic proxies - * that implement 1 or 2 interfaces. - */ - - /* - * a key used for proxy class with 1 implemented interface - */ - private static final class Key1 extends WeakReference> { - private final int hash; - - Key1(Class intf) { - super(intf); - this.hash = intf.hashCode(); - } - - @Override - public int hashCode() { - return hash; - } - - @Override - public boolean equals(Object obj) { - Class intf; - return this == obj || - obj != null && - obj.getClass() == Key1.class && - (intf = get()) != null && - intf == ((Key1) obj).get(); - } - } - - /* - * a key used for proxy class with 2 implemented interfaces - */ - private static final class Key2 extends WeakReference> { - private final int hash; - private final WeakReference> ref2; - - Key2(Class intf1, Class intf2) { - super(intf1); - hash = 31 * intf1.hashCode() + intf2.hashCode(); - ref2 = new WeakReference>(intf2); - } - - @Override - public int hashCode() { - return hash; - } - - @Override - public boolean equals(Object obj) { - Class intf1, intf2; - return this == obj || - obj != null && - obj.getClass() == Key2.class && - (intf1 = get()) != null && - intf1 == ((Key2) obj).get() && - (intf2 = ref2.get()) != null && - intf2 == ((Key2) obj).ref2.get(); - } - } - - /* - * a key used for proxy class with any number of implemented interfaces - * (used here for 3 or more only) - */ - private static final class KeyX { - private final int hash; - private final WeakReference>[] refs; - - @SuppressWarnings("unchecked") - KeyX(Class[] interfaces) { - hash = Arrays.hashCode(interfaces); - refs = (WeakReference>[])new WeakReference[interfaces.length]; - for (int i = 0; i < interfaces.length; i++) { - refs[i] = new WeakReference<>(interfaces[i]); - } - } - - @Override - public int hashCode() { - return hash; - } - - @Override - public boolean equals(Object obj) { - return this == obj || - obj != null && - obj.getClass() == KeyX.class && - equals(refs, ((KeyX) obj).refs); - } - - private static boolean equals(WeakReference>[] refs1, - WeakReference>[] refs2) { - if (refs1.length != refs2.length) { - return false; - } - for (int i = 0; i < refs1.length; i++) { - Class intf = refs1[i].get(); - if (intf == null || intf != refs2[i].get()) { - return false; - } - } - return true; - } - } - - /** - * A function that maps an array of interfaces to an optimal key where - * Class objects representing interfaces are weakly referenced. - */ - private static final class KeyFactory - implements BiFunction[], Object> - { - @Override - public Object apply(ClassLoader classLoader, Class[] interfaces) { - switch (interfaces.length) { - case 1: return new Key1(interfaces[0]); // the most frequent - case 2: return new Key2(interfaces[0], interfaces[1]); - case 0: return key0; - default: return new KeyX(interfaces); - } - } - } - - /** - * A factory function that generates, defines and returns the proxy class given - * the ClassLoader and array of interfaces. - */ - private static final class ProxyClassFactory - implements BiFunction[], Class> - { - // prefix for all proxy class names - private static final String proxyClassNamePrefix = "$Proxy"; - - // next number to use for generation of unique proxy class names - private static final AtomicLong nextUniqueNumber = new AtomicLong(); - - @Override - public Class apply(ClassLoader loader, Class[] interfaces) { - - Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); - for (Class intf : interfaces) { - /* - * Verify that the class loader resolves the name of this - * interface to the same Class object. - */ - Class interfaceClass = null; - try { - interfaceClass = Class.forName(intf.getName(), false, loader); - } catch (ClassNotFoundException e) { - } - if (interfaceClass != intf) { - throw new IllegalArgumentException( - intf + " is not visible from class loader"); - } - /* - * Verify that the Class object actually represents an - * interface. - */ - if (!interfaceClass.isInterface()) { - throw new IllegalArgumentException( - interfaceClass.getName() + " is not an interface"); - } - /* - * Verify that this interface is not a duplicate. - */ - if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { - throw new IllegalArgumentException( - "repeated interface: " + interfaceClass.getName()); - } - } - - String proxyPkg = null; // package to define proxy class in - int accessFlags = Modifier.PUBLIC | Modifier.FINAL; - - /* - * Record the package of a non-public proxy interface so that the - * proxy class will be defined in the same package. Verify that - * all non-public proxy interfaces are in the same package. - */ - for (Class intf : interfaces) { - int flags = intf.getModifiers(); - if (!Modifier.isPublic(flags)) { - accessFlags = Modifier.FINAL; - String name = intf.getName(); - int n = name.lastIndexOf('.'); - String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); - if (proxyPkg == null) { - proxyPkg = pkg; - } else if (!pkg.equals(proxyPkg)) { - throw new IllegalArgumentException( - "non-public interfaces from different packages"); - } - } - } - - if (proxyPkg == null) { - // if no non-public proxy interfaces, use com.sun.proxy package - proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; - } - - /* - * Choose a name for the proxy class to generate. - */ - long num = nextUniqueNumber.getAndIncrement(); - String proxyName = proxyPkg + proxyClassNamePrefix + num; - - Class precompiledProxyClass = getPrecompiledProxy(loader, proxyName, interfaces); - if (precompiledProxyClass != null) { - return precompiledProxyClass; - } - - /* - * Generate the specified proxy class. - */ - byte[] proxyClassFile = ProxyGenerator.generateProxyClass( - proxyName, interfaces, accessFlags); - try { - return defineClass0(loader, proxyName, - proxyClassFile, 0, proxyClassFile.length); - } catch (ClassFormatError e) { - /* - * A ClassFormatError here means that (barring bugs in the - * proxy class generation code) there was some other - * invalid aspect of the arguments supplied to the proxy - * class creation (such as virtual machine limitations - * exceeded). - */ - throw new IllegalArgumentException(e.toString()); - } - } - } - - /** - * Returns an instance of a proxy class for the specified interfaces - * that dispatches method invocations to the specified invocation - * handler. - * - *

{@code Proxy.newProxyInstance} throws - * {@code IllegalArgumentException} for the same reasons that - * {@code Proxy.getProxyClass} does. - * - * @param loader the class loader to define the proxy class - * @param interfaces the list of interfaces for the proxy class - * to implement - * @param h the invocation handler to dispatch method invocations to - * @return a proxy instance with the specified invocation handler of a - * proxy class that is defined by the specified class loader - * and that implements the specified interfaces - * @throws IllegalArgumentException if any of the restrictions on the - * parameters that may be passed to {@code getProxyClass} - * are violated - * @throws SecurityException if a security manager, s, is present - * and any of the following conditions is met: - *

    - *
  • the given {@code loader} is {@code null} and - * the caller's class loader is not {@code null} and the - * invocation of {@link SecurityManager#checkPermission - * s.checkPermission} with - * {@code RuntimePermission("getClassLoader")} permission - * denies access;
  • - *
  • for each proxy interface, {@code intf}, - * the caller's class loader is not the same as or an - * ancestor of the class loader for {@code intf} and - * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to {@code intf};
  • - *
  • any of the given proxy interfaces is non-public and the - * caller class is not in the same {@linkplain Package runtime package} - * as the non-public interface and the invocation of - * {@link SecurityManager#checkPermission s.checkPermission} with - * {@code ReflectPermission("newProxyInPackage.{package name}")} - * permission denies access.
  • - *
- * @throws NullPointerException if the {@code interfaces} array - * argument or any of its elements are {@code null}, or - * if the invocation handler, {@code h}, is - * {@code null} - */ - @CallerSensitive - public static Object newProxyInstance(ClassLoader loader, - Class[] interfaces, - InvocationHandler h) - throws IllegalArgumentException - { - Objects.requireNonNull(h); - - final Class[] intfs = interfaces.clone(); - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - checkProxyAccess(Reflection.getCallerClass(), loader, intfs); - } - - /* - * Look up or generate the designated proxy class. - */ - Class cl = getProxyClass0(loader, intfs); - - /* - * Invoke its constructor with the designated invocation handler. - */ - try { - if (sm != null) { - checkNewProxyPermission(Reflection.getCallerClass(), cl); - } - - final Constructor cons = cl.getConstructor(constructorParams); - final InvocationHandler ih = h; - if (!Modifier.isPublic(cl.getModifiers())) { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - cons.setAccessible(true); - return null; - } - }); - } - return cons.newInstance(new Object[]{h}); - } catch (IllegalAccessException|InstantiationException e) { - throw new InternalError(e.toString(), e); - } catch (InvocationTargetException e) { - Throwable t = e.getCause(); - if (t instanceof RuntimeException) { - throw (RuntimeException) t; - } else { - throw new InternalError(t.toString(), t); - } - } catch (NoSuchMethodException e) { - throw new InternalError(e.toString(), e); - } - } - - private static void checkNewProxyPermission(Class caller, Class proxyClass) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { - ClassLoader ccl = caller.getClassLoader(); - ClassLoader pcl = proxyClass.getClassLoader(); - - // do permission check if the caller is in a different runtime package - // of the proxy class - int n = proxyClass.getName().lastIndexOf('.'); - String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n); - - n = caller.getName().lastIndexOf('.'); - String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n); - - if (pcl != ccl || !pkg.equals(callerPkg)) { - sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg)); - } - } - } - } - - /** - * Returns true if and only if the specified class was dynamically - * generated to be a proxy class using the {@code getProxyClass} - * method or the {@code newProxyInstance} method. - * - *

The reliability of this method is important for the ability - * to use it to make security decisions, so its implementation should - * not just test if the class in question extends {@code Proxy}. - * - * @param cl the class to test - * @return {@code true} if the class is a proxy class and - * {@code false} otherwise - * @throws NullPointerException if {@code cl} is {@code null} - */ - public static boolean isProxyClass(Class cl) { - return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl); - } - - /** - * Returns the invocation handler for the specified proxy instance. - * - * @param proxy the proxy instance to return the invocation handler for - * @return the invocation handler for the proxy instance - * @throws IllegalArgumentException if the argument is not a - * proxy instance - * @throws SecurityException if a security manager, s, is present - * and the caller's class loader is not the same as or an - * ancestor of the class loader for the invocation handler - * and invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to the invocation - * handler's class. - */ - @CallerSensitive - public static InvocationHandler getInvocationHandler(Object proxy) - throws IllegalArgumentException - { - /* - * Verify that the object is actually a proxy instance. - */ - if (!isProxyClass(proxy.getClass())) { - throw new IllegalArgumentException("not a proxy instance"); - } - - final Proxy p = (Proxy) proxy; - final InvocationHandler ih = p.h; - if (System.getSecurityManager() != null) { - Class ihClass = ih.getClass(); - Class caller = Reflection.getCallerClass(); - if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), - ihClass.getClassLoader())) - { - ReflectUtil.checkPackageAccess(ihClass); - } - } - - return ih; - } - - private static native Class defineClass0(ClassLoader loader, String name, - byte[] b, int off, int len); - - private static native Class getPrecompiledProxy(ClassLoader loader, String proxyName, Class[] interfaces); -} diff --git a/src/IKVM.Java/local/java/util/zip/ZipFile.java b/src/IKVM.Java/local/java/util/zip/ZipFile.java index 48097b2d3d..2a43207fc5 100644 --- a/src/IKVM.Java/local/java/util/zip/ZipFile.java +++ b/src/IKVM.Java/local/java/util/zip/ZipFile.java @@ -51,6 +51,7 @@ import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.jar.JarFile; import java.util.stream.Stream; import static java.util.zip.ZipConstants64.*; @@ -96,6 +97,7 @@ public class ZipFile implements ZipConstants, Closeable private LinkedHashMap entries; private boolean closed = false; + private int manifestNum = 0; // number of META-INF/MANIFEST.MF, case insensitive final boolean hasLocHeader; /** @@ -312,6 +314,10 @@ private void readEntries() throws IOException { entry.comment = inp.readString(commentLen, (flags & EFS) != 0); } + if (isManifestName(entry.name)) + { + manifestNum++; + } entries.put(entry.name, entry); } @@ -896,13 +902,25 @@ public void addDummyByte() } } + private int getManifestNum() { + return manifestNum; + } + + public static boolean isManifestName(String name) + { + return JarFile.MANIFEST_NAME.equalsIgnoreCase(name); + } + static { sun.misc.SharedSecrets.setJavaUtilZipFileAccess( new sun.misc.JavaUtilZipFileAccess() { public boolean startsWithLocHeader(ZipFile zip) { return zip.hasLocHeader; } + public int getManifestNum(JarFile jar) { + return ((ZipFile)jar).getManifestNum(); + } } ); } -} +} \ No newline at end of file diff --git a/src/IKVM.Java/local/nashorn/.gitignore b/src/IKVM.Java/local/jdk/nashorn/internal/runtime/resources/.gitignore similarity index 100% rename from src/IKVM.Java/local/nashorn/.gitignore rename to src/IKVM.Java/local/jdk/nashorn/internal/runtime/resources/.gitignore diff --git a/src/IKVM.Java/local/nashorn/version.properties.tt b/src/IKVM.Java/local/jdk/nashorn/internal/runtime/resources/version.properties.tt similarity index 100% rename from src/IKVM.Java/local/nashorn/version.properties.tt rename to src/IKVM.Java/local/jdk/nashorn/internal/runtime/resources/version.properties.tt diff --git a/src/IKVM.MSBuild.Tasks/IkvmCompiler.cs b/src/IKVM.MSBuild.Tasks/IkvmCompiler.cs index d8b4fe24dd..92b90ee4d6 100644 --- a/src/IKVM.MSBuild.Tasks/IkvmCompiler.cs +++ b/src/IKVM.MSBuild.Tasks/IkvmCompiler.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; diff --git a/src/IKVM.MSBuild.Tests/IKVM.MSBuild.Tests.csproj b/src/IKVM.MSBuild.Tests/IKVM.MSBuild.Tests.csproj index 2562e921ab..0bcdb6c2bd 100644 --- a/src/IKVM.MSBuild.Tests/IKVM.MSBuild.Tests.csproj +++ b/src/IKVM.MSBuild.Tests/IKVM.MSBuild.Tests.csproj @@ -30,7 +30,6 @@ - diff --git a/src/IKVM.NET.Sdk.Tests/IKVM.NET.Sdk.Tests.csproj b/src/IKVM.NET.Sdk.Tests/IKVM.NET.Sdk.Tests.csproj index e1f0792548..29cc4b91f8 100644 --- a/src/IKVM.NET.Sdk.Tests/IKVM.NET.Sdk.Tests.csproj +++ b/src/IKVM.NET.Sdk.Tests/IKVM.NET.Sdk.Tests.csproj @@ -12,6 +12,7 @@ + @@ -22,7 +23,6 @@ - diff --git a/src/IKVM.NET.Sdk.Tests/ProjectTests.cs b/src/IKVM.NET.Sdk.Tests/ProjectTests.cs index 4be669bb5b..efcb6ae887 100644 --- a/src/IKVM.NET.Sdk.Tests/ProjectTests.cs +++ b/src/IKVM.NET.Sdk.Tests/ProjectTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -9,9 +10,13 @@ using Buildalyzer; using Buildalyzer.Environment; +using CliWrap; +using CliWrap.Buffered; + using FluentAssertions; using Microsoft.Build.Framework; +using Microsoft.Build.Tasks; using Microsoft.Build.Utilities; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -108,6 +113,7 @@ public static void Init(TestContext context) var analyzer = manager.GetProject(Path.Combine(TestRoot, "Exe", "ProjectExe.msbuildproj")); analyzer.AddBuildLogger(new TargetLogger(context)); analyzer.AddBinaryLogger(Path.Combine(WorkRoot, "msbuild.binlog")); + analyzer.SetEnvironmentVariable("NUGET_PACKAGES", ""); analyzer.SetGlobalProperty("ImportDirectoryBuildProps", "false"); analyzer.SetGlobalProperty("ImportDirectoryBuildTargets", "false"); analyzer.SetGlobalProperty("IkvmCacheDir", IkvmCachePath + Path.DirectorySeparatorChar); @@ -220,7 +226,7 @@ public static void ClassCleanup() [DataRow(EnvironmentPreference.Framework, "net8.0", "linux-musl-arm64", "{0}", "lib{0}.so")] [DataRow(EnvironmentPreference.Framework, "net8.0", "osx-x64", "{0}", "lib{0}.dylib")] [DataRow(EnvironmentPreference.Framework, "net8.0", "osx-arm64", "{0}", "lib{0}.dylib")] - public void CanBuildTestProject(EnvironmentPreference env, string tfm, string rid, string exe, string lib) + public async System.Threading.Tasks.Task CanBuildTestProject(EnvironmentPreference env, string tfm, string rid, string exe, string lib) { // skip framework tests for non-Windows platforms if (env == EnvironmentPreference.Framework || tfm == "net472" || tfm == "net48") @@ -231,6 +237,7 @@ public void CanBuildTestProject(EnvironmentPreference env, string tfm, string ri var analyzer = manager.GetProject(Path.Combine(@"Project", "Exe", "ProjectExe.msbuildproj")); analyzer.AddBuildLogger(new TargetLogger(TestContext)); analyzer.AddBinaryLogger(Path.Combine(WorkRoot, $"{env}-{tfm}-{rid}-msbuild.binlog")); + analyzer.SetEnvironmentVariable("NUGET_PACKAGES", ""); analyzer.SetGlobalProperty("ImportDirectoryBuildProps", "false"); analyzer.SetGlobalProperty("ImportDirectoryBuildTargets", "false"); analyzer.SetGlobalProperty("IkvmCacheDir", IkvmCachePath + Path.DirectorySeparatorChar); @@ -295,6 +302,28 @@ public void CanBuildTestProject(EnvironmentPreference env, string tfm, string ri foreach (var libName in new[] { "awt", "iava", "jvm", "management", "net", "nio", "sunec", "unpack", "verify" }) File.Exists(Path.Combine(outDir, "ikvm", rid, "bin", string.Format(lib, libName))).Should().BeTrue(); } + + // current rid matches target, execute and check output + if (GetCurrentRid() == rid) + (await Cli.Wrap(Path.Combine(binDir, "publish", string.Format(exe, "ProjectExe"))).WithArguments("Hello").ExecuteBufferedAsync()).StandardOutput.Trim().Should().Be("Hello"); + } + + ///

+ /// Gets the current RID. + /// + /// + string GetCurrentRid() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && RuntimeInformation.ProcessArchitecture == Architecture.X64) + return "win-x64"; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && RuntimeInformation.ProcessArchitecture == Architecture.X64) + return "linux-x64"; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && RuntimeInformation.ProcessArchitecture == Architecture.X64) + return "osx-x64"; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && RuntimeInformation.ProcessArchitecture == Architecture.Arm64) + return "osx-arm64"; + else + return null; } } diff --git a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets index 8ef5d2891c..f937f4ab57 100644 --- a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets +++ b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.NoTasks.targets @@ -152,6 +152,7 @@ Value = b.ToString(); + @@ -336,6 +337,8 @@ Value = b.ToString(); + +
diff --git a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets index 3c91ca25fb..f0106ab7ba 100644 --- a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets +++ b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.Tasks.targets @@ -149,6 +149,8 @@ + +
\ No newline at end of file diff --git a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.targets b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.targets index 4ecd78d8f3..9a80c4533d 100644 --- a/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.targets +++ b/src/IKVM.NET.Sdk/targets/IKVM.Java.Core.targets @@ -204,7 +204,7 @@ Files = files.ToArray(); - + diff --git a/src/IKVM.NET.Sdk/targets/IKVM.NET.Sdk.targets b/src/IKVM.NET.Sdk/targets/IKVM.NET.Sdk.targets index 61079b54c1..f06e0b65de 100644 --- a/src/IKVM.NET.Sdk/targets/IKVM.NET.Sdk.targets +++ b/src/IKVM.NET.Sdk/targets/IKVM.NET.Sdk.targets @@ -29,8 +29,8 @@ - - + + diff --git a/src/IKVM.OpenJDK.Tests/IKVM.OpenJDK.Tests.csproj b/src/IKVM.OpenJDK.Tests/IKVM.OpenJDK.Tests.csproj index 10be97e0c0..45443d8c7b 100644 --- a/src/IKVM.OpenJDK.Tests/IKVM.OpenJDK.Tests.csproj +++ b/src/IKVM.OpenJDK.Tests/IKVM.OpenJDK.Tests.csproj @@ -18,49 +18,39 @@ - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - + + + + PreserveNewest - + PreserveNewest - - jdk\ExcludeList.tfm.txt + + jdk\test\ExcludeList.tfm.txt PreserveNewest - + PreserveNewest - - langtools\ExcludeList.tfm.txt + + langtools\test\ExcludeList.tfm.txt PreserveNewest - + PreserveNewest - - nashorn\ExcludeList.tfm.txt + + nashorn\test\ExcludeList.tfm.txt PreserveNewest - - - - - diff --git a/src/IKVM.OpenJDK.Tests/Properties/AssemblyInfo.cs b/src/IKVM.OpenJDK.Tests/Properties/AssemblyInfo.cs index a95cf5006c..78f62262d0 100644 --- a/src/IKVM.OpenJDK.Tests/Properties/AssemblyInfo.cs +++ b/src/IKVM.OpenJDK.Tests/Properties/AssemblyInfo.cs @@ -1,5 +1,5 @@ using IKVM.JTReg.TestAdapter; -[assembly: JTRegTestSuite("jdk")] -[assembly: JTRegTestSuite("langtools")] -[assembly: JTRegTestSuite("nashorn")] +[assembly: JTRegTestSuite("jdk/test")] +[assembly: JTRegTestSuite("langtools/test")] +[assembly: JTRegTestSuite("nashorn/test")] diff --git a/src/IKVM.OpenJDK.Tests/jdk/ExcludeList.net6.0.txt b/src/IKVM.OpenJDK.Tests/jdk/test/ExcludeList.net6.0.txt similarity index 100% rename from src/IKVM.OpenJDK.Tests/jdk/ExcludeList.net6.0.txt rename to src/IKVM.OpenJDK.Tests/jdk/test/ExcludeList.net6.0.txt diff --git a/src/IKVM.OpenJDK.Tests/jdk/ExcludeList.net8.0.txt b/src/IKVM.OpenJDK.Tests/jdk/test/ExcludeList.net8.0.txt similarity index 73% rename from src/IKVM.OpenJDK.Tests/jdk/ExcludeList.net8.0.txt rename to src/IKVM.OpenJDK.Tests/jdk/test/ExcludeList.net8.0.txt index d96c2ace55..9b65827597 100644 --- a/src/IKVM.OpenJDK.Tests/jdk/ExcludeList.net8.0.txt +++ b/src/IKVM.OpenJDK.Tests/jdk/test/ExcludeList.net8.0.txt @@ -4,3 +4,6 @@ java/util/concurrent/Executors/AutoShutdown.java java/lang/ref/ReferenceEnqueuePending.java generic-all java/util/HashMap/HashMapCloneLeak.java generic-all java/util/logging/ClassLoaderLeakTest.java generic-all + +java/net/ipv6tests/UdpTest.java linux-all +java/net/PortUnreachableException/Test.java linux-all diff --git a/src/IKVM.OpenJDK.Tests/jdk/ExcludeList.txt b/src/IKVM.OpenJDK.Tests/jdk/test/ExcludeList.txt similarity index 84% rename from src/IKVM.OpenJDK.Tests/jdk/ExcludeList.txt rename to src/IKVM.OpenJDK.Tests/jdk/test/ExcludeList.txt index ae79b96313..54a82baecc 100644 --- a/src/IKVM.OpenJDK.Tests/jdk/ExcludeList.txt +++ b/src/IKVM.OpenJDK.Tests/jdk/test/ExcludeList.txt @@ -269,14 +269,6 @@ java/awt/Container/isRemoveNotifyNeeded/JInternalFrameTest.java java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java generic-all java/awt/Cursor/MultiResolutionCursorTest/MultiResolutionCursorTest.java generic-all java/awt/Cursor/PredefinedPrivate/PredefinedPrivate.java generic-all -java/awt/DataFlavor/MissedHtmlAndRtfBug/AbsoluteComponentCenterCalculator.java generic-all -java/awt/DataFlavor/MissedHtmlAndRtfBug/DataFlavorSearcher.java generic-all -java/awt/DataFlavor/MissedHtmlAndRtfBug/InterprocessMessages.java generic-all -java/awt/DataFlavor/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.html generic-all -java/awt/DataFlavor/MissedHtmlAndRtfBug/MyTransferable.java generic-all -java/awt/DataFlavor/MissedHtmlAndRtfBug/NextFramePositionCalculator.java generic-all -java/awt/DataFlavor/MissedHtmlAndRtfBug/SourcePanel.java generic-all -java/awt/DataFlavor/MissedHtmlAndRtfBug/TargetPanel.java generic-all java/awt/Desktop/8064934/bug8064934.java generic-all java/awt/Desktop/OpenByUNCPathNameTest/OpenByUNCPathNameTest.java generic-all java/awt/Dialog/CloseDialog/CloseDialogTest.java generic-all @@ -511,6 +503,7 @@ java/awt/Modal/ModalDialogOrderingTest/ModalDialogOrderingTest.java java/awt/Modal/ModalInternalFrameTest/ModalInternalFrameTest.java generic-all java/awt/Modal/NpeOnClose/NpeOnCloseTest.java generic-all java/awt/Modal/SupportedTest/SupportedTest.java generic-all +java/awt/Modal/ToFront/DialogToFrontNonModalTest.java generic-all java/awt/Modal/WsDisabledStyle/CloseBlocker/CloseBlocker.java generic-all java/awt/Modal/WsDisabledStyle/OverBlocker/OverBlocker.java generic-all java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java generic-all @@ -522,7 +515,7 @@ java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.html generic-all java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java generic-all java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java generic-all -java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.html generic-all +java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.java generic-all java/awt/Mouse/MouseComboBoxTest/MouseComboBoxTest.java generic-all java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java generic-all java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java generic-all @@ -584,7 +577,7 @@ java/awt/TextArea/TextAreaCaretVisibilityTest/bug7129742.java java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java generic-all java/awt/TextArea/TextAreaEditing/TextAreaEditing.java generic-all java/awt/TextArea/TextAreaTwicePack/TextAreaTwicePack.java generic-all -java/awt/TextArea/UsingWithMouse/SelectionAutoscrollTest.html generic-all +java/awt/TextArea/UsingWithMouse/SelectionAutoscrollTest.java generic-all java/awt/TextField/DisposeTest/TestDispose.java generic-all java/awt/TextField/ScrollSelectionTest/ScrollSelectionTest.java generic-all java/awt/TextField/SelectionInvisibleTest/SelectionInvisibleTest.java generic-all @@ -674,6 +667,7 @@ java/awt/dnd/AcceptDropMultipleTimes/AcceptDropMultipleTimes.java java/awt/dnd/BadSerializaionTest/BadSerializationTest.java generic-all java/awt/dnd/BadSerializationTest/BadSerializationTest.java macosx-all java/awt/dnd/Button2DragTest/Button2DragTest.html generic-all +java/awt/dnd/Button2DragTest/Button2DragTest.java generic-all java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java generic-all java/awt/dnd/DnDFileGroupDescriptor/DnDFileGroupDescriptor.java generic-all java/awt/dnd/DnDFileGroupDescriptor/DnDTarget.java generic-all @@ -762,7 +756,7 @@ java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_4.java java/awt/event/MouseWheelEvent/WheelModifier/MouseWheelOnBackgroundComponent.java macosx-all java/awt/event/MouseWheelEvent/WheelModifier/WheelModifier.java generic-all java/awt/event/OtherEvents/UngrabID/UngrabID.java generic-all -java/awt/event/SequencedEvent/MultipleContextsFunctionalTest.java macosx-all +java/awt/event/SequencedEvent/MultipleContextsFunctionalTest.java linux-all,macosx-all java/awt/event/TextEvent/TextEventSequenceTest/TextEventSequenceTest.java generic-all java/awt/font/FontNames/LocaleFamilyNames.java generic-all java/awt/font/GlyphVector/VisualBounds.java generic-all @@ -861,6 +855,7 @@ java/awt/print/PrinterJob/Collate2DPrintingTest.java java/awt/print/PrinterJob/CustomPrintService/PrintDialog.java generic-all java/awt/print/PrinterJob/CustomPrintService/PrintServiceStub.java generic-all java/awt/print/PrinterJob/CustomPrintService/SetPrintServiceTest.java generic-all +java/awt/print/PrinterJob/ExceptionFromPrintableIsIgnoredTest.java generic-all java/awt/print/PrinterJob/ExceptionTest.java generic-all java/awt/print/PrinterJob/GetMediasTest.java generic-all java/awt/print/PrinterJob/ImagePrinting/ClippedImages.java generic-all @@ -1647,6 +1642,7 @@ java/util/Arrays/ParallelPrefix.java java/util/Arrays/SetAllTest.java generic-all java/util/Arrays/StreamAndSpliterator.java generic-all java/util/Arrays/TimSortStackSize.java generic-all +java/util/Arrays/TimSortStackSize2.java generic-all java/util/Base64/Base64GetEncoderTest.java generic-all java/util/Base64/TestBase64.java generic-all java/util/Base64/TestBase64Golden.java generic-all @@ -2433,6 +2429,7 @@ javax/swing/JFileChooser/8021253/bug8021253.java javax/swing/JFileChooser/8046391/bug8046391.java generic-all javax/swing/JFileChooser/8062561/bug8062561.java generic-all javax/swing/JFileChooser/8080628/bug8080628.java generic-all +javax/swing/JFileChooser/FileChooserListenerLeak.java generic-all javax/swing/JFileChooser/FileFilterDescription/FileFilterDescription.java generic-all javax/swing/JFormattedTextField/Test6462562.java generic-all javax/swing/JFrame/4962534/bug4962534.html generic-all @@ -2484,6 +2481,7 @@ javax/swing/JOptionPane/8024926/bug8024926.java javax/swing/JPopupMenu/4458079/bug4458079.java generic-all javax/swing/JPopupMenu/4966112/bug4966112.java generic-all javax/swing/JPopupMenu/6495920/bug6495920.java generic-all +javax/swing/JPopupMenu/6544309/bug6544309.java generic-all javax/swing/JPopupMenu/6675802/bug6675802.java generic-all javax/swing/JPopupMenu/6690791/bug6690791.java generic-all javax/swing/JPopupMenu/6691503/bug6691503.java generic-all @@ -2555,6 +2553,7 @@ javax/swing/JTable/6937798/bug6937798.java javax/swing/JTable/7027139/bug7027139.java generic-all javax/swing/JTable/7055065/bug7055065.java generic-all javax/swing/JTable/7068740/bug7068740.java generic-all +javax/swing/JTable/7124218/SelectEditTableCell.java generic-all javax/swing/JTable/7188612/JTableAccessibleGetLocationOnScreen.java generic-all javax/swing/JTable/8005019/bug8005019.java generic-all javax/swing/JTable/8031971/bug8031971.java generic-all @@ -2574,7 +2573,7 @@ javax/swing/JToolBar/4247996/bug4247996.java javax/swing/JToolTip/4846413/bug4846413.java generic-all javax/swing/JTree/4314199/bug4314199.java generic-all javax/swing/JTree/4330357/bug4330357.java generic-all -javax/swing/JTree/4633594/JTreeFocusTest.java linux-all,macosx-all +javax/swing/JTree/4633594/JTreeFocusTest.java generic-all javax/swing/JTree/4908142/bug4908142.java generic-all javax/swing/JTree/4927934/bug4927934.java generic-all javax/swing/JTree/6263446/bug6263446.java generic-all @@ -2644,10 +2643,12 @@ javax/swing/border/Test7034614.java javax/swing/border/Test7149090.java generic-all javax/swing/dnd/7171812/JListWithScroll.java generic-all javax/swing/dnd/7171812/bug7171812.java generic-all +javax/swing/event/RightAltKeyTest.java generic-all javax/swing/plaf/aqua/CustomComboBoxFocusTest.java generic-all javax/swing/plaf/basic/BasicComboBoxEditor/Test8015336.java generic-all javax/swing/plaf/basic/BasicComboPopup/8154069/Bug8154069.java generic-all javax/swing/plaf/basic/BasicHTML/4251579/bug4251579.java generic-all +javax/swing/plaf/basic/BasicHTML/4960629/bug4960629.java generic-all javax/swing/plaf/basic/BasicLabelUI/bug7172652.java generic-all javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java generic-all javax/swing/plaf/basic/BasicScrollPaneUI/Test6632810.java generic-all @@ -2731,6 +2732,7 @@ javax/xml/bind/marshal/8036981/Test.java javax/xml/crypto/dsig/GenerationTests.java generic-all javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java generic-all javax/xml/crypto/dsig/ValidationTests.java generic-all +javax/xml/jaxp/common/8035437/run.sh generic-all javax/xml/jaxp/Encodings/CheckEncodingPropertiesFile.java generic-all javax/xml/jaxp/XPath/8009579/XPathExceptionInitCause.java generic-all javax/xml/ws/8033113/WsImportTest.java generic-all @@ -2739,6 +2741,7 @@ javax/xml/ws/clientjar/TestWsImport.java javax/xml/ws/ebcdic/WsImportTest.java generic-all javax/xml/ws/xsanymixed/Test.java generic-all jdk/asm/AsmSanity.java generic-all +jdk/internal/platform/cgroup/TestCgroupMetrics.java generic-all jdk/lambda/ArrayCtorRefTest.java generic-all jdk/lambda/FDTest.java generic-all jdk/lambda/LambdaTranslationCompoundSamTest.java generic-all @@ -2913,6 +2916,7 @@ sun/net/www/http/HttpClient/ProxyTest.java sun/net/www/http/HttpClient/RetryPost.sh generic-all sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java generic-all sun/net/www/http/KeepAliveStream/InfiniteLoop.java generic-all +sun/net/www/http/RequestMethodCheck/RequestMethodEquality.java generic-all sun/net/www/protocol/file/DirPermissionDenied.sh generic-all sun/net/www/protocol/file/EncodedMultiByteChar.java generic-all sun/net/www/protocol/file/FileURLTest.java generic-all @@ -2947,6 +2951,7 @@ sun/rmi/runtime/Log/checkLogging/CheckLogStreams.java sun/rmi/runtime/Log/checkLogging/CheckLogging.java generic-all sun/rmi/server/MarshalOutputStream/marshalForeignStub/MarshalForeignStub.java generic-all sun/rmi/transport/tcp/DeadCachedConnection.java generic-all +sun/rmi/transport/tcp/DisableRMIOverHttp/DisableRMIOverHTTPTest.java generic-all sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java generic-all sun/security/ec/TestEC.java generic-all sun/security/jgss/DefaultGssConfig.java generic-all @@ -2996,6 +3001,7 @@ sun/security/krb5/auto/RRC.java sun/security/krb5/auto/ReplayCacheExpunge.java generic-all sun/security/krb5/auto/ReplayCacheTest.java generic-all sun/security/krb5/auto/ReplayCacheTestProc.java generic-all +sun/security/krb5/auto/rcache_usemd5.sh linux-all sun/security/krb5/auto/S4U2proxy.java generic-all sun/security/krb5/auto/S4U2proxyGSS.java generic-all sun/security/krb5/auto/S4U2self.java generic-all @@ -3063,57 +3069,8 @@ sun/security/ssl/EngineArgs/DebugReportsOneExtraByte.sh sun/security/ssl/SSLEngineImpl/SSLEngineDeadlock.java generic-all sun/security/ssl/SSLSocketImpl/NotifyHandshakeTest.sh generic-all sun/security/ssl/Stapling/StatusResponseManager.sh generic-all -sun/security/ssl/com/sun/net/ssl/SSLSecurity/ProviderTest.java generic-all -sun/security/ssl/com/sun/net/ssl/SSLSecurity/TruncateArray.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/DHKeyExchange/DHEKeySizing.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.sh generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/CustomizedDefaultProtocols.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/IllegalProtocolProperty.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/MD2InTrustAnchor.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/NoOldVersionContext.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/TrustTrustedCert.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseEngineException.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseInboundException.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/DelegatedTaskWrongException.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EmptyExtensionData.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/RehandshakeFinished.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/BasicConstraints.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SelfIssuedCert.java generic-all -sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyAuthTest.java generic-all sun/security/ssl/internal/TestRun.sh generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/AcceptLargeFragments.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ArgCheck.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/Arrays.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/CheckStatus.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ConnectionTest.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/ExtendedKeyEngine.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargeBufs.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/LargePacket.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/NoAuthClientAuth.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/SSLEngineResultArgs.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngineResult/Deserialize.java generic-all -sun/security/ssl/javax/net/ssl/NewAPIs/testEnabledProtocols.java generic-all -sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorer.java generic-all -sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java generic-all -sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerUnmatchedSNI.java generic-all -sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithCli.java generic-all -sun/security/ssl/javax/net/ssl/ServerName/SSLEngineExplorerWithSrv.java generic-all -sun/security/ssl/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java generic-all -sun/security/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java generic-all -sun/security/ssl/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java generic-all -sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java generic-all -sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java generic-all sun/security/ssl/sanity/pluggability/CheckSSLContextExport.java generic-all -sun/security/ssl/sun/net/www/http/ChunkedOutputStream/Test.java generic-all -sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/B6216082.java generic-all -sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/B6226610.java generic-all -sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/HttpsProxyStackOverflow.java generic-all -sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh generic-all -sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh generic-all sun/security/ssl/templates/SSLEngineTemplate.java generic-all sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java generic-all sun/security/tools/jarsigner/AlgOptions.sh generic-all @@ -3497,6 +3454,7 @@ java/net/MulticastSocket/B6427403.java java/net/MulticastSocket/JoinGroup.java macosx-all java/net/MulticastSocket/Leave.java macosx-all java/net/MulticastSocket/Promiscuous.java macosx-all +java/net/MulticastSocket/SetGetNetworkInterfaceTest.java generic-all java/net/MulticastSocket/SetOutgoingIf.java macosx-all java/net/PlainSocketImpl/SetBufferSize.java macosx-all java/net/Socket/LinkLocal.java macosx-all @@ -3563,7 +3521,7 @@ sun/tools/jcmd/TestJcmdDefaults.java sun/tools/jcmd/TestJcmdSanity.java generic-all # jconsole -sun/tools/jconsole/WorkerDeadlockTest.java generic-all +sun/tools/jconsole/WorkerDeadlockTest.sh generic-all # clhsdb sun/tools/clhsdb/Basic.sh generic-all @@ -3741,6 +3699,7 @@ jdk/jfr/api/recording/destination/TestDestToDiskFalse.java jdk/jfr/api/recording/destination/TestDestToDiskTrue.java generic-all jdk/jfr/api/recording/destination/TestDestWithDuration.java generic-all jdk/jfr/api/recording/dump/TestDump.java generic-all +jdk/jfr/api/recording/dump/TestDumpDevNull.java generic-all jdk/jfr/api/recording/dump/TestDumpInvalid.java generic-all jdk/jfr/api/recording/dump/TestDumpLongPath.java generic-all jdk/jfr/api/recording/dump/TestDumpMultiple.java generic-all @@ -3988,6 +3947,7 @@ jdk/jfr/event/runtime/TestVmFlagChangedEvent.java jdk/jfr/event/sampling/TestNative.java generic-all jdk/jfr/javaagent/EventEmitterAgent.java generic-all jdk/jfr/javaagent/JavaAgentBuilder.java generic-all +jdk/jfr/javaagent/Test8252904.java generic-all jdk/jfr/javaagent/TestLoadedAgent.java generic-all jdk/jfr/javaagent/TestPremainAgent.java generic-all jdk/jfr/jcmd/JcmdAsserts.java generic-all @@ -3997,6 +3957,7 @@ jdk/jfr/jcmd/TestJcmdDump.java jdk/jfr/jcmd/TestJcmdDumpGeneratedFilename.java generic-all jdk/jfr/jcmd/TestJcmdDumpLimited.java generic-all jdk/jfr/jcmd/TestJcmdDumpPathToGCRoots.java generic-all +jdk/jfr/jcmd/TestJcmdDumpWithFileName.java generic-all jdk/jfr/jcmd/TestJcmdLegacy.java generic-all jdk/jfr/jcmd/TestJcmdSaveToFile.java generic-all jdk/jfr/jcmd/TestJcmdStartDirNotExist.java generic-all @@ -4061,6 +4022,7 @@ jdk/jfr/jvm/TestLargeJavaEvent512k.java jdk/jfr/jvm/TestLargeJavaEvent64k.java generic-all jdk/jfr/jvm/TestLogImplementation.java generic-all jdk/jfr/jvm/TestPid.java generic-all +jdk/jfr/jvm/TestPrimitiveClasses.java generic-all jdk/jfr/jvm/TestUnloadEventClassCount.java generic-all jdk/jfr/jvm/TestUnsupportedVM.java generic-all jdk/jfr/security/JFRSecurityTestSuite.java generic-all @@ -4095,16 +4057,68 @@ jdk/jfr/tool/TestSummary.java # needs JRE subfolder security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/BuypassCA.java generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#actalisauthenticationrootca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#affirmtrustcommercialca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#affirmtrustnetworkingca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#affirmtrustpremiumca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#affirmtrustpremiumeccca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#amazonrootca1 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#amazonrootca2 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#amazonrootca3 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#amazonrootca4 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#buypassclass2ca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#buypassclass3ca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#certainlyroote1 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#certainlyrootr1 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#certignarootca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#comodoeccca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#comodorsaca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#digicerttlseccrootg5 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#digicerttlsrsarootg5 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#emsigneccrootcag3 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#emsignrootcag1 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#entrustrootcaec1 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#entrustrootcag4 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#globalsigne46 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#globalsigneccrootcar4 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#globalsignr46 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#globalsignrootcar6 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#godaddyrootg2ca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#gtsrootcar1 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#gtsrootcar2 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#gtsrootecccar3 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#gtsrootecccar4 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#letsencryptisrgx1 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#letsencryptisrgx2 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#microsoftecc2017 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#microsoftrsa2017 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#quovadisrootca1g3 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#quovadisrootca2g3 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#quovadisrootca3g3 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#sslrooteccca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#sslrootevrsaca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#sslrootrsaca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#starfieldrootg2ca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#teliarootcav2 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#teliasonerarootcav1 generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#twcaglobalrootca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#usertrusteccca generic-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#usertrustrsaca generic-all security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/DTrustCA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/EntrustCA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/GlobalSignR6CA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/GoDaddyCA.java generic-all +security/infra/java/security/cert/CertPathValidator/certification/HaricaCA.java generic-all +security/infra/java/security/cert/CertPathValidator/certification/HaricaCA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/LetsEncryptCA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/LuxTrustCA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/QuoVadisCA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/SSLCA.java generic-all security/infra/java/security/cert/CertPathValidator/certification/TeliaSoneraCA.java generic-all +security/infra/java/security/cert/CertPathValidator/certification/CertignaCA.java generic-all +security/infra/java/security/cert/CertPathValidator/certification/DigicertCSRootG5.java generic-all +security/infra/java/security/cert/CertPathValidator/certification/EmSignRootG2CA.java generic-all # Hotspot uses special detection to ensure native stack doesn't grow too far, which we can't do java/nio/channels/Selector/StackOverflowTest.java generic-all @@ -4135,7 +4149,687 @@ java/text/BreakIterator/BreakIteratorTest.java javax/xml/crypto/dsig/LineFeedOnlyTest.java generic-all # doesn't run on CI/CD, but probably could be made to -jdk/internal/platform/docker/TestDockerMemoryMetrics.java generic-all -jdk/internal/platform/docker/TestUseContainerSupport.java generic-all +jdk/internal/platform/docker/TestDockerBasic.java generic-all jdk/internal/platform/docker/TestDockerCpuMetrics.java generic-all +jdk/internal/platform/docker/TestDockerMemoryMetrics.java generic-all +jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java generic-all jdk/internal/platform/docker/TestSystemMetrics.java generic-all +jdk/internal/platform/docker/TestUseContainerSupport.java generic-all + +# Fixed in 8u372-b01 (JDK-8295982) +sun/security/tools/keytool/WeakAlg.java windows-all + +# Not working +com/sun/management/ThreadMXBean/MaxDepthForThreadInfoTest.java generic-all +demo/zipfs/ReleaseDeflater.java generic-all + +# OOM +java/awt/Frame/DisposeParentGC/DisposeParentGC.java generic-all +java/awt/Frame/FramesGC/FramesGC.java generic-all + +# Bad AWT +java/awt/AlphaComposite/HeadlessAlphaComposite.java macosx-all +java/awt/applet/Applet/HeadlessApplet.java macosx-all +java/awt/Choice/DragMouseOutAndRelease/DragMouseOutAndRelease.java macosx-all +java/awt/Choice/GetSizeTest/GetSizeTest.java macosx-all +java/awt/Choice/GrabLockTest/GrabLockTest.java macosx-all +java/awt/Choice/PopdownGeneratesMouseEvents/PopdownGeneratesMouseEvents.html macosx-all +java/awt/Choice/PopupPosTest/PopupPosTest.html macosx-all,windows-all +java/awt/Choice/ResizeAutoClosesChoice/ResizeAutoClosesChoice.java macosx-all +java/awt/Choice/SelectCurrentItemTest/SelectCurrentItemTest.html generic-all +java/awt/Choice/UnfocusableCB_ERR/UnfocusableCB_ERR.java macosx-all +java/awt/Color/HeadlessColor.java macosx-all +java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java macosx-all +java/awt/Component/Headless/HeadlessButton.java macosx-all +java/awt/Component/Headless/HeadlessCanvas.java macosx-all +java/awt/Component/Headless/HeadlessCheckbox.java macosx-all +java/awt/Component/Headless/HeadlessChoice.java macosx-all +java/awt/Component/Headless/HeadlessComponent.java macosx-all +java/awt/Component/Headless/HeadlessContainer.java macosx-all +java/awt/Component/Headless/HeadlessDialog.java macosx-all +java/awt/Component/Headless/HeadlessFileDialog.java macosx-all +java/awt/Component/Headless/HeadlessFrame.java macosx-all +java/awt/Component/Headless/HeadlessLabel.java macosx-all +java/awt/Component/Headless/HeadlessList.java macosx-all +java/awt/Component/Headless/HeadlessPanel.java macosx-all +java/awt/Component/Headless/HeadlessScrollbar.java macosx-all +java/awt/Component/Headless/HeadlessScrollPane.java macosx-all +java/awt/Component/Headless/HeadlessTextArea.java macosx-all +java/awt/Component/Headless/HeadlessTextField.java macosx-all +java/awt/Component/Headless/HeadlessWindow.java macosx-all +java/awt/Component/NativeInLightShow/NativeInLightShow.java linux-all,macosx-all +java/awt/Cursor/HeadlessCursor.java macosx-all +java/awt/datatransfer/Clipboard/BasicClipboardTest.java macosx-all +java/awt/datatransfer/Clipboard/GetContentsInterruptedTest.java macosx-all +java/awt/datatransfer/CustomClassLoaderTransferTest/CustomClassLoaderTransferTest.java macosx-all +java/awt/datatransfer/DataFlavor/DataFlavorCloneTest/DataFlavorCloneTest.java macosx-all +java/awt/datatransfer/DataFlavor/DataFlavorEqualsNullTest.java macosx-all +java/awt/datatransfer/DataFlavor/DataFlavorEqualsTest.java macosx-all +java/awt/datatransfer/DataFlavor/DataFlavorFileListTest.java macosx-all +java/awt/datatransfer/DataFlavor/DataFlavorSerializedTest.java macosx-all +java/awt/datatransfer/DataFlavor/DefaultMatchTest.java macosx-all +java/awt/datatransfer/DataFlavor/EqualHashCodeTest.java macosx-all +java/awt/datatransfer/DataFlavor/ExternalizeTest.java macosx-all +java/awt/datatransfer/DataFlavor/GetReaderForTextIAEForStringSelectionTest.java macosx-all +java/awt/datatransfer/DataFlavor/GetReaderForTextNPETest.java macosx-all +java/awt/datatransfer/DataFlavor/MimeTypeSerializationTest.java macosx-all +java/awt/datatransfer/DataFlavor/NoClassParameterTest.java macosx-all +java/awt/datatransfer/DataFlavor/NormalizeMimeTypeParameter.java macosx-all +java/awt/datatransfer/DataFlavor/NullDataFlavorTest.java macosx-all +java/awt/datatransfer/DataFlavor/ReaderForUnicodeText.java macosx-all +java/awt/datatransfer/DataFlavor/SelectBestFlavorNPETest.java macosx-all +java/awt/datatransfer/DataFlavor/SelectBestTextFlavorBadArrayTest.java macosx-all +java/awt/datatransfer/DataFlavor/ToStringNullPointerTest.java macosx-all +java/awt/datatransfer/Headless/HeadlessClipboard.java macosx-all +java/awt/datatransfer/Headless/HeadlessDataFlavor.java macosx-all +java/awt/datatransfer/Headless/HeadlessSystemFlavorMap.java macosx-all +java/awt/datatransfer/ImageTransfer/ImageTransferTest.java macosx-all +java/awt/datatransfer/Independence/IndependenceAWTTest.java macosx-all +java/awt/datatransfer/Independence/IndependenceSwingTest.java linux-all,macosx-all +java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.html macosx-all,windows-all +java/awt/datatransfer/SystemFlavorMap/AddFlavorForNativeTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/AddFlavorTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/AddNativeForFlavorTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/AddNativeTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/DuplicatedNativesTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/DuplicateMappingTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/GetFlavorsForNewNativeTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/GetNativesForFlavorTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/GetNativesForNewFlavorTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/InvalidMapArgumentsTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/ManyFlavorMapTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/MappingGenerationTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/SetDataFlavorsTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/SetFlavorsForNativeTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/SetNativesForFlavor.java macosx-all +java/awt/datatransfer/SystemFlavorMap/SetNativesForFlavorTest.java macosx-all +java/awt/datatransfer/SystemFlavorMap/SetNativesTest.java macosx-all +java/awt/datatransfer/SystemSelection/SystemSelectionAWTTest.java linux-all,macosx-all +java/awt/datatransfer/SystemSelection/SystemSelectionSwingTest.java linux-all,macosx-all +java/awt/EmbeddedFrame/GraphicsConfigTest/GraphicsConfigTest.java macosx-all +java/awt/event/ComponentEvent/MovedResizedTardyEventTest/MovedResizedTardyEventTest.html macosx-all +java/awt/event/ComponentEvent/MovedResizedTwiceTest/MovedResizedTwiceTest.java macosx-all +java/awt/event/KeyEvent/ExtendedModifiersTest/ExtendedModifiersTest.java generic-all +java/awt/event/KeyEvent/KeyMaskTest/KeyMaskTest.java generic-all +java/awt/event/MouseEvent/ClickDuringKeypress/ClickDuringKeypress.java generic-all +java/awt/event/MouseEvent/MouseButtonsAndKeyMasksTest/MouseButtonsAndKeyMasksTest.java generic-all +java/awt/event/MouseEvent/MouseButtonsTest/MouseButtonsTest.java generic-all +java/awt/event/MouseEvent/MultipleMouseButtonsTest/MultipleMouseButtonsTest.java generic-all +java/awt/EventQueue/HeadlessEventQueue.java macosx-all +java/awt/EventQueue/NonComponentSourcePost.java macosx-all +java/awt/FileDialog/ISCthrownByFileListTest/ISCthrownByFileListTest.java linux-all,macosx-all +java/awt/Focus/6378278/InputVerifierTest.java generic-all +java/awt/Focus/6382144/EndlessLoopTest.java macosx-all,windows-all +java/awt/Focus/6401036/InputVerifierTest2.java macosx-all +java/awt/Focus/ChildWindowFocusTest/ChildWindowFocusTest.html generic-all +java/awt/Focus/DisposedWindow/DisposeDialogNotActivateOwnerTest/DisposeDialogNotActivateOwnerTest.html linux-all,macosx-all +java/awt/Focus/FocusSubRequestTest/FocusSubRequestTest.html macosx-all +java/awt/Focus/Headless/HeadlessContainerOrderFocusTraversalPolicy.java macosx-all +java/awt/Focus/Headless/HeadlessDefaultFocusTraversalPolicy.java macosx-all +java/awt/Focus/Headless/HeadlessDefaultKeyboardFocusManager.java macosx-all +java/awt/Focus/ModalDialogInitialFocusTest/ModalDialogInitialFocusTest.html macosx-all +java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.html macosx-all +java/awt/Focus/MouseClickRequestFocusRaceTest/MouseClickRequestFocusRaceTest.html linux-all,macosx-all +java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.html macosx-all +java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.html macosx-all +java/awt/font/GlyphVector/TestLayoutFlags.java macosx-all +java/awt/font/Underline/UnderlineTest.java macosx-all +java/awt/FontClass/HeadlessFont.java macosx-all +java/awt/Frame/GetBoundsResizeTest/GetBoundsResizeTest.java macosx-all +java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java macosx-all,windows-all +java/awt/Frame/MiscUndecorated/ActiveAWTWindowTest.java linux-all,macosx-all +java/awt/Frame/MiscUndecorated/ActiveSwingWindowTest.java macosx-all +java/awt/Frame/MiscUndecorated/FrameCloseTest.java linux-all,macosx-all +java/awt/Frame/MiscUndecorated/RepaintTest.java generic-all +java/awt/Frame/MiscUndecorated/UndecoratedInitiallyIconified.java macosx-all +java/awt/Frame/NonEDT_GUI_DeadlockTest/NonEDT_GUI_Deadlock.html macosx-all +java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java macosx-all +java/awt/FullScreen/NonExistentDisplayModeTest/NonExistentDisplayModeTest.java macosx-all +java/awt/grab/MenuDragEvents/MenuDragEvents.html macosx-all,windows-all +java/awt/GradientPaint/HeadlessGradientPaint.java macosx-all +java/awt/Graphics2D/Headless/HeadlessPoint.java macosx-all +java/awt/Graphics2D/Headless/HeadlessPolygon.java macosx-all +java/awt/Graphics2D/Headless/HeadlessRectangle.java macosx-all +java/awt/GraphicsConfiguration/HeadlessGraphicsConfiguration.java macosx-all +java/awt/GraphicsDevice/HeadlessGraphicsDevice.java macosx-all +java/awt/GraphicsEnvironment/HeadlessGraphicsEnvironment.java macosx-all +java/awt/GridLayout/ChangeGridSize/ChangeGridSize.java generic-all +java/awt/GridLayout/ComponentPreferredSize/ComponentPreferredSize.java generic-all +java/awt/Headless/HeadlessAWTEventMulticaster.java macosx-all +java/awt/Headless/HeadlessAWTException.java macosx-all +java/awt/Headless/HeadlessBasicStroke.java macosx-all +java/awt/Headless/HeadlessBorderLayout.java macosx-all +java/awt/Headless/HeadlessCardLayout.java macosx-all +java/awt/Headless/HeadlessCheckboxGroup.java macosx-all +java/awt/Headless/HeadlessCheckboxMenuItem.java macosx-all +java/awt/Headless/HeadlessComponentOrientation.java macosx-all +java/awt/Headless/HeadlessDimension.java macosx-all +java/awt/Headless/HeadlessFlowLayout.java macosx-all +java/awt/Headless/HeadlessMediaTracker.java macosx-all +java/awt/Headless/HeadlessPopupMenu.java macosx-all +java/awt/im/Headless/HeadlessInputContext.java macosx-all +java/awt/im/Headless/HeadlessInputMethodHighlight.java macosx-all +java/awt/image/Headless/HeadlessAffineTransformOp.java macosx-all +java/awt/image/Headless/HeadlessAreaAveragingScaleFilter.java macosx-all +java/awt/image/Headless/HeadlessBufferedImage.java macosx-all +java/awt/image/Headless/HeadlessBufferedImageFilter.java macosx-all +java/awt/image/Headless/HeadlessColorModel.java macosx-all +java/awt/image/Headless/HeadlessCropImageFilter.java macosx-all +java/awt/image/Headless/HeadlessImageFilter.java macosx-all +java/awt/image/Headless/HeadlessIndexColorModel.java macosx-all +java/awt/image/Headless/HeadlessReplicateScaleFilter.java macosx-all +java/awt/image/Headless/HeadlessRGBImageFilter.java macosx-all +java/awt/image/VolatileImage/BitmaskVolatileImage.java linux-all,macosx-all +java/awt/Insets/HeadlessInsets.java macosx-all +java/awt/keyboard/AltPlusNumberKeyCombinationsTest/AltPlusNumberKeyCombinationsTest.java macosx-all,windows-all +java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeForModalDialogTest/ConsumeForModalDialogTest.html linux-all,macosx-all +java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.html macosx-all +java/awt/KeyboardFocusmanager/TypeAhead/EnqueueWithDialogButtonTest/EnqueueWithDialogButtonTest.java macosx-all +java/awt/KeyboardFocusmanager/TypeAhead/EnqueueWithDialogTest/EnqueueWithDialogTest.java generic-all +java/awt/KeyboardFocusmanager/TypeAhead/FreezeTest/FreezeTest.java macosx-all,windows-all +java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html macosx-all +java/awt/List/KeyEventsTest/KeyEventsTest.html linux-all,macosx-all +java/awt/Menu/Headless/HeadlessMenu.java macosx-all +java/awt/Menu/Headless/HeadlessMenuItem.java macosx-all +java/awt/Menu/Headless/HeadlessMenuShortcut.java macosx-all +java/awt/MenuBar/HeadlessMenuBar.java macosx-all +java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java generic-all +java/awt/Mixing/AWT_Mixing/JButtonInGlassPaneOverlapping.java macosx-all,windows-all +java/awt/Mixing/AWT_Mixing/JButtonOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JColorChooserOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JEditorPaneInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JEditorPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JGlassPaneInternalFrameOverlapping.java linux-all,macosx-all +java/awt/Mixing/AWT_Mixing/JGlassPaneMoveOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JInternalFrameMoveOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JInternalFrameOverlapping.java macosx-all,windows-all +java/awt/Mixing/AWT_Mixing/JLabelInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JLabelOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JListInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JListOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JPanelInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JPanelOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JProgressBarInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JProgressBarOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JScrollBarInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JScrollBarOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JScrollPaneOverlapping.java macosx-all,windows-all +java/awt/Mixing/AWT_Mixing/JSliderInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JSliderOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JSpinnerInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JSpinnerOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JSplitPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JTableInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JTableOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JTextAreaInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JTextAreaOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JTextFieldInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JTextFieldOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JToggleButtonInGlassPaneOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/JToggleButtonOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java generic-all +java/awt/Mixing/AWT_Mixing/MixingPanelsResizing.java macosx-all +java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java generic-all +java/awt/Mixing/AWT_Mixing/OpaqueOverlappingChoice.java generic-all +java/awt/Mixing/AWT_Mixing/ViewportOverlapping.java generic-all +java/awt/Modal/FileDialog/FileDialogAppModal1Test.java generic-all +java/awt/Modal/FileDialog/FileDialogAppModal2Test.java generic-all +java/awt/Modal/FileDialog/FileDialogAppModal3Test.java generic-all +java/awt/Modal/FileDialog/FileDialogAppModal4Test.java generic-all +java/awt/Modal/FileDialog/FileDialogAppModal5Test.java generic-all +java/awt/Modal/FileDialog/FileDialogAppModal6Test.java generic-all +java/awt/Modal/FileDialog/FileDialogDocModal1Test.java generic-all +java/awt/Modal/FileDialog/FileDialogDocModal2Test.java generic-all +java/awt/Modal/FileDialog/FileDialogDocModal3Test.java generic-all +java/awt/Modal/FileDialog/FileDialogDocModal4Test.java generic-all +java/awt/Modal/FileDialog/FileDialogDocModal5Test.java generic-all +java/awt/Modal/FileDialog/FileDialogDocModal6Test.java generic-all +java/awt/Modal/FileDialog/FileDialogDocModal7Test.java generic-all +java/awt/Modal/FileDialog/FileDialogModal1Test.java generic-all +java/awt/Modal/FileDialog/FileDialogModal2Test.java generic-all +java/awt/Modal/FileDialog/FileDialogModal3Test.java generic-all +java/awt/Modal/FileDialog/FileDialogModal4Test.java generic-all +java/awt/Modal/FileDialog/FileDialogModal5Test.java generic-all +java/awt/Modal/FileDialog/FileDialogModal6Test.java generic-all +java/awt/Modal/FileDialog/FileDialogNonModal1Test.java generic-all +java/awt/Modal/FileDialog/FileDialogNonModal2Test.java generic-all +java/awt/Modal/FileDialog/FileDialogNonModal3Test.java generic-all +java/awt/Modal/FileDialog/FileDialogNonModal4Test.java generic-all +java/awt/Modal/FileDialog/FileDialogNonModal5Test.java generic-all +java/awt/Modal/FileDialog/FileDialogNonModal6Test.java generic-all +java/awt/Modal/FileDialog/FileDialogNonModal7Test.java generic-all +java/awt/Modal/FileDialog/FileDialogTKModal1Test.java generic-all +java/awt/Modal/FileDialog/FileDialogTKModal2Test.java generic-all +java/awt/Modal/FileDialog/FileDialogTKModal3Test.java generic-all +java/awt/Modal/FileDialog/FileDialogTKModal4Test.java generic-all +java/awt/Modal/FileDialog/FileDialogTKModal5Test.java generic-all +java/awt/Modal/FileDialog/FileDialogTKModal6Test.java generic-all +java/awt/Modal/FileDialog/FileDialogTKModal7Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDDAppModalTest.java linux-all,macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDDDocModalTest.java linux-all,macosx-all +java/awt/Modal/ModalBlockingTests/BlockingDDModelessTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDDNonModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDDSetModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDDToolkitModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDFAppModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDFSetModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDFToolkitModalTest.java macosx-all,windows-all +java/awt/Modal/ModalBlockingTests/BlockingDFWModeless1Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDFWModeless2Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDFWNonModal1Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDFWNonModal2Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingDocModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDAppModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDDocModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDModelessTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDNonModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDSetModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDToolkitModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal1Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal2Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal3Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal4Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWModeless1Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWModeless2Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWModeless3Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWModeless4Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal1Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal2Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal3Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal4Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal1Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal2Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal3Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal4Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal5Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal6Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsDocModal1Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsDocModal2Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal1Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal2Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal3Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal4Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal5Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal6Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal1Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal2Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal3Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal4Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal5Test.java generic-all +java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal6Test.java generic-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogAppModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogDocModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogModelessTest.java generic-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogNonModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogSetModalTest.java generic-all +java/awt/Modal/ModalBlockingTests/UnblockedDialogToolkitModalTest.java generic-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeDialogFileTest.java generic-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeDialogPageSetupTest.java generic-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeDialogPrintSetupTest.java generic-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeFrameFileTest.java generic-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeFramePageSetupTest.java generic-all +java/awt/Modal/ModalExclusionTests/ApplicationExcludeFramePrintSetupTest.java generic-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeDialogFileTest.java generic-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeDialogPageSetupTest.java generic-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeDialogPrintSetupTest.java generic-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeFrameFileTest.java generic-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeFramePageSetupTest.java generic-all +java/awt/Modal/ModalExclusionTests/ToolkitExcludeFramePrintSetupTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsAppModalTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsDocModalTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsModelessTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsNonModalTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFAppModalTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFDocModalTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFModelessTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFNonModalTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWAppModalTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWDocModalTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWModelessTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWNonModalTest.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal1Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal2Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal3Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal4Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal1Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal2Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal3Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal4Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless1Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless2Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless3Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless4Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal1Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal2Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal3Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal4Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFAppModal1Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFAppModal2Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFAppModal3Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFDocModal1Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFDocModal2Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFDocModal3Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFModeless1Test.java macosx-all,windows-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFModeless2Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFModeless3Test.java macosx-all,windows-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal1Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal2Test.java generic-all +java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal3Test.java generic-all +java/awt/Modal/ModalitySettingsTest/ModalitySettingsTest.java macosx-all +java/awt/Modal/MultipleDialogs/MultipleDialogs1Test.java generic-all +java/awt/Modal/MultipleDialogs/MultipleDialogs2Test.java generic-all +java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java generic-all +java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java generic-all +java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java generic-all +java/awt/Modal/NullModalityDialogTest/NullModalityDialogTest.java generic-all +java/awt/Modal/OnTop/OnTopAppModal1Test.java generic-all +java/awt/Modal/OnTop/OnTopAppModal2Test.java generic-all +java/awt/Modal/OnTop/OnTopAppModal3Test.java generic-all +java/awt/Modal/OnTop/OnTopAppModal4Test.java generic-all +java/awt/Modal/OnTop/OnTopAppModal5Test.java generic-all +java/awt/Modal/OnTop/OnTopAppModal6Test.java generic-all +java/awt/Modal/OnTop/OnTopDocModal1Test.java generic-all +java/awt/Modal/OnTop/OnTopDocModal2Test.java generic-all +java/awt/Modal/OnTop/OnTopDocModal3Test.java generic-all +java/awt/Modal/OnTop/OnTopDocModal4Test.java generic-all +java/awt/Modal/OnTop/OnTopDocModal5Test.java generic-all +java/awt/Modal/OnTop/OnTopDocModal6Test.java generic-all +java/awt/Modal/OnTop/OnTopModal1Test.java generic-all +java/awt/Modal/OnTop/OnTopModal2Test.java generic-all +java/awt/Modal/OnTop/OnTopModal3Test.java generic-all +java/awt/Modal/OnTop/OnTopModal4Test.java generic-all +java/awt/Modal/OnTop/OnTopModal5Test.java generic-all +java/awt/Modal/OnTop/OnTopModal6Test.java generic-all +java/awt/Modal/OnTop/OnTopModeless1Test.java generic-all +java/awt/Modal/OnTop/OnTopModeless2Test.java generic-all +java/awt/Modal/OnTop/OnTopModeless3Test.java generic-all +java/awt/Modal/OnTop/OnTopModeless4Test.java generic-all +java/awt/Modal/OnTop/OnTopModeless5Test.java generic-all +java/awt/Modal/OnTop/OnTopModeless6Test.java generic-all +java/awt/Modal/OnTop/OnTopTKModal1Test.java generic-all +java/awt/Modal/OnTop/OnTopTKModal2Test.java generic-all +java/awt/Modal/OnTop/OnTopTKModal3Test.java generic-all +java/awt/Modal/OnTop/OnTopTKModal4Test.java generic-all +java/awt/Modal/OnTop/OnTopTKModal5Test.java generic-all +java/awt/Modal/OnTop/OnTopTKModal6Test.java generic-all +java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java macosx-all +java/awt/Modal/ToBack/ToBackAppModal1Test.java generic-all +java/awt/Modal/ToBack/ToBackAppModal2Test.java macosx-all,windows-all +java/awt/Modal/ToBack/ToBackAppModal3Test.java generic-all +java/awt/Modal/ToBack/ToBackAppModal4Test.java generic-all +java/awt/Modal/ToBack/ToBackAppModal5Test.java generic-all +java/awt/Modal/ToBack/ToBackAppModal6Test.java generic-all +java/awt/Modal/ToBack/ToBackDocModal1Test.java generic-all +java/awt/Modal/ToBack/ToBackDocModal2Test.java generic-all +java/awt/Modal/ToBack/ToBackDocModal3Test.java generic-all +java/awt/Modal/ToBack/ToBackDocModal4Test.java generic-all +java/awt/Modal/ToBack/ToBackDocModal5Test.java macosx-all,windows-all +java/awt/Modal/ToBack/ToBackDocModal6Test.java generic-all +java/awt/Modal/ToBack/ToBackModal1Test.java macosx-all,windows-all +java/awt/Modal/ToBack/ToBackModal2Test.java macosx-all,windows-all +java/awt/Modal/ToBack/ToBackModal3Test.java generic-all +java/awt/Modal/ToBack/ToBackModal4Test.java generic-all +java/awt/Modal/ToBack/ToBackModal5Test.java generic-all +java/awt/Modal/ToBack/ToBackModal6Test.java generic-all +java/awt/Modal/ToBack/ToBackModeless1Test.java generic-all +java/awt/Modal/ToBack/ToBackModeless2Test.java generic-all +java/awt/Modal/ToBack/ToBackModeless3Test.java generic-all +java/awt/Modal/ToBack/ToBackModeless4Test.java generic-all +java/awt/Modal/ToBack/ToBackModeless5Test.java generic-all +java/awt/Modal/ToBack/ToBackModeless6Test.java generic-all +java/awt/Modal/ToBack/ToBackNonModal1Test.java generic-all +java/awt/Modal/ToBack/ToBackNonModal2Test.java macosx-all,windows-all +java/awt/Modal/ToBack/ToBackNonModal3Test.java generic-all +java/awt/Modal/ToBack/ToBackNonModal4Test.java macosx-all,windows-all +java/awt/Modal/ToBack/ToBackNonModal5Test.java generic-all +java/awt/Modal/ToBack/ToBackNonModal6Test.java generic-all +java/awt/Modal/ToBack/ToBackTKModal1Test.java generic-all +java/awt/Modal/ToBack/ToBackTKModal2Test.java generic-all +java/awt/Modal/ToBack/ToBackTKModal3Test.java macosx-all,windows-all +java/awt/Modal/ToBack/ToBackTKModal4Test.java generic-all +java/awt/Modal/ToBack/ToBackTKModal5Test.java generic-all +java/awt/Modal/ToBack/ToBackTKModal6Test.java generic-all +java/awt/Modal/ToFront/DialogToFrontAppModalTest.java generic-all +java/awt/Modal/ToFront/DialogToFrontDocModalTest.java generic-all +java/awt/Modal/ToFront/DialogToFrontModalTest.java generic-all +java/awt/Modal/ToFront/DialogToFrontModeless1Test.java generic-all +java/awt/Modal/ToFront/DialogToFrontNonModalTest.java linux-all,macosx-all +java/awt/Modal/ToFront/DialogToFrontTKModalTest.java generic-all +java/awt/Modal/ToFront/FrameToFrontAppModal1Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontAppModal2Test.java macosx-all,windows-all +java/awt/Modal/ToFront/FrameToFrontAppModal3Test.java macosx-all,windows-all +java/awt/Modal/ToFront/FrameToFrontAppModal4Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontAppModal5Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontDocModal1Test.java linux-all,macosx-all +java/awt/Modal/ToFront/FrameToFrontDocModal2Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontModal1Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontModal2Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontModal3Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontModal4Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontModal5Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontModeless1Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontNonModalTest.java generic-all +java/awt/Modal/ToFront/FrameToFrontTKModal1Test.java macosx-all,windows-all +java/awt/Modal/ToFront/FrameToFrontTKModal2Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontTKModal3Test.java generic-all +java/awt/Modal/ToFront/FrameToFrontTKModal4Test.java macosx-all,windows-all +java/awt/Modal/ToFront/FrameToFrontTKModal5Test.java generic-all +java/awt/Paint/RepaintOnAWTShutdown.java macosx-all +java/awt/print/Dialog/DestinationTest.java macosx-all +java/awt/print/Dialog/MediaInPrintable.java macosx-all +java/awt/print/Dialog/PrintApplet.java macosx-all +java/awt/print/Dialog/PrintDialog.java macosx-all +java/awt/print/Dialog/PrintDlgApp.java macosx-all +java/awt/print/Dialog/PrintDlgPageable.java macosx-all +java/awt/print/Dialog/RestoreActiveWindowTest/RestoreActiveWindowTest.html macosx-all +java/awt/print/Headless/HeadlessBook.java macosx-all +java/awt/print/Headless/HeadlessPageFormat.java macosx-all +java/awt/print/Headless/HeadlessPaper.java macosx-all +java/awt/print/Headless/HeadlessPrinterJob.java macosx-all +java/awt/print/PageFormat/CustomPaper.java macosx-all +java/awt/print/PageFormat/NullPaper.java macosx-all +java/awt/print/PageFormat/Orient.java macosx-all +java/awt/print/PageFormat/PageSetupDialog.java macosx-all +java/awt/print/PageFormat/ReverseLandscapeTest.java macosx-all +java/awt/print/PageFormat/SetOrient.html macosx-all +java/awt/print/PageFormat/ValidateCustom.java macosx-all +java/awt/print/PrinterJob/Cancel/PrinterJobCancel.java macosx-all +java/awt/print/PrinterJob/CheckAccess.java macosx-all +java/awt/print/PrinterJob/CheckPrivilege.java macosx-all +java/awt/print/PrinterJob/CompareImageable.java macosx-all +java/awt/print/PrinterJob/CustomFont/CustomFont.java macosx-all +java/awt/print/PrinterJob/DeviceScale.java macosx-all +java/awt/print/PrinterJob/DrawImage.java macosx-all +java/awt/print/PrinterJob/DrawStringMethods.java macosx-all +java/awt/print/PrinterJob/EmptyFill.java macosx-all +java/awt/print/PrinterJob/GlyphPositions.java macosx-all +java/awt/print/PrinterJob/HeadlessPrintingTest.java macosx-all +java/awt/print/PrinterJob/InvalidPage.java macosx-all +java/awt/print/PrinterJob/JobName/PrinterJobName.java macosx-all +java/awt/print/PrinterJob/Legal/PrintTest.java macosx-all +java/awt/print/PrinterJob/MultiThread/MultiThreadTest.java macosx-all +java/awt/print/PrinterJob/NullGetName.java macosx-all +java/awt/print/PrinterJob/NumCopies.java macosx-all +java/awt/print/PrinterJob/PageDialogTest.java macosx-all +java/awt/print/PrinterJob/PageDlgPrnButton.java macosx-all +java/awt/print/PrinterJob/PaintText.java macosx-all +java/awt/print/PrinterJob/PrintBadImage.java macosx-all +java/awt/print/PrinterJob/PrintCompoundString.java macosx-all +java/awt/print/PrinterJob/PrintDialog.java macosx-all +java/awt/print/PrinterJob/PrintDialogCancel.java macosx-all +java/awt/print/PrinterJob/PrinterDialogsModalityTest/PrinterDialogsModalityTest.html macosx-all,windows-all +java/awt/print/PrinterJob/PrinterJobDialogBugDemo.java macosx-all +java/awt/print/PrinterJob/PrintImage.java macosx-all +java/awt/print/PrinterJob/PrintNullString.java macosx-all +java/awt/print/PrinterJob/PrintParenString.java macosx-all +java/awt/print/PrinterJob/PrintRotatedText.java macosx-all +java/awt/print/PrinterJob/PrintTextLayout.java macosx-all +java/awt/print/PrinterJob/PrintTextPane.java macosx-all +java/awt/print/PrinterJob/PrintTranslatedFont.java macosx-all +java/awt/print/PrinterJob/PrintVolatileImage.java macosx-all +java/awt/print/PrinterJob/PSQuestionMark.java macosx-all +java/awt/print/PrinterJob/PSWindingRule.java macosx-all +java/awt/print/PrinterJob/raster/RasterTest.java macosx-all +java/awt/print/PrinterJob/RemoveListener.java macosx-all +java/awt/print/PrinterJob/ScaledText/ScaledText.java macosx-all +java/awt/print/PrinterJob/SecurityDialogTest.java macosx-all +java/awt/print/PrinterJob/SetCopies/Test.java macosx-all +java/awt/print/PrinterJob/SwingUIText.java macosx-all +java/awt/print/PrinterJob/ThinLines.java macosx-all +java/awt/print/PrintServicesSecurityManager.java macosx-all +java/awt/Robot/CheckCommonColors/CheckCommonColors.java generic-all +java/awt/Robot/ModifierRobotKey/ModifierRobotKeyTest.java generic-all +java/awt/Robot/WaitForIdleSyncroizedOnString/WaitForIdleSyncroizedOnString.java macosx-all +java/awt/TextArea/ScrollbarIntersectionTest/ScrollbarIntersectionTest.java generic-all +java/awt/Toolkit/DesktopProperties/rfe4758438.java macosx-all +java/awt/Toolkit/Headless/HeadlessToolkit.java macosx-all +java/awt/Toolkit/LockingKeyStateTest/LockingKeyStateTest.java macosx-all,windows-all +java/awt/Toolkit/RealSync/Test.java generic-all +java/awt/TrayIcon/ActionCommand/ActionCommand.java macosx-all,windows-all +java/awt/TrayIcon/ActionEventMask/ActionEventMask.java macosx-all,windows-all +java/awt/TrayIcon/GetTrayIconsTest/GetTrayIcons.java macosx-all +java/awt/TrayIcon/InterJVMTest/InterJVM.java macosx-all +java/awt/TrayIcon/ModalityTest/ModalityTest.java macosx-all,windows-all +java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java macosx-all,windows-all +java/awt/TrayIcon/MouseMovedTest/MouseMovedTest.java generic-all +java/awt/TrayIcon/PropertyChangeListenerTest.java macosx-all +java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java macosx-all,windows-all +java/awt/TrayIcon/SecurityCheck/NoPermissionTest/NoPermissionTest.java macosx-all +java/awt/TrayIcon/SecurityCheck/PermissionTest/PermissionTest.java macosx-all +java/awt/TrayIcon/SystemTrayInstance/SystemTrayInstanceTest.java linux-all,macosx-all +java/awt/TrayIcon/TrayIconAddTest/TrayIconAddTest.java macosx-all +java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java macosx-all,windows-all +java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java macosx-all,windows-all +java/awt/TrayIcon/TrayIconMethodsTest/TrayIconMethodsTest.java macosx-all +java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java macosx-all,windows-all +java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java macosx-all,windows-all +java/awt/TrayIcon/TrayIconRemoveTest/TrayIconRemoveTest.java macosx-all +java/awt/TrayIcon/TrayIconSizeTest/TrayIconSizeTest.java macosx-all +java/awt/Window/AlwaysOnTop/AutoTestOnTop.java macosx-all,windows-all +java/awt/Window/FullWindowContentTest/FullWindowContentTest.java macosx-all +java/awt/Window/GetWindowsTest/GetWindowsTest.java macosx-all +java/awt/Window/HandleWindowDestroyTest/HandleWindowDestroyTest.html macosx-all +java/awt/Window/setLocRelativeTo/SetLocationRelativeToTest.java macosx-all +java/awt/Window/ShapedAndTranslucentWindows/SetShape.java linux-all,macosx-all +java/awt/Window/ShapedAndTranslucentWindows/SetShapeAndClick.java linux-all,macosx-all +java/awt/Window/ShapedAndTranslucentWindows/SetShapeDynamicallyAndClick.java macosx-all,windows-all +java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucentWindowClick.java macosx-all,windows-all +java/awt/Window/ShapedAndTranslucentWindows/TranslucentChoice.java macosx-all,windows-all +java/awt/Window/ShapedAndTranslucentWindows/TranslucentWindowClick.java macosx-all,windows-all +javax/accessibility/6192422/bug6192422.java macosx-all +javax/swing/Headless/HeadlessAbstractSpinnerModel.java macosx-all +javax/swing/Headless/HeadlessBox_Filler.java macosx-all +javax/swing/Headless/HeadlessBox.java macosx-all +javax/swing/Headless/HeadlessCellRendererPane.java macosx-all +javax/swing/Headless/HeadlessDefaultListCellRenderer_UIResource.java macosx-all +javax/swing/Headless/HeadlessDefaultListCellRenderer.java macosx-all +javax/swing/Headless/HeadlessGrayFilter.java macosx-all +javax/swing/Headless/HeadlessJApplet.java macosx-all +javax/swing/Headless/HeadlessJButton.java macosx-all +javax/swing/Headless/HeadlessJCheckBox.java macosx-all +javax/swing/Headless/HeadlessJCheckBoxMenuItem.java macosx-all +javax/swing/Headless/HeadlessJColorChooser.java macosx-all +javax/swing/Headless/HeadlessJComboBox.java macosx-all +javax/swing/Headless/HeadlessJComponent.java macosx-all +javax/swing/Headless/HeadlessJDesktopPane.java macosx-all +javax/swing/Headless/HeadlessJDialog.java macosx-all +javax/swing/Headless/HeadlessJEditorPane.java macosx-all +javax/swing/Headless/HeadlessJFileChooser.java macosx-all,windows-all +javax/swing/Headless/HeadlessJFormattedTextField.java macosx-all +javax/swing/Headless/HeadlessJFrame.java macosx-all +javax/swing/Headless/HeadlessJInternalFrame_JDesktopIcon.java macosx-all +javax/swing/Headless/HeadlessJInternalFrame.java macosx-all +javax/swing/Headless/HeadlessJLabel.java macosx-all +javax/swing/Headless/HeadlessJLayeredPane.java macosx-all +javax/swing/Headless/HeadlessJList.java macosx-all +javax/swing/Headless/HeadlessJMenu.java macosx-all +javax/swing/Headless/HeadlessJMenuBar.java macosx-all +javax/swing/Headless/HeadlessJMenuItem.java macosx-all +javax/swing/Headless/HeadlessJOptionPane.java macosx-all +javax/swing/Headless/HeadlessJPanel.java macosx-all +javax/swing/Headless/HeadlessJPasswordField.java macosx-all +javax/swing/Headless/HeadlessJPopupMenu_Separator.java macosx-all +javax/swing/Headless/HeadlessJPopupMenu.java macosx-all +javax/swing/Headless/HeadlessJProgressBar.java macosx-all +javax/swing/Headless/HeadlessJRadioButton.java macosx-all +javax/swing/Headless/HeadlessJRadioButtonMenuItem.java macosx-all +javax/swing/Headless/HeadlessJRootPane.java macosx-all +javax/swing/Headless/HeadlessJScrollBar.java macosx-all +javax/swing/Headless/HeadlessJScrollPane.java macosx-all +javax/swing/Headless/HeadlessJSeparator.java macosx-all +javax/swing/Headless/HeadlessJSlider.java macosx-all +javax/swing/Headless/HeadlessJSpinner.java macosx-all +javax/swing/Headless/HeadlessJSplitPane.java macosx-all +javax/swing/Headless/HeadlessJTabbedPane.java macosx-all +javax/swing/Headless/HeadlessJTable.java macosx-all +javax/swing/Headless/HeadlessJTextArea.java macosx-all +javax/swing/Headless/HeadlessJTextField.java macosx-all +javax/swing/Headless/HeadlessJTextPane.java macosx-all +javax/swing/Headless/HeadlessJToggleButton.java macosx-all +javax/swing/Headless/HeadlessJToolBar_Separator.java macosx-all +javax/swing/Headless/HeadlessJToolBar.java macosx-all +javax/swing/Headless/HeadlessJToolTip.java macosx-all +javax/swing/Headless/HeadlessJTree.java macosx-all +javax/swing/Headless/HeadlessJViewport.java macosx-all +javax/swing/Headless/HeadlessJWindow.java macosx-all +javax/swing/Headless/HeadlessLookAndFeel.java macosx-all +javax/swing/Headless/HeadlessMenuSelectionManager.java macosx-all +javax/swing/Headless/HeadlessOverlayLayout.java macosx-all +javax/swing/Headless/HeadlessPopupFactory.java macosx-all +javax/swing/Headless/HeadlessScrollPaneLayout.java macosx-all +javax/swing/Headless/HeadlessSizeRequirements.java macosx-all +javax/swing/Headless/HeadlessSizeSequence.java macosx-all +javax/swing/Headless/HeadlessSpinnerListModel.java macosx-all +javax/swing/Headless/HeadlessSpinnerNumberModel.java macosx-all +javax/swing/Headless/HeadlessTimer.java macosx-all +javax/swing/JButton/4368790/bug4368790.java generic-all +javax/swing/JColorChooser/Test4319113.java macosx-all +javax/swing/JComboBox/4515752/DefaultButtonTest.java macosx-all +javax/swing/JComboBox/4523758/bug4523758.java linux-all,macosx-all +javax/swing/JComboBox/6406264/bug6406264.java generic-all +javax/swing/JComboBox/6559152/bug6559152.java generic-all +javax/swing/JComboBox/8072767/bug8072767.java generic-all +javax/swing/JFrame/8255880/RepaintOnFrameIconifiedStateChangeTest.java generic-all +javax/swing/JList/6510999/bug6510999.java generic-all +javax/swing/JMenu/4417601/bug4417601.java generic-all +javax/swing/JMenu/6359669/bug6359669.java generic-all +javax/swing/JMenu/6470128/bug6470128.java generic-all +javax/swing/JMenu/6538132/bug6538132.java macosx-all,windows-all +javax/swing/JMenu/JMenuSelectedColorTest.java linux-all,macosx-all +javax/swing/JMenuItem/6249972/bug6249972.java generic-all +javax/swing/JOptionPane/4174551/bug4174551.java macosx-all +javax/swing/JOptionPane/6428694/bug6428694.java generic-all +javax/swing/JPopupMenu/4634626/bug4634626.java generic-all +javax/swing/JPopupMenu/6217905/bug6217905.java macosx-all,windows-all +javax/swing/JPopupMenu/6415145/bug6415145.java generic-all +javax/swing/JPopupMenu/6515446/bug6515446.java generic-all +javax/swing/JPopupMenu/6544309/bug6544309.java linux-all,macosx-all +javax/swing/JPopupMenu/6580930/bug6580930.java generic-all +javax/swing/JPopupMenu/6583251/bug6583251.java generic-all +javax/swing/JRadioButton/8041561/bug8041561.java generic-all +javax/swing/JScrollPane/6274267/bug6274267.java generic-all +javax/swing/JSlider/6401380/bug6401380.java generic-all +javax/swing/JSpinner/8008657/bug8008657.java generic-all +javax/swing/JTabbedPane/4666224/bug4666224.html macosx-all +javax/swing/JToolBar/4529206/bug4529206.java generic-all +javax/swing/JToolTip/4644444/bug4644444.html macosx-all +javax/swing/JTree/6578666/bug6578666.java generic-all +javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucent.java macosx-all,windows-all +javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java macosx-all,windows-all +javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentGradient.java macosx-all,windows-all +javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java macosx-all,windows-all +javax/swing/JWindow/ShapedAndTranslucentWindows/SetShapeAndClickSwing.java macosx-all,windows-all +javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java macosx-all,windows-all +javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java macosx-all,windows-all +javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentJComboBox.java macosx-all,windows-all +javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java macosx-all,windows-all +javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentWindowClickSwing.java macosx-all,windows-all +javax/swing/Popup/6514582/bug6514582.java macosx-all +javax/swing/reliability/TaskUndJFrameProperties.java macosx-all,windows-all +javax/swing/reliability/TaskZoomJFrameChangeState.java linux-all,macosx-all +javax/swing/reliability/TaskZoomJFrameRepaint.java linux-all,macosx-all +sun/java2d/OpenGL/CopyAreaOOB.java macosx-all,windows-all +sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java generic-all diff --git a/src/IKVM.OpenJDK.Tests/langtools/ExcludeList.txt b/src/IKVM.OpenJDK.Tests/langtools/test/ExcludeList.txt similarity index 72% rename from src/IKVM.OpenJDK.Tests/langtools/ExcludeList.txt rename to src/IKVM.OpenJDK.Tests/langtools/test/ExcludeList.txt index d24d7b3afe..c9874486a5 100644 --- a/src/IKVM.OpenJDK.Tests/langtools/ExcludeList.txt +++ b/src/IKVM.OpenJDK.Tests/langtools/test/ExcludeList.txt @@ -1,11 +1,9 @@ -# unknown errors (FIXME) com/sun/javadoc/testGeneratedBy/TestGeneratedBy.java generic-all -tools/javac/4846262/CheckEBCDICLocaleTest.java generic-all tools/javac/4917091/Test255.java generic-all tools/javac/6508981/TestInferBinaryName.java generic-all tools/javac/6589361/T6589361.java generic-all tools/javac/ArrayCloneCodeGen.java generic-all -tools/javac/ClassPathTest/ClassPathTest.java generic-all +tools/javac/Diagnostics/6769027/T6769027.java generic-all tools/javac/EarlyAssert.java generic-all tools/javac/Paths/Class-Path.sh generic-all tools/javac/Paths/Class-Path2.sh generic-all @@ -13,64 +11,43 @@ tools/javac/Paths/Diagnostics.sh tools/javac/Paths/Help.sh generic-all tools/javac/Paths/MineField.sh generic-all tools/javac/Paths/wcMineField.sh generic-all +tools/javac/StringsInSwitch/OneCaseSwitches.java macosx-all tools/javac/T6558476.java generic-all tools/javac/T6873845.java generic-all tools/javac/T7093325.java generic-all -tools/javac/T8003967/DetectMutableStaticFields.java generic-all tools/javac/T8024207/FlowCrashTest.java generic-all -tools/javac/TryWithResources/InterruptedExceptionTest.java generic-all -tools/javac/TryWithResources/UnusedResourcesTest.java linux-all tools/javac/VarDeclarationWithAssignment.java generic-all +tools/javac/annotations/8218152/MalformedAnnotationProcessorTests.java generic-all tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest1.java linux-all tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java linux-all tools/javac/api/6411310/T6411310.java generic-all tools/javac/api/6411310/Test.java generic-all tools/javac/api/T6430241.java generic-all tools/javac/api/T6877206.java generic-all -tools/javac/api/TestContainTypes.java generic-all -tools/javac/api/TestGetElement.java generic-all tools/javac/api/ToolProvider/HelloWorldTest.java generic-all tools/javac/api/ToolProvider/ToolProviderTest1.java generic-all tools/javac/api/ToolProvider/ToolProviderTest2.java generic-all tools/javac/defaultMethods/Assertions.java generic-all tools/javac/defaultMethods/static/hiding/InterfaceMethodHidingTest.java generic-all -tools/javac/defaultMethods/super/TestDefaultSuperCall.java generic-all -tools/javac/defaultMethods/syntax/TestDefaultMethodsSyntax.java generic-all tools/javac/diags/CheckExamples.java generic-all tools/javac/diags/CheckResourceKeys.java generic-all -tools/javac/diags/RunExamples.java generic-all -tools/javac/Diagnostics/6769027/T6769027.java generic-all tools/javac/failover/CheckAttributedTree.java generic-all -tools/javac/fatalErrors/NoJavaLangTest.java generic-all +tools/javac/file/zip/T6836682.java linux-all tools/javac/file/zip/T6865530.java generic-all -tools/javac/generics/diamond/7030150/GenericConstructorAndDiamondTest.java generic-all -tools/javac/generics/diamond/7046778/DiamondAndInnerClassTest.java generic-all -tools/javac/generics/inference/7086601/T7086601b.java generic-all tools/javac/generics/rawOverride/7062745/GenericOverrideTest.java generic-all +tools/javac/generics/inference/7086601/T7086601b.java windows-all tools/javac/inheritedAccess/MethodReferenceQualification_1.java generic-all tools/javac/jvm/T7024096.java generic-all tools/javac/jvm/T8020689.java generic-all -tools/javac/lambda/LambdaConv08.java generic-all -tools/javac/lambda/LambdaConv16.java generic-all -tools/javac/lambda/LambdaParserTest.java generic-all tools/javac/lambda/MethodReference66.java generic-all -tools/javac/lambda/MethodReferenceParserTest.java generic-all +tools/javac/lambda/T8031967.java macosx-all +tools/javac/lambda/T8145051.java generic-all tools/javac/lambda/TestInvokeDynamic.java linux-all tools/javac/lambda/TestSelfRef.java linux-all -tools/javac/lambda/bridge/TestMetafactoryBridges.java generic-all -tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java generic-all -tools/javac/lambda/funcInterfaces/LambdaTest2_SAM1.java generic-all -tools/javac/lambda/funcInterfaces/LambdaTest2_SAM2.java generic-all tools/javac/lambda/intersection/IntersectionTargetTypeTest.java generic-all tools/javac/lambda/lambdaExpression/LambdaTest5.java generic-all -tools/javac/lambda/lambdaExpression/SamConversionComboTest.java generic-all -tools/javac/lambda/methodReference/SamConversionComboTest.java generic-all -tools/javac/lambdaShapes/org/openjdk/tests/javac/FDTest.java generic-all tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java generic-all -tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java generic-all -tools/javac/newlines/NewLineTest.java generic-all tools/javac/nio/compileTest/CompileTest.java generic-all -tools/javac/processing/TestWarnErrorCount.java generic-all tools/javac/processing/model/testgetallmembers/Main.java generic-all tools/javac/processing/model/type/MirroredTypeEx/OverEager.java generic-all tools/javac/profiles/ProfileOptionTest.java generic-all @@ -83,11 +60,7 @@ tools/javac/proprietary/WarnWildcard.java tools/javac/tree/JavacTreeScannerTest.java linux-all tools/javac/tree/SourceTreeScannerTest.java linux-all tools/javac/tree/TreePosTest.java linux-all -tools/javac/types/TestComparisons.java generic-all tools/javac/varargs/6199075/T6199075.java generic-all -tools/javac/varargs/7042566/T7042566.java generic-all -tools/javac/varargs/7043922/T7043922.java generic-all -tools/javac/varargs/warning/Warn4.java generic-all tools/javac/varargs/warning/Warn5.java generic-all tools/javac/versions/check.sh generic-all tools/javac/warnings/6594914/T6594914b.java generic-all @@ -95,10 +68,10 @@ tools/javadoc/6942366/T6942366.java tools/javadoc/6964914/TestStdDoclet.java generic-all tools/javadoc/6964914/TestUserDoclet.java generic-all tools/javadoc/CheckResourceKeys.java generic-all +tools/javadoc/CompletionError.java macosx-all tools/javadoc/api/basic/GetTask_FileManagerTest.java generic-all tools/javah/ReadOldClass.sh generic-all tools/javah/T6893943.java generic-all -tools/javah/T6994608.java generic-all tools/javap/T6729471.java generic-all tools/javap/T6863746.java generic-all tools/jdeps/APIDeps.java generic-all @@ -106,20 +79,9 @@ tools/jdeps/Basic.java tools/jdeps/DotFileTest.java generic-all tools/sjavac/SJavacWrapper.java generic-all -# likely fails because the file takes too long to build -tools/javac/file/zip/T6836682.java linux-all - # executive decision: disabling these test because they're sensitive to the method order in the stubs, which is derived from the method order in the assembly metadata, which is supposed to be derived from the method order in the original class file. # however, RuntimeByteCodeJavaType can't currently be guarenteed to emit methods in the exact correct order, since some of the method linking is recursive and ondemand. # so, until this is fixed, and we have a stable way to determine method order, we're disabling this guy # it did work previously, by accident, as far as I can tell tools/javac/lambda/MostSpecific09.java generic-all tools/javac/lambda/8019480/T8019480.java generic-all - -# Broken on OS X -tools/javac/lambda/T8031967.java macosx-all -tools/javadoc/CompletionError.java macosx-all -tools/javac/StringsInSwitch/OneCaseSwitches.java macosx-all - -# unknown -tools/javac/annotations/8218152/MalformedAnnotationProcessorTests.java generic-all diff --git a/src/IKVM.OpenJDK.Tests/nashorn/ExcludeList.txt b/src/IKVM.OpenJDK.Tests/nashorn/test/ExcludeList.txt similarity index 100% rename from src/IKVM.OpenJDK.Tests/nashorn/ExcludeList.txt rename to src/IKVM.OpenJDK.Tests/nashorn/test/ExcludeList.txt diff --git a/src/IKVM.Reflection/Emit/ModuleBuilder.cs b/src/IKVM.Reflection/Emit/ModuleBuilder.cs index 6f1348fbb3..d00b52c81b 100644 --- a/src/IKVM.Reflection/Emit/ModuleBuilder.cs +++ b/src/IKVM.Reflection/Emit/ModuleBuilder.cs @@ -165,7 +165,10 @@ public override int GetHashCode() return type.GetHashCode() + name.GetHashCode() + signature.GetHashCode(); } - internal MethodBase LookupMethod() => type.FindMethod(name, (MethodSignature)signature); + internal MethodBase LookupMethod() + { + return type.FindMethod(name, (MethodSignature)signature); + } } diff --git a/src/IKVM.Runtime-ref/IKVM.Runtime-ref.csproj b/src/IKVM.Runtime-ref/IKVM.Runtime-ref.csproj index 79ebf253ea..919af962fb 100644 --- a/src/IKVM.Runtime-ref/IKVM.Runtime-ref.csproj +++ b/src/IKVM.Runtime-ref/IKVM.Runtime-ref.csproj @@ -13,7 +13,6 @@ - diff --git a/src/IKVM.Runtime/AttributeHelper.cs b/src/IKVM.Runtime/AttributeHelper.cs index c5d102f561..a8da1548c4 100644 --- a/src/IKVM.Runtime/AttributeHelper.cs +++ b/src/IKVM.Runtime/AttributeHelper.cs @@ -23,24 +23,20 @@ Jeroen Frijters */ using System; using System.Collections.Generic; - -using IKVM.Attributes; - -using System.Runtime.CompilerServices; +using System.ComponentModel; using System.Diagnostics; +using System.Runtime.CompilerServices; -using IKVM.ByteCode.Reading; -using IKVM.ByteCode.Parsing; - -using System.Linq; -using System.ComponentModel; +using IKVM.Attributes; +using IKVM.ByteCode.Buffers; +using IKVM.ByteCode.Decoding; +using IKVM.ByteCode.Encoding; #if IMPORTER || EXPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; using Type = IKVM.Reflection.Type; - #else using System.Reflection; using System.Reflection.Emit; @@ -118,9 +114,9 @@ class AttributeHelper Type TypeOfModifiers => typeofModifiers ??= LoadType(typeof(Modifiers)); - Type TypeOfSourceFileAttribute => typeofSourceFileAttribute ??= LoadType(typeof(SourceFileAttribute)); + Type TypeOfSourceFileAttribute => typeofSourceFileAttribute ??= LoadType(typeof(IKVM.Attributes.SourceFileAttribute)); - Type TypeOfLineNumberTableAttribute => typeofLineNumberTableAttribute ??= LoadType(typeof(LineNumberTableAttribute)); + Type TypeOfLineNumberTableAttribute => typeofLineNumberTableAttribute ??= LoadType(typeof(IKVM.Attributes.LineNumberTableAttribute)); #endif @@ -136,7 +132,7 @@ class AttributeHelper Type TypeOfJavaModuleAttribute => typeofJavaModuleAttribute ??= LoadType(typeof(JavaModuleAttribute)); - Type TypeOfSignatureAttribute => typeofSignatureAttribute ??= LoadType(typeof(SignatureAttribute)); + Type TypeOfSignatureAttribute => typeofSignatureAttribute ??= LoadType(typeof(IKVM.Attributes.SignatureAttribute)); Type TypeOfInnerClassAttribute => typeofInnerClassAttribute ??= LoadType(typeof(InnerClassAttribute)); @@ -160,11 +156,11 @@ class AttributeHelper Type TypeOfNonNestedOuterClassAttribute => typeofNonNestedOuterClassAttribute ??= LoadType(typeof(NonNestedOuterClassAttribute)); - Type TypeOfEnclosingMethodAttribute => typeofEnclosingMethodAttribute ??= LoadType(typeof(EnclosingMethodAttribute)); + Type TypeOfEnclosingMethodAttribute => typeofEnclosingMethodAttribute ??= LoadType(typeof(IKVM.Attributes.EnclosingMethodAttribute)); - Type TypeOfMethodParametersAttribute => typeofMethodParametersAttribute ??= LoadType(typeof(MethodParametersAttribute)); + Type TypeOfMethodParametersAttribute => typeofMethodParametersAttribute ??= LoadType(typeof(IKVM.Attributes.MethodParametersAttribute)); - Type TypeOfRuntimeVisibleTypeAnnotationsAttribute => typeofRuntimeVisibleTypeAnnotationsAttribute ??= LoadType(typeof(RuntimeVisibleTypeAnnotationsAttribute)); + Type TypeOfRuntimeVisibleTypeAnnotationsAttribute => typeofRuntimeVisibleTypeAnnotationsAttribute ??= LoadType(typeof(IKVM.Attributes.RuntimeVisibleTypeAnnotationsAttribute)); Type TypeOfConstantPoolAttribute => typeofConstantPoolAttribute ??= LoadType(typeof(ConstantPoolAttribute)); @@ -886,50 +882,44 @@ internal void SetSignatureAttribute(MethodBuilder mb, string signature) internal void SetMethodParametersAttribute(MethodBuilder mb, Modifiers[] modifiers) { - methodParametersAttribute ??= TypeOfMethodParametersAttribute.GetConstructor(new Type[] { TypeOfModifiers.MakeArrayType() }); - mb.SetCustomAttribute(new CustomAttributeBuilder(methodParametersAttribute, new object[] { modifiers })); + methodParametersAttribute ??= TypeOfMethodParametersAttribute.GetConstructor(new[] { TypeOfModifiers.MakeArrayType() }); + mb.SetCustomAttribute(new CustomAttributeBuilder(methodParametersAttribute, new[] { modifiers })); } - internal void SetRuntimeVisibleTypeAnnotationsAttribute(TypeBuilder tb, IReadOnlyList data) + internal void SetRuntimeVisibleTypeAnnotationsAttribute(TypeBuilder tb, ref readonly TypeAnnotationTable table) { - var r = new RuntimeVisibleTypeAnnotationsAttributeRecord(data.Select(i => i.Record).ToArray()); - var m = new byte[r.GetSize()]; - var w = new ClassFormatWriter(m); - if (r.TryWrite(ref w) == false) - throw new InternalException(); + var builder = new BlobBuilder(); + var encoder = new TypeAnnotationTableEncoder(builder); + table.WriteTo(ref encoder); - runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor(new Type[] { context.Types.Byte.MakeArrayType() }); - tb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, new object[] { m })); + runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor([context.Types.Byte.MakeArrayType()]); + tb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, [builder.ToArray()])); } - internal void SetRuntimeVisibleTypeAnnotationsAttribute(FieldBuilder fb, IReadOnlyList data) + internal void SetRuntimeVisibleTypeAnnotationsAttribute(FieldBuilder fb, ref readonly TypeAnnotationTable table) { - var r = new RuntimeVisibleTypeAnnotationsAttributeRecord(data.Select(i => i.Record).ToArray()); - var m = new byte[r.GetSize()]; - var w = new ClassFormatWriter(m); - if (r.TryWrite(ref w) == false) - throw new InternalException(); + var builder = new BlobBuilder(); + var encoder = new TypeAnnotationTableEncoder(builder); + table.WriteTo(ref encoder); - runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor(new Type[] { context.Types.Byte.MakeArrayType() }); - fb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, new object[] { m })); + runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor([context.Types.Byte.MakeArrayType()]); + fb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, [builder.ToArray()])); } - internal void SetRuntimeVisibleTypeAnnotationsAttribute(MethodBuilder mb, IReadOnlyList data) + internal void SetRuntimeVisibleTypeAnnotationsAttribute(MethodBuilder mb, ref readonly TypeAnnotationTable table) { - var r = new RuntimeVisibleTypeAnnotationsAttributeRecord(data.Select(i => i.Record).ToArray()); - var m = new byte[r.GetSize()]; - var w = new ClassFormatWriter(m); - if (r.TryWrite(ref w) == false) - throw new InternalException(); + var builder = new BlobBuilder(); + var encoder = new TypeAnnotationTableEncoder(builder); + table.WriteTo(ref encoder); - runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor(new Type[] { context.Types.Byte.MakeArrayType() }); - mb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, new object[] { m })); + runtimeVisibleTypeAnnotationsAttribute ??= TypeOfRuntimeVisibleTypeAnnotationsAttribute.GetConstructor([context.Types.Byte.MakeArrayType()]); + mb.SetCustomAttribute(new CustomAttributeBuilder(runtimeVisibleTypeAnnotationsAttribute, [builder.ToArray()])); } internal void SetConstantPoolAttribute(TypeBuilder tb, object[] constantPool) { constantPoolAttribute ??= TypeOfConstantPoolAttribute.GetConstructor(new Type[] { context.Types.Object.MakeArrayType() }); - tb.SetCustomAttribute(new CustomAttributeBuilder(constantPoolAttribute, new object[] { constantPool })); + tb.SetCustomAttribute(new CustomAttributeBuilder(constantPoolAttribute, [constantPool])); } internal void SetParamArrayAttribute(ParameterBuilder pb) @@ -1045,32 +1035,32 @@ internal string GetNonNestedOuterClasses(Type t) #endif } - internal SignatureAttribute GetSignature(MemberInfo member) + internal IKVM.Attributes.SignatureAttribute GetSignature(MemberInfo member) { #if !IMPORTER && !EXPORTER - var attribs = member.GetCustomAttributes(typeof(SignatureAttribute), false); - return attribs.Length == 1 ? (SignatureAttribute)attribs[0] : null; + var attribs = member.GetCustomAttributes(typeof(IKVM.Attributes.SignatureAttribute), false); + return attribs.Length == 1 ? (IKVM.Attributes.SignatureAttribute)attribs[0] : null; #else foreach (var cad in CustomAttributeData.__GetCustomAttributes(member, TypeOfSignatureAttribute, false)) { var args = cad.ConstructorArguments; - return new SignatureAttribute((string)args[0].Value); + return new IKVM.Attributes.SignatureAttribute((string)args[0].Value); } return null; #endif } - internal MethodParametersAttribute GetMethodParameters(MethodBase method) + internal IKVM.Attributes.MethodParametersAttribute GetMethodParameters(MethodBase method) { #if !IMPORTER && !EXPORTER - var attribs = method.GetCustomAttributes(typeof(MethodParametersAttribute), false); - return attribs.Length == 1 ? (MethodParametersAttribute)attribs[0] : null; + var attribs = method.GetCustomAttributes(typeof(IKVM.Attributes.MethodParametersAttribute), false); + return attribs.Length == 1 ? (IKVM.Attributes.MethodParametersAttribute)attribs[0] : null; #else foreach (var cad in CustomAttributeData.__GetCustomAttributes(method, TypeOfMethodParametersAttribute, false)) { var args = cad.ConstructorArguments; - return new MethodParametersAttribute(DecodeArray(args[0])); + return new IKVM.Attributes.MethodParametersAttribute(DecodeArray(args[0])); } return null; #endif @@ -1092,8 +1082,8 @@ internal object[] GetConstantPool(Type type) internal byte[] GetRuntimeVisibleTypeAnnotations(MemberInfo member) { #if !IMPORTER && !EXPORTER - object[] attribs = member.GetCustomAttributes(typeof(RuntimeVisibleTypeAnnotationsAttribute), false); - return attribs.Length == 1 ? ((RuntimeVisibleTypeAnnotationsAttribute)attribs[0]).data : null; + object[] attribs = member.GetCustomAttributes(typeof(IKVM.Attributes.RuntimeVisibleTypeAnnotationsAttribute), false); + return attribs.Length == 1 ? ((IKVM.Attributes.RuntimeVisibleTypeAnnotationsAttribute)attribs[0]).data : null; #else foreach (CustomAttributeData cad in CustomAttributeData.__GetCustomAttributes(member, TypeOfRuntimeVisibleTypeAnnotationsAttribute, false)) { @@ -1247,17 +1237,17 @@ internal bool HasEnclosingMethodAttribute(Type type) return type.IsDefined(TypeOfEnclosingMethodAttribute, false); } - internal EnclosingMethodAttribute GetEnclosingMethodAttribute(Type type) + internal IKVM.Attributes.EnclosingMethodAttribute GetEnclosingMethodAttribute(Type type) { #if !IMPORTER && !EXPORTER - var attr = type.GetCustomAttributes(typeof(EnclosingMethodAttribute), false); + var attr = type.GetCustomAttributes(typeof(IKVM.Attributes.EnclosingMethodAttribute), false); if (attr.Length == 1) - return ((EnclosingMethodAttribute)attr[0]).SetClassName(context, type); + return ((IKVM.Attributes.EnclosingMethodAttribute)attr[0]).SetClassName(context, type); return null; #else foreach (var cad in CustomAttributeData.__GetCustomAttributes(type, TypeOfEnclosingMethodAttribute, false)) - return new EnclosingMethodAttribute((string)cad.ConstructorArguments[0].Value, (string)cad.ConstructorArguments[1].Value, (string)cad.ConstructorArguments[2].Value).SetClassName(context, type); + return new IKVM.Attributes.EnclosingMethodAttribute((string)cad.ConstructorArguments[0].Value, (string)cad.ConstructorArguments[1].Value, (string)cad.ConstructorArguments[2].Value).SetClassName(context, type); return null; #endif diff --git a/src/IKVM.Runtime/Attributes/ConstantPoolAttribute.cs b/src/IKVM.Runtime/Attributes/ConstantPoolAttribute.cs index d1c26a115b..7bac3e38a8 100644 --- a/src/IKVM.Runtime/Attributes/ConstantPoolAttribute.cs +++ b/src/IKVM.Runtime/Attributes/ConstantPoolAttribute.cs @@ -30,87 +30,87 @@ namespace IKVM.Attributes { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)] - public sealed class ConstantPoolAttribute : Attribute - { - - internal readonly object[] constantPool; - - public ConstantPoolAttribute(object[] constantPool) - { - this.constantPool = Decompress(constantPool); - } - - internal static object[] Decompress(object[] constantPool) - { - List list = new List(); - foreach (object obj in constantPool) - { - int emptySlots = obj as byte? ?? obj as ushort? ?? 0; - if (emptySlots == 0) - { - list.Add(Unescape(obj)); - } - else - { - for (int i = 0; i < emptySlots; i++) - { - list.Add(null); - } - } - } - return list.ToArray(); - } - - private static object Unescape(object obj) - { - string str = obj as string; - if (str != null) - { - obj = UnicodeUtil.UnescapeInvalidSurrogates(str); - } - return obj; - } - - internal static object[] Compress(object[] constantPool, bool[] inUse) - { - int length = constantPool.Length; - while (!inUse[length - 1]) - { - length--; - } - int write = 0; - for (int read = 0; read < length; read++) - { - int start = read; - while (!inUse[read]) - { - read++; - } - int emptySlots = read - start; - if (emptySlots > 255) - { - constantPool[write++] = (ushort)emptySlots; - } - else if (emptySlots > 0) - { - constantPool[write++] = (byte)emptySlots; - } - constantPool[write++] = Escape(constantPool[read]); - } - Array.Resize(ref constantPool, write); - return constantPool; - } - - private static object Escape(object obj) - { - string str = obj as string; - if (str != null) - { - obj = UnicodeUtil.EscapeInvalidSurrogates(str); - } - return obj; - } - - } + public sealed class ConstantPoolAttribute : Attribute + { + + internal static object[] Decompress(object[] constantPool) + { + var list = new List(); + + foreach (var obj in constantPool) + { + int emptySlots = obj as byte? ?? obj as ushort? ?? 0; + if (emptySlots == 0) + { + list.Add(Unescape(obj)); + } + else + { + for (int i = 0; i < emptySlots; i++) + list.Add(null); + } + } + + return list.ToArray(); + } + + static object Unescape(object obj) + { + if (obj is string str) + obj = UnicodeUtil.UnescapeInvalidSurrogates(str); + + return obj; + } + + internal static object[] Compress(object[] constantPool, bool[] inUse) + { + int length = constantPool.Length; + while (!inUse[length - 1]) + length--; + + int write = 0; + for (int read = 0; read < length; read++) + { + int start = read; + while (!inUse[read]) + read++; + + int emptySlots = read - start; + if (emptySlots > 255) + { + constantPool[write++] = (ushort)emptySlots; + } + else if (emptySlots > 0) + { + constantPool[write++] = (byte)emptySlots; + } + + constantPool[write++] = Escape(constantPool[read]); + } + + Array.Resize(ref constantPool, write); + return constantPool; + } + + static object Escape(object obj) + { + if (obj is string str) + obj = UnicodeUtil.EscapeInvalidSurrogates(str); + + return obj; + } + + internal readonly object[] constantPool; + + /// + /// Initializes a new instance. + /// + /// + public ConstantPoolAttribute(object[] constantPool) + { + this.constantPool = Decompress(constantPool); + } + + } } diff --git a/src/IKVM.Runtime/ByteCodeHelper.cs b/src/IKVM.Runtime/ByteCodeHelper.cs index a170e6ed58..df39527faf 100644 --- a/src/IKVM.Runtime/ByteCodeHelper.cs +++ b/src/IKVM.Runtime/ByteCodeHelper.cs @@ -316,7 +316,7 @@ private static void DynamicLoadMethodTypeImpl(ref global::java.lang.invoke.Metho return cache; } - private static global::java.lang.invoke.MethodHandle DynamicLoadMethodHandleImpl(int kind, string clazz, string name, string sig, ikvm.@internal.CallerID callerID) + static global::java.lang.invoke.MethodHandle DynamicLoadMethodHandleImpl(int kind, string clazz, string name, string sig, ikvm.@internal.CallerID callerID) { #if FIRST_PASS throw new NotImplementedException(); @@ -325,19 +325,19 @@ private static void DynamicLoadMethodTypeImpl(ref global::java.lang.invoke.Metho try { - switch ((ReferenceKind)kind) + switch ((MethodHandleKind)kind) { - case ReferenceKind.GetStatic: - case ReferenceKind.PutStatic: - case ReferenceKind.GetField: - case ReferenceKind.PutField: + case MethodHandleKind.GetStatic: + case MethodHandleKind.PutStatic: + case MethodHandleKind.GetField: + case MethodHandleKind.PutField: global::java.lang.Class type = RuntimeClassLoader.FromCallerID(callerID).FieldTypeWrapperFromSig(sig, LoadMode.LoadOrThrow).ClassObject; return global::java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(callerID.getCallerClass(), kind, refc, name, type); default: global::java.lang.invoke.MethodType mt = null; DynamicLoadMethodType(ref mt, sig, callerID); // HACK linkMethodHandleConstant is broken for MethodHandle.invoke[Exact] - if (kind == (int)ReferenceKind.InvokeVirtual && refc == JVM.Context.JavaBase.TypeOfJavaLangInvokeMethodHandle.ClassObject) + if (kind == (int)MethodHandleKind.InvokeVirtual && refc == JVM.Context.JavaBase.TypeOfJavaLangInvokeMethodHandle.ClassObject) { switch (name) { @@ -1233,13 +1233,10 @@ public static void DynamicLinkIndyCallSite(ref IndyCallSite site, global:: if (cs != null) { if (cs.ics == null) - { MethodHandleNatives.InitializeCallSite(cs); - } + lock (cs.ics) - { cs.ics.SetTarget(cs.target); - } } global::java.lang.invoke.MethodType typeCache = null; @@ -1267,11 +1264,10 @@ public static void DynamicLinkIndyCallSite(ref IndyCallSite site, global:: ics = new IndyCallSite(); ((IIndyCallSite)ics).SetTarget(cs.dynamicInvoker().asType(LoadMethodType())); } + IndyCallSite curr = site; if (curr.IsBootstrap) - { Interlocked.CompareExchange(ref site, ics, curr); - } #endif } diff --git a/src/IKVM.Runtime/ClassFile.BootstrapMethod.cs b/src/IKVM.Runtime/ClassFile.BootstrapMethod.cs index 9820107791..5690a2cd1b 100644 --- a/src/IKVM.Runtime/ClassFile.BootstrapMethod.cs +++ b/src/IKVM.Runtime/ClassFile.BootstrapMethod.cs @@ -22,26 +22,29 @@ Jeroen Frijters */ +using IKVM.ByteCode; + namespace IKVM.Runtime { sealed partial class ClassFile { + internal struct BootstrapMethod { - private ushort bsm_index; - private ushort[] args; + private MethodHandleConstantHandle method; + private ConstantHandle[] args; - internal BootstrapMethod(ushort bsm_index, ushort[] args) + internal BootstrapMethod(MethodHandleConstantHandle method, ConstantHandle[] args) { - this.bsm_index = bsm_index; + this.method = method; this.args = args; } - internal int BootstrapMethodIndex + internal MethodHandleConstantHandle BootstrapMethodIndex { - get { return bsm_index; } + get { return method; } } internal int ArgumentCount @@ -49,7 +52,7 @@ internal int ArgumentCount get { return args.Length; } } - internal int GetArgument(int index) + internal ConstantHandle GetArgument(int index) { return args[index]; } diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemClass.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemClass.cs index 01b0031d59..06c0e92ab1 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemClass.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemClass.cs @@ -23,7 +23,7 @@ Jeroen Frijters */ using System; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -36,7 +36,7 @@ internal sealed class ConstantPoolItemClass : ConstantPoolItem, IEquatable /// - /// + /// /// - internal ConstantPoolItemClass(RuntimeContext context, ClassConstantReader reader) : + internal ConstantPoolItemClass(RuntimeContext context, ClassConstantData data) : base(context) { - this.reader = reader ?? throw new ArgumentNullException(nameof(reader)); + this.data = data; } /// @@ -72,7 +72,7 @@ internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileP if (name != null) return; - name = classFile.GetConstantPoolUtf8String(utf8_cp, reader.Record.NameIndex); + name = classFile.GetConstantPoolUtf8String(utf8_cp, data.Name); if (name.Length > 0) { // We don't enforce the strict class name rules in the static compiler, since HotSpot doesn't enforce *any* rules on diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemDouble.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemDouble.cs index e281d0999c..97c86ccaa6 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemDouble.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemDouble.cs @@ -22,7 +22,9 @@ Jeroen Frijters */ -using IKVM.ByteCode.Reading; +using System; + +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -39,11 +41,11 @@ sealed class ConstantPoolItemDouble : ConstantPoolItem /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemDouble(RuntimeContext context, DoubleConstantReader reader) : + /// + internal ConstantPoolItemDouble(RuntimeContext context, DoubleConstantData data) : base(context) { - d = reader.Value; + d = data.Value; } internal override ConstantType GetConstantType() => ConstantType.Double; diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemFMI.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFMI.cs index e6ea94f012..fea72e0112 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemFMI.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFMI.cs @@ -23,6 +23,8 @@ Jeroen Frijters */ using System; +using IKVM.ByteCode; + namespace IKVM.Runtime { @@ -32,8 +34,8 @@ sealed partial class ClassFile internal abstract class ConstantPoolItemFMI : ConstantPoolItem { - readonly ushort class_index; - readonly ushort name_and_type_index; + readonly ClassConstantHandle clazzHandle; + readonly NameAndTypeConstantHandle nameAndType; ConstantPoolItemClass clazz; string name; @@ -43,26 +45,28 @@ internal abstract class ConstantPoolItemFMI : ConstantPoolItem /// Initializes a new instance. /// /// - /// - /// - internal ConstantPoolItemFMI(RuntimeContext context, ushort classIndex, ushort nameAndTypeIndex) : + /// + /// + internal ConstantPoolItemFMI(RuntimeContext context, ClassConstantHandle clazz, NameAndTypeConstantHandle nameAndType) : base(context) { - class_index = classIndex; - name_and_type_index = nameAndTypeIndex; + this.clazzHandle = clazz; + this.nameAndType = nameAndType; } internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) { - ConstantPoolItemNameAndType name_and_type = (ConstantPoolItemNameAndType)classFile.GetConstantPoolItem(name_and_type_index); - clazz = (ConstantPoolItemClass)classFile.GetConstantPoolItem(class_index); + var name_and_type = (ConstantPoolItemNameAndType)classFile.GetConstantPoolItem(nameAndType); + + clazz = (ConstantPoolItemClass)classFile.GetConstantPoolItem(clazzHandle); // if the constant pool items referred to were strings, GetConstantPoolItem returns null if (name_and_type == null || clazz == null) { throw new ClassFormatError("Bad index in constant pool"); } - name = String.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.nameIndex)); - descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.descriptorIndex); + + name = String.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.NameHandle)); + descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.DescriptorHandle); Validate(name, descriptor, classFile.MajorVersion); descriptor = String.Intern(descriptor.Replace('/', '.')); } diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemFieldref.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFieldref.cs index 67c8da1ee0..4ff50358ce 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemFieldref.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFieldref.cs @@ -22,7 +22,10 @@ Jeroen Frijters */ -using IKVM.ByteCode.Reading; +using System; + +using IKVM.ByteCode; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -40,9 +43,9 @@ internal sealed class ConstantPoolItemFieldref : ConstantPoolItemFMI /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemFieldref(RuntimeContext context, FieldrefConstantReader reader) : - base(context, reader.Record.ClassIndex, reader.Record.NameAndTypeIndex) + /// + internal ConstantPoolItemFieldref(RuntimeContext context, FieldrefConstantData data) : + base(context, data.Class, data.NameAndType) { } @@ -51,7 +54,7 @@ protected override void Validate(string name, string descriptor, int majorVersio { if (!IsValidFieldSig(descriptor)) throw new ClassFormatError("Invalid field signature \"{0}\"", descriptor); - if (!IsValidFieldName(name, majorVersion)) + if (!IsValidFieldName(name, new ClassFormatVersion((ushort)majorVersion, 0))) throw new ClassFormatError("Invalid field name \"{0}\"", name); } diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemFloat.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFloat.cs index b682d15f0b..f7d6b0f323 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemFloat.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemFloat.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -39,11 +39,11 @@ sealed class ConstantPoolItemFloat : ConstantPoolItem /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemFloat(RuntimeContext context, FloatConstantReader reader) : + /// + internal ConstantPoolItemFloat(RuntimeContext context, FloatConstantData data) : base(context) { - v = reader.Value; + v = data.Value; } internal override ConstantType GetConstantType() diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemInteger.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInteger.cs index 9926f783bb..a3c44a75ba 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemInteger.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInteger.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -39,11 +39,11 @@ sealed class ConstantPoolItemInteger : ConstantPoolItem /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemInteger(RuntimeContext context, IntegerConstantReader reader) : + /// + internal ConstantPoolItemInteger(RuntimeContext context, IntegerConstantData data) : base(context) { - v = reader.Value; + v = data.Value; } internal override ConstantType GetConstantType() => ConstantType.Integer; diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemInterfaceMethodref.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInterfaceMethodref.cs index d3194db4ea..aea2883701 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemInterfaceMethodref.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInterfaceMethodref.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -37,9 +37,9 @@ internal sealed class ConstantPoolItemInterfaceMethodref : ConstantPoolItemMI /// initializes a new instance. /// /// - /// - internal ConstantPoolItemInterfaceMethodref(RuntimeContext context, InterfaceMethodrefConstantReader reader) : - base(context, reader.Record.ClassIndex, reader.Record.NameAndTypeIndex) + /// + internal ConstantPoolItemInterfaceMethodref(RuntimeContext context, InterfaceMethodrefConstantData data) : + base(context, data.Class, data.NameAndType) { } diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemInvokeDynamic.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInvokeDynamic.cs index 7af52807ca..35ad95e918 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemInvokeDynamic.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemInvokeDynamic.cs @@ -21,7 +21,10 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.ByteCode.Reading; +using System; + +using IKVM.ByteCode; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -31,8 +34,8 @@ sealed partial class ClassFile internal sealed class ConstantPoolItemInvokeDynamic : ConstantPoolItem { - readonly ushort bootstrap_specifier_index; - readonly ushort name_and_type_index; + readonly ushort bootstrapMethodAttributeIndex; + readonly NameAndTypeConstantHandle nameAndTypeHandle; string name; string descriptor; @@ -43,23 +46,22 @@ internal sealed class ConstantPoolItemInvokeDynamic : ConstantPoolItem /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemInvokeDynamic(RuntimeContext context, InvokeDynamicConstantReader reader) : + /// + internal ConstantPoolItemInvokeDynamic(RuntimeContext context, InvokeDynamicConstantData data) : base(context) { - bootstrap_specifier_index = reader.Record.BootstrapMethodAttributeIndex; - name_and_type_index = reader.Record.NameAndTypeIndex; + bootstrapMethodAttributeIndex = data.BootstrapMethodAttributeIndex; + nameAndTypeHandle = data.NameAndType; } internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) { - var name_and_type = (ConstantPoolItemNameAndType)classFile.GetConstantPoolItem(name_and_type_index); - // if the constant pool items referred to were strings, GetConstantPoolItem returns null - if (name_and_type == null) + var nameAndType = (ConstantPoolItemNameAndType)classFile.GetConstantPoolItem(nameAndTypeHandle); + if (nameAndType == null) throw new ClassFormatError("Bad index in constant pool"); - name = string.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.nameIndex)); - descriptor = string.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, name_and_type.descriptorIndex).Replace('/', '.')); + name = string.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, nameAndType.NameHandle)); + descriptor = string.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, nameAndType.DescriptorHandle).Replace('/', '.')); } internal override void Link(RuntimeJavaType thisType, LoadMode mode) @@ -108,7 +110,7 @@ internal string Signature internal ushort BootstrapMethod { - get { return bootstrap_specifier_index; } + get { return bootstrapMethodAttributeIndex; } } } diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemLong.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemLong.cs index d28b0cbbfe..7aabd4172c 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemLong.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemLong.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -39,11 +39,11 @@ sealed class ConstantPoolItemLong : ConstantPoolItem /// initializes a new instance. /// /// - /// - internal ConstantPoolItemLong(RuntimeContext context, LongConstantReader reader) : + /// + internal ConstantPoolItemLong(RuntimeContext context, LongConstantData data) : base(context) { - l = reader.Value; + l = data.Value; } internal override ConstantType GetConstantType() => ConstantType.Long; diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemMI.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMI.cs index 192542aa6f..10f2574b5d 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemMI.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMI.cs @@ -22,6 +22,8 @@ Jeroen Frijters */ +using IKVM.ByteCode; + namespace IKVM.Runtime { @@ -40,10 +42,10 @@ internal class ConstantPoolItemMI : ConstantPoolItemFMI /// Initializes a new instance. /// /// - /// + /// /// - internal ConstantPoolItemMI(RuntimeContext context, ushort classIndex, ushort nameAndTypeIndex) : - base(context, classIndex, nameAndTypeIndex) + internal ConstantPoolItemMI(RuntimeContext context, ClassConstantHandle clazz, NameAndTypeConstantHandle nameAndTypeIndex) : + base(context, clazz, nameAndTypeIndex) { } @@ -54,7 +56,7 @@ protected override void Validate(string name, string descriptor, int majorVersio { throw new ClassFormatError("Method {0} has invalid signature {1}", name, descriptor); } - if (!IsValidMethodName(name, majorVersion)) + if (!IsValidMethodName(name, new ClassFormatVersion((ushort)majorVersion, 0))) { if (!ReferenceEquals(name, StringConstants.INIT)) { diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodHandle.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodHandle.cs index 445c3da025..6a0fb79437 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodHandle.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodHandle.cs @@ -25,7 +25,7 @@ Jeroen Frijters using System; using IKVM.ByteCode; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -36,47 +36,47 @@ sealed partial class ClassFile internal sealed class ConstantPoolItemMethodHandle : ConstantPoolItem { - readonly MethodHandleConstantReader reader; + readonly MethodHandleConstantData data; ConstantPoolItemFMI cpi; /// /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemMethodHandle(RuntimeContext context, MethodHandleConstantReader reader) : + /// + internal ConstantPoolItemMethodHandle(RuntimeContext context, MethodHandleConstantData data) : base(context) { - this.reader = reader ?? throw new ArgumentNullException(nameof(reader)); + this.data = data; } internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) { - switch (reader.ReferenceKind) + switch (data.Kind) { - case ReferenceKind.GetField: - case ReferenceKind.GetStatic: - case ReferenceKind.PutField: - case ReferenceKind.PutStatic: - cpi = classFile.GetConstantPoolItem(reader.Record.Index) as ConstantPoolItemFieldref; + case MethodHandleKind.GetField: + case MethodHandleKind.GetStatic: + case MethodHandleKind.PutField: + case MethodHandleKind.PutStatic: + cpi = classFile.GetConstantPoolItem(data.Reference) as ConstantPoolItemFieldref; break; - case ReferenceKind.InvokeSpecial: - case ReferenceKind.InvokeVirtual: - case ReferenceKind.InvokeStatic: - case ReferenceKind.NewInvokeSpecial: - cpi = classFile.GetConstantPoolItem(reader.Record.Index) as ConstantPoolItemMethodref; - if (cpi == null && classFile.MajorVersion >= 52 && (reader.ReferenceKind is ReferenceKind.InvokeStatic or ReferenceKind.InvokeSpecial)) - goto case ReferenceKind.InvokeInterface; + case MethodHandleKind.InvokeSpecial: + case MethodHandleKind.InvokeVirtual: + case MethodHandleKind.InvokeStatic: + case MethodHandleKind.NewInvokeSpecial: + cpi = classFile.GetConstantPoolItem(data.Reference) as ConstantPoolItemMethodref; + if (cpi == null && classFile.MajorVersion >= 52 && (data.Kind is MethodHandleKind.InvokeStatic or MethodHandleKind.InvokeSpecial)) + goto case MethodHandleKind.InvokeInterface; break; - case ReferenceKind.InvokeInterface: - cpi = classFile.GetConstantPoolItem(reader.Record.Index) as ConstantPoolItemInterfaceMethodref; + case MethodHandleKind.InvokeInterface: + cpi = classFile.GetConstantPoolItem(data.Reference) as ConstantPoolItemInterfaceMethodref; break; } if (cpi == null) throw new ClassFormatError("Invalid constant pool item MethodHandle"); - if (ReferenceEquals(cpi.Name, StringConstants.INIT) && reader.ReferenceKind != ReferenceKind.NewInvokeSpecial) + if (ReferenceEquals(cpi.Name, StringConstants.INIT) && data.Kind != MethodHandleKind.NewInvokeSpecial) throw new ClassFormatError("Bad method name"); } @@ -105,9 +105,9 @@ internal ConstantPoolItemFMI MemberConstantPoolItem get { return cpi; } } - internal ReferenceKind Kind + internal MethodHandleKind Kind { - get { return reader.ReferenceKind; } + get { return data.Kind; } } internal RuntimeJavaMember Member diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodType.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodType.cs index 987d26a43c..b17327c9e6 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodType.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodType.cs @@ -21,7 +21,8 @@ Jeroen Frijters jeroen@frijters.net */ -using IKVM.ByteCode.Reading; +using IKVM.ByteCode; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -32,7 +33,7 @@ sealed partial class ClassFile internal sealed class ConstantPoolItemMethodType : ConstantPoolItem { - readonly ushort signature_index; + readonly Utf8ConstantHandle signature; string descriptor; RuntimeJavaType[] argTypeWrappers; @@ -42,16 +43,16 @@ internal sealed class ConstantPoolItemMethodType : ConstantPoolItem /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemMethodType(RuntimeContext context, MethodTypeConstantReader reader) : + /// + internal ConstantPoolItemMethodType(RuntimeContext context, MethodTypeConstantData data) : base(context) { - signature_index = reader.Record.DescriptorIndex; + signature = data.Descriptor; } internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) { - var descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, signature_index); + var descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, signature); if (descriptor == null || !IsValidMethodSig(descriptor)) throw new ClassFormatError("Invalid MethodType signature"); diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodref.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodref.cs index 0bbb314136..a65004c274 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodref.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemMethodref.cs @@ -22,7 +22,7 @@ Jeroen Frijters */ using IKVM.Attributes; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; using IKVM.Runtime; namespace IKVM.Runtime @@ -38,9 +38,9 @@ internal sealed class ConstantPoolItemMethodref : ConstantPoolItemMI /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemMethodref(RuntimeContext context, MethodrefConstantReader reader) : - base(context, reader.Record.ClassIndex, reader.Record.NameAndTypeIndex) + /// + internal ConstantPoolItemMethodref(RuntimeContext context, MethodrefConstantData data) : + base(context, data.Class, data.NameAndType) { } diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemNameAndType.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemNameAndType.cs index 73aec0ba9e..49d5e91e18 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemNameAndType.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemNameAndType.cs @@ -22,7 +22,8 @@ Jeroen Frijters */ -using IKVM.ByteCode.Reading; +using IKVM.ByteCode; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -33,24 +34,24 @@ sealed partial class ClassFile sealed class ConstantPoolItemNameAndType : ConstantPoolItem { - internal ushort nameIndex; - internal ushort descriptorIndex; + internal Utf8ConstantHandle NameHandle; + internal Utf8ConstantHandle DescriptorHandle; /// /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemNameAndType(RuntimeContext context, NameAndTypeConstantReader reader) : + /// + internal ConstantPoolItemNameAndType(RuntimeContext context, NameAndTypeConstantData data) : base(context) { - nameIndex = reader.Record.NameIndex; - descriptorIndex = reader.Record.DescriptorIndex; + NameHandle = data.Name; + DescriptorHandle = data.Descriptor; } internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) { - if (classFile.GetConstantPoolUtf8String(utf8_cp, nameIndex) == null || classFile.GetConstantPoolUtf8String(utf8_cp, descriptorIndex) == null) + if (classFile.GetConstantPoolUtf8String(utf8_cp, NameHandle) == null || classFile.GetConstantPoolUtf8String(utf8_cp, DescriptorHandle) == null) throw new ClassFormatError("Illegal constant pool index"); } diff --git a/src/IKVM.Runtime/ClassFile.ConstantPoolItemString.cs b/src/IKVM.Runtime/ClassFile.ConstantPoolItemString.cs index ed1fb25980..f8e8ca6cf3 100644 --- a/src/IKVM.Runtime/ClassFile.ConstantPoolItemString.cs +++ b/src/IKVM.Runtime/ClassFile.ConstantPoolItemString.cs @@ -22,7 +22,8 @@ Jeroen Frijters */ -using IKVM.ByteCode.Reading; +using IKVM.ByteCode; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -33,23 +34,23 @@ sealed partial class ClassFile sealed class ConstantPoolItemString : ConstantPoolItem { - readonly ushort valueIndex; + readonly Utf8ConstantHandle value; string s; /// /// Initializes a new instance. /// /// - /// - internal ConstantPoolItemString(RuntimeContext context, StringConstantReader reader) : + /// + internal ConstantPoolItemString(RuntimeContext context, StringConstantData data) : base(context) { - valueIndex = reader.Record.ValueIndex; + value = data.Value; } internal override void Resolve(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options) { - s = classFile.GetConstantPoolUtf8String(utf8_cp, valueIndex); + s = classFile.GetConstantPoolUtf8String(utf8_cp, value); } internal override ConstantType GetConstantType() => ConstantType.String; diff --git a/src/IKVM.Runtime/ClassFile.Field.cs b/src/IKVM.Runtime/ClassFile.Field.cs index ea90842c34..fb6dc3ab99 100644 --- a/src/IKVM.Runtime/ClassFile.Field.cs +++ b/src/IKVM.Runtime/ClassFile.Field.cs @@ -25,7 +25,7 @@ Jeroen Frijters using IKVM.Attributes; using IKVM.ByteCode; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -44,43 +44,39 @@ internal sealed class Field : FieldOrMethod /// /// /// - /// + /// /// - internal Field(ClassFile classFile, string[] utf8_cp, FieldReader reader) : - base(classFile, utf8_cp, reader.AccessFlags, reader.Record.NameIndex, reader.Record.DescriptorIndex) + internal Field(ClassFile classFile, string[] utf8_cp, IKVM.ByteCode.Decoding.Field field) : + base(classFile, utf8_cp, field.AccessFlags, field.Name, field.Descriptor) { if ((IsPrivate && IsPublic) || (IsPrivate && IsProtected) || (IsPublic && IsProtected) || (IsFinal && IsVolatile) || (classFile.IsInterface && (!IsPublic || !IsStatic || !IsFinal || IsTransient))) throw new ClassFormatError("{0} (Illegal field modifiers: 0x{1:X})", classFile.Name, accessFlags); - for (int i = 0; i < reader.Attributes.Count; i++) + for (int i = 0; i < field.Attributes.Count; i++) { - var attribute = reader.Attributes[i]; + var attribute = field.Attributes[i]; - switch (classFile.GetConstantPoolUtf8String(utf8_cp, attribute.Info.Record.NameIndex)) + switch (classFile.GetConstantPoolUtf8String(utf8_cp, attribute.Name)) { - case "Deprecated": - if (attribute is not DeprecatedAttributeReader deprecatedAttribute) - throw new ClassFormatError("Invalid Deprecated attribute type."); - + case AttributeName.Deprecated: + attribute.AsDeprecated(); flags |= FLAG_MASK_DEPRECATED; break; - case "ConstantValue": - if (attribute is not ConstantValueAttributeReader constantValueAttribute) - throw new ClassFormatError("Invalid ConstantValue attribute type."); - + case AttributeName.ConstantValue: try { + var _constantValue = (ConstantValueAttribute)attribute; constantValue = Signature switch { - "I" => classFile.GetConstantPoolConstantInteger(constantValueAttribute.Record.ValueIndex), - "S" => (short)classFile.GetConstantPoolConstantInteger(constantValueAttribute.Record.ValueIndex), - "B" => (byte)classFile.GetConstantPoolConstantInteger(constantValueAttribute.Record.ValueIndex), - "C" => (char)classFile.GetConstantPoolConstantInteger(constantValueAttribute.Record.ValueIndex), - "Z" => classFile.GetConstantPoolConstantInteger(constantValueAttribute.Record.ValueIndex) != 0, - "J" => classFile.GetConstantPoolConstantLong(constantValueAttribute.Record.ValueIndex), - "F" => classFile.GetConstantPoolConstantFloat(constantValueAttribute.Record.ValueIndex), - "D" => classFile.GetConstantPoolConstantDouble(constantValueAttribute.Record.ValueIndex), - "Ljava.lang.String;" => classFile.GetConstantPoolConstantString(constantValueAttribute.Record.ValueIndex), + "I" => classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value), + "S" => (short)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value), + "B" => (byte)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value), + "C" => (char)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value), + "Z" => classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)_constantValue.Value) != 0, + "J" => classFile.GetConstantPoolConstantLong((LongConstantHandle)_constantValue.Value), + "F" => classFile.GetConstantPoolConstantFloat((FloatConstantHandle)_constantValue.Value), + "D" => classFile.GetConstantPoolConstantDouble((DoubleConstantHandle)_constantValue.Value), + "Ljava.lang.String;" => classFile.GetConstantPoolConstantString((StringConstantHandle)_constantValue.Value), _ => throw new ClassFormatError("{0} (Invalid signature for constant)", classFile.Name), }; } @@ -105,32 +101,27 @@ internal Field(ClassFile classFile, string[] utf8_cp, FieldReader reader) : throw new ClassFormatError("{0} (Bad index into constant pool)", classFile.Name); } break; - case "Signature": + case AttributeName.Signature: if (classFile.MajorVersion < 49) goto default; - if (attribute is not SignatureAttributeReader signatureAttribute) - throw new ClassFormatError("Invalid Signature attribute type."); - - signature = classFile.GetConstantPoolUtf8String(utf8_cp, signatureAttribute.Record.SignatureIndex); + var _signature = (IKVM.ByteCode.Decoding.SignatureAttribute)attribute; + signature = classFile.GetConstantPoolUtf8String(utf8_cp, _signature.Signature); break; - case "RuntimeVisibleAnnotations": + case AttributeName.RuntimeVisibleAnnotations: if (classFile.MajorVersion < 49) goto default; - if (attribute is not RuntimeVisibleAnnotationsAttributeReader runtimeVisibleAnnotationsAttribute) - throw new ClassFormatError("Invalid RuntimeVisibleAnnotations attribute type."); - - annotations = ReadAnnotations(runtimeVisibleAnnotationsAttribute.Annotations, classFile, utf8_cp); + var _runtimeVisibleAnnotation = (RuntimeVisibleAnnotationsAttribute)attribute; + annotations = ReadAnnotations(_runtimeVisibleAnnotation.Annotations, classFile, utf8_cp); break; - case "RuntimeInvisibleAnnotations": + case AttributeName.RuntimeInvisibleAnnotations: if (classFile.MajorVersion < 49) goto default; - if (attribute is not RuntimeInvisibleAnnotationsAttributeReader runtimeInvisibleAnnotationsAttribute) - throw new ClassFormatError("Invalid RuntimeInvisibleAnnotations attribute type."); + var _runtimeInvisibleAnnotations = (RuntimeInvisibleAnnotationsAttribute)attribute; - foreach (object[] annot in ReadAnnotations(runtimeInvisibleAnnotationsAttribute.Annotations, classFile, utf8_cp)) + foreach (object[] annot in ReadAnnotations(_runtimeInvisibleAnnotations.Annotations, classFile, utf8_cp)) { if (annot[1].Equals("Likvm/lang/Property;")) DecodePropertyAnnotation(classFile, annot); @@ -144,15 +135,13 @@ internal Field(ClassFile classFile, string[] utf8_cp, FieldReader reader) : } break; - case "RuntimeVisibleTypeAnnotations": + case AttributeName.RuntimeVisibleTypeAnnotations: if (classFile.MajorVersion < 52) goto default; - if (attribute is not RuntimeVisibleTypeAnnotationsAttributeReader runtimeVisibleTypeAnnotationsAttribute) - throw new ClassFormatError("Invalid RuntimeVisibleTypeAnnotations attribute type."); - + var _runtimeVisibleTypeAnnotations = (IKVM.ByteCode.Decoding.RuntimeVisibleTypeAnnotationsAttribute)attribute; classFile.CreateUtf8ConstantPoolItems(utf8_cp); - runtimeVisibleTypeAnnotations = runtimeVisibleTypeAnnotationsAttribute.Annotations; + runtimeVisibleTypeAnnotations = _runtimeVisibleTypeAnnotations.TypeAnnotations; break; default: break; diff --git a/src/IKVM.Runtime/ClassFile.FieldOrMethod.cs b/src/IKVM.Runtime/ClassFile.FieldOrMethod.cs index f780a9f4f2..9f91bbe353 100644 --- a/src/IKVM.Runtime/ClassFile.FieldOrMethod.cs +++ b/src/IKVM.Runtime/ClassFile.FieldOrMethod.cs @@ -22,11 +22,10 @@ Jeroen Frijters */ using System; -using System.Collections.Generic; using IKVM.Attributes; using IKVM.ByteCode; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -37,33 +36,40 @@ sealed partial class ClassFile internal abstract class FieldOrMethod : IEquatable { + readonly ClassFile clazz; protected Modifiers accessFlags; protected ushort flags; string name; string descriptor; protected string signature; protected object[] annotations; - protected IReadOnlyList runtimeVisibleTypeAnnotations; - protected IReadOnlyList runtimeInvisibleTypeAnnotations; + protected TypeAnnotationTable runtimeVisibleTypeAnnotations = TypeAnnotationTable.Empty; + protected TypeAnnotationTable runtimeInvisibleTypeAnnotations = TypeAnnotationTable.Empty; /// /// Initializes a new instance. /// - /// + /// /// /// - /// - /// - internal FieldOrMethod(ClassFile classFile, string[] utf8_cp, AccessFlag accessFlags, ushort nameIndex, ushort descriptorIndex) + /// + /// + internal FieldOrMethod(ClassFile clazz, string[] utf8_cp, AccessFlag accessFlags, Utf8ConstantHandle name, Utf8ConstantHandle descriptor) { + this.clazz = clazz ?? throw new ArgumentNullException(nameof(clazz)); this.accessFlags = (Modifiers)accessFlags; - this.name = string.Intern(classFile.GetConstantPoolUtf8String(utf8_cp, nameIndex)); - this.descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, descriptorIndex); + this.name = string.Intern(clazz.GetConstantPoolUtf8String(utf8_cp, name)); + this.descriptor = clazz.GetConstantPoolUtf8String(utf8_cp, descriptor); - ValidateSig(classFile, descriptor); - this.descriptor = string.Intern(descriptor.Replace('/', '.')); + ValidateSig(clazz, this.descriptor); + this.descriptor = string.Intern(this.descriptor.Replace('/', '.')); } + /// + /// Gets the declaring . + /// + public ClassFile Class => clazz; + protected abstract void ValidateSig(ClassFile classFile, string descriptor); internal string Name => name; @@ -104,7 +110,7 @@ internal FieldOrMethod(ClassFile classFile, string[] utf8_cp, AccessFlag accessF internal bool IsModuleInitializer => (flags & FLAG_MODULE_INITIALIZER) != 0; - internal IReadOnlyList RuntimeVisibleTypeAnnotations => runtimeVisibleTypeAnnotations; + internal ref readonly TypeAnnotationTable RuntimeVisibleTypeAnnotations => ref runtimeVisibleTypeAnnotations; public sealed override int GetHashCode() => name.GetHashCode() ^ descriptor.GetHashCode(); diff --git a/src/IKVM.Runtime/ClassFile.InnerClass.cs b/src/IKVM.Runtime/ClassFile.InnerClass.cs index 49e71db614..ba903051aa 100644 --- a/src/IKVM.Runtime/ClassFile.InnerClass.cs +++ b/src/IKVM.Runtime/ClassFile.InnerClass.cs @@ -22,19 +22,22 @@ Jeroen Frijters */ using IKVM.Attributes; +using IKVM.ByteCode; namespace IKVM.Runtime { sealed partial class ClassFile { + internal struct InnerClass { - internal ushort innerClass; // ConstantPoolItemClass - internal ushort outerClass; // ConstantPoolItemClass - internal ushort name; // ConstantPoolItemUtf8 + internal ClassConstantHandle innerClass; // ConstantPoolItemClass + internal ClassConstantHandle outerClass; // ConstantPoolItemClass + internal Utf8ConstantHandle name; // ConstantPoolItemUtf8 internal Modifiers accessFlags; } + } } diff --git a/src/IKVM.Runtime/ClassFile.Method.Code.cs b/src/IKVM.Runtime/ClassFile.Method.Code.cs index f23d43c82e..1ef6606c44 100644 --- a/src/IKVM.Runtime/ClassFile.Method.Code.cs +++ b/src/IKVM.Runtime/ClassFile.Method.Code.cs @@ -22,9 +22,11 @@ Jeroen Frijters */ using System; +using System.Buffers; using System.Collections.Generic; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { @@ -48,11 +50,11 @@ struct Code internal LineNumberTableEntry[] lineNumberTable; internal LocalVariableTableEntry[] localVariableTable; - internal void Read(ClassFile classFile, string[] utf8_cp, Method method, CodeAttributeReader reader, ClassFileParseOptions options) + internal void Read(ClassFile classFile, string[] utf8_cp, Method method, CodeAttribute attribute, ClassFileParseOptions options) { - max_stack = reader.MaxStack; - max_locals = reader.MaxLocals; - var code_length = (uint)reader.Code.Length; + max_stack = attribute.MaxStack; + max_locals = attribute.MaxLocals; + var code_length = (uint)attribute.Code.Length; if (code_length == 0 || code_length > 65535) throw new ClassFormatError("Invalid method Code length {1} in class file {0}", classFile.Name, code_length); @@ -62,7 +64,9 @@ internal void Read(ClassFile classFile, string[] utf8_cp, Method method, CodeAtt try { - var rdr = new BigEndianBinaryReader(reader.Code); + var buf = new byte[attribute.Code.Length]; + attribute.Code.CopyTo(buf); + var rdr = new BigEndianBinaryReader(buf); while (rdr.IsAtEnd == false) { instructions[instructionIndex].Read((ushort)(rdr.Position - basePosition), rdr, classFile); @@ -122,16 +126,16 @@ internal void Read(ClassFile classFile, string[] utf8_cp, Method method, CodeAtt } // read exception table - exception_table = new ExceptionTableEntry[reader.ExceptionTable.Count]; - for (int i = 0; i < reader.ExceptionTable.Count; i++) + exception_table = new ExceptionTableEntry[attribute.ExceptionTable.Count]; + for (int i = 0; i < attribute.ExceptionTable.Count; i++) { - var handler = reader.ExceptionTable[i]; + var handler = attribute.ExceptionTable[i]; var start_pc = handler.StartOffset; var end_pc = handler.EndOffset; var handler_pc = handler.HandlerOffset; - var catch_type = handler.CatchTypeIndex; + var catch_type = handler.CatchType; - if (start_pc >= end_pc || end_pc > code_length || handler_pc >= code_length || (catch_type != 0 && !classFile.SafeIsConstantPoolClass(catch_type))) + if (start_pc >= end_pc || end_pc > code_length || handler_pc >= code_length || (catch_type.IsNotNil && !classFile.SafeIsConstantPoolClass(catch_type))) throw new ClassFormatError("Illegal exception table: {0}.{1}{2}", classFile.Name, method.Name, method.Signature); classFile.MarkLinkRequiredConstantPoolItem(catch_type); @@ -156,44 +160,38 @@ internal void Read(ClassFile classFile, string[] utf8_cp, Method method, CodeAtt exception_table[i] = new ExceptionTableEntry(startIndex, endIndex, handlerIndex, catch_type, i); } - for (int i = 0; i < reader.Attributes.Count; i++) + foreach (var _attribute in attribute.Attributes) { - var attribute = reader.Attributes[i]; - - switch (classFile.GetConstantPoolUtf8String(utf8_cp, attribute.Info.Record.NameIndex)) + switch (classFile.GetConstantPoolUtf8String(utf8_cp, _attribute.Name)) { - case "LineNumberTable": - if (attribute is not LineNumberTableAttributeReader lnt) - throw new ClassFormatError("Invalid reader for line number table."); - + case AttributeName.LineNumberTable: + var lnt = (IKVM.ByteCode.Decoding.LineNumberTableAttribute)_attribute; if ((options & ClassFileParseOptions.LineNumberTable) != 0) { - lineNumberTable = new LineNumberTableEntry[lnt.Record.Items.Length]; - for (int j = 0; j < lnt.Record.Items.Length; j++) + lineNumberTable = new LineNumberTableEntry[lnt.LineNumbers.Count]; + for (int j = 0; j < lnt.LineNumbers.Count; j++) { - var item = lnt.Record.Items[j]; - lineNumberTable[j].start_pc = item.CodeOffset; + var item = lnt.LineNumbers[j]; + lineNumberTable[j].start_pc = item.StartPc; lineNumberTable[j].line_number = item.LineNumber; if (lineNumberTable[j].start_pc >= code_length) throw new ClassFormatError("{0} (LineNumberTable has invalid pc)", classFile.Name); } } break; - case "LocalVariableTable": - if (attribute is not LocalVariableTableAttributeReader lvt) - throw new ClassFormatError("Invalid reader for local variable table."); - + case AttributeName.LocalVariableTable: + var lvt = (IKVM.ByteCode.Decoding.LocalVariableTableAttribute)_attribute; if ((options & ClassFileParseOptions.LocalVariableTable) != 0) { - localVariableTable = new LocalVariableTableEntry[lvt.Record.Items.Length]; - for (int j = 0; j < lvt.Record.Items.Length; j++) + localVariableTable = new LocalVariableTableEntry[lvt.LocalVariables.Count]; + for (int j = 0; j < lvt.LocalVariables.Count; j++) { - var item = lvt.Record.Items[j]; - localVariableTable[j].start_pc = item.CodeOffset; - localVariableTable[j].length = item.CodeLength; - localVariableTable[j].name = classFile.GetConstantPoolUtf8String(utf8_cp, item.NameIndex); - localVariableTable[j].descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, item.DescriptorIndex).Replace('/', '.'); - localVariableTable[j].index = item.Index; + var item = lvt.LocalVariables[j]; + localVariableTable[j].start_pc = item.StartPc; + localVariableTable[j].length = item.Length; + localVariableTable[j].name = classFile.GetConstantPoolUtf8String(utf8_cp, item.Name); + localVariableTable[j].descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, item.Descriptor).Replace('/', '.'); + localVariableTable[j].index = item.Slot; } } break; diff --git a/src/IKVM.Runtime/ClassFile.Method.ExceptionTableEntry.cs b/src/IKVM.Runtime/ClassFile.Method.ExceptionTableEntry.cs index 25e5008420..f71a62f346 100644 --- a/src/IKVM.Runtime/ClassFile.Method.ExceptionTableEntry.cs +++ b/src/IKVM.Runtime/ClassFile.Method.ExceptionTableEntry.cs @@ -22,38 +22,64 @@ Jeroen Frijters */ +using IKVM.ByteCode; + namespace IKVM.Runtime { sealed partial class ClassFile { + internal sealed partial class Method { + internal sealed class ExceptionTableEntry { + internal readonly int startIndex; internal readonly int endIndex; internal readonly int handlerIndex; - internal readonly ushort catch_type; + internal readonly ClassConstantHandle catchType; internal readonly int ordinal; internal readonly bool isFinally; - internal ExceptionTableEntry(int startIndex, int endIndex, int handlerIndex, ushort catch_type, int ordinal) - : this(startIndex, endIndex, handlerIndex, catch_type, ordinal, false) + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + /// + internal ExceptionTableEntry(int startIndex, int endIndex, int handlerIndex, ClassConstantHandle catchType, int ordinal) : + this(startIndex, endIndex, handlerIndex, catchType, ordinal, false) { + } - internal ExceptionTableEntry(int startIndex, int endIndex, int handlerIndex, ushort catch_type, int ordinal, bool isFinally) + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + /// + /// + internal ExceptionTableEntry(int startIndex, int endIndex, int handlerIndex, ClassConstantHandle catchType, int ordinal, bool isFinally) { this.startIndex = startIndex; this.endIndex = endIndex; this.handlerIndex = handlerIndex; - this.catch_type = catch_type; + this.catchType = catchType; this.ordinal = ordinal; this.isFinally = isFinally; } + } + } + } } diff --git a/src/IKVM.Runtime/ClassFile.Method.cs b/src/IKVM.Runtime/ClassFile.Method.cs index 84f19e9fb9..140e0b1d3b 100644 --- a/src/IKVM.Runtime/ClassFile.Method.cs +++ b/src/IKVM.Runtime/ClassFile.Method.cs @@ -21,10 +21,9 @@ Jeroen Frijters jeroen@frijters.net */ -using System.Collections.Generic; - using IKVM.Attributes; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode; +using IKVM.ByteCode.Decoding; #if IMPORTER using IKVM.Tools.Importer; @@ -52,8 +51,8 @@ internal sealed partial class Method : FieldOrMethod /// /// /// - internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options, MethodReader reader) : - base(classFile, utf8_cp, reader.AccessFlags, reader.Record.NameIndex, reader.Record.DescriptorIndex) + internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions options, IKVM.ByteCode.Decoding.Method reader) : + base(classFile, utf8_cp, reader.AccessFlags, reader.Name, reader.Descriptor) { // vmspec 4.6 says that all flags, except ACC_STRICT are ignored on // however, since Java 7 it does need to be marked static @@ -80,53 +79,45 @@ internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions opt { var attribute = reader.Attributes[i]; - switch (classFile.GetConstantPoolUtf8String(utf8_cp, attribute.Info.Record.NameIndex)) + switch (classFile.GetConstantPoolUtf8String(utf8_cp, attribute.Name)) { - case "Deprecated": - if (attribute is not DeprecatedAttributeReader deprecatedAttribute) - throw new ClassFormatError("Invalid Deprecated attribute type."); - + case AttributeName.Deprecated: + var deprecatedAttribute = (DeprecatedAttribute)attribute; flags |= FLAG_MASK_DEPRECATED; break; - case "Code": + case AttributeName.Code: { - if (attribute is not CodeAttributeReader codeAttribute) - throw new ClassFormatError("Invalid attribute reader type."); + var codeAttribute = (CodeAttribute)attribute; if (code.IsEmpty == false) throw new ClassFormatError("{0} (Duplicate Code attribute)", classFile.Name); code.Read(classFile, utf8_cp, this, codeAttribute, options); break; } - case "Exceptions": + case AttributeName.Exceptions: { - if (attribute is not ExceptionsAttributeReader exceptionsAttribute) - throw new ClassFormatError("Invalid Exceptions attribute type."); if (exceptions != null) throw new ClassFormatError("{0} (Duplicate Exceptions attribute)", classFile.Name); - exceptions = new string[exceptionsAttribute.Record.ExceptionsIndexes.Length]; - for (int j = 0; j < exceptionsAttribute.Record.ExceptionsIndexes.Length; j++) - exceptions[j] = classFile.GetConstantPoolClass(exceptionsAttribute.Record.ExceptionsIndexes[j]); + var exceptionsAttribute = (ExceptionsAttribute)attribute; + exceptions = new string[exceptionsAttribute.Exceptions.Count]; + for (int j = 0; j < exceptionsAttribute.Exceptions.Count; j++) + exceptions[j] = classFile.GetConstantPoolClass(exceptionsAttribute.Exceptions[j]); break; } - case "Signature": + case AttributeName.Signature: if (classFile.MajorVersion < 49) goto default; - if (attribute is not SignatureAttributeReader signatureAttribute) - throw new ClassFormatError("Invalid Signature attribute type."); - - signature = classFile.GetConstantPoolUtf8String(utf8_cp, signatureAttribute.Record.SignatureIndex); + var signatureAttribute = (IKVM.ByteCode.Decoding.SignatureAttribute)attribute; + signature = classFile.GetConstantPoolUtf8String(utf8_cp, signatureAttribute.Signature); break; - case "RuntimeVisibleAnnotations": + case AttributeName.RuntimeVisibleAnnotations: if (classFile.MajorVersion < 49) goto default; - if (attribute is not RuntimeVisibleAnnotationsAttributeReader runtimeVisibleAnnotationsAttribute) - throw new ClassFormatError("Invalid RuntimeVisibleAnnotations attribute type."); - + var runtimeVisibleAnnotationsAttribute = (RuntimeVisibleAnnotationsAttribute)attribute; annotations = ReadAnnotations(runtimeVisibleAnnotationsAttribute.Annotations, classFile, utf8_cp); if ((options & ClassFileParseOptions.TrustedAnnotations) != 0) { @@ -152,42 +143,37 @@ internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions opt } } break; - case "RuntimeVisibleParameterAnnotations": + case AttributeName.RuntimeVisibleParameterAnnotations: if (classFile.MajorVersion < 49) goto default; - if (attribute is not RuntimeVisibleParameterAnnotationsAttributeReader runtimeVisibleParameterAnnotationsAttribute) - throw new ClassFormatError("Invalid RuntimeVisibleParameterAnnotations attribute type."); - + var runtimeVisibleParameterAnnotationsAttribute = (RuntimeVisibleParameterAnnotationsAttribute)attribute; low ??= new LowFreqData(); - low.parameterAnnotations = new object[runtimeVisibleParameterAnnotationsAttribute.Parameters.Count][]; - for (int j = 0; j < runtimeVisibleParameterAnnotationsAttribute.Parameters.Count; j++) + low.parameterAnnotations = new object[runtimeVisibleParameterAnnotationsAttribute.ParameterAnnotations.Count][]; + for (int j = 0; j < runtimeVisibleParameterAnnotationsAttribute.ParameterAnnotations.Count; j++) { - var parameter = runtimeVisibleParameterAnnotationsAttribute.Parameters[j]; + var parameter = runtimeVisibleParameterAnnotationsAttribute.ParameterAnnotations[j]; low.parameterAnnotations[j] = new object[parameter.Annotations.Count]; for (int k = 0; k < parameter.Annotations.Count; k++) low.parameterAnnotations[j][k] = ReadAnnotation(parameter.Annotations[k], classFile, utf8_cp); } break; - case "AnnotationDefault": + case AttributeName.AnnotationDefault: if (classFile.MajorVersion < 49) goto default; - if (attribute is not AnnotationDefaultAttributeReader annotationDefaultAttribute) - throw new ClassFormatError("Invalid AnnotationDefault attribute type."); - + var annotationDefaultAttribute = (IKVM.ByteCode.Decoding.AnnotationDefaultAttribute)attribute; low ??= new LowFreqData(); low.annotationDefault = ReadAnnotationElementValue(annotationDefaultAttribute.DefaultValue, classFile, utf8_cp); break; #if IMPORTER - case "RuntimeInvisibleAnnotations": + case AttributeName.RuntimeInvisibleAnnotations: if (classFile.MajorVersion < 49) goto default; - if (attribute is not RuntimeInvisibleAnnotationsAttributeReader runtimeInvisibleAnnotationsAttribute) - throw new ClassFormatError("Invalid RuntimeInvisibleAnnotations attribute type."); + var runtimeInvisibleAnnotationsAttribute = (RuntimeInvisibleAnnotationsAttribute)attribute; foreach (object[] annot in ReadAnnotations(runtimeInvisibleAnnotationsAttribute.Annotations, classFile, utf8_cp)) { @@ -215,7 +201,7 @@ internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions opt low ??= new LowFreqData(); low.InterlockedCompareAndSetField = field; } - } + } else if (annot[1].Equals("Likvm/lang/ModuleInitializer;")) { if (classFile.IsInterface || IsConstructor || IsClassInitializer || IsPrivate || IsStatic == false) @@ -231,28 +217,24 @@ internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions opt break; #endif - case "MethodParameters": + case AttributeName.MethodParameters: if (classFile.MajorVersion < 52) goto default; - if (attribute is not MethodParametersAttributeReader methodParametersAttribute) - throw new ClassFormatError("Invalid attribute reader type."); - if (parameters != null) throw new ClassFormatError("{0} (Duplicate MethodParameters attribute)", classFile.Name); + var methodParametersAttribute = (IKVM.ByteCode.Decoding.MethodParametersAttribute)attribute; parameters = ReadMethodParameters(methodParametersAttribute.Parameters, utf8_cp); break; - case "RuntimeVisibleTypeAnnotations": + case AttributeName.RuntimeVisibleTypeAnnotations: if (classFile.MajorVersion < 52) goto default; - if (attribute is not RuntimeVisibleTypeAnnotationsAttributeReader runtimeVisibleTypeAnnotationsAttribute) - throw new ClassFormatError("Invalid attribute reader type."); - + var runtimeVisibleTypeAnnotationsAttribute = (IKVM.ByteCode.Decoding.RuntimeVisibleTypeAnnotationsAttribute)attribute; classFile.CreateUtf8ConstantPoolItems(utf8_cp); - runtimeVisibleTypeAnnotations = runtimeVisibleTypeAnnotationsAttribute.Annotations; + runtimeVisibleTypeAnnotations = runtimeVisibleTypeAnnotationsAttribute.TypeAnnotations; break; default: break; @@ -279,17 +261,17 @@ internal Method(ClassFile classFile, string[] utf8_cp, ClassFileParseOptions opt } } - private static MethodParametersEntry[] ReadMethodParameters(IReadOnlyList parameters, string[] utf8_cp) + private static MethodParametersEntry[] ReadMethodParameters(MethodParameterTable parameters, string[] utf8_cp) { var l = new MethodParametersEntry[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { - var name = parameters[i].Record.NameIndex; - if (name >= utf8_cp.Length || (name != 0 && utf8_cp[name] == null)) + var name = parameters[i].Name; + if (name.Slot >= utf8_cp.Length || (name.IsNotNil && utf8_cp[name.Slot] == null)) return MethodParametersEntry.Malformed; - l[i].name = utf8_cp[name]; + l[i].name = utf8_cp[name.Slot]; l[i].accessFlags = parameters[i].AccessFlags; } diff --git a/src/IKVM.Runtime/ClassFile.cs b/src/IKVM.Runtime/ClassFile.cs index 02a96281d0..2031b302b4 100644 --- a/src/IKVM.Runtime/ClassFile.cs +++ b/src/IKVM.Runtime/ClassFile.cs @@ -22,18 +22,17 @@ Jeroen Frijters */ using System; -using System.Buffers.Binary; using System.Collections.Generic; using System.Linq; using IKVM.Attributes; using IKVM.ByteCode; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; namespace IKVM.Runtime { - sealed partial class ClassFile + sealed partial class ClassFile : IDisposable { const ushort FLAG_MASK_DEPRECATED = 0x100; @@ -46,28 +45,28 @@ sealed partial class ClassFile const ushort FLAG_MODULE_INITIALIZER = 0x8000; readonly RuntimeContext context; - readonly ClassReader reader; + readonly IKVM.ByteCode.Decoding.ClassFile clazz; - ConstantPoolItem[] constantpool; - string[] utf8_cp; + readonly ConstantPoolItem[] constantpool; + readonly string[] utf8_cp; // Modifiers is a ushort, so the next four fields combine into two 32 bit slots Modifiers access_flags; ushort flags; - ConstantPoolItemClass[] interfaces; - Field[] fields; - Method[] methods; - string sourceFile; + readonly ConstantPoolItemClass[] interfaces; + readonly Field[] fields; + readonly Method[] methods; + readonly string sourceFile; #if IMPORTER string sourcePath; #endif - string ikvmAssembly; - InnerClass[] innerClasses; - object[] annotations; - string signature; - string[] enclosingMethod; - BootstrapMethod[] bootstrapMethods; - TypeAnnotationReaderCollection runtimeVisibleTypeAnnotations; + readonly string ikvmAssembly; + readonly InnerClass[] innerClasses; + readonly object[] annotations; + readonly string signature; + readonly string[] enclosingMethod; + readonly BootstrapMethod[] bootstrapMethods; + readonly TypeAnnotationTable runtimeVisibleTypeAnnotations = TypeAnnotationTable.Empty; #if IMPORTER @@ -83,7 +82,8 @@ internal static string GetClassName(byte[] bytes, int offset, int length, out bo { try { - return GetClassName(ClassReader.Read(bytes.AsMemory(offset, length)), out isstub); + using var clazz = IKVM.ByteCode.Decoding.ClassFile.Read(bytes.AsMemory(offset, length)); + return GetClassName(clazz, out isstub); } catch (UnsupportedClassVersionException e) { @@ -103,14 +103,14 @@ internal static string GetClassName(byte[] bytes, int offset, int length, out bo /// /// /// - static string GetClassName(ClassReader reader, out bool isstub) + static string GetClassName(IKVM.ByteCode.Decoding.ClassFile reader, out bool isstub) { if (reader.Version < new ClassFormatVersion(45, 3) || reader.Version > 52) throw new UnsupportedClassVersionError(reader.Version); // this is a terrible way to go about encoding this information - isstub = reader.Constants.OfType().Any(i => i.Value == "IKVM.NET.Assembly"); - return string.Intern(reader.This.Name.Value.Replace('/', '.')); + isstub = reader.Constants.Any(i => i.Kind == ConstantKind.Utf8 && reader.Constants.Get((Utf8ConstantHandle)i).Value == "IKVM.NET.Assembly"); + return string.Intern(reader.Constants.Get(reader.This).Name.Replace('/', '.')); } #endif @@ -119,79 +119,80 @@ static string GetClassName(ClassReader reader, out bool isstub) /// Initializes a new instance. /// /// - /// + /// /// /// /// /// /// /// - internal ClassFile(RuntimeContext context, ClassReader reader, string inputClassName, ClassFileParseOptions options, object[] constantPoolPatches) + internal ClassFile(RuntimeContext context, IKVM.ByteCode.Decoding.ClassFile clazz, string inputClassName, ClassFileParseOptions options, object[] constantPoolPatches) { this.context = context ?? throw new ArgumentNullException(nameof(context)); - this.reader = reader ?? throw new ArgumentNullException(nameof(reader)); + this.clazz = clazz ?? throw new ArgumentNullException(nameof(clazz)); try { - if (reader.Version < new ClassFormatVersion(45, 3) || reader.Version > 52) - throw new UnsupportedClassVersionError(reader.Version); + if (clazz.Version < new ClassFormatVersion(45, 3) || clazz.Version > 52) + throw new UnsupportedClassVersionError(clazz.Version); - constantpool = new ConstantPoolItem[reader.Constants.Count]; - utf8_cp = new string[reader.Constants.Count]; - for (int i = 1; i < reader.Constants.Count; i++) + // load a copy of the constant pool using our own custom class hierarchy, reading data from IKVM.ByteCdoe + constantpool = new ConstantPoolItem[clazz.Constants.SlotCount]; + utf8_cp = new string[clazz.Constants.SlotCount]; + for (ushort i = 1; i < clazz.Constants.SlotCount; i++) { - switch (reader.Constants[i]) + switch (clazz.Constants.GetKind(new ConstantHandle(ConstantKind.Unknown, i))) { - case null: + case ConstantKind.Unknown: // longs and doubles can leave holes in the constant pool break; - case ClassConstantReader clazzConstant: - constantpool[i] = new ConstantPoolItemClass(context, clazzConstant); + case ConstantKind.Class: + constantpool[i] = new ConstantPoolItemClass(context, clazz.Constants.Read(new ClassConstantHandle(i))); break; - case DoubleConstantReader doubleConstant: - constantpool[i] = new ConstantPoolItemDouble(context, doubleConstant); + case ConstantKind.Double: + constantpool[i] = new ConstantPoolItemDouble(context, clazz.Constants.Read(new DoubleConstantHandle(i))); break; - case FieldrefConstantReader fieldRefConstant: - constantpool[i] = new ConstantPoolItemFieldref(context, fieldRefConstant); + case ConstantKind.Fieldref: + constantpool[i] = new ConstantPoolItemFieldref(context, clazz.Constants.Read(new FieldrefConstantHandle(i))); break; - case FloatConstantReader floatConstant: - constantpool[i] = new ConstantPoolItemFloat(context, floatConstant); + case ConstantKind.Float: + constantpool[i] = new ConstantPoolItemFloat(context, clazz.Constants.Read(new FloatConstantHandle(i))); break; - case IntegerConstantReader integerConstant: - constantpool[i] = new ConstantPoolItemInteger(context, integerConstant); + case ConstantKind.Integer: + constantpool[i] = new ConstantPoolItemInteger(context, clazz.Constants.Read(new IntegerConstantHandle(i))); break; - case InterfaceMethodrefConstantReader interfaceMethodrefConstant: - constantpool[i] = new ConstantPoolItemInterfaceMethodref(context, interfaceMethodrefConstant); + case ConstantKind.InterfaceMethodref: + constantpool[i] = new ConstantPoolItemInterfaceMethodref(context, clazz.Constants.Read(new InterfaceMethodrefConstantHandle(i))); break; - case LongConstantReader longConstant: - constantpool[i] = new ConstantPoolItemLong(context, longConstant); + case ConstantKind.Long: + constantpool[i] = new ConstantPoolItemLong(context, clazz.Constants.Read(new LongConstantHandle(i))); break; - case MethodrefConstantReader methodrefConstantReader: - constantpool[i] = new ConstantPoolItemMethodref(context, methodrefConstantReader); + case ConstantKind.Methodref: + constantpool[i] = new ConstantPoolItemMethodref(context, clazz.Constants.Read(new MethodrefConstantHandle(i))); break; - case NameAndTypeConstantReader nameAndType: - constantpool[i] = new ConstantPoolItemNameAndType(context, nameAndType); + case ConstantKind.NameAndType: + constantpool[i] = new ConstantPoolItemNameAndType(context, clazz.Constants.Read(new NameAndTypeConstantHandle(i))); break; - case MethodHandleConstantReader methodHandle: - if (reader.Version < 51) + case ConstantKind.MethodHandle: + if (clazz.Version < 51) goto default; - constantpool[i] = new ConstantPoolItemMethodHandle(context, methodHandle); + constantpool[i] = new ConstantPoolItemMethodHandle(context, clazz.Constants.Read(new MethodHandleConstantHandle(i))); break; - case MethodTypeConstantReader methodType: - if (reader.Version < 51) + case ConstantKind.MethodType: + if (clazz.Version < 51) goto default; - constantpool[i] = new ConstantPoolItemMethodType(context, methodType); + constantpool[i] = new ConstantPoolItemMethodType(context, clazz.Constants.Read(new MethodTypeConstantHandle(i))); break; - case InvokeDynamicConstantReader invokeDynamic: - if (reader.Version < 51) + case ConstantKind.InvokeDynamic: + if (clazz.Version < 51) goto default; - constantpool[i] = new ConstantPoolItemInvokeDynamic(context, invokeDynamic); + constantpool[i] = new ConstantPoolItemInvokeDynamic(context, clazz.Constants.Read(new InvokeDynamicConstantHandle(i))); break; - case StringConstantReader stringConstant: - constantpool[i] = new ConstantPoolItemString(context, stringConstant); + case ConstantKind.String: + constantpool[i] = new ConstantPoolItemString(context, clazz.Constants.Read(new StringConstantHandle(i))); break; - case Utf8ConstantReader utf8ConstantReader: - utf8_cp[i] = utf8ConstantReader.Value; + case ConstantKind.Utf8: + utf8_cp[i] = clazz.Constants.Read(new Utf8ConstantHandle(i)).Value; break; default: throw new ClassFormatError("Unknown constant type."); @@ -201,7 +202,7 @@ internal ClassFile(RuntimeContext context, ClassReader reader, string inputClass if (constantPoolPatches != null) PatchConstantPool(constantPoolPatches, utf8_cp, inputClassName); - for (int i = 1; i < reader.Constants.Count; i++) + for (int i = 1; i < clazz.Constants.SlotCount; i++) { if (constantpool[i] != null) { @@ -226,20 +227,20 @@ internal ClassFile(RuntimeContext context, ClassReader reader, string inputClass } } - access_flags = (Modifiers)reader.AccessFlags; + access_flags = (Modifiers)clazz.AccessFlags; // NOTE although the vmspec says (in 4.1) that interfaces must be marked abstract, earlier versions of // javac (JDK 1.1) didn't do this, so the VM doesn't enforce this rule for older class files. // NOTE although the vmspec implies (in 4.1) that ACC_SUPER is illegal on interfaces, it doesn't enforce this // for older class files. // (See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6320322) - if ((IsInterface && IsFinal) || (IsAbstract && IsFinal) || (reader.Version >= 49 && IsAnnotation && !IsInterface) || (reader.Version >= 49 && IsInterface && (!IsAbstract || IsSuper || IsEnum))) + if ((IsInterface && IsFinal) || (IsAbstract && IsFinal) || (clazz.Version >= 49 && IsAnnotation && !IsInterface) || (clazz.Version >= 49 && IsInterface && (!IsAbstract || IsSuper || IsEnum))) throw new ClassFormatError("{0} (Illegal class modifiers 0x{1:X})", inputClassName, access_flags); - ValidateConstantPoolItemClass(inputClassName, reader.Record.ThisClassIndex); - ValidateConstantPoolItemClass(inputClassName, reader.Record.SuperClassIndex); + ValidateConstantPoolItemClass(inputClassName, clazz.This); + ValidateConstantPoolItemClass(inputClassName, clazz.Super); - if (IsInterface && (reader.Record.SuperClassIndex == 0 || SuperClass.Name != "java.lang.Object")) + if (IsInterface && (clazz.Super.IsNil || SuperClass.Name != "java.lang.Object")) throw new ClassFormatError("{0} (Interfaces must have java.lang.Object as superclass)", Name); // most checks are already done by ConstantPoolItemClass.Resolve, but since it allows @@ -247,14 +248,14 @@ internal ClassFile(RuntimeContext context, ClassReader reader, string inputClass if (Name[0] == '[') throw new ClassFormatError("Bad name"); - interfaces = new ConstantPoolItemClass[reader.Interfaces.Count]; + interfaces = new ConstantPoolItemClass[clazz.Interfaces.Count]; for (int i = 0; i < interfaces.Length; i++) { - int index = reader.Interfaces[i].Record.ClassIndex; - if (index == 0 || index >= constantpool.Length) + var handle = clazz.Interfaces[i].Class; + if (handle.IsNil || handle.Slot >= constantpool.Length) throw new ClassFormatError("{0} (Illegal constant pool index)", Name); - var cpi = constantpool[index] as ConstantPoolItemClass; + var cpi = constantpool[handle.Slot] as ConstantPoolItemClass; if (cpi == null) throw new ClassFormatError("{0} (Interface name has bad constant type)", Name); @@ -263,25 +264,25 @@ internal ClassFile(RuntimeContext context, ClassReader reader, string inputClass CheckDuplicates(interfaces, "Repetitive interface name"); - fields = new Field[reader.Fields.Count]; - for (int i = 0; i < reader.Fields.Count; i++) + fields = new Field[clazz.Fields.Count]; + for (int i = 0; i < clazz.Fields.Count; i++) { - fields[i] = new Field(this, utf8_cp, reader.Fields[i]); + fields[i] = new Field(this, utf8_cp, clazz.Fields[i]); var name = fields[i].Name; - if (!IsValidFieldName(name, reader.Version)) + if (!IsValidFieldName(name, clazz.Version)) throw new ClassFormatError("{0} (Illegal field name \"{1}\")", Name, name); } CheckDuplicates(fields, "Repetitive field name/signature"); - methods = new Method[reader.Methods.Count]; - for (int i = 0; i < reader.Methods.Count; i++) + methods = new Method[clazz.Methods.Count]; + for (int i = 0; i < clazz.Methods.Count; i++) { - methods[i] = new Method(this, utf8_cp, options, reader.Methods[i]); + methods[i] = new Method(this, utf8_cp, options, clazz.Methods[i]); string name = methods[i].Name; string sig = methods[i].Signature; - if (!IsValidMethodName(name, reader.Version)) + if (!IsValidMethodName(name, clazz.Version)) { if (!ReferenceEquals(name, StringConstants.INIT) && !ReferenceEquals(name, StringConstants.CLINIT)) throw new ClassFormatError("{0} (Illegal method name \"{1}\")", Name, name); @@ -294,54 +295,48 @@ internal ClassFile(RuntimeContext context, ClassReader reader, string inputClass CheckDuplicates(methods, "Repetitive method name/signature"); - for (int i = 0; i < reader.Attributes.Count; i++) + for (int i = 0; i < clazz.Attributes.Count; i++) { - var attribute = reader.Attributes[i]; + var attribute = clazz.Attributes[i]; - switch (GetConstantPoolUtf8String(utf8_cp, attribute.Info.Record.NameIndex)) + switch (GetConstantPoolUtf8String(utf8_cp, attribute.Name)) { - case "Deprecated": - if (attribute is not DeprecatedAttributeReader deprecatedAttribute) - throw new ClassFormatError("Invalid Deprecated attribute type."); - + case AttributeName.Deprecated: + var deprecatedAttribute = (DeprecatedAttribute)attribute; flags |= FLAG_MASK_DEPRECATED; break; - case "SourceFile": - if (attribute is not SourceFileAttributeReader sourceFileAttribute) - throw new ClassFormatError("Invalid SourceFile attribute type."); - - sourceFile = GetConstantPoolUtf8String(utf8_cp, sourceFileAttribute.Record.SourceFileIndex); + case AttributeName.SourceFile: + var sourceFileAttribute = (IKVM.ByteCode.Decoding.SourceFileAttribute)attribute; + sourceFile = GetConstantPoolUtf8String(utf8_cp, sourceFileAttribute.SourceFile); break; - case "InnerClasses": + case AttributeName.InnerClasses: if (MajorVersion < 49) goto default; - if (attribute is not InnerClassesAttributeReader innerClassesAttribute) - throw new ClassFormatError("Invalid InnerClasses attribute type."); - - innerClasses = new InnerClass[innerClassesAttribute.Items.Count]; + var innerClassesAttribute = (InnerClassesAttribute)attribute; + innerClasses = new InnerClass[innerClassesAttribute.Table.Count]; for (int j = 0; j < innerClasses.Length; j++) { - var item = innerClassesAttribute.Items[j]; + var item = innerClassesAttribute.Table[j]; - innerClasses[j].innerClass = item.InnerClass?.Index ?? 0; - innerClasses[j].outerClass = item.OuterClass?.Index ?? 0; - innerClasses[j].name = item.InnerName?.Index ?? 0; - innerClasses[j].accessFlags = (Modifiers)item.InnerClassAccessFlags; + innerClasses[j].innerClass = item.Inner; + innerClasses[j].outerClass = item.Outer; + innerClasses[j].name = item.InnerName; + innerClasses[j].accessFlags = (Modifiers)item.InnerAccessFlags; - if (innerClasses[j].innerClass != 0 && !(GetConstantPoolItem(innerClasses[j].innerClass) is ConstantPoolItemClass)) + if (innerClasses[j].innerClass.IsNotNil && !(GetConstantPoolItem(innerClasses[j].innerClass) is ConstantPoolItemClass)) throw new ClassFormatError("{0} (inner_class_info_index has bad constant pool index)", this.Name); - if (innerClasses[j].outerClass != 0 && !(GetConstantPoolItem(innerClasses[j].outerClass) is ConstantPoolItemClass)) + if (innerClasses[j].outerClass.IsNotNil && !(GetConstantPoolItem(innerClasses[j].outerClass) is ConstantPoolItemClass)) throw new ClassFormatError("{0} (outer_class_info_index has bad constant pool index)", this.Name); - if (innerClasses[j].name != 0 && utf8_cp[innerClasses[j].name] == null) + if (innerClasses[j].name.IsNotNil && utf8_cp[innerClasses[j].name.Slot] == null) throw new ClassFormatError("{0} (inner class name has bad constant pool index)", this.Name); if (innerClasses[j].innerClass == innerClasses[j].outerClass) throw new ClassFormatError("{0} (Class is both inner and outer class)", this.Name); - if (innerClasses[j].innerClass != 0 && innerClasses[j].outerClass != 0) + if (innerClasses[j].innerClass.IsNotNil && innerClasses[j].outerClass.IsNotNil) { MarkLinkRequiredConstantPoolItem(innerClasses[j].innerClass); MarkLinkRequiredConstantPoolItem(innerClasses[j].outerClass); @@ -349,67 +344,59 @@ internal ClassFile(RuntimeContext context, ClassReader reader, string inputClass } break; - case "Signature": - if (reader.Version < 49) + case AttributeName.Signature: + if (clazz.Version < 49) goto default; - if (attribute is not SignatureAttributeReader signatureAttribute) - throw new ClassFormatError("Invalid Signature attribute type."); - - signature = GetConstantPoolUtf8String(utf8_cp, signatureAttribute.Record.SignatureIndex); + var signatureAttribute = (IKVM.ByteCode.Decoding.SignatureAttribute)attribute; + signature = GetConstantPoolUtf8String(utf8_cp, signatureAttribute.Signature); break; - case "EnclosingMethod": - if (reader.Version < 49) + case AttributeName.EnclosingMethod: + if (clazz.Version < 49) goto default; - if (attribute is not EnclosingMethodAttributeReader enclosingMethodAttribute) - throw new ClassFormatError("Invalid EnclosingMethod attribute type."); + var enclosingMethodAttribute = (IKVM.ByteCode.Decoding.EnclosingMethodAttribute)attribute; + var classHandle = enclosingMethodAttribute.Class; + var methodHandle = enclosingMethodAttribute.Method; + ValidateConstantPoolItemClass(inputClassName, classHandle); - var classIndex = enclosingMethodAttribute.Record.ClassIndex; - var methodIndex = enclosingMethodAttribute.Record.MethodIndex; - ValidateConstantPoolItemClass(inputClassName, classIndex); - - if (methodIndex == 0) + if (methodHandle.IsNil) { - enclosingMethod = new string[] - { - GetConstantPoolClass(classIndex), + enclosingMethod = + [ + GetConstantPoolClass(classHandle), null, null - }; + ]; } else { - if (GetConstantPoolItem(methodIndex) is not ConstantPoolItemNameAndType m) - throw new ClassFormatError("{0} (Bad constant pool index #{1})", inputClassName, methodIndex); + if (GetConstantPoolItem(methodHandle) is not ConstantPoolItemNameAndType m) + throw new ClassFormatError("{0} (Bad constant pool index #{1})", inputClassName, methodHandle); enclosingMethod = new string[] { - GetConstantPoolClass(classIndex), - GetConstantPoolUtf8String(utf8_cp, m.nameIndex), - GetConstantPoolUtf8String(utf8_cp, m.descriptorIndex).Replace('/', '.') + GetConstantPoolClass(classHandle), + GetConstantPoolUtf8String(utf8_cp, m.NameHandle), + GetConstantPoolUtf8String(utf8_cp, m.DescriptorHandle).Replace('/', '.') }; } break; - case "RuntimeVisibleAnnotations": - if (reader.Version < 49) + case AttributeName.RuntimeVisibleAnnotations: + if (clazz.Version < 49) goto default; - if (attribute is not RuntimeVisibleAnnotationsAttributeReader runtimeVisibleAnnotationsAttribute) - throw new ClassFormatError("Invalid RuntimeVisibleAnnotations attribute type."); - + var runtimeVisibleAnnotationsAttribute = (RuntimeVisibleAnnotationsAttribute)attribute; annotations = ReadAnnotations(runtimeVisibleAnnotationsAttribute.Annotations, this, utf8_cp); break; #if IMPORTER - case "RuntimeInvisibleAnnotations": - if (reader.Version < 49) + case AttributeName.RuntimeInvisibleAnnotations: + if (clazz.Version < 49) goto default; - if (attribute is not RuntimeInvisibleAnnotationsAttributeReader runtimeInvisibleAnnotationsAttribute) - throw new ClassFormatError("Invalid RuntimeInvisibleAnnotations attribute type."); - - foreach (object[] annot in ReadAnnotations(runtimeInvisibleAnnotationsAttribute.Annotations, this, utf8_cp)) + var runtimeInvisibleAnnotationsAttribute = (RuntimeInvisibleAnnotationsAttribute)attribute; + foreach (var annot in ReadAnnotations(runtimeInvisibleAnnotationsAttribute.Annotations, this, utf8_cp)) { if (annot[1].Equals("Likvm/lang/Internal;")) { @@ -420,33 +407,30 @@ internal ClassFile(RuntimeContext context, ClassReader reader, string inputClass break; #endif - case "BootstrapMethods": - if (reader.Version < 51) + case AttributeName.BootstrapMethods: + if (clazz.Version < 51) goto default; - if (attribute is not BootstrapMethodsAttributeReader bootstrapMethodsAttribute) - throw new ClassFormatError("Invalid BootstrapMethods attribute type."); - + var bootstrapMethodsAttribute = (BootstrapMethodsAttribute)attribute; bootstrapMethods = ReadBootstrapMethods(bootstrapMethodsAttribute.Methods, this); break; - case "RuntimeVisibleTypeAnnotations": - if (reader.Version < 52) + case AttributeName.RuntimeVisibleTypeAnnotations: + if (clazz.Version < 52) goto default; - if (attribute is not RuntimeVisibleTypeAnnotationsAttributeReader runtimeVisibleTypeAnnotationsAttribute) - throw new ClassFormatError("Invalid RuntimeVisibleTypeAnnotations attribute type."); - + var _runtimeVisibleTypeAnnotations = (IKVM.ByteCode.Decoding.RuntimeVisibleTypeAnnotationsAttribute)attribute; CreateUtf8ConstantPoolItems(utf8_cp); - runtimeVisibleTypeAnnotations = runtimeVisibleTypeAnnotationsAttribute.Annotations; + runtimeVisibleTypeAnnotations = _runtimeVisibleTypeAnnotations.TypeAnnotations; break; case "IKVM.NET.Assembly": - if (attribute is not UnknownAttributeReader unknownAttributeReader) - throw new ClassFormatError("Invalid IKVM.NET.Assembly attribute type."); + if (attribute.Data.Length != 2) + throw new ClassFormatError("IKVM.NET.Assembly attribute has incorrect length"); - if (unknownAttributeReader.Record.Data.Length != 2) + var r = new ClassFormatReader(attribute.Data); + if (r.TryReadU2(out var index) == false) throw new ClassFormatError("IKVM.NET.Assembly attribute has incorrect length"); - ikvmAssembly = GetConstantPoolUtf8String(utf8_cp, BinaryPrimitives.ReadInt16BigEndian(unknownAttributeReader.Record.Data)); + ikvmAssembly = GetConstantPoolUtf8String(utf8_cp, new(index)); break; default: break; @@ -509,9 +493,8 @@ void PatchConstantPool(object[] constantPoolPatches, string[] utf8_cp, string in if (utf8_cp[i] != null) { if (!(constantPoolPatches[i] is string)) - { throw new ClassFormatError("Illegal utf8 patch at {0} in class file {1}", i, inputClassName); - } + utf8_cp[i] = (string)constantPoolPatches[i]; } else if (constantpool[i] != null) @@ -526,7 +509,7 @@ void PatchConstantPool(object[] constantPoolPatches, string[] utf8_cp, string in string name; if ((clazz = constantPoolPatches[i] as java.lang.Class) != null) { - RuntimeJavaType tw = RuntimeJavaType.FromClass(clazz); + var tw = RuntimeJavaType.FromClass(clazz); constantpool[i] = new ConstantPoolItemClass(context, tw.Name, tw); } else if ((name = constantPoolPatches[i] as string) != null) @@ -559,32 +542,35 @@ void PatchConstantPool(object[] constantPoolPatches, string[] utf8_cp, string in #endif } + void MarkLinkRequiredConstantPoolItem(ConstantHandle handle) + { + if (handle.Slot > 0 && handle.Slot < constantpool.Length && constantpool[handle.Slot] != null) + constantpool[handle.Slot].MarkLinkRequired(); + } + void MarkLinkRequiredConstantPoolItem(int index) { - if (index > 0 && index < constantpool.Length && constantpool[index] != null) - { - constantpool[index].MarkLinkRequired(); - } + MarkLinkRequiredConstantPoolItem(new ConstantHandle(ConstantKind.Unknown, checked((ushort)index))); } - static BootstrapMethod[] ReadBootstrapMethods(IReadOnlyList methods, ClassFile classFile) + static BootstrapMethod[] ReadBootstrapMethods(BootstrapMethodTable methods, ClassFile classFile) { var bsm = new BootstrapMethod[methods.Count]; for (int i = 0; i < methods.Count; i++) { var method = methods[i]; - var bsm_index = method.Record.MethodRefIndex; - if (bsm_index >= classFile.constantpool.Length || classFile.constantpool[bsm_index] is not ConstantPoolItemMethodHandle) + var bsm_index = method.Method; + if (bsm_index.Slot >= classFile.constantpool.Length || classFile.constantpool[bsm_index.Slot] is not ConstantPoolItemMethodHandle) throw new ClassFormatError("bootstrap_method_index {0} has bad constant type in class file {1}", bsm_index, classFile.Name); classFile.MarkLinkRequiredConstantPoolItem(bsm_index); var argument_count = method.Arguments.Count; - var args = new ushort[argument_count]; + var args = new ConstantHandle[argument_count]; for (int j = 0; j < args.Length; j++) { - var argument_index = method.Record.Arguments[j]; + var argument_index = method.Arguments[j]; if (classFile.IsValidConstant(argument_index) == false) throw new ClassFormatError("argument_index {0} has bad constant type in class file {1}", argument_index, classFile.Name); @@ -598,13 +584,13 @@ static BootstrapMethod[] ReadBootstrapMethods(IReadOnlyList= constantpool.Length || constantpool[index] is not ConstantPoolItemClass) - throw new ClassFormatError("{0} (Bad constant pool index #{1})", classFile, index); + if (handle.Slot >= constantpool.Length || constantpool[handle.Slot] is not ConstantPoolItemClass) + throw new ClassFormatError("{0} (Bad constant pool index #{1})", classFile, handle); } - private static bool IsValidMethodName(string name, ClassFormatVersion version) + static bool IsValidMethodName(string name, ClassFormatVersion version) { if (name.Length == 0) - { return false; - } + for (int i = 0; i < name.Length; i++) - { if (".;[/<>".IndexOf(name[i]) != -1) - { return false; - } - } + return version >= 49 || IsValidPre49Identifier(name); } - private static bool IsValidFieldName(string name, ClassFormatVersion version) + static bool IsValidFieldName(string name, ClassFormatVersion version) { if (name.Length == 0) - { return false; - } + for (int i = 0; i < name.Length; i++) - { if (".;[/".IndexOf(name[i]) != -1) - { return false; - } - } + return version >= 49 || IsValidPre49Identifier(name); } - private static bool IsValidPre49Identifier(string name) + static bool IsValidPre49Identifier(string name) { - if (!Char.IsLetter(name[0]) && "$_".IndexOf(name[0]) == -1) - { + if (!char.IsLetter(name[0]) && "$_".IndexOf(name[0]) == -1) return false; - } + for (int i = 1; i < name.Length; i++) - { - if (!Char.IsLetterOrDigit(name[i]) && "$_".IndexOf(name[i]) == -1) - { + if (!char.IsLetterOrDigit(name[i]) && "$_".IndexOf(name[i]) == -1) return false; - } - } + return true; } @@ -766,12 +745,11 @@ internal static bool IsValidFieldSig(string sig) return IsValidFieldSigImpl(sig, 0, sig.Length); } - private static bool IsValidFieldSigImpl(string sig, int start, int end) + static bool IsValidFieldSigImpl(string sig, int start, int end) { if (start >= end) - { return false; - } + switch (sig[start]) { case 'L': @@ -781,10 +759,9 @@ private static bool IsValidFieldSigImpl(string sig, int start, int end) { start++; if (start == end) - { return false; - } } + return IsValidFieldSigImpl(sig, start, end); case 'B': case 'Z': @@ -803,18 +780,15 @@ private static bool IsValidFieldSigImpl(string sig, int start, int end) internal static bool IsValidMethodSig(string sig) { if (sig.Length < 3 || sig[0] != '(') - { return false; - } + int end = sig.IndexOf(')'); if (end == -1) - { return false; - } + if (!sig.EndsWith(")V") && !IsValidFieldSigImpl(sig, end + 1, sig.Length)) - { return false; - } + for (int i = 1; i < end; i++) { switch (sig[i]) @@ -833,35 +807,29 @@ internal static bool IsValidMethodSig(string sig) break; case '[': while (sig[i] == '[') - { i++; - } if ("BZCSIJFDL".IndexOf(sig[i]) == -1) - { return false; - } if (sig[i] == 'L') - { i = sig.IndexOf(';', i); - } break; default: return false; } + if (i == -1 || i >= end) - { return false; - } } + return true; } - internal int MajorVersion => reader.Version.Major; + internal int MajorVersion => clazz.Version.Major; internal void Link(RuntimeJavaType thisType, LoadMode mode) { // this is not just an optimization, it's required for anonymous classes to be able to refer to themselves - ((ConstantPoolItemClass)constantpool[reader.Record.ThisClassIndex]).LinkSelf(thisType); + ((ConstantPoolItemClass)constantpool[clazz.This.Slot]).LinkSelf(thisType); for (int i = 1; i < constantpool.Length; i++) if (constantpool[i] != null) @@ -870,14 +838,13 @@ internal void Link(RuntimeJavaType thisType, LoadMode mode) internal Modifiers Modifiers => access_flags; - internal bool IsAbstract - { - get - { - // interfaces are implicitly abstract - return (access_flags & (Modifiers.Abstract | Modifiers.Interface)) != 0; - } - } + /// + /// + /// + /// + /// interfaces are implicitly abstract + /// + internal bool IsAbstract => (access_flags & (Modifiers.Abstract | Modifiers.Interface)) != 0; internal bool IsFinal => (access_flags & Modifiers.Final) != 0; @@ -893,125 +860,192 @@ internal bool IsAbstract internal bool IsReferenced(Field fld) => constantpool.OfType().Any(i => i.Class == Name && i.Name == fld.Name && i.Signature == fld.Signature); - internal ConstantPoolItemFieldref GetFieldref(int index) => (ConstantPoolItemFieldref)constantpool[index]; + internal ConstantPoolItemFieldref GetFieldref(FieldrefConstantHandle handle) + { + return (ConstantPoolItemFieldref)constantpool[handle.Slot]; + } + internal ConstantPoolItemFieldref GetFieldref(int slot) + { + return GetFieldref(new FieldrefConstantHandle(checked((ushort)slot))); + } - // this won't throw an exception if index is invalid - // (used by IsSideEffectFreeStaticInitializer) - internal ConstantPoolItemFieldref SafeGetFieldref(int index) + /// + /// Version of GetFieldref that does not throw if the handle is invalid. Used by IsSideEffectFreeStaticInitializer. + /// + /// + /// + internal ConstantPoolItemFieldref SafeGetFieldref(ConstantHandle handle) { - if (index > 0 && index < constantpool.Length) - return constantpool[index] as ConstantPoolItemFieldref; + if (handle.IsNotNil && handle.Slot < constantpool.Length) + return constantpool[handle.Slot] as ConstantPoolItemFieldref; return null; } + /// + /// Version of GetFieldref that does not throw if the handle is invalid. Used by IsSideEffectFreeStaticInitializer. + /// + /// + /// + internal ConstantPoolItemFieldref SafeGetFieldref(int index) + { + if (index > ushort.MaxValue || index < ushort.MinValue) + return null; + + return SafeGetFieldref(new ConstantHandle(ConstantKind.Unknown, (ushort)index)); + } + + internal ConstantPoolItemMI GetMethodref(MethodrefConstantHandle handle) + { + return (ConstantPoolItemMI)constantpool[handle.Slot]; + } + // NOTE this returns an MI, because it used for both normal methods and interface methods - internal ConstantPoolItemMI GetMethodref(int index) => (ConstantPoolItemMI)constantpool[index]; + internal ConstantPoolItemMI GetMethodref(int handle) + { + return GetMethodref(new MethodrefConstantHandle(checked((ushort)handle))); + } - // this won't throw an exception if index is invalid - // (used by IsAccessBridge) - internal ConstantPoolItemMI SafeGetMethodref(int index) + /// + /// Version of GetMethodref that does not throw if the handle is invalid. Used by IsAccessBridge. + /// + /// + /// + internal ConstantPoolItemMI SafeGetMethodref(ConstantHandle handle) { - if (index > 0 && index < constantpool.Length) - return constantpool[index] as ConstantPoolItemMI; + if (handle.IsNotNil && handle.Slot < constantpool.Length) + return constantpool[handle.Slot] as ConstantPoolItemMI; return null; } - internal ConstantPoolItemInvokeDynamic GetInvokeDynamic(int index) + /// + /// Version of GetMethodref that does not throw if the handle is invalid. Used by IsAccessBridge. + /// + /// + /// + internal ConstantPoolItemMI SafeGetMethodref(int slot) { - return (ConstantPoolItemInvokeDynamic)constantpool[index]; + if (slot > ushort.MaxValue || slot < ushort.MinValue) + return null; + + return SafeGetMethodref(new ConstantHandle(ConstantKind.Unknown, (ushort)slot)); } - private ConstantPoolItem GetConstantPoolItem(int index) + internal ConstantPoolItemInvokeDynamic GetInvokeDynamic(InvokeDynamicConstantHandle handle) { - return constantpool[index]; + return (ConstantPoolItemInvokeDynamic)constantpool[handle.Slot]; } - internal string GetConstantPoolClass(int index) + private ConstantPoolItem GetConstantPoolItem(ConstantHandle handle) { - return ((ConstantPoolItemClass)constantpool[index]).Name; + return constantpool[handle.Slot]; } - private bool SafeIsConstantPoolClass(int index) + internal string GetConstantPoolClass(ClassConstantHandle handle) { - if (index > 0 && index < constantpool.Length) - return constantpool[index] as ConstantPoolItemClass != null; + return ((ConstantPoolItemClass)constantpool[handle.Slot]).Name; + } + + private bool SafeIsConstantPoolClass(ClassConstantHandle handle) + { + if (handle.Slot > 0 && handle.Slot < constantpool.Length) + return constantpool[handle.Slot] as ConstantPoolItemClass != null; return false; } - internal RuntimeJavaType GetConstantPoolClassType(int index) + internal RuntimeJavaType GetConstantPoolClassType(ClassConstantHandle handle) { - return ((ConstantPoolItemClass)constantpool[index]).GetClassType(); + return ((ConstantPoolItemClass)constantpool[handle.Slot]).GetClassType(); } - private string GetConstantPoolUtf8String(string[] utf8_cp, int index) + internal RuntimeJavaType GetConstantPoolClassType(int slot) { - var s = utf8_cp[index]; + return GetConstantPoolClassType(new ClassConstantHandle(checked((ushort)slot))); + } + string GetConstantPoolUtf8String(string[] utf8_cp, Utf8ConstantHandle handle) + { + var s = utf8_cp[handle.Slot]; if (s == null) { - if (reader.This.Index == 0) - { - throw new ClassFormatError("Bad constant pool index #{0}", index); - } + if (clazz.This.IsNil) + throw new ClassFormatError("Bad constant pool index #{0}", handle); else - { - throw new ClassFormatError("{0} (Bad constant pool index #{1})", this.Name, index); - } + throw new ClassFormatError("{0} (Bad constant pool index #{1})", Name, handle); } return s; } - internal ConstantType GetConstantPoolConstantType(int index) + internal ConstantType GetConstantPoolConstantType(ConstantHandle handle) { - return constantpool[index].GetConstantType(); + return constantpool[handle.Slot].GetConstantType(); } - internal double GetConstantPoolConstantDouble(int index) + internal ConstantType GetConstantPoolConstantType(int slot) { - return ((ConstantPoolItemDouble)constantpool[index]).Value; + return GetConstantPoolConstantType(new ConstantHandle(ConstantKind.Unknown, checked((ushort)slot))); } - internal float GetConstantPoolConstantFloat(int index) + internal double GetConstantPoolConstantDouble(DoubleConstantHandle handle) { - return ((ConstantPoolItemFloat)constantpool[index]).Value; + return ((ConstantPoolItemDouble)constantpool[handle.Slot]).Value; } - internal int GetConstantPoolConstantInteger(int index) + internal float GetConstantPoolConstantFloat(FloatConstantHandle handle) { - return ((ConstantPoolItemInteger)constantpool[index]).Value; + return ((ConstantPoolItemFloat)constantpool[handle.Slot]).Value; } - internal long GetConstantPoolConstantLong(int index) + internal int GetConstantPoolConstantInteger(IntegerConstantHandle handle) { - return ((ConstantPoolItemLong)constantpool[index]).Value; + return ((ConstantPoolItemInteger)constantpool[handle.Slot]).Value; } - internal string GetConstantPoolConstantString(int index) + internal long GetConstantPoolConstantLong(LongConstantHandle handle) { - return ((ConstantPoolItemString)constantpool[index]).Value; + return ((ConstantPoolItemLong)constantpool[handle.Slot]).Value; } - internal ConstantPoolItemMethodHandle GetConstantPoolConstantMethodHandle(int index) + internal string GetConstantPoolConstantString(StringConstantHandle handle) { - return (ConstantPoolItemMethodHandle)constantpool[index]; + return ((ConstantPoolItemString)constantpool[handle.Slot]).Value; } - internal ConstantPoolItemMethodType GetConstantPoolConstantMethodType(int index) + internal string GetConstantPoolConstantString(int slot) { - return (ConstantPoolItemMethodType)constantpool[index]; + return GetConstantPoolConstantString(new StringConstantHandle(checked((ushort)slot))); } - internal object GetConstantPoolConstantLiveObject(int index) + internal ConstantPoolItemMethodHandle GetConstantPoolConstantMethodHandle(MethodHandleConstantHandle handle) { - return ((ConstantPoolItemLiveObject)constantpool[index]).Value; + return (ConstantPoolItemMethodHandle)constantpool[handle.Slot]; } - internal string Name => GetConstantPoolClass(reader.Record.ThisClassIndex); + internal ConstantPoolItemMethodHandle GetConstantPoolConstantMethodHandle(int slot) + { + return GetConstantPoolConstantMethodHandle(new MethodHandleConstantHandle(checked((ushort)slot))); + } - internal ConstantPoolItemClass SuperClass => (ConstantPoolItemClass)constantpool[reader.Record.SuperClassIndex]; + internal ConstantPoolItemMethodType GetConstantPoolConstantMethodType(MethodTypeConstantHandle handle) + { + return (ConstantPoolItemMethodType)constantpool[handle.Slot]; + } + + internal ConstantPoolItemMethodType GetConstantPoolConstantMethodType(int slot) + { + return GetConstantPoolConstantMethodType(new MethodTypeConstantHandle(checked((ushort)slot))); + } + + internal object GetConstantPoolConstantLiveObject(int slot) + { + return ((ConstantPoolItemLiveObject)constantpool[slot]).Value; + } + + internal string Name => GetConstantPoolClass(clazz.This); + + internal ConstantPoolItemClass SuperClass => (ConstantPoolItemClass)constantpool[clazz.Super.Slot]; internal Field[] Fields => fields; @@ -1043,7 +1077,7 @@ internal object[] Annotations internal string[] EnclosingMethod => enclosingMethod; - internal IReadOnlyList RuntimeVisibleTypeAnnotations => runtimeVisibleTypeAnnotations; + internal ref readonly TypeAnnotationTable RuntimeVisibleTypeAnnotations => ref runtimeVisibleTypeAnnotations; internal object[] GetConstantPool() { @@ -1098,7 +1132,11 @@ internal Field GetField(string name, string sig) return null; } - private void RemoveAssertionInit(Method m) + /// + /// Removes a call to java.lang.Class.desiredAssertionStatus() and replaces it with a hard coded constant (true). + /// + /// + void RemoveAssertionInit(Method method) { /* We match the following code sequence: * 0 ldc @@ -1111,33 +1149,38 @@ private void RemoveAssertionInit(Method m) */ ConstantPoolItemFieldref fieldref; Field field; - if (m.Instructions[0].NormalizedOpCode == NormalizedByteCode.__ldc && SafeIsConstantPoolClass(m.Instructions[0].Arg1) - && m.Instructions[1].NormalizedOpCode == NormalizedByteCode.__invokevirtual && IsDesiredAssertionStatusMethodref(m.Instructions[1].Arg1) - && m.Instructions[2].NormalizedOpCode == NormalizedByteCode.__ifne && m.Instructions[2].TargetIndex == 5 - && m.Instructions[3].NormalizedOpCode == NormalizedByteCode.__iconst && m.Instructions[3].Arg1 == 1 - && m.Instructions[4].NormalizedOpCode == NormalizedByteCode.__goto && m.Instructions[4].TargetIndex == 6 - && m.Instructions[5].NormalizedOpCode == NormalizedByteCode.__iconst && m.Instructions[5].Arg1 == 0 - && m.Instructions[6].NormalizedOpCode == NormalizedByteCode.__putstatic && (fieldref = SafeGetFieldref(m.Instructions[6].Arg1)) != null - && fieldref.Class == Name && fieldref.Signature == "Z" - && (field = GetField(fieldref.Name, fieldref.Signature)) != null - && field.IsStatic && field.IsFinal - && !HasBranchIntoRegion(m.Instructions, 7, m.Instructions.Length, 0, 7) - && !HasStaticFieldWrite(m.Instructions, 7, m.Instructions.Length, field) - && !HasExceptionHandlerInRegion(m.ExceptionTable, 0, 7)) + if (method.Instructions is [ + { NormalizedOpCode: NormalizedByteCode.__ldc }, + { NormalizedOpCode: NormalizedByteCode.__invokevirtual }, + { NormalizedOpCode: NormalizedByteCode.__ifne }, + { NormalizedOpCode: NormalizedByteCode.__iconst }, + { NormalizedOpCode: NormalizedByteCode.__goto }, + { NormalizedOpCode: NormalizedByteCode.__iconst }, + { NormalizedOpCode: NormalizedByteCode.__putstatic }, + ..] && + method.Instructions[0].NormalizedOpCode == NormalizedByteCode.__ldc && SafeIsConstantPoolClass(new ClassConstantHandle(checked((ushort)method.Instructions[0].Arg1))) && + method.Instructions[1].NormalizedOpCode == NormalizedByteCode.__invokevirtual && IsDesiredAssertionStatusMethodref(method.Instructions[1].Arg1) && + method.Instructions[2].NormalizedOpCode == NormalizedByteCode.__ifne && method.Instructions[2].TargetIndex == 5 && + method.Instructions[3].NormalizedOpCode == NormalizedByteCode.__iconst && method.Instructions[3].Arg1 == 1 && + method.Instructions[4].NormalizedOpCode == NormalizedByteCode.__goto && method.Instructions[4].TargetIndex == 6 && + method.Instructions[5].NormalizedOpCode == NormalizedByteCode.__iconst && method.Instructions[5].Arg1 == 0 && + method.Instructions[6].NormalizedOpCode == NormalizedByteCode.__putstatic && (fieldref = SafeGetFieldref(method.Instructions[6].Arg1)) != null && + fieldref.Class == Name && fieldref.Signature == "Z" && + (field = GetField(fieldref.Name, fieldref.Signature)) != null && + field.IsStatic && field.IsFinal && + !HasBranchIntoRegion(method.Instructions, 7, method.Instructions.Length, 0, 7) && + !HasStaticFieldWrite(method.Instructions, 7, method.Instructions.Length, field) && + !HasExceptionHandlerInRegion(method.ExceptionTable, 0, 7)) { field.PatchConstantValue(true); - m.Instructions[0].PatchOpCode(NormalizedByteCode.__goto, 7); + method.Instructions[0].PatchOpCode(NormalizedByteCode.__goto, 7); flags |= FLAG_HAS_ASSERTIONS; } } - private bool IsDesiredAssertionStatusMethodref(int cpi) + bool IsDesiredAssertionStatusMethodref(int cpi) { - ConstantPoolItemMethodref method = SafeGetMethodref(cpi) as ConstantPoolItemMethodref; - return method != null - && method.Class == "java.lang.Class" - && method.Name == "desiredAssertionStatus" - && method.Signature == "()Z"; + return SafeGetMethodref(cpi) is ConstantPoolItemMethodref { Class: "java.lang.Class", Name: "desiredAssertionStatus", Signature: "()Z" }; } private static bool HasBranchIntoRegion(Method.Instruction[] instructions, int checkStart, int checkEnd, int regionStart, int regionEnd) @@ -1215,6 +1258,23 @@ private static bool HasExceptionHandlerInRegion(Method.ExceptionTableEntry[] ent } return false; } + + /// + /// Dispses of the instance. + /// + public void Dispose() + { + clazz.Dispose(); + } + + /// + /// Finalizes the instance. + /// + ~ClassFile() + { + Dispose(); + } + } } diff --git a/src/IKVM.Runtime/EmitIntrinsicContext.cs b/src/IKVM.Runtime/EmitIntrinsicContext.cs index 2cc44cbea3..89b53d2b1c 100644 --- a/src/IKVM.Runtime/EmitIntrinsicContext.cs +++ b/src/IKVM.Runtime/EmitIntrinsicContext.cs @@ -22,6 +22,8 @@ Jeroen Frijters */ +using IKVM.ByteCode; + using Instruction = IKVM.Runtime.ClassFile.Method.Instruction; using InstructionFlags = IKVM.Runtime.ClassFile.Method.InstructionFlags; @@ -98,17 +100,17 @@ internal ClassFile.ConstantPoolItemFieldref GetFieldref(int offset) internal RuntimeJavaType GetClassLiteral(int offset) { - return ClassFile.GetConstantPoolClassType(Code[OpcodeIndex + offset].Arg1); + return ClassFile.GetConstantPoolClassType(new ClassConstantHandle(checked((ushort)Code[OpcodeIndex + offset].Arg1))); } internal string GetStringLiteral(int offset) { - return ClassFile.GetConstantPoolConstantString(Code[OpcodeIndex + offset].Arg1); + return ClassFile.GetConstantPoolConstantString(new StringConstantHandle(checked((ushort)Code[OpcodeIndex + offset].Arg1))); } internal ClassFile.ConstantType GetConstantType(int offset) { - return ClassFile.GetConstantPoolConstantType(Code[OpcodeIndex + offset].Arg1); + return ClassFile.GetConstantPoolConstantType(new ConstantHandle(ConstantKind.Unknown, checked((ushort)Code[OpcodeIndex + offset].Arg1))); } internal void PatchOpCode(int offset, NormalizedByteCode opc) diff --git a/src/IKVM.Runtime/IKVM.Runtime.csproj b/src/IKVM.Runtime/IKVM.Runtime.csproj index 9fc08eff47..a7980b19a4 100644 --- a/src/IKVM.Runtime/IKVM.Runtime.csproj +++ b/src/IKVM.Runtime/IKVM.Runtime.csproj @@ -13,7 +13,6 @@ - diff --git a/src/IKVM.Runtime/JVM.Properties.cs b/src/IKVM.Runtime/JVM.Properties.cs index 5bb1e268eb..0efbd1fa2d 100644 --- a/src/IKVM.Runtime/JVM.Properties.cs +++ b/src/IKVM.Runtime/JVM.Properties.cs @@ -97,18 +97,19 @@ static IEnumerable GetIkvmPropertiesSearchPaths() /// static Dictionary GetIkvmProperties() { + var props = new Dictionary(); + foreach (var basePath in GetIkvmPropertiesSearchPaths()) { var ikvmPropertiesPath = Path.Combine(basePath, "ikvm.properties"); if (File.Exists(ikvmPropertiesPath)) { - var props = new Dictionary(); LoadProperties(basePath, File.ReadAllLines(ikvmPropertiesPath), props); - return props; + break; } } - return null; + return props; } /// @@ -268,9 +269,6 @@ static void InitSystemProperties(Dictionary p) if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) p["jdk.lang.Process.launchMechanism"] = "FORK"; - // cacerts is mounted by the VFS into ikvmHome - p.Add("javax.net.ssl.trustStore", Path.Combine(HomePath, "lib", "security", "cacerts")); - #if NETFRAMEWORK // read properties from app.config try diff --git a/src/IKVM.Runtime/Java/Externs/ikvm/internal/io/FileStreamExtensions.cs b/src/IKVM.Runtime/Java/Externs/ikvm/internal/io/FileStreamExtensions.cs deleted file mode 100644 index 011d7c628c..0000000000 --- a/src/IKVM.Runtime/Java/Externs/ikvm/internal/io/FileStreamExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.IO; -using System.Security.AccessControl; - -namespace IKVM.Java.Externs.ikvm.@internal.io -{ - - static class FileStreamExtensions - { - - public static FileStream createInternal(string path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options) - { -#if NETFRAMEWORK - return new FileStream(path, mode, rights, share, bufferSize, options); -#else - var access = 0; - if ((rights & FileSystemRights.Read) != 0) - access |= (int)FileAccess.Read; - if ((rights & (FileSystemRights.Write | FileSystemRights.AppendData)) != 0) - access |= (int)FileAccess.Write; - if (access == 0) - access = (int)FileAccess.ReadWrite; - - return new FileStream(path, mode, (FileAccess)access, share, bufferSize, options); -#endif - } - - } - -} diff --git a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Launcher.cs b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Launcher.cs index c37090004a..1b1271ea54 100644 --- a/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Launcher.cs +++ b/src/IKVM.Runtime/Java/Externs/ikvm/runtime/Launcher.cs @@ -40,7 +40,13 @@ public static int run(Type main, string[] args, string jvmArgPrefix, global::jav foreach (global::java.util.Map.Entry entry in (IEnumerable)properties.entrySet()) p.Add((string)entry.getKey(), (string)entry.getValue()); - return IKVM.Runtime.Launcher.Run(main != null ? ((global::java.lang.Class)main).getName() : null, false, args, jvmArgPrefix, p); + return IKVM.Runtime.Launcher.Run( + main?.Assembly, + ((global::java.lang.Class)main)?.getName(), + jar: false, + args, + jvmArgPrefix, + p); #endif } diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.cs b/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.cs index 927c30707e..22c39fa46d 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/ClassLoader.cs @@ -24,9 +24,10 @@ Jeroen Frijters using System; using System.Buffers; using System.Linq; +using System.Runtime.InteropServices; using IKVM.ByteCode; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Encoding; using IKVM.Runtime; using sun.nio.ch; @@ -60,7 +61,9 @@ public static void registerNatives() #if FIRST_PASS throw new NotImplementedException(); #else - return DefineClass(self, name, ReadClass(new ReadOnlyMemory(b, off, len)), pd, null); + var buf = new byte[len]; + Array.Copy(b, off, buf, 0, len); + return DefineClass(self, name, ReadClass(buf), pd, null); #endif } @@ -81,7 +84,9 @@ public static void registerNatives() #if FIRST_PASS throw new NotImplementedException(); #else - return DefineClass(self, name, ReadClass(new ReadOnlyMemory(b, off, len)), pd, source); + var buf = new byte[len]; + Array.Copy(b, off, buf, 0, len); + return DefineClass(self, name, ReadClass(buf), pd, source); #endif } @@ -101,28 +106,9 @@ public static void registerNatives() #if FIRST_PASS throw new NotImplementedException(); #else - if (bb.hasArray()) - { - return DefineClass(self, name, ReadClass(new ReadOnlyMemory(bb.array(), bb.arrayOffset() + bb.position(), bb.remaining())), pd, source); - } - else if (bb.isDirect()) - { - return DefineClass(self, name, ReadClass((byte*)((DirectBuffer)bb).address() + bb.position(), bb.remaining()), pd, source); - } - else - { - var buf = ArrayPool.Shared.Rent(bb.remaining()); - - try - { - bb.get(buf); - return DefineClass(self, name, ReadClass(new ReadOnlyMemory(buf, 0, bb.remaining())), pd, source); - } - finally - { - ArrayPool.Shared.Return(buf); - } - } + var buf = new byte[bb.remaining()]; + bb.get(buf); + return DefineClass(self, name, ReadClass(buf), pd, source); #endif } @@ -133,32 +119,11 @@ public static void registerNatives() /// /// /// - static ClassReader ReadClass(ReadOnlyMemory buffer) + static IKVM.ByteCode.Decoding.ClassFile ReadClass(byte[] buffer) { try { - return ClassReader.Read(buffer); - } - catch (InvalidClassMagicException) - { - throw new global::java.lang.ClassFormatError("Incompatible magic value"); - } - catch (ByteCodeException e) - { - throw new global::java.lang.ClassFormatError(e.Message); - } - } - - /// - /// Attempts to read the class, handling exceptions. - /// - /// - /// - static unsafe ClassReader ReadClass(byte* buffer, int length) - { - try - { - return ClassReader.Read(buffer, length); + return IKVM.ByteCode.Decoding.ClassFile.Read(buffer); } catch (InvalidClassMagicException) { @@ -175,16 +140,16 @@ static unsafe ClassReader ReadClass(byte* buffer, int length) /// /// /// - /// + /// /// /// /// - static global::java.lang.Class DefineClass(global::java.lang.ClassLoader self, string name, ClassReader reader, global::java.security.ProtectionDomain pd, string source) + static global::java.lang.Class DefineClass(global::java.lang.ClassLoader self, string name, IKVM.ByteCode.Decoding.ClassFile clazz, global::java.security.ProtectionDomain pd, string source) { try { var runtimeClassLoader = JVM.Context.ClassLoaderFactory.GetClassLoaderWrapper(self); - var classFile = new ClassFile(JVM.Context, reader, name, runtimeClassLoader.ClassFileParseOptions, null); + var classFile = new IKVM.Runtime.ClassFile(JVM.Context, clazz, name, runtimeClassLoader.ClassFileParseOptions, null); if (name != null && classFile.Name != name) throw new global::java.lang.NoClassDefFoundError(name + " (wrong name: " + classFile.Name + ")"); diff --git a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Field.cs b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Field.cs index bb4ea9f07b..c0a22aa2c7 100644 --- a/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Field.cs +++ b/src/IKVM.Runtime/Java/Externs/java/lang/reflect/Field.cs @@ -31,13 +31,13 @@ static class Field public static object getDeclaredAnnotationsImpl(global::java.lang.reflect.Field thisField) { - RuntimeJavaField fw = RuntimeJavaField.FromField(thisField); + var fw = RuntimeJavaField.FromField(thisField); return IKVM.Java.Externs.java.lang.Class.AnnotationsToMap(fw.DeclaringType.GetClassLoader(), fw.DeclaringType.GetFieldAnnotations(fw)); } public static byte[] getTypeAnnotationBytes0(global::java.lang.reflect.Field thisField) { - RuntimeJavaField fw = RuntimeJavaField.FromField(thisField); + var fw = RuntimeJavaField.FromField(thisField); return fw.DeclaringType.GetFieldRawTypeAnnotations(fw); } diff --git a/src/IKVM.Runtime/Java/Externs/sun/misc/Unsafe.cs b/src/IKVM.Runtime/Java/Externs/sun/misc/Unsafe.cs index d647a5ea3e..a2e3bfba89 100644 --- a/src/IKVM.Runtime/Java/Externs/sun/misc/Unsafe.cs +++ b/src/IKVM.Runtime/Java/Externs/sun/misc/Unsafe.cs @@ -9,7 +9,7 @@ using System.Threading; using IKVM.ByteCode; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Encoding; using IKVM.Runtime; namespace IKVM.Java.Externs.sun.misc @@ -1674,7 +1674,7 @@ public static int pageSize(object self) { var tw = RuntimeJavaType.FromClass(hostClass); var cl = tw.GetClassLoader(); - var cf = new ClassFile(JVM.Context, ReadClass(data), "", cl.ClassFileParseOptions, cpPatches); + var cf = new IKVM.Runtime.ClassFile(JVM.Context, ReadClass(data), "", cl.ClassFileParseOptions, cpPatches); // if this happens, the OpenJDK is probably trying to load an OpenJDK class file as a resource, // make sure the build process includes the original class file as a resource in that case @@ -1697,11 +1697,11 @@ public static int pageSize(object self) /// /// /// - static ClassReader ReadClass(byte[] buffer) + static IKVM.ByteCode.Decoding.ClassFile ReadClass(byte[] buffer) { try { - return ClassReader.Read(buffer); + return IKVM.ByteCode.Decoding.ClassFile.Read(buffer); } catch (InvalidClassMagicException) { @@ -2699,7 +2699,7 @@ public static void park(object self, bool isAbsolute, long time) { ((global::java.lang.Object)currentThread.parkLock).wait(time / 1000000, (int)(time % 1000000)); } - catch (global::java.lang.InterruptedException _) + catch (global::java.lang.InterruptedException) { currentThread.interrupt(); } diff --git a/src/IKVM.Runtime/JsrInliner.cs b/src/IKVM.Runtime/JsrInliner.cs index d9b12b4365..9ae831b5d7 100644 --- a/src/IKVM.Runtime/JsrInliner.cs +++ b/src/IKVM.Runtime/JsrInliner.cs @@ -24,2041 +24,2062 @@ Jeroen Frijters using System; using System.Collections.Generic; +using IKVM.ByteCode; + using InstructionFlags = IKVM.Runtime.ClassFile.Method.InstructionFlags; namespace IKVM.Runtime { sealed class JsrInliner - { - - private ClassFile.Method.Instruction[] codeCopy; - private int codeLength; - private InstructionFlags[] flags; - private readonly ClassFile.Method m; - private readonly JsrMethodAnalyzer ma; - - internal static void InlineJsrs(RuntimeClassLoader classLoader, RuntimeJavaMethod mw, ClassFile classFile, ClassFile.Method m) - { - JsrInliner inliner; - do - { - ClassFile.Method.Instruction[] codeCopy = (ClassFile.Method.Instruction[])m.Instructions.Clone(); - InstructionFlags[] flags = new InstructionFlags[codeCopy.Length]; - JsrMethodAnalyzer ma = new JsrMethodAnalyzer(mw, classFile, m, classLoader, flags); - inliner = new JsrInliner(codeCopy, flags, m, ma); - } while (inliner.InlineJsrs()); - } - - private JsrInliner(ClassFile.Method.Instruction[] codeCopy, InstructionFlags[] flags, ClassFile.Method m, JsrMethodAnalyzer ma) - { - this.codeCopy = codeCopy; - codeLength = codeCopy.Length; - this.flags = flags; - this.m = m; - this.ma = ma; - } - - private void Add(ClassFile.Method.Instruction instr) - { - if (codeLength == codeCopy.Length) - { - Array.Resize(ref codeCopy, codeLength * 2); - Array.Resize(ref flags, codeLength * 2); - } - codeCopy[codeLength++] = instr; - } - - private bool InlineJsrs() - { - bool hasJsrs = false; - List subs = new List(); - int len = codeLength; - for (int i = 0; i < len; i++) - { - // note that we're also (needlessly) processing the subroutines here, but that shouldn't be a problem (just a minor waste of cpu) - // because the code is unreachable anyway - if ((flags[i] & InstructionFlags.Reachable) != 0 && m.Instructions[i].NormalizedOpCode == NormalizedByteCode.__jsr) - { - int subroutineId = m.Instructions[i].TargetIndex; - codeCopy[i].PatchOpCode(NormalizedByteCode.__goto, codeLength); - SubroutineCall sub = new SubroutineCall(this, subroutineId, i + 1); - hasJsrs |= sub.InlineSubroutine(); - subs.Add(sub); - } - } - List exceptions = new List(m.ExceptionTable); - foreach (SubroutineCall sub in subs) - { - sub.DoExceptions(m.ExceptionTable, exceptions); - } - m.ExceptionTable = exceptions.ToArray(); - ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); - instr.SetTermNop(0xFFFF); - Add(instr); - Array.Resize(ref codeCopy, codeLength); - - m.Instructions = codeCopy; - return hasJsrs; - } - - private sealed class SubroutineCall - { - private readonly JsrInliner inliner; - private readonly int subroutineIndex; - private readonly int returnIndex; - private readonly int[] branchMap; - private readonly int baseIndex; - private int endIndex; - - internal SubroutineCall(JsrInliner inliner, int subroutineIndex, int returnIndex) - { - this.inliner = inliner; - this.subroutineIndex = subroutineIndex; - this.returnIndex = returnIndex; - baseIndex = inliner.codeLength; - branchMap = new int[inliner.m.Instructions.Length]; - for (int i = 0; i < branchMap.Length; i++) - { - branchMap[i] = i; - } - } - - private void Emit(ClassFile.Method.Instruction instr) - { - inliner.Add(instr); - } - - private void EmitGoto(int targetIndex) - { - ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); - instr.PatchOpCode(NormalizedByteCode.__goto, targetIndex); - instr.SetPC(-1); - Emit(instr); - } - - internal bool InlineSubroutine() - { - bool hasJsrs = false; - // start with a pre-amble to load a dummy return address on the stack and to branch to the subroutine - { - // TODO consider exception handling around these instructions - ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); - instr.PatchOpCode(NormalizedByteCode.__aconst_null); - instr.SetPC(inliner.m.Instructions[subroutineIndex].PC); - Emit(instr); - EmitGoto(subroutineIndex); - } - - bool fallThru = false; - for (int instructionIndex = 0; instructionIndex < inliner.m.Instructions.Length; instructionIndex++) - { - if ((inliner.flags[instructionIndex] & InstructionFlags.Reachable) != 0 - && inliner.ma.IsSubroutineActive(instructionIndex, subroutineIndex)) - { - fallThru = false; - branchMap[instructionIndex] = inliner.codeLength; - switch (inliner.m.Instructions[instructionIndex].NormalizedOpCode) - { - case NormalizedByteCode.__tableswitch: - case NormalizedByteCode.__lookupswitch: - case NormalizedByteCode.__ireturn: - case NormalizedByteCode.__lreturn: - case NormalizedByteCode.__freturn: - case NormalizedByteCode.__dreturn: - case NormalizedByteCode.__areturn: - case NormalizedByteCode.__return: - case NormalizedByteCode.__athrow: - case NormalizedByteCode.__goto: - Emit(inliner.m.Instructions[instructionIndex]); - break; - case NormalizedByteCode.__jsr: - hasJsrs = true; - goto default; - case NormalizedByteCode.__ret: - { - int subid = inliner.ma.GetLocalTypeWrapper(instructionIndex, inliner.m.Instructions[instructionIndex].TargetIndex).SubroutineIndex; - if (subid == subroutineIndex) - { - EmitGoto(returnIndex); - } - else - { - Emit(inliner.m.Instructions[instructionIndex]); - } - break; - } - default: - fallThru = true; - Emit(inliner.m.Instructions[instructionIndex]); - break; - } - } - else if (fallThru) - { - EmitGoto(instructionIndex); - } - } - - endIndex = inliner.codeLength; - DoFixups(); - return hasJsrs; - } - - private void DoFixups() - { - for (int instructionIndex = baseIndex; instructionIndex < endIndex; instructionIndex++) - { - switch (inliner.codeCopy[instructionIndex].NormalizedOpCode) - { - case NormalizedByteCode.__lookupswitch: - case NormalizedByteCode.__tableswitch: - { - int[] targets = new int[inliner.codeCopy[instructionIndex].SwitchEntryCount]; - for (int i = 0; i < targets.Length; i++) - { - targets[i] = branchMap[inliner.codeCopy[instructionIndex].GetSwitchTargetIndex(i)]; - } - inliner.codeCopy[instructionIndex].SetSwitchTargets(targets); - inliner.codeCopy[instructionIndex].DefaultTarget = branchMap[inliner.codeCopy[instructionIndex].DefaultTarget]; - } - break; - case NormalizedByteCode.__ifeq: - case NormalizedByteCode.__ifne: - case NormalizedByteCode.__iflt: - case NormalizedByteCode.__ifge: - case NormalizedByteCode.__ifgt: - case NormalizedByteCode.__ifle: - case NormalizedByteCode.__if_icmpeq: - case NormalizedByteCode.__if_icmpne: - case NormalizedByteCode.__if_icmplt: - case NormalizedByteCode.__if_icmpge: - case NormalizedByteCode.__if_icmpgt: - case NormalizedByteCode.__if_icmple: - case NormalizedByteCode.__if_acmpeq: - case NormalizedByteCode.__if_acmpne: - case NormalizedByteCode.__ifnull: - case NormalizedByteCode.__ifnonnull: - case NormalizedByteCode.__goto: - case NormalizedByteCode.__jsr: - inliner.codeCopy[instructionIndex].TargetIndex = branchMap[inliner.codeCopy[instructionIndex].TargetIndex]; - break; - } - } - } - - private int MapExceptionStartEnd(int index) - { - while (branchMap[index] < baseIndex) - { - index++; - if (index == branchMap.Length) - { - return endIndex; - } - } - return branchMap[index]; - } - - internal void DoExceptions(ClassFile.Method.ExceptionTableEntry[] table, List newExceptions) - { - foreach (ClassFile.Method.ExceptionTableEntry entry in table) - { - int start = MapExceptionStartEnd(entry.startIndex); - int end = MapExceptionStartEnd(entry.endIndex); - if (start != end) - { - ClassFile.Method.ExceptionTableEntry newEntry = new ClassFile.Method.ExceptionTableEntry(start, end, branchMap[entry.handlerIndex], entry.catch_type, entry.ordinal); - newExceptions.Add(newEntry); - } - } - } - } - - class SimpleType - { - internal static readonly SimpleType Invalid = null; - internal static readonly SimpleType Primitive = new SimpleType(); - internal static readonly SimpleType WidePrimitive = new SimpleType(); - internal static readonly SimpleType Object = new SimpleType(); - internal static readonly SimpleType[] EmptyArray = new SimpleType[0]; - - private SimpleType() { } - - internal bool IsPrimitive - { - get - { - return this == SimpleType.Primitive - || this == SimpleType.WidePrimitive; - } - } - - internal bool IsWidePrimitive - { - get - { - return this == SimpleType.WidePrimitive; - } - } - - private sealed class ReturnAddressType : SimpleType - { - internal readonly int subroutineIndex; - - internal ReturnAddressType(int subroutineIndex) - { - this.subroutineIndex = subroutineIndex; - } - } - - internal static SimpleType MakeRet(int subroutineIndex) - { - return new ReturnAddressType(subroutineIndex); - } - - internal static bool IsRet(SimpleType w) - { - return w is ReturnAddressType; - } - - internal int SubroutineIndex - { - get - { - return ((ReturnAddressType)this).subroutineIndex; - } - } - } - - sealed class JsrMethodAnalyzer - { - private ClassFile classFile; - private InstructionState[] state; - private List[] callsites; - private List[] returnsites; - - internal JsrMethodAnalyzer(RuntimeJavaMethod mw, ClassFile classFile, ClassFile.Method method, RuntimeClassLoader classLoader, InstructionFlags[] flags) - { - if (method.VerifyError != null) - { - throw new VerifyError(method.VerifyError); - } - - this.classFile = classFile; - state = new InstructionState[method.Instructions.Length]; - callsites = new List[method.Instructions.Length]; - returnsites = new List[method.Instructions.Length]; - - // because types have to have identity, the subroutine return address types are cached here - Dictionary returnAddressTypes = new Dictionary(); - - try - { - // ensure that exception blocks and handlers start and end at instruction boundaries - for (int i = 0; i < method.ExceptionTable.Length; i++) - { - int start = method.ExceptionTable[i].startIndex; - int end = method.ExceptionTable[i].endIndex; - int handler = method.ExceptionTable[i].handlerIndex; - if (start >= end || start == -1 || end == -1 || handler <= 0) - { - throw new IndexOutOfRangeException(); - } - } - } - catch (IndexOutOfRangeException) - { - throw new ClassFormatError(string.Format("Illegal exception table (class: {0}, method: {1}, signature: {2}", classFile.Name, method.Name, method.Signature)); - } - - // start by computing the initial state, the stack is empty and the locals contain the arguments - state[0] = new InstructionState(method.MaxLocals, method.MaxStack); - SimpleType thisType; - int firstNonArgLocalIndex = 0; - if (!method.IsStatic) - { - thisType = SimpleType.Object; - state[0].SetLocalType(firstNonArgLocalIndex++, thisType, -1); - } - else - { - thisType = null; - } - RuntimeJavaType[] argTypeWrappers = mw.GetParameters(); - for (int i = 0; i < argTypeWrappers.Length; i++) - { - RuntimeJavaType tw = argTypeWrappers[i]; - SimpleType type; - if (tw.IsWidePrimitive) - { - type = SimpleType.WidePrimitive; - } - else if (tw.IsPrimitive) - { - type = SimpleType.Primitive; - } - else - { - type = SimpleType.Object; - } - state[0].SetLocalType(firstNonArgLocalIndex++, type, -1); - if (type.IsWidePrimitive) - { - firstNonArgLocalIndex++; - } - } - SimpleType[] argumentsByLocalIndex = new SimpleType[firstNonArgLocalIndex]; - for (int i = 0; i < argumentsByLocalIndex.Length; i++) - { - argumentsByLocalIndex[i] = state[0].GetLocalTypeEx(i); - } - InstructionState s = state[0].Copy(); - bool done = false; - ClassFile.Method.Instruction[] instructions = method.Instructions; - while (!done) - { - done = true; - for (int i = 0; i < instructions.Length; i++) - { - if (state[i] != null && state[i].changed) - { - try - { - //Console.WriteLine(method.Instructions[i].PC + ": " + method.Instructions[i].OpCode.ToString()); - done = false; - state[i].changed = false; - // mark the exception handlers reachable from this instruction - for (int j = 0; j < method.ExceptionTable.Length; j++) - { - if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex) - { - MergeExceptionHandler(method.ExceptionTable[j].handlerIndex, state[i]); - } - } - state[i].CopyTo(s); - ClassFile.Method.Instruction instr = instructions[i]; - switch (instr.NormalizedOpCode) - { - case NormalizedByteCode.__aload: - { - SimpleType type = s.GetLocalType(instr.NormalizedArg1); - if (type == SimpleType.Invalid || type.IsPrimitive) - { - throw new VerifyError("Object reference expected"); - } - s.PushType(type); - break; - } - case NormalizedByteCode.__astore: - s.SetLocalType(instr.NormalizedArg1, s.PopObjectType(), i); - break; - case NormalizedByteCode.__aconst_null: - s.PushObject(); - break; - case NormalizedByteCode.__aaload: - s.PopPrimitive(); - s.PopObjectType(); - s.PushObject(); - break; - case NormalizedByteCode.__aastore: - s.PopObjectType(); - s.PopPrimitive(); - s.PopObjectType(); - break; - case NormalizedByteCode.__baload: - s.PopPrimitive(); - s.PopObjectType(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__bastore: - s.PopPrimitive(); - s.PopPrimitive(); - s.PopObjectType(); - break; - case NormalizedByteCode.__caload: - s.PopPrimitive(); - s.PopObjectType(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__castore: - s.PopPrimitive(); - s.PopPrimitive(); - s.PopObjectType(); - break; - case NormalizedByteCode.__saload: - s.PopPrimitive(); - s.PopObjectType(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__sastore: - s.PopPrimitive(); - s.PopPrimitive(); - s.PopObjectType(); - break; - case NormalizedByteCode.__iaload: - s.PopPrimitive(); - s.PopObjectType(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__iastore: - s.PopPrimitive(); - s.PopPrimitive(); - s.PopObjectType(); - break; - case NormalizedByteCode.__laload: - s.PopPrimitive(); - s.PopObjectType(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__lastore: - s.PopWidePrimitive(); - s.PopPrimitive(); - s.PopObjectType(); - break; - case NormalizedByteCode.__daload: - s.PopPrimitive(); - s.PopObjectType(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__dastore: - s.PopWidePrimitive(); - s.PopPrimitive(); - s.PopObjectType(); - break; - case NormalizedByteCode.__faload: - s.PopPrimitive(); - s.PopObjectType(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__fastore: - s.PopPrimitive(); - s.PopPrimitive(); - s.PopObjectType(); - break; - case NormalizedByteCode.__arraylength: - s.PopObjectType(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__iconst: - s.PushPrimitive(); - break; - case NormalizedByteCode.__if_icmpeq: - case NormalizedByteCode.__if_icmpne: - case NormalizedByteCode.__if_icmplt: - case NormalizedByteCode.__if_icmpge: - case NormalizedByteCode.__if_icmpgt: - case NormalizedByteCode.__if_icmple: - s.PopPrimitive(); - s.PopPrimitive(); - break; - case NormalizedByteCode.__ifeq: - case NormalizedByteCode.__ifge: - case NormalizedByteCode.__ifgt: - case NormalizedByteCode.__ifle: - case NormalizedByteCode.__iflt: - case NormalizedByteCode.__ifne: - s.PopPrimitive(); - break; - case NormalizedByteCode.__ifnonnull: - case NormalizedByteCode.__ifnull: - s.PopObjectType(); - break; - case NormalizedByteCode.__if_acmpeq: - case NormalizedByteCode.__if_acmpne: - s.PopObjectType(); - s.PopObjectType(); - break; - case NormalizedByteCode.__getstatic: - s.PushType(GetFieldref(instr.Arg1).Signature); - break; - case NormalizedByteCode.__putstatic: - s.PopType(GetFieldref(instr.Arg1).Signature); - break; - case NormalizedByteCode.__getfield: - s.PopObjectType(); - s.PushType(GetFieldref(instr.Arg1).Signature); - break; - case NormalizedByteCode.__putfield: - s.PopType(GetFieldref(instr.Arg1).Signature); - s.PopObjectType(); - break; - case NormalizedByteCode.__ldc: - { - switch (GetConstantPoolConstantType(instr.Arg1)) - { - case ClassFile.ConstantType.Double: - s.PushWidePrimitive(); - break; - case ClassFile.ConstantType.Float: - s.PushPrimitive(); - break; - case ClassFile.ConstantType.Integer: - s.PushPrimitive(); - break; - case ClassFile.ConstantType.Long: - s.PushWidePrimitive(); - break; - case ClassFile.ConstantType.String: - case ClassFile.ConstantType.Class: - s.PushObject(); - break; - default: - // NOTE this is not a VerifyError, because it cannot happen (unless we have - // a bug in ClassFile.GetConstantPoolConstantType) - throw new InvalidOperationException(); - } - break; - } - case NormalizedByteCode.__invokevirtual: - case NormalizedByteCode.__invokespecial: - case NormalizedByteCode.__invokeinterface: - case NormalizedByteCode.__invokestatic: - { - ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1); - s.MultiPopAnyType(cpi.GetArgTypes().Length); - if (instr.NormalizedOpCode != NormalizedByteCode.__invokestatic) - { - s.PopType(); - } - string sig = cpi.Signature; - sig = sig.Substring(sig.IndexOf(')') + 1); - if (sig != "V") - { - s.PushType(sig); - } - break; - } - case NormalizedByteCode.__goto: - break; - case NormalizedByteCode.__istore: - s.PopPrimitive(); - s.SetLocalPrimitive(instr.NormalizedArg1, i); - break; - case NormalizedByteCode.__iload: - s.PushPrimitive(); - break; - case NormalizedByteCode.__ineg: - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__iadd: - case NormalizedByteCode.__isub: - case NormalizedByteCode.__imul: - case NormalizedByteCode.__idiv: - case NormalizedByteCode.__irem: - case NormalizedByteCode.__iand: - case NormalizedByteCode.__ior: - case NormalizedByteCode.__ixor: - case NormalizedByteCode.__ishl: - case NormalizedByteCode.__ishr: - case NormalizedByteCode.__iushr: - s.PopPrimitive(); - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__lneg: - s.PopWidePrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__ladd: - case NormalizedByteCode.__lsub: - case NormalizedByteCode.__lmul: - case NormalizedByteCode.__ldiv: - case NormalizedByteCode.__lrem: - case NormalizedByteCode.__land: - case NormalizedByteCode.__lor: - case NormalizedByteCode.__lxor: - s.PopWidePrimitive(); - s.PopWidePrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__lshl: - case NormalizedByteCode.__lshr: - case NormalizedByteCode.__lushr: - s.PopPrimitive(); - s.PopWidePrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__fneg: - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__fadd: - case NormalizedByteCode.__fsub: - case NormalizedByteCode.__fmul: - case NormalizedByteCode.__fdiv: - case NormalizedByteCode.__frem: - s.PopPrimitive(); - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__dneg: - s.PopWidePrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__dadd: - case NormalizedByteCode.__dsub: - case NormalizedByteCode.__dmul: - case NormalizedByteCode.__ddiv: - case NormalizedByteCode.__drem: - s.PopWidePrimitive(); - s.PopWidePrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__new: - s.PushObject(); - break; - case NormalizedByteCode.__multianewarray: - { - if (instr.Arg2 < 1) - { - throw new VerifyError("Illegal dimension argument"); - } - for (int j = 0; j < instr.Arg2; j++) - { - s.PopPrimitive(); - } - s.PushObject(); - break; - } - case NormalizedByteCode.__anewarray: - s.PopPrimitive(); - s.PushObject(); - break; - case NormalizedByteCode.__newarray: - s.PopPrimitive(); - s.PushObject(); - break; - case NormalizedByteCode.__swap: - { - SimpleType t1 = s.PopType(); - SimpleType t2 = s.PopType(); - s.PushType(t1); - s.PushType(t2); - break; - } - case NormalizedByteCode.__dup: - { - SimpleType t = s.PopType(); - s.PushType(t); - s.PushType(t); - break; - } - case NormalizedByteCode.__dup2: - { - SimpleType t = s.PopAnyType(); - if (t.IsWidePrimitive) - { - s.PushType(t); - s.PushType(t); - } - else - { - SimpleType t2 = s.PopType(); - s.PushType(t2); - s.PushType(t); - s.PushType(t2); - s.PushType(t); - } - break; - } - case NormalizedByteCode.__dup_x1: - { - SimpleType value1 = s.PopType(); - SimpleType value2 = s.PopType(); - s.PushType(value1); - s.PushType(value2); - s.PushType(value1); - break; - } - case NormalizedByteCode.__dup2_x1: - { - SimpleType value1 = s.PopAnyType(); - if (value1.IsWidePrimitive) - { - SimpleType value2 = s.PopType(); - s.PushType(value1); - s.PushType(value2); - s.PushType(value1); - } - else - { - SimpleType value2 = s.PopType(); - SimpleType value3 = s.PopType(); - s.PushType(value2); - s.PushType(value1); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - break; - } - case NormalizedByteCode.__dup_x2: - { - SimpleType value1 = s.PopType(); - SimpleType value2 = s.PopAnyType(); - if (value2.IsWidePrimitive) - { - s.PushType(value1); - s.PushType(value2); - s.PushType(value1); - } - else - { - SimpleType value3 = s.PopType(); - s.PushType(value1); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - break; - } - case NormalizedByteCode.__dup2_x2: - { - SimpleType value1 = s.PopAnyType(); - if (value1.IsWidePrimitive) - { - SimpleType value2 = s.PopAnyType(); - if (value2.IsWidePrimitive) - { - // Form 4 - s.PushType(value1); - s.PushType(value2); - s.PushType(value1); - } - else - { - // Form 2 - SimpleType value3 = s.PopType(); - s.PushType(value1); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - } - else - { - SimpleType value2 = s.PopType(); - SimpleType value3 = s.PopAnyType(); - if (value3.IsWidePrimitive) - { - // Form 3 - s.PushType(value2); - s.PushType(value1); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - else - { - // Form 4 - SimpleType value4 = s.PopType(); - s.PushType(value2); - s.PushType(value1); - s.PushType(value4); - s.PushType(value3); - s.PushType(value2); - s.PushType(value1); - } - } - break; - } - case NormalizedByteCode.__pop: - s.PopType(); - break; - case NormalizedByteCode.__pop2: - { - SimpleType type = s.PopAnyType(); - if (!type.IsWidePrimitive) - { - s.PopType(); - } - break; - } - case NormalizedByteCode.__monitorenter: - case NormalizedByteCode.__monitorexit: - s.PopObjectType(); - break; - case NormalizedByteCode.__return: - break; - case NormalizedByteCode.__areturn: - s.PopObjectType(); - break; - case NormalizedByteCode.__ireturn: - s.PopPrimitive(); - break; - case NormalizedByteCode.__lreturn: - s.PopWidePrimitive(); - break; - case NormalizedByteCode.__freturn: - s.PopPrimitive(); - break; - case NormalizedByteCode.__dreturn: - s.PopWidePrimitive(); - break; - case NormalizedByteCode.__fload: - s.PushPrimitive(); - break; - case NormalizedByteCode.__fstore: - s.PopPrimitive(); - s.SetLocalPrimitive(instr.NormalizedArg1, i); - break; - case NormalizedByteCode.__dload: - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__dstore: - s.PopWidePrimitive(); - s.SetLocalWidePrimitive(instr.NormalizedArg1, i); - break; - case NormalizedByteCode.__lload: - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__lstore: - s.PopWidePrimitive(); - s.SetLocalWidePrimitive(instr.NormalizedArg1, i); - break; - case NormalizedByteCode.__lconst_0: - case NormalizedByteCode.__lconst_1: - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__fconst_0: - case NormalizedByteCode.__fconst_1: - case NormalizedByteCode.__fconst_2: - s.PushPrimitive(); - break; - case NormalizedByteCode.__dconst_0: - case NormalizedByteCode.__dconst_1: - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__lcmp: - s.PopWidePrimitive(); - s.PopWidePrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__fcmpl: - case NormalizedByteCode.__fcmpg: - s.PopPrimitive(); - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__dcmpl: - case NormalizedByteCode.__dcmpg: - s.PopWidePrimitive(); - s.PopWidePrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__checkcast: - s.PopObjectType(); - s.PushObject(); - break; - case NormalizedByteCode.__instanceof: - s.PopObjectType(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__iinc: - break; - case NormalizedByteCode.__athrow: - s.PopObjectType(); - break; - case NormalizedByteCode.__tableswitch: - case NormalizedByteCode.__lookupswitch: - s.PopPrimitive(); - break; - case NormalizedByteCode.__i2b: - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__i2c: - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__i2s: - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__i2l: - s.PopPrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__i2f: - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__i2d: - s.PopPrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__l2i: - s.PopWidePrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__l2f: - s.PopWidePrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__l2d: - s.PopWidePrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__f2i: - s.PopPrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__f2l: - s.PopPrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__f2d: - s.PopPrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__d2i: - s.PopWidePrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__d2f: - s.PopWidePrimitive(); - s.PushPrimitive(); - break; - case NormalizedByteCode.__d2l: - s.PopWidePrimitive(); - s.PushWidePrimitive(); - break; - case NormalizedByteCode.__jsr: - // TODO make sure we're not calling a subroutine we're already in - break; - case NormalizedByteCode.__ret: - { - // TODO if we're returning from a higher level subroutine, invalidate - // all the intermediate return addresses - int subroutineIndex = s.GetLocalRet(instr.Arg1); - s.CheckSubroutineActive(subroutineIndex); - break; - } - case NormalizedByteCode.__nop: - if (i + 1 == instructions.Length) - { - throw new VerifyError("Falling off the end of the code"); - } - break; - case NormalizedByteCode.__invokedynamic: - // it is impossible to have a valid invokedynamic in a pre-7.0 class file - throw new VerifyError("Illegal type in constant pool"); - default: - throw new NotImplementedException(instr.NormalizedOpCode.ToString()); - } - if (s.GetStackHeight() > method.MaxStack) - { - throw new VerifyError("Stack size too large"); - } - for (int j = 0; j < method.ExceptionTable.Length; j++) - { - if (method.ExceptionTable[j].endIndex == i + 1) - { - MergeExceptionHandler(method.ExceptionTable[j].handlerIndex, s); - } - } - try - { - // another big switch to handle the opcode targets - switch (instr.NormalizedOpCode) - { - case NormalizedByteCode.__tableswitch: - case NormalizedByteCode.__lookupswitch: - for (int j = 0; j < instr.SwitchEntryCount; j++) - { - state[instr.GetSwitchTargetIndex(j)] += s; - } - state[instr.DefaultTarget] += s; - break; - case NormalizedByteCode.__ifeq: - case NormalizedByteCode.__ifne: - case NormalizedByteCode.__iflt: - case NormalizedByteCode.__ifge: - case NormalizedByteCode.__ifgt: - case NormalizedByteCode.__ifle: - case NormalizedByteCode.__if_icmpeq: - case NormalizedByteCode.__if_icmpne: - case NormalizedByteCode.__if_icmplt: - case NormalizedByteCode.__if_icmpge: - case NormalizedByteCode.__if_icmpgt: - case NormalizedByteCode.__if_icmple: - case NormalizedByteCode.__if_acmpeq: - case NormalizedByteCode.__if_acmpne: - case NormalizedByteCode.__ifnull: - case NormalizedByteCode.__ifnonnull: - state[i + 1] += s; - state[instr.TargetIndex] += s; - break; - case NormalizedByteCode.__goto: - state[instr.TargetIndex] += s; - break; - case NormalizedByteCode.__jsr: - { - int index = instr.TargetIndex; - s.SetSubroutineId(index); - SimpleType retAddressType; - if (!returnAddressTypes.TryGetValue(index, out retAddressType)) - { - retAddressType = SimpleType.MakeRet(index); - returnAddressTypes[index] = retAddressType; - } - s.PushType(retAddressType); - state[index] += s; - List returns = GetReturnSites(i); - if (returns != null) - { - foreach (int returnIndex in returns) - { - state[i + 1] = InstructionState.MergeSubroutineReturn(state[i + 1], s, state[returnIndex], state[returnIndex].GetLocalsModified(index)); - } - } - AddCallSite(index, i); - break; - } - case NormalizedByteCode.__ret: - { - // HACK if the ret is processed before all of the jsr instructions to this subroutine - // we wouldn't be able to properly merge, so that is why we track the number of callsites - // for each subroutine instruction (see Instruction.AddCallSite()) - int subroutineIndex = s.GetLocalRet(instr.Arg1); - int[] cs = GetCallSites(subroutineIndex); - bool[] locals_modified = s.GetLocalsModified(subroutineIndex); - for (int j = 0; j < cs.Length; j++) - { - AddReturnSite(cs[j], i); - state[cs[j] + 1] = InstructionState.MergeSubroutineReturn(state[cs[j] + 1], state[cs[j]], s, locals_modified); - } - break; - } - case NormalizedByteCode.__ireturn: - case NormalizedByteCode.__lreturn: - case NormalizedByteCode.__freturn: - case NormalizedByteCode.__dreturn: - case NormalizedByteCode.__areturn: - case NormalizedByteCode.__return: - case NormalizedByteCode.__athrow: - break; - default: - state[i + 1] += s; - break; - } - } - catch (IndexOutOfRangeException) - { - // we're going to assume that this always means that we have an invalid branch target - // NOTE because PcIndexMap returns -1 for illegal PCs (in the middle of an instruction) and - // we always use that value as an index into the state array, any invalid PC will result - // in an IndexOutOfRangeException - throw new VerifyError("Illegal target of jump or branch"); - } - } - catch (VerifyError x) - { - string opcode = instructions[i].NormalizedOpCode.ToString(); - if (opcode.StartsWith("__")) - { - opcode = opcode.Substring(2); - } - throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})", - classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x); - } - } - } - } - - // Now we do another pass to compute reachability - done = false; - flags[0] |= InstructionFlags.Reachable; - while (!done) - { - done = true; - bool didJsrOrRet = false; - for (int i = 0; i < instructions.Length; i++) - { - if ((flags[i] & (InstructionFlags.Reachable | InstructionFlags.Processed)) == InstructionFlags.Reachable) - { - done = false; - flags[i] |= InstructionFlags.Processed; - // mark the exception handlers reachable from this instruction - for (int j = 0; j < method.ExceptionTable.Length; j++) - { - if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex) - { - flags[method.ExceptionTable[j].handlerIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - } - } - // mark the successor instructions - switch (instructions[i].NormalizedOpCode) - { - case NormalizedByteCode.__tableswitch: - case NormalizedByteCode.__lookupswitch: - { - bool hasbackbranch = false; - for (int j = 0; j < instructions[i].SwitchEntryCount; j++) - { - hasbackbranch |= instructions[i].GetSwitchTargetIndex(j) < i; - flags[instructions[i].GetSwitchTargetIndex(j)] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - } - hasbackbranch |= instructions[i].DefaultTarget < i; - flags[instructions[i].DefaultTarget] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - break; - } - case NormalizedByteCode.__goto: - flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - break; - case NormalizedByteCode.__ifeq: - case NormalizedByteCode.__ifne: - case NormalizedByteCode.__iflt: - case NormalizedByteCode.__ifge: - case NormalizedByteCode.__ifgt: - case NormalizedByteCode.__ifle: - case NormalizedByteCode.__if_icmpeq: - case NormalizedByteCode.__if_icmpne: - case NormalizedByteCode.__if_icmplt: - case NormalizedByteCode.__if_icmpge: - case NormalizedByteCode.__if_icmpgt: - case NormalizedByteCode.__if_icmple: - case NormalizedByteCode.__if_acmpeq: - case NormalizedByteCode.__if_acmpne: - case NormalizedByteCode.__ifnull: - case NormalizedByteCode.__ifnonnull: - flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - flags[i + 1] |= InstructionFlags.Reachable; - break; - case NormalizedByteCode.__jsr: - flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - // Note that we don't mark the next instruction as reachable, - // because that depends on the corresponding ret actually being - // reachable. We handle this in the loop below. - didJsrOrRet = true; - break; - case NormalizedByteCode.__ret: - // Note that we can't handle ret here, because we might encounter the ret - // before having seen all the corresponding jsr instructions, so we can't - // update all the call sites. - // We handle ret in the loop below. - didJsrOrRet = true; - break; - case NormalizedByteCode.__ireturn: - case NormalizedByteCode.__lreturn: - case NormalizedByteCode.__freturn: - case NormalizedByteCode.__dreturn: - case NormalizedByteCode.__areturn: - case NormalizedByteCode.__return: - case NormalizedByteCode.__athrow: - break; - default: - flags[i + 1] |= InstructionFlags.Reachable; - break; - } - } - } - if (didJsrOrRet) - { - for (int i = 0; i < instructions.Length; i++) - { - if (instructions[i].NormalizedOpCode == NormalizedByteCode.__ret - && (flags[i] & InstructionFlags.Reachable) != 0) - { - int subroutineIndex = state[i].GetLocalRet(instructions[i].Arg1); - int[] cs = GetCallSites(subroutineIndex); - for (int j = 0; j < cs.Length; j++) - { - if ((flags[cs[j]] & InstructionFlags.Reachable) != 0) - { - flags[cs[j] + 1] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; - } - } - } - } - } - } - } - - private void MergeExceptionHandler(int handlerIndex, InstructionState curr) - { - // NOTE this used to be CopyLocalsAndSubroutines, but it doesn't (always) make - // sense to copy the subroutine state - // TODO figure out if there are circumstances under which it does make sense - // to copy the active subroutine state - // UPDATE subroutines must be copied as well, but I think I now have a better - // understanding of subroutine merges, so the problems that triggered the previous - // change here hopefully won't arise anymore - InstructionState ex = curr.CopyLocalsAndSubroutines(); - ex.PushObject(); - state[handlerIndex] += ex; - } - - private ClassFile.ConstantPoolItemMI GetMethodref(int index) - { - try - { - ClassFile.ConstantPoolItemMI item = classFile.GetMethodref(index); - if (item != null) - { - return item; - } - } - catch (InvalidCastException) - { - } - catch (IndexOutOfRangeException) - { - } - throw new VerifyError("Illegal constant pool index"); - } - - private ClassFile.ConstantPoolItemFieldref GetFieldref(int index) - { - try - { - ClassFile.ConstantPoolItemFieldref item = classFile.GetFieldref(index); - if (item != null) - { - return item; - } - } - catch (InvalidCastException) - { - } - catch (IndexOutOfRangeException) - { - } - throw new VerifyError("Illegal constant pool index"); - } - - private ClassFile.ConstantType GetConstantPoolConstantType(int index) - { - try - { - return classFile.GetConstantPoolConstantType(index); - } - catch (IndexOutOfRangeException) - { - // constant pool index out of range - } - catch (InvalidOperationException) - { - // specified constant pool entry doesn't contain a constant - } - catch (NullReferenceException) - { - // specified constant pool entry is empty (entry 0 or the filler following a wide entry) - } - throw new VerifyError("Illegal constant pool index"); - } - - private void AddReturnSite(int callSiteIndex, int returnSiteIndex) - { - if (returnsites[callSiteIndex] == null) - { - returnsites[callSiteIndex] = new List(); - } - List l = returnsites[callSiteIndex]; - if (l.IndexOf(returnSiteIndex) == -1) - { - state[callSiteIndex].changed = true; - l.Add(returnSiteIndex); - } - } - - private List GetReturnSites(int callSiteIndex) - { - return returnsites[callSiteIndex]; - } - - private void AddCallSite(int subroutineIndex, int callSiteIndex) - { - if (callsites[subroutineIndex] == null) - { - callsites[subroutineIndex] = new List(); - } - List l = callsites[subroutineIndex]; - if (l.IndexOf(callSiteIndex) == -1) - { - l.Add(callSiteIndex); - state[subroutineIndex].AddCallSite(); - } - } - - private int[] GetCallSites(int subroutineIndex) - { - return callsites[subroutineIndex].ToArray(); - } - - internal SimpleType GetLocalTypeWrapper(int index, int local) - { - return state[index].GetLocalTypeEx(local); - } - - internal bool IsSubroutineActive(int instructionIndex, int subroutineIndex) - { - return state[instructionIndex].IsSubroutineActive(subroutineIndex); - } - - sealed class Subroutine - { - private int subroutineIndex; - private bool[] localsModified; - - private Subroutine(int subroutineIndex, bool[] localsModified) - { - this.subroutineIndex = subroutineIndex; - this.localsModified = localsModified; - } - - internal Subroutine(int subroutineIndex, int maxLocals) - { - this.subroutineIndex = subroutineIndex; - localsModified = new bool[maxLocals]; - } - - internal int SubroutineIndex - { - get - { - return subroutineIndex; - } - } - - internal bool[] LocalsModified - { - get - { - return localsModified; - } - } - - internal void SetLocalModified(int local) - { - localsModified[local] = true; - } - - internal Subroutine Copy() - { - return new Subroutine(subroutineIndex, (bool[])localsModified.Clone()); - } - } - - sealed class InstructionState - { - private SimpleType[] stack; - private int stackSize; - private int stackEnd; - private SimpleType[] locals; - private List subroutines; - private int callsites; - internal bool changed = true; - private enum ShareFlags : byte - { - None = 0, - Stack = 1, - Locals = 2, - Subroutines = 4, - All = Stack | Locals | Subroutines - } - private ShareFlags flags; - - private InstructionState(SimpleType[] stack, int stackSize, int stackEnd, SimpleType[] locals, List subroutines, int callsites) - { - this.flags = ShareFlags.All; - this.stack = stack; - this.stackSize = stackSize; - this.stackEnd = stackEnd; - this.locals = locals; - this.subroutines = subroutines; - this.callsites = callsites; - } - - internal InstructionState(int maxLocals, int maxStack) - { - this.flags = ShareFlags.None; - this.stack = new SimpleType[maxStack]; - this.stackEnd = maxStack; - this.locals = new SimpleType[maxLocals]; - } - - internal InstructionState Copy() - { - return new InstructionState(stack, stackSize, stackEnd, locals, subroutines, callsites); - } - - internal void CopyTo(InstructionState target) - { - target.flags = ShareFlags.All; - target.stack = stack; - target.stackSize = stackSize; - target.stackEnd = stackEnd; - target.locals = locals; - target.subroutines = subroutines; - target.callsites = callsites; - target.changed = true; - } - - internal InstructionState CopyLocalsAndSubroutines() - { - InstructionState copy = new InstructionState(new SimpleType[stack.Length], 0, stack.Length, locals, subroutines, callsites); - copy.flags &= ~ShareFlags.Stack; - return copy; - } - - private static List CopySubroutines(List l) - { - if (l == null) - { - return null; - } - List n = new List(l.Count); - foreach (Subroutine s in l) - { - n.Add(s.Copy()); - } - return n; - } - - private void MergeSubroutineHelper(InstructionState s2) - { - if (subroutines == null || s2.subroutines == null) - { - if (subroutines != null) - { - subroutines = null; - changed = true; - } - } - else - { - SubroutinesCopyOnWrite(); - List ss1 = subroutines; - subroutines = new List(); - foreach (Subroutine ss2 in s2.subroutines) - { - foreach (Subroutine ss in ss1) - { - if (ss.SubroutineIndex == ss2.SubroutineIndex) - { - subroutines.Add(ss); - for (int i = 0; i < ss.LocalsModified.Length; i++) - { - if (ss2.LocalsModified[i] && !ss.LocalsModified[i]) - { - ss.LocalsModified[i] = true; - changed = true; - } - } - } - } - } - if (ss1.Count != subroutines.Count) - { - changed = true; - } - } - - if (s2.callsites > callsites) - { - //Console.WriteLine("s2.callsites = {0}, callsites = {1}", s2.callsites, callsites); - callsites = s2.callsites; - changed = true; - } - } - - internal static InstructionState MergeSubroutineReturn(InstructionState jsrSuccessor, InstructionState jsr, InstructionState ret, bool[] locals_modified) - { - InstructionState next = ret.Copy(); - next.LocalsCopyOnWrite(); - for (int i = 0; i < locals_modified.Length; i++) - { - if (!locals_modified[i]) - { - next.locals[i] = jsr.locals[i]; - } - } - next.flags |= ShareFlags.Subroutines; - next.subroutines = jsr.subroutines; - next.callsites = jsr.callsites; - return jsrSuccessor + next; - } - - public static InstructionState operator+(InstructionState s1, InstructionState s2) - { - if (s1 == null) - { - return s2.Copy(); - } - if (s1.stackSize != s2.stackSize || s1.stackEnd != s2.stackEnd) - { - throw new VerifyError(string.Format("Inconsistent stack height: {0} != {1}", - s1.stackSize + s1.stack.Length - s1.stackEnd, - s2.stackSize + s2.stack.Length - s2.stackEnd)); - } - InstructionState s = s1.Copy(); - s.changed = s1.changed; - for (int i = 0; i < s.stackSize; i++) - { - SimpleType type = s.stack[i]; - SimpleType type2 = s2.stack[i]; - if (type == type2) - { - // perfect match, nothing to do - } - else if (!type.IsPrimitive) - { - SimpleType baseType = InstructionState.FindCommonBaseType(type, type2); - if (baseType == SimpleType.Invalid) - { - if (SimpleType.IsRet(type) && SimpleType.IsRet(type2)) - { - // if we never return from a subroutine, it is legal to merge to subroutine flows - // (this is from the Mauve test subr.pass.mergeok) - } - else - { - throw new VerifyError(string.Format("cannot merge {0} and {1}", type, type2)); - } - } - if (type != baseType) - { - s.StackCopyOnWrite(); - s.stack[i] = baseType; - s.changed = true; - } - } - else - { - throw new VerifyError(string.Format("cannot merge {0} and {1}", type, type2)); - } - } - for (int i = 0; i < s.locals.Length; i++) - { - SimpleType type = s.locals[i]; - SimpleType type2 = s2.locals[i]; - SimpleType baseType = InstructionState.FindCommonBaseType(type, type2); - if (type != baseType) - { - s.LocalsCopyOnWrite(); - s.locals[i] = baseType; - s.changed = true; - } - } - s.MergeSubroutineHelper(s2); - return s; - } - - internal void AddCallSite() - { - callsites++; - changed = true; - } - - internal void SetSubroutineId(int subroutineIndex) - { - SubroutinesCopyOnWrite(); - if (subroutines == null) - { - subroutines = new List(); - } - else - { - foreach (Subroutine s in subroutines) - { - if (s.SubroutineIndex == subroutineIndex) - { - // subroutines cannot recursivly call themselves - throw new VerifyError("subroutines cannot recurse"); - } - } - } - subroutines.Add(new Subroutine(subroutineIndex, locals.Length)); - } - - internal bool[] GetLocalsModified(int subroutineIndex) - { - if (subroutines != null) - { - foreach (Subroutine s in subroutines) - { - if (s.SubroutineIndex == subroutineIndex) - { - return s.LocalsModified; - } - } - } - throw new VerifyError("return from wrong subroutine"); - } - - internal bool IsSubroutineActive(int subroutineIndex) - { - if (subroutines != null) - { - foreach (Subroutine s in subroutines) - { - if (s.SubroutineIndex == subroutineIndex) - { - return true; - } - } - } - return false; - } - - internal void CheckSubroutineActive(int subroutineIndex) - { - if (!IsSubroutineActive(subroutineIndex)) - { - throw new VerifyError("inactive subroutine"); - } - } - - internal static SimpleType FindCommonBaseType(SimpleType type1, SimpleType type2) - { - if (type1 == type2) - { - return type1; - } - if (type1 == SimpleType.Object) - { - return type2; - } - if (type2 == SimpleType.Object) - { - return type1; - } - if (type1 == SimpleType.Invalid || type2 == SimpleType.Invalid) - { - return SimpleType.Invalid; - } - if (type1.IsPrimitive || type2.IsPrimitive) - { - return SimpleType.Invalid; - } - if (SimpleType.IsRet(type1) || SimpleType.IsRet(type2)) - { - return SimpleType.Invalid; - } - return SimpleType.Object; - } - - private void SetLocal1(int index, SimpleType type) - { - try - { - LocalsCopyOnWrite(); - SubroutinesCopyOnWrite(); - if (index > 0 && locals[index - 1] != SimpleType.Invalid && locals[index - 1].IsWidePrimitive) - { - locals[index - 1] = SimpleType.Invalid; - if (subroutines != null) - { - foreach (Subroutine s in subroutines) - { - s.SetLocalModified(index - 1); - } - } - } - locals[index] = type; - if (subroutines != null) - { - foreach (Subroutine s in subroutines) - { - s.SetLocalModified(index); - } - } - } - catch (IndexOutOfRangeException) - { - throw new VerifyError("Illegal local variable number"); - } - } - - private void SetLocal2(int index, SimpleType type) - { - try - { - LocalsCopyOnWrite(); - SubroutinesCopyOnWrite(); - if (index > 0 && locals[index - 1] != SimpleType.Invalid && locals[index - 1].IsWidePrimitive) - { - locals[index - 1] = SimpleType.Invalid; - if (subroutines != null) - { - foreach (Subroutine s in subroutines) - { - s.SetLocalModified(index - 1); - } - } - } - locals[index] = type; - locals[index + 1] = SimpleType.Invalid; - if (subroutines != null) - { - foreach (Subroutine s in subroutines) - { - s.SetLocalModified(index); - s.SetLocalModified(index + 1); - } - } - } - catch (IndexOutOfRangeException) - { - throw new VerifyError("Illegal local variable number"); - } - } - - internal void SetLocalPrimitive(int index, int instructionIndex) - { - SetLocal1(index, SimpleType.Primitive); - } - - internal void SetLocalWidePrimitive(int index, int instructionIndex) - { - SetLocal2(index, SimpleType.WidePrimitive); - } - - internal SimpleType GetLocalType(int index) - { - try - { - return locals[index]; - } - catch (IndexOutOfRangeException) - { - throw new VerifyError("Illegal local variable number"); - } - } - - // this is used by the compiler (indirectly, through MethodAnalyzer.GetLocalTypeWrapper), - // we've already verified the code so we know we won't run outside the array boundary, - // and we don't need to record the fact that we're reading the local. - internal SimpleType GetLocalTypeEx(int index) - { - return locals[index]; - } - - internal int GetLocalRet(int index) - { - SimpleType type = GetLocalType(index); - if (SimpleType.IsRet(type)) - { - return type.SubroutineIndex; - } - throw new VerifyError("incorrect local type, not ret"); - } - - internal void SetLocalType(int index, SimpleType type, int instructionIndex) - { - if (type.IsWidePrimitive) - { - SetLocalWidePrimitive(index, instructionIndex); - } - else - { - SetLocal1(index, type); - } - } - - internal void PushType(string signature) - { - switch (signature[0]) - { - case 'J': - case 'D': - PushWidePrimitive(); - break; - case '[': - case 'L': - PushObject(); - break; - default: - PushPrimitive(); - break; - } - } - - internal void PushWidePrimitive() - { - PushType(SimpleType.WidePrimitive); - } - - internal void PushPrimitive() - { - PushType(SimpleType.Primitive); - } - - internal void PushObject() - { - PushType(SimpleType.Object); - } - - // object reference or a subroutine return address - internal SimpleType PopObjectType() - { - SimpleType type = PopType(); - if (type.IsPrimitive) - { - throw new VerifyError("Expected object reference on stack"); - } - return type; - } - - internal void MultiPopAnyType(int count) - { - while (count-- != 0) - { - PopAnyType(); - } - } - - internal SimpleType PopAnyType() - { - if (stackSize == 0) - { - throw new VerifyError("Unable to pop operand off an empty stack"); - } - SimpleType type = stack[--stackSize]; - if (type.IsWidePrimitive) - { - stackEnd++; - } - return type; - } - - // NOTE this can *not* be used to pop double or long - internal SimpleType PopType() - { - SimpleType type = PopAnyType(); - if (type.IsWidePrimitive) - { - throw new VerifyError("Attempt to split long or double on the stack"); - } - return type; - } - - internal void PopPrimitive() - { - if (!PopType().IsPrimitive) - { - throw new VerifyError("Primitive type expected on stack"); - } - } - - internal void PopWidePrimitive() - { - SimpleType type = PopAnyType(); - if (type != SimpleType.WidePrimitive) - { - throw new VerifyError("Wide primitive type expected on stack"); - } - } - - internal void PopType(string signature) - { - switch (signature[0]) - { - case 'J': - case 'D': - PopWidePrimitive(); - break; - case '[': - case 'L': - PopObjectType(); - break; - default: - PopPrimitive(); - break; - } - } - - internal int GetStackHeight() - { - return stackSize; - } - - internal void PushType(SimpleType type) - { - if (type.IsWidePrimitive) - { - stackEnd--; - } - if (stackSize >= stackEnd) - { - throw new VerifyError("Stack overflow"); - } - StackCopyOnWrite(); - stack[stackSize++] = type; - } - - private void StackCopyOnWrite() - { - if ((flags & ShareFlags.Stack) != 0) - { - flags &= ~ShareFlags.Stack; - stack = (SimpleType[])stack.Clone(); - } - } - - private void LocalsCopyOnWrite() - { - if ((flags & ShareFlags.Locals) != 0) - { - flags &= ~ShareFlags.Locals; - locals = (SimpleType[])locals.Clone(); - } - } - - private void SubroutinesCopyOnWrite() - { - if ((flags & ShareFlags.Subroutines) != 0) - { - flags &= ~ShareFlags.Subroutines; - subroutines = CopySubroutines(subroutines); - } - } - - internal void DumpLocals() - { - Console.Write("// "); - string sep = ""; - for (int i = 0; i < locals.Length; i++) - { - Console.Write(sep); - Console.Write(locals[i]); - sep = ", "; - } - Console.WriteLine(); - } - - internal void DumpStack() - { - Console.Write("// "); - string sep = ""; - for (int i = 0; i < stackSize; i++) - { - Console.Write(sep); - Console.Write(stack[i]); - sep = ", "; - } - Console.WriteLine(); - } - - internal void DumpSubroutines() - { - Console.Write("// subs: "); - string sep = ""; - if (subroutines != null) - { - for (int i = 0; i < subroutines.Count; i++) - { - Console.Write(sep); - Console.Write(((Subroutine)subroutines[i]).SubroutineIndex); - sep = ", "; - } - } - Console.WriteLine(); - } - } - } - } + { + + private ClassFile.Method.Instruction[] codeCopy; + private int codeLength; + private InstructionFlags[] flags; + private readonly ClassFile.Method m; + private readonly JsrMethodAnalyzer ma; + + internal static void InlineJsrs(RuntimeClassLoader classLoader, RuntimeJavaMethod mw, ClassFile classFile, ClassFile.Method m) + { + JsrInliner inliner; + do + { + ClassFile.Method.Instruction[] codeCopy = (ClassFile.Method.Instruction[])m.Instructions.Clone(); + InstructionFlags[] flags = new InstructionFlags[codeCopy.Length]; + JsrMethodAnalyzer ma = new JsrMethodAnalyzer(mw, classFile, m, classLoader, flags); + inliner = new JsrInliner(codeCopy, flags, m, ma); + } while (inliner.InlineJsrs()); + } + + private JsrInliner(ClassFile.Method.Instruction[] codeCopy, InstructionFlags[] flags, ClassFile.Method m, JsrMethodAnalyzer ma) + { + this.codeCopy = codeCopy; + codeLength = codeCopy.Length; + this.flags = flags; + this.m = m; + this.ma = ma; + } + + private void Add(ClassFile.Method.Instruction instr) + { + if (codeLength == codeCopy.Length) + { + Array.Resize(ref codeCopy, codeLength * 2); + Array.Resize(ref flags, codeLength * 2); + } + codeCopy[codeLength++] = instr; + } + + private bool InlineJsrs() + { + bool hasJsrs = false; + List subs = new List(); + int len = codeLength; + for (int i = 0; i < len; i++) + { + // note that we're also (needlessly) processing the subroutines here, but that shouldn't be a problem (just a minor waste of cpu) + // because the code is unreachable anyway + if ((flags[i] & InstructionFlags.Reachable) != 0 && m.Instructions[i].NormalizedOpCode == NormalizedByteCode.__jsr) + { + int subroutineId = m.Instructions[i].TargetIndex; + codeCopy[i].PatchOpCode(NormalizedByteCode.__goto, codeLength); + SubroutineCall sub = new SubroutineCall(this, subroutineId, i + 1); + hasJsrs |= sub.InlineSubroutine(); + subs.Add(sub); + } + } + List exceptions = new List(m.ExceptionTable); + foreach (SubroutineCall sub in subs) + { + sub.DoExceptions(m.ExceptionTable, exceptions); + } + m.ExceptionTable = exceptions.ToArray(); + ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); + instr.SetTermNop(0xFFFF); + Add(instr); + Array.Resize(ref codeCopy, codeLength); + + m.Instructions = codeCopy; + return hasJsrs; + } + + private sealed class SubroutineCall + { + private readonly JsrInliner inliner; + private readonly int subroutineIndex; + private readonly int returnIndex; + private readonly int[] branchMap; + private readonly int baseIndex; + private int endIndex; + + internal SubroutineCall(JsrInliner inliner, int subroutineIndex, int returnIndex) + { + this.inliner = inliner; + this.subroutineIndex = subroutineIndex; + this.returnIndex = returnIndex; + baseIndex = inliner.codeLength; + branchMap = new int[inliner.m.Instructions.Length]; + for (int i = 0; i < branchMap.Length; i++) + { + branchMap[i] = i; + } + } + + private void Emit(ClassFile.Method.Instruction instr) + { + inliner.Add(instr); + } + + private void EmitGoto(int targetIndex) + { + ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); + instr.PatchOpCode(NormalizedByteCode.__goto, targetIndex); + instr.SetPC(-1); + Emit(instr); + } + + internal bool InlineSubroutine() + { + bool hasJsrs = false; + // start with a pre-amble to load a dummy return address on the stack and to branch to the subroutine + { + // TODO consider exception handling around these instructions + ClassFile.Method.Instruction instr = new ClassFile.Method.Instruction(); + instr.PatchOpCode(NormalizedByteCode.__aconst_null); + instr.SetPC(inliner.m.Instructions[subroutineIndex].PC); + Emit(instr); + EmitGoto(subroutineIndex); + } + + bool fallThru = false; + for (int instructionIndex = 0; instructionIndex < inliner.m.Instructions.Length; instructionIndex++) + { + if ((inliner.flags[instructionIndex] & InstructionFlags.Reachable) != 0 + && inliner.ma.IsSubroutineActive(instructionIndex, subroutineIndex)) + { + fallThru = false; + branchMap[instructionIndex] = inliner.codeLength; + switch (inliner.m.Instructions[instructionIndex].NormalizedOpCode) + { + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__return: + case NormalizedByteCode.__athrow: + case NormalizedByteCode.__goto: + Emit(inliner.m.Instructions[instructionIndex]); + break; + case NormalizedByteCode.__jsr: + hasJsrs = true; + goto default; + case NormalizedByteCode.__ret: + { + int subid = inliner.ma.GetLocalTypeWrapper(instructionIndex, inliner.m.Instructions[instructionIndex].TargetIndex).SubroutineIndex; + if (subid == subroutineIndex) + { + EmitGoto(returnIndex); + } + else + { + Emit(inliner.m.Instructions[instructionIndex]); + } + break; + } + default: + fallThru = true; + Emit(inliner.m.Instructions[instructionIndex]); + break; + } + } + else if (fallThru) + { + EmitGoto(instructionIndex); + } + } + + endIndex = inliner.codeLength; + DoFixups(); + return hasJsrs; + } + + private void DoFixups() + { + for (int instructionIndex = baseIndex; instructionIndex < endIndex; instructionIndex++) + { + switch (inliner.codeCopy[instructionIndex].NormalizedOpCode) + { + case NormalizedByteCode.__lookupswitch: + case NormalizedByteCode.__tableswitch: + { + int[] targets = new int[inliner.codeCopy[instructionIndex].SwitchEntryCount]; + for (int i = 0; i < targets.Length; i++) + { + targets[i] = branchMap[inliner.codeCopy[instructionIndex].GetSwitchTargetIndex(i)]; + } + inliner.codeCopy[instructionIndex].SetSwitchTargets(targets); + inliner.codeCopy[instructionIndex].DefaultTarget = branchMap[inliner.codeCopy[instructionIndex].DefaultTarget]; + } + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + case NormalizedByteCode.__ifnull: + case NormalizedByteCode.__ifnonnull: + case NormalizedByteCode.__goto: + case NormalizedByteCode.__jsr: + inliner.codeCopy[instructionIndex].TargetIndex = branchMap[inliner.codeCopy[instructionIndex].TargetIndex]; + break; + } + } + } + + private int MapExceptionStartEnd(int index) + { + while (branchMap[index] < baseIndex) + { + index++; + if (index == branchMap.Length) + { + return endIndex; + } + } + return branchMap[index]; + } + + internal void DoExceptions(ClassFile.Method.ExceptionTableEntry[] table, List newExceptions) + { + foreach (ClassFile.Method.ExceptionTableEntry entry in table) + { + int start = MapExceptionStartEnd(entry.startIndex); + int end = MapExceptionStartEnd(entry.endIndex); + if (start != end) + { + ClassFile.Method.ExceptionTableEntry newEntry = new ClassFile.Method.ExceptionTableEntry(start, end, branchMap[entry.handlerIndex], entry.catchType, entry.ordinal); + newExceptions.Add(newEntry); + } + } + } + } + + class SimpleType + { + internal static readonly SimpleType Invalid = null; + internal static readonly SimpleType Primitive = new SimpleType(); + internal static readonly SimpleType WidePrimitive = new SimpleType(); + internal static readonly SimpleType Object = new SimpleType(); + internal static readonly SimpleType[] EmptyArray = new SimpleType[0]; + + private SimpleType() { } + + internal bool IsPrimitive + { + get + { + return this == SimpleType.Primitive + || this == SimpleType.WidePrimitive; + } + } + + internal bool IsWidePrimitive + { + get + { + return this == SimpleType.WidePrimitive; + } + } + + private sealed class ReturnAddressType : SimpleType + { + internal readonly int subroutineIndex; + + internal ReturnAddressType(int subroutineIndex) + { + this.subroutineIndex = subroutineIndex; + } + } + + internal static SimpleType MakeRet(int subroutineIndex) + { + return new ReturnAddressType(subroutineIndex); + } + + internal static bool IsRet(SimpleType w) + { + return w is ReturnAddressType; + } + + internal int SubroutineIndex + { + get + { + return ((ReturnAddressType)this).subroutineIndex; + } + } + } + + sealed class JsrMethodAnalyzer + { + private ClassFile classFile; + private InstructionState[] state; + private List[] callsites; + private List[] returnsites; + + internal JsrMethodAnalyzer(RuntimeJavaMethod mw, ClassFile classFile, ClassFile.Method method, RuntimeClassLoader classLoader, InstructionFlags[] flags) + { + if (method.VerifyError != null) + { + throw new VerifyError(method.VerifyError); + } + + this.classFile = classFile; + state = new InstructionState[method.Instructions.Length]; + callsites = new List[method.Instructions.Length]; + returnsites = new List[method.Instructions.Length]; + + // because types have to have identity, the subroutine return address types are cached here + Dictionary returnAddressTypes = new Dictionary(); + + try + { + // ensure that exception blocks and handlers start and end at instruction boundaries + for (int i = 0; i < method.ExceptionTable.Length; i++) + { + int start = method.ExceptionTable[i].startIndex; + int end = method.ExceptionTable[i].endIndex; + int handler = method.ExceptionTable[i].handlerIndex; + if (start >= end || start == -1 || end == -1 || handler <= 0) + { + throw new IndexOutOfRangeException(); + } + } + } + catch (IndexOutOfRangeException) + { + throw new ClassFormatError(string.Format("Illegal exception table (class: {0}, method: {1}, signature: {2}", classFile.Name, method.Name, method.Signature)); + } + + // start by computing the initial state, the stack is empty and the locals contain the arguments + state[0] = new InstructionState(method.MaxLocals, method.MaxStack); + SimpleType thisType; + int firstNonArgLocalIndex = 0; + if (!method.IsStatic) + { + thisType = SimpleType.Object; + state[0].SetLocalType(firstNonArgLocalIndex++, thisType, -1); + } + else + { + thisType = null; + } + RuntimeJavaType[] argTypeWrappers = mw.GetParameters(); + for (int i = 0; i < argTypeWrappers.Length; i++) + { + RuntimeJavaType tw = argTypeWrappers[i]; + SimpleType type; + if (tw.IsWidePrimitive) + { + type = SimpleType.WidePrimitive; + } + else if (tw.IsPrimitive) + { + type = SimpleType.Primitive; + } + else + { + type = SimpleType.Object; + } + state[0].SetLocalType(firstNonArgLocalIndex++, type, -1); + if (type.IsWidePrimitive) + { + firstNonArgLocalIndex++; + } + } + SimpleType[] argumentsByLocalIndex = new SimpleType[firstNonArgLocalIndex]; + for (int i = 0; i < argumentsByLocalIndex.Length; i++) + { + argumentsByLocalIndex[i] = state[0].GetLocalTypeEx(i); + } + InstructionState s = state[0].Copy(); + bool done = false; + ClassFile.Method.Instruction[] instructions = method.Instructions; + while (!done) + { + done = true; + for (int i = 0; i < instructions.Length; i++) + { + if (state[i] != null && state[i].changed) + { + try + { + //Console.WriteLine(method.Instructions[i].PC + ": " + method.Instructions[i].OpCode.ToString()); + done = false; + state[i].changed = false; + // mark the exception handlers reachable from this instruction + for (int j = 0; j < method.ExceptionTable.Length; j++) + { + if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex) + { + MergeExceptionHandler(method.ExceptionTable[j].handlerIndex, state[i]); + } + } + state[i].CopyTo(s); + ClassFile.Method.Instruction instr = instructions[i]; + switch (instr.NormalizedOpCode) + { + case NormalizedByteCode.__aload: + { + SimpleType type = s.GetLocalType(instr.NormalizedArg1); + if (type == SimpleType.Invalid || type.IsPrimitive) + { + throw new VerifyError("Object reference expected"); + } + s.PushType(type); + break; + } + case NormalizedByteCode.__astore: + s.SetLocalType(instr.NormalizedArg1, s.PopObjectType(), i); + break; + case NormalizedByteCode.__aconst_null: + s.PushObject(); + break; + case NormalizedByteCode.__aaload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushObject(); + break; + case NormalizedByteCode.__aastore: + s.PopObjectType(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__baload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__bastore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__caload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__castore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__saload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__sastore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__iaload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__iastore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__laload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__lastore: + s.PopWidePrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__daload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__dastore: + s.PopWidePrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__faload: + s.PopPrimitive(); + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__fastore: + s.PopPrimitive(); + s.PopPrimitive(); + s.PopObjectType(); + break; + case NormalizedByteCode.__arraylength: + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__iconst: + s.PushPrimitive(); + break; + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + s.PopPrimitive(); + s.PopPrimitive(); + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifne: + s.PopPrimitive(); + break; + case NormalizedByteCode.__ifnonnull: + case NormalizedByteCode.__ifnull: + s.PopObjectType(); + break; + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + s.PopObjectType(); + s.PopObjectType(); + break; + case NormalizedByteCode.__getstatic: + s.PushType(GetFieldref(instr.Arg1).Signature); + break; + case NormalizedByteCode.__putstatic: + s.PopType(GetFieldref(instr.Arg1).Signature); + break; + case NormalizedByteCode.__getfield: + s.PopObjectType(); + s.PushType(GetFieldref(instr.Arg1).Signature); + break; + case NormalizedByteCode.__putfield: + s.PopType(GetFieldref(instr.Arg1).Signature); + s.PopObjectType(); + break; + case NormalizedByteCode.__ldc: + { + switch (GetConstantPoolConstantType(instr.Arg1)) + { + case ClassFile.ConstantType.Double: + s.PushWidePrimitive(); + break; + case ClassFile.ConstantType.Float: + s.PushPrimitive(); + break; + case ClassFile.ConstantType.Integer: + s.PushPrimitive(); + break; + case ClassFile.ConstantType.Long: + s.PushWidePrimitive(); + break; + case ClassFile.ConstantType.String: + case ClassFile.ConstantType.Class: + s.PushObject(); + break; + default: + // NOTE this is not a VerifyError, because it cannot happen (unless we have + // a bug in ClassFile.GetConstantPoolConstantType) + throw new InvalidOperationException(); + } + break; + } + case NormalizedByteCode.__invokevirtual: + case NormalizedByteCode.__invokespecial: + case NormalizedByteCode.__invokeinterface: + case NormalizedByteCode.__invokestatic: + { + ClassFile.ConstantPoolItemMI cpi = GetMethodref(instr.Arg1); + s.MultiPopAnyType(cpi.GetArgTypes().Length); + if (instr.NormalizedOpCode != NormalizedByteCode.__invokestatic) + { + s.PopType(); + } + string sig = cpi.Signature; + sig = sig.Substring(sig.IndexOf(')') + 1); + if (sig != "V") + { + s.PushType(sig); + } + break; + } + case NormalizedByteCode.__goto: + break; + case NormalizedByteCode.__istore: + s.PopPrimitive(); + s.SetLocalPrimitive(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__iload: + s.PushPrimitive(); + break; + case NormalizedByteCode.__ineg: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__iadd: + case NormalizedByteCode.__isub: + case NormalizedByteCode.__imul: + case NormalizedByteCode.__idiv: + case NormalizedByteCode.__irem: + case NormalizedByteCode.__iand: + case NormalizedByteCode.__ior: + case NormalizedByteCode.__ixor: + case NormalizedByteCode.__ishl: + case NormalizedByteCode.__ishr: + case NormalizedByteCode.__iushr: + s.PopPrimitive(); + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__lneg: + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__ladd: + case NormalizedByteCode.__lsub: + case NormalizedByteCode.__lmul: + case NormalizedByteCode.__ldiv: + case NormalizedByteCode.__lrem: + case NormalizedByteCode.__land: + case NormalizedByteCode.__lor: + case NormalizedByteCode.__lxor: + s.PopWidePrimitive(); + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__lshl: + case NormalizedByteCode.__lshr: + case NormalizedByteCode.__lushr: + s.PopPrimitive(); + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__fneg: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__fadd: + case NormalizedByteCode.__fsub: + case NormalizedByteCode.__fmul: + case NormalizedByteCode.__fdiv: + case NormalizedByteCode.__frem: + s.PopPrimitive(); + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__dneg: + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__dadd: + case NormalizedByteCode.__dsub: + case NormalizedByteCode.__dmul: + case NormalizedByteCode.__ddiv: + case NormalizedByteCode.__drem: + s.PopWidePrimitive(); + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__new: + s.PushObject(); + break; + case NormalizedByteCode.__multianewarray: + { + if (instr.Arg2 < 1) + { + throw new VerifyError("Illegal dimension argument"); + } + for (int j = 0; j < instr.Arg2; j++) + { + s.PopPrimitive(); + } + s.PushObject(); + break; + } + case NormalizedByteCode.__anewarray: + s.PopPrimitive(); + s.PushObject(); + break; + case NormalizedByteCode.__newarray: + s.PopPrimitive(); + s.PushObject(); + break; + case NormalizedByteCode.__swap: + { + SimpleType t1 = s.PopType(); + SimpleType t2 = s.PopType(); + s.PushType(t1); + s.PushType(t2); + break; + } + case NormalizedByteCode.__dup: + { + SimpleType t = s.PopType(); + s.PushType(t); + s.PushType(t); + break; + } + case NormalizedByteCode.__dup2: + { + SimpleType t = s.PopAnyType(); + if (t.IsWidePrimitive) + { + s.PushType(t); + s.PushType(t); + } + else + { + SimpleType t2 = s.PopType(); + s.PushType(t2); + s.PushType(t); + s.PushType(t2); + s.PushType(t); + } + break; + } + case NormalizedByteCode.__dup_x1: + { + SimpleType value1 = s.PopType(); + SimpleType value2 = s.PopType(); + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + break; + } + case NormalizedByteCode.__dup2_x1: + { + SimpleType value1 = s.PopAnyType(); + if (value1.IsWidePrimitive) + { + SimpleType value2 = s.PopType(); + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + } + else + { + SimpleType value2 = s.PopType(); + SimpleType value3 = s.PopType(); + s.PushType(value2); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + break; + } + case NormalizedByteCode.__dup_x2: + { + SimpleType value1 = s.PopType(); + SimpleType value2 = s.PopAnyType(); + if (value2.IsWidePrimitive) + { + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + } + else + { + SimpleType value3 = s.PopType(); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + break; + } + case NormalizedByteCode.__dup2_x2: + { + SimpleType value1 = s.PopAnyType(); + if (value1.IsWidePrimitive) + { + SimpleType value2 = s.PopAnyType(); + if (value2.IsWidePrimitive) + { + // Form 4 + s.PushType(value1); + s.PushType(value2); + s.PushType(value1); + } + else + { + // Form 2 + SimpleType value3 = s.PopType(); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + } + else + { + SimpleType value2 = s.PopType(); + SimpleType value3 = s.PopAnyType(); + if (value3.IsWidePrimitive) + { + // Form 3 + s.PushType(value2); + s.PushType(value1); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + else + { + // Form 4 + SimpleType value4 = s.PopType(); + s.PushType(value2); + s.PushType(value1); + s.PushType(value4); + s.PushType(value3); + s.PushType(value2); + s.PushType(value1); + } + } + break; + } + case NormalizedByteCode.__pop: + s.PopType(); + break; + case NormalizedByteCode.__pop2: + { + SimpleType type = s.PopAnyType(); + if (!type.IsWidePrimitive) + { + s.PopType(); + } + break; + } + case NormalizedByteCode.__monitorenter: + case NormalizedByteCode.__monitorexit: + s.PopObjectType(); + break; + case NormalizedByteCode.__return: + break; + case NormalizedByteCode.__areturn: + s.PopObjectType(); + break; + case NormalizedByteCode.__ireturn: + s.PopPrimitive(); + break; + case NormalizedByteCode.__lreturn: + s.PopWidePrimitive(); + break; + case NormalizedByteCode.__freturn: + s.PopPrimitive(); + break; + case NormalizedByteCode.__dreturn: + s.PopWidePrimitive(); + break; + case NormalizedByteCode.__fload: + s.PushPrimitive(); + break; + case NormalizedByteCode.__fstore: + s.PopPrimitive(); + s.SetLocalPrimitive(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__dload: + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__dstore: + s.PopWidePrimitive(); + s.SetLocalWidePrimitive(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__lload: + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__lstore: + s.PopWidePrimitive(); + s.SetLocalWidePrimitive(instr.NormalizedArg1, i); + break; + case NormalizedByteCode.__lconst_0: + case NormalizedByteCode.__lconst_1: + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__fconst_0: + case NormalizedByteCode.__fconst_1: + case NormalizedByteCode.__fconst_2: + s.PushPrimitive(); + break; + case NormalizedByteCode.__dconst_0: + case NormalizedByteCode.__dconst_1: + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__lcmp: + s.PopWidePrimitive(); + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__fcmpl: + case NormalizedByteCode.__fcmpg: + s.PopPrimitive(); + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__dcmpl: + case NormalizedByteCode.__dcmpg: + s.PopWidePrimitive(); + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__checkcast: + s.PopObjectType(); + s.PushObject(); + break; + case NormalizedByteCode.__instanceof: + s.PopObjectType(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__iinc: + break; + case NormalizedByteCode.__athrow: + s.PopObjectType(); + break; + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + s.PopPrimitive(); + break; + case NormalizedByteCode.__i2b: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__i2c: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__i2s: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__i2l: + s.PopPrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__i2f: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__i2d: + s.PopPrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__l2i: + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__l2f: + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__l2d: + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__f2i: + s.PopPrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__f2l: + s.PopPrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__f2d: + s.PopPrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__d2i: + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__d2f: + s.PopWidePrimitive(); + s.PushPrimitive(); + break; + case NormalizedByteCode.__d2l: + s.PopWidePrimitive(); + s.PushWidePrimitive(); + break; + case NormalizedByteCode.__jsr: + // TODO make sure we're not calling a subroutine we're already in + break; + case NormalizedByteCode.__ret: + { + // TODO if we're returning from a higher level subroutine, invalidate + // all the intermediate return addresses + int subroutineIndex = s.GetLocalRet(instr.Arg1); + s.CheckSubroutineActive(subroutineIndex); + break; + } + case NormalizedByteCode.__nop: + if (i + 1 == instructions.Length) + { + throw new VerifyError("Falling off the end of the code"); + } + break; + case NormalizedByteCode.__invokedynamic: + // it is impossible to have a valid invokedynamic in a pre-7.0 class file + throw new VerifyError("Illegal type in constant pool"); + default: + throw new NotImplementedException(instr.NormalizedOpCode.ToString()); + } + if (s.GetStackHeight() > method.MaxStack) + { + throw new VerifyError("Stack size too large"); + } + for (int j = 0; j < method.ExceptionTable.Length; j++) + { + if (method.ExceptionTable[j].endIndex == i + 1) + { + MergeExceptionHandler(method.ExceptionTable[j].handlerIndex, s); + } + } + try + { + // another big switch to handle the opcode targets + switch (instr.NormalizedOpCode) + { + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + for (int j = 0; j < instr.SwitchEntryCount; j++) + { + state[instr.GetSwitchTargetIndex(j)] += s; + } + state[instr.DefaultTarget] += s; + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + case NormalizedByteCode.__ifnull: + case NormalizedByteCode.__ifnonnull: + state[i + 1] += s; + state[instr.TargetIndex] += s; + break; + case NormalizedByteCode.__goto: + state[instr.TargetIndex] += s; + break; + case NormalizedByteCode.__jsr: + { + int index = instr.TargetIndex; + s.SetSubroutineId(index); + SimpleType retAddressType; + if (!returnAddressTypes.TryGetValue(index, out retAddressType)) + { + retAddressType = SimpleType.MakeRet(index); + returnAddressTypes[index] = retAddressType; + } + s.PushType(retAddressType); + state[index] += s; + List returns = GetReturnSites(i); + if (returns != null) + { + foreach (int returnIndex in returns) + { + state[i + 1] = InstructionState.MergeSubroutineReturn(state[i + 1], s, state[returnIndex], state[returnIndex].GetLocalsModified(index)); + } + } + AddCallSite(index, i); + break; + } + case NormalizedByteCode.__ret: + { + // HACK if the ret is processed before all of the jsr instructions to this subroutine + // we wouldn't be able to properly merge, so that is why we track the number of callsites + // for each subroutine instruction (see Instruction.AddCallSite()) + int subroutineIndex = s.GetLocalRet(instr.Arg1); + int[] cs = GetCallSites(subroutineIndex); + bool[] locals_modified = s.GetLocalsModified(subroutineIndex); + for (int j = 0; j < cs.Length; j++) + { + AddReturnSite(cs[j], i); + state[cs[j] + 1] = InstructionState.MergeSubroutineReturn(state[cs[j] + 1], state[cs[j]], s, locals_modified); + } + break; + } + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__return: + case NormalizedByteCode.__athrow: + break; + default: + state[i + 1] += s; + break; + } + } + catch (IndexOutOfRangeException) + { + // we're going to assume that this always means that we have an invalid branch target + // NOTE because PcIndexMap returns -1 for illegal PCs (in the middle of an instruction) and + // we always use that value as an index into the state array, any invalid PC will result + // in an IndexOutOfRangeException + throw new VerifyError("Illegal target of jump or branch"); + } + } + catch (VerifyError x) + { + string opcode = instructions[i].NormalizedOpCode.ToString(); + if (opcode.StartsWith("__")) + { + opcode = opcode.Substring(2); + } + throw new VerifyError(string.Format("{5} (class: {0}, method: {1}, signature: {2}, offset: {3}, instruction: {4})", + classFile.Name, method.Name, method.Signature, instructions[i].PC, opcode, x.Message), x); + } + } + } + } + + // Now we do another pass to compute reachability + done = false; + flags[0] |= InstructionFlags.Reachable; + while (!done) + { + done = true; + bool didJsrOrRet = false; + for (int i = 0; i < instructions.Length; i++) + { + if ((flags[i] & (InstructionFlags.Reachable | InstructionFlags.Processed)) == InstructionFlags.Reachable) + { + done = false; + flags[i] |= InstructionFlags.Processed; + // mark the exception handlers reachable from this instruction + for (int j = 0; j < method.ExceptionTable.Length; j++) + { + if (method.ExceptionTable[j].startIndex <= i && i < method.ExceptionTable[j].endIndex) + { + flags[method.ExceptionTable[j].handlerIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + } + } + // mark the successor instructions + switch (instructions[i].NormalizedOpCode) + { + case NormalizedByteCode.__tableswitch: + case NormalizedByteCode.__lookupswitch: + { + bool hasbackbranch = false; + for (int j = 0; j < instructions[i].SwitchEntryCount; j++) + { + hasbackbranch |= instructions[i].GetSwitchTargetIndex(j) < i; + flags[instructions[i].GetSwitchTargetIndex(j)] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + } + hasbackbranch |= instructions[i].DefaultTarget < i; + flags[instructions[i].DefaultTarget] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + break; + } + case NormalizedByteCode.__goto: + flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + break; + case NormalizedByteCode.__ifeq: + case NormalizedByteCode.__ifne: + case NormalizedByteCode.__iflt: + case NormalizedByteCode.__ifge: + case NormalizedByteCode.__ifgt: + case NormalizedByteCode.__ifle: + case NormalizedByteCode.__if_icmpeq: + case NormalizedByteCode.__if_icmpne: + case NormalizedByteCode.__if_icmplt: + case NormalizedByteCode.__if_icmpge: + case NormalizedByteCode.__if_icmpgt: + case NormalizedByteCode.__if_icmple: + case NormalizedByteCode.__if_acmpeq: + case NormalizedByteCode.__if_acmpne: + case NormalizedByteCode.__ifnull: + case NormalizedByteCode.__ifnonnull: + flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + flags[i + 1] |= InstructionFlags.Reachable; + break; + case NormalizedByteCode.__jsr: + flags[instructions[i].TargetIndex] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + // Note that we don't mark the next instruction as reachable, + // because that depends on the corresponding ret actually being + // reachable. We handle this in the loop below. + didJsrOrRet = true; + break; + case NormalizedByteCode.__ret: + // Note that we can't handle ret here, because we might encounter the ret + // before having seen all the corresponding jsr instructions, so we can't + // update all the call sites. + // We handle ret in the loop below. + didJsrOrRet = true; + break; + case NormalizedByteCode.__ireturn: + case NormalizedByteCode.__lreturn: + case NormalizedByteCode.__freturn: + case NormalizedByteCode.__dreturn: + case NormalizedByteCode.__areturn: + case NormalizedByteCode.__return: + case NormalizedByteCode.__athrow: + break; + default: + flags[i + 1] |= InstructionFlags.Reachable; + break; + } + } + } + if (didJsrOrRet) + { + for (int i = 0; i < instructions.Length; i++) + { + if (instructions[i].NormalizedOpCode == NormalizedByteCode.__ret + && (flags[i] & InstructionFlags.Reachable) != 0) + { + int subroutineIndex = state[i].GetLocalRet(instructions[i].Arg1); + int[] cs = GetCallSites(subroutineIndex); + for (int j = 0; j < cs.Length; j++) + { + if ((flags[cs[j]] & InstructionFlags.Reachable) != 0) + { + flags[cs[j] + 1] |= InstructionFlags.Reachable | InstructionFlags.BranchTarget; + } + } + } + } + } + } + } + + private void MergeExceptionHandler(int handlerIndex, InstructionState curr) + { + // NOTE this used to be CopyLocalsAndSubroutines, but it doesn't (always) make + // sense to copy the subroutine state + // TODO figure out if there are circumstances under which it does make sense + // to copy the active subroutine state + // UPDATE subroutines must be copied as well, but I think I now have a better + // understanding of subroutine merges, so the problems that triggered the previous + // change here hopefully won't arise anymore + InstructionState ex = curr.CopyLocalsAndSubroutines(); + ex.PushObject(); + state[handlerIndex] += ex; + } + + ClassFile.ConstantPoolItemMI GetMethodref(int index) + { + try + { + var item = classFile.GetMethodref(new MethodrefConstantHandle(checked((ushort)index))); + if (item != null) + return item; + } + catch (OverflowException) + { + // constant pool index isn't ushort + } + catch (InvalidCastException) + { + + } + catch (IndexOutOfRangeException) + { + + } + + throw new VerifyError("Illegal constant pool index"); + } + + ClassFile.ConstantPoolItemFieldref GetFieldref(int index) + { + try + { + var item = classFile.GetFieldref(new FieldrefConstantHandle(checked((ushort)index))); + if (item != null) + return item; + } + catch (OverflowException) + { + // constant pool index isn't ushort + } + catch (InvalidCastException) + { + // constant pool index isn't ushort + } + catch (IndexOutOfRangeException) + { + + } + + throw new VerifyError("Illegal constant pool index"); + } + + ClassFile.ConstantType GetConstantPoolConstantType(int index) + { + try + { + return classFile.GetConstantPoolConstantType(new ConstantHandle(ConstantKind.Unknown, checked((ushort)index))); + } + catch (OverflowException) + { + // constant pool index isn't ushort + } + catch (InvalidCastException) + { + // constant pool index isn't ushort + } + catch (IndexOutOfRangeException) + { + // constant pool index out of range + } + catch (InvalidOperationException) + { + // specified constant pool entry doesn't contain a constant + } + catch (NullReferenceException) + { + // specified constant pool entry is empty (entry 0 or the filler following a wide entry) + } + + throw new VerifyError("Illegal constant pool index"); + } + + private void AddReturnSite(int callSiteIndex, int returnSiteIndex) + { + if (returnsites[callSiteIndex] == null) + { + returnsites[callSiteIndex] = new List(); + } + List l = returnsites[callSiteIndex]; + if (l.IndexOf(returnSiteIndex) == -1) + { + state[callSiteIndex].changed = true; + l.Add(returnSiteIndex); + } + } + + private List GetReturnSites(int callSiteIndex) + { + return returnsites[callSiteIndex]; + } + + private void AddCallSite(int subroutineIndex, int callSiteIndex) + { + if (callsites[subroutineIndex] == null) + { + callsites[subroutineIndex] = new List(); + } + List l = callsites[subroutineIndex]; + if (l.IndexOf(callSiteIndex) == -1) + { + l.Add(callSiteIndex); + state[subroutineIndex].AddCallSite(); + } + } + + private int[] GetCallSites(int subroutineIndex) + { + return callsites[subroutineIndex].ToArray(); + } + + internal SimpleType GetLocalTypeWrapper(int index, int local) + { + return state[index].GetLocalTypeEx(local); + } + + internal bool IsSubroutineActive(int instructionIndex, int subroutineIndex) + { + return state[instructionIndex].IsSubroutineActive(subroutineIndex); + } + + sealed class Subroutine + { + private int subroutineIndex; + private bool[] localsModified; + + private Subroutine(int subroutineIndex, bool[] localsModified) + { + this.subroutineIndex = subroutineIndex; + this.localsModified = localsModified; + } + + internal Subroutine(int subroutineIndex, int maxLocals) + { + this.subroutineIndex = subroutineIndex; + localsModified = new bool[maxLocals]; + } + + internal int SubroutineIndex + { + get + { + return subroutineIndex; + } + } + + internal bool[] LocalsModified + { + get + { + return localsModified; + } + } + + internal void SetLocalModified(int local) + { + localsModified[local] = true; + } + + internal Subroutine Copy() + { + return new Subroutine(subroutineIndex, (bool[])localsModified.Clone()); + } + } + + sealed class InstructionState + { + private SimpleType[] stack; + private int stackSize; + private int stackEnd; + private SimpleType[] locals; + private List subroutines; + private int callsites; + internal bool changed = true; + private enum ShareFlags : byte + { + None = 0, + Stack = 1, + Locals = 2, + Subroutines = 4, + All = Stack | Locals | Subroutines + } + private ShareFlags flags; + + private InstructionState(SimpleType[] stack, int stackSize, int stackEnd, SimpleType[] locals, List subroutines, int callsites) + { + this.flags = ShareFlags.All; + this.stack = stack; + this.stackSize = stackSize; + this.stackEnd = stackEnd; + this.locals = locals; + this.subroutines = subroutines; + this.callsites = callsites; + } + + internal InstructionState(int maxLocals, int maxStack) + { + this.flags = ShareFlags.None; + this.stack = new SimpleType[maxStack]; + this.stackEnd = maxStack; + this.locals = new SimpleType[maxLocals]; + } + + internal InstructionState Copy() + { + return new InstructionState(stack, stackSize, stackEnd, locals, subroutines, callsites); + } + + internal void CopyTo(InstructionState target) + { + target.flags = ShareFlags.All; + target.stack = stack; + target.stackSize = stackSize; + target.stackEnd = stackEnd; + target.locals = locals; + target.subroutines = subroutines; + target.callsites = callsites; + target.changed = true; + } + + internal InstructionState CopyLocalsAndSubroutines() + { + InstructionState copy = new InstructionState(new SimpleType[stack.Length], 0, stack.Length, locals, subroutines, callsites); + copy.flags &= ~ShareFlags.Stack; + return copy; + } + + private static List CopySubroutines(List l) + { + if (l == null) + { + return null; + } + List n = new List(l.Count); + foreach (Subroutine s in l) + { + n.Add(s.Copy()); + } + return n; + } + + private void MergeSubroutineHelper(InstructionState s2) + { + if (subroutines == null || s2.subroutines == null) + { + if (subroutines != null) + { + subroutines = null; + changed = true; + } + } + else + { + SubroutinesCopyOnWrite(); + List ss1 = subroutines; + subroutines = new List(); + foreach (Subroutine ss2 in s2.subroutines) + { + foreach (Subroutine ss in ss1) + { + if (ss.SubroutineIndex == ss2.SubroutineIndex) + { + subroutines.Add(ss); + for (int i = 0; i < ss.LocalsModified.Length; i++) + { + if (ss2.LocalsModified[i] && !ss.LocalsModified[i]) + { + ss.LocalsModified[i] = true; + changed = true; + } + } + } + } + } + if (ss1.Count != subroutines.Count) + { + changed = true; + } + } + + if (s2.callsites > callsites) + { + //Console.WriteLine("s2.callsites = {0}, callsites = {1}", s2.callsites, callsites); + callsites = s2.callsites; + changed = true; + } + } + + internal static InstructionState MergeSubroutineReturn(InstructionState jsrSuccessor, InstructionState jsr, InstructionState ret, bool[] locals_modified) + { + InstructionState next = ret.Copy(); + next.LocalsCopyOnWrite(); + for (int i = 0; i < locals_modified.Length; i++) + { + if (!locals_modified[i]) + { + next.locals[i] = jsr.locals[i]; + } + } + next.flags |= ShareFlags.Subroutines; + next.subroutines = jsr.subroutines; + next.callsites = jsr.callsites; + return jsrSuccessor + next; + } + + public static InstructionState operator +(InstructionState s1, InstructionState s2) + { + if (s1 == null) + { + return s2.Copy(); + } + if (s1.stackSize != s2.stackSize || s1.stackEnd != s2.stackEnd) + { + throw new VerifyError(string.Format("Inconsistent stack height: {0} != {1}", + s1.stackSize + s1.stack.Length - s1.stackEnd, + s2.stackSize + s2.stack.Length - s2.stackEnd)); + } + InstructionState s = s1.Copy(); + s.changed = s1.changed; + for (int i = 0; i < s.stackSize; i++) + { + SimpleType type = s.stack[i]; + SimpleType type2 = s2.stack[i]; + if (type == type2) + { + // perfect match, nothing to do + } + else if (!type.IsPrimitive) + { + SimpleType baseType = InstructionState.FindCommonBaseType(type, type2); + if (baseType == SimpleType.Invalid) + { + if (SimpleType.IsRet(type) && SimpleType.IsRet(type2)) + { + // if we never return from a subroutine, it is legal to merge to subroutine flows + // (this is from the Mauve test subr.pass.mergeok) + } + else + { + throw new VerifyError(string.Format("cannot merge {0} and {1}", type, type2)); + } + } + if (type != baseType) + { + s.StackCopyOnWrite(); + s.stack[i] = baseType; + s.changed = true; + } + } + else + { + throw new VerifyError(string.Format("cannot merge {0} and {1}", type, type2)); + } + } + for (int i = 0; i < s.locals.Length; i++) + { + SimpleType type = s.locals[i]; + SimpleType type2 = s2.locals[i]; + SimpleType baseType = InstructionState.FindCommonBaseType(type, type2); + if (type != baseType) + { + s.LocalsCopyOnWrite(); + s.locals[i] = baseType; + s.changed = true; + } + } + s.MergeSubroutineHelper(s2); + return s; + } + + internal void AddCallSite() + { + callsites++; + changed = true; + } + + internal void SetSubroutineId(int subroutineIndex) + { + SubroutinesCopyOnWrite(); + if (subroutines == null) + { + subroutines = new List(); + } + else + { + foreach (Subroutine s in subroutines) + { + if (s.SubroutineIndex == subroutineIndex) + { + // subroutines cannot recursivly call themselves + throw new VerifyError("subroutines cannot recurse"); + } + } + } + subroutines.Add(new Subroutine(subroutineIndex, locals.Length)); + } + + internal bool[] GetLocalsModified(int subroutineIndex) + { + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + if (s.SubroutineIndex == subroutineIndex) + { + return s.LocalsModified; + } + } + } + throw new VerifyError("return from wrong subroutine"); + } + + internal bool IsSubroutineActive(int subroutineIndex) + { + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + if (s.SubroutineIndex == subroutineIndex) + { + return true; + } + } + } + return false; + } + + internal void CheckSubroutineActive(int subroutineIndex) + { + if (!IsSubroutineActive(subroutineIndex)) + { + throw new VerifyError("inactive subroutine"); + } + } + + internal static SimpleType FindCommonBaseType(SimpleType type1, SimpleType type2) + { + if (type1 == type2) + { + return type1; + } + if (type1 == SimpleType.Object) + { + return type2; + } + if (type2 == SimpleType.Object) + { + return type1; + } + if (type1 == SimpleType.Invalid || type2 == SimpleType.Invalid) + { + return SimpleType.Invalid; + } + if (type1.IsPrimitive || type2.IsPrimitive) + { + return SimpleType.Invalid; + } + if (SimpleType.IsRet(type1) || SimpleType.IsRet(type2)) + { + return SimpleType.Invalid; + } + return SimpleType.Object; + } + + private void SetLocal1(int index, SimpleType type) + { + try + { + LocalsCopyOnWrite(); + SubroutinesCopyOnWrite(); + if (index > 0 && locals[index - 1] != SimpleType.Invalid && locals[index - 1].IsWidePrimitive) + { + locals[index - 1] = SimpleType.Invalid; + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + s.SetLocalModified(index - 1); + } + } + } + locals[index] = type; + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + s.SetLocalModified(index); + } + } + } + catch (IndexOutOfRangeException) + { + throw new VerifyError("Illegal local variable number"); + } + } + + private void SetLocal2(int index, SimpleType type) + { + try + { + LocalsCopyOnWrite(); + SubroutinesCopyOnWrite(); + if (index > 0 && locals[index - 1] != SimpleType.Invalid && locals[index - 1].IsWidePrimitive) + { + locals[index - 1] = SimpleType.Invalid; + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + s.SetLocalModified(index - 1); + } + } + } + locals[index] = type; + locals[index + 1] = SimpleType.Invalid; + if (subroutines != null) + { + foreach (Subroutine s in subroutines) + { + s.SetLocalModified(index); + s.SetLocalModified(index + 1); + } + } + } + catch (IndexOutOfRangeException) + { + throw new VerifyError("Illegal local variable number"); + } + } + + internal void SetLocalPrimitive(int index, int instructionIndex) + { + SetLocal1(index, SimpleType.Primitive); + } + + internal void SetLocalWidePrimitive(int index, int instructionIndex) + { + SetLocal2(index, SimpleType.WidePrimitive); + } + + internal SimpleType GetLocalType(int index) + { + try + { + return locals[index]; + } + catch (IndexOutOfRangeException) + { + throw new VerifyError("Illegal local variable number"); + } + } + + // this is used by the compiler (indirectly, through MethodAnalyzer.GetLocalTypeWrapper), + // we've already verified the code so we know we won't run outside the array boundary, + // and we don't need to record the fact that we're reading the local. + internal SimpleType GetLocalTypeEx(int index) + { + return locals[index]; + } + + internal int GetLocalRet(int index) + { + SimpleType type = GetLocalType(index); + if (SimpleType.IsRet(type)) + { + return type.SubroutineIndex; + } + throw new VerifyError("incorrect local type, not ret"); + } + + internal void SetLocalType(int index, SimpleType type, int instructionIndex) + { + if (type.IsWidePrimitive) + { + SetLocalWidePrimitive(index, instructionIndex); + } + else + { + SetLocal1(index, type); + } + } + + internal void PushType(string signature) + { + switch (signature[0]) + { + case 'J': + case 'D': + PushWidePrimitive(); + break; + case '[': + case 'L': + PushObject(); + break; + default: + PushPrimitive(); + break; + } + } + + internal void PushWidePrimitive() + { + PushType(SimpleType.WidePrimitive); + } + + internal void PushPrimitive() + { + PushType(SimpleType.Primitive); + } + + internal void PushObject() + { + PushType(SimpleType.Object); + } + + // object reference or a subroutine return address + internal SimpleType PopObjectType() + { + SimpleType type = PopType(); + if (type.IsPrimitive) + { + throw new VerifyError("Expected object reference on stack"); + } + return type; + } + + internal void MultiPopAnyType(int count) + { + while (count-- != 0) + { + PopAnyType(); + } + } + + internal SimpleType PopAnyType() + { + if (stackSize == 0) + { + throw new VerifyError("Unable to pop operand off an empty stack"); + } + SimpleType type = stack[--stackSize]; + if (type.IsWidePrimitive) + { + stackEnd++; + } + return type; + } + + // NOTE this can *not* be used to pop double or long + internal SimpleType PopType() + { + SimpleType type = PopAnyType(); + if (type.IsWidePrimitive) + { + throw new VerifyError("Attempt to split long or double on the stack"); + } + return type; + } + + internal void PopPrimitive() + { + if (!PopType().IsPrimitive) + { + throw new VerifyError("Primitive type expected on stack"); + } + } + + internal void PopWidePrimitive() + { + SimpleType type = PopAnyType(); + if (type != SimpleType.WidePrimitive) + { + throw new VerifyError("Wide primitive type expected on stack"); + } + } + + internal void PopType(string signature) + { + switch (signature[0]) + { + case 'J': + case 'D': + PopWidePrimitive(); + break; + case '[': + case 'L': + PopObjectType(); + break; + default: + PopPrimitive(); + break; + } + } + + internal int GetStackHeight() + { + return stackSize; + } + + internal void PushType(SimpleType type) + { + if (type.IsWidePrimitive) + { + stackEnd--; + } + if (stackSize >= stackEnd) + { + throw new VerifyError("Stack overflow"); + } + StackCopyOnWrite(); + stack[stackSize++] = type; + } + + private void StackCopyOnWrite() + { + if ((flags & ShareFlags.Stack) != 0) + { + flags &= ~ShareFlags.Stack; + stack = (SimpleType[])stack.Clone(); + } + } + + private void LocalsCopyOnWrite() + { + if ((flags & ShareFlags.Locals) != 0) + { + flags &= ~ShareFlags.Locals; + locals = (SimpleType[])locals.Clone(); + } + } + + private void SubroutinesCopyOnWrite() + { + if ((flags & ShareFlags.Subroutines) != 0) + { + flags &= ~ShareFlags.Subroutines; + subroutines = CopySubroutines(subroutines); + } + } + + internal void DumpLocals() + { + Console.Write("// "); + string sep = ""; + for (int i = 0; i < locals.Length; i++) + { + Console.Write(sep); + Console.Write(locals[i]); + sep = ", "; + } + Console.WriteLine(); + } + + internal void DumpStack() + { + Console.Write("// "); + string sep = ""; + for (int i = 0; i < stackSize; i++) + { + Console.Write(sep); + Console.Write(stack[i]); + sep = ", "; + } + Console.WriteLine(); + } + + internal void DumpSubroutines() + { + Console.Write("// subs: "); + string sep = ""; + if (subroutines != null) + { + for (int i = 0; i < subroutines.Count; i++) + { + Console.Write(sep); + Console.Write(((Subroutine)subroutines[i]).SubroutineIndex); + sep = ", "; + } + } + Console.WriteLine(); + } + } + } + } } diff --git a/src/IKVM.Runtime/LambdaMetafactory.cs b/src/IKVM.Runtime/LambdaMetafactory.cs index f30ae1b466..c02667c77f 100644 --- a/src/IKVM.Runtime/LambdaMetafactory.cs +++ b/src/IKVM.Runtime/LambdaMetafactory.cs @@ -81,15 +81,15 @@ private bool EmitImpl(RuntimeByteCodeJavaType.FinishContext context, ClassFile c ClassFile.ConstantPoolItemMethodType[] bridges = null; if (bsm.ArgumentCount > 3) { - AltFlags flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3)); + AltFlags flags = (AltFlags)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)bsm.GetArgument(3)); serializable = (flags & AltFlags.Serializable) != 0; int argpos = 4; if ((flags & AltFlags.Markers) != 0) { - markers = new RuntimeJavaType[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; + markers = new RuntimeJavaType[classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)bsm.GetArgument(argpos++))]; for (int i = 0; i < markers.Length; i++) { - if ((markers[i] = classFile.GetConstantPoolClassType(bsm.GetArgument(argpos++))).IsUnloadable) + if ((markers[i] = classFile.GetConstantPoolClassType((ClassConstantHandle)bsm.GetArgument(argpos++))).IsUnloadable) { Fail("unloadable marker"); return false; @@ -98,10 +98,10 @@ private bool EmitImpl(RuntimeByteCodeJavaType.FinishContext context, ClassFile c } if ((flags & AltFlags.Bridges) != 0) { - bridges = new ClassFile.ConstantPoolItemMethodType[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; + bridges = new ClassFile.ConstantPoolItemMethodType[classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)bsm.GetArgument(argpos++))]; for (int i = 0; i < bridges.Length; i++) { - bridges[i] = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(argpos++)); + bridges[i] = classFile.GetConstantPoolConstantMethodType((MethodTypeConstantHandle)bsm.GetArgument(argpos++)); if (HasUnloadable(bridges[i])) { Fail("unloadable bridge"); @@ -110,9 +110,10 @@ private bool EmitImpl(RuntimeByteCodeJavaType.FinishContext context, ClassFile c } } } - ClassFile.ConstantPoolItemMethodType samMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(0)); - ClassFile.ConstantPoolItemMethodHandle implMethod = classFile.GetConstantPoolConstantMethodHandle(bsm.GetArgument(1)); - ClassFile.ConstantPoolItemMethodType instantiatedMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(2)); + + var samMethodType = classFile.GetConstantPoolConstantMethodType((MethodTypeConstantHandle)bsm.GetArgument(0)); + var implMethod = classFile.GetConstantPoolConstantMethodHandle((MethodHandleConstantHandle)bsm.GetArgument(1)); + var instantiatedMethodType = classFile.GetConstantPoolConstantMethodType((MethodTypeConstantHandle)bsm.GetArgument(2)); if (HasUnloadable(samMethodType) || HasUnloadable((ClassFile.ConstantPoolItemMI)implMethod.MemberConstantPoolItem) || HasUnloadable(instantiatedMethodType)) @@ -120,6 +121,7 @@ private bool EmitImpl(RuntimeByteCodeJavaType.FinishContext context, ClassFile c Fail("bsm args has unloadable"); return false; } + RuntimeJavaType interfaceType = cpi.GetRetType(); RuntimeJavaMethod[] methodList; if (!CheckSupportedInterfaces(context.TypeWrapper, interfaceType, markers, bridges, out methodList)) @@ -256,9 +258,7 @@ private static RuntimeJavaType[] GetImplParameters(ClassFile.ConstantPoolItemMet private static RuntimeJavaType GetImplReturnType(ClassFile.ConstantPoolItemMethodHandle implMethod) { - return implMethod.Kind == ReferenceKind.NewInvokeSpecial - ? implMethod.Member.DeclaringType - : ((RuntimeJavaMethod)implMethod.Member).ReturnType; + return implMethod.Kind == MethodHandleKind.NewInvokeSpecial ? implMethod.Member.DeclaringType : ((RuntimeJavaMethod)implMethod.Member).ReturnType; } private static bool IsAdaptable(RuntimeJavaType Q, RuntimeJavaType S, bool isReturn) @@ -534,14 +534,14 @@ private static void EmitDispatch(RuntimeByteCodeJavaType.FinishContext context, for (int i = 0; i < capturedFields.Length; i++) { ilgen.EmitLdarg(0); - OpCode opc = OpCodes.Ldfld; + var opc = OpCodes.Ldfld; if (i == 0 && args[0].IsGhost) { switch (implMethod.Kind) { - case ReferenceKind.InvokeInterface: - case ReferenceKind.InvokeVirtual: - case ReferenceKind.InvokeSpecial: + case MethodHandleKind.InvokeInterface: + case MethodHandleKind.InvokeVirtual: + case MethodHandleKind.InvokeSpecial: opc = OpCodes.Ldflda; break; } @@ -604,15 +604,15 @@ private static void EmitDispatch(RuntimeByteCodeJavaType.FinishContext context, } switch (implMethod.Kind) { - case ReferenceKind.InvokeVirtual: - case ReferenceKind.InvokeInterface: + case MethodHandleKind.InvokeVirtual: + case MethodHandleKind.InvokeInterface: ((RuntimeJavaMethod)implMethod.Member).EmitCallvirt(ilgen); break; - case ReferenceKind.NewInvokeSpecial: + case MethodHandleKind.NewInvokeSpecial: ((RuntimeJavaMethod)implMethod.Member).EmitNewobj(ilgen); break; - case ReferenceKind.InvokeStatic: - case ReferenceKind.InvokeSpecial: + case MethodHandleKind.InvokeStatic: + case MethodHandleKind.InvokeSpecial: ((RuntimeJavaMethod)implMethod.Member).EmitCall(ilgen); break; default: @@ -768,15 +768,15 @@ private static void AddDefaultInterfaceMethods(RuntimeByteCodeJavaType.FinishCon } } - private static bool IsSupportedImplMethod(ClassFile.ConstantPoolItemMethodHandle implMethod, RuntimeJavaType caller, RuntimeJavaType[] captured, ClassFile.ConstantPoolItemMethodType instantiatedMethodType) + static bool IsSupportedImplMethod(ClassFile.ConstantPoolItemMethodHandle implMethod, RuntimeJavaType caller, RuntimeJavaType[] captured, ClassFile.ConstantPoolItemMethodType instantiatedMethodType) { switch (implMethod.Kind) { - case ReferenceKind.InvokeVirtual: - case ReferenceKind.InvokeInterface: - case ReferenceKind.NewInvokeSpecial: - case ReferenceKind.InvokeStatic: - case ReferenceKind.InvokeSpecial: + case MethodHandleKind.InvokeVirtual: + case MethodHandleKind.InvokeInterface: + case MethodHandleKind.NewInvokeSpecial: + case MethodHandleKind.InvokeStatic: + case MethodHandleKind.InvokeSpecial: break; default: return false; @@ -973,7 +973,7 @@ private static bool IsLambdaMetafactory(ClassFile classFile, ClassFile.Bootstrap && classFile.GetConstantPoolConstantType(bsm.GetArgument(0)) == ClassFile.ConstantType.MethodType && classFile.GetConstantPoolConstantType(bsm.GetArgument(1)) == ClassFile.ConstantType.MethodHandle && classFile.GetConstantPoolConstantType(bsm.GetArgument(2)) == ClassFile.ConstantType.MethodType - && (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == ReferenceKind.InvokeStatic + && (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == MethodHandleKind.InvokeStatic && mh.Member != null && IsLambdaMetafactory(mh.Member); } @@ -1000,48 +1000,42 @@ private static bool IsLambdaAltMetafactory(ClassFile classFile, ClassFile.Bootst AltFlags flags; int argpos = 4; return bsm.ArgumentCount >= 4 - && (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == ReferenceKind.InvokeStatic + && (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == MethodHandleKind.InvokeStatic && mh.Member != null && IsLambdaAltMetafactory(mh.Member) && classFile.GetConstantPoolConstantType(bsm.GetArgument(0)) == ClassFile.ConstantType.MethodType && classFile.GetConstantPoolConstantType(bsm.GetArgument(1)) == ClassFile.ConstantType.MethodHandle && classFile.GetConstantPoolConstantType(bsm.GetArgument(2)) == ClassFile.ConstantType.MethodType && classFile.GetConstantPoolConstantType(bsm.GetArgument(3)) == ClassFile.ConstantType.Integer - && ((flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3))) & ~AltFlags.Mask) == 0 + && ((flags = (AltFlags)classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)bsm.GetArgument(3))) & ~AltFlags.Mask) == 0 && ((flags & AltFlags.Markers) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.Class, ref argpos)) && ((flags & AltFlags.Bridges) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.MethodType, ref argpos)) && argpos == bsm.ArgumentCount; } - private static bool IsLambdaAltMetafactory(RuntimeJavaMember mw) + static bool IsLambdaAltMetafactory(RuntimeJavaMember mw) { return mw.Name == "altMetafactory" && mw.Signature == "(Ljava.lang.invoke.MethodHandles$Lookup;Ljava.lang.String;Ljava.lang.invoke.MethodType;[Ljava.lang.Object;)Ljava.lang.invoke.CallSite;" && mw.DeclaringType.Name == "java.lang.invoke.LambdaMetafactory"; } - private static bool CheckOptionalArgs(ClassFile classFile, ClassFile.BootstrapMethod bsm, ClassFile.ConstantType type, ref int argpos) + static bool CheckOptionalArgs(ClassFile classFile, ClassFile.BootstrapMethod bsm, ClassFile.ConstantType type, ref int argpos) { if (bsm.ArgumentCount - argpos < 1) - { return false; - } + if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos)) != ClassFile.ConstantType.Integer) - { return false; - } - int count = classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++)); + + int count = classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)bsm.GetArgument(argpos++)); if (count < 0 || bsm.ArgumentCount - argpos < count) - { return false; - } + for (int i = 0; i < count; i++) - { if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos++)) != type) - { return false; - } - } + return true; } diff --git a/src/IKVM.Runtime/Launcher.cs b/src/IKVM.Runtime/Launcher.cs index 907d8b9c4e..a86e528e13 100644 --- a/src/IKVM.Runtime/Launcher.cs +++ b/src/IKVM.Runtime/Launcher.cs @@ -256,8 +256,9 @@ static bool ArgEquals(ReadOnlySpan a, string b) } /// - /// Launches a Java application. + /// Services as the managed entry point jump for a Java executable. /// + /// /// /// /// @@ -265,7 +266,7 @@ static bool ArgEquals(ReadOnlySpan a, string b) /// /// [HideFromJava(HideFromJavaFlags.StackTrace)] - public static int Run(string main, bool jar, string[] args, string rarg, IDictionary properties) + public static int Run(Assembly assembly, string main, bool jar, string[] args, string rarg, IDictionary properties) { if (args is null) throw new ArgumentNullException(nameof(args)); @@ -275,6 +276,7 @@ public static int Run(string main, bool jar, string[] args, string rarg, IDictio #else HandleDebugTrace(); + // initialize attribute parsing var initialize = properties != null ? new Dictionary(properties) : new Dictionary(); var showversion = false; var exit = false; @@ -504,6 +506,11 @@ public static int Run(string main, bool jar, string[] args, string rarg, IDictio // VM initialization, configures system properties, done before any static initializers JVM.Init(); + // ensure the entry assembly is added to the classpath + // we do this after Init since it triggers the VFS + if (assembly != null) + AddBootClassPathAssembly(assembly); + // first entry into base assembly EnterMainThread(); diff --git a/src/IKVM.Runtime/LibIkvm.cs b/src/IKVM.Runtime/LibIkvm.cs index 5ceb9cabba..4235c8b545 100644 --- a/src/IKVM.Runtime/LibIkvm.cs +++ b/src/IKVM.Runtime/LibIkvm.cs @@ -218,7 +218,7 @@ static nint Load() return h1; // start looking at assembly path, or path given by environmental variable - var asml = typeof(NativeLibrary).Assembly.Location is string s ? Path.GetDirectoryName(s) : null; + var asml = typeof(NativeLibrary).Assembly.Location is string s && !string.IsNullOrEmpty(s) ? Path.GetDirectoryName(s) : null; var root = Environment.GetEnvironmentVariable("IKVM_LIBRARY_PATH") ?? asml ?? AppContext.BaseDirectory; // assembly possible loaded in memory: we have no available search path diff --git a/src/IKVM.Runtime/MethodAnalyzer.cs b/src/IKVM.Runtime/MethodAnalyzer.cs index fcd6c137bb..9a72cb836b 100644 --- a/src/IKVM.Runtime/MethodAnalyzer.cs +++ b/src/IKVM.Runtime/MethodAnalyzer.cs @@ -1299,25 +1299,27 @@ private void AnalyzeTypeFlow() private void MergeExceptionHandler(int exceptionIndex, InstructionState curr) { - int idx = method.ExceptionTable[exceptionIndex].handlerIndex; - InstructionState ex = curr.CopyLocals(); - int catch_type = method.ExceptionTable[exceptionIndex].catch_type; - if (catch_type == 0) + var idx = method.ExceptionTable[exceptionIndex].handlerIndex; + var ex = curr.CopyLocals(); + + var catchType = method.ExceptionTable[exceptionIndex].catchType; + if (catchType.IsNil) { - RuntimeJavaType tw; - if (!faultTypes.TryGetValue(idx, out tw)) + if (!faultTypes.TryGetValue(idx, out var tw)) { tw = RuntimeVerifierJavaType.MakeFaultBlockException(this, idx); faultTypes.Add(idx, tw); } + ex.PushType(tw); } else { // TODO if the exception type is unloadable we should consider pushing // Throwable as the type and recording a loader constraint - ex.PushType(GetConstantPoolClassType(catch_type)); + ex.PushType(GetConstantPoolClassType(catchType)); } + state[idx] += ex; } @@ -1576,18 +1578,17 @@ private void PatchHardErrorsAndDynamicMemberAccess(RuntimeJavaType wrapper, Runt { case ClassFile.ConstantType.Class: { - RuntimeJavaType tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); + var tw = classFile.GetConstantPoolClassType(instructions[i].Arg1); if (tw.IsUnloadable) - { ConditionalPatchNoClassDefFoundError(ref instructions[i], tw); - } + break; } case ClassFile.ConstantType.MethodType: { - ClassFile.ConstantPoolItemMethodType cpi = classFile.GetConstantPoolConstantMethodType(instructions[i].Arg1); - RuntimeJavaType[] args = cpi.GetArgTypes(); - RuntimeJavaType tw = cpi.GetRetType(); + var cpi = classFile.GetConstantPoolConstantMethodType(instructions[i].Arg1); + var args = cpi.GetArgTypes(); + var tw = cpi.GetRetType(); for (int j = 0; !tw.IsUnloadable && j < args.Length; j++) { tw = args[j]; @@ -1680,9 +1681,9 @@ private void PatchHardErrorsAndDynamicMemberAccess(RuntimeJavaType wrapper, Runt } } - private void PatchLdcMethodHandle(ref ClassFile.Method.Instruction instr) + void PatchLdcMethodHandle(ref ClassFile.Method.Instruction instr) { - ClassFile.ConstantPoolItemMethodHandle cpi = classFile.GetConstantPoolConstantMethodHandle(instr.Arg1); + var cpi = classFile.GetConstantPoolConstantMethodHandle(instr.Arg1); if (cpi.GetClassType().IsUnloadable) { ConditionalPatchNoClassDefFoundError(ref instr, cpi.GetClassType()); @@ -1691,22 +1692,20 @@ private void PatchLdcMethodHandle(ref ClassFile.Method.Instruction instr) { SetHardError(wrapper.GetClassLoader(), ref instr, HardError.IllegalAccessError, "tried to access class {0} from class {1}", cpi.Class, wrapper.Name); } - else if (cpi.Kind == ReferenceKind.InvokeVirtual - && cpi.GetClassType() == context.JavaBase.TypeOfJavaLangInvokeMethodHandle - && (cpi.Name == "invoke" || cpi.Name == "invokeExact")) + else if (cpi.Kind == MethodHandleKind.InvokeVirtual && cpi.GetClassType() == context.JavaBase.TypeOfJavaLangInvokeMethodHandle && (cpi.Name == "invoke" || cpi.Name == "invokeExact")) { // it's allowed to use ldc to create a MethodHandle invoker } - else if (cpi.Member == null || cpi.Member.IsStatic != (cpi.Kind == ReferenceKind.GetStatic || cpi.Kind == ReferenceKind.PutStatic || cpi.Kind == ReferenceKind.InvokeStatic)) + else if (cpi.Member == null || cpi.Member.IsStatic != (cpi.Kind == MethodHandleKind.GetStatic || cpi.Kind == MethodHandleKind.PutStatic || cpi.Kind == MethodHandleKind.InvokeStatic)) { HardError err; string msg; switch (cpi.Kind) { - case ReferenceKind.GetField: - case ReferenceKind.GetStatic: - case ReferenceKind.PutField: - case ReferenceKind.PutStatic: + case MethodHandleKind.GetField: + case MethodHandleKind.GetStatic: + case MethodHandleKind.PutField: + case MethodHandleKind.PutStatic: err = HardError.NoSuchFieldError; msg = cpi.Name; break; @@ -1730,10 +1729,10 @@ private void PatchLdcMethodHandle(ref ClassFile.Method.Instruction instr) } } - private static string SigToString(string sig) + static string SigToString(string sig) { - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - string sep = ""; + var sb = new System.Text.StringBuilder(); + var sep = ""; int dims = 0; for (int i = 0; i < sig.Length; i++) { @@ -1748,6 +1747,7 @@ private static string SigToString(string sig) dims++; continue; } + sb.Append(sep); sep = ","; switch (sig[i]) @@ -1784,11 +1784,11 @@ private static string SigToString(string sig) i = sig.IndexOf(';', i + 1); break; } + for (; dims != 0; dims--) - { sb.Append("[]"); - } } + return sb.ToString(); } @@ -1800,7 +1800,7 @@ internal static InstructionFlags[] ComputePartialReachability(CodeInfo codeInfo, return flags; } - private static void UpdatePartialReachability(InstructionFlags[] flags, CodeInfo codeInfo, ClassFile.Method.Instruction[] instructions, UntangledExceptionTable exceptions, bool skipFaultBlocks) + static void UpdatePartialReachability(InstructionFlags[] flags, CodeInfo codeInfo, ClassFile.Method.Instruction[] instructions, UntangledExceptionTable exceptions, bool skipFaultBlocks) { bool done = false; while (!done) @@ -1880,7 +1880,7 @@ internal static UntangledExceptionTable UntangleExceptionBlocks(RuntimeContext c for (int i = 0; i < ar.Count; i++) { ExceptionTableEntry ei = ar[i]; - if (ei.startIndex == ei.handlerIndex && ei.catch_type == 0) + if (ei.startIndex == ei.handlerIndex && ei.catchType.IsNil) { int index = ei.startIndex; if (index + 2 < instructions.Length @@ -1923,10 +1923,10 @@ internal static UntangledExceptionTable UntangleExceptionBlocks(RuntimeContext c { if (ar[i].endIndex + 1 == ar[i + 1].startIndex && ar[i].handlerIndex == ar[i + 1].handlerIndex - && ar[i].catch_type == ar[i + 1].catch_type + && ar[i].catchType == ar[i + 1].catchType && IsReturn(instructions[ar[i].endIndex].NormalizedOpCode)) { - ar[i] = new ExceptionTableEntry(ar[i].startIndex, ar[i + 1].endIndex, ar[i].handlerIndex, ar[i].catch_type, ar[i].ordinal); + ar[i] = new ExceptionTableEntry(ar[i].startIndex, ar[i + 1].endIndex, ar[i].handlerIndex, ar[i].catchType, ar[i].ordinal); ar.RemoveAt(i + 1); i--; } @@ -1944,10 +1944,10 @@ internal static UntangledExceptionTable UntangleExceptionBlocks(RuntimeContext c // 0006/test.j if (ej.endIndex > ei.endIndex) { - ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ExceptionTableEntry emj = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ej.handlerIndex, ej.catch_type, ej.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ej = new ExceptionTableEntry(emj.endIndex, ej.endIndex, ej.handlerIndex, ej.catch_type, ej.ordinal); + ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ei.handlerIndex, ei.catchType, ei.ordinal); + ExceptionTableEntry emj = new ExceptionTableEntry(ej.startIndex, ei.endIndex, ej.handlerIndex, ej.catchType, ej.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catchType, ei.ordinal); + ej = new ExceptionTableEntry(emj.endIndex, ej.endIndex, ej.handlerIndex, ej.catchType, ej.ordinal); ar[i] = ei; ar[j] = ej; ar.Insert(j, emj); @@ -1957,9 +1957,9 @@ internal static UntangledExceptionTable UntangleExceptionBlocks(RuntimeContext c // 0007/test.j else if (j > i && ej.endIndex < ei.endIndex) { - ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ej.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ExceptionTableEntry eei = new ExceptionTableEntry(ej.endIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ExceptionTableEntry emi = new ExceptionTableEntry(ej.startIndex, ej.endIndex, ei.handlerIndex, ei.catchType, ei.ordinal); + ExceptionTableEntry eei = new ExceptionTableEntry(ej.endIndex, ei.endIndex, ei.handlerIndex, ei.catchType, ei.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, emi.startIndex, ei.handlerIndex, ei.catchType, ei.ordinal); ar[i] = ei; ar.Insert(i + 1, eei); ar.Insert(i + 1, emi); @@ -1989,8 +1989,8 @@ internal static UntangledExceptionTable UntangleExceptionBlocks(RuntimeContext c int targetIndex = (k == -1 ? instructions[j].DefaultTarget : instructions[j].GetSwitchTargetIndex(k)); if (ei.startIndex < targetIndex && targetIndex < ei.endIndex) { - ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catchType, ei.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catchType, ei.ordinal); ar[i] = ei; ar.Insert(i + 1, en); goto restart_split; @@ -2018,8 +2018,8 @@ internal static UntangledExceptionTable UntangleExceptionBlocks(RuntimeContext c int targetIndex = instructions[j].Arg1; if (ei.startIndex < targetIndex && targetIndex < ei.endIndex) { - ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ExceptionTableEntry en = new ExceptionTableEntry(targetIndex, ei.endIndex, ei.handlerIndex, ei.catchType, ei.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, targetIndex, ei.handlerIndex, ei.catchType, ei.ordinal); ar[i] = ei; ar.Insert(i + 1, en); goto restart_split; @@ -2039,8 +2039,8 @@ internal static UntangledExceptionTable UntangleExceptionBlocks(RuntimeContext c ExceptionTableEntry ej = ar[j]; if (ei.startIndex < ej.handlerIndex && ej.handlerIndex < ei.endIndex) { - ExceptionTableEntry en = new ExceptionTableEntry(ej.handlerIndex, ei.endIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); - ei = new ExceptionTableEntry(ei.startIndex, ej.handlerIndex, ei.handlerIndex, ei.catch_type, ei.ordinal); + ExceptionTableEntry en = new ExceptionTableEntry(ej.handlerIndex, ei.endIndex, ei.handlerIndex, ei.catchType, ei.ordinal); + ei = new ExceptionTableEntry(ei.startIndex, ej.handlerIndex, ei.handlerIndex, ei.catchType, ei.ordinal); ar[i] = ei; ar.Insert(i + 1, en); goto restart_split; @@ -2050,7 +2050,7 @@ internal static UntangledExceptionTable UntangleExceptionBlocks(RuntimeContext c // filter out zero length try blocks for (int i = 0; i < ar.Count; i++) { - ExceptionTableEntry ei = ar[i]; + var ei = ar[i]; if (ei.startIndex == ei.endIndex) { ar.RemoveAt(i); @@ -2060,7 +2060,7 @@ internal static UntangledExceptionTable UntangleExceptionBlocks(RuntimeContext c { // exception blocks that only contain harmless instructions (i.e. instructions that will *never* throw an exception) // are also filtered out (to improve the quality of the generated code) - RuntimeJavaType exceptionType = ei.catch_type == 0 ? context.JavaBase.TypeOfjavaLangThrowable : classFile.GetConstantPoolClassType(ei.catch_type); + RuntimeJavaType exceptionType = ei.catchType.IsNil ? context.JavaBase.TypeOfjavaLangThrowable : classFile.GetConstantPoolClassType(ei.catchType); if (exceptionType.IsUnloadable) { // we can't remove handlers for unloadable types @@ -2158,21 +2158,18 @@ private static bool AnalyzePotentialFaultBlocks(CodeInfo codeInfo, ClassFile.Met while (!done) { done = true; - Stack stack = new Stack(); - ExceptionTableEntry current = new ExceptionTableEntry(0, code.Length, -1, ushort.MaxValue, -1); + var stack = new Stack(); + var current = new ExceptionTableEntry(0, code.Length, -1, new ClassConstantHandle(ushort.MaxValue), -1); stack.Push(current); for (int i = 0; i < exceptions.Length; i++) { while (exceptions[i].startIndex >= current.endIndex) - { current = stack.Pop(); - } + Debug.Assert(exceptions[i].startIndex >= current.startIndex && exceptions[i].endIndex <= current.endIndex); - if (exceptions[i].catch_type == 0 - && codeInfo.HasState(exceptions[i].handlerIndex) - && RuntimeVerifierJavaType.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0))) + if (exceptions[i].catchType.IsNil && codeInfo.HasState(exceptions[i].handlerIndex) && RuntimeVerifierJavaType.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0))) { - InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(codeInfo, method.Instructions, exceptions, exceptions[i].handlerIndex, true); + var flags = MethodAnalyzer.ComputePartialReachability(codeInfo, method.Instructions, exceptions, exceptions[i].handlerIndex, true); for (int j = 0; j < code.Length; j++) { if ((flags[j] & InstructionFlags.Reachable) != 0) @@ -2234,14 +2231,12 @@ private static void ConvertFinallyBlocks(CodeInfo codeInfo, ClassFile.Method met InstructionFlags[] flags = ComputePartialReachability(codeInfo, code, exceptions, 0, false); for (int i = 0; i < exceptions.Length; i++) { - if (exceptions[i].catch_type == 0 - && codeInfo.HasState(exceptions[i].handlerIndex) - && RuntimeVerifierJavaType.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0))) + if (exceptions[i].catchType.IsNil && codeInfo.HasState(exceptions[i].handlerIndex) && RuntimeVerifierJavaType.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(exceptions[i].handlerIndex, 0))) { int exit; if (IsSynchronizedBlockHandler(code, exceptions[i].handlerIndex) && exceptions[i].endIndex - 2 >= exceptions[i].startIndex - && TryFindSingleTryBlockExit(code, flags, exceptions, new ExceptionTableEntry(exceptions[i].startIndex, exceptions[i].endIndex - 2, exceptions[i].handlerIndex, 0, exceptions[i].ordinal), i, out exit) + && TryFindSingleTryBlockExit(code, flags, exceptions, new ExceptionTableEntry(exceptions[i].startIndex, exceptions[i].endIndex - 2, exceptions[i].handlerIndex, ClassConstantHandle.Nil, exceptions[i].ordinal), i, out exit) && exit == exceptions[i].endIndex - 2 && (flags[exit + 1] & InstructionFlags.BranchTarget) == 0 && MatchInstructions(code, exit, exceptions[i].handlerIndex + 1) @@ -2692,7 +2687,7 @@ private static string ToSlash(string str) private void PatchFieldAccess(RuntimeJavaType wrapper, RuntimeJavaMethod mw, ref ClassFile.Method.Instruction instr, StackState stack) { - ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); + var cpi = GetFieldref(instr.Arg1); bool isStatic; bool write; RuntimeJavaType thisType; @@ -2900,68 +2895,113 @@ private string CheckLoaderConstraints(ClassFile.ConstantPoolItemMI cpi, RuntimeJ return null; } - private ClassFile.ConstantPoolItemInvokeDynamic GetInvokeDynamic(int index) + ClassFile.ConstantPoolItemInvokeDynamic GetInvokeDynamic(int index) { try { - ClassFile.ConstantPoolItemInvokeDynamic item = classFile.GetInvokeDynamic(index); + var item = classFile.GetInvokeDynamic(new InvokeDynamicConstantHandle(checked((ushort)index))); if (item != null) { return item; } } + catch (OverflowException) + { + // constant pool index out of range + } catch (InvalidCastException) { + // constant pool index not of proper type } catch (IndexOutOfRangeException) { + // constant pool index out of range + } + catch (InvalidOperationException) + { + // specified constant pool entry doesn't contain a constant + } + catch (NullReferenceException) + { + // specified constant pool entry is empty (entry 0 or the filler following a wide entry) } + throw new VerifyError("Illegal constant pool index"); } - private ClassFile.ConstantPoolItemMI GetMethodref(int index) + ClassFile.ConstantPoolItemMI GetMethodref(int index) { try { - ClassFile.ConstantPoolItemMI item = classFile.GetMethodref(index); + var item = classFile.GetMethodref(new MethodrefConstantHandle(checked((ushort)index))); if (item != null) - { return item; - } + } + catch (OverflowException) + { + // constant pool index out of range } catch (InvalidCastException) { + // constant pool index not of proper type } catch (IndexOutOfRangeException) { + // constant pool index out of range + } + catch (InvalidOperationException) + { + // specified constant pool entry doesn't contain a constant } + catch (NullReferenceException) + { + // specified constant pool entry is empty (entry 0 or the filler following a wide entry) + } + throw new VerifyError("Illegal constant pool index"); } - private ClassFile.ConstantPoolItemFieldref GetFieldref(int index) + ClassFile.ConstantPoolItemFieldref GetFieldref(int index) { try { - ClassFile.ConstantPoolItemFieldref item = classFile.GetFieldref(index); + var item = classFile.GetFieldref(new FieldrefConstantHandle(checked((ushort)index))); if (item != null) - { return item; - } + } + catch (OverflowException) + { + // constant pool index out of range } catch (InvalidCastException) { + // constant pool index not of proper type } catch (IndexOutOfRangeException) { + // constant pool index out of range + } + catch (InvalidOperationException) + { + // specified constant pool entry doesn't contain a constant + } + catch (NullReferenceException) + { + // specified constant pool entry is empty (entry 0 or the filler following a wide entry) } + throw new VerifyError("Illegal constant pool index"); } - private ClassFile.ConstantType GetConstantPoolConstantType(int index) + ClassFile.ConstantType GetConstantPoolConstantType(int slot) { try { - return classFile.GetConstantPoolConstantType(index); + return classFile.GetConstantPoolConstantType(new ConstantHandle(ConstantKind.Unknown, checked((ushort)slot))); + } + catch (OverflowException) + { + // constant pool index out of range } catch (IndexOutOfRangeException) { @@ -2975,27 +3015,41 @@ private ClassFile.ConstantType GetConstantPoolConstantType(int index) { // specified constant pool entry is empty (entry 0 or the filler following a wide entry) } + throw new VerifyError("Illegal constant pool index"); } - private RuntimeJavaType GetConstantPoolClassType(int index) + RuntimeJavaType GetConstantPoolClassType(int slot) { try { - return classFile.GetConstantPoolClassType(index); + return classFile.GetConstantPoolClassType(new ClassConstantHandle(checked((ushort)slot))); + } + catch (OverflowException) + { + // constant pool index out of range } catch (InvalidCastException) { + // constant pool index out of range } catch (IndexOutOfRangeException) { + // specified constant pool entry doesn't contain a constant } catch (NullReferenceException) { + // specified constant pool entry is empty (entry 0 or the filler following a wide entry) } + throw new VerifyError("Illegal constant pool index"); } + RuntimeJavaType GetConstantPoolClassType(ClassConstantHandle handle) + { + return GetConstantPoolClassType(handle.Slot); + } + internal void ClearFaultBlockException(int instructionIndex) { Debug.Assert(state[instructionIndex].GetStackHeight() == 1); @@ -3070,7 +3124,7 @@ private static void DumpMethod(CodeInfo codeInfo, ClassFile.Method method, Untan } for (int i = 0; i < exceptions.Length; i++) { - Console.WriteLine(".catch #{0} from label{1} to label{2} using label{3}", exceptions[i].catch_type, exceptions[i].startIndex, exceptions[i].endIndex, exceptions[i].handlerIndex); + Console.WriteLine(".catch #{0} from label{1} to label{2} using label{3}", exceptions[i].catchType, exceptions[i].startIndex, exceptions[i].endIndex, exceptions[i].handlerIndex); } } } diff --git a/src/IKVM.Runtime/NativeLibrary.cs b/src/IKVM.Runtime/NativeLibrary.cs index 28f02a7bb1..a96054309e 100644 --- a/src/IKVM.Runtime/NativeLibrary.cs +++ b/src/IKVM.Runtime/NativeLibrary.cs @@ -73,7 +73,7 @@ public static NativeLibraryHandle Load(string nameOrPath) return h1; // start looking at assembly path, or path given by environmental variable - var asml = typeof(NativeLibrary).Assembly.Location is string s ? Path.GetDirectoryName(s) : null; + var asml = typeof(NativeLibrary).Assembly.Location is string s && !string.IsNullOrEmpty(s) ? Path.GetDirectoryName(s) : null; var root = Environment.GetEnvironmentVariable("IKVM_LIBRARY_PATH") ?? asml; // assembly possible loaded in memory: we have no available search path diff --git a/src/IKVM.Runtime/ReflectUtil.cs b/src/IKVM.Runtime/ReflectUtil.cs index 39e9e07898..f5ae01f505 100644 --- a/src/IKVM.Runtime/ReflectUtil.cs +++ b/src/IKVM.Runtime/ReflectUtil.cs @@ -26,6 +26,7 @@ Jeroen Frijters #if IMPORTER || EXPORTER using IKVM.Reflection; using IKVM.Reflection.Emit; + using Type = IKVM.Reflection.Type; #else using System.Reflection; @@ -56,7 +57,7 @@ internal static Assembly GetAssembly(Type type) internal static bool IsDynamicAssembly(Assembly asm) { #if IMPORTER || EXPORTER - return false; + return false; #else return asm.IsDynamic; #endif @@ -100,7 +101,7 @@ internal static bool ContainsTypeBuilder(Type type) internal static bool IsVector(Type type) { #if IMPORTER || EXPORTER - return type.__IsVector; + return type.__IsVector; #else // there's no API to distinguish an array of rank 1 from a vector, // so we check if the type name ends in [], which indicates it's a vector @@ -126,20 +127,7 @@ internal static bool IsDynamicMethod(MethodInfo method) internal static MethodBuilder DefineTypeInitializer(TypeBuilder typeBuilder, RuntimeClassLoader loader) { - MethodAttributes attr = MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName; - if (typeBuilder.IsInterface && loader.WorkaroundInterfacePrivateMethods) - { - // LAMESPEC the ECMA spec says (part. I, sect. 8.5.3.2) that all interface members must be public, so we make - // the class constructor public. - // NOTE it turns out that on .NET 2.0 this isn't necessary anymore (neither Ref.Emit nor the CLR verifier complain about it), - // but the C# compiler still considers interfaces with non-public methods to be invalid, so to keep interop with C# we have - // to keep making the .cctor method public. - attr |= MethodAttributes.Public; - } - else - { - attr |= MethodAttributes.Private; - } + var attr = MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.Private; return typeBuilder.DefineMethod(ConstructorInfo.TypeConstructorName, attr, null, Type.EmptyTypes); } @@ -217,36 +205,36 @@ private static bool MatchTypes(Type[] t1, Type[] t2) #if IMPORTER - internal static Type GetMissingType(Type type) - { - while (type.HasElementType) - { - type = type.GetElementType(); - } - if (type.__IsMissing) - { - return type; - } - else if (type.__ContainsMissingType) - { - if (type.IsGenericType) - { - foreach (Type arg in type.GetGenericArguments()) - { - Type t1 = GetMissingType(arg); - if (t1.__IsMissing) - { - return t1; - } - } - } - throw new NotImplementedException(type.FullName); - } - else - { - return type; - } - } + internal static Type GetMissingType(Type type) + { + while (type.HasElementType) + { + type = type.GetElementType(); + } + if (type.__IsMissing) + { + return type; + } + else if (type.__ContainsMissingType) + { + if (type.IsGenericType) + { + foreach (Type arg in type.GetGenericArguments()) + { + Type t1 = GetMissingType(arg); + if (t1.__IsMissing) + { + return t1; + } + } + } + throw new NotImplementedException(type.FullName); + } + else + { + return type; + } + } #endif diff --git a/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs b/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs index 200a08fcff..3cba3e77d8 100644 --- a/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs +++ b/src/IKVM.Runtime/RuntimeAssemblyClassLoader.cs @@ -1129,10 +1129,9 @@ internal override bool InternalsVisibleToImpl(RuntimeJavaType wrapper, RuntimeJa internal void AddDelegate(RuntimeAssemblyClassLoader acl) { LazyInitExports(); + lock (this) - { delegates = ArrayUtil.Concat(delegates, acl); - } } #if !IMPORTER && !EXPORTER diff --git a/src/IKVM.Runtime/RuntimeByteCodeJavaType.FinishContext.cs b/src/IKVM.Runtime/RuntimeByteCodeJavaType.FinishContext.cs index e6d2d73594..4b8c105073 100644 --- a/src/IKVM.Runtime/RuntimeByteCodeJavaType.FinishContext.cs +++ b/src/IKVM.Runtime/RuntimeByteCodeJavaType.FinishContext.cs @@ -25,8 +25,9 @@ Jeroen Frijters using System.Collections.Generic; using System.Diagnostics; -using IKVM.ByteCode.Reading; using IKVM.Attributes; +using IKVM.ByteCode; +using IKVM.ByteCode.Decoding; #if IMPORTER using IKVM.Reflection; @@ -765,17 +766,26 @@ internal Type FinishImpl() } #if IMPORTER + static void AddConstantPoolAttributeIfNecessary(RuntimeContext context, ClassFile classFile, TypeBuilder typeBuilder) { object[] constantPool = null; bool[] inUse = null; - MarkConstantPoolUsage(classFile, classFile.RuntimeVisibleTypeAnnotations, ref constantPool, ref inUse); + + ref readonly var runtimeVisibleTypeAnnotations = ref classFile.RuntimeVisibleTypeAnnotations; + MarkConstantPoolUsage(classFile, in runtimeVisibleTypeAnnotations, ref constantPool, ref inUse); foreach (var method in classFile.Methods) - MarkConstantPoolUsage(classFile, method.RuntimeVisibleTypeAnnotations, ref constantPool, ref inUse); + { + ref readonly var methodRuntimeVisibleTypeAnnotations = ref method.RuntimeVisibleTypeAnnotations; + MarkConstantPoolUsage(classFile, in methodRuntimeVisibleTypeAnnotations, ref constantPool, ref inUse); + } foreach (var field in classFile.Fields) - MarkConstantPoolUsage(classFile, field.RuntimeVisibleTypeAnnotations, ref constantPool, ref inUse); + { + ref readonly var fieldRuntimeVisibleTypeAnnotations = ref field.RuntimeVisibleTypeAnnotations; + MarkConstantPoolUsage(classFile, in field.RuntimeVisibleTypeAnnotations, ref constantPool, ref inUse); + } if (constantPool != null) { @@ -785,9 +795,16 @@ static void AddConstantPoolAttributeIfNecessary(RuntimeContext context, ClassFil } } - private static void MarkConstantPoolUsage(ClassFile classFile, IReadOnlyList runtimeVisibleTypeAnnotations, ref object[] constantPool, ref bool[] inUse) + /// + /// Scans the specified for used constant handles and marks them as in-use. + /// + /// + /// + /// + /// + static void MarkConstantPoolUsage(ClassFile classFile, ref readonly TypeAnnotationTable runtimeVisibleTypeAnnotations, ref object[] constantPool, ref bool[] inUse) { - if (runtimeVisibleTypeAnnotations != null) + if (runtimeVisibleTypeAnnotations.Count > 0) { if (constantPool == null) { @@ -796,69 +813,89 @@ private static void MarkConstantPoolUsage(ClassFile classFile, IReadOnlyList 0 && wrapper.classLoader.WorkaroundInterfaceFields) - { - TypeBuilder tbFields = DefineNestedInteropType(NestedTypeName.Fields); - CodeEmitter ilgenClinit = null; - for (int i = 0; i < classFile.Fields.Length; i++) - { - ClassFile.Field f = classFile.Fields[i]; - if (f.ConstantValue != null) - { - FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal; - FieldBuilder fb = tbFields.DefineField(f.Name, fields[i].FieldTypeWrapper.TypeAsSignatureType, attribs); - fb.SetConstant(f.ConstantValue); - } - else - { - FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly; - FieldBuilder fb = tbFields.DefineField(f.Name, fields[i].FieldTypeWrapper.TypeAsPublicSignatureType, attribs); - if (ilgenClinit == null) - { - ilgenClinit = context.CodeEmitterFactory.Create(ReflectUtil.DefineTypeInitializer(tbFields, wrapper.classLoader)); - } - wrapper.GetFieldWrapper(f.Name, f.Signature).EmitGet(ilgenClinit); - ilgenClinit.Emit(OpCodes.Stsfld, fb); - } - } - if (ilgenClinit != null) - { - ilgenClinit.Emit(OpCodes.Ret); - ilgenClinit.DoEmit(); - } - } + } - private void AddInterfaceMethodsInterop(RuntimeJavaMethod[] methods) + void AddInterfaceMethodsInterop(RuntimeJavaMethod[] methods) { - if (classFile.IsInterface && classFile.IsPublic && classFile.MajorVersion >= 52 && !wrapper.IsGhost && methods.Length > 0 && wrapper.classLoader.WorkaroundInterfaceStaticMethods) - { - TypeBuilder tbMethods = null; - foreach (var mw in methods) - { - if (mw.IsStatic && mw.IsPublic && mw.Name != StringConstants.CLINIT && ParametersAreAccessible(mw)) - { - if (tbMethods == null) - { - tbMethods = DefineNestedInteropType(NestedTypeName.Methods); - } - var mb = mw.GetDefineMethodHelper().DefineMethod(wrapper.GetClassLoader().GetTypeWrapperFactory(), tbMethods, mw.Name, MethodAttributes.Public | MethodAttributes.Static, null, true); - var ilgen = context.CodeEmitterFactory.Create(mb); - var parameters = mw.GetParameters(); - for (int i = 0; i < parameters.Length; i++) - { - ilgen.EmitLdarg(i); - if (!parameters[i].IsUnloadable && !parameters[i].IsPublic) - { - parameters[i].EmitCheckcast(ilgen); - } - } - mw.EmitCall(ilgen); - ilgen.Emit(OpCodes.Ret); - ilgen.DoEmit(); - } - } - } + } private void CreateDefaultMethodInterop(ref TypeBuilder tbDefaultMethods, MethodBuilder defaultMethod, RuntimeJavaMethod mw) @@ -2311,16 +2291,16 @@ internal TypeBuilder DefineIndyCallSiteType() return tb; } - internal TypeBuilder DefineMethodHandleConstantType(int index) + internal TypeBuilder DefineMethodHandleConstantType(MethodHandleConstantHandle handle) { - var tb = typeBuilder.DefineNestedType(NestedTypeName.MethodHandleConstant + index, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); ; + var tb = typeBuilder.DefineNestedType(NestedTypeName.MethodHandleConstant + handle.Slot, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); ; RegisterNestedTypeBuilder(tb); return tb; } - internal TypeBuilder DefineMethodTypeConstantType(int index) + internal TypeBuilder DefineMethodTypeConstantType(MethodTypeConstantHandle handle) { - var tb = typeBuilder.DefineNestedType(NestedTypeName.MethodTypeConstant + index, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); + var tb = typeBuilder.DefineNestedType(NestedTypeName.MethodTypeConstant + handle.Slot, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); RegisterNestedTypeBuilder(tb); return tb; } @@ -2336,20 +2316,6 @@ internal TypeBuilder DefineAnonymousClass() MethodBuilder DefineHelperMethod(string name, Type returnType, Type[] parameterTypes) { -#if IMPORTER - // FXBUG csc.exe doesn't like non-public methods in interfaces, so for public interfaces we move - // the helper methods into a nested type. - if (wrapper.IsPublic && wrapper.IsInterface && wrapper.classLoader.WorkaroundInterfacePrivateMethods) - { - if (interfaceHelperMethodsTypeBuilder == null) - { - interfaceHelperMethodsTypeBuilder = typeBuilder.DefineNestedType(NestedTypeName.InterfaceHelperMethods, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); - RegisterNestedTypeBuilder(interfaceHelperMethodsTypeBuilder); - } - return interfaceHelperMethodsTypeBuilder.DefineMethod(name, MethodAttributes.PrivateScope | MethodAttributes.Static, returnType, parameterTypes); - } -#endif - return typeBuilder.DefineMethod(name, MethodAttributes.PrivateScope | MethodAttributes.Static, returnType, parameterTypes); } diff --git a/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs b/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs index 29dd44b081..ea07b61031 100644 --- a/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs +++ b/src/IKVM.Runtime/RuntimeByteCodeJavaType.JavaTypeImpl.cs @@ -288,7 +288,7 @@ internal void CreateStep2() // and doesn't buy us anything in dynamic mode (and if fact, due to an FXBUG it would make handling // the TypeResolve event very hard) var outerClass = getOuterClass(); - if (outerClass.outerClass != 0) + if (outerClass.outerClass.IsNotNil) { enclosingClassName = classFile.GetConstantPoolClass(outerClass.outerClass); } @@ -301,7 +301,7 @@ internal void CreateStep2() { if (!CheckInnerOuterNames(f.Name, enclosingClassName)) { - Tracer.Warning(Tracer.Compiler, "Incorrect {0} attribute on {1}", outerClass.outerClass != 0 ? "InnerClasses" : "EnclosingMethod", f.Name); + Tracer.Warning(Tracer.Compiler, "Incorrect {0} attribute on {1}", outerClass.outerClass.IsNotNil ? "InnerClasses" : "EnclosingMethod", f.Name); } else { @@ -334,10 +334,7 @@ internal void CreateStep2() var ok = false; for (int i = 0; i < outerInnerClasses.Length; i++) { - if (((outerInnerClasses[i].outerClass != 0 && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].outerClass) == outerClassFile.Name) - || (outerInnerClasses[i].outerClass == 0 && outerClass.outerClass == 0)) - && outerInnerClasses[i].innerClass != 0 - && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].innerClass) == f.Name) + if (((outerInnerClasses[i].outerClass.IsNotNil && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].outerClass) == outerClassFile.Name) || (outerInnerClasses[i].outerClass.IsNil && outerClass.outerClass.IsNil)) && outerInnerClasses[i].innerClass.IsNotNil && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].innerClass) == f.Name) { ok = true; break; @@ -359,7 +356,7 @@ internal void CreateStep2() { enclosingClassWrapper.CreateStep2(); enclosing = oimpl.typeBuilder; - if (outerClass.outerClass == 0) + if (outerClass.outerClass.IsNil) { // we need to record that we're not an inner classes, but an enclosed class typeAttribs |= TypeAttributes.SpecialName; @@ -466,7 +463,7 @@ internal void CreateStep2() // types that we're currently compiling (i.e. a cyclic dependency between the currently assembly we're compiling and a referenced assembly). wrapper.Context.ClassLoaderFactory.SetWrapperForType(typeBuilder, wrapper); - if (outerClass.outerClass != 0) + if (outerClass.outerClass.IsNotNil) { if (enclosing != null && cantNest) { @@ -519,7 +516,7 @@ internal void CreateStep2() AddCliEnum(); } - AddInnerClassAttribute(enclosing != null, outerClass.innerClass != 0, mangledTypeName, outerClass.accessFlags); + AddInnerClassAttribute(enclosing != null, outerClass.innerClass.IsNotNil, mangledTypeName, outerClass.accessFlags); if (classFile.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(classFile.Annotations)) { wrapper.Context.AttributeHelper.SetDeprecatedAttribute(typeBuilder); @@ -531,7 +528,7 @@ internal void CreateStep2() } if (classFile.EnclosingMethod != null) { - if (outerClass.outerClass == 0 && enclosing != null && !cantNest) + if (outerClass.outerClass.IsNil && enclosing != null && !cantNest) { // we don't need to record the enclosing type, if we're compiling the current type as a nested type because of the EnclosingMethod attribute wrapper.Context.AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, null, classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]); @@ -541,10 +538,10 @@ internal void CreateStep2() wrapper.Context.AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, classFile.EnclosingMethod[0], classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]); } } - if (classFile.RuntimeVisibleTypeAnnotations != null) - { - wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(typeBuilder, classFile.RuntimeVisibleTypeAnnotations); - } + + if (classFile.RuntimeVisibleTypeAnnotations.Count > 0) + wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(typeBuilder, in classFile.RuntimeVisibleTypeAnnotations); + if (wrapper.classLoader.EmitStackTraceInfo) { if (f.SourceFileAttribute != null) @@ -696,8 +693,7 @@ private ClassFile.InnerClass getOuterClass() { for (int j = 0; j < innerClasses.Length; j++) { - if (innerClasses[j].innerClass != 0 - && classFile.GetConstantPoolClass(innerClasses[j].innerClass) == classFile.Name) + if (innerClasses[j].innerClass.IsNotNil && classFile.GetConstantPoolClass(innerClasses[j].innerClass) == classFile.Name) { return innerClasses[j]; } @@ -1120,7 +1116,7 @@ internal override FieldInfo LinkField(RuntimeJavaField fw) } if (fld.IsTransient) { - CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder(wrapper.Context.Resolver.ResolveCoreType(typeof(NonSerializedAttribute).FullName).GetConstructor(Type.EmptyTypes), new object[0]); + var transientAttrib = new CustomAttributeBuilder(wrapper.Context.Resolver.ResolveCoreType(typeof(NonSerializedAttribute).FullName).GetConstructor(Type.EmptyTypes), []); field.SetCustomAttribute(transientAttrib); } #if IMPORTER @@ -1128,39 +1124,32 @@ internal override FieldInfo LinkField(RuntimeJavaField fw) // if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store // the Java modifiers if (setModifiers) - { wrapper.Context.AttributeHelper.SetModifiers(field, fld.Modifiers, fld.IsInternal); - } + if (fld.DeprecatedAttribute && !Annotation.HasObsoleteAttribute(fld.Annotations)) - { wrapper.Context.AttributeHelper.SetDeprecatedAttribute(field); - } + if (fld.GenericSignature != null) - { wrapper.Context.AttributeHelper.SetSignatureAttribute(field, fld.GenericSignature); - } - if (fld.RuntimeVisibleTypeAnnotations != null) - { - wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(field, fld.RuntimeVisibleTypeAnnotations); - } + + if (fld.RuntimeVisibleTypeAnnotations.Count > 0) + wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(field, in fld.RuntimeVisibleTypeAnnotations); } #endif return field; } - private FieldBuilder DefineField(string name, RuntimeJavaType tw, FieldAttributes attribs, bool isVolatile) + FieldBuilder DefineField(string name, RuntimeJavaType tw, FieldAttributes attribs, bool isVolatile) { - Type[] modreq = isVolatile ? new Type[] { wrapper.Context.Types.IsVolatile } : Type.EmptyTypes; + var modreq = isVolatile ? [wrapper.Context.Types.IsVolatile] : Type.EmptyTypes; return typeBuilder.DefineField(name, tw.TypeAsSignatureType, modreq, wrapper.GetModOpt(tw, false), attribs); } internal override void EmitRunClassConstructor(CodeEmitter ilgen) { if (clinitMethod != null) - { ilgen.Emit(OpCodes.Call, clinitMethod); - } } internal override DynamicImpl Finish() @@ -1255,7 +1244,7 @@ FinishedTypeImpl FinishCore() var wrappers = new List(); for (int i = 0; i < innerclasses.Length; i++) { - if (innerclasses[i].innerClass != 0 && innerclasses[i].outerClass != 0) + if (innerclasses[i].innerClass.IsNotNil && innerclasses[i].outerClass.IsNotNil) { if (classFile.GetConstantPoolClassType(innerclasses[i].outerClass) == wrapper) { @@ -1930,7 +1919,7 @@ internal override Modifiers ReflectiveModifiers { for (int i = 0; i < innerclasses.Length; i++) { - if (innerclasses[i].innerClass != 0) + if (innerclasses[i].innerClass.IsNotNil) { if (classFile.GetConstantPoolClass(innerclasses[i].innerClass) == wrapper.Name) { @@ -2554,10 +2543,8 @@ internal override MethodBase LinkMethod(RuntimeJavaMethod mw) } // copy runtime visible annotations as attributes - if (m.RuntimeVisibleTypeAnnotations != null) - { - wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(method, m.RuntimeVisibleTypeAnnotations); - } + if (m.RuntimeVisibleTypeAnnotations.Count > 0) + wrapper.Context.AttributeHelper.SetRuntimeVisibleTypeAnnotationsAttribute(method, in m.RuntimeVisibleTypeAnnotations); #else // IMPORTER @@ -2784,17 +2771,6 @@ MethodBuilder GenerateMethod(int index, ClassFile.Method m, ref bool setModifier if (classFile.IsInterface && !m.IsPublic && !wrapper.IsGhost) { var tb = typeBuilder; -#if IMPORTER - if (wrapper.IsPublic && wrapper.classLoader.WorkaroundInterfacePrivateMethods) - { - // FXBUG csc.exe doesn't like non-public methods in interfaces, so we put them in a nested type - if (privateInterfaceMethods == null) - privateInterfaceMethods = typeBuilder.DefineNestedType(NestedTypeName.PrivateInterfaceMethods, TypeAttributes.NestedPrivate | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit); - tb = privateInterfaceMethods; - attribs &= ~MethodAttributes.MemberAccessMask; - attribs |= MethodAttributes.Assembly; - } -#endif if (m.IsStatic) { mb = methods[index].GetDefineMethodHelper().DefineMethod(wrapper, tb, name, attribs); diff --git a/src/IKVM.Runtime/RuntimeByteCodeJavaType.Metadata.cs b/src/IKVM.Runtime/RuntimeByteCodeJavaType.Metadata.cs index a29a71359c..7a9f4745e5 100644 --- a/src/IKVM.Runtime/RuntimeByteCodeJavaType.Metadata.cs +++ b/src/IKVM.Runtime/RuntimeByteCodeJavaType.Metadata.cs @@ -21,11 +21,9 @@ Jeroen Frijters jeroen@frijters.net */ -using System.Collections.Generic; -using System.Linq; - -using IKVM.ByteCode.Parsing; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Buffers; +using IKVM.ByteCode.Decoding; +using IKVM.ByteCode.Encoding; namespace IKVM.Runtime { @@ -41,33 +39,6 @@ sealed partial class RuntimeByteCodeJavaType sealed class Metadata { - readonly string[][] genericMetaData; - readonly object[][] annotations; - readonly MethodParametersEntry[][] methodParameters; - readonly IReadOnlyList runtimeVisibleTypeAnnotations; - readonly IReadOnlyList[] fieldRuntimeVisibleTypeAnnotations; - readonly IReadOnlyList[] methodRuntimeVisibleTypeAnnotations; - readonly object[] constantPool; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - /// - /// - Metadata(string[][] genericMetaData, object[][] annotations, MethodParametersEntry[][] methodParameters, IReadOnlyList runtimeVisibleTypeAnnotations, IReadOnlyList[] fieldRuntimeVisibleTypeAnnotations, IReadOnlyList[] methodRuntimeVisibleTypeAnnotations, object[] constantPool) - { - this.genericMetaData = genericMetaData; - this.annotations = annotations; - this.methodParameters = methodParameters; - this.runtimeVisibleTypeAnnotations = runtimeVisibleTypeAnnotations; - this.fieldRuntimeVisibleTypeAnnotations = fieldRuntimeVisibleTypeAnnotations; - this.methodRuntimeVisibleTypeAnnotations = methodRuntimeVisibleTypeAnnotations; - this.constantPool = constantPool; - } - internal static Metadata Create(ClassFile classFile) { if (classFile.MajorVersion < 49) @@ -76,9 +47,9 @@ internal static Metadata Create(ClassFile classFile) string[][] genericMetaData = null; object[][] annotations = null; MethodParametersEntry[][] methodParameters = null; - IReadOnlyList runtimeVisibleTypeAnnotations = null; - IReadOnlyList[] fieldRuntimeVisibleTypeAnnotations = null; - IReadOnlyList[] methodRuntimeVisibleTypeAnnotations = null; + TypeAnnotationTable runtimeVisibleTypeAnnotations = TypeAnnotationTable.Empty; + TypeAnnotationTable[] fieldRuntimeVisibleTypeAnnotations = null; + TypeAnnotationTable[] methodRuntimeVisibleTypeAnnotations = null; if (classFile.EnclosingMethod != null) { @@ -98,7 +69,7 @@ internal static Metadata Create(ClassFile classFile) annotations[0] = classFile.Annotations; } - if (classFile.RuntimeVisibleTypeAnnotations != null) + if (classFile.RuntimeVisibleTypeAnnotations.Count > 0) { runtimeVisibleTypeAnnotations = classFile.RuntimeVisibleTypeAnnotations; } @@ -139,9 +110,9 @@ internal static Metadata Create(ClassFile classFile) methodParameters[i] = classFile.Methods[i].MethodParameters; } - if (classFile.Methods[i].RuntimeVisibleTypeAnnotations != null) + if (classFile.Methods[i].RuntimeVisibleTypeAnnotations.Count > 0) { - methodRuntimeVisibleTypeAnnotations ??= new IReadOnlyList[classFile.Methods.Length]; + methodRuntimeVisibleTypeAnnotations ??= new TypeAnnotationTable[classFile.Methods.Length]; methodRuntimeVisibleTypeAnnotations[i] = classFile.Methods[i].RuntimeVisibleTypeAnnotations; } } @@ -162,16 +133,21 @@ internal static Metadata Create(ClassFile classFile) annotations[4][i] = classFile.Fields[i].Annotations; } - if (classFile.Fields[i].RuntimeVisibleTypeAnnotations != null) + if (classFile.Fields[i].RuntimeVisibleTypeAnnotations.Count > 0) { - fieldRuntimeVisibleTypeAnnotations ??= new IReadOnlyList[classFile.Fields.Length]; + fieldRuntimeVisibleTypeAnnotations ??= new TypeAnnotationTable[classFile.Fields.Length]; fieldRuntimeVisibleTypeAnnotations[i] = classFile.Fields[i].RuntimeVisibleTypeAnnotations; } } - if (genericMetaData != null || annotations != null || methodParameters != null || runtimeVisibleTypeAnnotations != null || fieldRuntimeVisibleTypeAnnotations != null || methodRuntimeVisibleTypeAnnotations != null) + if (genericMetaData != null || + annotations != null || + methodParameters != null || + runtimeVisibleTypeAnnotations.Count > 0 || + fieldRuntimeVisibleTypeAnnotations != null || + methodRuntimeVisibleTypeAnnotations != null) { - var constantPool = runtimeVisibleTypeAnnotations != null || fieldRuntimeVisibleTypeAnnotations != null || methodRuntimeVisibleTypeAnnotations != null ? classFile.GetConstantPool() : null; + var constantPool = runtimeVisibleTypeAnnotations.Count > 0 || fieldRuntimeVisibleTypeAnnotations != null || methodRuntimeVisibleTypeAnnotations != null ? classFile.GetConstantPool() : null; return new Metadata(genericMetaData, annotations, methodParameters, runtimeVisibleTypeAnnotations, fieldRuntimeVisibleTypeAnnotations, methodRuntimeVisibleTypeAnnotations, constantPool); } @@ -181,81 +157,72 @@ internal static Metadata Create(ClassFile classFile) internal static string GetGenericSignature(Metadata m) { if (m != null && m.genericMetaData != null && m.genericMetaData[3] != null) - { return m.genericMetaData[3][0]; - } + return null; } internal static string[] GetEnclosingMethod(Metadata m) { if (m != null && m.genericMetaData != null) - { return m.genericMetaData[2]; - } + return null; } internal static string GetGenericMethodSignature(Metadata m, int index) { if (m != null && m.genericMetaData != null && m.genericMetaData[0] != null) - { return m.genericMetaData[0][index]; - } + return null; } internal static string GetGenericFieldSignature(Metadata m, int index) { if (m != null && m.genericMetaData != null && m.genericMetaData[1] != null) - { return m.genericMetaData[1][index]; - } + return null; } internal static object[] GetAnnotations(Metadata m) { if (m != null && m.annotations != null) - { return m.annotations[0]; - } + return null; } internal static object[] GetMethodAnnotations(Metadata m, int index) { if (m != null && m.annotations != null && m.annotations[1] != null) - { return (object[])m.annotations[1][index]; - } + return null; } internal static object[][] GetMethodParameterAnnotations(Metadata m, int index) { if (m != null && m.annotations != null && m.annotations[2] != null) - { return (object[][])m.annotations[2][index]; - } + return null; } internal static MethodParametersEntry[] GetMethodParameters(Metadata m, int index) { if (m != null && m.methodParameters != null) - { return m.methodParameters[index]; - } + return null; } internal static object GetMethodDefaultValue(Metadata m, int index) { if (m != null && m.annotations != null && m.annotations[3] != null) - { return m.annotations[3][index]; - } + return null; } @@ -263,9 +230,8 @@ internal static object GetMethodDefaultValue(Metadata m, int index) internal static object[] GetFieldAnnotations(Metadata m, int index) { if (m != null && m.annotations != null && m.annotations[4] != null) - { return (object[])m.annotations[4][index]; - } + return null; } @@ -276,40 +242,64 @@ internal static object[] GetConstantPool(Metadata m) internal static byte[] GetRawTypeAnnotations(Metadata m) { - if (m != null && m.runtimeVisibleTypeAnnotations != null) - return SerializeTypeAnnotations(m.runtimeVisibleTypeAnnotations); - else - return null; + if (m != null) + return SerializeTypeAnnotations(in m.runtimeVisibleTypeAnnotations); + + return null; } internal static byte[] GetMethodRawTypeAnnotations(Metadata m, int index) { if (m != null && m.methodRuntimeVisibleTypeAnnotations != null) - return SerializeTypeAnnotations(m.methodRuntimeVisibleTypeAnnotations[index]); - else - return null; + return SerializeTypeAnnotations(in m.methodRuntimeVisibleTypeAnnotations[index]); + + return null; } internal static byte[] GetFieldRawTypeAnnotations(Metadata m, int index) { if (m != null && m.fieldRuntimeVisibleTypeAnnotations != null) - return SerializeTypeAnnotations(m.fieldRuntimeVisibleTypeAnnotations[index]); - else - return null; + return SerializeTypeAnnotations(in m.fieldRuntimeVisibleTypeAnnotations[index]); + + return null; } - static byte[] SerializeTypeAnnotations(IReadOnlyList annotations) + static byte[] SerializeTypeAnnotations(ref readonly TypeAnnotationTable annotations) { - if (annotations == null) + if (annotations.Count == 0) return null; - var record = new RuntimeVisibleTypeAnnotationsAttributeRecord(annotations.Select(i => i.Record).ToArray()); - var buffer = new byte[record.GetSize()]; - var writer = new ClassFormatWriter(buffer); - if (record.TryWrite(ref writer) == false) - throw new InternalException("Failed to serialize raw type annotations."); + var builder = new BlobBuilder(); + var encoder = new TypeAnnotationTableEncoder(builder); + annotations.WriteTo(ref encoder); + return builder.ToArray(); + } + + readonly string[][] genericMetaData; + readonly object[][] annotations; + readonly MethodParametersEntry[][] methodParameters; + readonly TypeAnnotationTable runtimeVisibleTypeAnnotations; + readonly TypeAnnotationTable[] fieldRuntimeVisibleTypeAnnotations; + readonly TypeAnnotationTable[] methodRuntimeVisibleTypeAnnotations; + readonly object[] constantPool; - return buffer; + /// + /// Initializes a new instance. + /// + /// + /// + /// + /// + /// + Metadata(string[][] genericMetaData, object[][] annotations, MethodParametersEntry[][] methodParameters, TypeAnnotationTable runtimeVisibleTypeAnnotations, TypeAnnotationTable[] fieldRuntimeVisibleTypeAnnotations, TypeAnnotationTable[] methodRuntimeVisibleTypeAnnotations, object[] constantPool) + { + this.genericMetaData = genericMetaData; + this.annotations = annotations; + this.methodParameters = methodParameters; + this.runtimeVisibleTypeAnnotations = runtimeVisibleTypeAnnotations; + this.fieldRuntimeVisibleTypeAnnotations = fieldRuntimeVisibleTypeAnnotations; + this.methodRuntimeVisibleTypeAnnotations = methodRuntimeVisibleTypeAnnotations; + this.constantPool = constantPool; } } diff --git a/src/IKVM.Runtime/RuntimeClassLoader.cs b/src/IKVM.Runtime/RuntimeClassLoader.cs index 3c8717e041..044b4189a5 100644 --- a/src/IKVM.Runtime/RuntimeClassLoader.cs +++ b/src/IKVM.Runtime/RuntimeClassLoader.cs @@ -195,42 +195,6 @@ RuntimeJavaType RegisterInitiatingLoaderCritical(RuntimeJavaType tw) internal bool EnableOptimizations => (codegenoptions & CodeGenOptions.DisableOptimizations) == 0; - internal bool WorkaroundAbstractMethodWidening - { - get - { - // pre-Roslyn C# compiler doesn't like widening access to abstract methods - return true; - } - } - - internal bool WorkaroundInterfaceFields - { - get - { - // pre-Roslyn C# compiler doesn't allow access to interface fields - return true; - } - } - - internal bool WorkaroundInterfacePrivateMethods - { - get - { - // pre-Roslyn C# compiler doesn't like interfaces that have non-public methods - return true; - } - } - - internal bool WorkaroundInterfaceStaticMethods - { - get - { - // pre-Roslyn C# compiler doesn't allow access to interface static methods - return true; - } - } - #if !IMPORTER && !EXPORTER #if FIRST_PASS == false diff --git a/src/IKVM.Runtime/RuntimeContext.cs b/src/IKVM.Runtime/RuntimeContext.cs index ed9e4fe051..e2ef4cdc49 100644 --- a/src/IKVM.Runtime/RuntimeContext.cs +++ b/src/IKVM.Runtime/RuntimeContext.cs @@ -197,6 +197,7 @@ T GetOrCreateSingleton(ref T value, Func create) /// /// Gets the associated with this instance of the runtime. /// + /// public CompilerFactory CompilerFactory => GetOrCreateSingleton(ref compilerFactory, () => new CompilerFactory(this, bootstrap)); /// diff --git a/src/IKVM.Runtime/System/Index.cs b/src/IKVM.Runtime/System/Index.cs new file mode 100644 index 0000000000..15312fffdc --- /dev/null +++ b/src/IKVM.Runtime/System/Index.cs @@ -0,0 +1,152 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#if NETSTANDARD2_1 +[assembly: TypeForwardedTo(typeof(System.Index))] +#else +using System.Runtime.CompilerServices; + +namespace System; + +/// Represent a type can be used to index a collection either from the start or the end. +/// +/// Index is used by the C# compiler to support the new index syntax +/// +/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; +/// int lastElement = someArray[^1]; // lastElement = 5 +/// +/// +public readonly struct Index : IEquatable +{ + private readonly int _value; + + /// Construct an Index using a value and indicating if the index is from the start or from the end. + /// The index value. it has to be zero or positive number. + /// Indicating if the index is from the start or from the end. + /// + /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// +#if !NET35 + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public Index(int value, bool fromEnd = false) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + } + + if (fromEnd) + _value = ~value; + else + _value = value; + } + + // The following private constructors mainly created for perf reason to avoid the checks + private Index(int value) + { + _value = value; + } + + /// Create an Index pointing at first element. + public static Index Start => new Index(0); + + /// Create an Index pointing at beyond last element. + public static Index End => new Index(~0); + + /// Create an Index from the start at the position indicated by the value. + /// The index value from the start. +#if !NET35 + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Index FromStart(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + } + + return new Index(value); + } + + /// Create an Index from the end at the position indicated by the value. + /// The index value from the end. +#if !NET35 + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public static Index FromEnd(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + } + + return new Index(~value); + } + + /// Returns the index value. + public int Value + { + get + { + if (_value < 0) + return ~_value; + else + return _value; + } + } + + /// Indicates whether the index is from the start or the end. + public bool IsFromEnd => _value < 0; + + /// Calculate the offset from the start using the giving collection length. + /// The length of the collection that the Index will be used with. length has to be a positive value + /// + /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. + /// we don't validate either the returned offset is greater than the input length. + /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and + /// then used to index a collection will get out of range exception which will be same affect as the validation. + /// +#if !NET35 + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + public int GetOffset(int length) + { + int offset = _value; + if (IsFromEnd) + { + // offset = length - (~value) + // offset = length + (~(~value) + 1) + // offset = length + value + 1 + + offset += length + 1; + } + return offset; + } + + /// Indicates whether the current Index object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value; + + /// Indicates whether the current Index object is equal to another Index object. + /// An object to compare with this object + public bool Equals(Index other) => _value == other._value; + + /// Returns the hash code for this instance. + public override int GetHashCode() => _value; + + /// Converts integer number to an Index. + public static implicit operator Index(int value) => FromStart(value); + + /// Converts the value of the current Index object to its equivalent string representation. + public override string ToString() + { + if (IsFromEnd) + return "^" + ((uint)Value).ToString(); + + return ((uint)Value).ToString(); + } +} + +#endif diff --git a/src/IKVM.Runtime/System/Range.cs b/src/IKVM.Runtime/System/Range.cs new file mode 100644 index 0000000000..45884ff5d2 --- /dev/null +++ b/src/IKVM.Runtime/System/Range.cs @@ -0,0 +1,95 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#if NETSTANDARD2_1 +[assembly: TypeForwardedTo(typeof(System.Range))] +#else +using System.Runtime.CompilerServices; + +namespace System; + +/// Represent a range has start and end indexes. +/// +/// Range is used by the C# compiler to support the range syntax. +/// +/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; +/// int[] subArray1 = someArray[0..2]; // { 1, 2 } +/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } +/// +/// +public readonly struct Range : IEquatable +{ + /// Represent the inclusive start index of the Range. + public Index Start { get; } + + /// Represent the exclusive end index of the Range. + public Index End { get; } + + /// Construct a Range object using the start and end indexes. + /// Represent the inclusive start index of the range. + /// Represent the exclusive end index of the range. + public Range(Index start, Index end) + { + Start = start; + End = end; + } + + /// Indicates whether the current Range object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => + value is Range r && + r.Start.Equals(Start) && + r.End.Equals(End); + + /// Indicates whether the current Range object is equal to another Range object. + /// An object to compare with this object + public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); + + /// Returns the hash code for this instance. + public override int GetHashCode() + { + return Start.GetHashCode() * 31 + End.GetHashCode(); + } + + /// Converts the value of the current Range object to its equivalent string representation. + public override string ToString() + { + return Start + ".." + End; + } + + /// Create a Range object starting from start index to the end of the collection. + public static Range StartAt(Index start) => new Range(start, Index.End); + + /// Create a Range object starting from first element in the collection to the end Index. + public static Range EndAt(Index end) => new Range(Index.Start, end); + + /// Create a Range object starting from first element to the end. + public static Range All => new Range(Index.Start, Index.End); + + /// Calculate the start offset and length of range object using a collection length. + /// The length of the collection that the range will be used with. length has to be a positive value. + /// + /// For performance reason, we don't validate the input length parameter against negative values. + /// It is expected Range will be used with collections which always have non negative length/count. + /// We validate the range is inside the length scope though. + /// +#if !NET35 + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + [CLSCompliant(false)] + public (int Offset, int Length) GetOffsetAndLength(int length) + { + int start = Start.GetOffset(length); + int end = End.GetOffset(length); + + if ((uint)end > (uint)length || (uint)start > (uint)end) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + return (start, end - start); + } +} + +#endif diff --git a/src/IKVM.Runtime/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/IKVM.Runtime/System/Runtime/CompilerServices/RuntimeHelpers.cs new file mode 100644 index 0000000000..6ca51f3a78 --- /dev/null +++ b/src/IKVM.Runtime/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -0,0 +1,5 @@ +#if NETFRAMEWORK + + + +#endif diff --git a/src/IKVM.Runtime/UntangledExceptionTable.cs b/src/IKVM.Runtime/UntangledExceptionTable.cs index cf12988fb8..ee75376816 100644 --- a/src/IKVM.Runtime/UntangledExceptionTable.cs +++ b/src/IKVM.Runtime/UntangledExceptionTable.cs @@ -71,7 +71,7 @@ internal int Length internal void SetFinally(int index) { - exceptions[index] = new ExceptionTableEntry(exceptions[index].startIndex, exceptions[index].endIndex, exceptions[index].handlerIndex, exceptions[index].catch_type, exceptions[index].ordinal, true); + exceptions[index] = new ExceptionTableEntry(exceptions[index].startIndex, exceptions[index].endIndex, exceptions[index].handlerIndex, exceptions[index].catchType, exceptions[index].ordinal, true); } } diff --git a/src/IKVM.Runtime/Util/Java/Lang/Invoke/NativeInvokerBytecodeGenerator.cs b/src/IKVM.Runtime/Util/Java/Lang/Invoke/NativeInvokerBytecodeGenerator.cs index a69357895c..eb8231736f 100644 --- a/src/IKVM.Runtime/Util/Java/Lang/Invoke/NativeInvokerBytecodeGenerator.cs +++ b/src/IKVM.Runtime/Util/Java/Lang/Invoke/NativeInvokerBytecodeGenerator.cs @@ -40,7 +40,7 @@ using BasicType = global::java.lang.invoke.LambdaForm.BasicType; using Class = global::java.lang.Class; using Name = global::java.lang.invoke.LambdaForm.Name; -using Opcodes = jdk.@internal.org.objectweb.asm.Opcodes.__Fields; +using Opcodes = jdk.@internal.org.objectweb.asm.Opcodes; using VerifyType = global::sun.invoke.util.VerifyType; using Wrapper = global::sun.invoke.util.Wrapper; #endif diff --git a/src/IKVM.Runtime/Vfs/VfsCacertsFile.cs b/src/IKVM.Runtime/Vfs/VfsCacertsFile.cs deleted file mode 100644 index 8530bc20a7..0000000000 --- a/src/IKVM.Runtime/Vfs/VfsCacertsFile.cs +++ /dev/null @@ -1,113 +0,0 @@ -/* - Copyright (C) 2007-2011 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ -using System; -using System.Collections.Generic; -using System.IO; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; - -namespace IKVM.Runtime.Vfs -{ - - /// - /// Represents a fake cacerts file. - /// - internal sealed class VfsCacertsFile : VfsFile - { - - readonly Lazy buff; - - /// - /// Initializes a new instance. - /// - /// - internal VfsCacertsFile(VfsContext context) : - base(context) - { - this.buff = new Lazy(GenerateCacertsFile, true); - } - - /// - /// Gets the class file. - /// - /// - byte[] GenerateCacertsFile() - { -#if FIRST_PASS || IMPORTER || EXPORTER - throw new NotImplementedException(); -#else - var jstore = java.security.KeyStore.getInstance("jks"); - jstore.load(null); - var cf = java.security.cert.CertificateFactory.getInstance("X509"); - var aliases = new HashSet(); - - // import both local machine and current user certificates - foreach (var storeLocation in new[] { StoreLocation.LocalMachine, StoreLocation.CurrentUser }) - { - try - { - using var store = new X509Store(StoreName.Root, storeLocation); - store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); - - foreach (X509Certificate2 cert in store.Certificates) - { - // only interested in trust information - if (cert.HasPrivateKey) - continue; - - // the alias must be unique, otherwise we overwrite the previous certificate with that alias - var alias = cert.Subject; - var index = 0; - while (aliases.Add(alias) == false) - alias = cert.Subject + " #" + (++index); - - jstore.setCertificateEntry(alias, cf.generateCertificate(new java.io.ByteArrayInputStream(cert.RawData))); - } - } - catch (CryptographicException) - { - // ignore - } - } - - var baos = new java.io.ByteArrayOutputStream(); - jstore.store(baos, "changeit".ToCharArray()); - return baos.toByteArray(); -#endif - } - - /// - /// Opens the class file. - /// - /// - protected override Stream OpenRead() => new MemoryStream(buff.Value); - - /// - /// Gets the length of the class file. - /// - public override long Size => buff.Value.Length; - - } - -} diff --git a/src/IKVM.Runtime/Vfs/VfsTable.cs b/src/IKVM.Runtime/Vfs/VfsTable.cs index 436088b62e..dd29ee4437 100644 --- a/src/IKVM.Runtime/Vfs/VfsTable.cs +++ b/src/IKVM.Runtime/Vfs/VfsTable.cs @@ -33,7 +33,6 @@ public static VfsTable BuildDefaultTable(VfsContext context, string ikvmHome) var table = new VfsTable(context); table.AddMount(Path.Combine(ikvmHome, "assembly"), new VfsAssemblyDirectory(context)); - //table.AddMount(Path.Combine(ikvmHome, "lib", "security", "cacerts"), new VfsCacertsFile(context)); return table; #endif } diff --git a/src/IKVM.Runtime/compiler.cs b/src/IKVM.Runtime/compiler.cs index 7dde59526f..d141799c86 100644 --- a/src/IKVM.Runtime/compiler.cs +++ b/src/IKVM.Runtime/compiler.cs @@ -930,7 +930,7 @@ void Compile(Block block, int startIndex) int handlerIndex = exc.handlerIndex; - if (exc.catch_type == 0 && RuntimeVerifierJavaType.IsFaultBlockException(ma.GetRawStackTypeWrapper(handlerIndex, 0))) + if (exc.catchType.IsNil && RuntimeVerifierJavaType.IsFaultBlockException(ma.GetRawStackTypeWrapper(handlerIndex, 0))) { if (exc.isFinally) { @@ -949,14 +949,14 @@ void Compile(Block block, int startIndex) { RuntimeJavaType exceptionTypeWrapper; bool remap; - if (exc.catch_type == 0) + if (exc.catchType.IsNil) { exceptionTypeWrapper = finish.Context.JavaBase.TypeOfjavaLangThrowable; remap = true; } else { - exceptionTypeWrapper = classFile.GetConstantPoolClassType(exc.catch_type); + exceptionTypeWrapper = classFile.GetConstantPoolClassType(exc.catchType); remap = exceptionTypeWrapper.IsUnloadable || !exceptionTypeWrapper.IsSubTypeOf(finish.Context.JavaBase.TypeOfCliSystemException); } Type excType = exceptionTypeWrapper.TypeAsExceptionType; @@ -1258,11 +1258,11 @@ void Compile(Block block, int startIndex) break; case NormalizedByteCode.__ldc_nothrow: case NormalizedByteCode.__ldc: - EmitLoadConstant(ilGenerator, instr.Arg1); + EmitLoadConstant(ilGenerator, new ConstantHandle(ConstantKind.Unknown, (ushort)instr.Arg1)); break; case NormalizedByteCode.__invokedynamic: { - var cpi = classFile.GetInvokeDynamic(instr.Arg1); + var cpi = classFile.GetInvokeDynamic(new((ushort)instr.Arg1)); CastInterfaceArgs(null, cpi.GetArgTypes(), i, false); if (!LambdaMetafactory.Emit(finish, classFile, instr.Arg1, cpi, ilGenerator)) { @@ -2618,37 +2618,37 @@ void EmitReturnTypeConversion(RuntimeJavaType returnType) } } - void EmitLoadConstant(CodeEmitter ilgen, int constant) + void EmitLoadConstant(CodeEmitter ilgen, ConstantHandle constant) { switch (classFile.GetConstantPoolConstantType(constant)) { case ClassFile.ConstantType.Double: - ilgen.EmitLdc_R8(classFile.GetConstantPoolConstantDouble(constant)); + ilgen.EmitLdc_R8(classFile.GetConstantPoolConstantDouble((DoubleConstantHandle)constant)); break; case ClassFile.ConstantType.Float: - ilgen.EmitLdc_R4(classFile.GetConstantPoolConstantFloat(constant)); + ilgen.EmitLdc_R4(classFile.GetConstantPoolConstantFloat((FloatConstantHandle)constant)); break; case ClassFile.ConstantType.Integer: - ilgen.EmitLdc_I4(classFile.GetConstantPoolConstantInteger(constant)); + ilgen.EmitLdc_I4(classFile.GetConstantPoolConstantInteger((IntegerConstantHandle)constant)); break; case ClassFile.ConstantType.Long: - ilgen.EmitLdc_I8(classFile.GetConstantPoolConstantLong(constant)); + ilgen.EmitLdc_I8(classFile.GetConstantPoolConstantLong((LongConstantHandle)constant)); break; case ClassFile.ConstantType.String: - ilgen.Emit(OpCodes.Ldstr, classFile.GetConstantPoolConstantString(constant)); + ilgen.Emit(OpCodes.Ldstr, classFile.GetConstantPoolConstantString((StringConstantHandle)constant)); break; case ClassFile.ConstantType.Class: - EmitLoadClass(ilgen, classFile.GetConstantPoolClassType(constant)); + EmitLoadClass(ilgen, classFile.GetConstantPoolClassType((ClassConstantHandle)constant)); break; case ClassFile.ConstantType.MethodHandle: - finish.GetValue(constant).Emit(this, ilgen, constant); + finish.GetValue(constant.Slot).Emit(this, ilgen, (MethodHandleConstantHandle)constant); break; case ClassFile.ConstantType.MethodType: - finish.GetValue(constant).Emit(this, ilgen, constant); + finish.GetValue(constant.Slot).Emit(this, ilgen, (MethodTypeConstantHandle)constant); break; #if !IMPORTER case ClassFile.ConstantType.LiveObject: - finish.EmitLiveObjectLoad(ilgen, classFile.GetConstantPoolConstantLiveObject(constant)); + finish.EmitLiveObjectLoad(ilgen, classFile.GetConstantPoolConstantLiveObject(constant.Slot)); break; #endif default: @@ -2832,17 +2832,17 @@ static bool EmitCallBootstrapMethod(Compiler compiler, ClassFile.ConstantPoolIte var mw = mh.Member as RuntimeJavaMethod; switch (mh.Kind) { - case ReferenceKind.InvokeStatic: + case MethodHandleKind.InvokeStatic: if (mw != null && !mw.IsStatic) goto default; break; - case ReferenceKind.NewInvokeSpecial: + case MethodHandleKind.NewInvokeSpecial: if (mw != null && !mw.IsConstructor) goto default; break; default: // to throw the right exception, we have to resolve the MH constant here - compiler.finish.GetValue(bsm.BootstrapMethodIndex).Emit(compiler, ilgen, bsm.BootstrapMethodIndex); + compiler.finish.GetValue(bsm.BootstrapMethodIndex.Slot).Emit(compiler, ilgen, bsm.BootstrapMethodIndex); ilgen.Emit(OpCodes.Pop); ilgen.EmitLdc_I4(1); ilgen.Emit(OpCodes.Stloc, ok); @@ -2853,7 +2853,7 @@ static bool EmitCallBootstrapMethod(Compiler compiler, ClassFile.ConstantPoolIte if (mw == null) { // to throw the right exception (i.e. without wrapping it in a BootstrapMethodError), we have to resolve the MH constant here - compiler.finish.GetValue(bsm.BootstrapMethodIndex).Emit(compiler, ilgen, bsm.BootstrapMethodIndex); + compiler.finish.GetValue(bsm.BootstrapMethodIndex.Slot).Emit(compiler, ilgen, bsm.BootstrapMethodIndex); ilgen.Emit(OpCodes.Pop); if (mh.MemberConstantPoolItem is ClassFile.ConstantPoolItemMI cpiMI) { @@ -2939,7 +2939,7 @@ static bool EmitCallBootstrapMethod(Compiler compiler, ClassFile.ConstantPoolIte static void EmitExtraArg(Compiler compiler, CodeEmitter ilgen, ClassFile.BootstrapMethod bsm, int index, RuntimeJavaType targetType, CodeEmitterLocal wrapException) { - int constant = bsm.GetArgument(index); + var constant = bsm.GetArgument(index); compiler.EmitLoadConstant(ilgen, constant); var constType = compiler.classFile.GetConstantPoolConstantType(constant) switch @@ -3041,12 +3041,12 @@ sealed class MethodHandleConstant FieldBuilder field; - internal void Emit(Compiler compiler, CodeEmitter ilgen, int index) + internal void Emit(Compiler compiler, CodeEmitter ilgen, MethodHandleConstantHandle handle) { if (field == null) field = compiler.finish.DefineDynamicMethodHandleCacheField(); - var mh = compiler.classFile.GetConstantPoolConstantMethodHandle(index); + var mh = compiler.classFile.GetConstantPoolConstantMethodHandle(handle); ilgen.Emit(OpCodes.Ldsflda, field); ilgen.EmitLdc_I4((int)mh.Kind); ilgen.Emit(OpCodes.Ldstr, mh.Class); @@ -3064,15 +3064,15 @@ sealed class MethodTypeConstant FieldBuilder field; bool dynamic; - internal void Emit(Compiler compiler, CodeEmitter ilgen, int index) + internal void Emit(Compiler compiler, CodeEmitter ilgen, MethodTypeConstantHandle handle) { if (field == null) - field = CreateField(compiler, index, ref dynamic); + field = CreateField(compiler, handle, ref dynamic); if (dynamic) { ilgen.Emit(OpCodes.Ldsflda, field); - ilgen.Emit(OpCodes.Ldstr, compiler.classFile.GetConstantPoolConstantMethodType(index).Signature); + ilgen.Emit(OpCodes.Ldstr, compiler.classFile.GetConstantPoolConstantMethodType(handle).Signature); compiler.finish.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled); ilgen.Emit(OpCodes.Call, compiler.finish.Context.ByteCodeHelperMethods.DynamicLoadMethodType); } @@ -3082,9 +3082,9 @@ internal void Emit(Compiler compiler, CodeEmitter ilgen, int index) } } - static FieldBuilder CreateField(Compiler compiler, int index, ref bool dynamic) + static FieldBuilder CreateField(Compiler compiler, MethodTypeConstantHandle handle, ref bool dynamic) { - var cpi = compiler.classFile.GetConstantPoolConstantMethodType(index); + var cpi = compiler.classFile.GetConstantPoolConstantMethodType(handle); var args = cpi.GetArgTypes(); var ret = cpi.GetRetType(); @@ -3095,7 +3095,7 @@ static FieldBuilder CreateField(Compiler compiler, int index, ref bool dynamic) } else { - var tb = compiler.finish.DefineMethodTypeConstantType(index); + var tb = compiler.finish.DefineMethodTypeConstantType(handle); var field = tb.DefineField("value", compiler.finish.Context.JavaBase.TypeOfJavaLangInvokeMethodType.TypeAsSignatureType, FieldAttributes.Assembly | FieldAttributes.Static | FieldAttributes.InitOnly); var ilgen = compiler.finish.Context.CodeEmitterFactory.Create(ReflectUtil.DefineTypeInitializer(tb, compiler.clazz.GetClassLoader())); var delegateType = compiler.finish.Context.MethodHandleUtil.CreateDelegateTypeForLoadConstant(args, ret); @@ -3313,31 +3313,31 @@ private bool NeedsInterfaceDownCast(RuntimeJavaType tw, RuntimeJavaType arg) private void DynamicGetPutField(Instruction instr, int i) { - ReferenceKind kind; + MethodHandleKind kind; switch (instr.NormalizedOpCode) { case NormalizedByteCode.__dynamic_getfield: Profiler.Count("EmitDynamicGetfield"); - kind = ReferenceKind.GetField; + kind = MethodHandleKind.GetField; break; case NormalizedByteCode.__dynamic_putfield: Profiler.Count("EmitDynamicPutfield"); - kind = ReferenceKind.PutField; + kind = MethodHandleKind.PutField; break; case NormalizedByteCode.__dynamic_getstatic: Profiler.Count("EmitDynamicGetstatic"); - kind = ReferenceKind.GetStatic; + kind = MethodHandleKind.GetStatic; break; case NormalizedByteCode.__dynamic_putstatic: Profiler.Count("EmitDynamicPutstatic"); - kind = ReferenceKind.PutStatic; + kind = MethodHandleKind.PutStatic; break; default: throw new InvalidOperationException(); } ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1); RuntimeJavaType fieldType = cpi.GetFieldType(); - if (kind == ReferenceKind.PutField || kind == ReferenceKind.PutStatic) + if (kind == MethodHandleKind.PutField || kind == MethodHandleKind.PutStatic) { fieldType.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0)); if (strictfp) @@ -3350,7 +3350,7 @@ private void DynamicGetPutField(Instruction instr, int i) } } finish.GetValue(instr.Arg1 | ((byte)kind << 24)).Emit(this, cpi, kind); - if (kind == ReferenceKind.GetField || kind == ReferenceKind.GetStatic) + if (kind == MethodHandleKind.GetField || kind == MethodHandleKind.GetStatic) { fieldType.EmitConvSignatureTypeToStackType(ilGenerator); } @@ -3612,63 +3612,64 @@ private sealed class DynamicFieldBinder { private MethodInfo method; - internal void Emit(Compiler compiler, ClassFile.ConstantPoolItemFieldref cpi, ReferenceKind kind) + internal void Emit(Compiler compiler, ClassFile.ConstantPoolItemFieldref cpi, MethodHandleKind kind) { if (method == null) - { method = CreateMethod(compiler, cpi, kind); - } + compiler.ilGenerator.Emit(OpCodes.Call, method); } - private static MethodInfo CreateMethod(Compiler compiler, ClassFile.ConstantPoolItemFieldref cpi, ReferenceKind kind) + private static MethodInfo CreateMethod(Compiler compiler, ClassFile.ConstantPoolItemFieldref cpi, MethodHandleKind kind) { RuntimeJavaType ret; RuntimeJavaType[] args; switch (kind) { - case ReferenceKind.GetField: + case MethodHandleKind.GetField: ret = cpi.GetFieldType(); - args = new RuntimeJavaType[] { cpi.GetClassType() }; + args = new[] { cpi.GetClassType() }; break; - case ReferenceKind.GetStatic: + case MethodHandleKind.GetStatic: ret = cpi.GetFieldType(); args = Array.Empty(); break; - case ReferenceKind.PutField: + case MethodHandleKind.PutField: ret = compiler.finish.Context.PrimitiveJavaTypeFactory.VOID; - args = new RuntimeJavaType[] { cpi.GetClassType(), cpi.GetFieldType() }; + args = new[] { cpi.GetClassType(), cpi.GetFieldType() }; break; - case ReferenceKind.PutStatic: + case MethodHandleKind.PutStatic: ret = compiler.finish.Context.PrimitiveJavaTypeFactory.VOID; - args = new RuntimeJavaType[] { cpi.GetFieldType() }; + args = new[] { cpi.GetFieldType() }; break; default: throw new InvalidOperationException(); } + return DynamicBinder.Emit(compiler, kind, cpi, ret, args, false); } } private sealed class DynamicBinder { - private RuntimeJavaMethod mw; - internal RuntimeJavaMethod Get(Compiler compiler, ReferenceKind kind, ClassFile.ConstantPoolItemMI cpi, bool privileged) + RuntimeJavaMethod mw; + + internal RuntimeJavaMethod Get(Compiler compiler, MethodHandleKind kind, ClassFile.ConstantPoolItemMI cpi, bool privileged) { - return mw ?? (mw = new DynamicBinderMethodWrapper(cpi, Emit(compiler, kind, cpi, privileged), kind)); + return mw ??= new DynamicBinderMethodWrapper(cpi, Emit(compiler, kind, cpi, privileged), kind); } - private static MethodInfo Emit(Compiler compiler, ReferenceKind kind, ClassFile.ConstantPoolItemMI cpi, bool privileged) + private static MethodInfo Emit(Compiler compiler, MethodHandleKind kind, ClassFile.ConstantPoolItemMI cpi, bool privileged) { RuntimeJavaType ret; RuntimeJavaType[] args; - if (kind == ReferenceKind.InvokeStatic) + if (kind == MethodHandleKind.InvokeStatic) { ret = cpi.GetRetType(); args = cpi.GetArgTypes(); } - else if (kind == ReferenceKind.NewInvokeSpecial) + else if (kind == MethodHandleKind.NewInvokeSpecial) { ret = cpi.GetClassType(); args = cpi.GetArgTypes(); @@ -3681,20 +3682,19 @@ private static MethodInfo Emit(Compiler compiler, ReferenceKind kind, ClassFile. return Emit(compiler, kind, cpi, ret, args, privileged); } - internal static MethodInfo Emit(Compiler compiler, ReferenceKind kind, ClassFile.ConstantPoolItemFMI cpi, RuntimeJavaType ret, RuntimeJavaType[] args, bool privileged) + internal static MethodInfo Emit(Compiler compiler, MethodHandleKind kind, ClassFile.ConstantPoolItemFMI cpi, RuntimeJavaType ret, RuntimeJavaType[] args, bool privileged) { - bool ghostTarget = (kind == ReferenceKind.InvokeSpecial || kind == ReferenceKind.InvokeVirtual || kind == ReferenceKind.InvokeInterface) && args[0].IsGhost; - Type delegateType = compiler.finish.Context.MethodHandleUtil.CreateMethodHandleDelegateType(args, ret); - FieldBuilder fb = compiler.finish.DefineMethodHandleInvokeCacheField(delegateType); - Type[] types = new Type[args.Length]; + var ghostTarget = (kind == MethodHandleKind.InvokeSpecial || kind == MethodHandleKind.InvokeVirtual || kind == MethodHandleKind.InvokeInterface) && args[0].IsGhost; + var delegateType = compiler.finish.Context.MethodHandleUtil.CreateMethodHandleDelegateType(args, ret); + var fb = compiler.finish.DefineMethodHandleInvokeCacheField(delegateType); + + var types = new Type[args.Length]; for (int i = 0; i < types.Length; i++) - { types[i] = args[i].TypeAsSignatureType; - } + if (ghostTarget) - { types[0] = types[0].MakeByRefType(); - } + MethodBuilder mb = compiler.finish.DefineMethodHandleDispatchStub(ret.TypeAsSignatureType, types); CodeEmitter ilgen = compiler.finish.Context.CodeEmitterFactory.Create(mb); ilgen.Emit(OpCodes.Ldsfld, fb); @@ -3731,12 +3731,13 @@ internal static MethodInfo Emit(Compiler compiler, ReferenceKind kind, ClassFile return mb; } - private sealed class DynamicBinderMethodWrapper : RuntimeJavaMethod + sealed class DynamicBinderMethodWrapper : RuntimeJavaMethod { - private readonly MethodInfo method; - internal DynamicBinderMethodWrapper(ClassFile.ConstantPoolItemMI cpi, MethodInfo method, ReferenceKind kind) - : base(cpi.GetClassType(), cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), kind == ReferenceKind.InvokeStatic ? Modifiers.Public | Modifiers.Static : Modifiers.Public, MemberFlags.None) + readonly MethodInfo method; + + internal DynamicBinderMethodWrapper(ClassFile.ConstantPoolItemMI cpi, MethodInfo method, MethodHandleKind kind) : + base(cpi.GetClassType(), cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), kind == MethodHandleKind.InvokeStatic ? Modifiers.Public | Modifiers.Static : Modifiers.Public, MemberFlags.None) { this.method = method; } @@ -3755,12 +3756,14 @@ internal override void EmitNewobj(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Call, method); } + } + } - private RuntimeJavaMethod GetMethodCallEmitter(NormalizedByteCode invoke, int constantPoolIndex) + RuntimeJavaMethod GetMethodCallEmitter(NormalizedByteCode invoke, int constantPoolIndex) { - var cpi = classFile.GetMethodref(constantPoolIndex); + var cpi = classFile.GetMethodref(new MethodrefConstantHandle(checked((ushort)constantPoolIndex))); #if IMPORTER if (replacedMethodWrappers != null) { @@ -3813,32 +3816,32 @@ private RuntimeJavaMethod GetMethodCallEmitter(NormalizedByteCode invoke, int co private RuntimeJavaMethod GetDynamicMethodWrapper(int index, NormalizedByteCode invoke, ClassFile.ConstantPoolItemMI cpi) { - ReferenceKind kind; + MethodHandleKind kind; switch (invoke) { case NormalizedByteCode.__invokeinterface: case NormalizedByteCode.__dynamic_invokeinterface: - kind = ReferenceKind.InvokeInterface; + kind = MethodHandleKind.InvokeInterface; break; case NormalizedByteCode.__invokestatic: case NormalizedByteCode.__dynamic_invokestatic: case NormalizedByteCode.__privileged_invokestatic: - kind = ReferenceKind.InvokeStatic; + kind = MethodHandleKind.InvokeStatic; break; case NormalizedByteCode.__invokevirtual: case NormalizedByteCode.__dynamic_invokevirtual: case NormalizedByteCode.__privileged_invokevirtual: - kind = ReferenceKind.InvokeVirtual; + kind = MethodHandleKind.InvokeVirtual; break; case NormalizedByteCode.__invokespecial: case NormalizedByteCode.__dynamic_invokespecial: - kind = ReferenceKind.NewInvokeSpecial; + kind = MethodHandleKind.NewInvokeSpecial; break; case NormalizedByteCode.__privileged_invokespecial: // we don't support calling a base class constructor kind = cpi.GetMethod().IsConstructor - ? ReferenceKind.NewInvokeSpecial - : ReferenceKind.InvokeSpecial; + ? MethodHandleKind.NewInvokeSpecial + : MethodHandleKind.InvokeSpecial; break; default: throw new InvalidOperationException(); diff --git a/src/IKVM.Tests/IKVM.Tests.csproj b/src/IKVM.Tests/IKVM.Tests.csproj index 43f73295b8..630fb1a303 100644 --- a/src/IKVM.Tests/IKVM.Tests.csproj +++ b/src/IKVM.Tests/IKVM.Tests.csproj @@ -8,7 +8,7 @@ true true false - 11 + 12 $(MSBuildProjectDirectory)\IKVM.Tests.runsettings diff --git a/src/IKVM.Tests/Java/java/beans/XMLEncoderTests.cs b/src/IKVM.Tests/Java/java/beans/XMLEncoderTests.cs index 415843f14b..70a944ac5e 100644 --- a/src/IKVM.Tests/Java/java/beans/XMLEncoderTests.cs +++ b/src/IKVM.Tests/Java/java/beans/XMLEncoderTests.cs @@ -156,7 +156,7 @@ public void exceptionThrown(global::java.lang.Exception e) [DataRow("Cp921")] [DataRow("Cp922")] [DataRow("Cp933")] - [DataRow("Cp943")] + //[DataRow("Cp943")] [DataRow("Cp948")] [DataRow("Cp949")] [DataRow("Cp950")] @@ -267,7 +267,7 @@ public void exceptionThrown(global::java.lang.Exception e) [DataRow("x-IBM921")] [DataRow("x-IBM922")] [DataRow("x-IBM933")] - [DataRow("x-IBM943")] + //[DataRow("x-IBM943")] [DataRow("x-IBM948")] [DataRow("x-IBM949")] [DataRow("x-IBM950")] diff --git a/src/IKVM.Tests/Java/java/lang/StrictMathTests.cs b/src/IKVM.Tests/Java/java/lang/StrictMathTests.cs new file mode 100644 index 0000000000..e16c44f1e6 --- /dev/null +++ b/src/IKVM.Tests/Java/java/lang/StrictMathTests.cs @@ -0,0 +1,22 @@ +using FluentAssertions; + +using java.lang; + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IKVM.Tests.Java.java.lang +{ + + [TestClass] + public class StrictMathTests + { + + [TestMethod] + public void AbsDouble() + { + StrictMath.abs(-1.5d).Should().Be(1.5d); + } + + } + +} diff --git a/src/IKVM.Tests/Java/java/lang/annotation/TypeAnnotationTests.cs b/src/IKVM.Tests/Java/java/lang/annotation/TypeAnnotationTests.cs index b9dfc3c654..f8bd954a9e 100644 --- a/src/IKVM.Tests/Java/java/lang/annotation/TypeAnnotationTests.cs +++ b/src/IKVM.Tests/Java/java/lang/annotation/TypeAnnotationTests.cs @@ -18,13 +18,13 @@ public class TypeAnnotationTests static readonly string[] FilesToBuild = new[] { - "TypeAnnotation1", - "TypeAnnotation2", - "TypeAnnotationArrayTest", - "TypeAnnotationClassTypeVarAndField", - "TypeAnnotationNestedTestOuter", - "TypeAnnotationNestedTest", - "TypeAnnotationWildcardTest" + "TypeAnnotation1", + "TypeAnnotation2", + "TypeAnnotationArrayTest", + "TypeAnnotationClassTypeVarAndField", + "TypeAnnotationNestedTestOuter", + "TypeAnnotationNestedTest", + "TypeAnnotationWildcardTest" }; static readonly string Package = "ikvm.tests.java.lang.annotation"; @@ -152,7 +152,6 @@ public void TestWildcardType() t.Length.Should().Be(0); t = w.getAnnotatedLowerBounds(); t.Length.Should().Be(1); - } } diff --git a/src/IKVM.Tests/Java/java/net/URLTests.cs b/src/IKVM.Tests/Java/java/net/URLTests.cs index b51ef08888..cc6b3f2939 100644 --- a/src/IKVM.Tests/Java/java/net/URLTests.cs +++ b/src/IKVM.Tests/Java/java/net/URLTests.cs @@ -50,8 +50,6 @@ public void CanCreateUnixFileURL() } [DataTestMethod] - [DataRow("tls-v1-0")] - [DataRow("tls-v1-1")] [DataRow("tls-v1-2")] [DataRow("sha256")] //[DataRow("sha384")] diff --git a/src/IKVM.Tests/Java/javax/script/BooleanAccessTests.cs b/src/IKVM.Tests/Java/javax/script/BooleanAccessTests.cs new file mode 100644 index 0000000000..3f716e8437 --- /dev/null +++ b/src/IKVM.Tests/Java/javax/script/BooleanAccessTests.cs @@ -0,0 +1,46 @@ +using FluentAssertions; + +using javax.script; + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace IKVM.Tests.Java.javax.script +{ + + [TestClass] + public class BooleanAccessTests + { + + static ScriptEngine e; + static SharedObject o; + + [TestInitialize] + public void Initialize() + { + var m = new ScriptEngineManager(); + e = m.getEngineByName("nashorn"); + o = new SharedObject(); + e.put("o", o); + e.eval("var SharedObject = Packages.cli.IKVM.Tests.Java.javax.script.SharedObject;"); + } + + [TestCleanup] + public void Cleanup() + { + e = null; + o = null; + } + + [TestMethod] + public void AccessFieldBoolean() + { + e.eval("var p_boolean = o.publicBoolean;"); + o.publicBoolean.Should().Be(((global::java.lang.Boolean)e.get("p_boolean")).booleanValue()); + e.eval("typeof p_boolean;").Should().Be("boolean"); + e.eval("o.publicBoolean = false;"); + o.publicBoolean.Should().Be(false); + } + + } + +} diff --git a/src/IKVM.Tests/Java/javax/script/NashornAccessTests.cs b/src/IKVM.Tests/Java/javax/script/NashornAccessTests.cs deleted file mode 100644 index edf0f24068..0000000000 --- a/src/IKVM.Tests/Java/javax/script/NashornAccessTests.cs +++ /dev/null @@ -1,36 +0,0 @@ -using FluentAssertions; - -using javax.script; - -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace IKVM.Tests.Java.javax.script -{ - - [TestClass] - public class NashornAccessTests - { - - class SharedObject - { - - public string publicString = "PublicString"; - - } - - static ScriptEngine e; - static SharedObject o; - - [TestInitialize] - public void Initialize() - { - var m = new ScriptEngineManager(); - e = m.getEngineByName("nashorn"); - o = new SharedObject(); - e.put("o", o); - e.eval("var SharedObject = Packages.cli.IKVM.Tests.Java.javax.script.NashornAccessTests$SharedObject;"); - } - - } - -} diff --git a/src/IKVM.Tests/Java/javax/script/Person.cs b/src/IKVM.Tests/Java/javax/script/Person.cs new file mode 100644 index 0000000000..c683780c36 --- /dev/null +++ b/src/IKVM.Tests/Java/javax/script/Person.cs @@ -0,0 +1,42 @@ +namespace IKVM.Tests.Java.javax.script +{ + + public class Person + { + + public int id = 0; + + public Person() + { + + } + + public Person(int code) + { + this.id = code; + } + + public override bool Equals(object obj) + { + if (obj != null && obj is Person) + { + Person o = (Person)obj; + return this.id == o.id; + } + + return false; + } + + public override int GetHashCode() + { + return id; + } + + public override string ToString() + { + return "Person(" + id + ")"; + } + + } + +} diff --git a/src/IKVM.Tests/Java/javax/script/SharedObject.cs b/src/IKVM.Tests/Java/javax/script/SharedObject.cs new file mode 100644 index 0000000000..3ad8011ada --- /dev/null +++ b/src/IKVM.Tests/Java/javax/script/SharedObject.cs @@ -0,0 +1,521 @@ +using System; + +using javax.script; + +namespace IKVM.Tests.Java.javax.script +{ + + public class SharedObject + { + + // Public fields + public string publicString = "PublicString"; + public string[] publicStringArray = ["ArrayString[0]", "ArrayString[1]", "ArrayString[2]", "ArrayString[3]"]; + public Person publicObject = new Person(256); + public Person[] publicObjectArray = [new Person(4), new Person(-422), new Person(14)]; + public bool publicBoolean = true; + public bool[] publicBooleanArray = [true, false, false, true]; + public global::java.lang.Boolean publicBooleanBox = new global::java.lang.Boolean(true); + public long publicLong = 933333333333333333L; + public long[] publicLongArray = [99012333333333L, -124355555L, 89777777777L]; + public global::java.lang.Long publicLongBox = new global::java.lang.Long(9333333333L); + public int publicInt = 2076543123; + public int[] publicIntArray = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]; + public global::java.lang.Integer publicIntBox = new global::java.lang.Integer(20765123); + public byte publicByte = unchecked((byte)-128); + public byte[] publicByteArray = [1, 2, 4, 8, 16, 32, 64, 127, unchecked((byte)-128)]; + public global::java.lang.Byte publicByteBox = new global::java.lang.Byte(127); + public short publicShort = 32000; + public short[] publicShortArray = [3240, 8900, -16789, 1, 12]; + public global::java.lang.Short publicShortBox = new global::java.lang.Short(global::java.lang.Short.MIN_VALUE); + public float publicFloat = 0.7f; + public float[] publicFloatArray = [-32.01f, 89.3f, -1.3e8f, 3.1f]; + public global::java.lang.Float publicFloatBox = new global::java.lang.Float(1.377e4f); + public double publicDouble = 1.34e20; + public double[] publicDoubleArray = [0.75e80, 8e-43, 1.000077, 0.123e10]; + public global::java.lang.Double publicDoubleBox = new global::java.lang.Double(1.4e-19); + public char publicChar = 'A'; + public char[] publicCharArray = "Hello Nashorn".ToCharArray(); + public global::java.lang.Character publicCharBox = new global::java.lang.Character('B'); + + // Public static fields + public static string publicStaticString = "PublicStaticString"; + public static string[] publicStaticStringArray = ["StaticArrayString[0]", "StaticArrayString[1]", "StaticArrayString[2]", "StaticArrayString[3]"]; + public static Person publicStaticObject = new Person(512); + public static Person[] publicStaticObjectArray = { new Person(40), new Person(-22), new Person(18) }; + public static bool publicStaticBoolean = true; + public static bool[] publicStaticBooleanArray = { false, false, false, true }; + public static global::java.lang.Boolean publicStaticBooleanBox = new global::java.lang.Boolean(true); + public static long publicStaticLong = 13333333333333333L; + public static long[] publicStaticLongArray = { 19012333333333L, -224355555L, 39777777777L }; + public static global::java.lang.Long publicStaticLongBox = new global::java.lang.Long(9333333334L); + public static int publicStaticInt = 207654323; + public static int[] publicStaticIntArray = { 5, 8, 13, 21, 34 }; + public static global::java.lang.Integer publicStaticIntBox = new global::java.lang.Integer(2075123); + public static byte publicStaticByte = unchecked((byte)-12); + public static byte[] publicStaticByteArray = { 16, 32, 64, 127, unchecked((byte)-128) }; + public static global::java.lang.Byte publicStaticByteBox = new global::java.lang.Byte(17); + public static short publicStaticShort = 320; + public static short[] publicStaticShortArray = { 1240, 900, -1789, 100, 12 }; + public static global::java.lang.Short publicStaticShortBox = new global::java.lang.Short(-16777); + public static float publicStaticFloat = 7.7e8f; + public static float[] publicStaticFloatArray = { -131.01f, 189.3f, -31.3e8f, 3.7f }; + public static global::java.lang.Float publicStaticFloatBox = new global::java.lang.Float(1.37e4f); + public static double publicStaticDouble = 1.341e20; + public static double[] publicStaticDoubleArray = { 0.75e80, 0.123e10, 8e-43, 1.000077 }; + public static global::java.lang.Double publicStaticDoubleBox = new global::java.lang.Double(1.41e-12); + public static char publicStaticChar = 'C'; + public static char[] publicStaticCharArray = "Nashorn".ToCharArray(); + public static global::java.lang.Character publicStaticCharBox = new global::java.lang.Character('D'); + + // Public final fields + public readonly string publicFinalString = "PublicFinalString"; + public readonly string[] publicFinalStringArray = ["FinalArrayString[0]", "FinalArrayString[1]", "FinalArrayString[2]", "FinalArrayString[3]"]; + public readonly Person publicFinalObject = new Person(1024); + public readonly Person[] publicFinalObjectArray = [new Person(-900), new Person(1000), new Person(180)]; + public readonly bool publicFinalBoolean = true; + public readonly bool[] publicFinalBooleanArray = [false, false, true, false]; + public readonly global::java.lang.Boolean publicFinalBooleanBox = new global::java.lang.Boolean(true); + public readonly long publicFinalLong = 13353333333333333L; + public readonly long[] publicFinalLongArray = [1901733333333L, -2247355555L, 3977377777L]; + public readonly global::java.lang.Long publicFinalLongBox = new global::java.lang.Long(9377333334L); + public readonly int publicFinalInt = 20712023; + public readonly int[] publicFinalIntArray = [50, 80, 130, 210, 340]; + public readonly global::java.lang.Integer publicFinalIntBox = new global::java.lang.Integer(207512301); + public readonly byte publicFinalByte = unchecked((byte)-7); + public readonly byte[] publicFinalByteArray = [1, 3, 6, 17, unchecked((byte)-128)]; + public readonly global::java.lang.Byte publicFinalByteBox = new global::java.lang.Byte(19); + public readonly short publicFinalShort = 31220; + public readonly short[] publicFinalShortArray = [12240, 9200, -17289, 1200, 12]; + public readonly global::java.lang.Short publicFinalShortBox = new global::java.lang.Short(-26777); + public readonly float publicFinalFloat = 7.72e8f; + public readonly float[] publicFinalFloatArray = [-131.012f, 189.32f, -31.32e8f, 3.72f]; + public readonly global::java.lang.Float publicFinalFloatBox = new global::java.lang.Float(1.372e4f); + public readonly double publicFinalDouble = 1.3412e20; + public readonly double[] publicFinalDoubleArray = [0.725e80, 0.12e10, 8e-3, 1.00077]; + public readonly global::java.lang.Double publicFinalDoubleBox = new global::java.lang.Double(1.412e-12); + public readonly char publicFinalChar = 'E'; + public readonly char[] publicFinalCharArray = "Nashorn hello".ToCharArray(); + public readonly global::java.lang.Character publicFinalCharBox = new global::java.lang.Character('F'); + + // Public static final fields + public static readonly string publicStaticFinalString = "PublicStaticFinalString"; + public static readonly string[] publicStaticFinalStringArray = ["StaticFinalArrayString[0]", "StaticFinalArrayString[1]", "StaticFinalArrayString[2]", "StaticFinalArrayString[3]"]; + public static readonly Person publicStaticFinalObject = new Person(2048); + public static readonly Person[] publicStaticFinalObjectArray = [new Person(-9), new Person(110), new Person(global::java.lang.Integer.MAX_VALUE)]; + public static readonly bool publicStaticFinalBoolean = true; + public static readonly bool[] publicStaticFinalBooleanArray = [false, true, false, false]; + public static readonly global::java.lang.Boolean publicStaticFinalBooleanBox = new global::java.lang.Boolean(true); + public static readonly long publicStaticFinalLong = 8333333333333L; + public static readonly long[] publicStaticFinalLongArray = [19017383333L, -2247358L, 39773787L]; + public static readonly global::java.lang.Long publicStaticFinalLongBox = new global::java.lang.Long(9377388334L); + public static readonly int publicStaticFinalInt = 207182023; + public static readonly int[] publicStaticFinalIntArray = [1308, 210, 340]; + public static readonly global::java.lang.Integer publicStaticFinalIntBox = new global::java.lang.Integer(2078301); + public static readonly byte publicStaticFinalByte = unchecked((byte)-70); + public static readonly byte[] publicStaticFinalByteArray = [17, unchecked((byte)-128), 81]; + public static readonly global::java.lang.Byte publicStaticFinalByteBox = new global::java.lang.Byte(91); + public static readonly short publicStaticFinalShort = 8888; + public static readonly short[] publicStaticFinalShortArray = [8240, 9280, -1289, 120, 812]; + public static readonly global::java.lang.Short publicStaticFinalShortBox = new global::java.lang.Short(-26); + public static readonly float publicStaticFinalFloat = 0.72e8f; + public static readonly float[] publicStaticFinalFloatArray = [-8131.012f, 9.32f, -138.32e8f, 0.72f]; + public static readonly global::java.lang.Float publicStaticFinalFloatBox = new global::java.lang.Float(1.2e4f); + public static readonly double publicStaticFinalDouble = 1.8e12; + public static readonly double[] publicStaticFinalDoubleArray = [8.725e80, 0.82e10, 18e-3, 1.08077]; + public static readonly global::java.lang.Double publicStaticFinalDoubleBox = new global::java.lang.Double(1.5612e-13); + public static readonly char publicStaticFinalChar = 'K'; + public static readonly char[] publicStaticFinalCharArray = "StaticString".ToCharArray(); + public static readonly global::java.lang.Character publicStaticFinalCharBox = new global::java.lang.Character('L'); + + // Special vars + public volatile bool volatileBoolean = true; + + [NonSerialized] + public bool transientBoolean = true; + + // For methods testing + public bool isAccessed = false; + public volatile bool isFinished = false; + + private ScriptEngine engine; + + public ScriptEngine getEngine() + { + return engine; + } + + public void setEngine(ScriptEngine engine) + { + this.engine = engine; + } + + public void voidMethod() + { + isAccessed = true; + } + + public bool booleanMethod(bool arg) + { + return !arg; + } + + public global::java.lang.Boolean booleanBoxingMethod(global::java.lang.Boolean arg) + { + return new global::java.lang.Boolean(!arg.booleanValue()); + } + + public bool[] booleanArrayMethod(bool[] arg) + { + bool[] res = new bool[arg.Length]; + for (int i = 0; i < arg.Length; i++) + { + res[i] = !arg[i]; + } + return res; + } + + public int intMethod(int arg) + { + return arg + arg; + } + + public global::java.lang.Integer intBoxingMethod(global::java.lang.Integer arg) + { + return new global::java.lang.Integer(arg.intValue() + arg.intValue()); + } + + public int[] intArrayMethod(int[] arg) + { + int[] res = new int[arg.Length]; + for (int i = 0; i < arg.Length; i++) + { + res[i] = arg[i] * 2; + } + return res; + } + + public long longMethod(long arg) + { + return arg + arg; + } + + public global::java.lang.Long longBoxingMethod(global::java.lang.Long arg) + { + return new global::java.lang.Long(arg.longValue() + arg.longValue()); + } + + public long[] longArrayMethod(long[] arg) + { + long[] res = new long[arg.Length]; + for (int i = 0; i < arg.Length; i++) + { + res[i] = arg[i] * 2; + } + return res; + } + + public byte byteMethod(byte arg) + { + return (byte)(arg + arg); + } + + public global::java.lang.Byte byteBoxingMethod(global::java.lang.Byte arg) + { + return new global::java.lang.Byte((byte)(arg.byteValue() + arg.byteValue())); + } + + public byte[] byteArrayMethod(byte[] arg) + { + byte[] res = new byte[arg.Length]; + for (int i = 0; i < arg.Length; i++) + { + res[i] = (byte)(arg[i] * 2); + } + return res; + } + + public char charMethod(char arg) + { + return global::java.lang.Character.toUpperCase(arg); + } + + public global::java.lang.Character charBoxingMethod(global::java.lang.Character arg) + { + return new global::java.lang.Character(global::java.lang.Character.toUpperCase(arg.charValue())); + } + + public char[] charArrayMethod(char[] arg) + { + char[] res = new char[arg.Length]; + for (int i = 0; i < arg.Length; i++) + { + res[i] = global::java.lang.Character.toUpperCase(arg[i]); + } + return res; + } + + public short shortMethod(short arg) + { + return (short)(arg + arg); + } + + public global::java.lang.Short shortBoxingMethod(global::java.lang.Short arg) + { + return new global::java.lang.Short((short)(arg.shortValue() + arg.shortValue())); + } + + public short[] shortArrayMethod(short[] arg) + { + short[] res = new short[arg.Length]; + for (int i = 0; i < arg.Length; i++) + { + res[i] = (short)(arg[i] * 2); + } + return res; + } + + public float floatMethod(float arg) + { + return arg + arg; + } + + public global::java.lang.Float floatBoxingMethod(global::java.lang.Float arg) + { + return new global::java.lang.Float(arg.floatValue() + arg.floatValue()); + } + + public float[] floatArrayMethod(float[] arg) + { + float[] res = new float[arg.Length]; + for (int i = 0; i < arg.Length; i++) + { + res[i] = arg[i] * 2; + } + return res; + } + + public double doubleMethod(double arg) + { + return arg + arg; + } + + public global::java.lang.Double doubleBoxingMethod(global::java.lang.Double arg) + { + return new global::java.lang.Double(arg.doubleValue() + arg.doubleValue()); + } + + public double[] doubleArrayMethod(double[] arg) + { + double[] res = new double[arg.Length]; + for (int i = 0; i < arg.Length; i++) + { + res[i] = arg[i] * 2; + } + return res; + } + + public string stringMethod(string str) + { + return str + str; + } + + public string[] stringArrayMethod(string[] arr) + { + int l = arr.Length; + string[] res = new string[l]; + for (int i = 0; i < l; i++) + { + res[i] = arr[l - i - 1]; + } + return res; + } + + public Person[] objectArrayMethod(Person[] arr) + { + Person[] res = new Person[arr.Length]; + for (int i = 0; i < arr.Length; i++) + { + res[i] = new Person(i + 100); + } + return res; + } + + public Person objectMethod(Person t) + { + t.id *= 2; + return t; + } + + public int twoParamMethod(long l, double d) + { + return (int)(l + d); + } + + public int threeParamMethod(short s, long l, char c) + { + return (int)(s + l + c); + } + + public Person[] twoObjectParamMethod(Person arg1, Person arg2) + { + return new Person[] { arg2, arg1 }; + } + + public Person[] threeObjectParamMethod(Person arg1, Person arg2, Person arg3) + { + return new Person[] { arg3, arg2, arg1 }; + } + + public Person[] eightObjectParamMethod(Person arg1, Person arg2, Person arg3, Person arg4, Person arg5, Person arg6, Person arg7, Person arg8) + { + return new Person[] { arg8, arg7, arg6, arg5, arg4, arg3, arg2, arg1 }; + } + + public Person[] nineObjectParamMethod(Person arg1, Person arg2, Person arg3, Person arg4, Person arg5, Person arg6, Person arg7, Person arg8, Person arg9) + { + return new Person[] { arg9, arg8, arg7, arg6, arg5, arg4, arg3, arg2, arg1 }; + } + + public Person[] methodObjectEllipsis(params Person[] args) + { + int l = args.Length; + Person[] res = new Person[l]; + for (int i = 0; i < l; i++) + { + res[i] = args[l - i - 1]; + } + return res; + } + + public Person[] methodPrimitiveEllipsis(params int[] args) + { + int l = args.Length; + Person[] res = new Person[l]; + for (int i = 0; i < l; i++) + { + res[i] = new Person(args[i]); + } + return res; + } + + public object[] methodMixedEllipsis(params object[] args) + { + return args; + } + + public object[] methodObjectWithEllipsis(string arg, params int[] args) + { + object[] res = new object[args.Length + 1]; + res[0] = arg; + for (int i = 0; i < args.Length; i++) + { + res[i + 1] = args[i]; + } + return res; + } + + public object[] methodPrimitiveWithEllipsis(int arg, params long[] args) + { + object[] res = new object[args.Length + 1]; + res[0] = arg; + for (int i = 0; i < args.Length; i++) + { + res[i + 1] = args[i]; + } + return res; + } + + public object[] methodMixedWithEllipsis(string arg1, int arg2, params object[] args) + { + object[] res = new object[args.Length + 2]; + res[0] = arg1; + res[1] = arg2; + global::java.lang.System.arraycopy(args, 0, res, 2, args.Length); + return res; + } + + public void methodStartsThread() + { + isFinished = false; + + global::java.lang.Thread t = new global::java.lang.Thread(new IKVM.Java.Extensions.java.lang.DelegateRunnable(() => + { + try + { + global::java.lang.Thread.sleep(1000); + isFinished = true; + } + catch (global::java.lang.InterruptedException e) + { + e.printStackTrace(); + } + })); + + t.start(); + } + + public string overloadedMethodDoubleVSint(int arg) + { + return "int"; + } + + public string overloadedMethodDoubleVSint(double arg) + { + return "double"; + } + + public int overloadedMethod(int arg) + { + return arg * 2; + } + + public int overloadedMethod(string arg) + { + return arg.Length; + } + + public int overloadedMethod(bool arg) + { + return (arg) ? 1 : 0; + } + + public int overloadedMethod(Person arg) + { + return arg.id * 2; + } + + public int firstLevelMethodInt(int arg) + { + return (int)((Invocable)engine).invokeFunction("secondLevelMethodInt", arg); + } + + public int thirdLevelMethodInt(int arg) + { + return arg * 5; + } + + public int firstLevelMethodInteger(global::java.lang.Integer arg) + { + return (int)((Invocable)engine).invokeFunction("secondLevelMethodInteger", arg); + } + + public int thirdLevelMethodInteger(global::java.lang.Integer arg) + { + return arg.intValue() * 10; + } + + public Person firstLevelMethodObject(Person p) + { + return (Person)((Invocable)engine).invokeFunction("secondLevelMethodObject", p); + } + + public Person thirdLevelMethodObject(Person p) + { + p.id *= 10; + return p; + } + + } + +} \ No newline at end of file diff --git a/src/IKVM.Tools.Exporter/IKVM.Tools.Exporter.csproj b/src/IKVM.Tools.Exporter/IKVM.Tools.Exporter.csproj index f1b9435073..4af39ee6f5 100644 --- a/src/IKVM.Tools.Exporter/IKVM.Tools.Exporter.csproj +++ b/src/IKVM.Tools.Exporter/IKVM.Tools.Exporter.csproj @@ -12,7 +12,6 @@ - diff --git a/src/IKVM.Tools.Importer/CompilerClassLoader.cs b/src/IKVM.Tools.Importer/CompilerClassLoader.cs index 5c31cb1522..b03d8b4388 100644 --- a/src/IKVM.Tools.Importer/CompilerClassLoader.cs +++ b/src/IKVM.Tools.Importer/CompilerClassLoader.cs @@ -35,7 +35,6 @@ Jeroen Frijters using IKVM.Attributes; using IKVM.ByteCode; -using IKVM.ByteCode.Reading; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; @@ -273,7 +272,7 @@ private RuntimeJavaType PeerLoad(string name) return null; } - private RuntimeJavaType GetTypeWrapperCompilerHook(string name) + RuntimeJavaType GetTypeWrapperCompilerHook(string name) { if (remapped.TryGetValue(name, out var rtw)) { @@ -285,10 +284,11 @@ private RuntimeJavaType GetTypeWrapperCompilerHook(string name) { classes.Remove(name); - ClassFile f; + IKVM.Runtime.ClassFile f; + try { - f = new ClassFile(Context, ClassReader.Read(itemRef.GetData()), name, ClassFileParseOptions, null); + f = new IKVM.Runtime.ClassFile(Context, IKVM.ByteCode.Decoding.ClassFile.Read(itemRef.GetData()), name, ClassFileParseOptions, null); } catch (UnsupportedClassVersionException e) { @@ -514,19 +514,24 @@ void SetMain(RuntimeJavaType type, PEFileKinds target, IDictionary 0) { var environmentType = Context.Resolver.ResolveCoreType(typeof(Environment).FullName); @@ -557,7 +562,7 @@ void SetMain(RuntimeJavaType type, PEFileKinds target, IDictionary - diff --git a/src/IKVM.Tools.Importer/IkvmImporterInternal.cs b/src/IKVM.Tools.Importer/IkvmImporterInternal.cs index 2b8d100d79..96da26085b 100644 --- a/src/IKVM.Tools.Importer/IkvmImporterInternal.cs +++ b/src/IKVM.Tools.Importer/IkvmImporterInternal.cs @@ -29,7 +29,7 @@ Jeroen Frijters using System.Threading; using IKVM.ByteCode; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; using IKVM.Reflection; using IKVM.Reflection.Emit; using IKVM.Runtime; @@ -1172,11 +1172,11 @@ static byte[] ReadFromZip(ZipArchiveEntry ze) static bool EmitStubWarning(RuntimeContext context, StaticCompiler compiler, CompilerOptions options, byte[] buf) { - ClassFile cf; + IKVM.Runtime.ClassFile cf; try { - cf = new ClassFile(context, ClassReader.Read(buf), "", ClassFileParseOptions.None, null); + cf = new IKVM.Runtime.ClassFile(context, IKVM.ByteCode.Decoding.ClassFile.Read(buf), "", ClassFileParseOptions.None, null); } catch (ClassFormatError) { @@ -1217,7 +1217,7 @@ static bool IsExcludedOrStubLegacy(RuntimeContext context, StaticCompiler compil { try { - var name = ClassFile.GetClassName(data, 0, data.Length, out var stub); + var name = IKVM.Runtime.ClassFile.GetClassName(data, 0, data.Length, out var stub); if (options.IsExcludedClass(name) || (stub && EmitStubWarning(context, compiler, options, data))) { // we use stubs to add references, but otherwise ignore them @@ -1308,7 +1308,7 @@ bool ProcessZipFile(RuntimeContext context, StaticCompiler compiler, CompilerOpt void ProcessFile(RuntimeContext context, StaticCompiler compiler, CompilerOptions options, DirectoryInfo baseDir, string file) { - FileInfo fileInfo = GetFileInfo(file); + var fileInfo = GetFileInfo(file); if (fileInfo.Extension.Equals(".jar", StringComparison.OrdinalIgnoreCase) || fileInfo.Extension.Equals(".zip", StringComparison.OrdinalIgnoreCase)) { ProcessZipFile(context, compiler, options, file, null); @@ -1320,17 +1320,14 @@ void ProcessFile(RuntimeContext context, StaticCompiler compiler, CompilerOption byte[] data = ReadAllBytes(fileInfo); try { - bool stub; - string name = ClassFile.GetClassName(data, 0, data.Length, out stub); + var name = IKVM.Runtime.ClassFile.GetClassName(data, 0, data.Length, out var stub); if (options.IsExcludedClass(name)) - { return; - } + + // we use stubs to add references, but otherwise ignore them if (stub && EmitStubWarning(context, compiler, options, data)) - { - // we use stubs to add references, but otherwise ignore them return; - } + options.GetClassesJar().Add(name.Replace('.', '/') + ".class", data, fileInfo); return; } @@ -1339,6 +1336,7 @@ void ProcessFile(RuntimeContext context, StaticCompiler compiler, CompilerOption IssueMessage(compiler, Message.ClassFormatError, file, x.Message); } } + if (baseDir == null) { IssueMessage(compiler, Message.UnknownFileType, file); @@ -1347,8 +1345,7 @@ void ProcessFile(RuntimeContext context, StaticCompiler compiler, CompilerOption { // include as resource // extract the resource name by chopping off the base directory - string name = file.Substring(baseDir.FullName.Length); - Console.WriteLine("ADDING ZIP HERE"); + var name = file.Substring(baseDir.FullName.Length); name = name.TrimStart(Path.DirectorySeparatorChar).Replace('\\', '/'); options.GetResourcesJar().Add(name, ReadAllBytes(fileInfo), fileInfo); } @@ -1427,7 +1424,7 @@ static void ProcessAttributeAnnotationsClass(RuntimeContext context, ref object[ try { using var file = File.OpenRead(filename); - var cf = new ClassFile(context, ClassReader.Read(file), null, ClassFileParseOptions.None, null); + var cf = new IKVM.Runtime.ClassFile(context, IKVM.ByteCode.Decoding.ClassFile.Read(file), null, ClassFileParseOptions.None, null); ArrayAppend(ref annotations, cf.Annotations); } catch (Exception x) diff --git a/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs b/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs index f56514d96a..db78dd01d2 100644 --- a/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs +++ b/src/IKVM.Tools.Importer/RuntimeImportByteCodeJavaType.cs @@ -51,7 +51,6 @@ sealed class RuntimeImportByteCodeJavaType : RuntimeByteCodeJavaType Annotation annotation; Type enumType; RuntimeJavaMethod[] replacedMethods; - WorkaroundBaseClass workaroundBaseClass; /// /// Initializes a new instance. @@ -64,106 +63,12 @@ internal RuntimeImportByteCodeJavaType(ClassFile f, CompilerClassLoader loader) } - protected override Type GetBaseTypeForDefineType() - { - var baseTypeWrapper = BaseTypeWrapper; - - if (IsPublic && IsAbstract && baseTypeWrapper.IsPublic && baseTypeWrapper.IsAbstract && classLoader.WorkaroundAbstractMethodWidening) - { - // FXBUG - // if the current class widens access on an abstract base class method, - // we need to inject an artificial base class to workaround a C# compiler bug - List methods = null; - - foreach (var mw in GetMethods()) - { - if (!mw.IsStatic && mw.IsPublic) - { - var baseMethod = baseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true); - if (baseMethod != null && baseMethod.IsAbstract && baseMethod.IsProtected) - { - methods ??= new List(); - methods.Add(baseMethod); - } - } - } - - if (methods != null) - { - var name = "__WorkaroundBaseClass__." + UnicodeUtil.EscapeInvalidSurrogates(Name); - while (!classLoader.ReserveName(name)) - name = "_" + name; - - var context = classLoader.GetTypeWrapperFactory(); - var typeBuilder = context.ModuleBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Abstract, base.GetBaseTypeForDefineType()); - Context.AttributeHelper.HideFromJava(typeBuilder); - Context.AttributeHelper.SetEditorBrowsableNever(typeBuilder); - workaroundBaseClass = new WorkaroundBaseClass(this, typeBuilder, methods.ToArray()); - var constructors = new List(); - foreach (var mw in baseTypeWrapper.GetMethods()) - if (ReferenceEquals(mw.Name, StringConstants.INIT) && mw.IsAccessibleFrom(baseTypeWrapper, this, this)) - constructors.Add(new ConstructorForwarder(context, typeBuilder, mw)); - replacedMethods = constructors.ToArray(); - return typeBuilder; - } - } - - return base.GetBaseTypeForDefineType(); - } - internal override void Finish() { base.Finish(); - workaroundBaseClass?.Finish(); } - sealed class WorkaroundBaseClass - { - - readonly RuntimeImportByteCodeJavaType wrapper; - readonly TypeBuilder typeBuilder; - readonly RuntimeJavaMethod[] methods; - MethodBuilder baseSerializationCtor; - - /// - /// Initializes a new instance. - /// - /// - /// - /// - internal WorkaroundBaseClass(RuntimeImportByteCodeJavaType wrapper, TypeBuilder typeBuilder, RuntimeJavaMethod[] methods) - { - this.wrapper = wrapper; - this.typeBuilder = typeBuilder; - this.methods = methods; - } - - internal MethodBuilder GetSerializationConstructor() - { - if (baseSerializationCtor == null) - baseSerializationCtor = wrapper.Context.Serialization.AddAutomagicSerializationToWorkaroundBaseClass(typeBuilder, wrapper.BaseTypeWrapper.GetSerializationConstructor()); - - return baseSerializationCtor; - } - - internal void Finish() - { - if (!typeBuilder.IsCreated()) - { - foreach (var mw in methods) - { - var mb = mw.GetDefineMethodHelper().DefineMethod(wrapper, typeBuilder, mw.Name, MethodAttributes.FamORAssem | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.CheckAccessOnOverride); - wrapper.Context.AttributeHelper.HideFromJava(mb); - var ilgen = wrapper.Context.CodeEmitterFactory.Create(mb); - ilgen.EmitThrow("java.lang.AbstractMethodError"); - ilgen.DoEmit(); - } - typeBuilder.CreateType(); - } - } - } - - private sealed class ConstructorForwarder : RuntimeJavaMethod + sealed class ConstructorForwarder : RuntimeJavaMethod { readonly RuntimeJavaTypeFactory context; @@ -381,6 +286,7 @@ private void PublishProperties(TypeBuilder typeBuilder, Class clazz) Context.AttributeHelper.SetCustomAttribute(classLoader, propbuilder, attr); } } + RuntimeJavaMethod getter = null; RuntimeJavaMethod setter = null; if (prop.Getter != null) @@ -391,30 +297,31 @@ private void PublishProperties(TypeBuilder typeBuilder, Class clazz) Console.Error.WriteLine("Warning: getter not found for {0}::{1}", clazz.Name, prop.Name); } } + if (prop.Setter != null) { setter = GetMethodWrapper(prop.Setter.Name, prop.Setter.Sig, true); if (setter == null) - { Console.Error.WriteLine("Warning: setter not found for {0}::{1}", clazz.Name, prop.Name); - } } - bool final = (getter != null && getter.IsFinal) || (setter != null && setter.IsFinal); + + var final = (getter != null && getter.IsFinal) || (setter != null && setter.IsFinal); if (getter != null) { - RuntimeJavaMethod mw = getter; + var mw = getter; + if (!CheckPropertyArgs(mw.GetParametersForDefineMethod(), indexer) || mw.ReturnType != typeWrapper) { Console.Error.WriteLine("Warning: ignoring invalid property getter for {0}::{1}", clazz.Name, prop.Name); } else { - MethodBuilder mb = mw.GetMethod() as MethodBuilder; + var mb = mw.GetMethod() as MethodBuilder; if (mb == null || mb.DeclaringType != typeBuilder || (!mb.IsFinal && final)) { mb = typeBuilder.DefineMethod("get_" + prop.Name, GetPropertyMethodAttributes(mw, final), typeWrapper.TypeAsSignatureType, indexer); Context.AttributeHelper.HideFromJava(mb); - CodeEmitter ilgen = Context.CodeEmitterFactory.Create(mb); + var ilgen = Context.CodeEmitterFactory.Create(mb); if (mw.IsStatic) { for (int i = 0; i < indexer.Length; i++) @@ -427,9 +334,7 @@ private void PublishProperties(TypeBuilder typeBuilder, Class clazz) { ilgen.Emit(OpCodes.Ldarg_0); for (int i = 0; i < indexer.Length; i++) - { ilgen.EmitLdarg(i + 1); - } mw.EmitCallvirt(ilgen); } ilgen.Emit(OpCodes.Ret); @@ -440,7 +345,7 @@ private void PublishProperties(TypeBuilder typeBuilder, Class clazz) } if (setter != null) { - RuntimeJavaMethod mw = setter; + var mw = setter; var args = ArrayUtil.Concat(indexer, typeWrapper.TypeAsSignatureType); if (!CheckPropertyArgs(args, mw.GetParametersForDefineMethod())) { @@ -457,23 +362,20 @@ private void PublishProperties(TypeBuilder typeBuilder, Class clazz) if (mw.IsStatic) { for (int i = 0; i <= indexer.Length; i++) - { ilgen.EmitLdarg(i); - } mw.EmitCall(ilgen); } else { ilgen.Emit(OpCodes.Ldarg_0); for (int i = 0; i <= indexer.Length; i++) - { ilgen.EmitLdarg(i + 1); - } mw.EmitCallvirt(ilgen); } ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); } + propbuilder.SetSetMethod(mb); } } @@ -483,7 +385,7 @@ private void PublishProperties(TypeBuilder typeBuilder, Class clazz) private static void MapModifiers(MapModifiers mapmods, bool isConstructor, out bool setmodifiers, ref MethodAttributes attribs, bool isNewSlot) { setmodifiers = false; - Modifiers modifiers = (Modifiers)mapmods; + var modifiers = (Modifiers)mapmods; if ((modifiers & Modifiers.Public) != 0) { attribs |= MethodAttributes.Public; @@ -500,6 +402,7 @@ private static void MapModifiers(MapModifiers mapmods, bool isConstructor, out b { attribs |= MethodAttributes.Assembly; } + if ((modifiers & Modifiers.Static) != 0) { attribs |= MethodAttributes.Static; @@ -536,6 +439,7 @@ private static void MapModifiers(MapModifiers mapmods, bool isConstructor, out b } } } + if ((modifiers & Modifiers.Synchronized) != 0) { throw new NotImplementedException(); @@ -555,33 +459,30 @@ private void MapSignature(string sig, out Type returnType, out Type[] parameterT protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, RuntimeJavaField[] fields, RuntimeJavaMethod[] methods) { - Dictionary mapxml = classLoader.GetMapXmlClasses(); + var mapxml = classLoader.GetMapXmlClasses(); if (mapxml != null) { - IKVM.Tools.Importer.MapXml.Class clazz; - if (mapxml.TryGetValue(classFile.Name, out clazz)) + if (mapxml.TryGetValue(classFile.Name, out var clazz)) { if (clazz.Attributes != null) - { PublishAttributes(typeBuilder, clazz); - } + if (clazz.Properties != null) - { PublishProperties(typeBuilder, clazz); - } + if (clazz.Fields != null) { - foreach (IKVM.Tools.Importer.MapXml.Field field in clazz.Fields) + foreach (var field in clazz.Fields) { if (field.Attributes != null) { - foreach (RuntimeJavaField fw in fields) + foreach (var fw in fields) { if (fw.Name == field.Name && fw.Signature == field.Sig) { var fb = fw.GetField() as FieldBuilder; if (fb != null) - foreach (IKVM.Tools.Importer.MapXml.Attribute attr in field.Attributes) + foreach (var attr in field.Attributes) Context.AttributeHelper.SetCustomAttribute(classLoader, fb, attr); } } @@ -591,7 +492,7 @@ protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile cl if (clazz.Constructors != null) { // HACK this isn't the right place to do this, but for now it suffices - foreach (IKVM.Tools.Importer.MapXml.Constructor constructor in clazz.Constructors) + foreach (var constructor in clazz.Constructors) { // are we adding a new constructor? if (GetMethodWrapper(StringConstants.INIT, constructor.Sig, false) == null) @@ -602,27 +503,24 @@ protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile cl continue; } - bool setmodifiers = false; MethodAttributes attribs = 0; - MapModifiers(constructor.Modifiers, true, out setmodifiers, ref attribs, false); - Type returnType; - Type[] parameterTypes; - MapSignature(constructor.Sig, out returnType, out parameterTypes); - MethodBuilder cb = ReflectUtil.DefineConstructor(typeBuilder, attribs, parameterTypes); + MapModifiers(constructor.Modifiers, true, out var setmodifiers, ref attribs, false); + MapSignature(constructor.Sig, out var returnType, out var parameterTypes); + var cb = ReflectUtil.DefineConstructor(typeBuilder, attribs, parameterTypes); if (setmodifiers) - { Context.AttributeHelper.SetModifiers(cb, (Modifiers)constructor.Modifiers, false); - } + CompilerClassLoader.AddDeclaredExceptions(Context, cb, constructor.Throws); var ilgen = Context.CodeEmitterFactory.Create(cb); constructor.Emit(classLoader, ilgen); ilgen.DoEmit(); if (constructor.Attributes != null) - foreach (IKVM.Tools.Importer.MapXml.Attribute attr in constructor.Attributes) + foreach (var attr in constructor.Attributes) Context.AttributeHelper.SetCustomAttribute(classLoader, cb, attr); } } - foreach (IKVM.Tools.Importer.MapXml.Constructor constructor in clazz.Constructors) + + foreach (var constructor in clazz.Constructors) { if (constructor.Attributes != null) { @@ -632,7 +530,7 @@ protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile cl { var mb = mw.GetMethod() as MethodBuilder; if (mb != null) - foreach (IKVM.Tools.Importer.MapXml.Attribute attr in constructor.Attributes) + foreach (var attr in constructor.Attributes) Context.AttributeHelper.SetCustomAttribute(classLoader, mb, attr); } } @@ -642,33 +540,33 @@ protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile cl if (clazz.Methods != null) { // HACK this isn't the right place to do this, but for now it suffices - foreach (IKVM.Tools.Importer.MapXml.Method method in clazz.Methods) + foreach (var method in clazz.Methods) { // are we adding a new method? if (GetMethodWrapper(method.Name, method.Sig, false) == null) { - bool setmodifiers = false; - MethodAttributes attribs = method.MethodAttributes; - MapModifiers(method.Modifiers, false, out setmodifiers, ref attribs, BaseTypeWrapper == null || BaseTypeWrapper.GetMethodWrapper(method.Name, method.Sig, true) == null); + var attribs = method.MethodAttributes; + MapModifiers(method.Modifiers, false, out var setmodifiers, ref attribs, BaseTypeWrapper == null || BaseTypeWrapper.GetMethodWrapper(method.Name, method.Sig, true) == null); if (method.Body == null && (attribs & MethodAttributes.Abstract) == 0) { Console.Error.WriteLine("Error: Method {0}.{1}{2} in xml remap file doesn't have a body.", clazz.Name, method.Name, method.Sig); continue; } - Type returnType; - Type[] parameterTypes; - MapSignature(method.Sig, out returnType, out parameterTypes); - MethodBuilder mb = typeBuilder.DefineMethod(method.Name, attribs, returnType, parameterTypes); + + MapSignature(method.Sig, out var returnType, out var parameterTypes); + var mb = typeBuilder.DefineMethod(method.Name, attribs, returnType, parameterTypes); if (setmodifiers) { Context.AttributeHelper.SetModifiers(mb, (Modifiers)method.Modifiers, false); } + if (method.Override != null) { var mw = GetClassLoader().LoadClassByName(method.Override.Class).GetMethodWrapper(method.Override.Name, method.Sig, true); mw.Link(); typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); } + CompilerClassLoader.AddDeclaredExceptions(Context, mb, method.Throws); if (method.Body != null) { @@ -676,15 +574,13 @@ protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile cl method.Emit(classLoader, ilgen); ilgen.DoEmit(); } + if (method.Attributes != null) - { - foreach (IKVM.Tools.Importer.MapXml.Attribute attr in method.Attributes) - { + foreach (var attr in method.Attributes) Context.AttributeHelper.SetCustomAttribute(classLoader, mb, attr); - } - } } } + foreach (IKVM.Tools.Importer.MapXml.Method method in clazz.Methods) { if (method.Attributes != null) @@ -1118,13 +1014,7 @@ internal void SetAnnotation(Annotation annotation) this.annotation = annotation; } - internal override Annotation Annotation - { - get - { - return annotation; - } - } + internal override Annotation Annotation => annotation; internal void SetEnumType(Type enumType) { @@ -1133,7 +1023,7 @@ internal void SetEnumType(Type enumType) internal override Type EnumType => enumType; - private sealed class ReplacedMethodWrapper : RuntimeJavaMethod + sealed class ReplacedMethodWrapper : RuntimeJavaMethod { readonly InstructionList code; @@ -1169,12 +1059,10 @@ protected override void DoLinkMethod() private void DoEmit(CodeEmitter ilgen) { - IKVM.Tools.Importer.MapXml.CodeGenContext context = new IKVM.Tools.Importer.MapXml.CodeGenContext(this.DeclaringType.GetClassLoader()); + var context = new IKVM.Tools.Importer.MapXml.CodeGenContext(this.DeclaringType.GetClassLoader()); // we don't want the line numbers from map.xml, so we have our own emit loop for (int i = 0; i < code.Instructions.Length; i++) - { code.Instructions[i].Generate(context, ilgen); - } } internal override void EmitCall(CodeEmitter ilgen) @@ -1233,11 +1121,6 @@ internal RuntimeJavaMethod ReplaceMethodWrapper(RuntimeJavaMethod mw) return mw; } - internal override IKVM.Reflection.MethodBase GetBaseSerializationConstructor() - { - return workaroundBaseClass != null ? workaroundBaseClass.GetSerializationConstructor() : base.GetBaseSerializationConstructor(); - } - } } diff --git a/src/IKVM.Util/IKVM.Util.csproj b/src/IKVM.Util/IKVM.Util.csproj index 201e4ed6e3..88ed239ec0 100644 --- a/src/IKVM.Util/IKVM.Util.csproj +++ b/src/IKVM.Util/IKVM.Util.csproj @@ -8,10 +8,7 @@ - - - - + diff --git a/src/IKVM.Util/Jar/JarFileExtensions.cs b/src/IKVM.Util/Jar/JarFileExtensions.cs index 876a5db536..63e03088c0 100644 --- a/src/IKVM.Util/Jar/JarFileExtensions.cs +++ b/src/IKVM.Util/Jar/JarFileExtensions.cs @@ -1,7 +1,8 @@ using System; +using System.Linq; using IKVM.ByteCode; -using IKVM.ByteCode.Reading; +using IKVM.ByteCode.Decoding; using IKVM.Util.Modules; using static IKVM.Util.Jar.JarFileUtil; @@ -35,14 +36,26 @@ public static ModuleInfo GetModuleInfo(this JarFile jar) /// static ModuleInfo GetModuleInfoFromClass(JarFile jar) { + if (jar is null) + throw new ArgumentNullException(nameof(jar)); + var e = jar.GetEntry("module-info.class"); if (e == null) return null; using var s = e.Open(); - var c = ClassReader.Read(s); - if ((c.AccessFlags & AccessFlag.ACC_MODULE) != 0 && c.Attributes.Module != null) - return new ModuleInfo(c.Attributes.Module.Name.Name.Value, c.Attributes.Module.Version != null && ModuleVersion.TryParse(c.Attributes.Module.Version.Value.AsSpan(), out var version) ? version : null); + using var c = ClassFile.Read(s); + if ((c.AccessFlags & AccessFlag.ACC_MODULE) != 0) + { + var a = c.Attributes.FirstOrDefault(i => i.IsNotNil && i.Name.IsNotNil && c.Constants.Get(i.Name).Value == AttributeName.Module); + if (a.IsNotNil) + { + var m = (ModuleAttribute)a; + var name_ = c.Constants.Get(m.Name).Name; + var version_ = c.Constants.Get(m.Version).Value; + return new ModuleInfo(name_, version_ != null && ModuleVersion.TryParse(version_.AsSpan(), out var version) ? version : null); + } + } return null; } diff --git a/src/dist-nuget/dist-nuget.csproj b/src/dist-nuget/dist-nuget.csproj index ffdd1b5ddc..093f3f31b3 100644 --- a/src/dist-nuget/dist-nuget.csproj +++ b/src/dist-nuget/dist-nuget.csproj @@ -6,9 +6,6 @@ - - . - . diff --git a/src/dist-tests/dist-tests.csproj b/src/dist-tests/dist-tests.csproj index 2ddfdc02fc..019371a15d 100644 --- a/src/dist-tests/dist-tests.csproj +++ b/src/dist-tests/dist-tests.csproj @@ -7,10 +7,6 @@ - - - - diff --git a/src/java/Program.cs b/src/java/Program.cs index a7336611f4..7937c48d26 100644 --- a/src/java/Program.cs +++ b/src/java/Program.cs @@ -8,7 +8,7 @@ public static class Program { [HideFromJava] - public static int Main(string[] args) => Launcher.Run(null, false, args, "", null); + public static int Main(string[] args) => Launcher.Run(null, null, false, args, "", null); } diff --git a/src/libfdlibm/libfdlibm.clangproj b/src/libfdlibm/libfdlibm.clangproj index 37b34be8e6..0845e6d907 100644 --- a/src/libfdlibm/libfdlibm.clangproj +++ b/src/libfdlibm/libfdlibm.clangproj @@ -12,6 +12,7 @@
+ diff --git a/src/libiava/libiava.clangproj b/src/libiava/libiava.clangproj index dfdd87bb5c..59f6b07c1f 100644 --- a/src/libiava/libiava.clangproj +++ b/src/libiava/libiava.clangproj @@ -92,7 +92,7 @@ - + diff --git a/src/libj2gss/libj2gss.clangproj b/src/libj2gss/libj2gss.clangproj new file mode 100644 index 0000000000..a1e7a47a19 --- /dev/null +++ b/src/libj2gss/libj2gss.clangproj @@ -0,0 +1,26 @@ + + + + + 723f8d26-f3cb-430d-b142-4ab89dbf1298 + + + j2gss + dll + c99 + + + + + + + +
+ + + + + + + + diff --git a/src/libjvm/mapfile-vers b/src/libjvm/mapfile-vers index 821f4b3e4a..2573f4be4a 100644 --- a/src/libjvm/mapfile-vers +++ b/src/libjvm/mapfile-vers @@ -85,7 +85,6 @@ SUNWprivate_1.1 { JVM_DumpAllStacks; JVM_DumpThreads; JVM_EnableCompiler; - JVM_Exit; JVM_FillInStackTrace; JVM_FindClassFromCaller; JVM_FindClassFromClass; diff --git a/src/libosxapp/libosxapp.clangproj b/src/libosxapp/libosxapp.clangproj index 9241d4e5c4..e8dd16c41b 100644 --- a/src/libosxapp/libosxapp.clangproj +++ b/src/libosxapp/libosxapp.clangproj @@ -55,28 +55,28 @@ - <_GenIcon Include="$(OpenJdkDir)jdk\src\macosx\native\sun\osxapp\resource\icons\JavaApp.icns" Destination="$(IntermediateOutputPath)\gensrc\AWTIconData.h" /> + - - + + - + <_Src Remove="@(_Src)" /> - <_Src Include="%(_GenIcon.Identity)" /> + <_Src Include="%(OSXIcon.Identity)" /> <_Tmp Remove="@(_Tmp)" /> - <_Tmp Include="%(_GenIcon.Destination).tmp" /> + <_Tmp Include="%(OSXIcon.Destination).tmp" /> <_Dst Remove="@(_Dst)" /> - <_Dst Include="%(_GenIcon.Destination)" /> + <_Dst Include="%(OSXIcon.Destination)" /> - - + + - + @@ -85,7 +85,7 @@ - + GenerateOSXIcons; diff --git a/src/libsspi_bridge/libsspi_bridge.clangproj b/src/libsspi_bridge/libsspi_bridge.clangproj new file mode 100644 index 0000000000..e347fbff9b --- /dev/null +++ b/src/libsspi_bridge/libsspi_bridge.clangproj @@ -0,0 +1,24 @@ + + + + + 461d3f93-30ad-481e-b3d3-476a3ce2bf7b + + + sspi_bridge + dll + win-x64;win-x86;win-arm64 + + + + + + + + + + + + + + diff --git a/src/libzip/libzip.clangproj b/src/libzip/libzip.clangproj index 3f1d9844c5..43f2afe533 100644 --- a/src/libzip/libzip.clangproj +++ b/src/libzip/libzip.clangproj @@ -40,6 +40,7 @@ + diff --git a/targets/openjdk.buildtools.targets b/targets/openjdk.buildtools.targets index 77509feb16..3a75d320d6 100644 --- a/targets/openjdk.buildtools.targets +++ b/targets/openjdk.buildtools.targets @@ -11,33 +11,33 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - + - $([System.IO.Path]::GetFullPath('$(JAVA_HOME)\lib\tools.jar')) + $([System.IO.Path]::GetFullPath('$(JAVA_HOME)\lib\tools.jar')) - - + + - $(IntermediateOutputPath)btclasses.javac.rsp - $(IntermediateOutputPath)btclasses\ - $(IntermediateOutputPath)$(MSBuildProjectName).OpenJdkBuildTools.stamp + $(IntermediateOutputPath)jdk_btclasses\ + $(IntermediateOutputPath)jdk_btclasses.javac.rsp + $(IntermediateOutputPath)jdk_btclasses.stamp - - - - + + + + - - - + + + - <_OpenJdkBuildToolsJavaCompilerClasspath Include="$(OpenJdkToolsJarPath)" /> + <_OpenJdkBuildToolsJavaCompilerClasspath Include="$(JavaToolsJarPath)" /> @@ -54,34 +54,34 @@ <_OpenJdkBuildToolsJavaCompilerArgs Include="1.8" /> <_OpenJdkBuildToolsJavaCompilerArgs Include="-nowarn" /> <_OpenJdkBuildToolsJavaCompilerArgs Include="-d" /> - <_OpenJdkBuildToolsJavaCompilerArgs Include="$(OpenJdkBuildToolsOutputPath)" /> - <_OpenJdkBuildToolsJavaCompilerArgs Include="@(OpenJdkBuildToolsSource->'%(FullPath)')" /> + <_OpenJdkBuildToolsJavaCompilerArgs Include="$(JdkBuildToolsOutputPath)" /> + <_OpenJdkBuildToolsJavaCompilerArgs Include="@(JdkBuildToolsSource->'%(FullPath)')" /> - + - + - + - - - - - - - + + + + + + + - - - - + + + +