< prev index next >

src/hotspot/share/opto/library_call.cpp

Print this page
rev 64210 : Merge

*** 332,341 **** --- 332,345 ---- 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,914 **** --- 909,927 ---- 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,6905 **** --- 6914,7066 ---- 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* off_val = _gvn.transform(new AddXNode(raw_val, MakeConX(Universe::non_heap_offset()))); + Node* long_val = ConvX2L(off_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 >