提交 5e752fcd 编写于 作者: A amurillo

Merge

......@@ -557,3 +557,4 @@ eb16b24e2eba9bdf04a9b377bebc2db9f713ff5e jdk8u40-b15
3a8a0fd171c5876023112941b1c7254262f9adfc hs25.40-b19
aa2442f89230dc46147c721812f3b3bd4c612e83 hs25.40-b20
5ea68fb91139081304357f9b937f32c5fdfeca6d jdk8u40-b16
6bf89bfe8185747a57193efb6cec1f17ccc80414 hs25.40-b21
......@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014
HS_MAJOR_VER=25
HS_MINOR_VER=40
HS_BUILD_NUMBER=20
HS_BUILD_NUMBER=21
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
......
......@@ -68,7 +68,10 @@
// ciMethod::ciMethod
//
// Loaded method.
ciMethod::ciMethod(methodHandle h_m) : ciMetadata(h_m()) {
ciMethod::ciMethod(methodHandle h_m, ciInstanceKlass* holder) :
ciMetadata(h_m()),
_holder(holder)
{
assert(h_m() != NULL, "no null method");
// These fields are always filled in in loaded methods.
......@@ -124,7 +127,6 @@ ciMethod::ciMethod(methodHandle h_m) : ciMetadata(h_m()) {
// generating _signature may allow GC and therefore move m.
// These fields are always filled in.
_name = env->get_symbol(h_m()->name());
_holder = env->get_instance_klass(h_m()->method_holder());
ciSymbol* sig_symbol = env->get_symbol(h_m()->signature());
constantPoolHandle cpool = h_m()->constants();
_signature = new (env->arena()) ciSignature(_holder, cpool, sig_symbol);
......
......@@ -90,7 +90,7 @@ class ciMethod : public ciMetadata {
BCEscapeAnalyzer* _bcea;
#endif
ciMethod(methodHandle h_m);
ciMethod(methodHandle h_m, ciInstanceKlass* holder);
ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature, ciInstanceKlass* accessor);
Method* get_Method() const {
......
......@@ -239,7 +239,7 @@ void ciObjectFactory::remove_symbols() {
ciObject* ciObjectFactory::get(oop key) {
ASSERT_IN_VM;
assert(key == NULL || Universe::heap()->is_in_reserved(key), "must be");
assert(Universe::heap()->is_in_reserved(key), "must be");
NonPermObject* &bucket = find_non_perm(key);
if (bucket != NULL) {
......@@ -260,10 +260,10 @@ ciObject* ciObjectFactory::get(oop key) {
}
// ------------------------------------------------------------------
// ciObjectFactory::get
// ciObjectFactory::get_metadata
//
// Get the ciObject corresponding to some oop. If the ciObject has
// already been created, it is returned. Otherwise, a new ciObject
// Get the ciMetadata corresponding to some Metadata. If the ciMetadata has
// already been created, it is returned. Otherwise, a new ciMetadata
// is created.
ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
ASSERT_IN_VM;
......@@ -290,9 +290,9 @@ ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
}
#endif
if (!is_found_at(index, key, _ci_metadata)) {
// The ciObject does not yet exist. Create it and insert it
// The ciMetadata does not yet exist. Create it and insert it
// into the cache.
ciMetadata* new_object = create_new_object(key);
ciMetadata* new_object = create_new_metadata(key);
init_ident_of(new_object);
assert(new_object->is_metadata(), "must be");
......@@ -344,15 +344,28 @@ ciObject* ciObjectFactory::create_new_object(oop o) {
}
// ------------------------------------------------------------------
// ciObjectFactory::create_new_object
// ciObjectFactory::create_new_metadata
//
// Create a new ciObject from a Metadata*.
// Create a new ciMetadata from a Metadata*.
//
// Implementation note: this functionality could be virtual behavior
// of the oop itself. For now, we explicitly marshal the object.
ciMetadata* ciObjectFactory::create_new_object(Metadata* o) {
// Implementation note: in order to keep Metadata live, an auxiliary ciObject
// is used, which points to it's holder.
ciMetadata* ciObjectFactory::create_new_metadata(Metadata* o) {
EXCEPTION_CONTEXT;
// Hold metadata from unloading by keeping it's holder alive.
if (_initialized && o->is_klass()) {
Klass* holder = ((Klass*)o);
if (holder->oop_is_instance() && InstanceKlass::cast(holder)->is_anonymous()) {
// Though ciInstanceKlass records class loader oop, it's not enough to keep
// VM anonymous classes alive (loader == NULL). Klass holder should be used instead.
// It is enough to record a ciObject, since cached elements are never removed
// during ciObjectFactory lifetime. ciObjectFactory itself is created for
// every compilation and lives for the whole duration of the compilation.
ciObject* h = get(holder->klass_holder());
}
}
if (o->is_klass()) {
KlassHandle h_k(THREAD, (Klass*)o);
Klass* k = (Klass*)o;
......@@ -365,14 +378,16 @@ ciMetadata* ciObjectFactory::create_new_object(Metadata* o) {
}
} else if (o->is_method()) {
methodHandle h_m(THREAD, (Method*)o);
return new (arena()) ciMethod(h_m);
ciEnv *env = CURRENT_THREAD_ENV;
ciInstanceKlass* holder = env->get_instance_klass(h_m()->method_holder());
return new (arena()) ciMethod(h_m, holder);
} else if (o->is_methodData()) {
// Hold methodHandle alive - might not be necessary ???
methodHandle h_m(THREAD, ((MethodData*)o)->method());
return new (arena()) ciMethodData((MethodData*)o);
}
// The oop is of some type not supported by the compiler interface.
// The Metadata* is of some type not supported by the compiler interface.
ShouldNotReachHere();
return NULL;
}
......@@ -701,7 +716,7 @@ static ciObjectFactory::NonPermObject* emptyBucket = NULL;
// If there is no entry in the cache corresponding to this oop, return
// the null tail of the bucket into which the oop should be inserted.
ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) {
assert(Universe::heap()->is_in_reserved_or_null(key), "must be");
assert(Universe::heap()->is_in_reserved(key), "must be");
ciMetadata* klass = get_metadata(key->klass());
NonPermObject* *bp = &_non_perm_bucket[(unsigned) klass->hash() % NON_PERM_BUCKETS];
for (NonPermObject* p; (p = (*bp)) != NULL; bp = &p->next()) {
......
......@@ -73,7 +73,7 @@ private:
void insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects);
ciObject* create_new_object(oop o);
ciMetadata* create_new_object(Metadata* o);
ciMetadata* create_new_metadata(Metadata* o);
void ensure_metadata_alive(ciMetadata* m);
......
......@@ -35,6 +35,7 @@
#include "interpreter/bytecode.hpp"
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/compile.hpp"
#include "runtime/deoptimization.hpp"
#include "utilities/growableArray.hpp"
......@@ -2646,7 +2647,7 @@ void ciTypeFlow::df_flow_types(Block* start,
assert (!blk->has_pre_order(), "");
blk->set_next_pre_order();
if (_next_pre_order >= MaxNodeLimit / 2) {
if (_next_pre_order >= (int)Compile::current()->max_node_limit() / 2) {
// Too many basic blocks. Bail out.
// This can happen when try/finally constructs are nested to depth N,
// and there is O(2**N) cloning of jsr bodies. See bug 4697245!
......
......@@ -63,6 +63,9 @@ public:
ClassPathEntry* new_entry) {
ClassLoader::add_to_list(new_entry);
}
static void append_boot_classpath(ClassPathEntry* new_entry) {
ClassLoader::add_to_list(new_entry);
}
static void setup_search_paths() {}
static void init_lookup_cache(TRAPS) {}
......
......@@ -879,6 +879,8 @@ class ClassHierarchyWalker {
bool is_witness(Klass* k) {
if (doing_subtype_search()) {
return Dependencies::is_concrete_klass(k);
} else if (!k->oop_is_instance()) {
return false; // no methods to find in an array type
} else {
Method* m = InstanceKlass::cast(k)->find_method(_name, _signature);
if (m == NULL || !Dependencies::is_concrete_method(m)) return false;
......@@ -1085,7 +1087,7 @@ Klass* ClassHierarchyWalker::find_witness_anywhere(Klass* context_type,
Klass* chain; // scratch variable
#define ADD_SUBCLASS_CHAIN(k) { \
assert(chaini < CHAINMAX, "oob"); \
chain = InstanceKlass::cast(k)->subklass(); \
chain = k->subklass(); \
if (chain != NULL) chains[chaini++] = chain; }
// Look for non-abstract subclasses.
......@@ -1096,35 +1098,37 @@ Klass* ClassHierarchyWalker::find_witness_anywhere(Klass* context_type,
// (Their subclasses are additional indirect implementors.
// See InstanceKlass::add_implementor.)
// (Note: nof_implementors is always zero for non-interfaces.)
int nof_impls = InstanceKlass::cast(context_type)->nof_implementors();
if (nof_impls > 1) {
// Avoid this case: *I.m > { A.m, C }; B.m > C
// Here, I.m has 2 concrete implementations, but m appears unique
// as A.m, because the search misses B.m when checking C.
// The inherited method B.m was getting missed by the walker
// when interface 'I' was the starting point.
// %%% Until this is fixed more systematically, bail out.
// (Old CHA had the same limitation.)
return context_type;
}
if (nof_impls > 0) {
Klass* impl = InstanceKlass::cast(context_type)->implementor();
assert(impl != NULL, "just checking");
// If impl is the same as the context_type, then more than one
// implementor has seen. No exact info in this case.
if (impl == context_type) {
return context_type; // report an inexact witness to this sad affair
if (top_level_call) {
int nof_impls = InstanceKlass::cast(context_type)->nof_implementors();
if (nof_impls > 1) {
// Avoid this case: *I.m > { A.m, C }; B.m > C
// Here, I.m has 2 concrete implementations, but m appears unique
// as A.m, because the search misses B.m when checking C.
// The inherited method B.m was getting missed by the walker
// when interface 'I' was the starting point.
// %%% Until this is fixed more systematically, bail out.
// (Old CHA had the same limitation.)
return context_type;
}
if (do_counts)
{ NOT_PRODUCT(deps_find_witness_steps++); }
if (is_participant(impl)) {
if (!participants_hide_witnesses) {
if (nof_impls > 0) {
Klass* impl = InstanceKlass::cast(context_type)->implementor();
assert(impl != NULL, "just checking");
// If impl is the same as the context_type, then more than one
// implementor has seen. No exact info in this case.
if (impl == context_type) {
return context_type; // report an inexact witness to this sad affair
}
if (do_counts)
{ NOT_PRODUCT(deps_find_witness_steps++); }
if (is_participant(impl)) {
if (!participants_hide_witnesses) {
ADD_SUBCLASS_CHAIN(impl);
}
} else if (is_witness(impl) && !ignore_witness(impl)) {
return impl;
} else {
ADD_SUBCLASS_CHAIN(impl);
}
} else if (is_witness(impl) && !ignore_witness(impl)) {
return impl;
} else {
ADD_SUBCLASS_CHAIN(impl);
}
}
......
......@@ -647,7 +647,7 @@
develop(bool, AlwaysIncrementalInline, false, \
"do all inlining incrementally") \
\
product(intx, LiveNodeCountInliningCutoff, 20000, \
product(intx, LiveNodeCountInliningCutoff, 40000, \
"max number of live nodes in a method") \
\
diagnostic(bool, OptimizeExpensiveOps, true, \
......
......@@ -679,7 +679,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_inlining_incrementally(false),
_print_inlining_list(NULL),
_print_inlining_idx(0),
_interpreter_frame_size(0) {
_interpreter_frame_size(0),
_max_node_limit(MaxNodeLimit) {
C = this;
CompileWrapper cw(this);
......@@ -990,7 +991,8 @@ Compile::Compile( ciEnv* ci_env,
_print_inlining_list(NULL),
_print_inlining_idx(0),
_allowed_reasons(0),
_interpreter_frame_size(0) {
_interpreter_frame_size(0),
_max_node_limit(MaxNodeLimit) {
C = this;
#ifndef PRODUCT
......@@ -1100,6 +1102,7 @@ void Compile::Init(int aliaslevel) {
set_do_count_invocations(false);
set_do_method_data_update(false);
set_rtm_state(NoRTM); // No RTM lock eliding by default
method_has_option_value("MaxNodeLimit", _max_node_limit);
#if INCLUDE_RTM_OPT
if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
int rtm_state = method()->method_data()->rtm_state();
......
......@@ -290,6 +290,7 @@ class Compile : public Phase {
int _freq_inline_size; // Max hot method inline size for this compilation
int _fixed_slots; // count of frame slots not allocated by the register
// allocator i.e. locks, original deopt pc, etc.
uintx _max_node_limit; // Max unique node count during a single compilation.
// For deopt
int _orig_pc_slot;
int _orig_pc_slot_offset_in_bytes;
......@@ -594,6 +595,9 @@ class Compile : public Phase {
void set_rtm_state(RTMState s) { _rtm_state = s; }
bool use_rtm() const { return (_rtm_state & NoRTM) == 0; }
bool profile_rtm() const { return _rtm_state == ProfileRTM; }
uint max_node_limit() const { return (uint)_max_node_limit; }
void set_max_node_limit(uint n) { _max_node_limit = n; }
// check the CompilerOracle for special behaviours for this compile
bool method_has_option(const char * option) {
return method() != NULL && method()->has_option(option);
......@@ -723,7 +727,7 @@ class Compile : public Phase {
record_method_not_compilable(reason, true);
}
bool check_node_count(uint margin, const char* reason) {
if (live_nodes() + margin > (uint)MaxNodeLimit) {
if (live_nodes() + margin > max_node_limit()) {
record_method_not_compilable(reason);
return true;
} else {
......
......@@ -410,6 +410,11 @@ void Parse::do_call() {
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
assert(declared_signature != NULL, "cannot be null");
// Bump max node limit for JSR292 users
if (bc() == Bytecodes::_invokedynamic || orig_callee->is_method_handle_intrinsic()) {
C->set_max_node_limit(3*MaxNodeLimit);
}
// uncommon-trap when callee is unloaded, uninitialized or will not link
// bailout when too many arguments for register representation
if (!will_link || can_not_compile_call_site(orig_callee, klass)) {
......
......@@ -2409,7 +2409,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro
}
}
}
if ((int) (C->live_nodes() + 2*NodeLimitFudgeFactor) > MaxNodeLimit) {
if (C->live_nodes() + 2*NodeLimitFudgeFactor > C->max_node_limit()) {
if (C->do_escape_analysis() == true && !C->failing()) {
// Retry compilation without escape analysis.
// If this is the first failure, the sentinel string will "stick"
......
......@@ -269,10 +269,9 @@ void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) {
bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const {
Node *test = ((IdealLoopTree*)this)->tail();
int body_size = ((IdealLoopTree*)this)->_body.size();
int live_node_count = phase->C->live_nodes();
// Peeling does loop cloning which can result in O(N^2) node construction
if( body_size > 255 /* Prevent overflow for large body_size */
|| (body_size * body_size + live_node_count > MaxNodeLimit) ) {
|| (body_size * body_size + phase->C->live_nodes()) > phase->C->max_node_limit() ) {
return false; // too large to safely clone
}
while( test != _head ) { // Scan till run off top of loop
......@@ -601,7 +600,7 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
return false;
if (new_body_size > unroll_limit ||
// Unrolling can result in a large amount of node construction
new_body_size >= MaxNodeLimit - (uint) phase->C->live_nodes()) {
new_body_size >= phase->C->max_node_limit() - phase->C->live_nodes()) {
return false;
}
......@@ -2287,8 +2286,8 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_
// Skip next optimizations if running low on nodes. Note that
// policy_unswitching and policy_maximally_unroll have this check.
uint nodes_left = MaxNodeLimit - (uint) phase->C->live_nodes();
if ((2 * _body.size()) > nodes_left) {
int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
if ((int)(2 * _body.size()) > nodes_left) {
return true;
}
......
......@@ -59,8 +59,8 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
if (!_head->is_Loop()) {
return false;
}
uint nodes_left = MaxNodeLimit - phase->C->live_nodes();
if (2 * _body.size() > nodes_left) {
int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
if ((int)(2 * _body.size()) > nodes_left) {
return false; // Too speculative if running low on nodes.
}
LoopNode* head = _head->as_Loop();
......
......@@ -734,7 +734,7 @@ static bool merge_point_too_heavy(Compile* C, Node* region) {
for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
weight += region->fast_out(i)->outcnt();
}
int nodes_left = MaxNodeLimit - C->live_nodes();
int nodes_left = C->max_node_limit() - C->live_nodes();
if (weight * 8 > nodes_left) {
#ifndef PRODUCT
if (PrintOpto)
......
......@@ -1255,6 +1255,16 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) {
result = new (phase->C) ConvI2LNode(phase->transform(result));
}
#endif
// Boxing/unboxing can be done from signed & unsigned loads (e.g. LoadUB -> ... -> LoadB pair).
// Need to preserve unboxing load type if it is unsigned.
switch(this->Opcode()) {
case Op_LoadUB:
result = new (phase->C) AndINode(phase->transform(result), phase->intcon(0xFF));
break;
case Op_LoadUS:
result = new (phase->C) AndINode(phase->transform(result), phase->intcon(0xFFFF));
break;
}
return result;
}
}
......
......@@ -69,7 +69,7 @@ void Node::verify_construction() {
Compile::set_debug_idx(new_debug_idx);
set_debug_idx( new_debug_idx );
assert(Compile::current()->unique() < (INT_MAX - 1), "Node limit exceeded INT_MAX");
assert(Compile::current()->live_nodes() < (uint)MaxNodeLimit, "Live Node limit exceeded limit");
assert(Compile::current()->live_nodes() < Compile::current()->max_node_limit(), "Live Node limit exceeded limit");
if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) {
tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx);
BREAKPOINT;
......@@ -326,7 +326,7 @@ inline int Node::Init(int req, Compile* C) {
Node::Node(uint req)
: _idx(IDX_INIT(req))
{
assert( req < (uint)(MaxNodeLimit - NodeLimitFudgeFactor), "Input limit exceeded" );
assert( req < Compile::current()->max_node_limit() - NodeLimitFudgeFactor, "Input limit exceeded" );
debug_only( verify_construction() );
NOT_PRODUCT(nodes_created++);
if (req == 0) {
......
......@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "interpreter/bytecodeStream.hpp"
......@@ -475,7 +476,7 @@ JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) {
if (TraceClassLoading) {
tty->print_cr("[Opened %s]", zip_entry->name());
}
ClassLoader::add_to_list(zip_entry);
ClassLoaderExt::append_boot_classpath(zip_entry);
return JVMTI_ERROR_NONE;
} else {
return JVMTI_ERROR_WRONG_PHASE;
......
......@@ -56,6 +56,7 @@
#endif // INCLUDE_NMT
#include "compiler/compileBroker.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "runtime/compilationPolicy.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
......@@ -126,6 +127,29 @@ WB_ENTRY(jintArray, WB_GetLookupCacheMatches(JNIEnv* env, jobject o, jobject loa
return result;
WB_END
WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
#if INCLUDE_JVMTI
ResourceMark rm;
const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
assert(err == JVMTI_ERROR_NONE, "must not fail");
#endif
}
WB_END
WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
#if INCLUDE_JVMTI
ResourceMark rm;
const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
assert(err == JVMTI_ERROR_NONE, "must not fail");
#endif
}
WB_END
WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
return (jlong)Arguments::max_heap_for_compressed_oops();
}
......@@ -958,6 +982,10 @@ static JNINativeMethod methods[] = {
CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
(void*) &WB_ParseCommandLine
},
{CC"addToBootstrapClassLoaderSearch", CC"(Ljava/lang/String;)V",
(void*)&WB_AddToBootstrapClassLoaderSearch},
{CC"addToSystemClassLoaderSearch", CC"(Ljava/lang/String;)V",
(void*)&WB_AddToSystemClassLoaderSearch},
{CC"getCompressedOopsMaxHeapSize", CC"()J",
(void*)&WB_GetCompressedOopsMaxHeapSize},
{CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes },
......
/*
* Copyright (c) 2014, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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
* @library /testlibrary
* @run main/othervm -Xbatch -XX:+EliminateAutoBox
* -XX:CompileOnly=::valueOf,::byteValue,::shortValue,::testUnsignedByte,::testUnsignedShort
* UnsignedLoads
*/
import static com.oracle.java.testlibrary.Asserts.assertEQ;
public class UnsignedLoads {
public static int testUnsignedByte() {
byte[] bytes = new byte[] {-1};
int res = 0;
for (int i = 0; i < 100000; i++) {
for (Byte b : bytes) {
res = b & 0xff;
}
}
return res;
}
public static int testUnsignedShort() {
int res = 0;
short[] shorts = new short[] {-1};
for (int i = 0; i < 100000; i++) {
for (Short s : shorts) {
res = s & 0xffff;
}
}
return res;
}
public static void main(String[] args) {
assertEQ(testUnsignedByte(), 255);
assertEQ(testUnsignedShort(), 65535);
System.out.println("TEST PASSED");
}
}
/*
* Copyright (c) 2014, 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.
*/
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import com.oracle.java.testlibrary.*;
/*
* @test
* @bug 8050079
* @summary Compiles a monomorphic call to finalizeObject() on a modified java.lang.Object to test C1 CHA.
* @library /testlibrary
* @compile -XDignore.symbol.file java/lang/Object.java TestMonomorphicObjectCall.java
* @run main TestMonomorphicObjectCall
*/
public class TestMonomorphicObjectCall {
final static String testClasses = System.getProperty("test.classes") + File.separator;
private static void callFinalize(Object object) throws Throwable {
// Call modified version of java.lang.Object::finalize() that is
// not overridden by any subclass. C1 CHA should mark the call site
// as monomorphic and inline the method.
object.finalizeObject();
}
public static void main(String[] args) throws Throwable {
if (args.length == 0) {
// Execute new instance with modified java.lang.Object
executeTestJvm();
} else {
// Trigger compilation of 'callFinalize'
callFinalize(new Object());
}
}
public static void executeTestJvm() throws Throwable {
// Execute test with modified version of java.lang.Object
// in -Xbootclasspath.
String[] vmOpts = new String[] {
"-Xbootclasspath/p:" + testClasses,
"-Xcomp",
"-XX:-VerifyDependencies",
"-XX:CompileOnly=TestMonomorphicObjectCall::callFinalize",
"-XX:CompileOnly=Object::finalizeObject",
"-XX:TieredStopAtLevel=1",
TestMonomorphicObjectCall.class.getName(),
"true"};
OutputAnalyzer output = ProcessTools.executeTestJvm(vmOpts);
output.shouldHaveExitValue(0);
}
}
/*
* Copyright (c) 1994, 2014, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package java.lang;
/**
* Slightly modified version of java.lang.Object that replaces
* finalize() by finalizeObject() to avoid overriding in subclasses.
*/
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
timeout++;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
/**
* Replaces original finalize() method and is therefore not
* overridden by any subclasses of Object.
* @throws Throwable
*/
// protected void finalize() throws Throwable { }
public void finalizeObject() throws Throwable { }
}
......@@ -90,6 +90,10 @@ public class WhiteBox {
public native URL[] getLookupCacheURLs(ClassLoader loader);
public native int[] getLookupCacheMatches(ClassLoader loader, String name);
// JVMTI
public native void addToBootstrapClassLoaderSearch(String segment);
public native void addToSystemClassLoaderSearch(String segment);
// G1
public native boolean g1InConcurrentMark();
public native boolean g1IsHumongous(Object o);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册