提交 567a33c9 编写于 作者: D dlong

Merge

...@@ -599,3 +599,5 @@ ebf89088c08ab0508b9002b48dd3d68a340259af hs25.60-b01 ...@@ -599,3 +599,5 @@ ebf89088c08ab0508b9002b48dd3d68a340259af hs25.60-b01
0fb1ac49ae7764c5d7c6dfb9fe046d0e1a4eb5aa hs25.60-b04 0fb1ac49ae7764c5d7c6dfb9fe046d0e1a4eb5aa hs25.60-b04
586a449cd30332dd53c0f74bf2ead6f3d4724bfc jdk8u60-b04 586a449cd30332dd53c0f74bf2ead6f3d4724bfc jdk8u60-b04
74931e85352be8556eaa511ca0dd7c38fe272ec3 hs25.60-b05 74931e85352be8556eaa511ca0dd7c38fe272ec3 hs25.60-b05
b13f1890afb8abc31ecb9c21fd2ba95aba3e33f8 jdk8u60-b05
b17a8a22a0344e3c93e2e4677de20d35f99cf4f5 hs25.60-b06
...@@ -51,6 +51,9 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { ...@@ -51,6 +51,9 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
private static final int C_INT32_SIZE = 4; private static final int C_INT32_SIZE = 4;
private static final int C_INT64_SIZE = 8; private static final int C_INT64_SIZE = 8;
private static int pointerSize = UNINITIALIZED_SIZE; private static int pointerSize = UNINITIALIZED_SIZE;
// Counter to ensure read loops terminate:
private static final int MAX_DUPLICATE_DEFINITIONS = 100;
private int duplicateDefCount = 0;
private static final boolean DEBUG; private static final boolean DEBUG;
static { static {
...@@ -166,6 +169,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { ...@@ -166,6 +169,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
if (typeEntryArrayStride == 0L) {
throw new RuntimeException("zero stride: cannot read types.");
}
// Start iterating down it until we find an entry with no name // Start iterating down it until we find an entry with no name
Address typeNameAddr = null; Address typeNameAddr = null;
do { do {
...@@ -192,7 +199,11 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { ...@@ -192,7 +199,11 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
} }
entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride); entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride);
} while (typeNameAddr != null); } while (typeNameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
throw new RuntimeException("too many duplicate definitions");
}
} }
private void initializePrimitiveTypes() { private void initializePrimitiveTypes() {
...@@ -395,6 +406,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { ...@@ -395,6 +406,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset"); structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset");
structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride"); structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride");
if (structEntryArrayStride == 0L) {
throw new RuntimeException("zero stride: cannot read types.");
}
// Fetch the address of the VMStructEntry* // Fetch the address of the VMStructEntry*
Address entryAddr = lookupInProcess("gHotSpotVMStructs"); Address entryAddr = lookupInProcess("gHotSpotVMStructs");
// Dereference this once to get the pointer to the first VMStructEntry // Dereference this once to get the pointer to the first VMStructEntry
...@@ -472,6 +487,11 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { ...@@ -472,6 +487,11 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset"); intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset");
intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride"); intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride");
if (intConstantEntryArrayStride == 0L) {
throw new RuntimeException("zero stride: cannot read types.");
}
// Fetch the address of the VMIntConstantEntry* // Fetch the address of the VMIntConstantEntry*
Address entryAddr = lookupInProcess("gHotSpotVMIntConstants"); Address entryAddr = lookupInProcess("gHotSpotVMIntConstants");
// Dereference this once to get the pointer to the first VMIntConstantEntry // Dereference this once to get the pointer to the first VMIntConstantEntry
...@@ -501,12 +521,17 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { ...@@ -501,12 +521,17 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
} else { } else {
System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " + System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " +
"had its value declared as " + value + " twice. Continuing."); "had its value declared as " + value + " twice. Continuing.");
duplicateDefCount++;
} }
} }
} }
entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride);
} while (nameAddr != null); } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
throw new RuntimeException("too many duplicate definitions");
}
} }
private void readVMLongConstants() { private void readVMLongConstants() {
...@@ -519,6 +544,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { ...@@ -519,6 +544,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset");
longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride");
if (longConstantEntryArrayStride == 0L) {
throw new RuntimeException("zero stride: cannot read types.");
}
// Fetch the address of the VMLongConstantEntry* // Fetch the address of the VMLongConstantEntry*
Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); Address entryAddr = lookupInProcess("gHotSpotVMLongConstants");
// Dereference this once to get the pointer to the first VMLongConstantEntry // Dereference this once to get the pointer to the first VMLongConstantEntry
...@@ -548,12 +577,17 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { ...@@ -548,12 +577,17 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
} else { } else {
System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " +
"had its value declared as " + value + " twice. Continuing."); "had its value declared as " + value + " twice. Continuing.");
duplicateDefCount++;
} }
} }
} }
entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride);
} while (nameAddr != null); } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
throw new RuntimeException("too many duplicate definitions.");
}
} }
private BasicType lookupOrFail(String typeName) { private BasicType lookupOrFail(String typeName) {
...@@ -740,9 +774,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { ...@@ -740,9 +774,10 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
} }
if (!typeNameIsPointerType(typeName)) { if (!typeNameIsPointerType(typeName)) {
System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
"had its size declared as " + size + " twice. Continuing."); "had its size declared as " + size + " twice. Continuing.");
} duplicateDefCount++;
}
} }
} }
......
...@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2015 ...@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2015
HS_MAJOR_VER=25 HS_MAJOR_VER=25
HS_MINOR_VER=60 HS_MINOR_VER=60
HS_BUILD_NUMBER=06 HS_BUILD_NUMBER=07
JDK_MAJOR_VER=1 JDK_MAJOR_VER=1
JDK_MINOR_VER=8 JDK_MINOR_VER=8
......
/* /*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -41,7 +41,9 @@ ...@@ -41,7 +41,9 @@
* JNI conversion, which should be sorted out later. * JNI conversion, which should be sorted out later.
*/ */
#define __USE_LEGACY_PROTOTYPES__
#include <dirent.h> /* For DIR */ #include <dirent.h> /* For DIR */
#undef __USE_LEGACY_PROTOTYPES__
#include <sys/param.h> /* For MAXPATHLEN */ #include <sys/param.h> /* For MAXPATHLEN */
#include <sys/socket.h> /* For socklen_t */ #include <sys/socket.h> /* For socklen_t */
#include <unistd.h> /* For F_OK, R_OK, W_OK */ #include <unistd.h> /* For F_OK, R_OK, W_OK */
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#define TRACE_BCEA(level, code) #define TRACE_BCEA(level, code)
#endif #endif
// Maintain a map of which aguments a local variable or // Maintain a map of which arguments a local variable or
// stack slot may contain. In addition to tracking // stack slot may contain. In addition to tracking
// arguments, it tracks two special values, "allocated" // arguments, it tracks two special values, "allocated"
// which represents any object allocated in the current // which represents any object allocated in the current
...@@ -318,14 +318,16 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* ...@@ -318,14 +318,16 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
bool must_record_dependencies = false; bool must_record_dependencies = false;
for (i = arg_size - 1; i >= 0; i--) { for (i = arg_size - 1; i >= 0; i--) {
ArgumentMap arg = state.raw_pop(); ArgumentMap arg = state.raw_pop();
if (!is_argument(arg)) // Check if callee arg is a caller arg or an allocated object
bool allocated = arg.contains_allocated();
if (!(is_argument(arg) || allocated))
continue; continue;
for (int j = 0; j < _arg_size; j++) { for (int j = 0; j < _arg_size; j++) {
if (arg.contains(j)) { if (arg.contains(j)) {
_arg_modified[j] |= analyzer._arg_modified[i]; _arg_modified[j] |= analyzer._arg_modified[i];
} }
} }
if (!is_arg_stack(arg)) { if (!(is_arg_stack(arg) || allocated)) {
// arguments have already been recognized as escaping // arguments have already been recognized as escaping
} else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) { } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) {
set_method_escape(arg); set_method_escape(arg);
......
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -235,7 +235,7 @@ protected: ...@@ -235,7 +235,7 @@ protected:
* @return the size of the user data. * @return the size of the user data.
*/ */
size_t get_user_size() const { size_t get_user_size() const {
assert(_base_addr, "Not wrapping any memory"); assert(_base_addr != NULL, "Not wrapping any memory");
return get_head_guard()->get_user_size(); return get_head_guard()->get_user_size();
} }
...@@ -245,7 +245,7 @@ protected: ...@@ -245,7 +245,7 @@ protected:
* @return the user data pointer. * @return the user data pointer.
*/ */
u_char* get_user_ptr() const { u_char* get_user_ptr() const {
assert(_base_addr, "Not wrapping any memory"); assert(_base_addr != NULL, "Not wrapping any memory");
return _base_addr + sizeof(GuardHeader); return _base_addr + sizeof(GuardHeader);
} }
...@@ -281,7 +281,7 @@ protected: ...@@ -281,7 +281,7 @@ protected:
memset(get_user_ptr(), ch, get_user_size()); memset(get_user_ptr(), ch, get_user_size());
} }
public: public:
/** /**
* Return the total size required for wrapping the given user size. * Return the total size required for wrapping the given user size.
* *
......
此差异已折叠。
/* /*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -296,6 +296,7 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread) { ...@@ -296,6 +296,7 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread) {
block->_top = 0; block->_top = 0;
block->_next = NULL; block->_next = NULL;
block->_pop_frame_link = NULL; block->_pop_frame_link = NULL;
block->_planned_capacity = block_size_in_oops;
// _last, _free_list & _allocate_before_rebuild initialized in allocate_handle // _last, _free_list & _allocate_before_rebuild initialized in allocate_handle
debug_only(block->_last = NULL); debug_only(block->_last = NULL);
debug_only(block->_free_list = NULL); debug_only(block->_free_list = NULL);
...@@ -529,6 +530,12 @@ int JNIHandleBlock::length() const { ...@@ -529,6 +530,12 @@ int JNIHandleBlock::length() const {
return result; return result;
} }
const size_t JNIHandleBlock::get_number_of_live_handles() {
CountHandleClosure counter;
oops_do(&counter);
return counter.count();
}
// This method is not thread-safe, i.e., must be called whule holding a lock on the // This method is not thread-safe, i.e., must be called whule holding a lock on the
// structure. // structure.
long JNIHandleBlock::memory_usage() const { long JNIHandleBlock::memory_usage() const {
......
/* /*
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -112,6 +112,9 @@ class JNIHandleBlock : public CHeapObj<mtInternal> { ...@@ -112,6 +112,9 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
oop* _free_list; // Handle free list oop* _free_list; // Handle free list
int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
// Check JNI, "planned capacity" for current frame (or push/ensure)
size_t _planned_capacity;
#ifndef PRODUCT #ifndef PRODUCT
JNIHandleBlock* _block_list_link; // Link for list below JNIHandleBlock* _block_list_link; // Link for list below
static JNIHandleBlock* _block_list; // List of all allocated blocks (for debugging only) static JNIHandleBlock* _block_list; // List of all allocated blocks (for debugging only)
...@@ -152,6 +155,11 @@ class JNIHandleBlock : public CHeapObj<mtInternal> { ...@@ -152,6 +155,11 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
// Traversal of weak handles. Unreachable oops are cleared. // Traversal of weak handles. Unreachable oops are cleared.
void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f); void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
// Checked JNI support
void set_planned_capacity(size_t planned_capacity) { _planned_capacity = planned_capacity; }
const size_t get_planned_capacity() { return _planned_capacity; }
const size_t get_number_of_live_handles();
// Debugging // Debugging
bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle
bool contains(jobject handle) const; // Does this block contain handle bool contains(jobject handle) const; // Does this block contain handle
......
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1465,6 +1465,7 @@ void JavaThread::initialize() { ...@@ -1465,6 +1465,7 @@ void JavaThread::initialize() {
_thread_stat = new ThreadStatistics(); _thread_stat = new ThreadStatistics();
_blocked_on_compilation = false; _blocked_on_compilation = false;
_jni_active_critical = 0; _jni_active_critical = 0;
_pending_jni_exception_check_fn = NULL;
_do_not_unlock_if_synchronized = false; _do_not_unlock_if_synchronized = false;
_cached_monitor_info = NULL; _cached_monitor_info = NULL;
_parker = Parker::Allocate(this) ; _parker = Parker::Allocate(this) ;
......
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -926,6 +926,9 @@ class JavaThread: public Thread { ...@@ -926,6 +926,9 @@ class JavaThread: public Thread {
// support for JNI critical regions // support for JNI critical regions
jint _jni_active_critical; // count of entries into JNI critical region jint _jni_active_critical; // count of entries into JNI critical region
// Checked JNI: function name requires exception check
char* _pending_jni_exception_check_fn;
// For deadlock detection. // For deadlock detection.
int _depth_first_number; int _depth_first_number;
...@@ -1408,6 +1411,12 @@ class JavaThread: public Thread { ...@@ -1408,6 +1411,12 @@ class JavaThread: public Thread {
assert(_jni_active_critical >= 0, assert(_jni_active_critical >= 0,
"JNI critical nesting problem?"); } "JNI critical nesting problem?"); }
// Checked JNI, is the programmer required to check for exceptions, specify which function name
bool is_pending_jni_exception_check() const { return _pending_jni_exception_check_fn != NULL; }
void clear_pending_jni_exception_check() { _pending_jni_exception_check_fn = NULL; }
const char* get_pending_jni_exception_check() const { return _pending_jni_exception_check_fn; }
void set_pending_jni_exception_check(const char* fn_name) { _pending_jni_exception_check_fn = (char*) fn_name; }
// For deadlock detection // For deadlock detection
int depth_first_number() { return _depth_first_number; } int depth_first_number() { return _depth_first_number; }
void set_depth_first_number(int dfn) { _depth_first_number = dfn; } void set_depth_first_number(int dfn) { _depth_first_number = dfn; }
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -33,7 +33,9 @@ ...@@ -33,7 +33,9 @@
# include <ctype.h> # include <ctype.h>
#define __USE_LEGACY_PROTOTYPES__
# include <dirent.h> # include <dirent.h>
#undef __USE_LEGACY_PROTOTYPES__
# include <string.h> # include <string.h>
# include <strings.h> // for bsd'isms # include <strings.h> // for bsd'isms
# include <stdarg.h> # include <stdarg.h>
......
/*
* Copyright (c) 2015, 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
* @bug 8073956
* @summary Tests C2 EA with allocated object escaping through a call.
* @run main/othervm -XX:CompileCommand=dontinline,TestEscapeThroughInvoke::create TestEscapeThroughInvoke
*/
public class TestEscapeThroughInvoke {
private A a;
public static void main(String[] args) {
TestEscapeThroughInvoke test = new TestEscapeThroughInvoke();
test.a = new A(42);
// Make sure run gets compiled by C2
for (int i = 0; i < 100_000; ++i) {
test.run();
}
}
private void run() {
// Allocate something to trigger EA
new Object();
// Create a new escaping instance of A and
// verify that it is always equal to 'a.saved'.
A escapingA = create(42);
a.check(escapingA);
}
// Create and return a new instance of A that escaped through 'A::saveInto'.
// The 'dummy' parameters are needed to avoid EA skipping the methods.
private A create(Integer dummy) {
A result = new A(dummy);
result.saveInto(a, dummy); // result escapes into 'a' here
return result;
}
}
class A {
private A saved;
public A(Integer dummy) { }
public void saveInto(A other, Integer dummy) {
other.saved = this;
}
public void check(A other) {
if (this.saved != other) {
throw new RuntimeException("TEST FAILED: Objects not equal.");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册