RFR: 8293980: Resolve CONSTANT_FieldRef at CDS dump time [v3]
Ioi Lam
iklam at openjdk.org
Wed May 29 16:07:22 UTC 2024
On Wed, 29 May 2024 12:53:57 GMT, Dan Heidinga <heidinga at openjdk.org> wrote:
>> Ioi Lam has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision:
>>
>> - Fixed typo in previous commit
>> - Merge branch 'master' into 8293980-resolve-fields-at-dumptime
>> - @matias9927 comments - moved remove_resolved_field_entries_if_non_deterministic() to cpCache
>> - Merge branch 'master' into 8293980-resolve-fields-at-dumptime
>> - 8293980: Resolve CONSTANT_FieldRef at CDS dump time
>
> src/hotspot/share/cds/classListParser.cpp line 848:
>
>> 846: if (preresolve_fmi) {
>> 847: ClassPrelinker::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
>> 848: }
>
> Can you clarify the approach here?
>
> As I read the code, `ClassPrelinker::preresolve_class_cp_entries` will walk the whole constant pool looking for unresolved class entries that match and then resolve them. `ClassPrelinker::preresolve_field_and_method_cp_entries` walks all methods bytecode by bytecode to resolve them.
>
> Doesn't the `preresolve_list` already tell us which CP entries need to be resolved and the cp tag tell us the type of resolution to do? Can we not do this in a single pass over the cp rather than walking method bytecodes?
>
> Is the reason for this approach to avoid always resolving FieldMethodRefs for both get and put and only do them if there's a corresponding bytecode?
`preresolve_list` has the original CP indices (E.g., `putfield #123` as stored in the classfile), but in HotSpot, after bytecode rewriting, the u2 following the bytecode is changed to an index into the `cpcache()->_resolved_field_entries` array, so it becomes something like `putfield #45`. So we need to know how to convert the `123` index to the `45` index.
We could walk `_resolved_field_entries` to find the `ResolvedFieldEntry` whose `_cpool_index` is `123`. However, before the `ResolvedFieldEntry` is resolved, we don't know which bytecode is used to resolve it, so we don't know whether it's for a static field or non-static field. Since we want to filter out the static fields in the PR, we need to:
- walk the bytecodes to find only getfield/putfield bytecodes
- these bytecodes will give us an index to the `_resolved_field_entries` array
- from there, we discover the original CP index
- then we see if this index is set to true in `preresolve_list`
There's also a compatibility issue -- it's possible to have static and non-static field access using the same CP index:
class Hack {
static int myField;
int foo(boolean flag) {
try {
if (flag) {
// throw IncompatibleClassChangeError
return /* pseudo code*/ getfield this.myField;
} else {
// OK
return /* pseudo code*/ getstatic Hack.myField;
}
} catch (Throwable) {
return 5678;
}
}
So we must call `InterpreterRuntime::resolve_get_put()` which performs all the checks for access rights, static-vs-non-static, etc. This call requires a Method parameter, so we must walk all the Methods to find an appropriate one.
Perhaps it's possible to refactor the `InterpreterRuntime` code to avoid passing in a Method, but I am hesitant to do that with code that deals with access right checks.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/19355#discussion_r1619144592
More information about the build-dev
mailing list