< prev index next >

src/hotspot/share/c1/c1_Runtime1.cpp

Print this page
*** 51,10 ***
--- 51,12 ---
  #include "memory/allocation.inline.hpp"
  #include "memory/oopFactory.hpp"
  #include "memory/resourceArea.hpp"
  #include "memory/universe.hpp"
  #include "oops/access.inline.hpp"
+ #include "oops/flatArrayKlass.hpp"
+ #include "oops/flatArrayOop.inline.hpp"
  #include "oops/klass.inline.hpp"
  #include "oops/objArrayOop.inline.hpp"
  #include "oops/objArrayKlass.hpp"
  #include "oops/oop.inline.hpp"
  #include "prims/jvmtiExport.hpp"

*** 120,21 ***
--- 122,28 ---
  uint Runtime1::_arraycopy_slowcase_cnt = 0;
  uint Runtime1::_arraycopy_checkcast_cnt = 0;
  uint Runtime1::_arraycopy_checkcast_attempt_cnt = 0;
  uint Runtime1::_new_type_array_slowcase_cnt = 0;
  uint Runtime1::_new_object_array_slowcase_cnt = 0;
+ uint Runtime1::_new_flat_array_slowcase_cnt = 0;
  uint Runtime1::_new_instance_slowcase_cnt = 0;
  uint Runtime1::_new_multi_array_slowcase_cnt = 0;
+ uint Runtime1::_load_flat_array_slowcase_cnt = 0;
+ uint Runtime1::_store_flat_array_slowcase_cnt = 0;
+ uint Runtime1::_substitutability_check_slowcase_cnt = 0;
+ uint Runtime1::_buffer_inline_args_slowcase_cnt = 0;
+ uint Runtime1::_buffer_inline_args_no_receiver_slowcase_cnt = 0;
  uint Runtime1::_monitorenter_slowcase_cnt = 0;
  uint Runtime1::_monitorexit_slowcase_cnt = 0;
  uint Runtime1::_patch_code_slowcase_cnt = 0;
  uint Runtime1::_throw_range_check_exception_count = 0;
  uint Runtime1::_throw_index_exception_count = 0;
  uint Runtime1::_throw_div0_exception_count = 0;
  uint Runtime1::_throw_null_pointer_exception_count = 0;
  uint Runtime1::_throw_class_cast_exception_count = 0;
  uint Runtime1::_throw_incompatible_class_change_error_count = 0;
+ uint Runtime1::_throw_illegal_monitor_state_exception_count = 0;
  uint Runtime1::_throw_count = 0;
  
  static uint _byte_arraycopy_stub_cnt = 0;
  static uint _short_arraycopy_stub_cnt = 0;
  static uint _int_arraycopy_stub_cnt = 0;

*** 346,15 ***
  
    // Soft float adds more runtime names.
    return pd_name_for_address(entry);
  }
  
! 
- JRT_ENTRY(void, Runtime1::new_instance(JavaThread* current, Klass* klass))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
!     _new_instance_slowcase_cnt++;
    }
  #endif
    assert(klass->is_klass(), "not a class");
    Handle holder(current, klass->klass_holder()); // keep the klass alive
    InstanceKlass* h = InstanceKlass::cast(klass);
--- 355,14 ---
  
    // Soft float adds more runtime names.
    return pd_name_for_address(entry);
  }
  
! static void allocate_instance(JavaThread* current, Klass* klass, TRAPS) {
  #ifndef PRODUCT
    if (PrintC1Statistics) {
!     Runtime1::_new_instance_slowcase_cnt++;
    }
  #endif
    assert(klass->is_klass(), "not a class");
    Handle holder(current, klass->klass_holder()); // keep the klass alive
    InstanceKlass* h = InstanceKlass::cast(klass);

*** 364,10 ***
--- 372,22 ---
    // allocate instance and return via TLS
    oop obj = h->allocate_instance(CHECK);
    current->set_vm_result(obj);
  JRT_END
  
+ JRT_ENTRY(void, Runtime1::new_instance(JavaThread* current, Klass* klass))
+   allocate_instance(current, klass, CHECK);
+ JRT_END
+ 
+ // Same as new_instance but throws error for inline klasses
+ JRT_ENTRY(void, Runtime1::new_instance_no_inline(JavaThread* current, Klass* klass))
+   if (klass->is_inline_klass()) {
+     SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_InstantiationError());
+   } else {
+     allocate_instance(current, klass, CHECK);
+   }
+ JRT_END
  
  JRT_ENTRY(void, Runtime1::new_type_array(JavaThread* current, Klass* klass, jint length))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _new_type_array_slowcase_cnt++;

*** 398,21 ***
    // Note: no handle for klass needed since they are not used
    //       anymore after new_objArray() and no GC can happen before.
    //       (This may have to change if this code changes!)
    assert(array_klass->is_klass(), "not a class");
    Handle holder(current, array_klass->klass_holder()); // keep the klass alive
!   Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass();
    objArrayOop obj = oopFactory::new_objArray(elem_klass, length, CHECK);
    current->set_vm_result(obj);
    // This is pretty rare but this runtime patch is stressful to deoptimization
    // if we deoptimize here so force a deopt to stress the path.
    if (DeoptimizeALot) {
      deopt_caller(current);
    }
  JRT_END
  
  
  JRT_ENTRY(void, Runtime1::new_multi_array(JavaThread* current, Klass* klass, int rank, jint* dims))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _new_multi_array_slowcase_cnt++;
    }
--- 418,43 ---
    // Note: no handle for klass needed since they are not used
    //       anymore after new_objArray() and no GC can happen before.
    //       (This may have to change if this code changes!)
    assert(array_klass->is_klass(), "not a class");
    Handle holder(current, array_klass->klass_holder()); // keep the klass alive
!   Klass* elem_klass = ArrayKlass::cast(array_klass)->element_klass();
    objArrayOop obj = oopFactory::new_objArray(elem_klass, length, CHECK);
    current->set_vm_result(obj);
    // This is pretty rare but this runtime patch is stressful to deoptimization
    // if we deoptimize here so force a deopt to stress the path.
    if (DeoptimizeALot) {
      deopt_caller(current);
    }
  JRT_END
  
  
+ JRT_ENTRY(void, Runtime1::new_flat_array(JavaThread* current, Klass* array_klass, jint length))
+   NOT_PRODUCT(_new_flat_array_slowcase_cnt++;)
+ 
+   // Note: no handle for klass needed since they are not used
+   //       anymore after new_objArray() and no GC can happen before.
+   //       (This may have to change if this code changes!)
+   assert(array_klass->is_klass(), "not a class");
+   Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive
+   Klass* elem_klass = ArrayKlass::cast(array_klass)->element_klass();
+   assert(elem_klass->is_inline_klass(), "must be");
+   // Logically creates elements, ensure klass init
+   elem_klass->initialize(CHECK);
+   arrayOop obj = oopFactory::new_valueArray(elem_klass, length, CHECK);
+   current->set_vm_result(obj);
+   // This is pretty rare but this runtime patch is stressful to deoptimization
+   // if we deoptimize here so force a deopt to stress the path.
+   if (DeoptimizeALot) {
+     deopt_caller(current);
+   }
+ JRT_END
+ 
+ 
  JRT_ENTRY(void, Runtime1::new_multi_array(JavaThread* current, Klass* klass, int rank, jint* dims))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _new_multi_array_slowcase_cnt++;
    }

*** 423,10 ***
--- 465,91 ---
    oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK);
    current->set_vm_result(obj);
  JRT_END
  
  
+ static void profile_flat_array(JavaThread* current) {
+   ResourceMark rm(current);
+   vframeStream vfst(current, true);
+   assert(!vfst.at_end(), "Java frame must exist");
+   // Check if array access profiling is enabled
+   if (vfst.nm()->comp_level() != CompLevel_full_profile || !C1UpdateMethodData) {
+     return;
+   }
+   int bci = vfst.bci();
+   Method* method = vfst.method();
+   MethodData* md = method->method_data();
+   if (md != nullptr) {
+     ProfileData* data = md->bci_to_data(bci);
+     assert(data != nullptr && data->is_ArrayLoadStoreData(), "incorrect profiling entry");
+     ArrayLoadStoreData* load_store = (ArrayLoadStoreData*)data;
+     load_store->set_flat_array();
+   }
+ }
+ 
+ JRT_ENTRY(void, Runtime1::load_flat_array(JavaThread* current, flatArrayOopDesc* array, int index))
+   assert(array->klass()->is_flatArray_klass(), "should not be called");
+   profile_flat_array(current);
+ 
+   NOT_PRODUCT(_load_flat_array_slowcase_cnt++;)
+   assert(array->length() > 0 && index < array->length(), "already checked");
+   flatArrayHandle vah(current, array);
+   oop obj = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, CHECK);
+   current->set_vm_result(obj);
+ JRT_END
+ 
+ 
+ JRT_ENTRY(void, Runtime1::store_flat_array(JavaThread* current, flatArrayOopDesc* array, int index, oopDesc* value))
+   if (array->klass()->is_flatArray_klass()) {
+     profile_flat_array(current);
+   }
+ 
+   NOT_PRODUCT(_store_flat_array_slowcase_cnt++;)
+   if (value == nullptr) {
+     assert(array->klass()->is_flatArray_klass() || array->klass()->is_null_free_array_klass(), "should not be called");
+     SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_NullPointerException());
+   } else {
+     assert(array->klass()->is_flatArray_klass(), "should not be called");
+     array->value_copy_to_index(value, index);
+   }
+ JRT_END
+ 
+ 
+ JRT_ENTRY(int, Runtime1::substitutability_check(JavaThread* current, oopDesc* left, oopDesc* right))
+   NOT_PRODUCT(_substitutability_check_slowcase_cnt++;)
+   JavaCallArguments args;
+   args.push_oop(Handle(THREAD, left));
+   args.push_oop(Handle(THREAD, right));
+   JavaValue result(T_BOOLEAN);
+   JavaCalls::call_static(&result,
+                          vmClasses::ValueObjectMethods_klass(),
+                          vmSymbols::isSubstitutable_name(),
+                          vmSymbols::object_object_boolean_signature(),
+                          &args, CHECK_0);
+   return result.get_jboolean() ? 1 : 0;
+ JRT_END
+ 
+ 
+ extern "C" void ps();
+ 
+ void Runtime1::buffer_inline_args_impl(JavaThread* current, Method* m, bool allocate_receiver) {
+   JavaThread* THREAD = current;
+   methodHandle method(current, m); // We are inside the verified_entry or verified_inline_ro_entry of this method.
+   oop obj = SharedRuntime::allocate_inline_types_impl(current, method, allocate_receiver, CHECK);
+   current->set_vm_result(obj);
+ }
+ 
+ JRT_ENTRY(void, Runtime1::buffer_inline_args(JavaThread* current, Method* method))
+   NOT_PRODUCT(_buffer_inline_args_slowcase_cnt++;)
+   buffer_inline_args_impl(current, method, true);
+ JRT_END
+ 
+ JRT_ENTRY(void, Runtime1::buffer_inline_args_no_receiver(JavaThread* current, Method* method))
+   NOT_PRODUCT(_buffer_inline_args_no_receiver_slowcase_cnt++;)
+   buffer_inline_args_impl(current, method, false);
+ JRT_END
+ 
  JRT_ENTRY(void, Runtime1::unimplemented_entry(JavaThread* current, StubID id))
    tty->print_cr("Runtime1::entry_for(%d) returned unimplemented entry point", id);
  JRT_END
  
  

*** 746,10 ***
--- 869,16 ---
    ResourceMark rm(current);
    SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_IncompatibleClassChangeError());
  JRT_END
  
  
+ JRT_ENTRY(void, Runtime1::throw_illegal_monitor_state_exception(JavaThread* current))
+   NOT_PRODUCT(_throw_illegal_monitor_state_exception_count++;)
+   ResourceMark rm(current);
+   SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_IllegalMonitorStateException());
+ JRT_END
+ 
  JRT_BLOCK_ENTRY(void, Runtime1::monitorenter(JavaThread* current, oopDesc* obj, BasicObjectLock* lock))
  #ifndef PRODUCT
    if (PrintC1Statistics) {
      _monitorenter_slowcase_cnt++;
    }

*** 967,10 ***
--- 1096,11 ---
      fieldDescriptor result; // initialize class if needed
      Bytecodes::Code code = field_access.code();
      constantPoolHandle constants(current, caller_method->constants());
      LinkResolver::resolve_field_access(result, constants, field_access.index(), caller_method, Bytecodes::java_code(code), CHECK);
      patch_field_offset = result.offset();
+     assert(!result.is_flat(), "Can not patch access to flat field");
  
      // If we're patching a field which is volatile then at compile it
      // must not have been know to be volatile, so the generated code
      // isn't correct for a volatile reference.  The nmethod has to be
      // deoptimized so that the code can be regenerated correctly.

*** 1009,13 ***
--- 1139,22 ---
        case Bytecodes::_new:
          { Bytecode_new bnew(caller_method(), caller_method->bcp_from(bci));
            k = caller_method->constants()->klass_at(bnew.index(), CHECK);
          }
          break;
+       case Bytecodes::_aconst_init:
+         { Bytecode_aconst_init baconst_init(caller_method(), caller_method->bcp_from(bci));
+           k = caller_method->constants()->klass_at(baconst_init.index(), CHECK);
+         }
+         break;
        case Bytecodes::_multianewarray:
          { Bytecode_multianewarray mna(caller_method(), caller_method->bcp_from(bci));
            k = caller_method->constants()->klass_at(mna.index(), CHECK);
+           if (k->name()->is_Q_array_signature()) {
+             // Logically creates elements, ensure klass init
+             k->initialize(CHECK);
+           }
          }
          break;
        case Bytecodes::_instanceof:
          { Bytecode_instanceof io(caller_method(), caller_method->bcp_from(bci));
            k = caller_method->constants()->klass_at(io.index(), CHECK);

*** 1535,22 ***
--- 1674,30 ---
    tty->print_cr(" _arraycopy_checkcast_cnt:        %u", _arraycopy_checkcast_cnt);
    tty->print_cr(" _arraycopy_checkcast_attempt_cnt:%u", _arraycopy_checkcast_attempt_cnt);
  
    tty->print_cr(" _new_type_array_slowcase_cnt:    %u", _new_type_array_slowcase_cnt);
    tty->print_cr(" _new_object_array_slowcase_cnt:  %u", _new_object_array_slowcase_cnt);
+   tty->print_cr(" _new_flat_array_slowcase_cnt:    %u", _new_flat_array_slowcase_cnt);
    tty->print_cr(" _new_instance_slowcase_cnt:      %u", _new_instance_slowcase_cnt);
    tty->print_cr(" _new_multi_array_slowcase_cnt:   %u", _new_multi_array_slowcase_cnt);
+   tty->print_cr(" _load_flat_array_slowcase_cnt:   %u", _load_flat_array_slowcase_cnt);
+   tty->print_cr(" _store_flat_array_slowcase_cnt:  %u", _store_flat_array_slowcase_cnt);
+   tty->print_cr(" _substitutability_check_slowcase_cnt: %u", _substitutability_check_slowcase_cnt);
+   tty->print_cr(" _buffer_inline_args_slowcase_cnt:%u", _buffer_inline_args_slowcase_cnt);
+   tty->print_cr(" _buffer_inline_args_no_receiver_slowcase_cnt:%u", _buffer_inline_args_no_receiver_slowcase_cnt);
+ 
    tty->print_cr(" _monitorenter_slowcase_cnt:      %u", _monitorenter_slowcase_cnt);
    tty->print_cr(" _monitorexit_slowcase_cnt:       %u", _monitorexit_slowcase_cnt);
    tty->print_cr(" _patch_code_slowcase_cnt:        %u", _patch_code_slowcase_cnt);
  
    tty->print_cr(" _throw_range_check_exception_count:            %u:", _throw_range_check_exception_count);
    tty->print_cr(" _throw_index_exception_count:                  %u:", _throw_index_exception_count);
    tty->print_cr(" _throw_div0_exception_count:                   %u:", _throw_div0_exception_count);
    tty->print_cr(" _throw_null_pointer_exception_count:           %u:", _throw_null_pointer_exception_count);
    tty->print_cr(" _throw_class_cast_exception_count:             %u:", _throw_class_cast_exception_count);
    tty->print_cr(" _throw_incompatible_class_change_error_count:  %u:", _throw_incompatible_class_change_error_count);
+   tty->print_cr(" _throw_illegal_monitor_state_exception_count:  %u:", _throw_illegal_monitor_state_exception_count);
    tty->print_cr(" _throw_count:                                  %u:", _throw_count);
  
    SharedRuntime::print_ic_miss_histogram();
    tty->cr();
  }
< prev index next >