Merge
This commit is contained in:
commit
85a47f34c6
@ -762,7 +762,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, const MachNode* n, int primary, int te
|
||||
case Assembler::stdf_op3: st_op = Op_StoreD; break;
|
||||
|
||||
case Assembler::ldsb_op3: ld_op = Op_LoadB; break;
|
||||
case Assembler::lduh_op3: ld_op = Op_LoadC; break;
|
||||
case Assembler::lduh_op3: ld_op = Op_LoadUS; break;
|
||||
case Assembler::ldsh_op3: ld_op = Op_LoadS; break;
|
||||
case Assembler::ldx_op3: // may become LoadP or stay LoadI
|
||||
case Assembler::ldsw_op3: // may become LoadP or stay LoadI
|
||||
@ -3869,6 +3869,8 @@ operand regD() %{
|
||||
constraint(ALLOC_IN_RC(dflt_reg));
|
||||
match(RegD);
|
||||
|
||||
match(regD_low);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
@ -3883,7 +3885,7 @@ operand regF() %{
|
||||
|
||||
operand regD_low() %{
|
||||
constraint(ALLOC_IN_RC(dflt_low_reg));
|
||||
match(RegD);
|
||||
match(regD);
|
||||
|
||||
format %{ %}
|
||||
interface(REG_INTER);
|
||||
@ -5314,9 +5316,9 @@ instruct loadUBL(iRegL dst, memory mem, immL_FF bytemask) %{
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Char (16bit UNsigned) into a Long Register
|
||||
instruct loadUCL(iRegL dst, memory mem, immL_FFFF bytemask) %{
|
||||
match(Set dst (AndL (ConvI2L (LoadC mem)) bytemask));
|
||||
// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
|
||||
instruct loadUS2L(iRegL dst, memory mem, immL_FFFF bytemask) %{
|
||||
match(Set dst (AndL (ConvI2L (LoadUS mem)) bytemask));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
@ -5326,9 +5328,9 @@ instruct loadUCL(iRegL dst, memory mem, immL_FFFF bytemask) %{
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Char (16bit unsigned)
|
||||
instruct loadC(iRegI dst, memory mem) %{
|
||||
match(Set dst (LoadC mem));
|
||||
// Load Unsigned Short/Char (16bit unsigned)
|
||||
instruct loadUS(iRegI dst, memory mem) %{
|
||||
match(Set dst (LoadUS mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
|
@ -6413,9 +6413,9 @@ instruct loadUB(xRegI dst, memory mem, immI_255 bytemask) %{
|
||||
ins_pipe( ialu_reg_mem );
|
||||
%}
|
||||
|
||||
// Load Char (16bit unsigned)
|
||||
instruct loadC(eRegI dst, memory mem) %{
|
||||
match(Set dst (LoadC mem));
|
||||
// Load Unsigned Short/Char (16bit unsigned)
|
||||
instruct loadUS(eRegI dst, memory mem) %{
|
||||
match(Set dst (LoadUS mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVZX $dst,$mem" %}
|
||||
|
@ -6096,25 +6096,25 @@ instruct loadS(rRegI dst, memory mem)
|
||||
// ins_pipe(ialu_reg_mem);
|
||||
// %}
|
||||
|
||||
// Load Char (16 bit UNsigned)
|
||||
instruct loadC(rRegI dst, memory mem)
|
||||
// Load Unsigned Short/Char (16 bit UNsigned)
|
||||
instruct loadUS(rRegI dst, memory mem)
|
||||
%{
|
||||
match(Set dst (LoadC mem));
|
||||
match(Set dst (LoadUS mem));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movzwl $dst, $mem\t# char" %}
|
||||
format %{ "movzwl $dst, $mem\t# ushort/char" %}
|
||||
opcode(0x0F, 0xB7);
|
||||
ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Char (16 bit UNsigned) into long
|
||||
// instruct loadC2L(rRegL dst, memory mem)
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) into long
|
||||
// instruct loadUS2L(rRegL dst, memory mem)
|
||||
// %{
|
||||
// match(Set dst (ConvI2L (LoadC mem)));
|
||||
// match(Set dst (ConvI2L (LoadUS mem)));
|
||||
|
||||
// ins_cost(125);
|
||||
// format %{ "movzwl $dst, $mem\t# char -> long" %}
|
||||
// format %{ "movzwl $dst, $mem\t# ushort/char -> long" %}
|
||||
// opcode(0x0F, 0xB7);
|
||||
// ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
|
||||
// ins_pipe(ialu_reg_mem);
|
||||
@ -9490,14 +9490,14 @@ instruct andL_rReg_imm255(rRegL dst, immL_255 src)
|
||||
%{
|
||||
match(Set dst (AndL dst src));
|
||||
|
||||
format %{ "movzbq $dst, $src\t# long & 0xFF" %}
|
||||
format %{ "movzbq $dst, $dst\t# long & 0xFF" %}
|
||||
opcode(0x0F, 0xB6);
|
||||
ins_encode(REX_reg_reg_wide(dst, dst), OpcP, OpcS, reg_reg(dst, dst));
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
// And Register with Immediate 65535
|
||||
instruct andL_rReg_imm65535(rRegI dst, immL_65535 src)
|
||||
instruct andL_rReg_imm65535(rRegL dst, immL_65535 src)
|
||||
%{
|
||||
match(Set dst (AndL dst src));
|
||||
|
||||
|
@ -316,9 +316,12 @@ int cmpstr(const void *k1, const void *k2) {
|
||||
return strcmp((const char *)k1,(const char *)k2);
|
||||
}
|
||||
|
||||
// Slimey cheap key comparator.
|
||||
// Cheap key comparator.
|
||||
int cmpkey(const void *key1, const void *key2) {
|
||||
return (int)((intptr_t)key1 - (intptr_t)key2);
|
||||
if (key1 == key2) return 0;
|
||||
intptr_t delta = (intptr_t)key1 - (intptr_t)key2;
|
||||
if (delta > 0) return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -248,7 +248,7 @@ Form::DataType Form::ideal_to_Reg_type(const char *name) const {
|
||||
// True if 'opType', an ideal name, loads or stores.
|
||||
Form::DataType Form::is_load_from_memory(const char *opType) const {
|
||||
if( strcmp(opType,"LoadB")==0 ) return Form::idealB;
|
||||
if( strcmp(opType,"LoadC")==0 ) return Form::idealC;
|
||||
if( strcmp(opType,"LoadUS")==0 ) return Form::idealC;
|
||||
if( strcmp(opType,"LoadD")==0 ) return Form::idealD;
|
||||
if( strcmp(opType,"LoadD_unaligned")==0 ) return Form::idealD;
|
||||
if( strcmp(opType,"LoadF")==0 ) return Form::idealF;
|
||||
|
@ -3314,7 +3314,7 @@ int MatchNode::needs_ideal_memory_edge(FormDict &globals) const {
|
||||
"StoreI","StoreL","StoreP","StoreN","StoreD","StoreF" ,
|
||||
"StoreB","StoreC","Store" ,"StoreFP",
|
||||
"LoadI" ,"LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" ,
|
||||
"LoadB" ,"LoadC" ,"LoadS" ,"Load" ,
|
||||
"LoadB" ,"LoadUS" ,"LoadS" ,"Load" ,
|
||||
"Store4I","Store2I","Store2L","Store2D","Store4F","Store2F","Store16B",
|
||||
"Store8B","Store4B","Store8C","Store4C","Store2C",
|
||||
"Load4I" ,"Load2I" ,"Load2L" ,"Load2D" ,"Load4F" ,"Load2F" ,"Load16B" ,
|
||||
|
@ -123,6 +123,10 @@ CodeBuffer::~CodeBuffer() {
|
||||
// addresses constructed before expansions will not be confused.
|
||||
cb->free_blob();
|
||||
}
|
||||
|
||||
// free any overflow storage
|
||||
delete _overflow_arena;
|
||||
|
||||
#ifdef ASSERT
|
||||
Copy::fill_to_bytes(this, sizeof(*this), badResourceValue);
|
||||
#endif
|
||||
|
@ -846,6 +846,12 @@ klassOop SystemDictionary::find(symbolHandle class_name,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
|
||||
// UseNewReflection
|
||||
// The result of this call should be consistent with the result
|
||||
// of the call to resolve_instance_class_or_null().
|
||||
// See evaluation 6790209 and 4474172 for more details.
|
||||
class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
|
||||
|
||||
unsigned int d_hash = dictionary()->compute_hash(class_name, class_loader);
|
||||
int d_index = dictionary()->hash_to_index(d_hash);
|
||||
|
||||
|
@ -346,9 +346,12 @@ int32 cmpstr(const void *k1, const void *k2) {
|
||||
return strcmp((const char *)k1,(const char *)k2);
|
||||
}
|
||||
|
||||
// Slimey cheap key comparator.
|
||||
// Cheap key comparator.
|
||||
int32 cmpkey(const void *key1, const void *key2) {
|
||||
return (int32)((intptr_t)key1 - (intptr_t)key2);
|
||||
if (key1 == key2) return 0;
|
||||
intptr_t delta = (intptr_t)key1 - (intptr_t)key2;
|
||||
if (delta > 0) return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -217,15 +217,28 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
|
||||
(HeapWord*) align_size_up((uintptr_t)new_end, _page_size);
|
||||
assert(new_end_aligned >= (HeapWord*) new_end,
|
||||
"align up, but less");
|
||||
// Check the other regions (excludes "ind") to ensure that
|
||||
// the new_end_aligned does not intrude onto the committed
|
||||
// space of another region.
|
||||
int ri = 0;
|
||||
for (ri = 0; ri < _cur_covered_regions; ri++) {
|
||||
if (ri != ind) {
|
||||
if (_committed[ri].contains(new_end_aligned)) {
|
||||
assert((new_end_aligned >= _committed[ri].start()) &&
|
||||
(_committed[ri].start() > _committed[ind].start()),
|
||||
// The prior check included in the assert
|
||||
// (new_end_aligned >= _committed[ri].start())
|
||||
// is redundant with the "contains" test.
|
||||
// Any region containing the new end
|
||||
// should start at or beyond the region found (ind)
|
||||
// for the new end (committed regions are not expected to
|
||||
// be proper subsets of other committed regions).
|
||||
assert(_committed[ri].start() >= _committed[ind].start(),
|
||||
"New end of committed region is inconsistent");
|
||||
new_end_aligned = _committed[ri].start();
|
||||
assert(new_end_aligned > _committed[ind].start(),
|
||||
// new_end_aligned can be equal to the start of its
|
||||
// committed region (i.e., of "ind") if a second
|
||||
// region following "ind" also start at the same location
|
||||
// as "ind".
|
||||
assert(new_end_aligned >= _committed[ind].start(),
|
||||
"New end of committed region is before start");
|
||||
debug_only(collided = true;)
|
||||
// Should only collide with 1 region
|
||||
|
@ -880,6 +880,7 @@ void PhaseCFG::dump_headers() {
|
||||
}
|
||||
|
||||
void PhaseCFG::verify( ) const {
|
||||
#ifdef ASSERT
|
||||
// Verify sane CFG
|
||||
for( uint i = 0; i < _num_blocks; i++ ) {
|
||||
Block *b = _blocks[i];
|
||||
@ -894,10 +895,20 @@ void PhaseCFG::verify( ) const {
|
||||
"CreateEx must be first instruction in block" );
|
||||
}
|
||||
for( uint k = 0; k < n->req(); k++ ) {
|
||||
Node *use = n->in(k);
|
||||
if( use && use != n ) {
|
||||
assert( _bbs[use->_idx] || use->is_Con(),
|
||||
Node *def = n->in(k);
|
||||
if( def && def != n ) {
|
||||
assert( _bbs[def->_idx] || def->is_Con(),
|
||||
"must have block; constants for debug info ok" );
|
||||
// Verify that instructions in the block is in correct order.
|
||||
// Uses must follow their definition if they are at the same block.
|
||||
// Mostly done to check that MachSpillCopy nodes are placed correctly
|
||||
// when CreateEx node is moved in build_ifg_physical().
|
||||
if( _bbs[def->_idx] == b &&
|
||||
!(b->head()->is_Loop() && n->is_Phi()) &&
|
||||
// See (+++) comment in reg_split.cpp
|
||||
!(n->jvms() != NULL && n->jvms()->is_monitor_use(k)) ) {
|
||||
assert( b->find_node(def) < j, "uses must follow definitions" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -914,6 +925,7 @@ void PhaseCFG::verify( ) const {
|
||||
assert( b->_num_succs == 2, "Conditional branch must have two targets");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -191,6 +191,9 @@
|
||||
notproduct(bool, VerifyHashTableKeys, true, \
|
||||
"Verify the immutability of keys in the VN hash tables") \
|
||||
\
|
||||
notproduct(bool, VerifyRegisterAllocator , false, \
|
||||
"Verify Register Allocator") \
|
||||
\
|
||||
develop_pd(intx, FLOATPRESSURE, \
|
||||
"Number of float LRG's that constitute high register pressure") \
|
||||
\
|
||||
|
@ -858,12 +858,18 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
|
||||
// convert the one to the other.
|
||||
const TypePtr* ttp = _type->make_ptr();
|
||||
const TypeInstPtr* ttip = (ttp != NULL) ? ttp->isa_instptr() : NULL;
|
||||
const TypeKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_klassptr() : NULL;
|
||||
bool is_intf = false;
|
||||
if (ttip != NULL) {
|
||||
ciKlass* k = ttip->klass();
|
||||
if (k->is_loaded() && k->is_interface())
|
||||
is_intf = true;
|
||||
}
|
||||
if (ttkp != NULL) {
|
||||
ciKlass* k = ttkp->klass();
|
||||
if (k->is_loaded() && k->is_interface())
|
||||
is_intf = true;
|
||||
}
|
||||
|
||||
// Default case: merge all inputs
|
||||
const Type *t = Type::TOP; // Merged type starting value
|
||||
@ -921,6 +927,8 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
|
||||
// uplift the type.
|
||||
if( !t->empty() && ttip && ttip->is_loaded() && ttip->klass()->is_interface() )
|
||||
{ assert(ft == _type, ""); } // Uplift to interface
|
||||
else if( !t->empty() && ttkp && ttkp->is_loaded() && ttkp->klass()->is_interface() )
|
||||
{ assert(ft == _type, ""); } // Uplift to interface
|
||||
// Otherwise it's something stupid like non-overlapping int ranges
|
||||
// found on dying counted loops.
|
||||
else
|
||||
@ -936,6 +944,7 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
|
||||
// because the type system doesn't interact well with interfaces.
|
||||
const TypePtr *jtp = jt->make_ptr();
|
||||
const TypeInstPtr *jtip = (jtp != NULL) ? jtp->isa_instptr() : NULL;
|
||||
const TypeKlassPtr *jtkp = (jtp != NULL) ? jtp->isa_klassptr() : NULL;
|
||||
if( jtip && ttip ) {
|
||||
if( jtip->is_loaded() && jtip->klass()->is_interface() &&
|
||||
ttip->is_loaded() && !ttip->klass()->is_interface() ) {
|
||||
@ -945,6 +954,14 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
|
||||
jt = ft;
|
||||
}
|
||||
}
|
||||
if( jtkp && ttkp ) {
|
||||
if( jtkp->is_loaded() && jtkp->klass()->is_interface() &&
|
||||
ttkp->is_loaded() && !ttkp->klass()->is_interface() ) {
|
||||
assert(ft == ttkp->cast_to_ptr_type(jtkp->ptr()) ||
|
||||
ft->isa_narrowoop() && ft->make_ptr() == ttkp->cast_to_ptr_type(jtkp->ptr()), "");
|
||||
jt = ft;
|
||||
}
|
||||
}
|
||||
if (jt != ft && jt->base() == ft->base()) {
|
||||
if (jt->isa_int() &&
|
||||
jt->is_int()->_lo == ft->is_int()->_lo &&
|
||||
|
@ -228,6 +228,11 @@ void PhaseChaitin::Register_Allocate() {
|
||||
// them for real.
|
||||
de_ssa();
|
||||
|
||||
#ifdef ASSERT
|
||||
// Veify the graph before RA.
|
||||
verify(&live_arena);
|
||||
#endif
|
||||
|
||||
{
|
||||
NOT_PRODUCT( Compile::TracePhase t3("computeLive", &_t_computeLive, TimeCompiler); )
|
||||
_live = NULL; // Mark live as being not available
|
||||
@ -306,12 +311,6 @@ void PhaseChaitin::Register_Allocate() {
|
||||
C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after physical split");
|
||||
if (C->failing()) return;
|
||||
|
||||
#ifdef ASSERT
|
||||
if( VerifyOpto ) {
|
||||
_cfg.verify();
|
||||
verify_base_ptrs(&live_arena);
|
||||
}
|
||||
#endif
|
||||
NOT_PRODUCT( C->verify_graph_edges(); )
|
||||
|
||||
compact(); // Compact LRGs; return new lower max lrg
|
||||
@ -340,7 +339,7 @@ void PhaseChaitin::Register_Allocate() {
|
||||
compress_uf_map_for_nodes();
|
||||
|
||||
#ifdef ASSERT
|
||||
if( VerifyOpto ) _ifg->verify(this);
|
||||
verify(&live_arena, true);
|
||||
#endif
|
||||
} else {
|
||||
ifg.SquareUp();
|
||||
@ -376,12 +375,6 @@ void PhaseChaitin::Register_Allocate() {
|
||||
// Bail out if unique gets too large (ie - unique > MaxNodeLimit - 2*NodeLimitFudgeFactor)
|
||||
C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after split");
|
||||
if (C->failing()) return;
|
||||
#ifdef ASSERT
|
||||
if( VerifyOpto ) {
|
||||
_cfg.verify();
|
||||
verify_base_ptrs(&live_arena);
|
||||
}
|
||||
#endif
|
||||
|
||||
compact(); // Compact LRGs; return new lower max lrg
|
||||
|
||||
@ -412,7 +405,7 @@ void PhaseChaitin::Register_Allocate() {
|
||||
}
|
||||
compress_uf_map_for_nodes();
|
||||
#ifdef ASSERT
|
||||
if( VerifyOpto ) _ifg->verify(this);
|
||||
verify(&live_arena, true);
|
||||
#endif
|
||||
cache_lrg_info(); // Count degree of LRGs
|
||||
|
||||
@ -432,6 +425,11 @@ void PhaseChaitin::Register_Allocate() {
|
||||
// Peephole remove copies
|
||||
post_allocate_copy_removal();
|
||||
|
||||
#ifdef ASSERT
|
||||
// Veify the graph after RA.
|
||||
verify(&live_arena);
|
||||
#endif
|
||||
|
||||
// max_reg is past the largest *register* used.
|
||||
// Convert that to a frame_slot number.
|
||||
if( _max_reg <= _matcher._new_SP )
|
||||
@ -956,7 +954,7 @@ void PhaseChaitin::Simplify( ) {
|
||||
while ((neighbor = elements.next()) != 0) {
|
||||
LRG *n = &lrgs(neighbor);
|
||||
#ifdef ASSERT
|
||||
if( VerifyOpto ) {
|
||||
if( VerifyOpto || VerifyRegisterAllocator ) {
|
||||
assert( _ifg->effective_degree(neighbor) == n->degree(), "" );
|
||||
}
|
||||
#endif
|
||||
|
@ -491,6 +491,8 @@ private:
|
||||
// Verify that base pointers and derived pointers are still sane
|
||||
void verify_base_ptrs( ResourceArea *a ) const;
|
||||
|
||||
void verify( ResourceArea *a, bool verify_ifg = false ) const;
|
||||
|
||||
void dump_for_spill_split_recycle() const;
|
||||
|
||||
public:
|
||||
|
@ -129,7 +129,7 @@ macro(JumpProj)
|
||||
macro(LShiftI)
|
||||
macro(LShiftL)
|
||||
macro(LoadB)
|
||||
macro(LoadC)
|
||||
macro(LoadUS)
|
||||
macro(LoadD)
|
||||
macro(LoadD_unaligned)
|
||||
macro(LoadF)
|
||||
|
@ -2005,7 +2005,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) {
|
||||
case Op_StoreP:
|
||||
case Op_StoreN:
|
||||
case Op_LoadB:
|
||||
case Op_LoadC:
|
||||
case Op_LoadUS:
|
||||
case Op_LoadI:
|
||||
case Op_LoadKlass:
|
||||
case Op_LoadNKlass:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, 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
|
||||
@ -244,42 +244,73 @@ static bool magic_long_divide_constants(jlong d, jlong &M, jint &s) {
|
||||
|
||||
//---------------------long_by_long_mulhi--------------------------------------
|
||||
// Generate ideal node graph for upper half of a 64 bit x 64 bit multiplication
|
||||
static Node *long_by_long_mulhi( PhaseGVN *phase, Node *dividend, jlong magic_const) {
|
||||
static Node* long_by_long_mulhi(PhaseGVN* phase, Node* dividend, jlong magic_const) {
|
||||
// If the architecture supports a 64x64 mulhi, there is
|
||||
// no need to synthesize it in ideal nodes.
|
||||
if (Matcher::has_match_rule(Op_MulHiL)) {
|
||||
Node *v = phase->longcon(magic_const);
|
||||
Node* v = phase->longcon(magic_const);
|
||||
return new (phase->C, 3) MulHiLNode(dividend, v);
|
||||
}
|
||||
|
||||
// Taken from Hacker's Delight, Fig. 8-2. Multiply high signed.
|
||||
// (http://www.hackersdelight.org/HDcode/mulhs.c)
|
||||
//
|
||||
// int mulhs(int u, int v) {
|
||||
// unsigned u0, v0, w0;
|
||||
// int u1, v1, w1, w2, t;
|
||||
//
|
||||
// u0 = u & 0xFFFF; u1 = u >> 16;
|
||||
// v0 = v & 0xFFFF; v1 = v >> 16;
|
||||
// w0 = u0*v0;
|
||||
// t = u1*v0 + (w0 >> 16);
|
||||
// w1 = t & 0xFFFF;
|
||||
// w2 = t >> 16;
|
||||
// w1 = u0*v1 + w1;
|
||||
// return u1*v1 + w2 + (w1 >> 16);
|
||||
// }
|
||||
//
|
||||
// Note: The version above is for 32x32 multiplications, while the
|
||||
// following inline comments are adapted to 64x64.
|
||||
|
||||
const int N = 64;
|
||||
|
||||
Node *u_hi = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2)));
|
||||
Node *u_lo = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF)));
|
||||
// u0 = u & 0xFFFFFFFF; u1 = u >> 32;
|
||||
Node* u0 = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF)));
|
||||
Node* u1 = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2)));
|
||||
|
||||
Node *v_hi = phase->longcon(magic_const >> N/2);
|
||||
Node *v_lo = phase->longcon(magic_const & 0XFFFFFFFF);
|
||||
// v0 = v & 0xFFFFFFFF; v1 = v >> 32;
|
||||
Node* v0 = phase->longcon(magic_const & 0xFFFFFFFF);
|
||||
Node* v1 = phase->longcon(magic_const >> (N / 2));
|
||||
|
||||
Node *hihi_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_hi));
|
||||
Node *hilo_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_lo));
|
||||
Node *lohi_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_hi));
|
||||
Node *lolo_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_lo));
|
||||
// w0 = u0*v0;
|
||||
Node* w0 = phase->transform(new (phase->C, 3) MulLNode(u0, v0));
|
||||
|
||||
Node *t1 = phase->transform(new (phase->C, 3) URShiftLNode(lolo_product, phase->intcon(N / 2)));
|
||||
Node *t2 = phase->transform(new (phase->C, 3) AddLNode(hilo_product, t1));
|
||||
// t = u1*v0 + (w0 >> 32);
|
||||
Node* u1v0 = phase->transform(new (phase->C, 3) MulLNode(u1, v0));
|
||||
Node* temp = phase->transform(new (phase->C, 3) URShiftLNode(w0, phase->intcon(N / 2)));
|
||||
Node* t = phase->transform(new (phase->C, 3) AddLNode(u1v0, temp));
|
||||
|
||||
// Construct both t3 and t4 before transforming so t2 doesn't go dead
|
||||
// prematurely.
|
||||
Node *t3 = new (phase->C, 3) RShiftLNode(t2, phase->intcon(N / 2));
|
||||
Node *t4 = new (phase->C, 3) AndLNode(t2, phase->longcon(0xFFFFFFFF));
|
||||
t3 = phase->transform(t3);
|
||||
t4 = phase->transform(t4);
|
||||
// w1 = t & 0xFFFFFFFF;
|
||||
Node* w1 = new (phase->C, 3) AndLNode(t, phase->longcon(0xFFFFFFFF));
|
||||
|
||||
Node *t5 = phase->transform(new (phase->C, 3) AddLNode(t4, lohi_product));
|
||||
Node *t6 = phase->transform(new (phase->C, 3) RShiftLNode(t5, phase->intcon(N / 2)));
|
||||
Node *t7 = phase->transform(new (phase->C, 3) AddLNode(t3, hihi_product));
|
||||
// w2 = t >> 32;
|
||||
Node* w2 = new (phase->C, 3) RShiftLNode(t, phase->intcon(N / 2));
|
||||
|
||||
return new (phase->C, 3) AddLNode(t7, t6);
|
||||
// 6732154: Construct both w1 and w2 before transforming, so t
|
||||
// doesn't go dead prematurely.
|
||||
w1 = phase->transform(w1);
|
||||
w2 = phase->transform(w2);
|
||||
|
||||
// w1 = u0*v1 + w1;
|
||||
Node* u0v1 = phase->transform(new (phase->C, 3) MulLNode(u0, v1));
|
||||
w1 = phase->transform(new (phase->C, 3) AddLNode(u0v1, w1));
|
||||
|
||||
// return u1*v1 + w2 + (w1 >> 32);
|
||||
Node* u1v1 = phase->transform(new (phase->C, 3) MulLNode(u1, v1));
|
||||
Node* temp1 = phase->transform(new (phase->C, 3) AddLNode(u1v1, w2));
|
||||
Node* temp2 = phase->transform(new (phase->C, 3) RShiftLNode(w1, phase->intcon(N / 2)));
|
||||
|
||||
return new (phase->C, 3) AddLNode(temp1, temp2);
|
||||
}
|
||||
|
||||
|
||||
@ -976,7 +1007,7 @@ Node *ModLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
|
||||
// Expand mod
|
||||
if( con >= 0 && con < max_jlong && is_power_of_2_long(con+1) ) {
|
||||
uint k = log2_long(con); // Extract k
|
||||
uint k = exact_log2_long(con+1); // Extract k
|
||||
|
||||
// Basic algorithm by David Detlefs. See fastmod_long.java for gory details.
|
||||
// Used to help a popular random number generator which does a long-mod
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include "incls/_precompiled.incl"
|
||||
#include "incls/_gcm.cpp.incl"
|
||||
|
||||
// To avoid float value underflow
|
||||
#define MIN_BLOCK_FREQUENCY 1.e-35f
|
||||
|
||||
//----------------------------schedule_node_into_block-------------------------
|
||||
// Insert node n into block b. Look for projections of n and make sure they
|
||||
// are in b also.
|
||||
@ -1380,6 +1383,13 @@ void PhaseCFG::Estimate_Block_Frequency() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
for (uint i = 0; i < _num_blocks; i++ ) {
|
||||
Block *b = _blocks[i];
|
||||
assert(b->_freq >= MIN_BLOCK_FREQUENCY, "Register Allocator requiers meaningful block frequency");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (PrintCFGBlockFreq) {
|
||||
tty->print_cr("CFG Block Frequencies");
|
||||
@ -1877,7 +1887,9 @@ void CFGLoop::scale_freq() {
|
||||
float loop_freq = _freq * trip_count();
|
||||
for (int i = 0; i < _members.length(); i++) {
|
||||
CFGElement* s = _members.at(i);
|
||||
s->_freq *= loop_freq;
|
||||
float block_freq = s->_freq * loop_freq;
|
||||
if (block_freq < MIN_BLOCK_FREQUENCY) block_freq = MIN_BLOCK_FREQUENCY;
|
||||
s->_freq = block_freq;
|
||||
}
|
||||
CFGLoop* ch = _child;
|
||||
while (ch != NULL) {
|
||||
|
@ -1836,10 +1836,7 @@ void GraphKit::write_barrier_post(Node* oop_store, Node* obj, Node* adr,
|
||||
(CardTableModRefBS*)(Universe::heap()->barrier_set());
|
||||
Node *b = _gvn.transform(new (C, 3) URShiftXNode( cast, _gvn.intcon(CardTableModRefBS::card_shift) ));
|
||||
// We store into a byte array, so do not bother to left-shift by zero
|
||||
// Get base of card map
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte),
|
||||
"adjust this code");
|
||||
Node *c = makecon(TypeRawPtr::make((address)ct->byte_map_base));
|
||||
Node *c = byte_map_base_node();
|
||||
// Combine
|
||||
Node *sb_ctl = control();
|
||||
Node *sb_adr = _gvn.transform(new (C, 4) AddPNode( top()/*no base ptr*/, c, b ));
|
||||
@ -2945,16 +2942,10 @@ Node* GraphKit::new_instance(Node* klass_node,
|
||||
|
||||
// Now generate allocation code
|
||||
|
||||
// With escape analysis, the entire memory state is needed to be able to
|
||||
// eliminate the allocation. If the allocations cannot be eliminated, this
|
||||
// will be optimized to the raw slice when the allocation is expanded.
|
||||
Node *mem;
|
||||
if (C->do_escape_analysis()) {
|
||||
mem = reset_memory();
|
||||
set_all_memory(mem);
|
||||
} else {
|
||||
mem = memory(Compile::AliasIdxRaw);
|
||||
}
|
||||
// The entire memory state is needed for slow path of the allocation
|
||||
// since GC and deoptimization can happened.
|
||||
Node *mem = reset_memory();
|
||||
set_all_memory(mem); // Create new memory state
|
||||
|
||||
AllocateNode* alloc
|
||||
= new (C, AllocateNode::ParmLimit)
|
||||
@ -3091,16 +3082,10 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
||||
|
||||
// Now generate allocation code
|
||||
|
||||
// With escape analysis, the entire memory state is needed to be able to
|
||||
// eliminate the allocation. If the allocations cannot be eliminated, this
|
||||
// will be optimized to the raw slice when the allocation is expanded.
|
||||
Node *mem;
|
||||
if (C->do_escape_analysis()) {
|
||||
mem = reset_memory();
|
||||
set_all_memory(mem);
|
||||
} else {
|
||||
mem = memory(Compile::AliasIdxRaw);
|
||||
}
|
||||
// The entire memory state is needed for slow path of the allocation
|
||||
// since GC and deoptimization can happened.
|
||||
Node *mem = reset_memory();
|
||||
set_all_memory(mem); // Create new memory state
|
||||
|
||||
// Create the AllocateArrayNode and its result projections
|
||||
AllocateArrayNode* alloc
|
||||
@ -3365,14 +3350,6 @@ void GraphKit::g1_write_barrier_post(Node* store,
|
||||
|
||||
const TypeFunc *tf = OptoRuntime::g1_wb_post_Type();
|
||||
|
||||
// Get the address of the card table
|
||||
CardTableModRefBS* ct =
|
||||
(CardTableModRefBS*)(Universe::heap()->barrier_set());
|
||||
Node *card_table = __ makecon(TypeRawPtr::make((address)ct->byte_map_base));
|
||||
// Get base of card map
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
|
||||
|
||||
// Offsets into the thread
|
||||
const int index_offset = in_bytes(JavaThread::dirty_card_queue_offset() +
|
||||
PtrQueue::byte_offset_of_index());
|
||||
@ -3402,7 +3379,7 @@ void GraphKit::g1_write_barrier_post(Node* store,
|
||||
Node* card_offset = __ URShiftX( cast, __ ConI(CardTableModRefBS::card_shift) );
|
||||
|
||||
// Combine card table base and card offset
|
||||
Node *card_adr = __ AddP(no_base, card_table, card_offset );
|
||||
Node *card_adr = __ AddP(no_base, byte_map_base_node(), card_offset );
|
||||
|
||||
// If we know the value being stored does it cross regions?
|
||||
|
||||
|
@ -83,6 +83,18 @@ class GraphKit : public Phase {
|
||||
Node* zerocon(BasicType bt) const { return _gvn.zerocon(bt); }
|
||||
// (See also macro MakeConX in type.hpp, which uses intcon or longcon.)
|
||||
|
||||
// Helper for byte_map_base
|
||||
Node* byte_map_base_node() {
|
||||
// Get base of card map
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)(Universe::heap()->barrier_set());
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust users of this code");
|
||||
if (ct->byte_map_base != NULL) {
|
||||
return makecon(TypeRawPtr::make((address)ct->byte_map_base));
|
||||
} else {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
||||
jint find_int_con(Node* n, jint value_if_unknown) {
|
||||
return _gvn.find_int_con(n, value_if_unknown);
|
||||
}
|
||||
|
@ -471,12 +471,28 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
|
||||
// for the "collect_gc_info" phase later.
|
||||
IndexSet liveout(_live->live(b));
|
||||
uint last_inst = b->end_idx();
|
||||
// Compute last phi index
|
||||
uint last_phi;
|
||||
for( last_phi = 1; last_phi < last_inst; last_phi++ )
|
||||
if( !b->_nodes[last_phi]->is_Phi() )
|
||||
// Compute first nonphi node index
|
||||
uint first_inst;
|
||||
for( first_inst = 1; first_inst < last_inst; first_inst++ )
|
||||
if( !b->_nodes[first_inst]->is_Phi() )
|
||||
break;
|
||||
|
||||
// Spills could be inserted before CreateEx node which should be
|
||||
// first instruction in block after Phis. Move CreateEx up.
|
||||
for( uint insidx = first_inst; insidx < last_inst; insidx++ ) {
|
||||
Node *ex = b->_nodes[insidx];
|
||||
if( ex->is_SpillCopy() ) continue;
|
||||
if( insidx > first_inst && ex->is_Mach() &&
|
||||
ex->as_Mach()->ideal_Opcode() == Op_CreateEx ) {
|
||||
// If the CreateEx isn't above all the MachSpillCopies
|
||||
// then move it to the top.
|
||||
b->_nodes.remove(insidx);
|
||||
b->_nodes.insert(first_inst, ex);
|
||||
}
|
||||
// Stop once a CreateEx or any other node is found
|
||||
break;
|
||||
}
|
||||
|
||||
// Reset block's register pressure values for each ifg construction
|
||||
uint pressure[2], hrp_index[2];
|
||||
pressure[0] = pressure[1] = 0;
|
||||
@ -485,7 +501,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
|
||||
// Liveout things are presumed live for the whole block. We accumulate
|
||||
// 'area' accordingly. If they get killed in the block, we'll subtract
|
||||
// the unused part of the block from the area.
|
||||
int inst_count = last_inst - last_phi;
|
||||
int inst_count = last_inst - first_inst;
|
||||
double cost = (inst_count <= 0) ? 0.0 : b->_freq * double(inst_count);
|
||||
assert(!(cost < 0.0), "negative spill cost" );
|
||||
IndexSetIterator elements(&liveout);
|
||||
|
@ -107,7 +107,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe
|
||||
was_store = false;
|
||||
switch( mach->ideal_Opcode() ) {
|
||||
case Op_LoadB:
|
||||
case Op_LoadC:
|
||||
case Op_LoadUS:
|
||||
case Op_LoadD:
|
||||
case Op_LoadF:
|
||||
case Op_LoadI:
|
||||
|
@ -271,9 +271,9 @@ void PhaseLive::dump( const Block *b ) const {
|
||||
|
||||
//------------------------------verify_base_ptrs-------------------------------
|
||||
// Verify that base pointers and derived pointers are still sane.
|
||||
// Basically, if a derived pointer is live at a safepoint, then its
|
||||
// base pointer must be live also.
|
||||
void PhaseChaitin::verify_base_ptrs( ResourceArea *a ) const {
|
||||
#ifdef ASSERT
|
||||
Unique_Node_List worklist(a);
|
||||
for( uint i = 0; i < _cfg._num_blocks; i++ ) {
|
||||
Block *b = _cfg._blocks[i];
|
||||
for( uint j = b->end_idx() + 1; j > 1; j-- ) {
|
||||
@ -287,28 +287,81 @@ void PhaseChaitin::verify_base_ptrs( ResourceArea *a ) const {
|
||||
// Now scan for a live derived pointer
|
||||
if (jvms->oopoff() < sfpt->req()) {
|
||||
// Check each derived/base pair
|
||||
for (uint idx = jvms->oopoff(); idx < sfpt->req(); idx += 2) {
|
||||
for (uint idx = jvms->oopoff(); idx < sfpt->req(); idx++) {
|
||||
Node *check = sfpt->in(idx);
|
||||
uint j = 0;
|
||||
bool is_derived = ((idx - jvms->oopoff()) & 1) == 0;
|
||||
// search upwards through spills and spill phis for AddP
|
||||
while(true) {
|
||||
if( !check ) break;
|
||||
int idx = check->is_Copy();
|
||||
if( idx ) {
|
||||
check = check->in(idx);
|
||||
} else if( check->is_Phi() && check->_idx >= _oldphi ) {
|
||||
check = check->in(1);
|
||||
} else
|
||||
break;
|
||||
j++;
|
||||
assert(j < 100000,"Derived pointer checking in infinite loop");
|
||||
worklist.clear();
|
||||
worklist.push(check);
|
||||
uint k = 0;
|
||||
while( k < worklist.size() ) {
|
||||
check = worklist.at(k);
|
||||
assert(check,"Bad base or derived pointer");
|
||||
// See PhaseChaitin::find_base_for_derived() for all cases.
|
||||
int isc = check->is_Copy();
|
||||
if( isc ) {
|
||||
worklist.push(check->in(isc));
|
||||
} else if( check->is_Phi() ) {
|
||||
for (uint m = 1; m < check->req(); m++)
|
||||
worklist.push(check->in(m));
|
||||
} else if( check->is_Con() ) {
|
||||
if (is_derived) {
|
||||
// Derived is NULL+offset
|
||||
assert(!is_derived || check->bottom_type()->is_ptr()->ptr() == TypePtr::Null,"Bad derived pointer");
|
||||
} else {
|
||||
assert(check->bottom_type()->is_ptr()->_offset == 0,"Bad base pointer");
|
||||
// Base either ConP(NULL) or loadConP
|
||||
if (check->is_Mach()) {
|
||||
assert(check->as_Mach()->ideal_Opcode() == Op_ConP,"Bad base pointer");
|
||||
} else {
|
||||
assert(check->Opcode() == Op_ConP &&
|
||||
check->bottom_type()->is_ptr()->ptr() == TypePtr::Null,"Bad base pointer");
|
||||
}
|
||||
}
|
||||
} else if( check->bottom_type()->is_ptr()->_offset == 0 ) {
|
||||
if(check->is_Proj() || check->is_Mach() &&
|
||||
(check->as_Mach()->ideal_Opcode() == Op_CreateEx ||
|
||||
check->as_Mach()->ideal_Opcode() == Op_ThreadLocal ||
|
||||
check->as_Mach()->ideal_Opcode() == Op_CMoveP ||
|
||||
check->as_Mach()->ideal_Opcode() == Op_CheckCastPP ||
|
||||
#ifdef _LP64
|
||||
UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_CastPP ||
|
||||
UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_DecodeN ||
|
||||
#endif
|
||||
check->as_Mach()->ideal_Opcode() == Op_LoadP ||
|
||||
check->as_Mach()->ideal_Opcode() == Op_LoadKlass)) {
|
||||
// Valid nodes
|
||||
} else {
|
||||
check->dump();
|
||||
assert(false,"Bad base or derived pointer");
|
||||
}
|
||||
} else {
|
||||
assert(is_derived,"Bad base pointer");
|
||||
assert(check->is_Mach() && check->as_Mach()->ideal_Opcode() == Op_AddP,"Bad derived pointer");
|
||||
}
|
||||
k++;
|
||||
assert(k < 100000,"Derived pointer checking in infinite loop");
|
||||
} // End while
|
||||
assert(check->is_Mach() && check->as_Mach()->ideal_Opcode() == Op_AddP,"Bad derived pointer")
|
||||
}
|
||||
} // End of check for derived pointers
|
||||
} // End of Kcheck for debug info
|
||||
} // End of if found a safepoint
|
||||
} // End of forall instructions in block
|
||||
} // End of forall blocks
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------verify-------------------------------------
|
||||
// Verify that graphs and base pointers are still sane.
|
||||
void PhaseChaitin::verify( ResourceArea *a, bool verify_ifg ) const {
|
||||
#ifdef ASSERT
|
||||
if( VerifyOpto || VerifyRegisterAllocator ) {
|
||||
_cfg.verify();
|
||||
verify_base_ptrs(a);
|
||||
if(verify_ifg)
|
||||
_ifg->verify(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -2654,7 +2654,7 @@ void PhaseIdealLoop::build_loop_late_post( Node *n, const PhaseIdealLoop *verify
|
||||
case Op_ModF:
|
||||
case Op_ModD:
|
||||
case Op_LoadB: // Same with Loads; they can sink
|
||||
case Op_LoadC: // during loop optimizations.
|
||||
case Op_LoadUS: // during loop optimizations.
|
||||
case Op_LoadD:
|
||||
case Op_LoadF:
|
||||
case Op_LoadI:
|
||||
|
@ -952,13 +952,6 @@ void PhaseMacroExpand::expand_allocate_common(
|
||||
Node* klass_node = alloc->in(AllocateNode::KlassNode);
|
||||
Node* initial_slow_test = alloc->in(AllocateNode::InitialTest);
|
||||
|
||||
// With escape analysis, the entire memory state was needed to be able to
|
||||
// eliminate the allocation. Since the allocations cannot be eliminated,
|
||||
// optimize it to the raw slice.
|
||||
if (mem->is_MergeMem()) {
|
||||
mem = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw);
|
||||
}
|
||||
|
||||
assert(ctrl != NULL, "must have control");
|
||||
// We need a Region and corresponding Phi's to merge the slow-path and fast-path results.
|
||||
// they will not be used if "always_slow" is set
|
||||
@ -1016,6 +1009,11 @@ void PhaseMacroExpand::expand_allocate_common(
|
||||
Node *slow_mem = mem; // save the current memory state for slow path
|
||||
// generate the fast allocation code unless we know that the initial test will always go slow
|
||||
if (!always_slow) {
|
||||
// Fast path modifies only raw memory.
|
||||
if (mem->is_MergeMem()) {
|
||||
mem = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw);
|
||||
}
|
||||
|
||||
Node* eden_top_adr;
|
||||
Node* eden_end_adr;
|
||||
|
||||
@ -1239,8 +1237,6 @@ void PhaseMacroExpand::expand_allocate_common(
|
||||
}
|
||||
}
|
||||
|
||||
mem = result_phi_rawmem;
|
||||
|
||||
// An allocate node has separate i_o projections for the uses on the control and i_o paths
|
||||
// Replace uses of the control i_o projection with result_phi_i_o (unless we are only generating a slow call)
|
||||
if (_ioproj_fallthrough == NULL) {
|
||||
|
@ -1824,7 +1824,7 @@ void Matcher::find_shared( Node *n ) {
|
||||
mem_op = true;
|
||||
break;
|
||||
case Op_LoadB:
|
||||
case Op_LoadC:
|
||||
case Op_LoadUS:
|
||||
case Op_LoadD:
|
||||
case Op_LoadF:
|
||||
case Op_LoadI:
|
||||
|
@ -779,14 +779,14 @@ Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const Type
|
||||
"use LoadRangeNode instead");
|
||||
switch (bt) {
|
||||
case T_BOOLEAN:
|
||||
case T_BYTE: return new (C, 3) LoadBNode(ctl, mem, adr, adr_type, rt->is_int() );
|
||||
case T_INT: return new (C, 3) LoadINode(ctl, mem, adr, adr_type, rt->is_int() );
|
||||
case T_CHAR: return new (C, 3) LoadCNode(ctl, mem, adr, adr_type, rt->is_int() );
|
||||
case T_SHORT: return new (C, 3) LoadSNode(ctl, mem, adr, adr_type, rt->is_int() );
|
||||
case T_LONG: return new (C, 3) LoadLNode(ctl, mem, adr, adr_type, rt->is_long() );
|
||||
case T_FLOAT: return new (C, 3) LoadFNode(ctl, mem, adr, adr_type, rt );
|
||||
case T_DOUBLE: return new (C, 3) LoadDNode(ctl, mem, adr, adr_type, rt );
|
||||
case T_ADDRESS: return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_ptr() );
|
||||
case T_BYTE: return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() );
|
||||
case T_INT: return new (C, 3) LoadINode (ctl, mem, adr, adr_type, rt->is_int() );
|
||||
case T_CHAR: return new (C, 3) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int() );
|
||||
case T_SHORT: return new (C, 3) LoadSNode (ctl, mem, adr, adr_type, rt->is_int() );
|
||||
case T_LONG: return new (C, 3) LoadLNode (ctl, mem, adr, adr_type, rt->is_long() );
|
||||
case T_FLOAT: return new (C, 3) LoadFNode (ctl, mem, adr, adr_type, rt );
|
||||
case T_DOUBLE: return new (C, 3) LoadDNode (ctl, mem, adr, adr_type, rt );
|
||||
case T_ADDRESS: return new (C, 3) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr() );
|
||||
case T_OBJECT:
|
||||
#ifdef _LP64
|
||||
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
|
||||
@ -1076,13 +1076,14 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) {
|
||||
// of the original value.
|
||||
Node* mem_phi = in(Memory);
|
||||
Node* offset = in(Address)->in(AddPNode::Offset);
|
||||
Node* region = base->in(0);
|
||||
|
||||
Node* in1 = clone();
|
||||
Node* in1_addr = in1->in(Address)->clone();
|
||||
in1_addr->set_req(AddPNode::Base, base->in(allocation_index));
|
||||
in1_addr->set_req(AddPNode::Address, base->in(allocation_index));
|
||||
in1_addr->set_req(AddPNode::Offset, offset);
|
||||
in1->set_req(0, base->in(allocation_index));
|
||||
in1->set_req(0, region->in(allocation_index));
|
||||
in1->set_req(Address, in1_addr);
|
||||
in1->set_req(Memory, mem_phi->in(allocation_index));
|
||||
|
||||
@ -1091,7 +1092,7 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) {
|
||||
in2_addr->set_req(AddPNode::Base, base->in(load_index));
|
||||
in2_addr->set_req(AddPNode::Address, base->in(load_index));
|
||||
in2_addr->set_req(AddPNode::Offset, offset);
|
||||
in2->set_req(0, base->in(load_index));
|
||||
in2->set_req(0, region->in(load_index));
|
||||
in2->set_req(Address, in2_addr);
|
||||
in2->set_req(Memory, mem_phi->in(load_index));
|
||||
|
||||
@ -1100,7 +1101,7 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) {
|
||||
in2_addr = phase->transform(in2_addr);
|
||||
in2 = phase->transform(in2);
|
||||
|
||||
PhiNode* result = PhiNode::make_blank(base->in(0), this);
|
||||
PhiNode* result = PhiNode::make_blank(region, this);
|
||||
result->set_req(allocation_index, in1);
|
||||
result->set_req(load_index, in2);
|
||||
return result;
|
||||
@ -1357,7 +1358,7 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
// Steps (a), (b): Walk past independent stores to find an exact match.
|
||||
if (prev_mem != NULL && prev_mem != in(MemNode::Memory)) {
|
||||
// (c) See if we can fold up on the spot, but don't fold up here.
|
||||
// Fold-up might require truncation (for LoadB/LoadS/LoadC) or
|
||||
// Fold-up might require truncation (for LoadB/LoadS/LoadUS) or
|
||||
// just return a prior value, which is done by Identity calls.
|
||||
if (can_see_stored_value(prev_mem, phase)) {
|
||||
// Make ready for step (d):
|
||||
@ -1606,14 +1607,14 @@ Node *LoadBNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
return LoadNode::Ideal(phase, can_reshape);
|
||||
}
|
||||
|
||||
//--------------------------LoadCNode::Ideal--------------------------------------
|
||||
//--------------------------LoadUSNode::Ideal-------------------------------------
|
||||
//
|
||||
// If the previous store is to the same address as this load,
|
||||
// and the value stored was larger than a char, replace this load
|
||||
// with the value stored truncated to a char. If no truncation is
|
||||
// needed, the replacement is done in LoadNode::Identity().
|
||||
//
|
||||
Node *LoadCNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
Node *LoadUSNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
Node* mem = in(MemNode::Memory);
|
||||
Node* value = can_see_stored_value(mem,phase);
|
||||
if( value && !phase->type(value)->higher_equal( _type ) )
|
||||
|
@ -207,11 +207,11 @@ public:
|
||||
virtual BasicType memory_type() const { return T_BYTE; }
|
||||
};
|
||||
|
||||
//------------------------------LoadCNode--------------------------------------
|
||||
// Load a char (16bits unsigned) from memory
|
||||
class LoadCNode : public LoadNode {
|
||||
//------------------------------LoadUSNode-------------------------------------
|
||||
// Load an unsigned short/char (16bits unsigned) from memory
|
||||
class LoadUSNode : public LoadNode {
|
||||
public:
|
||||
LoadCNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::CHAR )
|
||||
LoadUSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::CHAR )
|
||||
: LoadNode(c,mem,adr,at,ti) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, 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
|
||||
@ -442,16 +442,17 @@ Node *AndINode::Identity( PhaseTransform *phase ) {
|
||||
return load;
|
||||
}
|
||||
uint lop = load->Opcode();
|
||||
if( lop == Op_LoadC &&
|
||||
if( lop == Op_LoadUS &&
|
||||
con == 0x0000FFFF ) // Already zero-extended
|
||||
return load;
|
||||
// Masking off the high bits of a unsigned-shift-right is not
|
||||
// needed either.
|
||||
if( lop == Op_URShiftI ) {
|
||||
const TypeInt *t12 = phase->type( load->in(2) )->isa_int();
|
||||
if( t12 && t12->is_con() ) {
|
||||
int shift_con = t12->get_con();
|
||||
int mask = max_juint >> shift_con;
|
||||
if( t12 && t12->is_con() ) { // Shift is by a constant
|
||||
int shift = t12->get_con();
|
||||
shift &= BitsPerJavaInteger - 1; // semantics of Java shifts
|
||||
int mask = max_juint >> shift;
|
||||
if( (mask&con) == mask ) // If AND is useless, skip it
|
||||
return load;
|
||||
}
|
||||
@ -470,19 +471,19 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
uint lop = load->Opcode();
|
||||
|
||||
// Masking bits off of a Character? Hi bits are already zero.
|
||||
if( lop == Op_LoadC &&
|
||||
if( lop == Op_LoadUS &&
|
||||
(mask & 0xFFFF0000) ) // Can we make a smaller mask?
|
||||
return new (phase->C, 3) AndINode(load,phase->intcon(mask&0xFFFF));
|
||||
|
||||
// Masking bits off of a Short? Loading a Character does some masking
|
||||
if( lop == Op_LoadS &&
|
||||
(mask & 0xFFFF0000) == 0 ) {
|
||||
Node *ldc = new (phase->C, 3) LoadCNode(load->in(MemNode::Control),
|
||||
Node *ldus = new (phase->C, 3) LoadUSNode(load->in(MemNode::Control),
|
||||
load->in(MemNode::Memory),
|
||||
load->in(MemNode::Address),
|
||||
load->adr_type());
|
||||
ldc = phase->transform(ldc);
|
||||
return new (phase->C, 3) AndINode(ldc,phase->intcon(mask&0xFFFF));
|
||||
ldus = phase->transform(ldus);
|
||||
return new (phase->C, 3) AndINode(ldus, phase->intcon(mask&0xFFFF));
|
||||
}
|
||||
|
||||
// Masking sign bits off of a Byte? Let the matcher use an unsigned load
|
||||
@ -579,9 +580,10 @@ Node *AndLNode::Identity( PhaseTransform *phase ) {
|
||||
// needed either.
|
||||
if( lop == Op_URShiftL ) {
|
||||
const TypeInt *t12 = phase->type( usr->in(2) )->isa_int();
|
||||
if( t12 && t12->is_con() ) {
|
||||
int shift_con = t12->get_con();
|
||||
jlong mask = max_julong >> shift_con;
|
||||
if( t12 && t12->is_con() ) { // Shift is by a constant
|
||||
int shift = t12->get_con();
|
||||
shift &= BitsPerJavaLong - 1; // semantics of Java shifts
|
||||
jlong mask = max_julong >> shift;
|
||||
if( (mask&con) == mask ) // If AND is useless, skip it
|
||||
return usr;
|
||||
}
|
||||
@ -605,8 +607,8 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
const TypeInt *t12 = phase->type(rsh->in(2))->isa_int();
|
||||
if( t12 && t12->is_con() ) { // Shift is by a constant
|
||||
int shift = t12->get_con();
|
||||
shift &= (BitsPerJavaInteger*2)-1; // semantics of Java shifts
|
||||
const jlong sign_bits_mask = ~(((jlong)CONST64(1) << (jlong)(BitsPerJavaInteger*2 - shift)) -1);
|
||||
shift &= BitsPerJavaLong - 1; // semantics of Java shifts
|
||||
const jlong sign_bits_mask = ~(((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - shift)) -1);
|
||||
// If the AND'ing of the 2 masks has no bits, then only original shifted
|
||||
// bits survive. NO sign-extension bits survive the maskings.
|
||||
if( (sign_bits_mask & mask) == 0 ) {
|
||||
@ -786,7 +788,7 @@ Node *LShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
|
||||
// Check for ((x & ((CONST64(1)<<(64-c0))-1)) << c0) which ANDs off high bits
|
||||
// before shifting them away.
|
||||
const jlong bits_mask = ((jlong)CONST64(1) << (jlong)(BitsPerJavaInteger*2 - con)) - CONST64(1);
|
||||
const jlong bits_mask = ((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) - CONST64(1);
|
||||
if( add1_op == Op_AndL &&
|
||||
phase->type(add1->in(2)) == TypeLong::make( bits_mask ) )
|
||||
return new (phase->C, 3) LShiftLNode( add1->in(1), in(2) );
|
||||
@ -820,7 +822,7 @@ const Type *LShiftLNode::Value( PhaseTransform *phase ) const {
|
||||
return TypeLong::LONG;
|
||||
|
||||
uint shift = r2->get_con();
|
||||
shift &= (BitsPerJavaInteger*2)-1; // semantics of Java shifts
|
||||
shift &= BitsPerJavaLong - 1; // semantics of Java shifts
|
||||
// Shift by a multiple of 64 does nothing:
|
||||
if (shift == 0) return t1;
|
||||
|
||||
@ -913,7 +915,7 @@ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
set_req(2, phase->intcon(0));
|
||||
return this;
|
||||
}
|
||||
else if( ld->Opcode() == Op_LoadC )
|
||||
else if( ld->Opcode() == Op_LoadUS )
|
||||
// Replace zero-extension-load with sign-extension-load
|
||||
return new (phase->C, 3) LoadSNode( ld->in(MemNode::Control),
|
||||
ld->in(MemNode::Memory),
|
||||
@ -1235,7 +1237,7 @@ Node *URShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count
|
||||
// note: mask computation below does not work for 0 shift count
|
||||
// We'll be wanting the right-shift amount as a mask of that many bits
|
||||
const jlong mask = (((jlong)CONST64(1) << (jlong)(BitsPerJavaInteger*2 - con)) -1);
|
||||
const jlong mask = (((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) -1);
|
||||
|
||||
// Check for ((x << z) + Y) >>> z. Replace with x + con>>>z
|
||||
// The idiom for rounding to a power of 2 is "(Q+(2^z-1)) >>> z".
|
||||
@ -1302,7 +1304,7 @@ const Type *URShiftLNode::Value( PhaseTransform *phase ) const {
|
||||
|
||||
if (r2->is_con()) {
|
||||
uint shift = r2->get_con();
|
||||
shift &= (2*BitsPerJavaInteger)-1; // semantics of Java shifts
|
||||
shift &= BitsPerJavaLong - 1; // semantics of Java shifts
|
||||
// Shift by a multiple of 64 does nothing:
|
||||
if (shift == 0) return t1;
|
||||
// Calculate reasonably aggressive bounds for the result.
|
||||
@ -1325,7 +1327,7 @@ const Type *URShiftLNode::Value( PhaseTransform *phase ) const {
|
||||
const TypeLong* tl = TypeLong::make(lo, hi, MAX2(r1->_widen,r2->_widen));
|
||||
#ifdef ASSERT
|
||||
// Make sure we get the sign-capture idiom correct.
|
||||
if (shift == (2*BitsPerJavaInteger)-1) {
|
||||
if (shift == BitsPerJavaLong - 1) {
|
||||
if (r1->_lo >= 0) assert(tl == TypeLong::ZERO, ">>>63 of + is 0");
|
||||
if (r1->_hi < 0) assert(tl == TypeLong::ONE, ">>>63 of - is +1");
|
||||
}
|
||||
|
@ -1444,7 +1444,7 @@ const Type* SuperWord::container_type(const Type* t) {
|
||||
// (Start, end] half-open range defining which operands are vector
|
||||
void SuperWord::vector_opd_range(Node* n, uint* start, uint* end) {
|
||||
switch (n->Opcode()) {
|
||||
case Op_LoadB: case Op_LoadC:
|
||||
case Op_LoadB: case Op_LoadUS:
|
||||
case Op_LoadI: case Op_LoadL:
|
||||
case Op_LoadF: case Op_LoadD:
|
||||
case Op_LoadP:
|
||||
|
@ -2471,6 +2471,8 @@ const Type *TypeOopPtr::filter( const Type *kills ) const {
|
||||
const Type* ft = join(kills);
|
||||
const TypeInstPtr* ftip = ft->isa_instptr();
|
||||
const TypeInstPtr* ktip = kills->isa_instptr();
|
||||
const TypeKlassPtr* ftkp = ft->isa_klassptr();
|
||||
const TypeKlassPtr* ktkp = kills->isa_klassptr();
|
||||
|
||||
if (ft->empty()) {
|
||||
// Check for evil case of 'this' being a class and 'kills' expecting an
|
||||
@ -2484,6 +2486,8 @@ const Type *TypeOopPtr::filter( const Type *kills ) const {
|
||||
// uplift the type.
|
||||
if (!empty() && ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface())
|
||||
return kills; // Uplift to interface
|
||||
if (!empty() && ktkp != NULL && ktkp->klass()->is_loaded() && ktkp->klass()->is_interface())
|
||||
return kills; // Uplift to interface
|
||||
|
||||
return Type::TOP; // Canonical empty value
|
||||
}
|
||||
@ -2499,6 +2503,12 @@ const Type *TypeOopPtr::filter( const Type *kills ) const {
|
||||
// Happens in a CTW of rt.jar, 320-341, no extra flags
|
||||
return ktip->cast_to_ptr_type(ftip->ptr());
|
||||
}
|
||||
if (ftkp != NULL && ktkp != NULL &&
|
||||
ftkp->is_loaded() && ftkp->klass()->is_interface() &&
|
||||
ktkp->is_loaded() && !ktkp->klass()->is_interface()) {
|
||||
// Happens in a CTW of rt.jar, 320-341, no extra flags
|
||||
return ktkp->cast_to_ptr_type(ftkp->ptr());
|
||||
}
|
||||
|
||||
return ft;
|
||||
}
|
||||
@ -3657,7 +3667,7 @@ const TypePtr *TypeKlassPtr::add_offset( intptr_t offset ) const {
|
||||
|
||||
//------------------------------cast_to_ptr_type-------------------------------
|
||||
const Type *TypeKlassPtr::cast_to_ptr_type(PTR ptr) const {
|
||||
assert(_base == OopPtr, "subclass must override cast_to_ptr_type");
|
||||
assert(_base == KlassPtr, "subclass must override cast_to_ptr_type");
|
||||
if( ptr == _ptr ) return this;
|
||||
return make(ptr, _klass, _offset);
|
||||
}
|
||||
|
@ -882,6 +882,8 @@ class TypeKlassPtr : public TypeOopPtr {
|
||||
public:
|
||||
ciSymbol* name() const { return _klass->name(); }
|
||||
|
||||
bool is_loaded() const { return _klass->is_loaded(); }
|
||||
|
||||
// ptr to klass 'k'
|
||||
static const TypeKlassPtr *make( ciKlass* k ) { return make( TypePtr::Constant, k, 0); }
|
||||
// ptr to klass 'k' with offset
|
||||
|
@ -239,7 +239,7 @@ int VectorNode::opcode(int sopc, uint vlen, const Type* opd_t) {
|
||||
return Op_XorV;
|
||||
|
||||
case Op_LoadB:
|
||||
case Op_LoadC:
|
||||
case Op_LoadUS:
|
||||
case Op_LoadS:
|
||||
case Op_LoadI:
|
||||
case Op_LoadL:
|
||||
@ -269,7 +269,7 @@ int VectorLoadNode::opcode(int sopc, uint vlen) {
|
||||
case 16: return Op_Load16B;
|
||||
}
|
||||
break;
|
||||
case Op_LoadC:
|
||||
case Op_LoadUS:
|
||||
switch (vlen) {
|
||||
case 2: return Op_Load2C;
|
||||
case 4: return Op_Load4C;
|
||||
|
@ -2489,7 +2489,7 @@ jint Arguments::parse_options_environment_variable(const char* name, SysClassPat
|
||||
vm_args.version = JNI_VERSION_1_2;
|
||||
vm_args.options = options;
|
||||
vm_args.nOptions = i;
|
||||
vm_args.ignoreUnrecognized = false;
|
||||
vm_args.ignoreUnrecognized = IgnoreUnrecognizedVMOptions;
|
||||
|
||||
if (PrintVMOptions) {
|
||||
const char* tail;
|
||||
@ -2536,13 +2536,12 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
||||
|
||||
// If flag "-XX:Flags=flags-file" is used it will be the first option to be processed.
|
||||
bool settings_file_specified = false;
|
||||
const char* flags_file;
|
||||
int index;
|
||||
for (index = 0; index < args->nOptions; index++) {
|
||||
const JavaVMOption *option = args->options + index;
|
||||
if (match_option(option, "-XX:Flags=", &tail)) {
|
||||
if (!process_settings_file(tail, true, args->ignoreUnrecognized)) {
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
flags_file = tail;
|
||||
settings_file_specified = true;
|
||||
}
|
||||
if (match_option(option, "-XX:+PrintVMOptions", &tail)) {
|
||||
@ -2551,6 +2550,24 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
||||
if (match_option(option, "-XX:-PrintVMOptions", &tail)) {
|
||||
PrintVMOptions = false;
|
||||
}
|
||||
if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions", &tail)) {
|
||||
IgnoreUnrecognizedVMOptions = true;
|
||||
}
|
||||
if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) {
|
||||
IgnoreUnrecognizedVMOptions = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (IgnoreUnrecognizedVMOptions) {
|
||||
// uncast const to modify the flag args->ignoreUnrecognized
|
||||
*(jboolean*)(&args->ignoreUnrecognized) = true;
|
||||
}
|
||||
|
||||
// Parse specified settings file
|
||||
if (settings_file_specified) {
|
||||
if (!process_settings_file(flags_file, true, args->ignoreUnrecognized)) {
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse default .hotspotrc settings file
|
||||
|
@ -2194,6 +2194,9 @@ class CommandLineFlags {
|
||||
product(bool, PrintVMOptions, trueInDebug, \
|
||||
"print VM flag settings") \
|
||||
\
|
||||
product(bool, IgnoreUnrecognizedVMOptions, false, \
|
||||
"Ignore unrecognized VM options") \
|
||||
\
|
||||
diagnostic(bool, SerializeVMOutput, true, \
|
||||
"Use a mutex to serialize output to tty and hotspot.log") \
|
||||
\
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, 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
|
||||
@ -74,6 +74,7 @@ extern int BytesPerHeapOop;
|
||||
extern int BitsPerHeapOop;
|
||||
|
||||
const int BitsPerJavaInteger = 32;
|
||||
const int BitsPerJavaLong = 64;
|
||||
const int BitsPerSize_t = size_tSize * BitsPerByte;
|
||||
|
||||
// Size of a char[] needed to represent a jint as a string in decimal.
|
||||
@ -906,6 +907,14 @@ inline int exact_log2(intptr_t x) {
|
||||
return log2_intptr(x);
|
||||
}
|
||||
|
||||
//* the argument must be exactly a power of 2
|
||||
inline int exact_log2_long(jlong x) {
|
||||
#ifdef ASSERT
|
||||
if (!is_power_of_2_long(x)) basic_fatal("x must be a power of 2");
|
||||
#endif
|
||||
return log2_long(x);
|
||||
}
|
||||
|
||||
|
||||
// returns integer round-up to the nearest multiple of s (s must be a power of two)
|
||||
inline intptr_t round_to(intptr_t x, uintx s) {
|
||||
|
@ -28,9 +28,9 @@
|
||||
|
||||
# Get OS/ARCH specifics
|
||||
OSNAME = $(shell uname -s)
|
||||
SLASH_JAVA = /java
|
||||
ifeq ($(OSNAME), SunOS)
|
||||
PLATFORM = solaris
|
||||
SLASH_JAVA = /java
|
||||
ARCH = $(shell uname -p)
|
||||
ifeq ($(ARCH), i386)
|
||||
ARCH=i586
|
||||
@ -38,6 +38,7 @@ ifeq ($(OSNAME), SunOS)
|
||||
endif
|
||||
ifeq ($(OSNAME), Linux)
|
||||
PLATFORM = linux
|
||||
SLASH_JAVA = /java
|
||||
ARCH = $(shell uname -m)
|
||||
ifeq ($(ARCH), i386)
|
||||
ARCH = i586
|
||||
@ -62,6 +63,10 @@ ifeq ($(OSNAME), Windows_NT)
|
||||
EXESUFFIX = .exe
|
||||
endif
|
||||
|
||||
ifdef ALT_SLASH_JAVA
|
||||
SLASH_JAVA = $(ALT_SLASH_JAVA)
|
||||
endif
|
||||
|
||||
# Utilities used
|
||||
CD = cd
|
||||
CP = cp
|
||||
|
220
hotspot/test/compiler/6603011/Test.java
Normal file
220
hotspot/test/compiler/6603011/Test.java
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6603011
|
||||
* @summary long/int division by constant
|
||||
*
|
||||
* @run main/othervm -Xcomp -Xbatch -XX:-Inline Test
|
||||
*/
|
||||
|
||||
//
|
||||
// -XX:-Inline is essential to this test so that verification functions
|
||||
// divi, modi, divl and modl generate "plain" divides.
|
||||
// -Xcomp -Xbatch are also useful to ensure the full range of
|
||||
// dividend and divisor combinations are tested
|
||||
//
|
||||
|
||||
import java.net.*;
|
||||
|
||||
class s {
|
||||
static int divi(int dividend, int divisor) { return dividend / divisor; }
|
||||
static int modi(int dividend, int divisor) { return dividend % divisor; }
|
||||
static long divl(long dividend, long divisor) { return dividend / divisor; }
|
||||
static long modl(long dividend, long divisor) { return dividend % divisor; }
|
||||
}
|
||||
|
||||
public class Test implements Runnable {
|
||||
// Report verbose messages on failure; turn off to suppress
|
||||
// too much output with gross numbers of failures.
|
||||
static final boolean VERBOSE = true;
|
||||
|
||||
// Initailize DIVISOR so that it is final in this class.
|
||||
static final int DIVISOR;
|
||||
static {
|
||||
int value = 0;
|
||||
try {
|
||||
value = Integer.decode(System.getProperty("divisor"));
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
DIVISOR = value;
|
||||
}
|
||||
|
||||
// The methods of interest. We want the JIT to compile these
|
||||
// and convert the divide into a multiply.
|
||||
public int divbyI (int dividend) { return dividend / DIVISOR; }
|
||||
public int modbyI (int dividend) { return dividend % DIVISOR; }
|
||||
public long divbyL (long dividend) { return dividend / DIVISOR; }
|
||||
public long modbyL (long dividend) { return dividend % DIVISOR; }
|
||||
|
||||
public int divisor() { return DIVISOR; }
|
||||
|
||||
public boolean checkI (int dividend) {
|
||||
int quo = divbyI(dividend);
|
||||
int rem = modbyI(dividend);
|
||||
int quo0 = s.divi(dividend, divisor());
|
||||
int rem0 = s.modi(dividend, divisor());
|
||||
|
||||
if (quo != quo0 || rem != rem0) {
|
||||
if (VERBOSE) {
|
||||
System.out.println("Computed: " + dividend + " / " + divisor() + " = " +
|
||||
quo + ", " + dividend + " % " + divisor() + " = " + rem );
|
||||
System.out.println("expected: " + dividend + " / " + divisor() + " = " +
|
||||
quo0 + ", " + dividend + " % " + divisor() + " = " + rem0);
|
||||
// Report sign of rem failure
|
||||
if (rem != 0 && (rem ^ dividend) < 0) {
|
||||
System.out.println(" rem & dividend have different signs");
|
||||
}
|
||||
// Report range of rem failure
|
||||
if (java.lang.Math.abs(rem) >= java.lang.Math.abs(divisor())) {
|
||||
System.out.println(" remainder out of range");
|
||||
}
|
||||
// Report quo/rem identity relationship failure
|
||||
if ((quo * divisor()) + rem != dividend) {
|
||||
System.out.println(" quotien/remainder invariant broken");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean checkL (long dividend) {
|
||||
long quo = divbyL(dividend);
|
||||
long rem = modbyL(dividend);
|
||||
long quo0 = s.divl(dividend, divisor());
|
||||
long rem0 = s.modl(dividend, divisor());
|
||||
|
||||
if (quo != quo0 || rem != rem0) {
|
||||
if (VERBOSE) {
|
||||
System.out.println(" " + dividend + " / " + divisor() + " = " +
|
||||
quo + ", " + dividend + " % " + divisor() + " = " + rem);
|
||||
// Report sign of rem failure
|
||||
if (rem != 0 && (rem ^ dividend) < 0) {
|
||||
System.out.println(" rem & dividend have different signs");
|
||||
}
|
||||
// Report range of rem failure
|
||||
if (java.lang.Math.abs(rem) >= java.lang.Math.abs(divisor())) {
|
||||
System.out.println(" remainder out of range");
|
||||
}
|
||||
// Report quo/rem identity relationship failure
|
||||
if ((quo * divisor()) + rem != dividend) {
|
||||
System.out.println(" (" + quo + " * " + divisor() + ") + " + rem + " != "
|
||||
+ dividend);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// Don't try to divide by zero
|
||||
if (divisor() == 0) return;
|
||||
|
||||
// Range of dividends to check. Try dividends from start to end
|
||||
// inclusive, as well as variations on those values as shifted
|
||||
// left.
|
||||
int start = -1024;
|
||||
int end = 1024;
|
||||
|
||||
// Test int division using a variety of dividends.
|
||||
int wrong = 0;
|
||||
int total = 0;
|
||||
|
||||
outerloop:
|
||||
for (int i = start; i <= end; i++) {
|
||||
for (int s = 0; s < 32; s += 4) {
|
||||
total++;
|
||||
int dividend = i << s;
|
||||
if (!checkI(dividend)) {
|
||||
wrong++;
|
||||
// Stop on the first failure
|
||||
// break outerloop;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wrong > 0) {
|
||||
System.out.println("divisor " + divisor() + ": " +
|
||||
wrong + "/" + total + " wrong int divisions");
|
||||
}
|
||||
|
||||
// Test long division using a variety of dividends.
|
||||
wrong = 0;
|
||||
total = 0;
|
||||
|
||||
outerloop:
|
||||
for (int i = start; i <= end; i++) {
|
||||
for (int s = 0; s < 64; s += 4) {
|
||||
total++;
|
||||
long dividend = i << s;
|
||||
if (!checkL(dividend)) {
|
||||
wrong++;
|
||||
// Stop on the first failure
|
||||
// break outerloop;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wrong > 0) {
|
||||
System.out.println("divisor " + divisor() + ": " +
|
||||
wrong + "/" + total + " wrong long divisions");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Reload this class with the "divisor" property set to the input parameter.
|
||||
// This allows the JIT to see q.DIVISOR as a final constant, and change
|
||||
// any divisions or mod operations into multiplies.
|
||||
public static void test_divisor(int divisor,
|
||||
URLClassLoader apploader) throws Exception {
|
||||
System.setProperty("divisor", "" + divisor);
|
||||
ClassLoader loader = new URLClassLoader(apploader.getURLs(),
|
||||
apploader.getParent());
|
||||
Class c = loader.loadClass("Test");
|
||||
Runnable r = (Runnable)c.newInstance();
|
||||
r.run();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class cl = Class.forName("Test");
|
||||
URLClassLoader apploader = (URLClassLoader)cl.getClassLoader();
|
||||
|
||||
|
||||
// Test every divisor between -100 and 100.
|
||||
for (int i = -100; i <= 100; i++) {
|
||||
test_divisor(i, apploader);
|
||||
}
|
||||
|
||||
// Try a few divisors outside the typical range.
|
||||
// The values below have been observed in rt.jar.
|
||||
test_divisor(101, apploader);
|
||||
test_divisor(400, apploader);
|
||||
test_divisor(1000, apploader);
|
||||
test_divisor(3600, apploader);
|
||||
test_divisor(9973, apploader);
|
||||
test_divisor(86400, apploader);
|
||||
test_divisor(1000000, apploader);
|
||||
}
|
||||
|
||||
}
|
@ -27,7 +27,7 @@
|
||||
* @bug 6775880
|
||||
* @summary EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
|
||||
* @compile -source 1.4 -target 1.4 Test.java
|
||||
* @run main/othervm -server -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test
|
||||
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test
|
||||
*/
|
||||
|
||||
public class Test {
|
||||
|
60
hotspot/test/compiler/6795161/Test.java
Normal file
60
hotspot/test/compiler/6795161/Test.java
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6795161
|
||||
* @summary Escape analysis leads to data corruption
|
||||
* @run main/othervm -server -Xcomp -XX:CompileOnly=Test -XX:+DoEscapeAnalysis Test
|
||||
*/
|
||||
|
||||
class Test_Class_1 {
|
||||
static String var_1;
|
||||
|
||||
static void badFunc(int size)
|
||||
{
|
||||
try {
|
||||
for (int i = 0; i < 1; (new byte[size-i])[0] = 0, i++) {}
|
||||
} catch (Exception e) {
|
||||
// don't comment it out, it will lead to correct results ;)
|
||||
//System.out.println("Got exception: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Test {
|
||||
static String var_1_copy = Test_Class_1.var_1;
|
||||
|
||||
static byte var_check;
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
var_check = 1;
|
||||
|
||||
Test_Class_1.badFunc(-1);
|
||||
|
||||
System.out.println("EATester.var_check = " + Test.var_check + " (expected 1)\n");
|
||||
}
|
||||
}
|
||||
|
48
hotspot/test/compiler/6795362/Test6795362.java
Normal file
48
hotspot/test/compiler/6795362/Test6795362.java
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6795362
|
||||
* @summary 32bit server compiler leads to wrong results on solaris-x86
|
||||
*
|
||||
* @run main/othervm -Xcomp -XX:CompileOnly=Test6795362.sub Test6795362
|
||||
*/
|
||||
|
||||
public class Test6795362 {
|
||||
public static void main(String[] args)
|
||||
{
|
||||
sub();
|
||||
|
||||
if (var_bad != 0)
|
||||
throw new InternalError(var_bad + " != 0");
|
||||
}
|
||||
|
||||
static long var_bad = -1L;
|
||||
|
||||
static void sub()
|
||||
{
|
||||
var_bad >>= 65;
|
||||
var_bad /= 65;
|
||||
}
|
||||
}
|
47
hotspot/test/compiler/6799693/Test.java
Normal file
47
hotspot/test/compiler/6799693/Test.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6799693
|
||||
* @summary Server compiler leads to data corruption when expression throws an Exception
|
||||
* @run main/othervm -Xcomp -XX:CompileOnly=Test Test
|
||||
*/
|
||||
|
||||
public class Test {
|
||||
static int var_bad = 1;
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
var_bad++;
|
||||
|
||||
try {
|
||||
for (int i = 0; i < 10; i++) (new byte[((byte)-1 << i)])[0] = 0;
|
||||
}
|
||||
catch (Exception e) { System.out.println("Got " + e); }
|
||||
|
||||
System.out.println("Test.var_bad = " + var_bad + " (expected 2)\n");
|
||||
}
|
||||
}
|
||||
|
109
hotspot/test/compiler/6800154/Test6800154.java
Normal file
109
hotspot/test/compiler/6800154/Test6800154.java
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6800154
|
||||
* @summary Add comments to long_by_long_mulhi() for better understandability
|
||||
*
|
||||
* @run main/othervm -Xcomp -XX:CompileOnly=Test6800154.divcomp Test6800154
|
||||
*/
|
||||
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
public class Test6800154 implements Runnable {
|
||||
static final long[] DIVIDENDS = {
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
1423487,
|
||||
4444441,
|
||||
4918923241323L,
|
||||
-1,
|
||||
-24351,
|
||||
0x3333,
|
||||
0x0000000080000000L,
|
||||
0x7fffffffffffffffL,
|
||||
0x8000000000000000L
|
||||
};
|
||||
|
||||
static final long[] DIVISORS = {
|
||||
1,
|
||||
2,
|
||||
17,
|
||||
12342,
|
||||
24123,
|
||||
143444,
|
||||
123444442344L,
|
||||
-1,
|
||||
-2,
|
||||
-4423423234231423L,
|
||||
0x0000000080000000L,
|
||||
0x7fffffffffffffffL,
|
||||
0x8000000000000000L
|
||||
};
|
||||
|
||||
// Initialize DIVISOR so that it is final in this class.
|
||||
static final long DIVISOR;
|
||||
|
||||
static {
|
||||
long value = 0;
|
||||
try {
|
||||
value = Long.decode(System.getProperty("divisor"));
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
DIVISOR = value;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
Class cl = Class.forName("Test6800154");
|
||||
URLClassLoader apploader = (URLClassLoader) cl.getClassLoader();
|
||||
|
||||
// Iterate over all divisors.
|
||||
for (int i = 0; i < DIVISORS.length; i++) {
|
||||
System.setProperty("divisor", "" + DIVISORS[i]);
|
||||
ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent());
|
||||
Class c = loader.loadClass("Test6800154");
|
||||
Runnable r = (Runnable) c.newInstance();
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
// Iterate over all dividends.
|
||||
for (int i = 0; i < DIVIDENDS.length; i++) {
|
||||
long dividend = DIVIDENDS[i];
|
||||
|
||||
long expected = divint(dividend);
|
||||
long result = divcomp(dividend);
|
||||
|
||||
if (result != expected)
|
||||
throw new InternalError(dividend + " / " + DIVISOR + " failed: " + result + " != " + expected);
|
||||
}
|
||||
}
|
||||
|
||||
static long divint(long a) { return a / DIVISOR; }
|
||||
static long divcomp(long a) { return a / DIVISOR; }
|
||||
}
|
80
hotspot/test/compiler/6805724/Test6805724.java
Normal file
80
hotspot/test/compiler/6805724/Test6805724.java
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6805724
|
||||
* @summary ModLNode::Ideal() generates functionally incorrect graph when divisor is any (2^k-1) constant.
|
||||
*
|
||||
* @run main/othervm -Xcomp -XX:CompileOnly=Test6805724.fcomp Test6805724
|
||||
*/
|
||||
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
public class Test6805724 implements Runnable {
|
||||
// Initialize DIVISOR so that it is final in this class.
|
||||
static final long DIVISOR; // 2^k-1 constant
|
||||
|
||||
static {
|
||||
long value = 0;
|
||||
try {
|
||||
value = Long.decode(System.getProperty("divisor"));
|
||||
} catch (Throwable t) {
|
||||
// This one is required for the Class.forName() in main.
|
||||
}
|
||||
DIVISOR = value;
|
||||
}
|
||||
|
||||
static long fint(long x) {
|
||||
return x % DIVISOR;
|
||||
}
|
||||
|
||||
static long fcomp(long x) {
|
||||
return x % DIVISOR;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
long a = 0x617981E1L;
|
||||
|
||||
long expected = fint(a);
|
||||
long result = fcomp(a);
|
||||
|
||||
if (result != expected)
|
||||
throw new InternalError(result + " != " + expected);
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
Class cl = Class.forName("Test6805724");
|
||||
URLClassLoader apploader = (URLClassLoader) cl.getClassLoader();
|
||||
|
||||
// Iterate over all 2^k-1 divisors.
|
||||
for (int k = 1; k < Long.SIZE; k++) {
|
||||
long divisor = (1L << k) - 1;
|
||||
System.setProperty("divisor", "" + divisor);
|
||||
ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent());
|
||||
Class c = loader.loadClass("Test6805724");
|
||||
Runnable r = (Runnable) c.newInstance();
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user