changeset 13021:06653fdee38e mvt

box/vunbox should throw ClassCastException if target type is invalid
author thartmann
date Fri, 09 Jun 2017 15:03:46 +0200
parents 4cd1b06ce224
children 3a4ea109aeb9
files src/share/vm/ci/ciTypeFlow.cpp src/share/vm/opto/parse3.cpp test/compiler/valhalla/valuetypes/ValueTypeTestBench.java
diffstat 3 files changed, 20 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/ci/ciTypeFlow.cpp	Thu Jun 08 18:25:59 2017 +0200
+++ b/src/share/vm/ci/ciTypeFlow.cpp	Fri Jun 09 15:03:46 2017 +0200
@@ -855,9 +855,9 @@
   ciKlass* klass = str->get_klass(will_link);
   // TODO: Handle case when class is not loaded.
   guarantee(will_link, "Class to which the value-capable class will unbox to must be loaded for JIT compilation");
-  assert(klass->is_valuetype(), "must be value type");
+  assert(klass->is_instance_klass(), "must be an instance class");
   pop_object();
-  push_object(klass->as_value_klass());
+  push_object(klass->as_instance_klass());
 }
 
 void ciTypeFlow::StateVector::do_vbox(ciBytecodeStream* str) {
--- a/src/share/vm/opto/parse3.cpp	Thu Jun 08 18:25:59 2017 +0200
+++ b/src/share/vm/opto/parse3.cpp	Fri Jun 09 15:03:46 2017 +0200
@@ -546,25 +546,25 @@
 
   // Obtain source type
   ValueTypeNode* vt = peek()->as_ValueType();
-  const TypeValueType* source_type = gvn().type(vt)->isa_valuetype();
-  guarantee(source_type != NULL && source_type->value_klass() != NULL && source_type->value_klass()->is_loaded(),
-            "vbox: Source class must be a value type and must be loaded");
-
-  ciInstanceKlass* target_vcc_klass = target_klass->as_instance_klass();
-  guarantee(target_vcc_klass->derive_value_type() != NULL, "vbox: Target class must have a derived value type class linked");
-  ciValueKlass* target_dvt_klass = target_vcc_klass->derive_value_type()->as_value_klass();
+  const TypeValueType* src_type = gvn().type(vt)->isa_valuetype();
+  guarantee(src_type != NULL, "vbox: Source type must not be null");
+  ciValueKlass* src_vk = src_type->value_klass();
+  guarantee(src_vk != NULL && src_vk->is_loaded() && src_vk->exact_klass(),
+            "vbox: Source class must be a value type and must be loaded and exact");
 
   kill_dead_locals();
 
+  ciInstanceKlass* target_vcc_klass = target_klass->as_instance_klass();
+  ciInstanceKlass* target_dvt_klass = target_vcc_klass->derive_value_type();
+
   // TODO: Extend type check below if (and once) value type class hierarchies become available.
   // (incl. extension to support dynamic type checks).
-  guarantee(source_type->value_klass()->exact_klass(), "Value type classes are exact");
-  if (!source_type->value_klass()->equals(target_dvt_klass)) {
+  if (!src_vk->equals(target_dvt_klass)) {
     builtin_throw(Deoptimization::Reason_class_check);
     guarantee(stopped(), "A ClassCastException must be always thrown on this path");
     return;
   }
-
+  guarantee(target_dvt_klass->is_valuetype(), "vbox: Target DVT must be a value type");
   pop();
 
   // Create new object
@@ -596,7 +596,7 @@
   bool will_link;
   ciKlass* target_klass = iter().get_klass(will_link);
   guarantee(will_link, "vunbox: Derived value type must be loaded");
-  guarantee(target_klass->is_valuetype(), "vunbox: Target class must be a value type");
+  guarantee(target_klass->is_instance_klass(), "vunbox: Target class must be an instance type");
 
   // Obtain source type
   const TypeOopPtr* source_type = gvn().type(not_null_obj)->isa_oopptr();
@@ -604,19 +604,19 @@
             source_type->klass()->is_instance_klass() && source_type->klass()->is_loaded(),
             "vunbox: Source class must be an instance type and must be loaded");
 
-  ciValueKlass* target_dvt_klass = target_klass->as_value_klass();
-  guarantee(target_dvt_klass->derive_value_type() != NULL, "vunbox: Target class must have a value-capable class linked");
-  ciInstanceKlass* target_vcc_klass = target_dvt_klass->derive_value_type()->as_instance_klass();
+  ciInstanceKlass* target_dvt_klass = target_klass->as_instance_klass();
+  ciInstanceKlass* target_vcc_klass = target_dvt_klass->derive_value_type();
 
   // Check if the class of the source is a subclass of the value-capable class
   // corresponding to the target.
   // TOOD: Implement profiling of vunbox bytecodes to enable type speculation.
-  if (!target_vcc_klass->is_subclass_of(source_type->klass())) {
+  if (target_vcc_klass == NULL || !source_type->klass()->is_subclass_of(target_vcc_klass)) {
     // It is obvious at compile-time that source and target are unrelated.
     builtin_throw(Deoptimization::Reason_class_check);
     guarantee(stopped(), "A ClassCastException must be always thrown on this path");
     return;
   }
+  guarantee(target_dvt_klass->is_valuetype(), "vunbox: Target DVT must be a value type");
 
   if (!target_vcc_klass->equals(source_type->klass()) || !source_type->klass_is_exact()) {
     Node* exact_obj = not_null_obj;
@@ -634,7 +634,8 @@
   pop();
 
   // Create a value type node with the corresponding type
-  Node* vt = ValueTypeNode::make(gvn(), target_dvt_klass, map()->memory(), not_null_obj, not_null_obj, target_vcc_klass, target_dvt_klass->first_field_offset());
+  ciValueKlass* vk = target_dvt_klass->as_value_klass();
+  Node* vt = ValueTypeNode::make(gvn(), vk, map()->memory(), not_null_obj, not_null_obj, target_vcc_klass, vk->first_field_offset());
 
   // Push the value type onto the stack
   push(vt);
--- a/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java	Thu Jun 08 18:25:59 2017 +0200
+++ b/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java	Fri Jun 09 15:03:46 2017 +0200
@@ -1866,7 +1866,7 @@
     /* Generate an if-then-else construct with one path that contains
      * an invalid boxing operation (boxing of a value-type to a
      * non-matching value-capable class).*/
-    @Test(match = {NPE,CCE}, matchCount = {2,3})
+    @Test(match = {NPE, CCE}, matchCount = {2, 2})
     public long test65(Object obj, boolean warmup) throws Throwable {
         return (long)objectBoxMH.invokeExact(obj, warmup);
     }