Fix potential bug in jaotc
Ludovic Henry
luhenry at microsoft.com
Tue Jan 7 22:16:05 UTC 2020
Hello,
As I was learning and reading over the codebase of src/jdk.aot and src/hotspot/share/aot, I discovered a discrepancy which might lead to future bugs. The issue is around how some of the metadata is generated and loaded between jaotc and the runtime.
In the runtime, `aot_metadata` (src/hotspot/share/aot/aotCompiledMethod.hpp) contains metadata about each method that is compiled in the AOT image - for example, information like the implicit and explicit exception table, or the oop map. Because the size of this data is specific to each method, `aot_metadata` contains fields that store offsets to the `this` pointer, and the data is stored right after the `aot_metadata` structure in the AOT image.
The structure of `aot_metadata` is the following:
class aot_metadata {
int _size;
int _code_size;
int _entry;
int _verified_entry;
int _exception_handler_offset;
int _deopt_handler_offset;
int _stubs_offset;
int _frame_size;
int _orig_pc_offset;
int _unsafe_access;
// contain the offset to the `this` pointer
int _pc_desc_begin;
int _scopes_begin;
int _reloc_begin;
int _exception_table_begin;
int _nul_chk_table_begin;
int _oopmap_begin;
}
When creating the AOT image and generating the information in `jdk.tools.jaotc.MetadataBuilder` (src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java), the `aot_metadata._nul_chk_table_begin` field is conditionally generated. In the case where there is no implicit exceptions in the method, no data/field is generated in the AOT image. However, there is no check for the existence of this field when loading the `aot_metadata` from the AOT image.
This issue is mitigated by the fact that the `HotSpotMetaData.implicitExceptionBytes` is always set, even if only with an empty `byte[]`. Nonetheless, this field is populated in the runtime in `getMetadata` (in src/hotspot/share/jvmci/jvmciCompilerToVM.cpp), making the initialization and usage of this field far apart, complexifying the overall solution.
The following patch proposes to always generate the `aot_metadata._nul_chk_table_begin` field. It also has the advantage to unify how this field and the others are generated.
diff --git a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java
index 34ce4d8c8b..fa89d34796 100644
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java
@@ -98,7 +98,8 @@ final class MetadataBuilder {
byte[] scopeDesc = metaData.scopesDescBytes();
byte[] relocationInfo = metaData.relocBytes();
byte[] oopMapInfo = metaData.oopMaps();
- byte[] implicitExceptionBytes = HotSpotGraalServices.getImplicitExceptionBytes(metaData);
+ byte[] exceptionBytes = metaData.exceptionBytes();
+ byte[] implicitExceptionBytes = metaData.implicitExceptionBytes();
// create a global symbol at this position for this method
NativeOrderOutputStream metadataStream = new NativeOrderOutputStream();
@@ -143,10 +144,7 @@ final class MetadataBuilder {
NativeOrderOutputStream.PatchableInt scopeOffset = metadataStream.patchableInt();
NativeOrderOutputStream.PatchableInt relocationOffset = metadataStream.patchableInt();
NativeOrderOutputStream.PatchableInt exceptionOffset = metadataStream.patchableInt();
- NativeOrderOutputStream.PatchableInt implictTableOffset = null;
- if (implicitExceptionBytes != null) {
- implictTableOffset = metadataStream.patchableInt();
- }
+ NativeOrderOutputStream.PatchableInt implictTableOffset = metadataStream.patchableInt();
NativeOrderOutputStream.PatchableInt oopMapOffset = metadataStream.patchableInt();
metadataStream.align(8);
@@ -160,12 +158,10 @@ final class MetadataBuilder {
metadataStream.put(relocationInfo).align(8);
exceptionOffset.set(metadataStream.position());
- metadataStream.put(metaData.exceptionBytes()).align(8);
+ metadataStream.put(exceptionBytes).align(8);
- if (implicitExceptionBytes != null) {
- implictTableOffset.set(metadataStream.position());
- metadataStream.put(implicitExceptionBytes).align(8);
- }
+ implictTableOffset.set(metadataStream.position());
+ metadataStream.put(implicitExceptionBytes).align(8);
// oopmaps should be last
oopMapOffset.set(metadataStream.position());
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java
index fc54c41312..3acb6191b9 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java
@@ -41,6 +41,7 @@ public class HotSpotMetaData {
scopesDescBytes = new byte[0];
relocBytes = new byte[0];
exceptionBytes = new byte[0];
+ implicitExceptionBytes = new byte[0];
oopMaps = new byte[0];
metadata = new String[0];
// ...some of them will be overwritten by the VM:
Thank you,
--
Ludovic
More information about the hotspot-compiler-dev
mailing list