Created
May 6, 2012 14:44
-
-
Save rednaxelafx/2622617 to your computer and use it in GitHub Desktop.
C2 should recognize "obj.getClass() == A.class" code pattern. Diff against jdk8/jdk8/hotspot tip. Previous versions: https://gist.github.com/2499019
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -r bfcf92bfefb8 src/share/vm/opto/parse2.cpp | |
--- a/src/share/vm/opto/parse2.cpp Thu Apr 26 14:05:31 2012 -0700 | |
+++ b/src/share/vm/opto/parse2.cpp Sun May 06 22:42:44 2012 +0800 | |
@@ -1165,6 +1165,138 @@ | |
} | |
} | |
+static Node* extract_obj_from_klass_load(PhaseGVN* gvn, Node* n) { | |
+ Node* ldk; | |
+ if (n->is_DecodeN()) { | |
+ if (n->in(1)->Opcode() != Op_LoadNKlass) { | |
+ return NULL; | |
+ } else { | |
+ ldk = n->in(1); | |
+ } | |
+ } else if (n->Opcode() != Op_LoadKlass) { | |
+ return NULL; | |
+ } else { | |
+ ldk = n; | |
+ } | |
+ assert(ldk != NULL, "should have found a LoadKlass or LoadNKlass node"); | |
+ | |
+ Node* adr = ldk->in(MemNode::Address); | |
+ intptr_t off = 0; | |
+ Node* obj = AddPNode::Ideal_base_and_offset(adr, gvn, off); | |
+ const TypePtr* tp = gvn->type(obj)->is_ptr(); | |
+ if ( !obj // is adr an AddP node? | |
+ || !tp // is obj of pointer type? | |
+ || !(tp->isa_instptr() || tp->isa_aryptr()) // is obj a Java object ptr? | |
+ || off != oopDesc::klass_offset_in_bytes()) // loading oopDesc::_klass? | |
+ return NULL; | |
+ | |
+ return obj; | |
+} | |
+ | |
+static void sharpen_type_after_if(Parse* p, BoolTest::mask btest, | |
+ Node* con, const Type* tcon, | |
+ Node* val, const Type* tval) { | |
+ Compile* C = p->C; | |
+ PhaseGVN& gvn = p->gvn(); | |
+ | |
+ // look for opportunities to sharpen the type of a node | |
+ // whose klass is compared with a constant klass | |
+ Node* obj = extract_obj_from_klass_load(&gvn, val); | |
+ const TypeKlassPtr* tkp = tcon->isa_klassptr(); | |
+ bool is_klass_cmp = obj && tkp; | |
+ | |
+ // the node to be replaced, and its type | |
+ Node* rep; | |
+ const Type* trep; | |
+ if (is_klass_cmp) { | |
+ const Type* tobj = gvn.type(obj); | |
+ rep = obj; | |
+ trep = tobj; | |
+ } else { | |
+ rep = val; | |
+ trep = tval; | |
+ } | |
+ | |
+ int rep_in_map = p->map()->find_edge(rep); | |
+ if (rep_in_map < 0) return; // replace_in_map would be useless | |
+ { | |
+ JVMState* jvms = p->jvms(); | |
+ if (!(jvms->is_loc(rep_in_map) || | |
+ jvms->is_stk(rep_in_map))) | |
+ return; // again, it would be useless | |
+ } | |
+ | |
+ // Check for a comparison to a constant, and "know" that the compared | |
+ // value is constrained on this path. | |
+ assert(tcon->singleton(), ""); | |
+ TypeNode* ccast = NULL; | |
+ Node* cast = NULL; | |
+ | |
+ switch (btest) { | |
+ case BoolTest::eq: // Constant test? | |
+ { | |
+ if (is_klass_cmp) { | |
+ const TypeOopPtr* obj_xtype = tkp->as_instance_type(); | |
+ if (obj_xtype->isa_instptr() || obj_xtype->isa_aryptr()) { | |
+ // Found: | |
+ // Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq]) | |
+ // or the narrowOop equivalent. | |
+ // obj has to be of the exact type Foo if the CmpP succeeds. | |
+ const TypeOopPtr* tboth = obj_xtype->join(trep)->is_oopptr(); | |
+ if (tboth == trep) break; // Nothing to gain. | |
+ | |
+ assert(tboth->klass_is_exact(), "klass should be exact"); | |
+ ccast = new (C, 2) CheckCastPPNode(p->control(), obj, tboth); | |
+ } | |
+ } else { | |
+ const Type* tboth = tcon->join(tval); | |
+ if (tboth == tval) break; // Nothing to gain. | |
+ if (tcon->isa_int()) { | |
+ ccast = new (C, 2) CastIINode(val, tboth); | |
+ } else if (tcon == TypePtr::NULL_PTR) { | |
+ // Cast to null, but keep the pointer identity temporarily live. | |
+ ccast = new (C, 2) CastPPNode(val, tboth); | |
+ } else { | |
+ const TypeF* tf = tcon->isa_float_constant(); | |
+ const TypeD* td = tcon->isa_double_constant(); | |
+ // Exclude tests vs float/double 0 as these could be | |
+ // either +0 or -0. Just because you are equal to +0 | |
+ // doesn't mean you ARE +0! | |
+ if ((!tf || tf->_f != 0.0) && | |
+ (!td || td->_d != 0.0)) | |
+ cast = con; // Replace non-constant val by con. | |
+ } | |
+ } | |
+ } | |
+ break; | |
+ | |
+ case BoolTest::ne: | |
+ if (tcon == TypePtr::NULL_PTR) { | |
+ cast = p->cast_not_null(val, false); | |
+ } | |
+ break; | |
+ | |
+ default: | |
+ // (At this point we could record int range types with CastII.) | |
+ break; | |
+ } | |
+ | |
+ if (ccast != NULL) { | |
+ const Type* tcc = ccast->as_Type()->type(); | |
+ assert(tcc != trep && tcc->higher_equal(trep), "must improve"); | |
+ // Delay transform() call to allow recovery of pre-cast value | |
+ // at the control merge. | |
+ ccast->set_req(0, p->control()); | |
+ gvn.set_type_bottom(ccast); | |
+ p->record_for_igvn(ccast); | |
+ cast = ccast; | |
+ } | |
+ | |
+ if (cast != NULL) { // Here's the payoff. | |
+ p->replace_in_map(rep, cast); | |
+ } | |
+} | |
+ | |
//----------------------------adjust_map_after_if------------------------------ | |
// Adjust the JVM state to reflect the result of taking this path. | |
// Basically, it means inspecting the CmpNode controlling this | |
@@ -1233,70 +1365,7 @@ | |
if (!have_con) // remaining adjustments need a con | |
return; | |
- | |
- int val_in_map = map()->find_edge(val); | |
- if (val_in_map < 0) return; // replace_in_map would be useless | |
- { | |
- JVMState* jvms = this->jvms(); | |
- if (!(jvms->is_loc(val_in_map) || | |
- jvms->is_stk(val_in_map))) | |
- return; // again, it would be useless | |
- } | |
- | |
- // Check for a comparison to a constant, and "know" that the compared | |
- // value is constrained on this path. | |
- assert(tcon->singleton(), ""); | |
- ConstraintCastNode* ccast = NULL; | |
- Node* cast = NULL; | |
- | |
- switch (btest) { | |
- case BoolTest::eq: // Constant test? | |
- { | |
- const Type* tboth = tcon->join(tval); | |
- if (tboth == tval) break; // Nothing to gain. | |
- if (tcon->isa_int()) { | |
- ccast = new (C, 2) CastIINode(val, tboth); | |
- } else if (tcon == TypePtr::NULL_PTR) { | |
- // Cast to null, but keep the pointer identity temporarily live. | |
- ccast = new (C, 2) CastPPNode(val, tboth); | |
- } else { | |
- const TypeF* tf = tcon->isa_float_constant(); | |
- const TypeD* td = tcon->isa_double_constant(); | |
- // Exclude tests vs float/double 0 as these could be | |
- // either +0 or -0. Just because you are equal to +0 | |
- // doesn't mean you ARE +0! | |
- if ((!tf || tf->_f != 0.0) && | |
- (!td || td->_d != 0.0)) | |
- cast = con; // Replace non-constant val by con. | |
- } | |
- } | |
- break; | |
- | |
- case BoolTest::ne: | |
- if (tcon == TypePtr::NULL_PTR) { | |
- cast = cast_not_null(val, false); | |
- } | |
- break; | |
- | |
- default: | |
- // (At this point we could record int range types with CastII.) | |
- break; | |
- } | |
- | |
- if (ccast != NULL) { | |
- const Type* tcc = ccast->as_Type()->type(); | |
- assert(tcc != tval && tcc->higher_equal(tval), "must improve"); | |
- // Delay transform() call to allow recovery of pre-cast value | |
- // at the control merge. | |
- ccast->set_req(0, control()); | |
- _gvn.set_type_bottom(ccast); | |
- record_for_igvn(ccast); | |
- cast = ccast; | |
- } | |
- | |
- if (cast != NULL) { // Here's the payoff. | |
- replace_in_map(val, cast); | |
- } | |
+ sharpen_type_after_if(this, btest, con, tcon, val, tval); | |
} | |
diff -r bfcf92bfefb8 src/share/vm/opto/subnode.cpp | |
--- a/src/share/vm/opto/subnode.cpp Thu Apr 26 14:05:31 2012 -0700 | |
+++ b/src/share/vm/opto/subnode.cpp Sun May 06 22:42:44 2012 +0800 | |
@@ -702,12 +702,83 @@ | |
return TypeInt::CC; | |
} | |
+static inline Node* isa_java_mirror_load(PhaseGVN* phase, Node* n) { | |
+ // return the klass node for | |
+ // LoadP(AddP(foo:Klass, #java_mirror)) | |
+ // , or NULL if not matching | |
+ if (n->Opcode() != Op_LoadP) return NULL; | |
+ | |
+ const TypeInstPtr* tp = phase->type(n)->isa_instptr(); | |
+ if (!tp || tp->klass() != phase->C->env()->Class_klass()) return NULL; | |
+ | |
+ Node* adr = n->in(MemNode::Address); | |
+ intptr_t off = 0; | |
+ Node* k = AddPNode::Ideal_base_and_offset(adr, phase, off); | |
+ const TypeKlassPtr* tkp = phase->type(k)->isa_klassptr(); | |
+ if (!tkp || off != in_bytes(Klass::java_mirror_offset())) return NULL; | |
+ | |
+ // now we've found the klass node of a Java mirror load | |
+ return k; | |
+} | |
+ | |
+static inline Node* isa_const_java_mirror(PhaseGVN* phase, Node* n) { | |
+ // for ConP(Foo.class) return ConP(Foo.klass) | |
+ // otherwise return NULL | |
+ if (!n->is_Con()) return NULL; | |
+ | |
+ const TypeInstPtr* tp = phase->type(n)->isa_instptr(); | |
+ if (!tp) return NULL; | |
+ | |
+ ciType* mirror_type = tp->java_mirror_type(); | |
+ // TypeInstPtr::java_mirror_type() returns non-NULL for compile- | |
+ // time Class constants only. | |
+ if (!mirror_type) return NULL; | |
+ | |
+ // x.getClass() == int.class can never be true (for all primitive types) | |
+ // Return a ConP(NULL) node for this case. | |
+ if (mirror_type->is_classless()) { | |
+ return phase->makecon(TypePtr::NULL_PTR); | |
+ } | |
+ | |
+ // return the ConP(Foo.klass) | |
+ assert(mirror_type->is_klass(), "mirror_type should represent a klassOop"); | |
+ return phase->makecon(TypeKlassPtr::make(mirror_type->as_klass())); | |
+} | |
+ | |
//------------------------------Ideal------------------------------------------ | |
-// Check for the case of comparing an unknown klass loaded from the primary | |
+// Normalize comparisons between Java mirror loads to compare the klass instead. | |
+// | |
+// Also check for the case of comparing an unknown klass loaded from the primary | |
// super-type array vs a known klass with no subtypes. This amounts to | |
// checking to see an unknown klass subtypes a known klass with no subtypes; | |
// this only happens on an exact match. We can shorten this test by 1 load. | |
Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) { | |
+ // Normalize comparisons between Java mirrors into comparisons of the low- | |
+ // level klass, where a dependent load could be shortened. | |
+ // | |
+ // The new pattern has a nice effect of matching the same pattern used in the | |
+ // fast path of instanceof/checkcast/Class.isInstance(), which allows redundant | |
+ // exact type check be optimized away by GVN. | |
+ // For example, in | |
+ // if (x.getClass() == Foo.class) { | |
+ // Foo foo = (Foo) x; | |
+ // // ... use a ... | |
+ // } | |
+ // a CmpPNode could be shared between if_acmpne and checkcast | |
+ { | |
+ Node* k1 = isa_java_mirror_load(phase, in(1)); | |
+ Node* k2 = isa_java_mirror_load(phase, in(2)); | |
+ Node* conk2 = isa_const_java_mirror(phase, in(2)); | |
+ | |
+ if (k1 && (k2 || conk2)) { | |
+ Node* lhs = k1; | |
+ Node* rhs = k2 != NULL ? k2 : conk2; | |
+ this->set_req(1, lhs); | |
+ this->set_req(2, rhs); | |
+ return this; | |
+ } | |
+ } | |
+ | |
// Constant pointer on right? | |
const TypeKlassPtr* t2 = phase->type(in(2))->isa_klassptr(); | |
if (t2 == NULL || !t2->klass_is_exact()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(gdb) run -XX:-UseTypeProfile -XX:-TieredCompilation InstanceofTest | |
The program being debugged has been started already. | |
Start it from the beginning? (y or n) y | |
Starting program: /home/sajia/testjdk7u1/bin/java -XX:-UseTypeProfile -XX:-TieredCompilation InstanceofTest | |
[Thread debugging using libthread_db enabled] | |
[New Thread 0x2b1a8f8de610 (LWP 26198)] | |
[New Thread 0x401d4940 (LWP 26199)] | |
[New Thread 0x402d5940 (LWP 26200)] | |
[New Thread 0x40c73940 (LWP 26201)] | |
[New Thread 0x40d74940 (LWP 26202)] | |
[New Thread 0x40e75940 (LWP 26203)] | |
[New Thread 0x40f76940 (LWP 26204)] | |
[New Thread 0x41077940 (LWP 26205)] | |
[New Thread 0x41178940 (LWP 26206)] | |
[New Thread 0x41c5e940 (LWP 26207)] | |
[New Thread 0x41d5f940 (LWP 26208)] | |
[New Thread 0x41e60940 (LWP 26209)] | |
[New Thread 0x41f61940 (LWP 26210)] | |
[New Thread 0x42062940 (LWP 26211)] | |
[New Thread 0x42163940 (LWP 26212)] | |
CompilerOracle: exclude InstanceofTest.main | |
CompilerOracle: exclude A.<init> | |
CompilerOracle: exclude A.dump | |
CompilerOracle: exclude java*.* | |
CompilerOracle: exclude sun*.* | |
CompilerOracle: exclude com*.* | |
[New Thread 0x41279940 (LWP 26213)] | |
[New Thread 0x42264940 (LWP 26214)] | |
[New Thread 0x42365940 (LWP 26215)] | |
[New Thread 0x41a00940 (LWP 26216)] | |
[New Thread 0x41b01940 (LWP 26217)] | |
[New Thread 0x42466940 (LWP 26218)] | |
[New Thread 0x42567940 (LWP 26219)] | |
### Excluding generation of native wrapper: java.lang.Object::getClass | |
[Switching to Thread 0x41b01940 (LWP 26217)] | |
Breakpoint 1, extract_obj_from_klass_load (gvn=0x41aff190, n=0x17e8d78) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1170 | |
1170 if (n->is_DecodeN()) { | |
(gdb) next | |
1171 if (n->in(1)->Opcode() != Op_LoadNKlass) { | |
(gdb) | |
1174 ldk = n->in(1); | |
(gdb) | |
1181 assert(ldk != NULL, "should have found a LoadKlass or LoadNKlass node"); | |
(gdb) | |
1183 Node* adr = ldk->in(MemNode::Address); | |
(gdb) | |
1184 intptr_t off = 0; | |
(gdb) | |
1185 Node* obj = AddPNode::Ideal_base_and_offset(adr, gvn, off); | |
(gdb) | |
1186 const TypePtr* tp = gvn->type(obj)->is_ptr(); | |
(gdb) | |
1187 if ( !obj // is adr an AddP node? | |
(gdb) | |
1193 return obj; | |
(gdb) | |
1194 } | |
(gdb) | |
sharpen_type_after_if (parse=0x41afeed0, btest=BoolTest::ne, con=0x17e9250, tcon=0x17f0dc0, val=0x17e8d78, tval=0x17f0a40) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1203 | |
1203 const TypeKlassPtr* tkp = tcon->isa_klassptr(); | |
(gdb) | |
1204 if (obj && tkp && btest == BoolTest::eq) { | |
(gdb) | |
1224 int val_in_map = parse->map()->find_edge(val); | |
(gdb) | |
1225 if (val_in_map < 0) return; // replace_in_map would be useless | |
(gdb) print obj->dump() | |
36 CastPP === 28 10 [[ 20 39 39 54 ]] #IFoo:NotNull * Interface:IFoo:NotNull * !jvms: InstanceofTest::test @ bci:4 | |
$5 = void | |
(gdb) print tkp->dump() | |
precise klass A: 0x00000000017d6f98:Constant:exact *$6 = void | |
(gdb) print btest | |
$7 = BoolTest::ne | |
(gdb) print BoolTest(btest).commute() | |
A syntax error in expression, near `btest).commute()'. | |
(gdb) print ((BoolTest)btest).commute() | |
$8 = BoolTest::ne | |
(gdb) cont | |
Continuing. | |
Breakpoint 1, extract_obj_from_klass_load (gvn=0x41aff190, n=0x17e8d78) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1170 | |
1170 if (n->is_DecodeN()) { | |
(gdb) bt | |
#0 extract_obj_from_klass_load (gvn=0x41aff190, n=0x17e8d78) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1170 | |
#1 0x00002b1a902686cd in sharpen_type_after_if (parse=0x41afeed0, btest=BoolTest::eq, con=0x17e9250, tcon=0x17f0dc0, | |
val=0x17e8d78, tval=0x17f0a40) at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1202 | |
#2 0x00002b1a902692c8 in Parse::adjust_map_after_if (this=0x41afeed0, btest=BoolTest::eq, c=0x17e91e0, prob=0.499962509, | |
path=0x17cbb40, other_path=0x17cbb88) at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1358 | |
#3 0x00002b1a9026a0ca in Parse::do_if (this=0x41afeed0, btest=BoolTest::ne, c=0x17e91e0) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1164 | |
#4 0x00002b1a9027281a in Parse::do_one_bytecode (this=0x41afeed0) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:2233 | |
#5 0x00002b1a90263200 in Parse::do_one_block (this=0x41afeed0) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse1.cpp:1405 | |
#6 0x00002b1a90263661 in Parse::do_all_blocks (this=0x41afeed0) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse1.cpp:680 | |
#7 0x00002b1a902665a7 in Parse (this=0x41afeed0, caller=0x17d8118, parse_method=0x2aaab00139b8, expected_uses=10020) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse1.cpp:589 | |
#8 0x00002b1a8fd4284d in ParseGenerator::generate (this=0x17cbac8, jvms=0x17d8118) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/callGenerator.cpp:85 | |
#9 0x00002b1a8fdfa18b in Compile (this=0x41afff30, ci_env=0x41b00900, compiler=0x2aaab0000908, target=0x2aaab00139b8, | |
osr_bci=-1, subsume_loads=true, do_escape_analysis=true) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/compile.cpp:692 | |
#10 0x00002b1a8fd3da3c in C2Compiler::compile_method (this=0x2aaab0000908, env=0x41b00900, target=0x2aaab00139b8, | |
entry_bci=-1) at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/c2compiler.cpp:130 | |
#11 0x00002b1a8fe01516 in CompileBroker::invoke_compiler_on_method (task=0x2aaab0027ec8) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/compiler/compileBroker.cpp:1760 | |
#12 0x00002b1a8fe03ed4 in CompileBroker::compiler_thread_loop () | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/compiler/compileBroker.cpp:1597 | |
#13 0x00002b1a90380046 in compiler_thread_entry (thread=0x2aaab0001000, __the_thread__=0x2aaab0001000) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/runtime/thread.cpp:3043 | |
#14 0x00002b1a90383b4a in JavaThread::thread_main_inner (this=0x2aaab0001000) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/runtime/thread.cpp:1548 | |
#15 0x00002b1a903861c9 in JavaThread::run (this=0x2aaab0001000) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/runtime/thread.cpp:1528 | |
#16 0x00002b1a9023cc8b in java_start (thread=0x2aaab0001000) | |
at /home/sajia/temp/jdk8/hotspot/src/os/linux/vm/os_linux.cpp:886 | |
#17 0x000000347f4064a7 in start_thread () from /lib64/libpthread.so.0 | |
#18 0x000000347ecd3c2d in clone () from /lib64/libc.so.6 | |
(gdb) frame 2 | |
#2 0x00002b1a902692c8 in Parse::adjust_map_after_if (this=0x41afeed0, btest=BoolTest::eq, c=0x17e91e0, prob=0.499962509, | |
path=0x17cbb40, other_path=0x17cbb88) at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1358 | |
1358 sharpen_type_after_if(this, btest, con, tcon, val, tval); | |
(gdb) print this->bci() | |
$9 = 7 | |
(gdb) frame 0 | |
#0 extract_obj_from_klass_load (gvn=0x41aff190, n=0x17e8d78) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1170 | |
1170 if (n->is_DecodeN()) { | |
(gdb) next | |
1171 if (n->in(1)->Opcode() != Op_LoadNKlass) { | |
(gdb) | |
1174 ldk = n->in(1); | |
(gdb) | |
1181 assert(ldk != NULL, "should have found a LoadKlass or LoadNKlass node"); | |
(gdb) | |
1183 Node* adr = ldk->in(MemNode::Address); | |
(gdb) | |
1184 intptr_t off = 0; | |
(gdb) | |
1185 Node* obj = AddPNode::Ideal_base_and_offset(adr, gvn, off); | |
(gdb) | |
1186 const TypePtr* tp = gvn->type(obj)->is_ptr(); | |
(gdb) | |
1187 if ( !obj // is adr an AddP node? | |
(gdb) | |
1193 return obj; | |
(gdb) | |
1194 } | |
(gdb) | |
sharpen_type_after_if (parse=0x41afeed0, btest=BoolTest::eq, con=0x17e9250, tcon=0x17f0dc0, val=0x17e8d78, tval=0x17f0a40) | |
at /home/sajia/temp/jdk8/hotspot/src/share/vm/opto/parse2.cpp:1203 | |
1203 const TypeKlassPtr* tkp = tcon->isa_klassptr(); | |
(gdb) | |
1204 if (obj && tkp && btest == BoolTest::eq) { | |
(gdb) | |
1205 const TypeOopPtr* obj_xtype = tkp->as_instance_type(); | |
(gdb) | |
1206 if (obj_xtype->isa_instptr() || obj_xtype->isa_aryptr()) { | |
(gdb) | |
1211 assert(obj_xtype->higher_equal(gvn.type(obj)), "must improve"); | |
(gdb) print obj_xtype->join(gvn.type(obj)) | |
$10 = (const Type *) 0x17f0fb0 | |
(gdb) print $10->_base | |
$11 = Type::InstPtr | |
(gdb) print $10->dump() | |
A:NotNull:exact *$12 = void | |
(gdb) print obj_xtype->dump() | |
A:NotNull:exact *$13 = void | |
(gdb) quit | |
The program is running. Exit anyway? (y or n) y | |
$ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment