On Fri, Jun 23, 2023 at 6:36 PM Dan Smith <[email protected]> wrote:
> > On Jun 15, 2023, at 6:31 AM, Dan Heidinga <[email protected]> wrote: > > > > Following on from our discussion during the EG meeting, I think our > current error handling approach (drop the errors) unfortunately violates > the spec. > > So using the existing flexibility in the resolution of symbolic > references means we still have to report errors where they may occur in the > program. Looking back at the example classfile, we're within the spec to > preload Constant_class #8 using the existing rules but if it fails during > preload, we need to poison Constant_class #8 so reuse of it fails with the > same exception even if the load of class "V" would succeed later. > > > > This is not the outcome I wanted when digging through the spec - I liked > our decision to ignore errors from preload. > > Let's consider a vanilla VM, without 'Preload'. According to 5.4, when can > an implementation resolve symbolic references? > > - At first execution of an instruction that references the constant > - During verification > - Immediately after loading > - ... > > In fact, there's no constraint on resolution at all, within these bounds: > sometime after loading, sometime before instruction execution (or some > similar "blocking" requirement to access the resolution result). > > There *are* some additional constraints on surfacing errors: they must be > "thrown at a point in the program where some action is taken by the program > that might, directly or indirectly, require linkage to the class or > interface involved in the error". I'm not entirely sure what that means, > but one implication is that resolution might happen at time X, but the > error is held until time Y (X > Y) when it is allowed to be thrown. > (Implemented, perhaps, by setting the state of the constant as "resolved > with error", then leaving it to future resolution attempts to discover and > throw the error.) > Agreed. Once resolution of a symbolic reference to a class fails, it must always fail. > > Within that framework, my interpretation of Preload is that it (1) forces > some symbolic references into the constant pool, giving VMs the opportunity > to resolve them whenever it's convenient (subject to the usual rules); and > (2) encourages VMs to pay special attention to those references, perhaps > resolving them earlier than other references. But this doesn't change > anything about what the spec allows vs. the equivalent class file that has > had its Preload attribute removed. > Also agreed. My concern was that during our EG discussion, we had indicated that Preload-related errors were dropped. Not reporting them at the preload point is fine, but the spec requires that failed preloads poison symbolic reference (ie: Constant_Class constant pool entry) so future attempts to use it also fail. It sounds like you and I are interpreting the current spec the same way but that it's more subtle than we expressed on the EG call. > > What would be invalid, according to JVMS, is to attempt to resolve > something mentioned by 'Preload', get an error, discard the error, and then > come back later and attempt to resolve it again (perhaps succeeding this > time). > 100% > > So that's my read of the status quo. What about this do you specifically > think we should change? > As I said above, I think you and I agree on how error handling has to happen and it's unfortunately more subtle than just drop the errors. I would still like to see a defined point in the loading / linking sequence where the VM has to have attempted the preloads as it makes a stronger guarantee for users. The current approach feels very much like a hack to work around limitations in how calling conventions are bound (and something we'd be happy to see go away in the future) rather than a principled addition to the VM's behaviour. --Dan
