--- old/src/hotspot/share/c1/c1_LIRGenerator.cpp 2019-03-11 14:25:11.246355915 +0100 +++ new/src/hotspot/share/c1/c1_LIRGenerator.cpp 2019-03-11 14:25:11.046355917 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,8 @@ #include "ci/ciInstance.hpp" #include "ci/ciObjArray.hpp" #include "ci/ciUtilities.hpp" +#include "ci/ciValueArrayKlass.hpp" +#include "ci/ciValueKlass.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/c1/barrierSetC1.hpp" #include "runtime/arguments.hpp" @@ -641,13 +643,14 @@ } -void LIRGenerator::monitor_enter(LIR_Opr object, LIR_Opr lock, LIR_Opr hdr, LIR_Opr scratch, int monitor_no, CodeEmitInfo* info_for_exception, CodeEmitInfo* info) { +void LIRGenerator::monitor_enter(LIR_Opr object, LIR_Opr lock, LIR_Opr hdr, LIR_Opr scratch, int monitor_no, + CodeEmitInfo* info_for_exception, CodeEmitInfo* info, CodeStub* throw_imse_stub) { if (!GenerateSynchronizationCode) return; // for slow path, use debug info for state after successful locking - CodeStub* slow_path = new MonitorEnterStub(object, lock, info); + CodeStub* slow_path = new MonitorEnterStub(object, lock, info, throw_imse_stub, scratch); __ load_stack_address_monitor(monitor_no, lock); // for handling NullPointerException, use debug info representing just the lock stack before this monitorenter - __ lock_object(hdr, object, lock, scratch, slow_path, info_for_exception); + __ lock_object(hdr, object, lock, scratch, slow_path, info_for_exception, throw_imse_stub); } @@ -789,6 +792,16 @@ // of the required checks for a fast case can be elided. int flags = LIR_OpArrayCopy::all_flags; + if (!src->is_loaded_flattened_array() && !dst->is_loaded_flattened_array()) { + flags &= ~LIR_OpArrayCopy::always_slow_path; + } + if (!src->maybe_flattened_array()) { + flags &= ~LIR_OpArrayCopy::src_flat_check; + } + if (!dst->maybe_flattened_array()) { + flags &= ~LIR_OpArrayCopy::dst_flat_check; + } + if (!src_objarray) flags &= ~LIR_OpArrayCopy::src_objarray; if (!dst_objarray) @@ -1530,10 +1543,19 @@ if (x->needs_null_check() && (needs_patching || MacroAssembler::needs_explicit_null_check(x->offset()))) { - // Emit an explicit null check because the offset is too large. - // If the class is not loaded and the object is NULL, we need to deoptimize to throw a - // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code. - __ null_check(object.result(), new CodeEmitInfo(info), /* deoptimize */ needs_patching); + if (needs_patching && x->field()->signature()->starts_with("Q", 1)) { + // We are storing a field of type "QT;", but T is not yet loaded, so we don't + // know whether this field is flattened or not. Let's deoptimize and recompile. + CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info), + Deoptimization::Reason_unloaded, + Deoptimization::Action_make_not_entrant); + __ branch(lir_cond_always, T_ILLEGAL, stub); + } else { + // Emit an explicit null check because the offset is too large. + // If the class is not loaded and the object is NULL, we need to deoptimize to throw a + // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code. + __ null_check(object.result(), new CodeEmitInfo(info), /* deoptimize */ needs_patching); + } } DecoratorSet decorators = IN_HEAP; @@ -1548,12 +1570,135 @@ value.result(), info != NULL ? new CodeEmitInfo(info) : NULL, info); } +// FIXME -- I can't find any other way to pass an address to access_load_at(). +class TempResolvedAddress: public Instruction { + public: + TempResolvedAddress(ValueType* type, LIR_Opr addr) : Instruction(type) { + set_operand(addr); + } + virtual void input_values_do(ValueVisitor*) {} + virtual void visit(InstructionVisitor* v) {} + virtual const char* name() const { return "TempResolvedAddress"; } +}; + +void LIRGenerator::access_flattened_array(bool is_load, LIRItem& array, LIRItem& index, LIRItem& obj_item) { + // Find the starting address of the source (inside the array) + ciType* array_type = array.value()->declared_type(); + ciValueArrayKlass* value_array_klass = array_type->as_value_array_klass(); + assert(value_array_klass->is_loaded(), "must be"); + + ciValueKlass* elem_klass = value_array_klass->element_klass()->as_value_klass(); + int array_header_size = value_array_klass->array_header_in_bytes(); + int shift = value_array_klass->log2_element_size(); + +#ifndef _LP64 + LIR_Opr index_op = new_register(T_INT); + // FIXME -- on 32-bit, the shift below can overflow, so we need to check that + // the top (shift+1) bits of index_op must be zero, or + // else throw ArrayIndexOutOfBoundsException + if (index.result()->is_constant()) { + jint const_index = index.result()->as_jint(); + __ move(LIR_OprFact::intConst(const_index << shift), index_op); + } else { + __ shift_left(index_op, shift, index.result()); + } +#else + LIR_Opr index_op = new_register(T_LONG); + if (index.result()->is_constant()) { + jint const_index = index.result()->as_jint(); + __ move(LIR_OprFact::longConst(const_index << shift), index_op); + } else { + __ convert(Bytecodes::_i2l, index.result(), index_op); + // Need to shift manually, as LIR_Address can scale only up to 3. + __ shift_left(index_op, shift, index_op); + } +#endif + + LIR_Opr elm_op = new_pointer_register(); + LIR_Address* elm_address = new LIR_Address(array.result(), index_op, array_header_size, T_ADDRESS); + __ leal(LIR_OprFact::address(elm_address), elm_op); + + for (int i = 0; i < elem_klass->nof_nonstatic_fields(); i++) { + ciField* inner_field = elem_klass->nonstatic_field_at(i); + assert(!inner_field->is_flattened(), "flattened fields must have been expanded"); + int obj_offset = inner_field->offset(); + int elm_offset = obj_offset - elem_klass->first_field_offset(); // object header is not stored in array. + + BasicType field_type = inner_field->type()->basic_type(); + switch (field_type) { + case T_BYTE: + case T_BOOLEAN: + case T_SHORT: + case T_CHAR: + field_type = T_INT; + break; + default: + break; + } + + LIR_Opr temp = new_register(field_type); + TempResolvedAddress* elm_resolved_addr = new TempResolvedAddress(as_ValueType(field_type), elm_op); + LIRItem elm_item(elm_resolved_addr, this); + + DecoratorSet decorators = IN_HEAP; + if (is_load) { + access_load_at(decorators, field_type, + elm_item, LIR_OprFact::intConst(elm_offset), temp, + NULL, NULL); + access_store_at(decorators, field_type, + obj_item, LIR_OprFact::intConst(obj_offset), temp, + NULL, NULL); + } else { + access_load_at(decorators, field_type, + obj_item, LIR_OprFact::intConst(obj_offset), temp, + NULL, NULL); + access_store_at(decorators, field_type, + elm_item, LIR_OprFact::intConst(elm_offset), temp, + NULL, NULL); + } + } +} + +void LIRGenerator::check_flattened_array(LIRItem& array, CodeStub* slow_path) { + LIR_Opr array_klass_reg = new_register(T_METADATA); + + __ move(new LIR_Address(array.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), array_klass_reg); + LIR_Opr layout = new_register(T_INT); + __ move(new LIR_Address(array_klass_reg, in_bytes(Klass::layout_helper_offset()), T_INT), layout); + __ shift_right(layout, Klass::_lh_array_tag_shift, layout); + __ cmp(lir_cond_equal, layout, LIR_OprFact::intConst(Klass::_lh_array_tag_vt_value)); + __ branch(lir_cond_equal, T_ILLEGAL, slow_path); +} + +bool LIRGenerator::needs_flattened_array_store_check(StoreIndexed* x) { + if (ValueArrayFlatten && x->elt_type() == T_OBJECT && x->array()->maybe_flattened_array()) { + ciType* type = x->value()->declared_type(); + if (type != NULL && type->is_klass()) { + ciKlass* klass = type->as_klass(); + if (klass->is_loaded() && + !(klass->is_valuetype() && klass->as_value_klass()->flatten_array()) && + !klass->is_java_lang_Object() && + !klass->is_interface()) { + // This is known to be a non-flattenable object. If the array is flattened, + // it will be caught by the code generated by array_store_check(). + return false; + } + } + // We're not 100% sure, so let's do the flattened_array_store_check. + return true; + } + return false; +} + void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { assert(x->is_pinned(),""); + assert(x->elt_type() != T_ARRAY, "never used"); + bool is_loaded_flattened_array = x->array()->is_loaded_flattened_array(); bool needs_range_check = x->compute_needs_range_check(); bool use_length = x->length() != NULL; - bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT; - bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL || + bool obj_store = x->elt_type() == T_OBJECT; + bool needs_store_check = obj_store && !is_loaded_flattened_array && + (x->value()->as_Constant() == NULL || !get_jobject_constant(x->value())->is_null_object() || x->should_profile()); @@ -1568,9 +1713,10 @@ if (use_length && needs_range_check) { length.set_instruction(x->length()); length.load_item(); - } - if (needs_store_check || x->check_boolean()) { + + if (needs_store_check || x->check_boolean() + || is_loaded_flattened_array || needs_flattened_array_store_check(x)) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -1603,13 +1749,36 @@ array_store_check(value.result(), array.result(), store_check_info, x->profiled_method(), x->profiled_bci()); } - DecoratorSet decorators = IN_HEAP | IS_ARRAY; - if (x->check_boolean()) { - decorators |= C1_MASK_BOOLEAN; + if (is_loaded_flattened_array) { + if (!x->is_exact_flattened_array_store()) { + CodeEmitInfo* info = new CodeEmitInfo(range_check_info); + ciKlass* element_klass = x->array()->declared_type()->as_value_array_klass()->element_klass(); + flattened_array_store_check(value.result(), element_klass, info); + } else if (!x->value()->is_never_null()) { + __ null_check(value.result(), new CodeEmitInfo(range_check_info)); + } + access_flattened_array(false, array, index, value); + } else { + StoreFlattenedArrayStub* slow_path = NULL; + + if (needs_flattened_array_store_check(x)) { + // Check if we indeed have a flattened array + index.load_item(); + slow_path = new StoreFlattenedArrayStub(array.result(), index.result(), value.result(), state_for(x)); + check_flattened_array(array, slow_path); + } + + DecoratorSet decorators = IN_HEAP | IS_ARRAY; + if (x->check_boolean()) { + decorators |= C1_MASK_BOOLEAN; + } + + access_store_at(decorators, x->elt_type(), array, index.result(), value.result(), + NULL, null_check_info); + if (slow_path != NULL) { + __ branch_destination(slow_path->continuation()); + } } - - access_store_at(decorators, x->elt_type(), array, index.result(), value.result(), - NULL, null_check_info); } void LIRGenerator::access_load_at(DecoratorSet decorators, BasicType type, @@ -1733,15 +1902,32 @@ (needs_patching || MacroAssembler::needs_explicit_null_check(x->offset()) || stress_deopt)) { - LIR_Opr obj = object.result(); - if (stress_deopt) { - obj = new_register(T_OBJECT); - __ move(LIR_OprFact::oopConst(NULL), obj); - } - // Emit an explicit null check because the offset is too large. - // If the class is not loaded and the object is NULL, we need to deoptimize to throw a - // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code. - __ null_check(obj, new CodeEmitInfo(info), /* deoptimize */ needs_patching); + if (needs_patching && x->field()->signature()->starts_with("Q", 1)) { + // We are loading a field of type "QT;", but class T is not yet loaded. We don't know + // whether this field is flattened or not. Let's deoptimize and recompile. + CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info), + Deoptimization::Reason_unloaded, + Deoptimization::Action_make_not_entrant); + __ branch(lir_cond_always, T_ILLEGAL, stub); + } else { + LIR_Opr obj = object.result(); + if (stress_deopt) { + obj = new_register(T_OBJECT); + __ move(LIR_OprFact::oopConst(NULL), obj); + } + // Emit an explicit null check because the offset is too large. + // If the class is not loaded and the object is NULL, we need to deoptimize to throw a + // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code. + __ null_check(obj, new CodeEmitInfo(info), /* deoptimize */ needs_patching); + } + } else if (x->value_klass() != NULL && x->default_value() == NULL) { + assert(x->is_static() && !x->value_klass()->is_loaded(), "must be"); + assert(needs_patching, "must be"); + // The value klass was not loaded so we don't know what its default value should be + CodeStub* stub = new DeoptimizeStub(new CodeEmitInfo(info), + Deoptimization::Reason_unloaded, + Deoptimization::Action_make_not_entrant); + __ branch(lir_cond_always, T_ILLEGAL, stub); } DecoratorSet decorators = IN_HEAP; @@ -1756,6 +1942,18 @@ access_load_at(decorators, field_type, object, LIR_OprFact::intConst(x->offset()), result, info ? new CodeEmitInfo(info) : NULL, info); + + if (x->value_klass() != NULL && x->default_value() != NULL) { + LabelObj* L_end = new LabelObj(); + __ cmp(lir_cond_notEqual, result, LIR_OprFact::oopConst(NULL)); + __ branch(lir_cond_notEqual, T_OBJECT, L_end->label()); + + LIRItem default_value(x->default_value(), this); + default_value.load_item(); + __ move(default_value.result(), result); + + __ branch_destination(L_end->label()); + } } @@ -1870,12 +2068,33 @@ } } - DecoratorSet decorators = IN_HEAP | IS_ARRAY; + if (x->array()->is_loaded_flattened_array()) { + // Find the destination address (of the NewValueTypeInstance) + LIR_Opr obj = x->vt()->operand(); + LIRItem obj_item(x->vt(), this); + + access_flattened_array(true, array, index, obj_item); + set_no_result(x); + } else { + LIR_Opr result = rlock_result(x, x->elt_type()); + LoadFlattenedArrayStub* slow_path = NULL; + + if (x->elt_type() == T_OBJECT && x->array()->maybe_flattened_array()) { + index.load_item(); + // if we are loading from flattened array, load it using a runtime call + slow_path = new LoadFlattenedArrayStub(array.result(), index.result(), result, state_for(x)); + check_flattened_array(array, slow_path); + } + + DecoratorSet decorators = IN_HEAP | IS_ARRAY; + access_load_at(decorators, x->elt_type(), + array, index.result(), result, + NULL, null_check_info); - LIR_Opr result = rlock_result(x, x->elt_type()); - access_load_at(decorators, x->elt_type(), - array, index.result(), result, - NULL, null_check_info); + if (slow_path != NULL) { + __ branch_destination(slow_path->continuation()); + } + } } @@ -2735,6 +2954,7 @@ } else { LIR_Address* addr = loc->as_address_ptr(); param->load_for_store(addr->type()); + assert(addr->type() != T_VALUETYPE, "not supported yet"); if (addr->type() == T_OBJECT) { __ move_wide(param->result(), addr); } else