Merge
This commit is contained in:
commit
0458113c6b
@ -53,6 +53,8 @@ BUILD_JDK_JTREG_EXECUTABLES_CFLAGS_exeJliLaunchTest := \
|
||||
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli \
|
||||
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjli
|
||||
|
||||
BUILD_JDK_JTREG_LIBRARIES_LDFLAGS_libAsyncStackWalk := $(LIBCXX)
|
||||
|
||||
# Platform specific setup
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
BUILD_JDK_JTREG_EXCLUDE += libDirectIO.c libInheritedChannel.c exelauncher.c
|
||||
@ -63,6 +65,7 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJliLaunchTest := $(WIN_LIB_JLI)
|
||||
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := jvm.lib
|
||||
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib
|
||||
BUILD_JDK_JTREG_LIBRARIES_CFLAGS_libAsyncStackWalk := /EHsc
|
||||
else
|
||||
BUILD_JDK_JTREG_LIBRARIES_LIBS_libstringPlatformChars := -ljava
|
||||
BUILD_JDK_JTREG_LIBRARIES_LIBS_libDirectIO := -ljava
|
||||
|
@ -367,6 +367,11 @@ JavaFrameAnchor* OptimizedEntryBlob::jfa_for_frame(const frame& frame) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool frame::optimized_entry_frame_is_first() const {
|
||||
ShouldNotCallThis();
|
||||
return false;
|
||||
}
|
||||
|
||||
frame frame::sender_for_optimized_entry_frame(RegisterMap* map) const {
|
||||
ShouldNotCallThis();
|
||||
return {};
|
||||
|
@ -313,6 +313,11 @@ frame frame::sender_for_entry_frame(RegisterMap* map) const {
|
||||
return fr;
|
||||
}
|
||||
|
||||
bool frame::optimized_entry_frame_is_first() const {
|
||||
ShouldNotCallThis();
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::verify_deopt_original_pc
|
||||
//
|
||||
|
@ -197,6 +197,11 @@ frame frame::sender_for_entry_frame(RegisterMap *map) const {
|
||||
return fr;
|
||||
}
|
||||
|
||||
bool frame::optimized_entry_frame_is_first() const {
|
||||
ShouldNotCallThis();
|
||||
return false;
|
||||
}
|
||||
|
||||
frame frame::sender_for_interpreter_frame(RegisterMap *map) const {
|
||||
// Pass callers initial_caller_sp as unextended_sp.
|
||||
return frame(sender_sp(), sender_pc(), (intptr_t*)get_ijava_state()->sender_sp);
|
||||
|
@ -208,6 +208,11 @@ frame frame::sender_for_entry_frame(RegisterMap *map) const {
|
||||
return fr;
|
||||
}
|
||||
|
||||
bool frame::optimized_entry_frame_is_first() const {
|
||||
ShouldNotCallThis();
|
||||
return false;
|
||||
}
|
||||
|
||||
frame frame::sender_for_interpreter_frame(RegisterMap *map) const {
|
||||
// Pass callers sender_sp as unextended_sp.
|
||||
return frame(sender_sp(), sender_pc(), (intptr_t*)(ijava_state()->sender_sp));
|
||||
|
@ -358,12 +358,20 @@ JavaFrameAnchor* OptimizedEntryBlob::jfa_for_frame(const frame& frame) const {
|
||||
return reinterpret_cast<JavaFrameAnchor*>(reinterpret_cast<char*>(frame.unextended_sp()) + in_bytes(jfa_sp_offset()));
|
||||
}
|
||||
|
||||
bool frame::optimized_entry_frame_is_first() const {
|
||||
assert(is_optimized_entry_frame(), "must be optimzed entry frame");
|
||||
OptimizedEntryBlob* blob = _cb->as_optimized_entry_blob();
|
||||
JavaFrameAnchor* jfa = blob->jfa_for_frame(*this);
|
||||
return jfa->last_Java_sp() == NULL;
|
||||
}
|
||||
|
||||
frame frame::sender_for_optimized_entry_frame(RegisterMap* map) const {
|
||||
assert(map != NULL, "map must be set");
|
||||
OptimizedEntryBlob* blob = _cb->as_optimized_entry_blob();
|
||||
// Java frame called from C; skip all C frames and return top C
|
||||
// frame of that chunk as the sender
|
||||
JavaFrameAnchor* jfa = blob->jfa_for_frame(*this);
|
||||
assert(!optimized_entry_frame_is_first(), "must have a frame anchor to go back to");
|
||||
assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack");
|
||||
// Since we are walking the stack now this nested anchor is obviously walkable
|
||||
// even if it wasn't when it was stacked.
|
||||
|
@ -61,6 +61,11 @@ frame frame::sender_for_entry_frame(RegisterMap *map) const {
|
||||
return frame(zeroframe()->next(), sender_sp());
|
||||
}
|
||||
|
||||
bool frame::optimized_entry_frame_is_first() const {
|
||||
ShouldNotCallThis();
|
||||
return false;
|
||||
}
|
||||
|
||||
frame frame::sender_for_nonentry_frame(RegisterMap *map) const {
|
||||
assert(zeroframe()->is_interpreter_frame() ||
|
||||
zeroframe()->is_fake_stub_frame(), "wrong type of frame");
|
||||
|
@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "jfr/jfr.hpp"
|
||||
#include "jfr/dcmd/jfrDcmds.hpp"
|
||||
@ -33,6 +33,7 @@
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logConfiguration.hpp"
|
||||
#include "logging/logMessage.hpp"
|
||||
#include "memory/arena.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/objArrayOop.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
@ -219,7 +220,6 @@ void JfrDCmd::invoke(JfrJavaArguments& method, TRAPS) const {
|
||||
JfrJavaArguments constructor_args(&constructor_result);
|
||||
constructor_args.set_klass(javaClass(), CHECK);
|
||||
|
||||
ResourceMark rm(THREAD);
|
||||
HandleMark hm(THREAD);
|
||||
JNIHandleBlockManager jni_handle_management(THREAD);
|
||||
|
||||
@ -241,12 +241,10 @@ void JfrDCmd::parse(CmdLine* line, char delim, TRAPS) {
|
||||
}
|
||||
|
||||
void JfrDCmd::execute(DCmdSource source, TRAPS) {
|
||||
static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;C)[Ljava/lang/String;";
|
||||
|
||||
if (invalid_state(output(), THREAD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;C)[Ljava/lang/String;";
|
||||
JavaValue result(T_OBJECT);
|
||||
JfrJavaArguments execute(&result, javaClass(), "execute", signature, CHECK);
|
||||
jstring argument = JfrJavaSupport::new_string(_args, CHECK);
|
||||
@ -271,13 +269,92 @@ void JfrDCmd::print_help(const char* name) const {
|
||||
static const char signature[] = "()[Ljava/lang/String;";
|
||||
JavaThread* thread = JavaThread::current();
|
||||
JavaValue result(T_OBJECT);
|
||||
JfrJavaArguments print_help(&result, javaClass(), "printHelp", signature, thread);
|
||||
invoke(print_help, thread);
|
||||
JfrJavaArguments printHelp(&result, javaClass(), "printHelp", signature, thread);
|
||||
invoke(printHelp, thread);
|
||||
handle_dcmd_result(output(), result.get_oop(), DCmd_Source_MBean, thread);
|
||||
}
|
||||
|
||||
// Since the DcmdFramework does not support dynamically allocated strings,
|
||||
// we keep them in a thread local arena. The arena is reset between invocations.
|
||||
static THREAD_LOCAL Arena* dcmd_arena = NULL;
|
||||
|
||||
static void prepare_dcmd_string_arena() {
|
||||
if (dcmd_arena == NULL) {
|
||||
dcmd_arena = new (mtTracing) Arena(mtTracing);
|
||||
} else {
|
||||
dcmd_arena->destruct_contents(); // will grow on next allocation
|
||||
}
|
||||
}
|
||||
|
||||
static char* dcmd_arena_allocate(size_t size) {
|
||||
assert(dcmd_arena != NULL, "invariant");
|
||||
return (char*)dcmd_arena->Amalloc(size);
|
||||
}
|
||||
|
||||
static const char* get_as_dcmd_arena_string(oop string, JavaThread* t) {
|
||||
char* str = NULL;
|
||||
const typeArrayOop value = java_lang_String::value(string);
|
||||
if (value != NULL) {
|
||||
const size_t length = static_cast<size_t>(java_lang_String::utf8_length(string, value)) + 1;
|
||||
str = dcmd_arena_allocate(length);
|
||||
assert(str != NULL, "invariant");
|
||||
java_lang_String::as_utf8_string(string, value, str, static_cast<int>(length));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static const char* read_string_field(oop argument, const char* field_name, TRAPS) {
|
||||
JavaValue result(T_OBJECT);
|
||||
JfrJavaArguments args(&result);
|
||||
args.set_klass(argument->klass());
|
||||
args.set_name(field_name);
|
||||
args.set_signature("Ljava/lang/String;");
|
||||
args.set_receiver(argument);
|
||||
JfrJavaSupport::get_field(&args, THREAD);
|
||||
const oop string_oop = result.get_oop();
|
||||
return string_oop != NULL ? get_as_dcmd_arena_string(string_oop, (JavaThread*)THREAD) : NULL;
|
||||
}
|
||||
|
||||
static bool read_boolean_field(oop argument, const char* field_name, TRAPS) {
|
||||
JavaValue result(T_BOOLEAN);
|
||||
JfrJavaArguments args(&result);
|
||||
args.set_klass(argument->klass());
|
||||
args.set_name(field_name);
|
||||
args.set_signature("Z");
|
||||
args.set_receiver(argument);
|
||||
JfrJavaSupport::get_field(&args, THREAD);
|
||||
return (result.get_jint() & 1) == 1;
|
||||
}
|
||||
|
||||
static DCmdArgumentInfo* create_info(oop argument, TRAPS) {
|
||||
return new DCmdArgumentInfo(
|
||||
read_string_field(argument, "name", THREAD),
|
||||
read_string_field(argument, "description", THREAD),
|
||||
read_string_field(argument, "type", THREAD),
|
||||
read_string_field(argument, "defaultValue", THREAD),
|
||||
read_boolean_field(argument, "mandatory", THREAD),
|
||||
true, // a DcmdFramework "option"
|
||||
read_boolean_field(argument, "allowMultiple", THREAD));
|
||||
}
|
||||
|
||||
GrowableArray<DCmdArgumentInfo*>* JfrDCmd::argument_info_array() const {
|
||||
return new GrowableArray<DCmdArgumentInfo*>();
|
||||
static const char signature[] = "()[Ljdk/jfr/internal/dcmd/Argument;";
|
||||
JavaThread* thread = JavaThread::current();
|
||||
JavaValue result(T_OBJECT);
|
||||
JfrJavaArguments getArgumentInfos(&result, javaClass(), "getArgumentInfos", signature, thread);
|
||||
invoke(getArgumentInfos, thread);
|
||||
objArrayOop arguments = objArrayOop(result.get_oop());
|
||||
assert(arguments != NULL, "invariant");
|
||||
assert(arguments->is_array(), "must be array");
|
||||
GrowableArray<DCmdArgumentInfo*>* const array = new GrowableArray<DCmdArgumentInfo*>();
|
||||
const int length = arguments->length();
|
||||
prepare_dcmd_string_arena();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
DCmdArgumentInfo* const dai = create_info(arguments->obj_at(i), thread);
|
||||
assert(dai != NULL, "invariant");
|
||||
array->append(dai);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
GrowableArray<const char*>* JfrDCmd::argument_name_array() const {
|
||||
@ -387,7 +464,6 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceMark rm(THREAD);
|
||||
HandleMark hm(THREAD);
|
||||
JNIHandleBlockManager jni_handle_management(THREAD);
|
||||
|
||||
|
@ -65,6 +65,9 @@ class JfrStartFlightRecordingDCmd : public JfrDCmd {
|
||||
virtual const char* javaClass() const {
|
||||
return "jdk/jfr/internal/dcmd/DCmdStart";
|
||||
}
|
||||
static int num_arguments() {
|
||||
return 11;
|
||||
}
|
||||
};
|
||||
|
||||
class JfrDumpFlightRecordingDCmd : public JfrDCmd {
|
||||
@ -87,6 +90,9 @@ class JfrDumpFlightRecordingDCmd : public JfrDCmd {
|
||||
virtual const char* javaClass() const {
|
||||
return "jdk/jfr/internal/dcmd/DCmdDump";
|
||||
}
|
||||
static int num_arguments() {
|
||||
return 7;
|
||||
}
|
||||
};
|
||||
|
||||
class JfrCheckFlightRecordingDCmd : public JfrDCmd {
|
||||
@ -109,6 +115,9 @@ class JfrCheckFlightRecordingDCmd : public JfrDCmd {
|
||||
virtual const char* javaClass() const {
|
||||
return "jdk/jfr/internal/dcmd/DCmdCheck";
|
||||
}
|
||||
static int num_arguments() {
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
|
||||
class JfrStopFlightRecordingDCmd : public JfrDCmd {
|
||||
@ -131,6 +140,9 @@ class JfrStopFlightRecordingDCmd : public JfrDCmd {
|
||||
virtual const char* javaClass() const {
|
||||
return "jdk/jfr/internal/dcmd/DCmdStop";
|
||||
}
|
||||
static int num_arguments() {
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
|
||||
class JfrConfigureFlightRecorderDCmd : public DCmdWithParser {
|
||||
|
@ -1758,7 +1758,7 @@ Node *AllocateArrayNode::make_ideal_length(const TypeOopPtr* oop_type, PhaseTran
|
||||
InitializeNode* init = initialization();
|
||||
assert(init != NULL, "initialization not found");
|
||||
length = new CastIINode(length, narrow_length_type);
|
||||
length->set_req(0, init->proj_out_or_null(0));
|
||||
length->set_req(TypeFunc::Control, init->proj_out_or_null(TypeFunc::Control));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1184,15 +1184,31 @@ Node* GraphKit::load_array_length(Node* array) {
|
||||
Node *r_adr = basic_plus_adr(array, arrayOopDesc::length_offset_in_bytes());
|
||||
alen = _gvn.transform( new LoadRangeNode(0, immutable_memory(), r_adr, TypeInt::POS));
|
||||
} else {
|
||||
alen = alloc->Ideal_length();
|
||||
Node* ccast = alloc->make_ideal_length(_gvn.type(array)->is_oopptr(), &_gvn);
|
||||
if (ccast != alen) {
|
||||
alen = _gvn.transform(ccast);
|
||||
}
|
||||
alen = array_ideal_length(alloc, _gvn.type(array)->is_oopptr(), false);
|
||||
}
|
||||
return alen;
|
||||
}
|
||||
|
||||
Node* GraphKit::array_ideal_length(AllocateArrayNode* alloc,
|
||||
const TypeOopPtr* oop_type,
|
||||
bool replace_length_in_map) {
|
||||
Node* length = alloc->Ideal_length();
|
||||
if (replace_length_in_map == false || map()->find_edge(length) >= 0) {
|
||||
Node* ccast = alloc->make_ideal_length(oop_type, &_gvn);
|
||||
if (ccast != length) {
|
||||
// do not transfrom ccast here, it might convert to top node for
|
||||
// negative array length and break assumptions in parsing stage.
|
||||
_gvn.set_type_bottom(ccast);
|
||||
record_for_igvn(ccast);
|
||||
if (replace_length_in_map) {
|
||||
replace_in_map(length, ccast);
|
||||
}
|
||||
return ccast;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
//------------------------------do_null_check----------------------------------
|
||||
// Helper function to do a NULL pointer check. Returned value is
|
||||
// the incoming address with NULL casted away. You are allowed to use the
|
||||
@ -3980,16 +3996,7 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
||||
|
||||
Node* javaoop = set_output_for_allocation(alloc, ary_type, deoptimize_on_exception);
|
||||
|
||||
// Cast length on remaining path to be as narrow as possible
|
||||
if (map()->find_edge(length) >= 0) {
|
||||
Node* ccast = alloc->make_ideal_length(ary_type, &_gvn);
|
||||
if (ccast != length) {
|
||||
_gvn.set_type_bottom(ccast);
|
||||
record_for_igvn(ccast);
|
||||
replace_in_map(length, ccast);
|
||||
}
|
||||
}
|
||||
|
||||
array_ideal_length(alloc, ary_type, true);
|
||||
return javaoop;
|
||||
}
|
||||
|
||||
|
@ -343,6 +343,12 @@ class GraphKit : public Phase {
|
||||
Node* load_object_klass(Node* object);
|
||||
// Find out the length of an array.
|
||||
Node* load_array_length(Node* array);
|
||||
// Cast array allocation's length as narrow as possible.
|
||||
// If replace_length_in_map is true, replace length with CastIINode in map.
|
||||
// This method is invoked after creating/moving ArrayAllocationNode or in load_array_length
|
||||
Node* array_ideal_length(AllocateArrayNode* alloc,
|
||||
const TypeOopPtr* oop_type,
|
||||
bool replace_length_in_map);
|
||||
|
||||
|
||||
// Helper function to do a NULL pointer check or ZERO check based on type.
|
||||
|
@ -4445,6 +4445,36 @@ void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, No
|
||||
Node* alloc_mem = alloc->in(TypeFunc::Memory);
|
||||
C->gvn_replace_by(callprojs.fallthrough_ioproj, alloc->in(TypeFunc::I_O));
|
||||
C->gvn_replace_by(init->proj_out(TypeFunc::Memory), alloc_mem);
|
||||
|
||||
// The CastIINode created in GraphKit::new_array (in AllocateArrayNode::make_ideal_length) must stay below
|
||||
// the allocation (i.e. is only valid if the allocation succeeds):
|
||||
// 1) replace CastIINode with AllocateArrayNode's length here
|
||||
// 2) Create CastIINode again once allocation has moved (see below) at the end of this method
|
||||
//
|
||||
// Multiple identical CastIINodes might exist here. Each GraphKit::load_array_length() call will generate
|
||||
// new separate CastIINode (arraycopy guard checks or any array length use between array allocation and ararycopy)
|
||||
Node* init_control = init->proj_out(TypeFunc::Control);
|
||||
Node* alloc_length = alloc->Ideal_length();
|
||||
#ifdef ASSERT
|
||||
Node* prev_cast = NULL;
|
||||
#endif
|
||||
for (uint i = 0; i < init_control->outcnt(); i++) {
|
||||
Node* init_out = init_control->raw_out(i);
|
||||
if (init_out->is_CastII() && init_out->in(TypeFunc::Control) == init_control && init_out->in(1) == alloc_length) {
|
||||
#ifdef ASSERT
|
||||
if (prev_cast == NULL) {
|
||||
prev_cast = init_out;
|
||||
} else {
|
||||
if (prev_cast->cmp(*init_out) == false) {
|
||||
prev_cast->dump();
|
||||
init_out->dump();
|
||||
assert(false, "not equal CastIINode");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
C->gvn_replace_by(init_out, alloc_length);
|
||||
}
|
||||
}
|
||||
C->gvn_replace_by(init->proj_out(TypeFunc::Control), alloc->in(0));
|
||||
|
||||
// move the allocation here (after the guards)
|
||||
@ -4476,6 +4506,8 @@ void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, No
|
||||
dest->set_req(0, control());
|
||||
Node* destx = _gvn.transform(dest);
|
||||
assert(destx == dest, "where has the allocation result gone?");
|
||||
|
||||
array_ideal_length(alloc, ary_type, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1996,10 +1996,13 @@ static void clone_outer_loop_helper(Node* n, const IdealLoopTree *loop, const Id
|
||||
Node* u = n->fast_out(j);
|
||||
assert(check_old_new || old_new[u->_idx] == NULL, "shouldn't have been cloned");
|
||||
if (!u->is_CFG() && (!check_old_new || old_new[u->_idx] == NULL)) {
|
||||
Node* c = u->in(0) != NULL ? u->in(0) : phase->get_ctrl(u);
|
||||
Node* c = phase->get_ctrl(u);
|
||||
IdealLoopTree* u_loop = phase->get_loop(c);
|
||||
assert(!loop->is_member(u_loop), "can be in outer loop or out of both loops only");
|
||||
if (outer_loop->is_member(u_loop)) {
|
||||
if (outer_loop->is_member(u_loop) ||
|
||||
// nodes pinned with control in the outer loop but not referenced from the safepoint must be moved out of
|
||||
// the outer loop too
|
||||
(u->in(0) != NULL && outer_loop->is_member(phase->get_loop(u->in(0))))) {
|
||||
wq.push(u);
|
||||
}
|
||||
}
|
||||
|
@ -2306,6 +2306,7 @@ WB_ENTRY(void, WB_VerifyFrames(JNIEnv* env, jobject wb, jboolean log, jboolean u
|
||||
tty_token = ttyLocker::hold_tty();
|
||||
tty->print_cr("[WhiteBox::VerifyFrames] Walking Frames");
|
||||
}
|
||||
ResourceMark rm; // for verify
|
||||
for (StackFrameStream fst(JavaThread::current(), update_map, true); !fst.is_done(); fst.next()) {
|
||||
frame* current_frame = fst.current();
|
||||
if (log) {
|
||||
|
@ -1957,7 +1957,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr
|
||||
|
||||
ScopeDesc* trap_scope = cvf->scope();
|
||||
|
||||
bool is_receiver_constraint_failure = VerifyReceiverTypes && (reason == Deoptimization::Reason_receiver_constraint);
|
||||
bool is_receiver_constraint_failure = COMPILER2_PRESENT(VerifyReceiverTypes &&) (reason == Deoptimization::Reason_receiver_constraint);
|
||||
|
||||
if (TraceDeoptimization || is_receiver_constraint_failure) {
|
||||
ttyLocker ttyl;
|
||||
|
@ -342,6 +342,7 @@ class frame {
|
||||
|
||||
// tells whether there is another chunk of Delta stack above
|
||||
bool entry_frame_is_first() const;
|
||||
bool optimized_entry_frame_is_first() const;
|
||||
|
||||
// Safepoints
|
||||
|
||||
|
@ -50,7 +50,9 @@ inline bool frame::is_stub_frame() const {
|
||||
}
|
||||
|
||||
inline bool frame::is_first_frame() const {
|
||||
return is_entry_frame() && entry_frame_is_first();
|
||||
return (is_entry_frame() && entry_frame_is_first())
|
||||
// Optimized entry frames are only present on certain platforms
|
||||
|| (is_optimized_entry_frame() && optimized_entry_frame_is_first());
|
||||
}
|
||||
|
||||
inline bool frame::is_optimized_entry_frame() const {
|
||||
|
@ -58,7 +58,10 @@ abstract class AbstractDCmd {
|
||||
// Called by native
|
||||
public abstract String[] printHelp();
|
||||
|
||||
// Called by native
|
||||
// Called by native. The number of arguments for each command is
|
||||
// reported to the DCmdFramework as a hardcoded number in native.
|
||||
// This is to avoid an upcall as part of DcmdFramework enumerating existing commands.
|
||||
// Remember to keep the two sides in synch.
|
||||
public abstract Argument[] getArgumentInfos();
|
||||
|
||||
// Called by native
|
||||
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8268362
|
||||
* @requires vm.compiler2.enabled & vm.debug
|
||||
* @summary C2 using negative array length as index, using a.length.
|
||||
* AllocateArrayNode::make_ideal_length create CastIINode to not negative range.
|
||||
* Apply transform in GraphKit::load_array_length will covert array load index type to top.
|
||||
* This cause assert in Parse::array_addressing, it expect index type is int.
|
||||
* @run main/othervm -XX:-PrintCompilation compiler.arraycopy.TestNegArrayLengthAsIndex1
|
||||
*/
|
||||
|
||||
package compiler.arraycopy;
|
||||
public class TestNegArrayLengthAsIndex1 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
|
||||
static int foo() {
|
||||
int minusOne = -1;
|
||||
int[] a = null;
|
||||
try {
|
||||
a = new int[minusOne];
|
||||
} catch (NegativeArraySizeException e) {
|
||||
return 0;
|
||||
}
|
||||
return a[a.length - 1];
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8268362
|
||||
* @requires vm.compiler2.enabled & vm.debug
|
||||
* @summary C2 using negative array length as index, using array allocation length.
|
||||
* This assertion is triggered by 8267904.
|
||||
* @run main/othervm compiler.arraycopy.TestNegArrayLengthAsIndex2
|
||||
*/
|
||||
|
||||
package compiler.arraycopy;
|
||||
public class TestNegArrayLengthAsIndex2 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
|
||||
static int foo() {
|
||||
int minusOne = -1;
|
||||
int[] a = null;
|
||||
try {
|
||||
a = new int[minusOne];
|
||||
} catch (NegativeArraySizeException e) {
|
||||
return 0;
|
||||
}
|
||||
return a[minusOne - 1];
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2021 THL A29 Limited, a Tencent company. 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8267904
|
||||
* @requires vm.compiler2.enabled
|
||||
* @summary C2 inline array_copy move CastIINode(Array Length) before allocation cause crash.
|
||||
* @run main/othervm compiler.arraycopy.TestNegativeArrayCopyAfterLoop
|
||||
*/
|
||||
|
||||
package compiler.arraycopy;
|
||||
import java.util.Arrays;
|
||||
|
||||
class test {
|
||||
public static int exp_count = 0;
|
||||
public int in1 = -4096;
|
||||
test (){
|
||||
try {
|
||||
short sha4[] = new short[1012];
|
||||
for (int i = 0; i < sha4.length; i++) {
|
||||
sha4[i] = 9;
|
||||
}
|
||||
Arrays.copyOf(sha4, in1);
|
||||
} catch (Exception ex) {
|
||||
exp_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TestNegativeArrayCopyAfterLoop {
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
new test();
|
||||
}
|
||||
if (test.exp_count == 20000) {
|
||||
System.out.println("TEST PASSED");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Red Hat, Inc. 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8268672
|
||||
* @summary C2: assert(!loop->is_member(u_loop)) failed: can be in outer loop or out of both loops only
|
||||
*
|
||||
* @run main/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=TestPinnedNodeInInnerLoop TestPinnedNodeInInnerLoop
|
||||
*
|
||||
*/
|
||||
|
||||
public class TestPinnedNodeInInnerLoop {
|
||||
boolean b;
|
||||
double d;
|
||||
int iArr[];
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestPinnedNodeInInnerLoop t = new TestPinnedNodeInInnerLoop();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
t.test();
|
||||
}
|
||||
}
|
||||
|
||||
void test() {
|
||||
int e = 4, f = -51874, g = 7, h = 0;
|
||||
|
||||
for (; f < 3; ++f) {
|
||||
}
|
||||
while (++g < 2) {
|
||||
if (b) {
|
||||
d = h;
|
||||
} else {
|
||||
iArr[g] = e;
|
||||
}
|
||||
}
|
||||
System.out.println(g);
|
||||
}
|
||||
}
|
113
test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java
Normal file
113
test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
|
||||
* @library /test/lib
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
*
|
||||
* @run main/othervm
|
||||
* -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -Djdk.internal.foreign.ProgrammableInvoker.USE_INTRINSICS=true
|
||||
* --enable-native-access=ALL-UNNAMED
|
||||
* -Xbatch
|
||||
* TestAsyncStackWalk
|
||||
*
|
||||
* @run main/othervm
|
||||
* -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -Djdk.internal.foreign.ProgrammableInvoker.USE_INTRINSICS=false
|
||||
* --enable-native-access=ALL-UNNAMED
|
||||
* -Xbatch
|
||||
* TestAsyncStackWalk
|
||||
*/
|
||||
|
||||
import jdk.incubator.foreign.CLinker;
|
||||
import jdk.incubator.foreign.FunctionDescriptor;
|
||||
import jdk.incubator.foreign.SymbolLookup;
|
||||
import jdk.incubator.foreign.MemoryAddress;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
||||
import jdk.incubator.foreign.ResourceScope;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
import static java.lang.invoke.MethodHandles.lookup;
|
||||
import static jdk.incubator.foreign.CLinker.C_POINTER;
|
||||
import static jdk.test.lib.Asserts.assertTrue;
|
||||
|
||||
public class TestAsyncStackWalk {
|
||||
static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||
|
||||
static final CLinker linker = CLinker.getInstance();
|
||||
|
||||
static final MethodHandle MH_asyncStackWalk;
|
||||
static final MethodHandle MH_m;
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("AsyncStackWalk");
|
||||
SymbolLookup lookup = SymbolLookup.loaderLookup();
|
||||
MH_asyncStackWalk = linker.downcallHandle(
|
||||
lookup.lookup("asyncStackWalk").get(),
|
||||
MethodType.methodType(void.class, MemoryAddress.class),
|
||||
FunctionDescriptor.ofVoid(C_POINTER));
|
||||
MH_m = lookup().findStatic(TestAsyncStackWalk.class, "m", MethodType.methodType(void.class));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static int invocations;
|
||||
static boolean didStackWalk;
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
|
||||
MemoryAddress stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), scope);
|
||||
MemoryAddress stubAddress = stub.address();
|
||||
invocations = 0;
|
||||
didStackWalk = false;
|
||||
payload(stubAddress);
|
||||
assertTrue(didStackWalk);
|
||||
}
|
||||
}
|
||||
|
||||
static void payload(MemoryAddress cb) throws Throwable {
|
||||
MH_asyncStackWalk.invokeExact(cb);
|
||||
}
|
||||
|
||||
static void m() {
|
||||
if (invocations++ >= 20000) { // warmup
|
||||
didStackWalk = true;
|
||||
WB.verifyFrames(/*log=*/true, /*updateRegisterMap=*/true);
|
||||
WB.verifyFrames(/*log=*/true, /*updateRegisterMap=*/false); // triggers different code paths
|
||||
}
|
||||
}
|
||||
|
||||
}
|
44
test/jdk/java/foreign/stackwalk/libAsyncStackWalk.cpp
Normal file
44
test/jdk/java/foreign/stackwalk/libAsyncStackWalk.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <thread>
|
||||
|
||||
#ifdef _WIN64
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define EXPORT
|
||||
#endif
|
||||
|
||||
static void start(void (*cb)(void)) {
|
||||
for (int i = 0; i < 25000; i++) {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
EXPORT void asyncStackWalk(void (*cb)(void)) {
|
||||
std::thread thrd(start, cb);
|
||||
thrd.join();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user