Skip to content
Permalink
Browse files
8227745: Enable Escape Analysis for Better Performance in the Presenc…
…e of JVMTI Agents

8233915: JVMTI FollowReferences: Java Heap Leak not found because of C2 Scalar Replacement

Reviewed-by: mdoerr, goetz, sspitsyn, kvn
  • Loading branch information
reinrich committed Oct 20, 2020
1 parent f167a71 commit 40f847e2fb5af957f1b416d2fe11fe233f8764c2
Showing with 5,744 additions and 218 deletions.
  1. +6 −2 src/hotspot/share/c1/c1_IR.hpp
  2. +5 −0 src/hotspot/share/ci/ciEnv.cpp
  3. +2 −0 src/hotspot/share/ci/ciEnv.hpp
  4. +3 −7 src/hotspot/share/code/compiledMethod.cpp
  5. +4 −0 src/hotspot/share/code/debugInfoRec.cpp
  6. +3 −1 src/hotspot/share/code/debugInfoRec.hpp
  7. +2 −6 src/hotspot/share/code/nmethod.cpp
  8. +14 −2 src/hotspot/share/code/pcDesc.hpp
  9. +10 −15 src/hotspot/share/code/scopeDesc.cpp
  10. +9 −7 src/hotspot/share/code/scopeDesc.hpp
  11. +107 −15 src/hotspot/share/compiler/compileBroker.cpp
  12. +8 −2 src/hotspot/share/compiler/compileBroker.hpp
  13. +2 −1 src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp
  14. +4 −0 src/hotspot/share/jvmci/jvmciCodeInstaller.cpp
  15. +1 −2 src/hotspot/share/opto/c2compiler.cpp
  16. +15 −3 src/hotspot/share/opto/callnode.hpp
  17. +84 −0 src/hotspot/share/opto/escape.cpp
  18. +5 −0 src/hotspot/share/opto/escape.hpp
  19. +3 −1 src/hotspot/share/opto/machnode.hpp
  20. +4 −3 src/hotspot/share/opto/macro.cpp
  21. +2 −0 src/hotspot/share/opto/matcher.cpp
  22. +7 −1 src/hotspot/share/opto/output.cpp
  23. +1 −1 src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp
  24. +87 −0 src/hotspot/share/prims/jvmtiDeferredUpdates.cpp
  25. +159 −0 src/hotspot/share/prims/jvmtiDeferredUpdates.hpp
  26. +23 −0 src/hotspot/share/prims/jvmtiEnv.cpp
  27. +15 −2 src/hotspot/share/prims/jvmtiEnvBase.cpp
  28. +1 −1 src/hotspot/share/prims/jvmtiEnvBase.hpp
  29. +60 −1 src/hotspot/share/prims/jvmtiImpl.cpp
  30. +5 −0 src/hotspot/share/prims/jvmtiImpl.hpp
  31. +19 −2 src/hotspot/share/prims/jvmtiTagMap.cpp
  32. +15 −0 src/hotspot/share/prims/whitebox.cpp
  33. +148 −40 src/hotspot/share/runtime/deoptimization.cpp
  34. +15 −3 src/hotspot/share/runtime/deoptimization.hpp
  35. +353 −0 src/hotspot/share/runtime/escapeBarrier.cpp
  36. +139 −0 src/hotspot/share/runtime/escapeBarrier.hpp
  37. +23 −0 src/hotspot/share/runtime/globals.hpp
  38. +2 −0 src/hotspot/share/runtime/mutexLocker.cpp
  39. +1 −0 src/hotspot/share/runtime/mutexLocker.hpp
  40. +3 −1 src/hotspot/share/runtime/objectMonitor.cpp
  41. +8 −0 src/hotspot/share/runtime/safepoint.cpp
  42. +82 −12 src/hotspot/share/runtime/thread.cpp
  43. +20 −11 src/hotspot/share/runtime/thread.hpp
  44. +6 −0 src/hotspot/share/runtime/thread.inline.hpp
  45. +5 −0 src/hotspot/share/runtime/vframe.cpp
  46. +82 −8 src/hotspot/share/runtime/vframe_hp.cpp
  47. +11 −68 src/hotspot/share/runtime/vframe_hp.hpp
  48. +4 −0 src/hotspot/share/utilities/macros.hpp
  49. +610 −0 test/hotspot/jtreg/serviceability/jvmti/Heap/IterateHeapWithEscapeAnalysisEnabled.java
  50. +370 −0 test/hotspot/jtreg/serviceability/jvmti/Heap/libIterateHeapWithEscapeAnalysisEnabled.cpp
  51. +1 −0 test/jdk/TEST.ROOT
  52. +3,175 −0 test/jdk/com/sun/jdi/EATests.java
  53. +1 −0 test/lib/sun/hotspot/WhiteBox.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -244,7 +244,11 @@ class IRScopeDebugInfo: public CompilationResourceObj {
bool reexecute = topmost ? should_reexecute() : false;
bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
bool rethrow_exception = false;
recorder->describe_scope(pc_offset, methodHandle(), scope()->method(), bci(), reexecute, rethrow_exception, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
bool has_ea_local_in_scope = false;
bool arg_escape = false;
recorder->describe_scope(pc_offset, methodHandle(), scope()->method(), bci(),
reexecute, rethrow_exception, is_method_handle_invoke, return_oop,
has_ea_local_in_scope, arg_escape, locvals, expvals, monvals);
}
};

@@ -242,6 +242,7 @@ bool ciEnv::cache_jvmti_state() {
_jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions();
_jvmti_can_pop_frame = JvmtiExport::can_pop_frame();
_jvmti_can_get_owned_monitor_info = JvmtiExport::can_get_owned_monitor_info();
_jvmti_can_walk_any_space = JvmtiExport::can_walk_any_space();
return _task != NULL && _task->method()->is_old();
}

@@ -271,6 +272,10 @@ bool ciEnv::jvmti_state_changed() const {
JvmtiExport::can_get_owned_monitor_info()) {
return true;
}
if (!_jvmti_can_walk_any_space &&
JvmtiExport::can_walk_any_space()) {
return true;
}

return false;
}
@@ -74,6 +74,7 @@ class ciEnv : StackObj {
bool _jvmti_can_post_on_exceptions;
bool _jvmti_can_pop_frame;
bool _jvmti_can_get_owned_monitor_info; // includes can_get_owned_monitor_stack_depth_info
bool _jvmti_can_walk_any_space;

// Cache DTrace flags
bool _dtrace_extended_probes;
@@ -349,6 +350,7 @@ class ciEnv : StackObj {
bool jvmti_can_hotswap_or_post_breakpoint() const { return _jvmti_can_hotswap_or_post_breakpoint; }
bool jvmti_can_post_on_exceptions() const { return _jvmti_can_post_on_exceptions; }
bool jvmti_can_get_owned_monitor_info() const { return _jvmti_can_get_owned_monitor_info; }
bool jvmti_can_walk_any_space() const { return _jvmti_can_walk_any_space; }

// Cache DTrace flags
void cache_dtrace_flags();
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -293,17 +293,13 @@ void CompiledMethod::verify_oop_relocations() {
ScopeDesc* CompiledMethod::scope_desc_at(address pc) {
PcDesc* pd = pc_desc_at(pc);
guarantee(pd != NULL, "scope must be present");
return new ScopeDesc(this, pd->scope_decode_offset(),
pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
pd->return_oop());
return new ScopeDesc(this, pd);
}

ScopeDesc* CompiledMethod::scope_desc_near(address pc) {
PcDesc* pd = pc_desc_near(pc);
guarantee(pd != NULL, "scope must be present");
return new ScopeDesc(this, pd->scope_decode_offset(),
pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
pd->return_oop());
return new ScopeDesc(this, pd);
}

address CompiledMethod::oops_reloc_begin() const {
@@ -288,6 +288,8 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
bool rethrow_exception,
bool is_method_handle_invoke,
bool return_oop,
bool has_ea_local_in_scope,
bool arg_escape,
DebugToken* locals,
DebugToken* expressions,
DebugToken* monitors) {
@@ -304,6 +306,8 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
last_pd->set_rethrow_exception(rethrow_exception);
last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
last_pd->set_return_oop(return_oop);
last_pd->set_has_ea_local_in_scope(has_ea_local_in_scope);
last_pd->set_arg_escape(arg_escape);

// serialize sender stream offest
stream()->write_int(sender_stream_offset);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -105,6 +105,8 @@ class DebugInformationRecorder: public ResourceObj {
bool rethrow_exception = false,
bool is_method_handle_invoke = false,
bool return_oop = false,
bool has_ea_local_in_scope = false,
bool arg_escape = false,
DebugToken* locals = NULL,
DebugToken* expressions = NULL,
DebugToken* monitors = NULL);
@@ -2419,9 +2419,7 @@ void nmethod::verify_interrupt_point(address call_site) {

PcDesc* pd = pc_desc_at(nativeCall_at(call_site)->return_address());
assert(pd != NULL, "PcDesc must exist");
for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(),
pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
pd->return_oop());
for (ScopeDesc* sd = new ScopeDesc(this, pd);
!sd->is_top(); sd = sd->sender()) {
sd->verify();
}
@@ -3056,9 +3054,7 @@ const char* nmethod::reloc_string_for(u_char* begin, u_char* end) {
ScopeDesc* nmethod::scope_desc_in(address begin, address end) {
PcDesc* p = pc_desc_near(begin+1);
if (p != NULL && p->real_pc(this) <= end) {
return new ScopeDesc(this, p->scope_decode_offset(),
p->obj_decode_offset(), p->should_reexecute(), p->rethrow_exception(),
p->return_oop());
return new ScopeDesc(this, p);
}
return NULL;
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,9 @@ class PcDesc {
PCDESC_reexecute = 1 << 0,
PCDESC_is_method_handle_invoke = 1 << 1,
PCDESC_return_oop = 1 << 2,
PCDESC_rethrow_exception = 1 << 3
PCDESC_rethrow_exception = 1 << 3,
PCDESC_has_ea_local_in_scope = 1 << 4,
PCDESC_arg_escape = 1 << 5
};

int _flags;
@@ -89,6 +91,16 @@ class PcDesc {
bool return_oop() const { return (_flags & PCDESC_return_oop) != 0; }
void set_return_oop(bool z) { set_flag(PCDESC_return_oop, z); }

// Indicates if there are objects in scope that, based on escape analysis, are local to the
// compiled method or local to the current thread, i.e. NoEscape or ArgEscape
bool has_ea_local_in_scope() const { return (_flags & PCDESC_has_ea_local_in_scope) != 0; }
void set_has_ea_local_in_scope(bool z) { set_flag(PCDESC_has_ea_local_in_scope, z); }

// Indicates if this pc descriptor is at a call site where objects that do not escape the
// current thread are passed as arguments.
bool arg_escape() const { return (_flags & PCDESC_arg_escape) != 0; }
void set_arg_escape(bool z) { set_flag(PCDESC_arg_escape, z); }

// Returns the real pc
address real_pc(const CompiledMethod* code) const;

@@ -31,23 +31,16 @@
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"

ScopeDesc::ScopeDesc(const CompiledMethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
ScopeDesc::ScopeDesc(const CompiledMethod* code, PcDesc* pd, bool ignore_objects) {
int obj_decode_offset = ignore_objects ? DebugInformationRecorder::serialized_null : pd->obj_decode_offset();
_code = code;
_decode_offset = decode_offset;
_decode_offset = pd->scope_decode_offset();
_objects = decode_object_values(obj_decode_offset);
_reexecute = reexecute;
_rethrow_exception = rethrow_exception;
_return_oop = return_oop;
decode_body();
}

ScopeDesc::ScopeDesc(const CompiledMethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
_code = code;
_decode_offset = decode_offset;
_objects = decode_object_values(DebugInformationRecorder::serialized_null);
_reexecute = reexecute;
_rethrow_exception = rethrow_exception;
_return_oop = return_oop;
_reexecute = pd->should_reexecute();
_rethrow_exception = pd->rethrow_exception();
_return_oop = pd->return_oop();
_has_ea_local_in_scope = ignore_objects ? false : pd->has_ea_local_in_scope();
_arg_escape = ignore_objects ? false : pd->arg_escape();
decode_body();
}

@@ -59,6 +52,8 @@ void ScopeDesc::initialize(const ScopeDesc* parent, int decode_offset) {
_reexecute = false; //reexecute only applies to the first scope
_rethrow_exception = false;
_return_oop = false;
_has_ea_local_in_scope = parent->has_ea_local_in_scope();
_arg_escape = false;
decode_body();
}

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,12 +60,7 @@ class SimpleScopeDesc : public StackObj {
class ScopeDesc : public ResourceObj {
public:
// Constructor
ScopeDesc(const CompiledMethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);

// Calls above, giving default value of "serialized_null" to the
// "obj_decode_offset" argument. (We don't use a default argument to
// avoid a .hpp-.hpp dependency.)
ScopeDesc(const CompiledMethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);
ScopeDesc(const CompiledMethod* code, PcDesc* pd, bool ignore_objects = false);

// Direct access to scope
ScopeDesc* at_offset(int decode_offset) { return new ScopeDesc(this, decode_offset); }
@@ -76,6 +71,10 @@ class ScopeDesc : public ResourceObj {
bool should_reexecute() const { return _reexecute; }
bool rethrow_exception() const { return _rethrow_exception; }
bool return_oop() const { return _return_oop; }
// Returns true if one or more NoEscape or ArgEscape objects exist in
// any of the scopes at compiled pc.
bool has_ea_local_in_scope() const { return _has_ea_local_in_scope; }
bool arg_escape() const { return _arg_escape; }

GrowableArray<ScopeValue*>* locals();
GrowableArray<ScopeValue*>* expressions();
@@ -105,6 +104,9 @@ class ScopeDesc : public ResourceObj {
bool _reexecute;
bool _rethrow_exception;
bool _return_oop;
bool _has_ea_local_in_scope; // One or more NoEscape or ArgEscape objects exist in
// any of the scopes at compiled pc.
bool _arg_escape; // Compiled Java call in youngest scope passes ArgEscape

// Decoding offsets
int _decode_offset;
Loading

1 comment on commit 40f847e

@bridgekeeper

This comment has been minimized.

Copy link

@bridgekeeper bridgekeeper bot commented on 40f847e Oct 20, 2020

Please sign in to comment.