7171890: C1: add Class.isInstance intrinsic

Tue, 05 Jun 2012 10:15:27 +0200

author
roland
date
Tue, 05 Jun 2012 10:15:27 +0200
changeset 3838
8f37087fc13f
parent 3837
7bc2d5136f54
child 3839
e1635876b206

7171890: C1: add Class.isInstance intrinsic
Summary: Class.cast which calls Class.isInstance is heavily used by the new JSR 292 implementation
Reviewed-by: roland
Contributed-by: Krystal Mok <rednaxelafx@gmail.com>

src/share/vm/c1/c1_Canonicalizer.cpp file | annotate | diff | comparison | revisions
src/share/vm/c1/c1_GraphBuilder.cpp file | annotate | diff | comparison | revisions
src/share/vm/c1/c1_LIRGenerator.cpp file | annotate | diff | comparison | revisions
src/share/vm/c1/c1_LIRGenerator.hpp file | annotate | diff | comparison | revisions
src/share/vm/c1/c1_Runtime1.cpp file | annotate | diff | comparison | revisions
src/share/vm/c1/c1_Runtime1.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/c1/c1_Canonicalizer.cpp	Fri Jun 01 11:25:12 2012 -0700
     1.2 +++ b/src/share/vm/c1/c1_Canonicalizer.cpp	Tue Jun 05 10:15:27 2012 +0200
     1.3 @@ -456,6 +456,28 @@
     1.4      }
     1.5      break;
     1.6    }
     1.7 +  case vmIntrinsics::_isInstance          : {
     1.8 +    assert(x->number_of_arguments() == 2, "wrong type");
     1.9 +
    1.10 +    InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
    1.11 +    if (c != NULL && !c->value()->is_null_object()) {
    1.12 +      // ciInstance::java_mirror_type() returns non-NULL only for Java mirrors
    1.13 +      ciType* t = c->value()->as_instance()->java_mirror_type();
    1.14 +      if (t->is_klass()) {
    1.15 +        // substitute cls.isInstance(obj) of a constant Class into
    1.16 +        // an InstantOf instruction
    1.17 +        InstanceOf* i = new InstanceOf(t->as_klass(), x->argument_at(1), x->state());
    1.18 +        set_canonical(i);
    1.19 +        // and try to canonicalize even further
    1.20 +        do_InstanceOf(i);
    1.21 +      } else {
    1.22 +        assert(t->is_primitive_type(), "should be a primitive type");
    1.23 +        // cls.isInstance(obj) always returns false for primitive classes
    1.24 +        set_constant(0);
    1.25 +      }
    1.26 +    }
    1.27 +    break;
    1.28 +  }
    1.29    }
    1.30  }
    1.31  
     2.1 --- a/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Jun 01 11:25:12 2012 -0700
     2.2 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Jun 05 10:15:27 2012 +0200
     2.3 @@ -3170,6 +3170,7 @@
     2.4        break;
     2.5  
     2.6      case vmIntrinsics::_getClass      :
     2.7 +    case vmIntrinsics::_isInstance    :
     2.8        if (!InlineClassNatives) return false;
     2.9        preserves_state = true;
    2.10        break;
     3.1 --- a/src/share/vm/c1/c1_LIRGenerator.cpp	Fri Jun 01 11:25:12 2012 -0700
     3.2 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Tue Jun 05 10:15:27 2012 +0200
     3.3 @@ -1242,6 +1242,36 @@
     3.4                NULL   /* info */);
     3.5  }
     3.6  
     3.7 +// Example: clazz.isInstance(object)
     3.8 +void LIRGenerator::do_isInstance(Intrinsic* x) {
     3.9 +  assert(x->number_of_arguments() == 2, "wrong type");
    3.10 +
    3.11 +  // TODO could try to substitute this node with an equivalent InstanceOf
    3.12 +  // if clazz is known to be a constant Class. This will pick up newly found
    3.13 +  // constants after HIR construction. I'll leave this to a future change.
    3.14 +
    3.15 +  // as a first cut, make a simple leaf call to runtime to stay platform independent.
    3.16 +  // could follow the aastore example in a future change.
    3.17 +
    3.18 +  LIRItem clazz(x->argument_at(0), this);
    3.19 +  LIRItem object(x->argument_at(1), this);
    3.20 +  clazz.load_item();
    3.21 +  object.load_item();
    3.22 +  LIR_Opr result = rlock_result(x);
    3.23 +
    3.24 +  // need to perform null check on clazz
    3.25 +  if (x->needs_null_check()) {
    3.26 +    CodeEmitInfo* info = state_for(x);
    3.27 +    __ null_check(clazz.result(), info);
    3.28 +  }
    3.29 +
    3.30 +  LIR_Opr call_result = call_runtime(clazz.value(), object.value(),
    3.31 +                                     CAST_FROM_FN_PTR(address, Runtime1::is_instance_of),
    3.32 +                                     x->type(),
    3.33 +                                     NULL); // NULL CodeEmitInfo results in a leaf call
    3.34 +  __ move(call_result, result);
    3.35 +}
    3.36 +
    3.37  // Example: object.getClass ()
    3.38  void LIRGenerator::do_getClass(Intrinsic* x) {
    3.39    assert(x->number_of_arguments() == 1, "wrong type");
    3.40 @@ -2951,6 +2981,7 @@
    3.41      break;
    3.42  
    3.43    case vmIntrinsics::_Object_init:    do_RegisterFinalizer(x); break;
    3.44 +  case vmIntrinsics::_isInstance:     do_isInstance(x);    break;
    3.45    case vmIntrinsics::_getClass:       do_getClass(x);      break;
    3.46    case vmIntrinsics::_currentThread:  do_currentThread(x); break;
    3.47  
     4.1 --- a/src/share/vm/c1/c1_LIRGenerator.hpp	Fri Jun 01 11:25:12 2012 -0700
     4.2 +++ b/src/share/vm/c1/c1_LIRGenerator.hpp	Tue Jun 05 10:15:27 2012 +0200
     4.3 @@ -238,6 +238,7 @@
     4.4    LIR_Opr getThreadPointer();
     4.5  
     4.6    void do_RegisterFinalizer(Intrinsic* x);
     4.7 +  void do_isInstance(Intrinsic* x);
     4.8    void do_getClass(Intrinsic* x);
     4.9    void do_currentThread(Intrinsic* x);
    4.10    void do_MathIntrinsic(Intrinsic* x);
     5.1 --- a/src/share/vm/c1/c1_Runtime1.cpp	Fri Jun 01 11:25:12 2012 -0700
     5.2 +++ b/src/share/vm/c1/c1_Runtime1.cpp	Tue Jun 05 10:15:27 2012 +0200
     5.3 @@ -294,6 +294,7 @@
     5.4    FUNCTION_CASE(entry, SharedRuntime::lrem);
     5.5    FUNCTION_CASE(entry, SharedRuntime::dtrace_method_entry);
     5.6    FUNCTION_CASE(entry, SharedRuntime::dtrace_method_exit);
     5.7 +  FUNCTION_CASE(entry, is_instance_of);
     5.8    FUNCTION_CASE(entry, trace_block_entry);
     5.9  #ifdef TRACE_HAVE_INTRINSICS
    5.10    FUNCTION_CASE(entry, TRACE_TIME_METHOD);
    5.11 @@ -1270,6 +1271,19 @@
    5.12  JRT_END
    5.13  
    5.14  
    5.15 +JRT_LEAF(int, Runtime1::is_instance_of(oopDesc* mirror, oopDesc* obj))
    5.16 +  // had to return int instead of bool, otherwise there may be a mismatch
    5.17 +  // between the C calling convention and the Java one.
    5.18 +  // e.g., on x86, GCC may clear only %al when returning a bool false, but
    5.19 +  // JVM takes the whole %eax as the return value, which may misinterpret
    5.20 +  // the return value as a boolean true.
    5.21 +
    5.22 +  assert(mirror != NULL, "should null-check on mirror before calling");
    5.23 +  klassOop k = java_lang_Class::as_klassOop(mirror);
    5.24 +  return (k != NULL && obj != NULL && obj->is_a(k)) ? 1 : 0;
    5.25 +JRT_END
    5.26 +
    5.27 +
    5.28  #ifndef PRODUCT
    5.29  void Runtime1::print_statistics() {
    5.30    tty->print_cr("C1 Runtime statistics:");
     6.1 --- a/src/share/vm/c1/c1_Runtime1.hpp	Fri Jun 01 11:25:12 2012 -0700
     6.2 +++ b/src/share/vm/c1/c1_Runtime1.hpp	Tue Jun 05 10:15:27 2012 +0200
     6.3 @@ -186,6 +186,7 @@
     6.4    static int  arraycopy(oopDesc* src, int src_pos, oopDesc* dst, int dst_pos, int length);
     6.5    static void primitive_arraycopy(HeapWord* src, HeapWord* dst, int length);
     6.6    static void oop_arraycopy(HeapWord* src, HeapWord* dst, int length);
     6.7 +  static int  is_instance_of(oopDesc* mirror, oopDesc* obj);
     6.8  
     6.9    static void print_statistics()                 PRODUCT_RETURN;
    6.10  };

mercurial