< prev index next >

src/hotspot/share/classfile/stackMapFrame.cpp

Print this page
@@ -29,14 +29,14 @@
  #include "oops/oop.inline.hpp"
  #include "oops/symbol.hpp"
  #include "runtime/handles.inline.hpp"
  #include "utilities/globalDefinitions.hpp"
  
- StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* v) :
+ StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, AssertUnsetFieldTable* initial_strict_fields, ClassVerifier* v) :
                        _offset(0), _locals_size(0), _stack_size(0),
                        _stack_mark(0), _max_locals(max_locals),
-                       _max_stack(max_stack), _flags(0), _verifier(v) {
+                       _max_stack(max_stack), _flags(0), _assert_unset_fields(initial_strict_fields), _verifier(v) {
    Thread* thr = v->thread();
    _locals = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_locals);
    _stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_stack);
    int32_t i;
    for(i = 0; i < max_locals; i++) {

@@ -45,14 +45,51 @@
    for(i = 0; i < max_stack; i++) {
      _stack[i] = VerificationType::bogus_type();
    }
  }
  
+ void StackMapFrame::unsatisfied_strict_fields_error(InstanceKlass* klass, int bci) {
+   Symbol* name;
+   Symbol* sig;
+   int num_uninit_fields = 0;
+ 
+   auto find_unset = [&] (const NameAndSig& key, const bool& value) {
+     if (!value) {
+       name = key._name;
+       sig = key._signature;
+       num_uninit_fields++;
+     }
+   };
+   assert_unset_fields()->iterate_all(find_unset);
+ 
+   verifier()->verify_error(
+     ErrorContext::bad_strict_fields(bci, this),
+     "All strict final fields must be initialized before super(): %d field(s), %s:%s in %s",
+     num_uninit_fields,
+     name->as_C_string(),
+     sig->as_C_string(),
+     klass->name()->as_C_string()
+   );
+ }
+ 
+ void StackMapFrame::print_strict_fields(AssertUnsetFieldTable* table) {
+   ResourceMark rm;
+   auto printfields = [&] (const NameAndSig& key, const bool& value) {
+     log_info(verification)("Strict field: %s%s (Satisfied: %s)",
+                            key._name->as_C_string(),
+                            key._signature->as_C_string(),
+                            value ? "true" : "false");
+   };
+   table->iterate_all(printfields);
+ }
+ 
  StackMapFrame* StackMapFrame::frame_in_exception_handler(u1 flags) {
    Thread* thr = _verifier->thread();
    VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, 1);
-   StackMapFrame* frame = new StackMapFrame(_offset, flags, _locals_size, 0, _max_locals, _max_stack, _locals, stack, _verifier);
+   StackMapFrame* frame = new StackMapFrame(_offset, flags, _locals_size, 0,
+                                            _max_locals, _max_stack, _locals, stack,
+                                            _assert_unset_fields, _verifier);
    return frame;
  }
  
  void StackMapFrame::initialize_object(
      VerificationType old_object, VerificationType new_object) {

@@ -78,11 +115,11 @@
    SignatureStream ss(m->signature());
    int init_local_num = 0;
    if (!m->is_static()) {
      init_local_num++;
      // add one extra argument for instance method
-     if (m->name() == vmSymbols::object_initializer_name() &&
+     if (m->is_object_constructor() &&
         thisKlass.name() != vmSymbols::java_lang_Object()) {
        _locals[0] = VerificationType::uninitialized_this_type();
        _flags |= FLAG_THIS_UNINIT;
      } else {
        _locals[0] = thisKlass;

@@ -186,10 +223,18 @@
          TypeOrigin::stack(mismatch_loc, (StackMapFrame*)this),
          TypeOrigin::sm_stack(mismatch_loc, (StackMapFrame*)target));
      return false;
    }
  
+   // Check that assert unset fields are compatible
+   bool compatible = verify_unset_fields_compatibility(target->assert_unset_fields());
+   if (!compatible) {
+     *ctx = ErrorContext::strict_fields_mismatch(target->offset(),
+         (StackMapFrame*)this, (StackMapFrame*)target);
+     return false;
+   }
+ 
    if ((_flags | target->flags()) == target->flags()) {
      return true;
    } else {
      *ctx = ErrorContext::bad_flags(target->offset(),
          (StackMapFrame*)this, (StackMapFrame*)target);
< prev index next >