-
Enhancement
-
Resolution: Fixed
-
P4
-
None
-
b21
agents loaded.
Main intent is to be able to start a production system in a mode that allows to
initiate a debugging session anytime later if necessary or desired without the
need to disable escape analysis at start-up. In most cases debugging will never
be activated and the production systems should run at the best possible
performance while still being ready for debugging. The enhancement will improve
performance also when a debugger has attached to the vm.
Another important scenario for the enhancement is heap diagnostics. Agents with
that purpose need not be loaded at start-up. They can be loadded into a running
system whenever necessary or desired. Unfortunately the current JVMTI
implementation does not and cannot give access to scalar replaced objects which
can hinder diagnostics.
fixed by this enhancement also.
Currently EA is disabled if a JVMTI agent added the capability
can_access_local_variables, because an access to a local reference variable
potentially changes the escape state of the referenced object and thereby
invalidates optimizations based on it.
There are more JVMTI capabilities that allow agents to acquire object references
from stack frames:
1. can_access_local_variables
2. can_get_owned_monitor_info
3. can_get_owned_monitor_stack_depth_info
4. can_tag_objects
This allows for example to walk the object graph beginning at its roots,
which include local variables.
4. as can_tag_objects is an always capability.
In addition EA is disabled if
5. can_pop_frame
is added. Not because it gives access to local variables, but because the
implementation of PopFrame interferes with object reallocation during
deoptimization of compiled frames.
It is likely a bug that EA is not disabled if
6. can_force_early_return
is added as ForceEarlyReturn has the same issues with deoptimization.
This enhancement shall allow the JVM to run with escape analysis enabled even if any of the
capabilities 1. to 6. is requested by a JVMTI agent.
Summary of Proposed Implementation
----------------------------------
The JVMTI implementation is changed to revert EA based optimizations just before objects
escape through JVMTI. At runtime there is no escape information for each object
in scope. Instead each scope is annotated, if non-escaping objects exist and if
some are passed as parameters. If a JVMTI agent accesses a reference on stack,
then the owning compiled frame C is deoptimized, if any non-escaping object is
in scope. Scalar replaced objects are reallocated on the heap and objects with
eliminated locking are relocked. This is called "deoptimizing objects" for
short.
If the agent accesses a reference in a callee frame of C and C is passing any
non-escaping object as argument then C and its objects are deoptimized as well.
Deoptimizing Objects
---------------------
Early reallocation of scalar replaced (aka virtual) objects, where reallocation
is done independently of and potentially long before replacing the owning
compiled frame with equivalent interpreter frames, is a preexisting
functionality that is leveraged by the enhancement (see
materializeVirtualObjects).
Reallocating and relocking objects is called "deoptimizing objects".
Deoptimized objects are kept as deferred updates (preexisting
JavaThread::_deferred_locals_updates). Either all objects of a compiled frame
are deoptimized or none. It is annotated at the corresponding deferred updates
if it happened already in order to avoid doing it twice.
EscapeBarrier
------------------
The class EscapeBarrier is the interface to synchronize and trigger
deoptimization before objects escape.
C2 Changes
----------
During EA C2 annotates each safepoint if it has non-escaping
objects in scope and each java call if it has non-escaping objects in its
parameter list.
This information is persisted in the CompiledMethod's debug information.
Escape Information at Runtime
-----------------------------
There is preexisting information about scalar replaced objects and eliminated
locking (note that locks are not only eliminated based on EA, but
also nested locks are omitted).
The implementation adds information about non-escping objects in scope and in
argument lists at call sites:
compiledVFrame::not_global_escape_in_scope()
compiledVFrame::arg_escape()
ScopeDesc::not_global_escape_in_scope()
ScopeDesc::arg_escape()
Synchronization
---------------
Competing agents use the new flag '_obj_deopt' in Thread::_suspend_flags and
the new Monitor EscapeBarrier_lock to synchronize and to suspend their
target thread.
Deoptimization can be concurrent for different target threads.
A self deoptimization cannot be concurrent with other deoptimizations.
Deoptimizing everything (e.g. before heap walks) cannot be concurrent with other
deoptimizations.
See EscapeBarrier::sync_and_suspend_one() and EscapeBarrier::sync_and_suspend_all()
PopFrame and ForceEarlyReturn
-----------------------------
Objects are deoptimized before the PopFrame/ForceEarlyReturn operation and
JVMTI_ERROR_OUT_OF_MEMORY is returned if reallocations fail. This avoids
reallocation failures during the operation.
Performance
-----------
Performance should not be affected if no JVMTI agent is loaded.
If a JVMTI agent is loaded that adds any of the capabilities listed above, but
remains inactive, then there should be a performance gain as high as the gain of
EA.
The performance impact is expected to be still positive if debugging interactively.
jvm2008 results are attated to the RFE.
Microbenchmark results: http://cr.openjdk.java.net/~rrich/webrevs/2019/8227745/webrev.6.microbenchmark/
Testing
-------
The proposed implementation comes with a significant abount of dedicated test
code.
The new develop flag DeoptimizeObjectsALot allows for stress testing, where
internal threads are started that deoptimize frames and objects in millisecond
intervals given with DeoptimizeObjectsALotInterval. The number of threads
started are given with DeoptimizeObjectsALotThreadCountAll and
DeoptimizeObjectsALotThreadCountSingle. The former targets all existing threads
whereas the latter operates on a single thread selected round robin.
- relates to
-
JDK-8259627 Potential memory leaks in JVMTI after JDK-8227745
- Resolved
-
JDK-8230956 Should disable Escape Analysis when JVMTI capability can_tag_objects is taken
- Closed
-
JDK-8226941 Improvements for the Debugging on Demand capabilities
- Closed
-
JDK-8320143 [JVMCI] FrameStates with EA'ed object needs to record extra info for JVMTI
- Open
-
JDK-8214584 stackwalk returns null for scalar-replaced value
- Open
-
JDK-8264699 Re-examine deopt of frames to allow EA be enabled with JVMTI agents
- Open
-
JDK-8230363 C2: Let ConnectionGraph::not_global_escape(Node* n) return false if n is not in the CG
- Resolved
-
JDK-8230677 Should disable Escape Analysis if JVMTI capability can_get_owned_monitor_info was taken
- Resolved
-
JDK-8233915 JVMTI FollowReferences: Java Heap Leak not found because of C2 Scalar Replacement
- Resolved
-
JDK-8256016 Dacapo24H.java failed with "assert(false) failed: unscheduable graph"
- Resolved
-
JDK-8318895 Deoptimization results in incorrect lightweight locking stack
- Resolved
-
JDK-8324881 ObjectSynchronizer::inflate(Thread* current...) is invoked for non-current thread
- Resolved
-
JDK-8255072 [TESTBUG] com/sun/jdi/EATests.java should not fail if expected VMOutOfMemoryException is not thrown
- Resolved
-
JDK-8332903 ubsan: opto/output.cpp:1002:18: runtime error: load of value 171, which is not a valid value for type 'bool'
- Resolved
-
JDK-8214585 LiveStackFrameInfo.getLocals does not materialize virtual objects
- Open