My Patch for Defect 6478991

Tom Rodriguez Thomas.Rodriguez at Sun.COM
Wed Jan 9 16:18:42 PST 2008


As Christian says your fix isn't really right.  The main thing this code 
it try to do is fold an explicit null check into an implicit one so we 
don't end up with extra checks and state.  Call sites commonly have 
explicit null checks once they are inlined and field accesses have 
implicit null checks so by folding the state of the explicit check into 
the field access we can eliminate extra work.  We have to careful that 
we don't end up reordering exceptions which is what Christians test 
showed.  Any instruction which might throw an exception should clear the 
last explicit null check so that its state doesn't get moved past the 
other exception point.  So we should be calling 
clear_last_explicit_null_check() for some instruction which we're not. 
Does that make it clearer?

tom


rgougol at email.sjsu.edu wrote:
> Hello everybody and thanks for the feedbacks so far,
> 
> Here comes my suggested patch for the defect of NullCheck Elimination. Basically
> it sets a flag if a type check operation is iterated. This flag prevents the 
> optimizations of folding the NullChecks and let the elimination of the latter
> NullCheck exception instead of the former. The flag is unset when the last
> explicit exception is set. I will be very thankful if I get any feedback? Shall
> I extend the patch to all the trap instruction besides type checks? Can also
> somebody explain me what is the purpose of folding null check exception and why
> should the former null check be eliminated instead of the latter? 
> 
> --- openjdk/hotspot/src/share/vm/c1/c1_Optimizer.cpp	2007-10-12
> 00:46:03.000000000 -0700
> +++ nullcheck-openjdk/hotspot/src/share/vm/c1/c1_Optimizer.cpp	2007-12-19
> 14:22:58.000000000 -0800
> @@ -490,6 +490,9 @@
>    // Returns true if caused a change in the block's state.
>    bool      merge_state_for(BlockBegin* block,
>                              ValueSet*   incoming_state);
> +  Instruction *  _prior_type_check;
> +  Instruction *  prior_type_check() const { return _prior_type_check; }
> +  void set_prior_type_check(Instruction * instr) { _prior_type_check = instr; } 
>  
>   public:
>    // constructor
> @@ -498,7 +501,8 @@
>      , _set(new ValueSet())
>      , _last_explicit_null_check(NULL)
>      , _block_states(BlockBegin::number_of_blocks(), NULL)
> -    , _work_list(new BlockList()) {
> +    , _work_list(new BlockList())
> +    , _prior_type_check (NULL)  {
>      _visitable_instructions = new ValueSet();
>      _visitor.set_eliminator(this);
>    }
> @@ -715,6 +719,9 @@
>      // visiting instructions which are references in other blocks or
>      // visiting instructions more than once.
>      mark_visitable(instr);
> +    if (instr->as_TypeCheck() != NULL ) {
> +	set_prior_type_check(instr);
> +    }
>      if (instr->is_root() || instr->can_trap() || (instr->as_NullCheck() != NULL)) {
>        mark_visited(instr);
>        instr->input_values_do(&NullCheckEliminator::do_value);
> @@ -769,13 +776,14 @@
>    Value obj = x->obj();
>    if (set_contains(obj)) {
>      // Value is non-null => update AccessField
> -    if (last_explicit_null_check_obj() == obj && !x->needs_patching()) {
> +    if (last_explicit_null_check_obj() == obj && !x->needs_patching() && !
> prior_type_check()) {
>      } else {
>        x->set_explicit_null_check(NULL);
>        x->set_needs_null_check(false);
> @@ -800,7 +808,7 @@
>    Value array = x->array();
>    if (set_contains(array)) {
>      // Value is non-null => update AccessArray
> -    if (last_explicit_null_check_obj() == array) {
> +    if (last_explicit_null_check_obj() == array && ! prior_type_check()) {
>        x->set_explicit_null_check(consume_last_explicit_null_check());
>        x->set_needs_null_check(true);
>        if (PrintNullCheckElimination) {
> @@ -831,7 +839,7 @@
>    Value array = x->array();
>    if (set_contains(array)) {
>      // Value is non-null => update AccessArray
> -    if (last_explicit_null_check_obj() == array) {
> +    if (last_explicit_null_check_obj() == array && ! prior_type_check()) {
>        x->set_explicit_null_check(consume_last_explicit_null_check());
>        x->set_needs_null_check(true);
>        if (PrintNullCheckElimination) {
> @@ -898,6 +906,7 @@
>      if (PrintNullCheckElimination) {
>        tty->print_cr("NullCheck %d of value %d proves value to be non-null",
> x->id(), obj->id());
>      }
> +    set_prior_type_check(NULL);
>    }
>  }
>  
> 
> Sincerely,
> 
> Rouhollah Gougol
> 
> 
> 



More information about the hotspot-compiler-dev mailing list