src/share/vm/opto/doCall.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/opto

src/share/vm/opto/doCall.cpp

Print this page
rev 6139 : 8031755: Type speculation should be used to optimize explicit null checks
Summary: feed profiling data about reference nullness to type speculation.
Reviewed-by:


 232         if (hit_cg != NULL) {
 233           // Look up second receiver.
 234           CallGenerator* next_hit_cg = NULL;
 235           ciMethod* next_receiver_method = NULL;
 236           if (morphism == 2 && UseBimorphicInlining) {
 237             next_receiver_method = callee->resolve_invoke(jvms->method()->holder(),
 238                                                                profile.receiver(1));
 239             if (next_receiver_method != NULL) {
 240               next_hit_cg = this->call_generator(next_receiver_method,
 241                                   vtable_index, !call_does_dispatch, jvms,
 242                                   allow_inline, prof_factor);
 243               if (next_hit_cg != NULL && !next_hit_cg->is_inline() &&
 244                   have_major_receiver && UseOnlyInlinedBimorphic) {
 245                   // Skip if we can't inline second receiver's method
 246                   next_hit_cg = NULL;
 247               }
 248             }
 249           }
 250           CallGenerator* miss_cg;
 251           Deoptimization::DeoptReason reason = morphism == 2 ?
 252                                     Deoptimization::Reason_bimorphic :
 253                                     (speculative_receiver_type == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check);
 254           if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) &&
 255               !too_many_traps(jvms->method(), jvms->bci(), reason)
 256              ) {
 257             // Generate uncommon trap for class check failure path
 258             // in case of monomorphic or bimorphic virtual call site.
 259             miss_cg = CallGenerator::for_uncommon_trap(callee, reason,
 260                         Deoptimization::Action_maybe_recompile);
 261           } else {
 262             // Generate virtual call for class check failure path
 263             // in case of polymorphic virtual call site.
 264             miss_cg = CallGenerator::for_virtual_call(callee, vtable_index);
 265           }
 266           if (miss_cg != NULL) {
 267             if (next_hit_cg != NULL) {
 268               assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation");
 269               trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(1), site_count, profile.receiver_count(1));
 270               // We don't need to record dependency on a receiver here and below.
 271               // Whenever we inline, the dependency is added by Parse::Parse().
 272               miss_cg = CallGenerator::for_predicted_call(profile.receiver(1), miss_cg, next_hit_cg, PROB_MAX);
 273             }


 614     // If the return type of the method is not loaded, assert that the
 615     // value we got is a null.  Otherwise, we need to recompile.
 616     if (!rtype->is_loaded()) {
 617 #ifndef PRODUCT
 618       if (PrintOpto && (Verbose || WizardMode)) {
 619         method()->print_name(); tty->print_cr(" asserting nullness of result at bci: %d", bci());
 620         cg->method()->print_name(); tty->cr();
 621       }
 622 #endif
 623       if (C->log() != NULL) {
 624         C->log()->elem("assert_null reason='return' klass='%d'",
 625                        C->log()->identify(rtype));
 626       }
 627       // If there is going to be a trap, put it at the next bytecode:
 628       set_bci(iter().next_bci());
 629       null_assert(peek());
 630       set_bci(iter().cur_bci()); // put it back
 631     }
 632     BasicType ct = ctype->basic_type();
 633     if (ct == T_OBJECT || ct == T_ARRAY) {
 634       ciKlass* better_type = method()->return_profiled_type(bci());
 635       if (UseTypeSpeculation && better_type != NULL) {
 636         // If profiling reports a single type for the return value,
 637         // feed it to the type system so it can propagate it as a
 638         // speculative type
 639         record_profile_for_speculation(stack(sp()-1), better_type);
 640       }
 641     }
 642   }
 643 
 644   // Restart record of parsing work after possible inlining of call
 645 #ifndef PRODUCT
 646   parse_histogram()->set_initial_state(bc());
 647 #endif
 648 }
 649 
 650 //---------------------------catch_call_exceptions-----------------------------
 651 // Put a Catch and CatchProj nodes behind a just-created call.
 652 // Send their caught exceptions to the proper handler.
 653 // This may be used after a call to the rethrow VM stub,
 654 // when it is needed to process unloaded exception classes.
 655 void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
 656   // Exceptions are delivered through this channel:
 657   Node* i_o = this->i_o();
 658 
 659   // Add a CatchNode.
 660   GrowableArray<int>* bcis = new (C->node_arena()) GrowableArray<int>(C->node_arena(), 8, 0, -1);




 232         if (hit_cg != NULL) {
 233           // Look up second receiver.
 234           CallGenerator* next_hit_cg = NULL;
 235           ciMethod* next_receiver_method = NULL;
 236           if (morphism == 2 && UseBimorphicInlining) {
 237             next_receiver_method = callee->resolve_invoke(jvms->method()->holder(),
 238                                                                profile.receiver(1));
 239             if (next_receiver_method != NULL) {
 240               next_hit_cg = this->call_generator(next_receiver_method,
 241                                   vtable_index, !call_does_dispatch, jvms,
 242                                   allow_inline, prof_factor);
 243               if (next_hit_cg != NULL && !next_hit_cg->is_inline() &&
 244                   have_major_receiver && UseOnlyInlinedBimorphic) {
 245                   // Skip if we can't inline second receiver's method
 246                   next_hit_cg = NULL;
 247               }
 248             }
 249           }
 250           CallGenerator* miss_cg;
 251           Deoptimization::DeoptReason reason = morphism == 2 ?
 252             Deoptimization::Reason_bimorphic : Deoptimization::reason_class_check(speculative_receiver_type != NULL);

 253           if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) &&
 254               !too_many_traps(jvms->method(), jvms->bci(), reason)
 255              ) {
 256             // Generate uncommon trap for class check failure path
 257             // in case of monomorphic or bimorphic virtual call site.
 258             miss_cg = CallGenerator::for_uncommon_trap(callee, reason,
 259                         Deoptimization::Action_maybe_recompile);
 260           } else {
 261             // Generate virtual call for class check failure path
 262             // in case of polymorphic virtual call site.
 263             miss_cg = CallGenerator::for_virtual_call(callee, vtable_index);
 264           }
 265           if (miss_cg != NULL) {
 266             if (next_hit_cg != NULL) {
 267               assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation");
 268               trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(1), site_count, profile.receiver_count(1));
 269               // We don't need to record dependency on a receiver here and below.
 270               // Whenever we inline, the dependency is added by Parse::Parse().
 271               miss_cg = CallGenerator::for_predicted_call(profile.receiver(1), miss_cg, next_hit_cg, PROB_MAX);
 272             }


 613     // If the return type of the method is not loaded, assert that the
 614     // value we got is a null.  Otherwise, we need to recompile.
 615     if (!rtype->is_loaded()) {
 616 #ifndef PRODUCT
 617       if (PrintOpto && (Verbose || WizardMode)) {
 618         method()->print_name(); tty->print_cr(" asserting nullness of result at bci: %d", bci());
 619         cg->method()->print_name(); tty->cr();
 620       }
 621 #endif
 622       if (C->log() != NULL) {
 623         C->log()->elem("assert_null reason='return' klass='%d'",
 624                        C->log()->identify(rtype));
 625       }
 626       // If there is going to be a trap, put it at the next bytecode:
 627       set_bci(iter().next_bci());
 628       null_assert(peek());
 629       set_bci(iter().cur_bci()); // put it back
 630     }
 631     BasicType ct = ctype->basic_type();
 632     if (ct == T_OBJECT || ct == T_ARRAY) {
 633       record_profiled_return_for_speculation();






 634     }
 635   }
 636 
 637   // Restart record of parsing work after possible inlining of call
 638 #ifndef PRODUCT
 639   parse_histogram()->set_initial_state(bc());
 640 #endif
 641 }
 642 
 643 //---------------------------catch_call_exceptions-----------------------------
 644 // Put a Catch and CatchProj nodes behind a just-created call.
 645 // Send their caught exceptions to the proper handler.
 646 // This may be used after a call to the rethrow VM stub,
 647 // when it is needed to process unloaded exception classes.
 648 void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
 649   // Exceptions are delivered through this channel:
 650   Node* i_o = this->i_o();
 651 
 652   // Add a CatchNode.
 653   GrowableArray<int>* bcis = new (C->node_arena()) GrowableArray<int>(C->node_arena(), 8, 0, -1);


src/share/vm/opto/doCall.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File