-
Notifications
You must be signed in to change notification settings - Fork 109
8353236: [lworld] Better documentation for Valhalla Unsafe intrinsics #1425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: lworld
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,14 +41,55 @@ | |
* Although the class and all methods are public, use of this class is | ||
* limited because only trusted code can obtain instances of it. | ||
* | ||
* <em>Note:</em> It is the responsibility of the caller to make sure | ||
* arguments are checked before methods of this class are | ||
* called. While some rudimentary checks are performed on the input, | ||
* the checks are best effort and when performance is an overriding | ||
* priority, as when methods of this class are optimized by the | ||
* runtime compiler, some or all checks (if any) may be elided. Hence, | ||
* the caller must not rely on the checks and corresponding | ||
* exceptions! | ||
* <h2><a id="undefined-behavior">Undefined Behavior</a></h2> | ||
* For performance reasons, {@code Unsafe} is allowed to work outside the | ||
* restrictions enforced by the JVM. As a result, it is the responsibility of | ||
* the caller to ensure that an invocation of an {@code Unsafe} method is | ||
* conformant, and failure to do so will result in undefined behavior. The | ||
* runtime and the JIT compiler may assume that undefined behavior never | ||
* happens, and operate accordingly. For example, the runtime assumes that each | ||
* object has a header with a particular layout, and if the users use | ||
* {@code Unsafe} to overwrite this header with invalid data, the behavior of | ||
* the runtime becomes unpredictable. Another example is that the JIT compiler | ||
* may assume that accesses on separate objects are unrelated, and schedule | ||
* each of them without taking into consideration the others. If there is an | ||
* {@code Unsafe} access that is out of bounds and points to object different | ||
* from the declared base, the program may execute in a way that a variable | ||
* seems to have multiple values at the same time. As a result, when a program | ||
* exhibits undefined behavior, there is no restrictions on its behaviors. Such | ||
* behaviors may include but not be limited to: | ||
* | ||
* <ul> | ||
* <li>Working as expected. | ||
* <li>Crashing the VM. | ||
* <li>Corruption of the heap or JVM memory. | ||
* <li>Nonsensical variable value. E.g. an {@code int} may appear to be | ||
* simultaneously 0 and 1. | ||
* <li>Impossible code execution. E.g. the branches of an {@code if} are | ||
* both executed or both not executed. | ||
* <li>Wiping out the hard drive. | ||
* </ul> | ||
* | ||
* Undefined behavior, as described in this class, is analogous to the | ||
* terminology with the same name in the C++ language. | ||
* <p> | ||
* Some methods (e.g. {@link #getInt}) exhibit undefined behavior if they | ||
* are invoked at runtime with illegal arguments. This means that they will | ||
* never exhibit undefined behavior if they are not actually reachable at | ||
* runtime. On the other hands, other methods (e.g. | ||
* {@link #makePrivateBuffer(Object)}) exhibit undefined behavior if they are | ||
* used incorrectly, even if the invocation may not be reachable at runtime. | ||
* The analogous terminology in C++ is that such programs are ill-formed. | ||
* <p> | ||
* For methods exhibiting undefined behavior if they are invoked at runtime | ||
* with illegal arguments, undefined behavior may time travel. That is, if a | ||
* control path may eventually reach an invocation of an {@code Unsafe} method | ||
* with illegal arguments, the symptoms of undefined behavior may be present | ||
* even before the invocation of the {@code Unsafe} method. This is because the | ||
* JIT compiler may have certain assumptions about the inputs of an | ||
* {@code Unsafe} invocation, these assumptions may propagate backward to | ||
* previous statements, leading to wrong executions if the assumptions are | ||
* invalid. | ||
* | ||
* @author John R. Rose | ||
* @see #getUnsafe | ||
|
@@ -381,8 +422,30 @@ public native Object[] newSpecialArray(Class<?> componentType, | |
|
||
/** | ||
* Returns an object instance with a private buffered value whose layout | ||
* and contents is exactly the given value instance. The return object | ||
* is in the larval state that can be updated using the unsafe put operation. | ||
* and contents is exactly the given value instance. The return object is | ||
* in the larval state that can be updated using the unsafe put operation. | ||
* <p> | ||
* This method mimics the operation of the bytecode {@code new}, allowing | ||
* the creation of a value object without the conventional Java procedure | ||
* and bypassing the bytecode verifier regarding larval objects. As a | ||
* result, it is the responsibility of the caller to ensure that this | ||
* method is used in a conformant manner. This method exhibits | ||
* {@linkplain Unsafe undefined behavior} unless all the following | ||
* conditions are true: | ||
* <ul> | ||
* <li>The argument must be a value object at runtime. | ||
* <li>The return object must be assigned to a local variable that is | ||
* effectively final as well as definitely assigned to with the return | ||
* value of this method. The object must also be not assigned to another | ||
* local variable. | ||
* <li>The return object can only be used as the first argument passed to | ||
* {@code Unsafe::putXXX} or to {@link #finishPrivateBuffer(Object)}, any | ||
* other usage, such as loading from or returning it, is illegal. The only | ||
* exception is the implicit check cast inserted by the compiler on the | ||
* return value of this method. Explicit check casts are not allowed. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "not allowed"? But there is no enforcement; unpredictable behavior yes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not allowed here in the sense that failure to do so will result in undefined behavior. |
||
* </ul> | ||
* Illegal usage of this method exhibits undefined behavior even if the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. may or can; but not always. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Illegal usage ALWAYS exhibits undefined behavior, the uncertainty here is that whether this undefined behavior manifests itself as an unexpected operation. |
||
* illegal statements are never actually reached at runtime. | ||
* | ||
* @param value a value instance | ||
* @param <V> the type of the given value instance | ||
|
@@ -392,6 +455,19 @@ public native Object[] newSpecialArray(Class<?> componentType, | |
|
||
/** | ||
* Exits the larval state and returns a value instance. | ||
* <p> | ||
* This method mimics the action of passing a larval object to a do-nothing | ||
* constructor to obtain a non-larval object. This method exhibits | ||
* {@linkplain Unsafe undefined behavior} unless all the following | ||
* conditions are true: | ||
* <ul> | ||
* <li>The argument must be a larval value object created by | ||
* {@link #makePrivateBuffer(Object)}. | ||
* <li>After the invocation of this method, the variable that holds the | ||
* argument passed into this method must not be used. | ||
* </ul> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would add the exhortation that every field of the value object must have a value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
* Illegal usage of this method exhibits undefined behavior even if the | ||
* illegal statements are never actually reached at runtime. | ||
Comment on lines
+469
to
+470
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another can/may exhibit case; improve the phrase everywhere. |
||
* | ||
* @param value a value instance | ||
* @param <V> the type of the given value instance | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this restriction? What assumption is violated if there is a second assignment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is none, but it would be easier to specify the restriction on
Unsafe::finishPrivateBuffer
as the only variable referring to the larval object is the one passed into that method. Otherwise, we must say that all variables referring to the object must not be used. This, however, sounds like a runtime constraint while what we really mean is a compile-time constraint. As a result, I think this restriction is harmless but make our life easier.