aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/opto
diff options
context:
space:
mode:
authorasaha <none@none>2012-10-18 21:58:55 -0700
committerasaha <none@none>2012-10-18 21:58:55 -0700
commit9b8a7e5a9522d69af733e834bc397fba61c74378 (patch)
tree0979807a19d4d62bde6841c29f751a206782e207 /src/share/vm/opto
parent4fc48b6aff23c1f2301df6282a3a4e379ab0d4c4 (diff)
parent3a4ffe878d2cf8ff2b71a8a2037cd74512ac1003 (diff)
Merge
Diffstat (limited to 'src/share/vm/opto')
-rw-r--r--src/share/vm/opto/addnode.cpp2
-rw-r--r--src/share/vm/opto/block.cpp2
-rw-r--r--src/share/vm/opto/block.hpp2
-rw-r--r--src/share/vm/opto/bytecodeInfo.cpp6
-rw-r--r--src/share/vm/opto/callGenerator.hpp2
-rw-r--r--src/share/vm/opto/cfgnode.cpp31
-rw-r--r--src/share/vm/opto/classes.hpp5
-rw-r--r--src/share/vm/opto/compile.cpp56
-rw-r--r--src/share/vm/opto/connode.cpp68
-rw-r--r--src/share/vm/opto/connode.hpp81
-rw-r--r--src/share/vm/opto/divnode.cpp2
-rw-r--r--src/share/vm/opto/domgraph.cpp2
-rw-r--r--src/share/vm/opto/escape.cpp23
-rw-r--r--src/share/vm/opto/gcm.cpp2
-rw-r--r--src/share/vm/opto/generateOptoStub.cpp2
-rw-r--r--src/share/vm/opto/graphKit.cpp2
-rw-r--r--src/share/vm/opto/idealKit.cpp2
-rw-r--r--src/share/vm/opto/idealKit.hpp2
-rw-r--r--src/share/vm/opto/ifnode.cpp2
-rw-r--r--src/share/vm/opto/lcm.cpp1
-rw-r--r--src/share/vm/opto/library_call.cpp14
-rw-r--r--src/share/vm/opto/live.cpp1
-rw-r--r--src/share/vm/opto/locknode.cpp2
-rw-r--r--src/share/vm/opto/locknode.hpp2
-rw-r--r--src/share/vm/opto/loopPredicate.cpp2
-rw-r--r--src/share/vm/opto/loopTransform.cpp16
-rw-r--r--src/share/vm/opto/loopUnswitch.cpp2
-rw-r--r--src/share/vm/opto/loopnode.cpp32
-rw-r--r--src/share/vm/opto/loopnode.hpp2
-rw-r--r--src/share/vm/opto/loopopts.cpp6
-rw-r--r--src/share/vm/opto/machnode.cpp7
-rw-r--r--src/share/vm/opto/macro.cpp2
-rw-r--r--src/share/vm/opto/macro.hpp2
-rw-r--r--src/share/vm/opto/matcher.cpp21
-rw-r--r--src/share/vm/opto/matcher.hpp1
-rw-r--r--src/share/vm/opto/memnode.cpp43
-rw-r--r--src/share/vm/opto/memnode.hpp29
-rw-r--r--src/share/vm/opto/mulnode.cpp16
-rw-r--r--src/share/vm/opto/node.hpp16
-rw-r--r--src/share/vm/opto/parse.hpp2
-rw-r--r--src/share/vm/opto/parse1.cpp6
-rw-r--r--src/share/vm/opto/parse2.cpp2
-rw-r--r--src/share/vm/opto/parse3.cpp2
-rw-r--r--src/share/vm/opto/parseHelper.cpp2
-rw-r--r--src/share/vm/opto/phaseX.cpp2
-rw-r--r--src/share/vm/opto/phaseX.hpp6
-rw-r--r--src/share/vm/opto/runtime.cpp18
-rw-r--r--src/share/vm/opto/split_if.cpp2
-rw-r--r--src/share/vm/opto/subnode.cpp4
-rw-r--r--src/share/vm/opto/subnode.hpp2
-rw-r--r--src/share/vm/opto/superword.cpp1
-rw-r--r--src/share/vm/opto/type.cpp222
-rw-r--r--src/share/vm/opto/type.hpp138
53 files changed, 613 insertions, 307 deletions
diff --git a/src/share/vm/opto/addnode.cpp b/src/share/vm/opto/addnode.cpp
index b3b92ec2c..6e5499028 100644
--- a/src/share/vm/opto/addnode.cpp
+++ b/src/share/vm/opto/addnode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
diff --git a/src/share/vm/opto/block.cpp b/src/share/vm/opto/block.cpp
index 60b0aa9da..70f00ca50 100644
--- a/src/share/vm/opto/block.cpp
+++ b/src/share/vm/opto/block.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
diff --git a/src/share/vm/opto/block.hpp b/src/share/vm/opto/block.hpp
index e3d8d3ef0..d0d67b7fc 100644
--- a/src/share/vm/opto/block.hpp
+++ b/src/share/vm/opto/block.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
diff --git a/src/share/vm/opto/bytecodeInfo.cpp b/src/share/vm/opto/bytecodeInfo.cpp
index 00632a239..1c08a6ebf 100644
--- a/src/share/vm/opto/bytecodeInfo.cpp
+++ b/src/share/vm/opto/bytecodeInfo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, 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
@@ -439,9 +439,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
WarmCallInfo wci = *(initial_wci);
failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci);
if (failure_msg != NULL && C->log() != NULL) {
- C->log()->begin_elem("inline_fail reason='");
- C->log()->text("%s", failure_msg);
- C->log()->end_elem("'");
+ C->log()->inline_fail(failure_msg);
}
#ifndef PRODUCT
diff --git a/src/share/vm/opto/callGenerator.hpp b/src/share/vm/opto/callGenerator.hpp
index a578a4258..3cfd39df6 100644
--- a/src/share/vm/opto/callGenerator.hpp
+++ b/src/share/vm/opto/callGenerator.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
diff --git a/src/share/vm/opto/cfgnode.cpp b/src/share/vm/opto/cfgnode.cpp
index a85cd34c7..24d51afd2 100644
--- a/src/share/vm/opto/cfgnode.cpp
+++ b/src/share/vm/opto/cfgnode.cpp
@@ -1386,7 +1386,7 @@ static Node* split_flow_path(PhaseGVN *phase, PhiNode *phi) {
Node *n = phi->in(i);
if( !n ) return NULL;
if( phase->type(n) == Type::TOP ) return NULL;
- if( n->Opcode() == Op_ConP || n->Opcode() == Op_ConN )
+ if( n->Opcode() == Op_ConP || n->Opcode() == Op_ConN || n->Opcode() == Op_ConNKlass )
break;
}
if( i >= phi->req() ) // Only split for constants
@@ -1875,17 +1875,19 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
#ifdef _LP64
- // Push DecodeN down through phi.
+ // Push DecodeN/DecodeNKlass down through phi.
// The rest of phi graph will transform by split EncodeP node though phis up.
- if (UseCompressedOops && can_reshape && progress == NULL) {
+ if ((UseCompressedOops || UseCompressedKlassPointers) && can_reshape && progress == NULL) {
bool may_push = true;
bool has_decodeN = false;
+ bool is_decodeN = false;
for (uint i=1; i<req(); ++i) {// For all paths in
Node *ii = in(i);
- if (ii->is_DecodeN() && ii->bottom_type() == bottom_type()) {
+ if (ii->is_DecodeNarrowPtr() && ii->bottom_type() == bottom_type()) {
// Do optimization if a non dead path exist.
if (ii->in(1)->bottom_type() != Type::TOP) {
has_decodeN = true;
+ is_decodeN = ii->is_DecodeN();
}
} else if (!ii->is_Phi()) {
may_push = false;
@@ -1895,13 +1897,18 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (has_decodeN && may_push) {
PhaseIterGVN *igvn = phase->is_IterGVN();
// Make narrow type for new phi.
- const Type* narrow_t = TypeNarrowOop::make(this->bottom_type()->is_ptr());
+ const Type* narrow_t;
+ if (is_decodeN) {
+ narrow_t = TypeNarrowOop::make(this->bottom_type()->is_ptr());
+ } else {
+ narrow_t = TypeNarrowKlass::make(this->bottom_type()->is_ptr());
+ }
PhiNode* new_phi = new (phase->C) PhiNode(r, narrow_t);
uint orig_cnt = req();
for (uint i=1; i<req(); ++i) {// For all paths in
Node *ii = in(i);
Node* new_ii = NULL;
- if (ii->is_DecodeN()) {
+ if (ii->is_DecodeNarrowPtr()) {
assert(ii->bottom_type() == bottom_type(), "sanity");
new_ii = ii->in(1);
} else {
@@ -1909,14 +1916,22 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (ii->as_Phi() == this) {
new_ii = new_phi;
} else {
- new_ii = new (phase->C) EncodePNode(ii, narrow_t);
+ if (is_decodeN) {
+ new_ii = new (phase->C) EncodePNode(ii, narrow_t);
+ } else {
+ new_ii = new (phase->C) EncodePKlassNode(ii, narrow_t);
+ }
igvn->register_new_node_with_optimizer(new_ii);
}
}
new_phi->set_req(i, new_ii);
}
igvn->register_new_node_with_optimizer(new_phi, this);
- progress = new (phase->C) DecodeNNode(new_phi, bottom_type());
+ if (is_decodeN) {
+ progress = new (phase->C) DecodeNNode(new_phi, bottom_type());
+ } else {
+ progress = new (phase->C) DecodeNKlassNode(new_phi, bottom_type());
+ }
}
}
#endif
diff --git a/src/share/vm/opto/classes.hpp b/src/share/vm/opto/classes.hpp
index ea5ea33f4..3f726991d 100644
--- a/src/share/vm/opto/classes.hpp
+++ b/src/share/vm/opto/classes.hpp
@@ -91,6 +91,7 @@ macro(GetAndSetP)
macro(GetAndSetN)
macro(Con)
macro(ConN)
+macro(ConNKlass)
macro(ConD)
macro(ConF)
macro(ConI)
@@ -118,6 +119,7 @@ macro(CountTrailingZerosI)
macro(CountTrailingZerosL)
macro(CreateEx)
macro(DecodeN)
+macro(DecodeNKlass)
macro(DivD)
macro(DivF)
macro(DivI)
@@ -126,6 +128,7 @@ macro(DivMod)
macro(DivModI)
macro(DivModL)
macro(EncodeP)
+macro(EncodePKlass)
macro(ExpD)
macro(FastLock)
macro(FastUnlock)
@@ -147,7 +150,6 @@ macro(LoadD)
macro(LoadD_unaligned)
macro(LoadF)
macro(LoadI)
-macro(LoadUI2L)
macro(LoadKlass)
macro(LoadNKlass)
macro(LoadL)
@@ -233,6 +235,7 @@ macro(StoreI)
macro(StoreL)
macro(StoreP)
macro(StoreN)
+macro(StoreNKlass)
macro(StrComp)
macro(StrEquals)
macro(StrIndexOf)
diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp
index 36933f976..d870872a9 100644
--- a/src/share/vm/opto/compile.cpp
+++ b/src/share/vm/opto/compile.cpp
@@ -828,6 +828,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
has_unsafe_access(),
SharedRuntime::is_wide_vector(max_vector_size())
);
+
+ if (log() != NULL) // Print code cache state into compiler log
+ log()->code_cache_state();
}
}
@@ -2236,6 +2239,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
nop != Op_CreateEx &&
nop != Op_CheckCastPP &&
nop != Op_DecodeN &&
+ nop != Op_DecodeNKlass &&
!n->is_Mem() ) {
Node *x = n->clone();
call->set_req( TypeFunc::Parms, x );
@@ -2284,11 +2288,11 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
case Op_GetAndSetN:
case Op_StoreP:
case Op_StoreN:
+ case Op_StoreNKlass:
case Op_LoadB:
case Op_LoadUB:
case Op_LoadUS:
case Op_LoadI:
- case Op_LoadUI2L:
case Op_LoadKlass:
case Op_LoadNKlass:
case Op_LoadL:
@@ -2318,7 +2322,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
addp->in(AddPNode::Base) == n->in(AddPNode::Base),
"Base pointers must match" );
#ifdef _LP64
- if (UseCompressedOops &&
+ if ((UseCompressedOops || UseCompressedKlassPointers) &&
addp->Opcode() == Op_ConP &&
addp == n->in(AddPNode::Base) &&
n->in(AddPNode::Offset)->is_Con()) {
@@ -2327,16 +2331,18 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
// instructions (4) then load 64-bits constant (7).
// Do this transformation here since IGVN will convert ConN back to ConP.
const Type* t = addp->bottom_type();
- if (t->isa_oopptr()) {
+ if (t->isa_oopptr() || t->isa_klassptr()) {
Node* nn = NULL;
+ int op = t->isa_oopptr() ? Op_ConN : Op_ConNKlass;
+
// Look for existing ConN node of the same exact type.
Compile* C = Compile::current();
Node* r = C->root();
uint cnt = r->outcnt();
for (uint i = 0; i < cnt; i++) {
Node* m = r->raw_out(i);
- if (m!= NULL && m->Opcode() == Op_ConN &&
+ if (m!= NULL && m->Opcode() == op &&
m->bottom_type()->make_ptr() == t) {
nn = m;
break;
@@ -2345,7 +2351,11 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
if (nn != NULL) {
// Decode a narrow oop to match address
// [R12 + narrow_oop_reg<<3 + offset]
- nn = new (C) DecodeNNode(nn, t);
+ if (t->isa_oopptr()) {
+ nn = new (C) DecodeNNode(nn, t);
+ } else {
+ nn = new (C) DecodeNKlassNode(nn, t);
+ }
n->set_req(AddPNode::Base, nn);
n->set_req(AddPNode::Address, nn);
if (addp->outcnt() == 0) {
@@ -2400,22 +2410,24 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
case Op_CmpP:
// Do this transformation here to preserve CmpPNode::sub() and
// other TypePtr related Ideal optimizations (for example, ptr nullness).
- if (n->in(1)->is_DecodeN() || n->in(2)->is_DecodeN()) {
+ if (n->in(1)->is_DecodeNarrowPtr() || n->in(2)->is_DecodeNarrowPtr()) {
Node* in1 = n->in(1);
Node* in2 = n->in(2);
- if (!in1->is_DecodeN()) {
+ if (!in1->is_DecodeNarrowPtr()) {
in2 = in1;
in1 = n->in(2);
}
- assert(in1->is_DecodeN(), "sanity");
+ assert(in1->is_DecodeNarrowPtr(), "sanity");
Compile* C = Compile::current();
Node* new_in2 = NULL;
- if (in2->is_DecodeN()) {
+ if (in2->is_DecodeNarrowPtr()) {
+ assert(in2->Opcode() == in1->Opcode(), "must be same node type");
new_in2 = in2->in(1);
} else if (in2->Opcode() == Op_ConP) {
const Type* t = in2->bottom_type();
if (t == TypePtr::NULL_PTR) {
+ assert(in1->is_DecodeN(), "compare klass to null?");
// Don't convert CmpP null check into CmpN if compressed
// oops implicit null check is not generated.
// This will allow to generate normal oop implicit null check.
@@ -2460,6 +2472,8 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
//
} else if (t->isa_oopptr()) {
new_in2 = ConNode::make(C, t->make_narrowoop());
+ } else if (t->isa_klassptr()) {
+ new_in2 = ConNode::make(C, t->make_narrowklass());
}
}
if (new_in2 != NULL) {
@@ -2476,23 +2490,28 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
break;
case Op_DecodeN:
- assert(!n->in(1)->is_EncodeP(), "should be optimized out");
+ case Op_DecodeNKlass:
+ assert(!n->in(1)->is_EncodeNarrowPtr(), "should be optimized out");
// DecodeN could be pinned when it can't be fold into
// an address expression, see the code for Op_CastPP above.
- assert(n->in(0) == NULL || !Matcher::narrow_oop_use_complex_address(), "no control");
+ assert(n->in(0) == NULL || (UseCompressedOops && !Matcher::narrow_oop_use_complex_address()), "no control");
break;
- case Op_EncodeP: {
+ case Op_EncodeP:
+ case Op_EncodePKlass: {
Node* in1 = n->in(1);
- if (in1->is_DecodeN()) {
+ if (in1->is_DecodeNarrowPtr()) {
n->subsume_by(in1->in(1));
} else if (in1->Opcode() == Op_ConP) {
Compile* C = Compile::current();
const Type* t = in1->bottom_type();
if (t == TypePtr::NULL_PTR) {
+ assert(t->isa_oopptr(), "null klass?");
n->subsume_by(ConNode::make(C, TypeNarrowOop::NULL_PTR));
} else if (t->isa_oopptr()) {
n->subsume_by(ConNode::make(C, t->make_narrowoop()));
+ } else if (t->isa_klassptr()) {
+ n->subsume_by(ConNode::make(C, t->make_narrowklass()));
}
}
if (in1->outcnt() == 0) {
@@ -2526,7 +2545,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
}
case Op_Phi:
- if (n->as_Phi()->bottom_type()->isa_narrowoop()) {
+ if (n->as_Phi()->bottom_type()->isa_narrowoop() || n->as_Phi()->bottom_type()->isa_narrowklass()) {
// The EncodeP optimization may create Phi with the same edges
// for all paths. It is not handled well by Register Allocator.
Node* unique_in = n->in(1);
@@ -2689,12 +2708,13 @@ static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Re
}
// Skip next transformation if compressed oops are not used.
- if (!UseCompressedOops || !Matcher::gen_narrow_oop_implicit_null_checks())
+ if ((UseCompressedOops && !Matcher::gen_narrow_oop_implicit_null_checks()) ||
+ (!UseCompressedOops && !UseCompressedKlassPointers))
return;
- // Go over safepoints nodes to skip DecodeN nodes for debug edges.
+ // Go over safepoints nodes to skip DecodeN/DecodeNKlass nodes for debug edges.
// It could be done for an uncommon traps or any safepoints/calls
- // if the DecodeN node is referenced only in a debug info.
+ // if the DecodeN/DecodeNKlass node is referenced only in a debug info.
while (sfpt.size() > 0) {
n = sfpt.pop();
JVMState *jvms = n->as_SafePoint()->jvms();
@@ -2705,7 +2725,7 @@ static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Re
n->as_CallStaticJava()->uncommon_trap_request() != 0);
for (int j = start; j < end; j++) {
Node* in = n->in(j);
- if (in->is_DecodeN()) {
+ if (in->is_DecodeNarrowPtr()) {
bool safe_to_skip = true;
if (!is_uncommon ) {
// Is it safe to skip?
diff --git a/src/share/vm/opto/connode.cpp b/src/share/vm/opto/connode.cpp
index a2da3ee46..3ba08ae5c 100644
--- a/src/share/vm/opto/connode.cpp
+++ b/src/share/vm/opto/connode.cpp
@@ -45,16 +45,17 @@ uint ConNode::hash() const {
//------------------------------make-------------------------------------------
ConNode *ConNode::make( Compile* C, const Type *t ) {
switch( t->basic_type() ) {
- case T_INT: return new (C) ConINode( t->is_int() );
- case T_LONG: return new (C) ConLNode( t->is_long() );
- case T_FLOAT: return new (C) ConFNode( t->is_float_constant() );
- case T_DOUBLE: return new (C) ConDNode( t->is_double_constant() );
- case T_VOID: return new (C) ConNode ( Type::TOP );
- case T_OBJECT: return new (C) ConPNode( t->is_ptr() );
- case T_ARRAY: return new (C) ConPNode( t->is_aryptr() );
- case T_ADDRESS: return new (C) ConPNode( t->is_ptr() );
- case T_NARROWOOP: return new (C) ConNNode( t->is_narrowoop() );
- case T_METADATA: return new (C) ConPNode( t->is_ptr() );
+ case T_INT: return new (C) ConINode( t->is_int() );
+ case T_LONG: return new (C) ConLNode( t->is_long() );
+ case T_FLOAT: return new (C) ConFNode( t->is_float_constant() );
+ case T_DOUBLE: return new (C) ConDNode( t->is_double_constant() );
+ case T_VOID: return new (C) ConNode ( Type::TOP );
+ case T_OBJECT: return new (C) ConPNode( t->is_ptr() );
+ case T_ARRAY: return new (C) ConPNode( t->is_aryptr() );
+ case T_ADDRESS: return new (C) ConPNode( t->is_ptr() );
+ case T_NARROWOOP: return new (C) ConNNode( t->is_narrowoop() );
+ case T_NARROWKLASS: return new (C) ConNKlassNode( t->is_narrowklass() );
+ case T_METADATA: return new (C) ConPNode( t->is_ptr() );
// Expected cases: TypePtr::NULL_PTR, any is_rawptr()
// Also seen: AnyPtr(TopPTR *+top); from command line:
// r -XX:+PrintOpto -XX:CIStart=285 -XX:+CompileTheWorld -XX:CompileTheWorldStartAt=660
@@ -447,7 +448,7 @@ Node *ConstraintCastNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
// If not converting int->oop, throw away cast after constant propagation
Node *CastPPNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
const Type *t = ccp->type(in(1));
- if (!t->isa_oop_ptr() || (in(1)->is_DecodeN() && Matcher::gen_narrow_oop_implicit_null_checks())) {
+ if (!t->isa_oop_ptr() || ((in(1)->is_DecodeN()) && Matcher::gen_narrow_oop_implicit_null_checks())) {
return NULL; // do not transform raw pointers or narrow oops
}
return ConstraintCastNode::Ideal_DU_postCCP(ccp);
@@ -607,15 +608,56 @@ const Type *EncodePNode::Value( PhaseTransform *phase ) const {
if (t == Type::TOP) return Type::TOP;
if (t == TypePtr::NULL_PTR) return TypeNarrowOop::NULL_PTR;
- assert(t->isa_oop_ptr() || UseCompressedKlassPointers && t->isa_klassptr(), "only oopptr here");
+ assert(t->isa_oop_ptr(), "only oopptr here");
return t->make_narrowoop();
}
-Node *EncodePNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
+Node *EncodeNarrowPtrNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
return MemNode::Ideal_common_DU_postCCP(ccp, this, in(1));
}
+Node* DecodeNKlassNode::Identity(PhaseTransform* phase) {
+ const Type *t = phase->type( in(1) );
+ if( t == Type::TOP ) return in(1);
+
+ if (in(1)->is_EncodePKlass()) {
+ // (DecodeNKlass (EncodePKlass p)) -> p
+ return in(1)->in(1);
+ }
+ return this;
+}
+
+const Type *DecodeNKlassNode::Value( PhaseTransform *phase ) const {
+ const Type *t = phase->type( in(1) );
+ if (t == Type::TOP) return Type::TOP;
+ assert(t != TypeNarrowKlass::NULL_PTR, "null klass?");
+
+ assert(t->isa_narrowklass(), "only narrow klass ptr here");
+ return t->make_ptr();
+}
+
+Node* EncodePKlassNode::Identity(PhaseTransform* phase) {
+ const Type *t = phase->type( in(1) );
+ if( t == Type::TOP ) return in(1);
+
+ if (in(1)->is_DecodeNKlass()) {
+ // (EncodePKlass (DecodeNKlass p)) -> p
+ return in(1)->in(1);
+ }
+ return this;
+}
+
+const Type *EncodePKlassNode::Value( PhaseTransform *phase ) const {
+ const Type *t = phase->type( in(1) );
+ if (t == Type::TOP) return Type::TOP;
+ assert (t != TypePtr::NULL_PTR, "null klass?");
+
+ assert(UseCompressedKlassPointers && t->isa_klassptr(), "only klass ptr here");
+ return t->make_narrowklass();
+}
+
+
//=============================================================================
//------------------------------Identity---------------------------------------
Node *Conv2BNode::Identity( PhaseTransform *phase ) {
diff --git a/src/share/vm/opto/connode.hpp b/src/share/vm/opto/connode.hpp
index 2f8c79aac..53ff820d8 100644
--- a/src/share/vm/opto/connode.hpp
+++ b/src/share/vm/opto/connode.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -88,6 +88,14 @@ public:
virtual int Opcode() const;
};
+//------------------------------ConNKlassNode---------------------------------
+// Simple narrow klass constants
+class ConNKlassNode : public ConNode {
+public:
+ ConNKlassNode( const TypeNarrowKlass *t ) : ConNode(t) {}
+ virtual int Opcode() const;
+};
+
//------------------------------ConLNode---------------------------------------
// Simple long constants
@@ -270,42 +278,91 @@ public:
};
+//------------------------------EncodeNarrowPtr--------------------------------
+class EncodeNarrowPtrNode : public TypeNode {
+ protected:
+ EncodeNarrowPtrNode(Node* value, const Type* type):
+ TypeNode(type, 2) {
+ init_class_id(Class_EncodeNarrowPtr);
+ init_req(0, NULL);
+ init_req(1, value);
+ }
+ public:
+ virtual uint ideal_reg() const { return Op_RegN; }
+ virtual Node *Ideal_DU_postCCP( PhaseCCP *ccp );
+};
+
//------------------------------EncodeP--------------------------------
// Encodes an oop pointers into its compressed form
// Takes an extra argument which is the real heap base as a long which
// may be useful for code generation in the backend.
-class EncodePNode : public TypeNode {
+class EncodePNode : public EncodeNarrowPtrNode {
public:
EncodePNode(Node* value, const Type* type):
- TypeNode(type, 2) {
+ EncodeNarrowPtrNode(value, type) {
init_class_id(Class_EncodeP);
- init_req(0, NULL);
- init_req(1, value);
}
virtual int Opcode() const;
virtual Node *Identity( PhaseTransform *phase );
virtual const Type *Value( PhaseTransform *phase ) const;
- virtual uint ideal_reg() const { return Op_RegN; }
+};
- virtual Node *Ideal_DU_postCCP( PhaseCCP *ccp );
+//------------------------------EncodePKlass--------------------------------
+// Encodes a klass pointer into its compressed form
+// Takes an extra argument which is the real heap base as a long which
+// may be useful for code generation in the backend.
+class EncodePKlassNode : public EncodeNarrowPtrNode {
+ public:
+ EncodePKlassNode(Node* value, const Type* type):
+ EncodeNarrowPtrNode(value, type) {
+ init_class_id(Class_EncodePKlass);
+ }
+ virtual int Opcode() const;
+ virtual Node *Identity( PhaseTransform *phase );
+ virtual const Type *Value( PhaseTransform *phase ) const;
+};
+
+//------------------------------DecodeNarrowPtr--------------------------------
+class DecodeNarrowPtrNode : public TypeNode {
+ protected:
+ DecodeNarrowPtrNode(Node* value, const Type* type):
+ TypeNode(type, 2) {
+ init_class_id(Class_DecodeNarrowPtr);
+ init_req(0, NULL);
+ init_req(1, value);
+ }
+ public:
+ virtual uint ideal_reg() const { return Op_RegP; }
};
//------------------------------DecodeN--------------------------------
// Converts a narrow oop into a real oop ptr.
// Takes an extra argument which is the real heap base as a long which
// may be useful for code generation in the backend.
-class DecodeNNode : public TypeNode {
+class DecodeNNode : public DecodeNarrowPtrNode {
public:
DecodeNNode(Node* value, const Type* type):
- TypeNode(type, 2) {
+ DecodeNarrowPtrNode(value, type) {
init_class_id(Class_DecodeN);
- init_req(0, NULL);
- init_req(1, value);
}
virtual int Opcode() const;
+ virtual const Type *Value( PhaseTransform *phase ) const;
virtual Node *Identity( PhaseTransform *phase );
+};
+
+//------------------------------DecodeNKlass--------------------------------
+// Converts a narrow klass pointer into a real klass ptr.
+// Takes an extra argument which is the real heap base as a long which
+// may be useful for code generation in the backend.
+class DecodeNKlassNode : public DecodeNarrowPtrNode {
+ public:
+ DecodeNKlassNode(Node* value, const Type* type):
+ DecodeNarrowPtrNode(value, type) {
+ init_class_id(Class_DecodeNKlass);
+ }
+ virtual int Opcode() const;
virtual const Type *Value( PhaseTransform *phase ) const;
- virtual uint ideal_reg() const { return Op_RegP; }
+ virtual Node *Identity( PhaseTransform *phase );
};
//------------------------------Conv2BNode-------------------------------------
diff --git a/src/share/vm/opto/divnode.cpp b/src/share/vm/opto/divnode.cpp
index c22241242..24f4fcb7e 100644
--- a/src/share/vm/opto/divnode.cpp
+++ b/src/share/vm/opto/divnode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
diff --git a/src/share/vm/opto/domgraph.cpp b/src/share/vm/opto/domgraph.cpp
index b3a367d53..9973cb562 100644
--- a/src/share/vm/opto/domgraph.cpp
+++ b/src/share/vm/opto/domgraph.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
diff --git a/src/share/vm/opto/escape.cpp b/src/share/vm/opto/escape.cpp
index 85d40b0d3..9fd318050 100644
--- a/src/share/vm/opto/escape.cpp
+++ b/src/share/vm/opto/escape.cpp
@@ -368,7 +368,9 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de
case Op_CastPP:
case Op_CheckCastPP:
case Op_EncodeP:
- case Op_DecodeN: {
+ case Op_DecodeN:
+ case Op_EncodePKlass:
+ case Op_DecodeNKlass: {
add_local_var_and_edge(n, PointsToNode::NoEscape,
n->in(1), delayed_worklist);
break;
@@ -381,7 +383,8 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de
break;
}
case Op_ConP:
- case Op_ConN: {
+ case Op_ConN:
+ case Op_ConNKlass: {
// assume all oop constants globally escape except for null
PointsToNode::EscapeState es;
if (igvn->type(n) == TypePtr::NULL_PTR ||
@@ -458,6 +461,7 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de
}
case Op_StoreP:
case Op_StoreN:
+ case Op_StoreNKlass:
case Op_StorePConditional:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN: {
@@ -465,7 +469,7 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de
const Type *adr_type = igvn->type(adr);
adr_type = adr_type->make_ptr();
if (adr_type->isa_oopptr() ||
- (opcode == Op_StoreP || opcode == Op_StoreN) &&
+ (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) &&
(adr_type == TypeRawPtr::NOTNULL &&
adr->in(AddPNode::Address)->is_Proj() &&
adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
@@ -572,7 +576,9 @@ void ConnectionGraph::add_final_edges(Node *n) {
case Op_CastPP:
case Op_CheckCastPP:
case Op_EncodeP:
- case Op_DecodeN: {
+ case Op_DecodeN:
+ case Op_EncodePKlass:
+ case Op_DecodeNKlass: {
add_local_var_and_edge(n, PointsToNode::NoEscape,
n->in(1), NULL);
break;
@@ -646,6 +652,7 @@ void ConnectionGraph::add_final_edges(Node *n) {
}
case Op_StoreP:
case Op_StoreN:
+ case Op_StoreNKlass:
case Op_StorePConditional:
case Op_CompareAndSwapP:
case Op_CompareAndSwapN:
@@ -661,7 +668,7 @@ void ConnectionGraph::add_final_edges(Node *n) {
const Type *adr_type = _igvn->type(adr);
adr_type = adr_type->make_ptr();
if (adr_type->isa_oopptr() ||
- (opcode == Op_StoreP || opcode == Op_StoreN) &&
+ (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) &&
(adr_type == TypeRawPtr::NOTNULL &&
adr->in(AddPNode::Address)->is_Proj() &&
adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
@@ -2088,7 +2095,7 @@ Node* ConnectionGraph::get_addp_base(Node *addp) {
Node* uncast_base = base->uncast();
int opcode = uncast_base->Opcode();
assert(opcode == Op_ConP || opcode == Op_ThreadLocal ||
- opcode == Op_CastX2P || uncast_base->is_DecodeN() ||
+ opcode == Op_CastX2P || uncast_base->is_DecodeNarrowPtr() ||
(uncast_base->is_Mem() && uncast_base->bottom_type() == TypeRawPtr::NOTNULL) ||
(uncast_base->is_Proj() && uncast_base->in(0)->is_Allocate()), "sanity");
}
@@ -2837,8 +2844,8 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
alloc_worklist.append_if_missing(use);
} else if (use->is_Phi() ||
use->is_CheckCastPP() ||
- use->is_EncodeP() ||
- use->is_DecodeN() ||
+ use->is_EncodeNarrowPtr() ||
+ use->is_DecodeNarrowPtr() ||
(use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) {
alloc_worklist.append_if_missing(use);
#ifdef ASSERT
diff --git a/src/share/vm/opto/gcm.cpp b/src/share/vm/opto/gcm.cpp
index 8b8f31157..6cd2ecd23 100644
--- a/src/share/vm/opto/gcm.cpp
+++ b/src/share/vm/opto/gcm.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
diff --git a/src/share/vm/opto/generateOptoStub.cpp b/src/share/vm/opto/generateOptoStub.cpp
index 032f0081d..56fc759f2 100644
--- a/src/share/vm/opto/generateOptoStub.cpp
+++ b/src/share/vm/opto/generateOptoStub.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp
index 53130fd45..95d5357d7 100644
--- a/src/share/vm/opto/graphKit.cpp
+++ b/src/share/vm/opto/graphKit.cpp
@@ -1115,7 +1115,7 @@ Node* GraphKit::ConvI2L(Node* offset) {
// short-circuit a common case
jint offset_con = find_int_con(offset, Type::OffsetBot);
if (offset_con != Type::OffsetBot) {
- return longcon((long) offset_con);
+ return longcon((jlong) offset_con);
}
return _gvn.transform( new (C) ConvI2LNode(offset));
}
diff --git a/src/share/vm/opto/idealKit.cpp b/src/share/vm/opto/idealKit.cpp
index 9083c6206..986f2e178 100644
--- a/src/share/vm/opto/idealKit.cpp
+++ b/src/share/vm/opto/idealKit.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
diff --git a/src/share/vm/opto/idealKit.hpp b/src/share/vm/opto/idealKit.hpp
index c6cc3c2af..15e4274db 100644
--- a/src/share/vm/opto/idealKit.hpp
+++ b/src/share/vm/opto/idealKit.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
diff --git a/src/share/vm/opto/ifnode.cpp b/src/share/vm/opto/ifnode.cpp
index bc9106b53..b506a03f5 100644
--- a/src/share/vm/opto/ifnode.cpp
+++ b/src/share/vm/opto/ifnode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
diff --git a/src/share/vm/opto/lcm.cpp b/src/share/vm/opto/lcm.cpp
index 4cca9c580..24a6a3182 100644
--- a/src/share/vm/opto/lcm.cpp
+++ b/src/share/vm/opto/lcm.cpp
@@ -164,6 +164,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe
case Op_StoreL:
case Op_StoreP:
case Op_StoreN:
+ case Op_StoreNKlass:
was_store = true; // Memory op is a store op
// Stores will have their address in slot 2 (memory in slot 1).
// If the value being nul-checked is in another slot, it means we
diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp
index 386662e15..f34df79b4 100644
--- a/src/share/vm/opto/library_call.cpp
+++ b/src/share/vm/opto/library_call.cpp
@@ -2378,13 +2378,15 @@ const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_
}
}
- if (sharpened_klass != NULL) {
+ // The sharpened class might be unloaded if there is no class loader
+ // contraint in place.
+ if (sharpened_klass != NULL && sharpened_klass->is_loaded()) {
const TypeOopPtr* tjp = TypeOopPtr::make_from_klass(sharpened_klass);
#ifndef PRODUCT
if (PrintIntrinsics || PrintInlining || PrintOptoInlining) {
- tty->print(" from base type: "); adr_type->dump();
- tty->print(" sharpened value: "); tjp->dump();
+ tty->print(" from base type: "); adr_type->dump();
+ tty->print(" sharpened value: "); tjp->dump();
}
#endif
// Sharpen the value type.
@@ -3435,7 +3437,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) {
if (generate_array_guard(kls, region) != NULL) {
// Be sure to pin the oop load to the guard edge just created:
Node* is_array_ctrl = region->in(region->req()-1);
- Node* cma = basic_plus_adr(kls, in_bytes(arrayKlass::component_mirror_offset()));
+ Node* cma = basic_plus_adr(kls, in_bytes(ArrayKlass::component_mirror_offset()));
Node* cmo = make_load(is_array_ctrl, cma, TypeInstPtr::MIRROR, T_OBJECT);
phi->add_req(cmo);
}
@@ -4381,7 +4383,7 @@ void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, b
// 12 - 64-bit VM, compressed klass
// 16 - 64-bit VM, normal klass
if (base_off % BytesPerLong != 0) {
- assert(UseCompressedOops, "");
+ assert(UseCompressedKlassPointers, "");
if (is_array) {
// Exclude length to copy by 8 bytes words.
base_off += sizeof(int);
@@ -5032,7 +5034,7 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type,
PreserveJVMState pjvms(this);
set_control(not_subtype_ctrl);
// (At this point we can assume disjoint_bases, since types differ.)
- int ek_offset = in_bytes(objArrayKlass::element_klass_offset());
+ int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset());
Node* p1 = basic_plus_adr(dest_klass, ek_offset);
Node* n1 = LoadKlassNode::make(_gvn, immutable_memory(), p1, TypeRawPtr::BOTTOM);
Node* dest_elem_klass = _gvn.transform(n1);
diff --git a/src/share/vm/opto/live.cpp b/src/share/vm/opto/live.cpp
index cdeed3b1f..5da418915 100644
--- a/src/share/vm/opto/live.cpp
+++ b/src/share/vm/opto/live.cpp
@@ -331,6 +331,7 @@ void PhaseChaitin::verify_base_ptrs( ResourceArea *a ) const {
#ifdef _LP64
UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_CastPP ||
UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_DecodeN ||
+ UseCompressedKlassPointers && check->as_Mach()->ideal_Opcode() == Op_DecodeNKlass ||
#endif
check->as_Mach()->ideal_Opcode() == Op_LoadP ||
check->as_Mach()->ideal_Opcode() == Op_LoadKlass)) {
diff --git a/src/share/vm/opto/locknode.cpp b/src/share/vm/opto/locknode.cpp
index 4147ed33d..1e6a6c20c 100644
--- a/src/share/vm/opto/locknode.cpp
+++ b/src/share/vm/opto/locknode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
diff --git a/src/share/vm/opto/locknode.hpp b/src/share/vm/opto/locknode.hpp
index 91b99bc00..b11486590 100644
--- a/src/share/vm/opto/locknode.hpp
+++ b/src/share/vm/opto/locknode.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
diff --git a/src/share/vm/opto/loopPredicate.cpp b/src/share/vm/opto/loopPredicate.cpp
index 6dd45e00e..a9867a5ee 100644
--- a/src/share/vm/opto/loopPredicate.cpp
+++ b/src/share/vm/opto/loopPredicate.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, 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
diff --git a/src/share/vm/opto/loopTransform.cpp b/src/share/vm/opto/loopTransform.cpp
index f4903e952..53d0fffdc 100644
--- a/src/share/vm/opto/loopTransform.cpp
+++ b/src/share/vm/opto/loopTransform.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -92,10 +92,10 @@ void IdealLoopTree::compute_exact_trip_count( PhaseIdealLoop *phase ) {
limit_n != NULL && limit_n->is_Con()) {
// Use longs to avoid integer overflow.
int stride_con = cl->stride_con();
- long init_con = cl->init_trip()->get_int();
- long limit_con = cl->limit()->get_int();
+ jlong init_con = cl->init_trip()->get_int();
+ jlong limit_con = cl->limit()->get_int();
int stride_m = stride_con - (stride_con > 0 ? 1 : -1);
- long trip_count = (limit_con - init_con + stride_m)/stride_con;
+ jlong trip_count = (limit_con - init_con + stride_m)/stride_con;
if (trip_count > 0 && (julong)trip_count < (julong)max_juint) {
// Set exact trip count.
cl->set_exact_trip_count((uint)trip_count);
@@ -1212,16 +1212,16 @@ void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad
} else if (loop_head->has_exact_trip_count() && init->is_Con()) {
// Loop's limit is constant. Loop's init could be constant when pre-loop
// become peeled iteration.
- long init_con = init->get_int();
+ jlong init_con = init->get_int();
// We can keep old loop limit if iterations count stays the same:
// old_trip_count == new_trip_count * 2
// Note: since old_trip_count >= 2 then new_trip_count >= 1
// so we also don't need to adjust zero trip test.
- long limit_con = limit->get_int();
+ jlong limit_con = limit->get_int();
// (stride_con*2) not overflow since stride_con <= 8.
int new_stride_con = stride_con * 2;
int stride_m = new_stride_con - (stride_con > 0 ? 1 : -1);
- long trip_count = (limit_con - init_con + stride_m)/new_stride_con;
+ jlong trip_count = (limit_con - init_con + stride_m)/new_stride_con;
// New trip count should satisfy next conditions.
assert(trip_count > 0 && (julong)trip_count < (julong)max_juint/2, "sanity");
uint new_trip_count = (uint)trip_count;
@@ -2413,7 +2413,7 @@ bool PhaseIdealLoop::match_fill_loop(IdealLoopTree* lpt, Node*& store, Node*& st
break;
}
int opc = n->Opcode();
- if (opc == Op_StoreP || opc == Op_StoreN || opc == Op_StoreCM) {
+ if (opc == Op_StoreP || opc == Op_StoreN || opc == Op_StoreNKlass || opc == Op_StoreCM) {
msg = "oop fills not handled";
break;
}
diff --git a/src/share/vm/opto/loopUnswitch.cpp b/src/share/vm/opto/loopUnswitch.cpp
index 1470598fc..fc3380f49 100644
--- a/src/share/vm/opto/loopUnswitch.cpp
+++ b/src/share/vm/opto/loopUnswitch.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, 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
diff --git a/src/share/vm/opto/loopnode.cpp b/src/share/vm/opto/loopnode.cpp
index 631e39a70..a483f0180 100644
--- a/src/share/vm/opto/loopnode.cpp
+++ b/src/share/vm/opto/loopnode.cpp
@@ -328,12 +328,12 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
const TypeInt* limit_t = gvn->type(limit)->is_int();
if (stride_con > 0) {
- long init_p = (long)init_t->_lo + stride_con;
- if (init_p > (long)max_jint || init_p > (long)limit_t->_hi)
+ jlong init_p = (jlong)init_t->_lo + stride_con;
+ if (init_p > (jlong)max_jint || init_p > (jlong)limit_t->_hi)
return false; // cyclic loop or this loop trips only once
} else {
- long init_p = (long)init_t->_hi + stride_con;
- if (init_p < (long)min_jint || init_p < (long)limit_t->_lo)
+ jlong init_p = (jlong)init_t->_hi + stride_con;
+ if (init_p < (jlong)min_jint || init_p < (jlong)limit_t->_lo)
return false; // cyclic loop or this loop trips only once
}
@@ -716,16 +716,16 @@ Node* PhaseIdealLoop::exact_limit( IdealLoopTree *loop ) {
#endif
if (cl->has_exact_trip_count()) {
// Simple case: loop has constant boundaries.
- // Use longs to avoid integer overflow.
+ // Use jlongs to avoid integer overflow.
int stride_con = cl->stride_con();
- long init_con = cl->init_trip()->get_int();
- long limit_con = cl->limit()->get_int();
+ jlong init_con = cl->init_trip()->get_int();
+ jlong limit_con = cl->limit()->get_int();
julong trip_cnt = cl->trip_count();
- long final_con = init_con + trip_cnt*stride_con;
+ jlong final_con = init_con + trip_cnt*stride_con;
int final_int = (int)final_con;
// The final value should be in integer range since the loop
// is counted and the limit was checked for overflow.
- assert(final_con == (long)final_int, "final value should be integer");
+ assert(final_con == (jlong)final_int, "final value should be integer");
limit = _igvn.intcon(final_int);
} else {
// Create new LoopLimit node to get exact limit (final iv value).
@@ -790,16 +790,16 @@ const Type *LoopLimitNode::Value( PhaseTransform *phase ) const {
return NULL; // Identity
if (init_t->is_int()->is_con() && limit_t->is_int()->is_con()) {
- // Use longs to avoid integer overflow.
- long init_con = init_t->is_int()->get_con();
- long limit_con = limit_t->is_int()->get_con();
+ // Use jlongs to avoid integer overflow.
+ jlong init_con = init_t->is_int()->get_con();
+ jlong limit_con = limit_t->is_int()->get_con();
int stride_m = stride_con - (stride_con > 0 ? 1 : -1);
- long trip_count = (limit_con - init_con + stride_m)/stride_con;
- long final_con = init_con + stride_con*trip_count;
+ jlong trip_count = (limit_con - init_con + stride_m)/stride_con;
+ jlong final_con = init_con + stride_con*trip_count;
int final_int = (int)final_con;
// The final value should be in integer range since the loop
// is counted and the limit was checked for overflow.
- assert(final_con == (long)final_int, "final value should be integer");
+ assert(final_con == (jlong)final_int, "final value should be integer");
return TypeInt::make(final_int);
}
@@ -829,7 +829,7 @@ Node *LoopLimitNode::Ideal(PhaseGVN *phase, bool can_reshape) {
const TypeInt* init_t = phase->type(in(Init) )->is_int();
const TypeInt* limit_t = phase->type(in(Limit))->is_int();
int stride_p;
- long lim, ini;
+ jlong lim, ini;
julong max;
if (stride_con > 0) {
stride_p = stride_con;
diff --git a/src/share/vm/opto/loopnode.hpp b/src/share/vm/opto/loopnode.hpp
index 92f691238..42096c0da 100644
--- a/src/share/vm/opto/loopnode.hpp
+++ b/src/share/vm/opto/loopnode.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, 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
diff --git a/src/share/vm/opto/loopopts.cpp b/src/share/vm/opto/loopopts.cpp
index 5c49a0444..015a063a8 100644
--- a/src/share/vm/opto/loopopts.cpp
+++ b/src/share/vm/opto/loopopts.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -550,7 +550,7 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
// This will likely Split-If, a higher-payoff operation.
for (DUIterator_Fast kmax, k = phi->fast_outs(kmax); k < kmax; k++) {
Node* use = phi->fast_out(k);
- if (use->is_Cmp() || use->is_DecodeN() || use->is_EncodeP())
+ if (use->is_Cmp() || use->is_DecodeNarrowPtr() || use->is_EncodeNarrowPtr())
cost += ConditionalMoveLimit;
// Is there a use inside the loop?
// Note: check only basic types since CMoveP is pinned.
@@ -1006,7 +1006,7 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
// to fold a StoreP and an AddP together (as part of an
// address expression) and the AddP and StoreP have
// different controls.
- if( !x->is_Load() && !x->is_DecodeN() ) _igvn._worklist.yank(x);
+ if (!x->is_Load() && !x->is_DecodeNarrowPtr()) _igvn._worklist.yank(x);
}
_igvn.remove_dead_node(n);
}
diff --git a/src/share/vm/opto/machnode.cpp b/src/share/vm/opto/machnode.cpp
index 2a5d96369..30970102d 100644
--- a/src/share/vm/opto/machnode.cpp
+++ b/src/share/vm/opto/machnode.cpp
@@ -265,7 +265,8 @@ const Node* MachNode::get_base_and_disp(intptr_t &offset, const TypePtr* &adr_ty
// See if it adds up to a base + offset.
if (index != NULL) {
const Type* t_index = index->bottom_type();
- if (t_index->isa_narrowoop()) { // EncodeN, LoadN, LoadConN, LoadNKlass.
+ if (t_index->isa_narrowoop() || t_index->isa_narrowklass()) { // EncodeN, LoadN, LoadConN, LoadNKlass,
+ // EncodeNKlass, LoadConNklass.
// Memory references through narrow oops have a
// funny base so grab the type from the index:
// [R12 + narrow_oop_reg<<3 + offset]
@@ -352,6 +353,10 @@ const class TypePtr *MachNode::adr_type() const {
// 32-bit unscaled narrow oop can be the base of any address expression
t = t->make_ptr();
}
+ if (UseCompressedKlassPointers && Universe::narrow_klass_shift() == 0) {
+ // 32-bit unscaled narrow oop can be the base of any address expression
+ t = t->make_ptr();
+ }
if (t->isa_intptr_t() && offset != 0 && offset != Type::OffsetBot) {
// We cannot assert that the offset does not look oop-ish here.
// Depending on the heap layout the cardmark base could land
diff --git a/src/share/vm/opto/macro.cpp b/src/share/vm/opto/macro.cpp
index 90f1f0299..16987d974 100644
--- a/src/share/vm/opto/macro.cpp
+++ b/src/share/vm/opto/macro.cpp
@@ -2125,7 +2125,7 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) {
Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes());
klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) );
#ifdef _LP64
- if (UseCompressedOops && klass_node->is_DecodeN()) {
+ if (UseCompressedKlassPointers && klass_node->is_DecodeNKlass()) {
assert(klass_node->in(1)->Opcode() == Op_LoadNKlass, "sanity");
klass_node->in(1)->init_req(0, ctrl);
} else
diff --git a/src/share/vm/opto/macro.hpp b/src/share/vm/opto/macro.hpp
index b84d8d7d7..ba35c497f 100644
--- a/src/share/vm/opto/macro.hpp
+++ b/src/share/vm/opto/macro.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
diff --git a/src/share/vm/opto/matcher.cpp b/src/share/vm/opto/matcher.cpp
index 8ee42d13d..53924d0c9 100644
--- a/src/share/vm/opto/matcher.cpp
+++ b/src/share/vm/opto/matcher.cpp
@@ -1058,7 +1058,7 @@ Node *Matcher::xform( Node *n, int max_stack ) {
Node *m = n->in(i); // Get input
int op = m->Opcode();
assert((op == Op_BoxLock) == jvms->is_monitor_use(i), "boxes only at monitor sites");
- if( op == Op_ConI || op == Op_ConP || op == Op_ConN ||
+ if( op == Op_ConI || op == Op_ConP || op == Op_ConN || op == Op_ConNKlass ||
op == Op_ConF || op == Op_ConD || op == Op_ConL
// || op == Op_BoxLock // %%%% enable this and remove (+++) in chaitin.cpp
) {
@@ -1450,7 +1450,8 @@ static bool match_into_reg( const Node *n, Node *m, Node *control, int i, bool s
if (j == max_scan) // No post-domination before scan end?
return true; // Then break the match tree up
}
- if (m->is_DecodeN() && Matcher::narrow_oop_use_complex_address()) {
+ if ((m->is_DecodeN() && Matcher::narrow_oop_use_complex_address()) ||
+ (m->is_DecodeNKlass() && Matcher::narrow_klass_use_complex_address())) {
// These are commonly used in address expressions and can
// efficiently fold into them on X64 in some cases.
return false;
@@ -1574,14 +1575,14 @@ Node *Matcher::Label_Root( const Node *n, State *svec, Node *control, const Node
// program. The register allocator is free to split uses later to
// split live ranges.
MachNode* Matcher::find_shared_node(Node* leaf, uint rule) {
- if (!leaf->is_Con() && !leaf->is_DecodeN()) return NULL;
+ if (!leaf->is_Con() && !leaf->is_DecodeNarrowPtr()) return NULL;
// See if this Con has already been reduced using this rule.
if (_shared_nodes.Size() <= leaf->_idx) return NULL;
MachNode* last = (MachNode*)_shared_nodes.at(leaf->_idx);
if (last != NULL && rule == last->rule()) {
// Don't expect control change for DecodeN
- if (leaf->is_DecodeN())
+ if (leaf->is_DecodeNarrowPtr())
return last;
// Get the new space root.
Node* xroot = new_node(C->root());
@@ -1671,12 +1672,12 @@ MachNode *Matcher::ReduceInst( State *s, int rule, Node *&mem ) {
// DecodeN node consumed by an address may have different type
// then its input. Don't compare types for such case.
if (m->adr_type() != mach_at &&
- (m->in(MemNode::Address)->is_DecodeN() ||
+ (m->in(MemNode::Address)->is_DecodeNarrowPtr() ||
m->in(MemNode::Address)->is_AddP() &&
- m->in(MemNode::Address)->in(AddPNode::Address)->is_DecodeN() ||
+ m->in(MemNode::Address)->in(AddPNode::Address)->is_DecodeNarrowPtr() ||
m->in(MemNode::Address)->is_AddP() &&
m->in(MemNode::Address)->in(AddPNode::Address)->is_AddP() &&
- m->in(MemNode::Address)->in(AddPNode::Address)->in(AddPNode::Address)->is_DecodeN())) {
+ m->in(MemNode::Address)->in(AddPNode::Address)->in(AddPNode::Address)->is_DecodeNarrowPtr())) {
mach_at = m->adr_type();
}
if (m->adr_type() != mach_at) {
@@ -1721,7 +1722,7 @@ MachNode *Matcher::ReduceInst( State *s, int rule, Node *&mem ) {
guarantee(_proj_list.size() == num_proj, "no allocation during spill generation");
}
- if (leaf->is_Con() || leaf->is_DecodeN()) {
+ if (leaf->is_Con() || leaf->is_DecodeNarrowPtr()) {
// Record the con for sharing
_shared_nodes.map(leaf->_idx, ex);
}
@@ -2038,7 +2039,7 @@ void Matcher::find_shared( Node *n ) {
continue; // for(int i = ...)
}
- if( mop == Op_AddP && m->in(AddPNode::Base)->Opcode() == Op_DecodeN ) {
+ if( mop == Op_AddP && m->in(AddPNode::Base)->is_DecodeNarrowPtr()) {
// Bases used in addresses must be shared but since
// they are shared through a DecodeN they may appear
// to have a single use so force sharing here.
@@ -2277,7 +2278,7 @@ void Matcher::validate_null_checks( ) {
if (has_new_node(val)) {
Node* new_val = new_node(val);
if (is_decoden) {
- assert(val->is_DecodeN() && val->in(0) == NULL, "sanity");
+ assert(val->is_DecodeNarrowPtr() && val->in(0) == NULL, "sanity");
// Note: new_val may have a control edge if
// the original ideal node DecodeN was matched before
// it was unpinned in Matcher::collect_null_checks().
diff --git a/src/share/vm/opto/matcher.hpp b/src/share/vm/opto/matcher.hpp
index 1936ba97a..280b8ad88 100644
--- a/src/share/vm/opto/matcher.hpp
+++ b/src/share/vm/opto/matcher.hpp
@@ -380,6 +380,7 @@ public:
static const bool clone_shift_expressions;
static bool narrow_oop_use_complex_address();
+ static bool narrow_klass_use_complex_address();
// Generate implicit null check for narrow oops if it can fold
// into address expression (x64).
diff --git a/src/share/vm/opto/memnode.cpp b/src/share/vm/opto/memnode.cpp
index 657d33105..b83e6253b 100644
--- a/src/share/vm/opto/memnode.cpp
+++ b/src/share/vm/opto/memnode.cpp
@@ -714,10 +714,12 @@ Node *MemNode::Ideal_common_DU_postCCP( PhaseCCP *ccp, Node* n, Node* adr ) {
continue;
case Op_DecodeN: // No change to NULL-ness, so peek thru
+ case Op_DecodeNKlass:
adr = adr->in(1);
continue;
case Op_EncodeP:
+ case Op_EncodePKlass:
// EncodeP node's control edge could be set by this method
// when EncodeP node depends on CastPP node.
//
@@ -794,6 +796,7 @@ Node *MemNode::Ideal_common_DU_postCCP( PhaseCCP *ccp, Node* n, Node* adr ) {
case Op_LoadNKlass: // Loading from within a klass
case Op_ConP: // Loading from a klass
case Op_ConN: // Loading from a klass
+ case Op_ConNKlass: // Loading from a klass
case Op_CreateEx: // Sucking up the guts of an exception oop
case Op_Con: // Reading from TLS
case Op_CMoveP: // CMoveP is pinned
@@ -900,7 +903,7 @@ Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const Type
} else
#endif
{
- assert(!adr->bottom_type()->is_ptr_to_narrowoop(), "should have got back a narrow oop");
+ assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop");
return new (C) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr());
}
}
@@ -1671,9 +1674,9 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
}
const Type* aift = load_array_final_field(tkls, klass);
if (aift != NULL) return aift;
- if (tkls->offset() == in_bytes(arrayKlass::component_mirror_offset())
+ if (tkls->offset() == in_bytes(ArrayKlass::component_mirror_offset())
&& klass->is_array_klass()) {
- // The field is arrayKlass::_component_mirror. Return its (constant) value.
+ // The field is ArrayKlass::_component_mirror. Return its (constant) value.
// (Folds up aClassConstant.getComponentType, common in Arrays.copyOf.)
assert(Opcode() == Op_LoadP, "must load an oop from _component_mirror");
return TypeInstPtr::make(klass->as_array_klass()->component_mirror());
@@ -1894,13 +1897,13 @@ Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* a
const TypePtr *adr_type = adr->bottom_type()->isa_ptr();
assert(adr_type != NULL, "expecting TypeKlassPtr");
#ifdef _LP64
- if (adr_type->is_ptr_to_narrowoop()) {
+ if (adr_type->is_ptr_to_narrowklass()) {
assert(UseCompressedKlassPointers, "no compressed klasses");
- Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowoop()));
- return new (C) DecodeNNode(load_klass, load_klass->bottom_type()->make_ptr());
+ Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass()));
+ return new (C) DecodeNKlassNode(load_klass, load_klass->bottom_type()->make_ptr());
}
#endif
- assert(!adr_type->is_ptr_to_narrowoop(), "should have got back a narrow oop");
+ assert(!adr_type->is_ptr_to_narrowklass() && !adr_type->is_ptr_to_narrowoop(), "should have got back a narrow oop");
return new (C) LoadKlassNode(ctl, mem, adr, at, tk);
}
@@ -2014,7 +2017,7 @@ const Type *LoadNode::klass_value_common( PhaseTransform *phase ) const {
if( !klass->is_loaded() )
return _type; // Bail out if not loaded
if( klass->is_obj_array_klass() &&
- tkls->offset() == in_bytes(objArrayKlass::element_klass_offset())) {
+ tkls->offset() == in_bytes(ObjArrayKlass::element_klass_offset())) {
ciKlass* elem = klass->as_obj_array_klass()->element_klass();
// // Always returning precise element type is incorrect,
// // e.g., element type could be object and array may contain strings
@@ -2067,7 +2070,7 @@ Node* LoadNode::klass_identity_common(PhaseTransform *phase ) {
}
// Simplify k.java_mirror.as_klass to plain k, where k is a Klass*.
- // Simplify ak.component_mirror.array_klass to plain ak, ak an arrayKlass.
+ // Simplify ak.component_mirror.array_klass to plain ak, ak an ArrayKlass.
// See inline_native_Class_query for occurrences of these patterns.
// Java Example: x.getClass().isAssignableFrom(y)
// Java Example: Array.newInstance(x.getClass().getComponentType(), n)
@@ -2080,7 +2083,7 @@ Node* LoadNode::klass_identity_common(PhaseTransform *phase ) {
&& (offset == java_lang_Class::klass_offset_in_bytes() ||
offset == java_lang_Class::array_klass_offset_in_bytes())) {
// We are loading a special hidden field from a Class mirror,
- // the field which points to its Klass or arrayKlass metaobject.
+ // the field which points to its Klass or ArrayKlass metaobject.
if (base->is_Load()) {
Node* adr2 = base->in(MemNode::Address);
const TypeKlassPtr* tkls = phase->type(adr2)->isa_klassptr();
@@ -2091,7 +2094,7 @@ Node* LoadNode::klass_identity_common(PhaseTransform *phase ) {
) {
int mirror_field = in_bytes(Klass::java_mirror_offset());
if (offset == java_lang_Class::array_klass_offset_in_bytes()) {
- mirror_field = in_bytes(arrayKlass::component_mirror_offset());
+ mirror_field = in_bytes(ArrayKlass::component_mirror_offset());
}
if (tkls->offset() == mirror_field) {
return adr2->in(AddPNode::Base);
@@ -2110,7 +2113,7 @@ const Type *LoadNKlassNode::Value( PhaseTransform *phase ) const {
if (t == Type::TOP)
return t;
- return t->make_narrowoop();
+ return t->make_narrowklass();
}
//------------------------------Identity---------------------------------------
@@ -2121,9 +2124,10 @@ Node* LoadNKlassNode::Identity( PhaseTransform *phase ) {
const Type *t = phase->type( x );
if( t == Type::TOP ) return x;
- if( t->isa_narrowoop()) return x;
+ if( t->isa_narrowklass()) return x;
+ assert (!t->isa_narrowoop(), "no narrow oop here");
- return phase->transform(new (phase->C) EncodePNode(x, t->make_narrowoop()));
+ return phase->transform(new (phase->C) EncodePKlassNode(x, t->make_narrowklass()));
}
//------------------------------Value-----------------------------------------
@@ -2228,12 +2232,15 @@ StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, cons
case T_ADDRESS:
case T_OBJECT:
#ifdef _LP64
- if (adr->bottom_type()->is_ptr_to_narrowoop() ||
- (UseCompressedKlassPointers && val->bottom_type()->isa_klassptr() &&
- adr->bottom_type()->isa_rawptr())) {
+ if (adr->bottom_type()->is_ptr_to_narrowoop()) {
val = gvn.transform(new (C) EncodePNode(val, val->bottom_type()->make_narrowoop()));
return new (C) StoreNNode(ctl, mem, adr, adr_type, val);
- } else
+ } else if (adr->bottom_type()->is_ptr_to_narrowklass() ||
+ (UseCompressedKlassPointers && val->bottom_type()->isa_klassptr() &&
+ adr->bottom_type()->isa_rawptr())) {
+ val = gvn.transform(new (C) EncodePKlassNode(val, val->bottom_type()->make_narrowklass()));
+ return new (C) StoreNKlassNode(ctl, mem, adr, adr_type, val);
+ }
#endif
{
return new (C) StorePNode(ctl, mem, adr, adr_type, val);
diff --git a/src/share/vm/opto/memnode.hpp b/src/share/vm/opto/memnode.hpp
index 6f722f938..92a3d12fe 100644
--- a/src/share/vm/opto/memnode.hpp
+++ b/src/share/vm/opto/memnode.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -274,18 +274,6 @@ public:
virtual BasicType memory_type() const { return T_INT; }
};
-//------------------------------LoadUI2LNode-----------------------------------
-// Load an unsigned integer into long from memory
-class LoadUI2LNode : public LoadNode {
-public:
- LoadUI2LNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeLong* t = TypeLong::UINT)
- : LoadNode(c, mem, adr, at, t) {}
- virtual int Opcode() const;
- virtual uint ideal_reg() const { return Op_RegL; }
- virtual int store_Opcode() const { return Op_StoreL; }
- virtual BasicType memory_type() const { return T_LONG; }
-};
-
//------------------------------LoadRangeNode----------------------------------
// Load an array length from the array
class LoadRangeNode : public LoadINode {
@@ -437,12 +425,12 @@ public:
// Load a narrow Klass from an object.
class LoadNKlassNode : public LoadNNode {
public:
- LoadNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowOop *tk )
+ LoadNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowKlass *tk )
: LoadNNode(c,mem,adr,at,tk) {}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegN; }
- virtual int store_Opcode() const { return Op_StoreN; }
- virtual BasicType memory_type() const { return T_NARROWOOP; }
+ virtual int store_Opcode() const { return Op_StoreNKlass; }
+ virtual BasicType memory_type() const { return T_NARROWKLASS; }
virtual const Type *Value( PhaseTransform *phase ) const;
virtual Node *Identity( PhaseTransform *phase );
@@ -593,6 +581,15 @@ public:
virtual BasicType memory_type() const { return T_NARROWOOP; }
};
+//------------------------------StoreNKlassNode--------------------------------------
+// Store narrow klass to memory
+class StoreNKlassNode : public StoreNNode {
+public:
+ StoreNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNNode(c,mem,adr,at,val) {}
+ virtual int Opcode() const;
+ virtual BasicType memory_type() const { return T_NARROWKLASS; }
+};
+
//------------------------------StoreCMNode-----------------------------------
// Store card-mark byte to memory for CM
// The last StoreCM before a SafePoint must be preserved and occur after its "oop" store
diff --git a/src/share/vm/opto/mulnode.cpp b/src/share/vm/opto/mulnode.cpp
index f53310e81..4572a265e 100644
--- a/src/share/vm/opto/mulnode.cpp
+++ b/src/share/vm/opto/mulnode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -599,20 +599,6 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* in1 = in(1);
uint op = in1->Opcode();
- // Masking sign bits off of an integer? Do an unsigned integer to
- // long load.
- // NOTE: This check must be *before* we try to convert the AndLNode
- // to an AndINode and commute it with ConvI2LNode because
- // 0xFFFFFFFFL masks the whole integer and we get a sign extension,
- // which is wrong.
- if (op == Op_ConvI2L && in1->in(1)->Opcode() == Op_LoadI && mask == CONST64(0x00000000FFFFFFFF)) {
- Node* load = in1->in(1);
- return new (phase->C) LoadUI2LNode(load->in(MemNode::Control),
- load->in(MemNode::Memory),
- load->in(MemNode::Address),
- load->adr_type());
- }
-
// Are we masking a long that was converted from an int with a mask
// that fits in 32-bits? Commute them and use an AndINode. Don't
// convert masks which would cause a sign extension of the integer
diff --git a/src/share/vm/opto/node.hpp b/src/share/vm/opto/node.hpp
index a6033c68b..f746f2e42 100644
--- a/src/share/vm/opto/node.hpp
+++ b/src/share/vm/opto/node.hpp
@@ -62,8 +62,12 @@ class ConstraintCastNode;
class ConNode;
class CountedLoopNode;
class CountedLoopEndNode;
+class DecodeNarrowPtrNode;
class DecodeNNode;
+class DecodeNKlassNode;
+class EncodeNarrowPtrNode;
class EncodePNode;
+class EncodePKlassNode;
class FastLockNode;
class FastUnlockNode;
class IfNode;
@@ -585,8 +589,12 @@ public:
DEFINE_CLASS_ID(CheckCastPP, Type, 2)
DEFINE_CLASS_ID(CMove, Type, 3)
DEFINE_CLASS_ID(SafePointScalarObject, Type, 4)
- DEFINE_CLASS_ID(DecodeN, Type, 5)
- DEFINE_CLASS_ID(EncodeP, Type, 6)
+ DEFINE_CLASS_ID(DecodeNarrowPtr, Type, 5)
+ DEFINE_CLASS_ID(DecodeN, DecodeNarrowPtr, 0)
+ DEFINE_CLASS_ID(DecodeNKlass, DecodeNarrowPtr, 1)
+ DEFINE_CLASS_ID(EncodeNarrowPtr, Type, 6)
+ DEFINE_CLASS_ID(EncodeP, EncodeNarrowPtr, 0)
+ DEFINE_CLASS_ID(EncodePKlass, EncodeNarrowPtr, 1)
DEFINE_CLASS_ID(Proj, Node, 3)
DEFINE_CLASS_ID(CatchProj, Proj, 0)
@@ -706,8 +714,12 @@ public:
DEFINE_CLASS_QUERY(Cmp)
DEFINE_CLASS_QUERY(CountedLoop)
DEFINE_CLASS_QUERY(CountedLoopEnd)
+ DEFINE_CLASS_QUERY(DecodeNarrowPtr)
DEFINE_CLASS_QUERY(DecodeN)
+ DEFINE_CLASS_QUERY(DecodeNKlass)
+ DEFINE_CLASS_QUERY(EncodeNarrowPtr)
DEFINE_CLASS_QUERY(EncodeP)
+ DEFINE_CLASS_QUERY(EncodePKlass)
DEFINE_CLASS_QUERY(FastLock)
DEFINE_CLASS_QUERY(FastUnlock)
DEFINE_CLASS_QUERY(If)
diff --git a/src/share/vm/opto/parse.hpp b/src/share/vm/opto/parse.hpp
index 620c8370d..23dd261b9 100644
--- a/src/share/vm/opto/parse.hpp
+++ b/src/share/vm/opto/parse.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
diff --git a/src/share/vm/opto/parse1.cpp b/src/share/vm/opto/parse1.cpp
index c3daeecc8..d0b52f554 100644
--- a/src/share/vm/opto/parse1.cpp
+++ b/src/share/vm/opto/parse1.cpp
@@ -1381,8 +1381,7 @@ void Parse::do_one_block() {
// that occur during parsing of this BC. If there is no log
// output until the next context string, this context string
// will be silently ignored.
- log->context()->reset();
- log->context()->print_cr("<bc code='%d' bci='%d'/>", (int)bc(), bci());
+ log->set_context("bc code='%d' bci='%d'", (int)bc(), bci());
}
if (block()->has_trap_at(bci())) {
@@ -1411,7 +1410,8 @@ void Parse::do_one_block() {
NOT_PRODUCT( parse_histogram()->record_change(); );
- if (log != NULL) log->context()->reset(); // done w/ this one
+ if (log != NULL)
+ log->clear_context(); // skip marker if nothing was printed
// Fall into next bytecode. Each bytecode normally has 1 sequential
// successor which is typically made ready by visiting this bytecode.
diff --git a/src/share/vm/opto/parse2.cpp b/src/share/vm/opto/parse2.cpp
index 0373ebfc9..af91156da 100644
--- a/src/share/vm/opto/parse2.cpp
+++ b/src/share/vm/opto/parse2.cpp
@@ -1239,7 +1239,7 @@ void Parse::adjust_map_after_if(BoolTest::mask btest, Node* c, float prob,
static Node* extract_obj_from_klass_load(PhaseGVN* gvn, Node* n) {
Node* ldk;
- if (n->is_DecodeN()) {
+ if (n->is_DecodeNKlass()) {
if (n->in(1)->Opcode() != Op_LoadNKlass) {
return NULL;
} else {
diff --git a/src/share/vm/opto/parse3.cpp b/src/share/vm/opto/parse3.cpp
index 1a2f0520a..119fe7d19 100644
--- a/src/share/vm/opto/parse3.cpp
+++ b/src/share/vm/opto/parse3.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, 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
diff --git a/src/share/vm/opto/parseHelper.cpp b/src/share/vm/opto/parseHelper.cpp
index 5cb6bd241..19b0f5133 100644
--- a/src/share/vm/opto/parseHelper.cpp
+++ b/src/share/vm/opto/parseHelper.cpp
@@ -200,7 +200,7 @@ void Parse::array_store_check() {
// Come here for polymorphic array klasses
// Extract the array element class
- int element_klass_offset = in_bytes(objArrayKlass::element_klass_offset());
+ int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset());
Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset);
Node *a_e_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p2, tak) );
diff --git a/src/share/vm/opto/phaseX.cpp b/src/share/vm/opto/phaseX.cpp
index 037359667..849327cf8 100644
--- a/src/share/vm/opto/phaseX.cpp
+++ b/src/share/vm/opto/phaseX.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
diff --git a/src/share/vm/opto/phaseX.hpp b/src/share/vm/opto/phaseX.hpp
index 8068e6d54..3fc8a9566 100644
--- a/src/share/vm/opto/phaseX.hpp
+++ b/src/share/vm/opto/phaseX.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -497,8 +497,8 @@ public:
#ifndef PRODUCT
protected:
// Sub-quadratic implementation of VerifyIterativeGVN.
- unsigned long _verify_counter;
- unsigned long _verify_full_passes;
+ julong _verify_counter;
+ julong _verify_full_passes;
enum { _verify_window_size = 30 };
Node* _verify_window[_verify_window_size];
void verify_step(Node* n);
diff --git a/src/share/vm/opto/runtime.cpp b/src/share/vm/opto/runtime.cpp
index e33c042e1..bb050533d 100644
--- a/src/share/vm/opto/runtime.cpp
+++ b/src/share/vm/opto/runtime.cpp
@@ -286,13 +286,13 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, JavaT
if (Klass::cast(array_type)->oop_is_typeArray()) {
// The oopFactory likes to work with the element type.
// (We could bypass the oopFactory, since it doesn't add much value.)
- BasicType elem_type = typeArrayKlass::cast(array_type)->element_type();
+ BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type();
result = oopFactory::new_typeArray(elem_type, len, THREAD);
} else {
// Although the oopFactory likes to work with the elem_type,
// the compiler prefers the array_type, since it must already have
// that latter value in hand for the fast path.
- Klass* elem_type = objArrayKlass::cast(array_type)->element_klass();
+ Klass* elem_type = ObjArrayKlass::cast(array_type)->element_klass();
result = oopFactory::new_objArray(elem_type, len, THREAD);
}
@@ -323,7 +323,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len
assert(Klass::cast(array_type)->oop_is_typeArray(), "should be called only for type array");
// The oopFactory likes to work with the element type.
- BasicType elem_type = typeArrayKlass::cast(array_type)->element_type();
+ BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type();
result = oopFactory::new_typeArray_nozero(elem_type, len, THREAD);
// Pass oops back through thread local storage. Our apparent type to Java
@@ -344,7 +344,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len
is_deoptimized_caller_frame(thread)) {
// Zero array here if the caller is deoptimized.
int size = ((typeArrayOop)result)->object_size();
- BasicType elem_type = typeArrayKlass::cast(array_type)->element_type();
+ BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type();
const size_t hs = arrayOopDesc::header_size(elem_type);
// Align to next 8 bytes to avoid trashing arrays's length.
const size_t aligned_hs = align_object_offset(hs);
@@ -370,7 +370,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray2_C(Klass* elem_type, int len1, int l
jint dims[2];
dims[0] = len1;
dims[1] = len2;
- oop obj = arrayKlass::cast(elem_type)->multi_allocate(2, dims, THREAD);
+ oop obj = ArrayKlass::cast(elem_type)->multi_allocate(2, dims, THREAD);
deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION);
thread->set_vm_result(obj);
JRT_END
@@ -386,7 +386,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray3_C(Klass* elem_type, int len1, int l
dims[0] = len1;
dims[1] = len2;
dims[2] = len3;
- oop obj = arrayKlass::cast(elem_type)->multi_allocate(3, dims, THREAD);
+ oop obj = ArrayKlass::cast(elem_type)->multi_allocate(3, dims, THREAD);
deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION);
thread->set_vm_result(obj);
JRT_END
@@ -403,7 +403,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray4_C(Klass* elem_type, int len1, int l
dims[1] = len2;
dims[2] = len3;
dims[3] = len4;
- oop obj = arrayKlass::cast(elem_type)->multi_allocate(4, dims, THREAD);
+ oop obj = ArrayKlass::cast(elem_type)->multi_allocate(4, dims, THREAD);
deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION);
thread->set_vm_result(obj);
JRT_END
@@ -421,7 +421,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray5_C(Klass* elem_type, int len1, int l
dims[2] = len3;
dims[3] = len4;
dims[4] = len5;
- oop obj = arrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD);
+ oop obj = ArrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD);
deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION);
thread->set_vm_result(obj);
JRT_END
@@ -438,7 +438,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(Klass* elem_type, arrayOopDesc* d
jint *c_dims = NEW_RESOURCE_ARRAY(jint, len);
Copy::conjoint_jints_atomic(j_dims, c_dims, len);
- oop obj = arrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD);
+ oop obj = ArrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD);
deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION);
thread->set_vm_result(obj);
JRT_END
diff --git a/src/share/vm/opto/split_if.cpp b/src/share/vm/opto/split_if.cpp
index c2f89df36..134c87347 100644
--- a/src/share/vm/opto/split_if.cpp
+++ b/src/share/vm/opto/split_if.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
diff --git a/src/share/vm/opto/subnode.cpp b/src/share/vm/opto/subnode.cpp
index 81d698526..cbfe77751 100644
--- a/src/share/vm/opto/subnode.cpp
+++ b/src/share/vm/opto/subnode.cpp
@@ -789,7 +789,7 @@ Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) {
// Now check for LoadKlass on left.
Node* ldk1 = in(1);
- if (ldk1->is_DecodeN()) {
+ if (ldk1->is_DecodeNKlass()) {
ldk1 = ldk1->in(1);
if (ldk1->Opcode() != Op_LoadNKlass )
return NULL;
@@ -814,7 +814,7 @@ Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) {
// Check for a LoadKlass from primary supertype array.
// Any nested loadklass from loadklass+con must be from the p.s. array.
- if (ldk2->is_DecodeN()) {
+ if (ldk2->is_DecodeNKlass()) {
// Keep ldk2 as DecodeN since it could be used in CmpP below.
if (ldk2->in(1)->Opcode() != Op_LoadNKlass )
return NULL;
diff --git a/src/share/vm/opto/subnode.hpp b/src/share/vm/opto/subnode.hpp
index 2b33e90f9..862519d05 100644
--- a/src/share/vm/opto/subnode.hpp
+++ b/src/share/vm/opto/subnode.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
diff --git a/src/share/vm/opto/superword.cpp b/src/share/vm/opto/superword.cpp
index ab202840a..ffc5394bb 100644
--- a/src/share/vm/opto/superword.cpp
+++ b/src/share/vm/opto/superword.cpp
@@ -179,7 +179,6 @@ void SuperWord::find_adjacent_refs() {
for (int i = 0; i < _block.length(); i++) {
Node* n = _block.at(i);
if (n->is_Mem() && !n->is_LoadStore() && in_bb(n) &&
- n->Opcode() != Op_LoadUI2L &&
is_java_primitive(n->as_Mem()->memory_type())) {
int align = memory_alignment(n->as_Mem(), 0);
if (align != bottom_align) {
diff --git a/src/share/vm/opto/type.cpp b/src/share/vm/opto/type.cpp
index 0a82b2f6a..f982799f6 100644
--- a/src/share/vm/opto/type.cpp
+++ b/src/share/vm/opto/type.cpp
@@ -57,6 +57,7 @@ Type::TypeInfo Type::_type_info[Type::lastype] = {
{ Bad, T_LONG, "long:", false, Op_RegL, relocInfo::none }, // Long
{ Half, T_VOID, "half", false, 0, relocInfo::none }, // Half
{ Bad, T_NARROWOOP, "narrowoop:", false, Op_RegN, relocInfo::none }, // NarrowOop
+ { Bad, T_NARROWKLASS,"narrowklass:", false, Op_RegN, relocInfo::none }, // NarrowKlass
{ Bad, T_ILLEGAL, "tuple:", false, Node::NotAMachineReg, relocInfo::none }, // Tuple
{ Bad, T_ARRAY, "array:", false, Node::NotAMachineReg, relocInfo::none }, // Array
@@ -332,6 +333,8 @@ void Type::Initialize_shared(Compile* current) {
TypeNarrowOop::NULL_PTR = TypeNarrowOop::make( TypePtr::NULL_PTR );
TypeNarrowOop::BOTTOM = TypeNarrowOop::make( TypeInstPtr::BOTTOM );
+ TypeNarrowKlass::NULL_PTR = TypeNarrowKlass::make( TypePtr::NULL_PTR );
+
mreg2type[Op_Node] = Type::BOTTOM;
mreg2type[Op_Set ] = 0;
mreg2type[Op_RegN] = TypeNarrowOop::BOTTOM;
@@ -395,34 +398,36 @@ void Type::Initialize_shared(Compile* current) {
longpair[1] = TypeLong::LONG;
TypeTuple::LONG_PAIR = TypeTuple::make(2, longpair);
- _const_basic_type[T_NARROWOOP] = TypeNarrowOop::BOTTOM;
- _const_basic_type[T_BOOLEAN] = TypeInt::BOOL;
- _const_basic_type[T_CHAR] = TypeInt::CHAR;
- _const_basic_type[T_BYTE] = TypeInt::BYTE;
- _const_basic_type[T_SHORT] = TypeInt::SHORT;
- _const_basic_type[T_INT] = TypeInt::INT;
- _const_basic_type[T_LONG] = TypeLong::LONG;
- _const_basic_type[T_FLOAT] = Type::FLOAT;
- _const_basic_type[T_DOUBLE] = Type::DOUBLE;
- _const_basic_type[T_OBJECT] = TypeInstPtr::BOTTOM;
- _const_basic_type[T_ARRAY] = TypeInstPtr::BOTTOM; // there is no separate bottom for arrays
- _const_basic_type[T_VOID] = TypePtr::NULL_PTR; // reflection represents void this way
- _const_basic_type[T_ADDRESS] = TypeRawPtr::BOTTOM; // both interpreter return addresses & random raw ptrs
- _const_basic_type[T_CONFLICT]= Type::BOTTOM; // why not?
-
- _zero_type[T_NARROWOOP] = TypeNarrowOop::NULL_PTR;
- _zero_type[T_BOOLEAN] = TypeInt::ZERO; // false == 0
- _zero_type[T_CHAR] = TypeInt::ZERO; // '\0' == 0
- _zero_type[T_BYTE] = TypeInt::ZERO; // 0x00 == 0
- _zero_type[T_SHORT] = TypeInt::ZERO; // 0x0000 == 0
- _zero_type[T_INT] = TypeInt::ZERO;
- _zero_type[T_LONG] = TypeLong::ZERO;
- _zero_type[T_FLOAT] = TypeF::ZERO;
- _zero_type[T_DOUBLE] = TypeD::ZERO;
- _zero_type[T_OBJECT] = TypePtr::NULL_PTR;
- _zero_type[T_ARRAY] = TypePtr::NULL_PTR; // null array is null oop
- _zero_type[T_ADDRESS] = TypePtr::NULL_PTR; // raw pointers use the same null
- _zero_type[T_VOID] = Type::TOP; // the only void value is no value at all
+ _const_basic_type[T_NARROWOOP] = TypeNarrowOop::BOTTOM;
+ _const_basic_type[T_NARROWKLASS] = Type::BOTTOM;
+ _const_basic_type[T_BOOLEAN] = TypeInt::BOOL;
+ _const_basic_type[T_CHAR] = TypeInt::CHAR;
+ _const_basic_type[T_BYTE] = TypeInt::BYTE;
+ _const_basic_type[T_SHORT] = TypeInt::SHORT;
+ _const_basic_type[T_INT] = TypeInt::INT;
+ _const_basic_type[T_LONG] = TypeLong::LONG;
+ _const_basic_type[T_FLOAT] = Type::FLOAT;
+ _const_basic_type[T_DOUBLE] = Type::DOUBLE;
+ _const_basic_type[T_OBJECT] = TypeInstPtr::BOTTOM;
+ _const_basic_type[T_ARRAY] = TypeInstPtr::BOTTOM; // there is no separate bottom for arrays
+ _const_basic_type[T_VOID] = TypePtr::NULL_PTR; // reflection represents void this way
+ _const_basic_type[T_ADDRESS] = TypeRawPtr::BOTTOM; // both interpreter return addresses & random raw ptrs
+ _const_basic_type[T_CONFLICT] = Type::BOTTOM; // why not?
+
+ _zero_type[T_NARROWOOP] = TypeNarrowOop::NULL_PTR;
+ _zero_type[T_NARROWKLASS] = TypeNarrowKlass::NULL_PTR;
+ _zero_type[T_BOOLEAN] = TypeInt::ZERO; // false == 0
+ _zero_type[T_CHAR] = TypeInt::ZERO; // '\0' == 0
+ _zero_type[T_BYTE] = TypeInt::ZERO; // 0x00 == 0
+ _zero_type[T_SHORT] = TypeInt::ZERO; // 0x0000 == 0
+ _zero_type[T_INT] = TypeInt::ZERO;
+ _zero_type[T_LONG] = TypeLong::ZERO;
+ _zero_type[T_FLOAT] = TypeF::ZERO;
+ _zero_type[T_DOUBLE] = TypeD::ZERO;
+ _zero_type[T_OBJECT] = TypePtr::NULL_PTR;
+ _zero_type[T_ARRAY] = TypePtr::NULL_PTR; // null array is null oop
+ _zero_type[T_ADDRESS] = TypePtr::NULL_PTR; // raw pointers use the same null
+ _zero_type[T_VOID] = Type::TOP; // the only void value is no value at all
// get_zero_type() should not happen for T_CONFLICT
_zero_type[T_CONFLICT]= NULL;
@@ -563,9 +568,14 @@ const Type *Type::meet( const Type *t ) const {
const Type* result = make_ptr()->meet(t->make_ptr());
return result->make_narrowoop();
}
+ if (isa_narrowklass() && t->isa_narrowklass()) {
+ const Type* result = make_ptr()->meet(t->make_ptr());
+ return result->make_narrowklass();
+ }
const Type *mt = xmeet(t);
if (isa_narrowoop() || t->isa_narrowoop()) return mt;
+ if (isa_narrowklass() || t->isa_narrowklass()) return mt;
#ifdef ASSERT
assert( mt == t->xmeet(this), "meet not commutative" );
const Type* dual_join = mt->_dual;
@@ -635,6 +645,9 @@ const Type *Type::xmeet( const Type *t ) const {
case NarrowOop:
return t->xmeet(this);
+ case NarrowKlass:
+ return t->xmeet(this);
+
case Bad: // Type check
default: // Bogus type not in lattice
typerr(t);
@@ -693,6 +706,7 @@ const Type::TYPES Type::dual_type[Type::lastype] = {
Bad, // Long - handled in v-call
Half, // Half
Bad, // NarrowOop - handled in v-call
+ Bad, // NarrowKlass - handled in v-call
Bad, // Tuple - handled in v-call
Bad, // Array - handled in v-call
@@ -756,6 +770,8 @@ void Type::dump_on(outputStream *st) const {
dump2(d,1, st);
if (is_ptr_to_narrowoop()) {
st->print(" [narrow]");
+ } else if (is_ptr_to_narrowklass()) {
+ st->print(" [narrowklass]");
}
}
#endif
@@ -838,6 +854,7 @@ const Type *TypeF::xmeet( const Type *t ) const {
case MetadataPtr:
case KlassPtr:
case NarrowOop:
+ case NarrowKlass:
case Int:
case Long:
case DoubleTop:
@@ -955,6 +972,7 @@ const Type *TypeD::xmeet( const Type *t ) const {
case MetadataPtr:
case KlassPtr:
case NarrowOop:
+ case NarrowKlass:
case Int:
case Long:
case FloatTop:
@@ -1109,6 +1127,7 @@ const Type *TypeInt::xmeet( const Type *t ) const {
case MetadataPtr:
case KlassPtr:
case NarrowOop:
+ case NarrowKlass:
case Long:
case FloatTop:
case FloatCon:
@@ -1366,6 +1385,7 @@ const Type *TypeLong::xmeet( const Type *t ) const {
case MetadataPtr:
case KlassPtr:
case NarrowOop:
+ case NarrowKlass:
case Int:
case FloatTop:
case FloatCon:
@@ -2096,6 +2116,7 @@ const Type *TypePtr::xmeet( const Type *t ) const {
case DoubleCon:
case DoubleBot:
case NarrowOop:
+ case NarrowKlass:
case Bottom: // Ye Olde Default
return Type::BOTTOM;
case Top:
@@ -2350,17 +2371,18 @@ TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int
_const_oop(o), _klass(k),
_klass_is_exact(xk),
_is_ptr_to_narrowoop(false),
+ _is_ptr_to_narrowklass(false),
_instance_id(instance_id) {
#ifdef _LP64
- if (UseCompressedOops && _offset != 0) {
+ if (_offset != 0) {
if (_offset == oopDesc::klass_offset_in_bytes()) {
- _is_ptr_to_narrowoop = UseCompressedKlassPointers;
+ _is_ptr_to_narrowklass = UseCompressedKlassPointers;
} else if (klass() == NULL) {
// Array with unknown body type
assert(this->isa_aryptr(), "only arrays without klass");
- _is_ptr_to_narrowoop = true;
+ _is_ptr_to_narrowoop = UseCompressedOops;
} else if (this->isa_aryptr()) {
- _is_ptr_to_narrowoop = (klass()->is_obj_array_klass() &&
+ _is_ptr_to_narrowoop = (UseCompressedOops && klass()->is_obj_array_klass() &&
_offset != arrayOopDesc::length_offset_in_bytes());
} else if (klass()->is_instance_klass()) {
ciInstanceKlass* ik = klass()->as_instance_klass();
@@ -2369,7 +2391,7 @@ TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int
// Perm objects don't use compressed references
} else if (_offset == OffsetBot || _offset == OffsetTop) {
// unsafe access
- _is_ptr_to_narrowoop = true;
+ _is_ptr_to_narrowoop = UseCompressedOops;
} else { // exclude unsafe ops
assert(this->isa_instptr(), "must be an instance ptr.");
@@ -2387,22 +2409,22 @@ TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int
ciField* field = k->get_field_by_offset(_offset, true);
assert(field != NULL, "missing field");
BasicType basic_elem_type = field->layout_type();
- _is_ptr_to_narrowoop = (basic_elem_type == T_OBJECT ||
- basic_elem_type == T_ARRAY);
+ _is_ptr_to_narrowoop = UseCompressedOops && (basic_elem_type == T_OBJECT ||
+ basic_elem_type == T_ARRAY);
} else {
// Instance fields which contains a compressed oop references.
field = ik->get_field_by_offset(_offset, false);
if (field != NULL) {
BasicType basic_elem_type = field->layout_type();
- _is_ptr_to_narrowoop = (basic_elem_type == T_OBJECT ||
- basic_elem_type == T_ARRAY);
+ _is_ptr_to_narrowoop = UseCompressedOops && (basic_elem_type == T_OBJECT ||
+ basic_elem_type == T_ARRAY);
} else if (klass()->equals(ciEnv::current()->Object_klass())) {
// Compile::find_alias_type() cast exactness on all types to verify
// that it does not affect alias type.
- _is_ptr_to_narrowoop = true;
+ _is_ptr_to_narrowoop = UseCompressedOops;
} else {
// Type for the copy start in LibraryCallKit::inline_native_clone().
- _is_ptr_to_narrowoop = true;
+ _is_ptr_to_narrowoop = UseCompressedOops;
}
}
}
@@ -2475,6 +2497,7 @@ const Type *TypeOopPtr::xmeet( const Type *t ) const {
case DoubleCon:
case DoubleBot:
case NarrowOop:
+ case NarrowKlass:
case Bottom: // Ye Olde Default
return Type::BOTTOM;
case Top:
@@ -2925,6 +2948,7 @@ const Type *TypeInstPtr::xmeet( const Type *t ) const {
case DoubleCon:
case DoubleBot:
case NarrowOop:
+ case NarrowKlass:
case Bottom: // Ye Olde Default
return Type::BOTTOM;
case Top:
@@ -3353,6 +3377,7 @@ static jint max_array_length(BasicType etype) {
case T_NARROWOOP:
etype = T_OBJECT;
break;
+ case T_NARROWKLASS:
case T_CONFLICT:
case T_ILLEGAL:
case T_VOID:
@@ -3425,6 +3450,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const {
case DoubleCon:
case DoubleBot:
case NarrowOop:
+ case NarrowKlass:
case Bottom: // Ye Olde Default
return Type::BOTTOM;
case Top:
@@ -3671,23 +3697,27 @@ const TypePtr *TypeAryPtr::add_offset( intptr_t offset ) const {
//=============================================================================
-const TypeNarrowOop *TypeNarrowOop::BOTTOM;
-const TypeNarrowOop *TypeNarrowOop::NULL_PTR;
-
-
-const TypeNarrowOop* TypeNarrowOop::make(const TypePtr* type) {
- return (const TypeNarrowOop*)(new TypeNarrowOop(type))->hashcons();
-}
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
-int TypeNarrowOop::hash(void) const {
+int TypeNarrowPtr::hash(void) const {
return _ptrtype->hash() + 7;
}
+bool TypeNarrowPtr::singleton(void) const { // TRUE if type is a singleton
+ return _ptrtype->singleton();
+}
+
+bool TypeNarrowPtr::empty(void) const {
+ return _ptrtype->empty();
+}
+
+intptr_t TypeNarrowPtr::get_con() const {
+ return _ptrtype->get_con();
+}
-bool TypeNarrowOop::eq( const Type *t ) const {
- const TypeNarrowOop* tc = t->isa_narrowoop();
+bool TypeNarrowPtr::eq( const Type *t ) const {
+ const TypeNarrowPtr* tc = isa_same_narrowptr(t);
if (tc != NULL) {
if (_ptrtype->base() != tc->_ptrtype->base()) {
return false;
@@ -3697,22 +3727,46 @@ bool TypeNarrowOop::eq( const Type *t ) const {
return false;
}
-bool TypeNarrowOop::singleton(void) const { // TRUE if type is a singleton
- return _ptrtype->singleton();
+const Type *TypeNarrowPtr::xdual() const { // Compute dual right now.
+ const TypePtr* odual = _ptrtype->dual()->is_ptr();
+ return make_same_narrowptr(odual);
}
-bool TypeNarrowOop::empty(void) const {
- return _ptrtype->empty();
+
+const Type *TypeNarrowPtr::filter( const Type *kills ) const {
+ if (isa_same_narrowptr(kills)) {
+ const Type* ft =_ptrtype->filter(is_same_narrowptr(kills)->_ptrtype);
+ if (ft->empty())
+ return Type::TOP; // Canonical empty value
+ if (ft->isa_ptr()) {
+ return make_hash_same_narrowptr(ft->isa_ptr());
+ }
+ return ft;
+ } else if (kills->isa_ptr()) {
+ const Type* ft = _ptrtype->join(kills);
+ if (ft->empty())
+ return Type::TOP; // Canonical empty value
+ return ft;
+ } else {
+ return Type::TOP;
+ }
}
//------------------------------xmeet------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
-const Type *TypeNarrowOop::xmeet( const Type *t ) const {
+const Type *TypeNarrowPtr::xmeet( const Type *t ) const {
// Perform a fast test for common case; meeting the same types together.
if( this == t ) return this; // Meeting same type-rep?
+ if (t->base() == base()) {
+ const Type* result = _ptrtype->xmeet(t->make_ptr());
+ if (result->isa_ptr()) {
+ return make_hash_same_narrowptr(result->is_ptr());
+ }
+ return result;
+ }
- // Current "this->_base" is OopPtr
+ // Current "this->_base" is NarrowKlass or NarrowOop
switch (t->base()) { // switch on original type
case Int: // Mixing ints & oops happens when javac
@@ -3730,20 +3784,14 @@ const Type *TypeNarrowOop::xmeet( const Type *t ) const {
case AryPtr:
case MetadataPtr:
case KlassPtr:
+ case NarrowOop:
+ case NarrowKlass:
case Bottom: // Ye Olde Default
return Type::BOTTOM;
case Top:
return this;
- case NarrowOop: {
- const Type* result = _ptrtype->xmeet(t->make_ptr());
- if (result->isa_ptr()) {
- return TypeNarrowOop::make(result->is_ptr());
- }
- return result;
- }
-
default: // All else is a mistake
typerr(t);
@@ -3752,42 +3800,40 @@ const Type *TypeNarrowOop::xmeet( const Type *t ) const {
return this;
}
-const Type *TypeNarrowOop::xdual() const { // Compute dual right now.
- const TypePtr* odual = _ptrtype->dual()->is_ptr();
- return new TypeNarrowOop(odual);
+#ifndef PRODUCT
+void TypeNarrowPtr::dump2( Dict & d, uint depth, outputStream *st ) const {
+ _ptrtype->dump2(d, depth, st);
}
+#endif
-const Type *TypeNarrowOop::filter( const Type *kills ) const {
- if (kills->isa_narrowoop()) {
- const Type* ft =_ptrtype->filter(kills->is_narrowoop()->_ptrtype);
- if (ft->empty())
- return Type::TOP; // Canonical empty value
- if (ft->isa_ptr()) {
- return make(ft->isa_ptr());
- }
- return ft;
- } else if (kills->isa_ptr()) {
- const Type* ft = _ptrtype->join(kills);
- if (ft->empty())
- return Type::TOP; // Canonical empty value
- return ft;
- } else {
- return Type::TOP;
- }
-}
+const TypeNarrowOop *TypeNarrowOop::BOTTOM;
+const TypeNarrowOop *TypeNarrowOop::NULL_PTR;
-intptr_t TypeNarrowOop::get_con() const {
- return _ptrtype->get_con();
+const TypeNarrowOop* TypeNarrowOop::make(const TypePtr* type) {
+ return (const TypeNarrowOop*)(new TypeNarrowOop(type))->hashcons();
}
+
#ifndef PRODUCT
void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const {
st->print("narrowoop: ");
- _ptrtype->dump2(d, depth, st);
+ TypeNarrowPtr::dump2(d, depth, st);
}
#endif
+const TypeNarrowKlass *TypeNarrowKlass::NULL_PTR;
+
+const TypeNarrowKlass* TypeNarrowKlass::make(const TypePtr* type) {
+ return (const TypeNarrowKlass*)(new TypeNarrowKlass(type))->hashcons();
+}
+
+#ifndef PRODUCT
+void TypeNarrowKlass::dump2( Dict & d, uint depth, outputStream *st ) const {
+ st->print("narrowklass: ");
+ TypeNarrowPtr::dump2(d, depth, st);
+}
+#endif
//------------------------------eq---------------------------------------------
@@ -3878,6 +3924,7 @@ const Type *TypeMetadataPtr::xmeet( const Type *t ) const {
case DoubleCon:
case DoubleBot:
case NarrowOop:
+ case NarrowKlass:
case Bottom: // Ye Olde Default
return Type::BOTTOM;
case Top:
@@ -4169,6 +4216,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const {
case DoubleCon:
case DoubleBot:
case NarrowOop:
+ case NarrowKlass:
case Bottom: // Ye Olde Default
return Type::BOTTOM;
case Top:
diff --git a/src/share/vm/opto/type.hpp b/src/share/vm/opto/type.hpp
index 666c78f5c..39bbf0306 100644
--- a/src/share/vm/opto/type.hpp
+++ b/src/share/vm/opto/type.hpp
@@ -48,7 +48,9 @@ class TypeD;
class TypeF;
class TypeInt;
class TypeLong;
-class TypeNarrowOop;
+class TypeNarrowPtr;
+class TypeNarrowOop;
+class TypeNarrowKlass;
class TypeAry;
class TypeTuple;
class TypeVect;
@@ -81,6 +83,7 @@ public:
Long, // Long integer range (lo-hi)
Half, // Placeholder half of doubleword
NarrowOop, // Compressed oop pointer
+ NarrowKlass, // Compressed klass pointer
Tuple, // Method signature or object layout
Array, // Array types
@@ -229,6 +232,7 @@ public:
// Returns true if this pointer points at memory which contains a
// compressed oop references.
bool is_ptr_to_narrowoop() const;
+ bool is_ptr_to_narrowklass() const;
// Convenience access
float getf() const;
@@ -252,6 +256,8 @@ public:
const TypeRawPtr *is_rawptr() const; // Asserts is rawptr
const TypeNarrowOop *is_narrowoop() const; // Java-style GC'd pointer
const TypeNarrowOop *isa_narrowoop() const; // Returns NULL if not oop ptr type
+ const TypeNarrowKlass *is_narrowklass() const; // compressed klass pointer
+ const TypeNarrowKlass *isa_narrowklass() const;// Returns NULL if not oop ptr type
const TypeOopPtr *isa_oopptr() const; // Returns NULL if not oop ptr type
const TypeOopPtr *is_oopptr() const; // Java-style GC'd pointer
const TypeInstPtr *isa_instptr() const; // Returns NULL if not InstPtr
@@ -278,6 +284,10 @@ public:
// of this pointer type.
const TypeNarrowOop* make_narrowoop() const;
+ // Returns this compressed klass pointer or the equivalent
+ // compressed version of this pointer type.
+ const TypeNarrowKlass* make_narrowklass() const;
+
// Special test for register pressure heuristic
bool is_floatingpoint() const; // True if Float or Double base type
@@ -670,7 +680,7 @@ class TypeVectY : public TypeVect {
// Otherwise the _base will indicate which subset of pointers is affected,
// and the class will be inherited from.
class TypePtr : public Type {
- friend class TypeNarrowOop;
+ friend class TypeNarrowPtr;
public:
enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR };
protected:
@@ -781,6 +791,7 @@ protected:
// Does the type exclude subclasses of the klass? (Inexact == polymorphic.)
bool _klass_is_exact;
bool _is_ptr_to_narrowoop;
+ bool _is_ptr_to_narrowklass;
// If not InstanceTop or InstanceBot, indicates that this is
// a particular instance of this type which is distinct.
@@ -825,6 +836,7 @@ public:
// Returns true if this pointer points at memory which contains a
// compressed oop references.
bool is_ptr_to_narrowoop_nv() const { return _is_ptr_to_narrowoop; }
+ bool is_ptr_to_narrowklass_nv() const { return _is_ptr_to_narrowklass; }
bool is_known_instance() const { return _instance_id > 0; }
int instance_id() const { return _instance_id; }
@@ -1122,22 +1134,21 @@ public:
#endif
};
-//------------------------------TypeNarrowOop----------------------------------
-// A compressed reference to some kind of Oop. This type wraps around
-// a preexisting TypeOopPtr and forwards most of it's operations to
-// the underlying type. It's only real purpose is to track the
-// oopness of the compressed oop value when we expose the conversion
-// between the normal and the compressed form.
-class TypeNarrowOop : public Type {
+class TypeNarrowPtr : public Type {
protected:
const TypePtr* _ptrtype; // Could be TypePtr::NULL_PTR
- TypeNarrowOop( const TypePtr* ptrtype): Type(NarrowOop),
- _ptrtype(ptrtype) {
+ TypeNarrowPtr(TYPES t, const TypePtr* ptrtype): _ptrtype(ptrtype),
+ Type(t) {
assert(ptrtype->offset() == 0 ||
ptrtype->offset() == OffsetBot ||
ptrtype->offset() == OffsetTop, "no real offsets");
}
+
+ virtual const TypeNarrowPtr *isa_same_narrowptr(const Type *t) const = 0;
+ virtual const TypeNarrowPtr *is_same_narrowptr(const Type *t) const = 0;
+ virtual const TypeNarrowPtr *make_same_narrowptr(const TypePtr *t) const = 0;
+ virtual const TypeNarrowPtr *make_hash_same_narrowptr(const TypePtr *t) const = 0;
public:
virtual bool eq( const Type *t ) const;
virtual int hash() const; // Type specific hashing
@@ -1153,17 +1164,51 @@ public:
virtual bool empty(void) const; // TRUE if type is vacuous
+ // returns the equivalent ptr type for this compressed pointer
+ const TypePtr *get_ptrtype() const {
+ return _ptrtype;
+ }
+
+#ifndef PRODUCT
+ virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
+#endif
+};
+
+//------------------------------TypeNarrowOop----------------------------------
+// A compressed reference to some kind of Oop. This type wraps around
+// a preexisting TypeOopPtr and forwards most of it's operations to
+// the underlying type. It's only real purpose is to track the
+// oopness of the compressed oop value when we expose the conversion
+// between the normal and the compressed form.
+class TypeNarrowOop : public TypeNarrowPtr {
+protected:
+ TypeNarrowOop( const TypePtr* ptrtype): TypeNarrowPtr(NarrowOop, ptrtype) {
+ }
+
+ virtual const TypeNarrowPtr *isa_same_narrowptr(const Type *t) const {
+ return t->isa_narrowoop();
+ }
+
+ virtual const TypeNarrowPtr *is_same_narrowptr(const Type *t) const {
+ return t->is_narrowoop();
+ }
+
+ virtual const TypeNarrowPtr *make_same_narrowptr(const TypePtr *t) const {
+ return new TypeNarrowOop(t);
+ }
+
+ virtual const TypeNarrowPtr *make_hash_same_narrowptr(const TypePtr *t) const {
+ return (const TypeNarrowPtr*)((new TypeNarrowOop(t))->hashcons());
+ }
+
+public:
+
static const TypeNarrowOop *make( const TypePtr* type);
static const TypeNarrowOop* make_from_constant(ciObject* con, bool require_constant = false) {
return make(TypeOopPtr::make_from_constant(con, require_constant));
}
- // returns the equivalent ptr type for this compressed pointer
- const TypePtr *get_ptrtype() const {
- return _ptrtype;
- }
-
static const TypeNarrowOop *BOTTOM;
static const TypeNarrowOop *NULL_PTR;
@@ -1172,6 +1217,42 @@ public:
#endif
};
+//------------------------------TypeNarrowKlass----------------------------------
+// A compressed reference to klass pointer. This type wraps around a
+// preexisting TypeKlassPtr and forwards most of it's operations to
+// the underlying type.
+class TypeNarrowKlass : public TypeNarrowPtr {
+protected:
+ TypeNarrowKlass( const TypePtr* ptrtype): TypeNarrowPtr(NarrowKlass, ptrtype) {
+ }
+
+ virtual const TypeNarrowPtr *isa_same_narrowptr(const Type *t) const {
+ return t->isa_narrowklass();
+ }
+
+ virtual const TypeNarrowPtr *is_same_narrowptr(const Type *t) const {
+ return t->is_narrowklass();
+ }
+
+ virtual const TypeNarrowPtr *make_same_narrowptr(const TypePtr *t) const {
+ return new TypeNarrowKlass(t);
+ }
+
+ virtual const TypeNarrowPtr *make_hash_same_narrowptr(const TypePtr *t) const {
+ return (const TypeNarrowPtr*)((new TypeNarrowKlass(t))->hashcons());
+ }
+
+public:
+ static const TypeNarrowKlass *make( const TypePtr* type);
+
+ // static const TypeNarrowKlass *BOTTOM;
+ static const TypeNarrowKlass *NULL_PTR;
+
+#ifndef PRODUCT
+ virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
+#endif
+};
+
//------------------------------TypeFunc---------------------------------------
// Class of Array Types
class TypeFunc : public Type {
@@ -1221,6 +1302,14 @@ inline bool Type::is_ptr_to_narrowoop() const {
#endif
}
+inline bool Type::is_ptr_to_narrowklass() const {
+#ifdef _LP64
+ return (isa_oopptr() != NULL && is_oopptr()->is_ptr_to_narrowklass_nv());
+#else
+ return false;
+#endif
+}
+
inline float Type::getf() const {
assert( _base == FloatCon, "Not a FloatCon" );
return ((TypeF*)this)->_f;
@@ -1346,6 +1435,15 @@ inline const TypeNarrowOop *Type::isa_narrowoop() const {
return (_base == NarrowOop) ? (TypeNarrowOop*)this : NULL;
}
+inline const TypeNarrowKlass *Type::is_narrowklass() const {
+ assert(_base == NarrowKlass, "Not a narrow oop" ) ;
+ return (TypeNarrowKlass*)this;
+}
+
+inline const TypeNarrowKlass *Type::isa_narrowklass() const {
+ return (_base == NarrowKlass) ? (TypeNarrowKlass*)this : NULL;
+}
+
inline const TypeMetadataPtr *Type::is_metadataptr() const {
// MetadataPtr is the first and CPCachePtr the last
assert(_base == MetadataPtr, "Not a metadata pointer" ) ;
@@ -1367,7 +1465,8 @@ inline const TypeKlassPtr *Type::is_klassptr() const {
inline const TypePtr* Type::make_ptr() const {
return (_base == NarrowOop) ? is_narrowoop()->get_ptrtype() :
- (isa_ptr() ? is_ptr() : NULL);
+ ((_base == NarrowKlass) ? is_narrowklass()->get_ptrtype() :
+ (isa_ptr() ? is_ptr() : NULL));
}
inline const TypeOopPtr* Type::make_oopptr() const {
@@ -1379,6 +1478,11 @@ inline const TypeNarrowOop* Type::make_narrowoop() const {
(isa_ptr() ? TypeNarrowOop::make(is_ptr()) : NULL);
}
+inline const TypeNarrowKlass* Type::make_narrowklass() const {
+ return (_base == NarrowKlass) ? is_narrowklass() :
+ (isa_ptr() ? TypeNarrowKlass::make(is_ptr()) : NULL);
+}
+
inline bool Type::is_floatingpoint() const {
if( (_base == FloatCon) || (_base == FloatBot) ||
(_base == DoubleCon) || (_base == DoubleBot) )