< prev index next >

src/hotspot/share/opto/library_call.cpp

Print this page
rev 63810 : Merge

@@ -332,10 +332,14 @@
   bool inline_vectorizedMismatch();
   bool inline_fma(vmIntrinsics::ID id);
   bool inline_character_compare(vmIntrinsics::ID id);
   bool inline_fp_min_max(vmIntrinsics::ID id);
 
+  bool inline_addressOf();
+  bool inline_sizeOf();
+  bool inline_getReferencedObjects();
+
   bool inline_profileBoolean();
   bool inline_isCompileConstant();
   void clear_upper_avx() {
 #ifdef X86
     if (UseAVX >= 2) {

@@ -905,10 +909,19 @@
   case vmIntrinsics::_minF:
   case vmIntrinsics::_maxD:
   case vmIntrinsics::_minD:
     return inline_fp_min_max(intrinsic_id());
 
+  case vmIntrinsics::_sizeOf:
+    return inline_sizeOf();
+
+  case vmIntrinsics::_addressOf:
+    return inline_addressOf();
+
+  case vmIntrinsics::_getReferencedObjects:
+    return inline_getReferencedObjects();
+
   default:
     // If you get here, it may be that someone has added a new intrinsic
     // to the list in vmSymbols.hpp without implementing it here.
 #ifndef PRODUCT
     if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) {

@@ -6901,5 +6914,152 @@
 bool LibraryCallKit::inline_isCompileConstant() {
   Node* n = argument(0);
   set_result(n->is_Con() ? intcon(1) : intcon(0));
   return true;
 }
+
+bool LibraryCallKit::inline_sizeOf() {
+  if (!RuntimeSizeOf) {
+    set_result(longcon(-1));
+    return true;
+  }
+
+  Node* obj = argument(0);
+  Node* klass_node = load_object_klass(obj);
+
+  jint  layout_con = Klass::_lh_neutral_value;
+  Node* layout_val = get_layout_helper(klass_node, layout_con);
+  int   layout_is_con = (layout_val == NULL);
+
+  if (layout_is_con) {
+    // Layout helper is constant, can figure out things at compile time.
+    assert(false, "Since sizeOf is @DontInline, this path should be unvisited");
+
+    if (Klass::layout_helper_is_instance(layout_con)) {
+      // Instance case:  layout_con contains the size itself.
+      Node *size = longcon(Klass::layout_helper_size_in_bytes(layout_con));
+      set_result(size);
+    } else {
+      // Array case: size is round(header + element_size*arraylength).
+      // Since arraylength is different for every array instance, we have to
+      // compute the whole thing at runtime.
+
+      Node* arr_length = load_array_length(obj);
+
+      int round_mask = MinObjAlignmentInBytes - 1;
+      int hsize  = Klass::layout_helper_header_size(layout_con);
+      int eshift = Klass::layout_helper_log2_element_size(layout_con);
+
+      if ((round_mask & ~right_n_bits(eshift)) == 0) {
+        round_mask = 0;  // strength-reduce it if it goes away completely
+      }
+      assert((hsize & right_n_bits(eshift)) == 0, "hsize is pre-rounded");
+      Node* header_size = intcon(hsize + round_mask);
+
+      Node* lengthx = ConvI2X(arr_length);
+      Node* headerx = ConvI2X(header_size);
+
+      Node* abody = lengthx;
+      if (eshift != 0) {
+        abody = _gvn.transform(new LShiftXNode(lengthx, intcon(eshift)));
+      }
+      Node* size = _gvn.transform( new AddXNode(headerx, abody) );
+      if (round_mask != 0) {
+        size = _gvn.transform( new AndXNode(size, MakeConX(~round_mask)) );
+      }
+      size = ConvX2L(size);
+      set_result(size);
+    }
+  } else {
+    // Layout helper is not constant, need to test for array-ness at runtime.
+
+    enum { _instance_path = 1, _array_path, PATH_LIMIT };
+    RegionNode* result_reg = new RegionNode(PATH_LIMIT);
+    PhiNode* result_val = new PhiNode(result_reg, TypeLong::LONG);
+    record_for_igvn(result_reg);
+
+    Node* array_ctl = generate_array_guard(klass_node, NULL);
+    if (array_ctl != NULL) {
+      // Array case: size is round(header + element_size*arraylength).
+      // Since arraylength is different for every array instance, we have to
+      // compute the whole thing at runtime.
+
+      PreserveJVMState pjvms(this);
+      set_control(array_ctl);
+      Node* arr_length = load_array_length(obj);
+
+      int round_mask = MinObjAlignmentInBytes - 1;
+      Node* mask = intcon(round_mask);
+
+      Node* hss = intcon(Klass::_lh_header_size_shift);
+      Node* hsm = intcon(Klass::_lh_header_size_mask);
+      Node* header_size = _gvn.transform(new URShiftINode(layout_val, hss));
+      header_size = _gvn.transform(new AndINode(header_size, hsm));
+      header_size = _gvn.transform(new AddINode(header_size, mask));
+
+      // There is no need to mask or shift this value.
+      // The semantics of LShiftINode include an implicit mask to 0x1F.
+      assert(Klass::_lh_log2_element_size_shift == 0, "use shift in place");
+      Node* elem_shift = layout_val;
+
+      Node* lengthx = ConvI2X(arr_length);
+      Node* headerx = ConvI2X(header_size);
+
+      Node* abody = _gvn.transform(new LShiftXNode(lengthx, elem_shift));
+      Node* size = _gvn.transform(new AddXNode(headerx, abody));
+      if (round_mask != 0) {
+        size = _gvn.transform(new AndXNode(size, MakeConX(~round_mask)));
+      }
+      size = ConvX2L(size);
+
+      result_reg->init_req(_array_path, control());
+      result_val->init_req(_array_path, size);
+    }
+
+    if (!stopped()) {
+      // Instance case: the layout helper gives us instance size almost directly,
+      // but we need to mask out the _lh_instance_slow_path_bit.
+      Node* size = ConvI2X(layout_val);
+      assert((int) Klass::_lh_instance_slow_path_bit < BytesPerLong, "clear bit");
+      Node* mask = MakeConX(~(intptr_t) right_n_bits(LogBytesPerLong));
+      size = _gvn.transform(new AndXNode(size, mask));
+      size = ConvX2L(size);
+
+      result_reg->init_req(_instance_path, control());
+      result_val->init_req(_instance_path, size);
+    }
+
+    set_result(result_reg, result_val);
+  }
+
+  return true;
+}
+
+bool LibraryCallKit::inline_addressOf() {
+  if (!RuntimeAddressOf) {
+    set_result(longcon(-1));
+    return true;
+  }
+
+  Node* obj = argument(0);
+  Node* raw_val = _gvn.transform(new CastP2XNode(NULL, obj));
+  Node* long_val = ConvX2L(raw_val);
+
+  set_result(long_val);
+  return true;
+}
+
+bool LibraryCallKit::inline_getReferencedObjects() {
+  Node* a1 = argument(0);
+  Node* a2 = argument(1);
+
+  Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
+                                 OptoRuntime::get_referenced_objects_Type(),
+                                 CAST_FROM_FN_PTR(address, SharedRuntime::get_referenced_objects),
+                                 "get_referenced_objects",
+                                 TypePtr::BOTTOM,
+                                 a1, a2);
+
+  Node* value = _gvn.transform(new ProjNode(call, TypeFunc::Parms+0));
+  set_result(value);
+  return true;
+}
< prev index next >