< prev index next >

src/hotspot/share/opto/parseHelper.cpp

Print this page

        

*** 21,39 **** --- 21,43 ---- * questions. * */ #include "precompiled.hpp" + #include "ci/ciValueKlass.hpp" #include "classfile/systemDictionary.hpp" #include "compiler/compileLog.hpp" #include "oops/objArrayKlass.hpp" + #include "oops/valueArrayKlass.hpp" #include "opto/addnode.hpp" + #include "opto/castnode.hpp" #include "opto/memnode.hpp" #include "opto/mulnode.hpp" #include "opto/parse.hpp" #include "opto/rootnode.hpp" #include "opto/runtime.hpp" + #include "opto/valuetypenode.hpp" #include "runtime/sharedRuntime.hpp" //------------------------------make_dtrace_method_entry_exit ---------------- // Dtrace -- record entry or exit of a method if compiled with dtrace support void GraphKit::make_dtrace_method_entry_exit(ciMethod* method, bool is_entry) {
*** 63,80 **** --- 67,86 ---- //============================================================================= //------------------------------do_checkcast----------------------------------- void Parse::do_checkcast() { bool will_link; ciKlass* klass = iter().get_klass(will_link); + bool never_null = iter().is_klass_never_null(); Node *obj = peek(); // Throw uncommon trap if class is not loaded or the value we are casting // _from_ is not loaded, and value is not null. If the value _is_ NULL, // then the checkcast does nothing. const TypeOopPtr *tp = _gvn.type(obj)->isa_oopptr(); if (!will_link || (tp && tp->klass() && !tp->klass()->is_loaded())) { + assert(!never_null, "Null-free value type should be loaded"); if (C->log() != NULL) { if (!will_link) { C->log()->elem("assert_null reason='checkcast' klass='%d'", C->log()->identify(klass)); }
*** 90,100 **** profile_null_checkcast(); } return; } ! Node *res = gen_checkcast(obj, makecon(TypeKlassPtr::make(klass)) ); // Pop from stack AFTER gen_checkcast because it can uncommon trap and // the debug info has to be correct. pop(); push(res); --- 96,109 ---- profile_null_checkcast(); } return; } ! Node* res = gen_checkcast(obj, makecon(TypeKlassPtr::make(klass)), NULL, never_null); ! if (stopped()) { ! return; ! } // Pop from stack AFTER gen_checkcast because it can uncommon trap and // the debug info has to be correct. pop(); push(res);
*** 135,164 **** push(res); } //------------------------------array_store_check------------------------------ // pull array from stack and check that the store is valid ! void Parse::array_store_check() { ! // Shorthand access to array store elements without popping them. Node *obj = peek(0); Node *idx = peek(1); Node *ary = peek(2); if (_gvn.type(obj) == TypePtr::NULL_PTR) { // There's never a type check on null values. // This cutout lets us avoid the uncommon_trap(Reason_array_check) // below, which turns into a performance liability if the // gen_checkcast folds up completely. ! return; } // Extract the array klass type ! int klass_offset = oopDesc::klass_offset_in_bytes(); ! Node* p = basic_plus_adr( ary, ary, klass_offset ); ! // p's type is array-of-OOPS plus klass_offset ! Node* array_klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS)); // Get the array klass const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr(); // The type of array_klass is usually INexact array-of-oop. Heroically // cast array_klass to EXACT array and uncommon-trap if the cast fails. --- 144,169 ---- push(res); } //------------------------------array_store_check------------------------------ // pull array from stack and check that the store is valid ! Node* Parse::array_store_check() { // Shorthand access to array store elements without popping them. Node *obj = peek(0); Node *idx = peek(1); Node *ary = peek(2); if (_gvn.type(obj) == TypePtr::NULL_PTR) { // There's never a type check on null values. // This cutout lets us avoid the uncommon_trap(Reason_array_check) // below, which turns into a performance liability if the // gen_checkcast folds up completely. ! return obj; } // Extract the array klass type ! Node* array_klass = load_object_klass(ary); // Get the array klass const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr(); // The type of array_klass is usually INexact array-of-oop. Heroically // cast array_klass to EXACT array and uncommon-trap if the cast fails.
*** 207,216 **** --- 212,224 ---- if (stopped()) { // MUST uncommon-trap? set_control(ctrl); // Then Don't Do It, just fall into the normal checking } else { // Cast array klass to exactness: // Use the exact constant value we know it is. replace_in_map(array_klass,con); + Node* cast = _gvn.transform(new CheckCastPPNode(control(), ary, extak->as_instance_type())); + replace_in_map(ary, cast); + CompileLog* log = C->log(); if (log != NULL) { log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'", log->identify(tak->klass())); }
*** 219,239 **** } // Come here for polymorphic array klasses // Extract the array element class ! int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset()); Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset); // We are allowed to use the constant type only if cast succeeded. If always_see_exact_class is true, // we must set a control edge from the IfTrue node created by the uncommon_trap above to the // LoadKlassNode. Node* a_e_klass = _gvn.transform(LoadKlassNode::make(_gvn, always_see_exact_class ? control() : NULL, immutable_memory(), p2, tak)); // Check (the hard way) and throw if not a subklass. ! // Result is ignored, we just need the CFG effects. ! gen_checkcast(obj, a_e_klass); } //------------------------------do_new----------------------------------------- void Parse::do_new() { --- 227,254 ---- } // Come here for polymorphic array klasses // Extract the array element class ! int element_klass_offset = in_bytes(ArrayKlass::element_klass_offset()); ! Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset); // We are allowed to use the constant type only if cast succeeded. If always_see_exact_class is true, // we must set a control edge from the IfTrue node created by the uncommon_trap above to the // LoadKlassNode. Node* a_e_klass = _gvn.transform(LoadKlassNode::make(_gvn, always_see_exact_class ? control() : NULL, immutable_memory(), p2, tak)); + // Handle value type arrays + const Type* elemtype = _gvn.type(ary)->is_aryptr()->elem(); + if (elemtype->isa_valuetype() != NULL || elemtype->is_valuetypeptr()) { + // We statically know that this is a value type array, use precise klass ptr + a_e_klass = makecon(TypeKlassPtr::make(elemtype->value_klass())); + } + // Check (the hard way) and throw if not a subklass. ! return gen_checkcast(obj, a_e_klass); } //------------------------------do_new----------------------------------------- void Parse::do_new() {
*** 276,285 **** --- 291,370 ---- if (C->eliminate_boxing() && klass->is_box_klass()) { C->set_has_boxed_value(true); } } + //------------------------------do_defaultvalue--------------------------------- + void Parse::do_defaultvalue() { + bool will_link; + ciValueKlass* vk = iter().get_klass(will_link)->as_value_klass(); + assert(will_link, "defaultvalue: typeflow responsibility"); + + // Should throw an InstantiationError? + if (iter().is_unresolved_klass()) { + uncommon_trap(Deoptimization::Reason_unhandled, + Deoptimization::Action_none, + vk); + return; + } + + if (C->needs_clinit_barrier(vk, method())) { + clinit_barrier(vk, method()); + if (stopped()) return; + } + + ValueTypeNode* vt = ValueTypeNode::make_default(_gvn, vk); + if (vk->is_scalarizable()) { + push(vt); + } else { + push(vt->get_oop()); + } + } + + //------------------------------do_withfield------------------------------------ + void Parse::do_withfield() { + bool will_link; + ciField* field = iter().get_field(will_link); + assert(will_link, "withfield: typeflow responsibility"); + BasicType bt = field->layout_type(); + Node* val = type2size[bt] == 1 ? pop() : pop_pair(); + ciValueKlass* holder_klass = field->holder()->as_value_klass(); + Node* holder = pop(); + + if (!holder->is_ValueType()) { + // Null check and scalarize value type holder + inc_sp(2); + holder = null_check(holder); + dec_sp(2); + if (stopped()) return; + holder = ValueTypeNode::make_from_oop(this, holder, holder_klass); + } + if (!val->is_ValueType() && field->is_flattenable()) { + // Null check and scalarize value type field value + inc_sp(2); + val = null_check(val); + dec_sp(2); + if (stopped()) return; + val = ValueTypeNode::make_from_oop(this, val, gvn().type(val)->value_klass()); + } else if (val->is_ValueType() && !field->is_flattenable()) { + // Non-flattenable field should not be scalarized + val = ValueTypePtrNode::make_from_value_type(this, val->as_ValueType()); + } + + // Clone the value type node and set the new field value + ValueTypeNode* new_vt = holder->clone()->as_ValueType(); + new_vt->set_oop(_gvn.zerocon(T_VALUETYPE)); + gvn().set_type(new_vt, new_vt->bottom_type()); + new_vt->set_field_value_by_offset(field->offset(), val); + + if (holder_klass->is_scalarizable()) { + push(_gvn.transform(new_vt)); + } else { + push(new_vt->allocate(this)->get_oop()); + } + } + #ifndef PRODUCT //------------------------------dump_map_adr_mem------------------------------- // Debug dump of the mapping from address types to MergeMemNode indices. void Parse::dump_map_adr_mem() const { tty->print_cr("--- Mapping from address types to memory Nodes ---");
< prev index next >