src/share/vm/opto/graphKit.cpp

Print this page
rev 5661 : 8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering.

*** 492,502 **** // take the uncommon_trap in the BuildCutout below. // first must access the should_post_on_exceptions_flag in this thread's JavaThread Node* jthread = _gvn.transform(new (C) ThreadLocalNode()); Node* adr = basic_plus_adr(top(), jthread, in_bytes(JavaThread::should_post_on_exceptions_flag_offset())); ! Node* should_post_flag = make_load(control(), adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, false); // Test the should_post_on_exceptions_flag vs. 0 Node* chk = _gvn.transform( new (C) CmpINode(should_post_flag, intcon(0)) ); Node* tst = _gvn.transform( new (C) BoolNode(chk, BoolTest::eq) ); --- 492,502 ---- // take the uncommon_trap in the BuildCutout below. // first must access the should_post_on_exceptions_flag in this thread's JavaThread Node* jthread = _gvn.transform(new (C) ThreadLocalNode()); Node* adr = basic_plus_adr(top(), jthread, in_bytes(JavaThread::should_post_on_exceptions_flag_offset())); ! Node* should_post_flag = make_load(control(), adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, false, LoadNode::unordered); // Test the should_post_on_exceptions_flag vs. 0 Node* chk = _gvn.transform( new (C) CmpINode(should_post_flag, intcon(0)) ); Node* tst = _gvn.transform( new (C) BoolNode(chk, BoolTest::eq) );
*** 594,604 **** int offset = java_lang_Throwable::get_detailMessage_offset(); const TypePtr* adr_typ = ex_con->add_offset(offset); Node *adr = basic_plus_adr(ex_node, ex_node, offset); const TypeOopPtr* val_type = TypeOopPtr::make_from_klass(env()->String_klass()); ! Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT); add_exception_state(make_exception_state(ex_node)); return; } } --- 594,605 ---- int offset = java_lang_Throwable::get_detailMessage_offset(); const TypePtr* adr_typ = ex_con->add_offset(offset); Node *adr = basic_plus_adr(ex_node, ex_node, offset); const TypeOopPtr* val_type = TypeOopPtr::make_from_klass(env()->String_klass()); ! // Conservatively release stores of object references. ! Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT, StoreNode::release); add_exception_state(make_exception_state(ex_node)); return; } }
*** 1481,1500 **** // // factory methods in "int adr_idx" Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, ! bool require_atomic_access) { assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" ); const TypePtr* adr_type = NULL; // debug-mode-only argument debug_only(adr_type = C->get_adr_type(adr_idx)); Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { ! ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t); } else { ! ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt); } ld = _gvn.transform(ld); if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) { // Improve graph before escape analysis and boxing elimination. record_for_igvn(ld); --- 1482,1501 ---- // // factory methods in "int adr_idx" Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, ! bool require_atomic_access, LoadNode::Sem sem) { assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" ); const TypePtr* adr_type = NULL; // debug-mode-only argument debug_only(adr_type = C->get_adr_type(adr_idx)); Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { ! ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, sem); } else { ! ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, sem); } ld = _gvn.transform(ld); if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) { // Improve graph before escape analysis and boxing elimination. record_for_igvn(ld);
*** 1502,1521 **** return ld; } Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt, int adr_idx, ! bool require_atomic_access) { assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); const TypePtr* adr_type = NULL; debug_only(adr_type = C->get_adr_type(adr_idx)); Node *mem = memory(adr_idx); Node* st; if (require_atomic_access && bt == T_LONG) { ! st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val); } else { ! st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt); } st = _gvn.transform(st); set_memory(st, adr_idx); // Back-to-back stores can only remove intermediate store with DU info // so push on worklist for optimizer. --- 1503,1523 ---- return ld; } Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt, int adr_idx, ! bool require_atomic_access, ! StoreNode::Sem sem) { assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); const TypePtr* adr_type = NULL; debug_only(adr_type = C->get_adr_type(adr_idx)); Node *mem = memory(adr_idx); Node* st; if (require_atomic_access && bt == T_LONG) { ! st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, sem); } else { ! st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, sem); } st = _gvn.transform(st); set_memory(st, adr_idx); // Back-to-back stores can only remove intermediate store with DU info // so push on worklist for optimizer.
*** 1611,1621 **** Node* adr, const TypePtr* adr_type, Node* val, const TypeOopPtr* val_type, BasicType bt, ! bool use_precise) { // Transformation of a value which could be NULL pointer (CastPP #NULL) // could be delayed during Parse (for example, in adjust_map_after_if()). // Execute transformation here to avoid barrier generation in such case. if (_gvn.type(val) == TypePtr::NULL_PTR) val = _gvn.makecon(TypePtr::NULL_PTR); --- 1613,1624 ---- Node* adr, const TypePtr* adr_type, Node* val, const TypeOopPtr* val_type, BasicType bt, ! bool use_precise, ! StoreNode::Sem sem) { // Transformation of a value which could be NULL pointer (CastPP #NULL) // could be delayed during Parse (for example, in adjust_map_after_if()). // Execute transformation here to avoid barrier generation in such case. if (_gvn.type(val) == TypePtr::NULL_PTR) val = _gvn.makecon(TypePtr::NULL_PTR);
*** 1631,1652 **** pre_barrier(true /* do_load */, control(), obj, adr, adr_idx, val, val_type, NULL /* pre_val */, bt); ! Node* store = store_to_memory(control(), adr, val, bt, adr_idx); post_barrier(control(), store, obj, adr, adr_idx, val, bt, use_precise); return store; } // Could be an array or object we don't know at compile time (unsafe ref.) Node* GraphKit::store_oop_to_unknown(Node* ctl, Node* obj, // containing obj Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, ! BasicType bt) { Compile::AliasType* at = C->alias_type(adr_type); const TypeOopPtr* val_type = NULL; if (adr_type->isa_instptr()) { if (at->field() != NULL) { // known field. This code is a copy of the do_put_xxx logic. --- 1634,1656 ---- pre_barrier(true /* do_load */, control(), obj, adr, adr_idx, val, val_type, NULL /* pre_val */, bt); ! Node* store = store_to_memory(control(), adr, val, bt, adr_idx, false, sem); post_barrier(control(), store, obj, adr, adr_idx, val, bt, use_precise); return store; } // Could be an array or object we don't know at compile time (unsafe ref.) Node* GraphKit::store_oop_to_unknown(Node* ctl, Node* obj, // containing obj Node* adr, // actual adress to store val at const TypePtr* adr_type, Node* val, ! BasicType bt, ! StoreNode::Sem sem) { Compile::AliasType* at = C->alias_type(adr_type); const TypeOopPtr* val_type = NULL; if (adr_type->isa_instptr()) { if (at->field() != NULL) { // known field. This code is a copy of the do_put_xxx logic.
*** 1661,1671 **** val_type = adr_type->is_aryptr()->elem()->make_oopptr(); } if (val_type == NULL) { val_type = TypeInstPtr::BOTTOM; } ! return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true); } //-------------------------array_element_address------------------------- Node* GraphKit::array_element_address(Node* ary, Node* idx, BasicType elembt, --- 1665,1675 ---- val_type = adr_type->is_aryptr()->elem()->make_oopptr(); } if (val_type == NULL) { val_type = TypeInstPtr::BOTTOM; } ! return store_oop(ctl, obj, adr, adr_type, val, val_type, bt, true, sem); } //-------------------------array_element_address------------------------- Node* GraphKit::array_element_address(Node* ary, Node* idx, BasicType elembt,
*** 1705,1715 **** //-------------------------load_array_element------------------------- Node* GraphKit::load_array_element(Node* ctl, Node* ary, Node* idx, const TypeAryPtr* arytype) { const Type* elemtype = arytype->elem(); BasicType elembt = elemtype->array_element_basic_type(); Node* adr = array_element_address(ary, idx, elembt, arytype->size()); ! Node* ld = make_load(ctl, adr, elemtype, elembt, arytype); return ld; } //-------------------------set_arguments_for_java_call------------------------- // Arguments (pre-popped from the stack) are taken from the JVMS. --- 1709,1719 ---- //-------------------------load_array_element------------------------- Node* GraphKit::load_array_element(Node* ctl, Node* ary, Node* idx, const TypeAryPtr* arytype) { const Type* elemtype = arytype->elem(); BasicType elembt = elemtype->array_element_basic_type(); Node* adr = array_element_address(ary, idx, elembt, arytype->size()); ! Node* ld = make_load(ctl, adr, elemtype, elembt, arytype, false, LoadNode::unordered); return ld; } //-------------------------set_arguments_for_java_call------------------------- // Arguments (pre-popped from the stack) are taken from the JVMS.
*** 1940,1952 **** } void GraphKit::increment_counter(Node* counter_addr) { int adr_type = Compile::AliasIdxRaw; Node* ctrl = control(); ! Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type); Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1))); ! store_to_memory( ctrl, counter_addr, incr, T_INT, adr_type ); } //------------------------------uncommon_trap---------------------------------- // Bail out to the interpreter in mid-method. Implemented by calling the --- 1944,1956 ---- } void GraphKit::increment_counter(Node* counter_addr) { int adr_type = Compile::AliasIdxRaw; Node* ctrl = control(); ! Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type, false, LoadNode::unordered); Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1))); ! store_to_memory(ctrl, counter_addr, incr, T_INT, adr_type, false, StoreNode::unordered); } //------------------------------uncommon_trap---------------------------------- // Bail out to the interpreter in mid-method. Implemented by calling the
*** 2523,2533 **** // if the subklass is the unique subtype of the superklass, the check // will always succeed. We could leave a dependency behind to ensure this. // First load the super-klass's check-offset Node *p1 = basic_plus_adr( superklass, superklass, in_bytes(Klass::super_check_offset_offset()) ); ! Node *chk_off = _gvn.transform( new (C) LoadINode( NULL, memory(p1), p1, _gvn.type(p1)->is_ptr() ) ); int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); bool might_be_cache = (find_int_con(chk_off, cacheoff_con) == cacheoff_con); // Load from the sub-klass's super-class display list, or a 1-word cache of // the secondary superclass list, or a failing value with a sentinel offset --- 2527,2538 ---- // if the subklass is the unique subtype of the superklass, the check // will always succeed. We could leave a dependency behind to ensure this. // First load the super-klass's check-offset Node *p1 = basic_plus_adr( superklass, superklass, in_bytes(Klass::super_check_offset_offset()) ); ! Node *chk_off = _gvn.transform(new (C) LoadINode(NULL, memory(p1), p1, _gvn.type(p1)->is_ptr(), ! TypeInt::INT, LoadNode::unordered)); int cacheoff_con = in_bytes(Klass::secondary_super_cache_offset()); bool might_be_cache = (find_int_con(chk_off, cacheoff_con) == cacheoff_con); // Load from the sub-klass's super-class display list, or a 1-word cache of // the secondary superclass list, or a failing value with a sentinel offset
*** 3236,3246 **** } } } constant_value = Klass::_lh_neutral_value; // put in a known value Node* lhp = basic_plus_adr(klass_node, klass_node, in_bytes(Klass::layout_helper_offset())); ! return make_load(NULL, lhp, TypeInt::INT, T_INT); } // We just put in an allocate/initialize with a big raw-memory effect. // Hook selected additional alias categories on the initialization. static void hook_memory_on_init(GraphKit& kit, int alias_idx, --- 3241,3251 ---- } } } constant_value = Klass::_lh_neutral_value; // put in a known value Node* lhp = basic_plus_adr(klass_node, klass_node, in_bytes(Klass::layout_helper_offset())); ! return make_load(NULL, lhp, TypeInt::INT, T_INT, false, LoadNode::unordered); } // We just put in an allocate/initialize with a big raw-memory effect. // Hook selected additional alias categories on the initialization. static void hook_memory_on_init(GraphKit& kit, int alias_idx,
*** 3771,3781 **** __ if_then(card_val, BoolTest::ne, zero); } // Smash zero into card if( !UseConcMarkSweepGC ) { ! __ store(__ ctrl(), card_adr, zero, bt, adr_type); } else { // Specialized path for CM store barrier __ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type); } --- 3776,3786 ---- __ if_then(card_val, BoolTest::ne, zero); } // Smash zero into card if( !UseConcMarkSweepGC ) { ! __ store(__ ctrl(), card_adr, zero, bt, adr_type, false, StoreNode::release); } else { // Specialized path for CM store barrier __ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, bt, adr_type); }
*** 3868,3880 **** // decrement the index Node* next_index = _gvn.transform(new (C) SubXNode(index, __ ConX(sizeof(intptr_t)))); // Now get the buffer location we will log the previous value into and store it Node *log_addr = __ AddP(no_base, buffer, next_index); ! __ store(__ ctrl(), log_addr, pre_val, T_OBJECT, Compile::AliasIdxRaw); // update the index ! __ store(__ ctrl(), index_adr, next_index, index_bt, Compile::AliasIdxRaw); } __ else_(); { // logging buffer is full, call the runtime const TypeFunc *tf = OptoRuntime::g1_wb_pre_Type(); --- 3873,3885 ---- // decrement the index Node* next_index = _gvn.transform(new (C) SubXNode(index, __ ConX(sizeof(intptr_t)))); // Now get the buffer location we will log the previous value into and store it Node *log_addr = __ AddP(no_base, buffer, next_index); ! __ store(__ ctrl(), log_addr, pre_val, T_OBJECT, Compile::AliasIdxRaw, false, StoreNode::unordered); // update the index ! __ store(__ ctrl(), index_adr, next_index, index_bt, Compile::AliasIdxRaw, false, StoreNode::unordered); } __ else_(); { // logging buffer is full, call the runtime const TypeFunc *tf = OptoRuntime::g1_wb_pre_Type();
*** 3910,3921 **** __ if_then(index, BoolTest::ne, zeroX); { Node* next_index = _gvn.transform(new (C) SubXNode(index, __ ConX(sizeof(intptr_t)))); Node* log_addr = __ AddP(no_base, buffer, next_index); ! __ store(__ ctrl(), log_addr, card_adr, T_ADDRESS, Compile::AliasIdxRaw); ! __ store(__ ctrl(), index_adr, next_index, TypeX_X->basic_type(), Compile::AliasIdxRaw); } __ else_(); { __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), "g1_wb_post", card_adr, __ thread()); } __ end_if(); --- 3915,3927 ---- __ if_then(index, BoolTest::ne, zeroX); { Node* next_index = _gvn.transform(new (C) SubXNode(index, __ ConX(sizeof(intptr_t)))); Node* log_addr = __ AddP(no_base, buffer, next_index); ! // Order, see storeCM. ! __ store(__ ctrl(), log_addr, card_adr, T_ADDRESS, Compile::AliasIdxRaw, false, StoreNode::unordered); ! __ store(__ ctrl(), index_adr, next_index, TypeX_X->basic_type(), Compile::AliasIdxRaw, false, StoreNode::unordered); } __ else_(); { __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), "g1_wb_post", card_adr, __ thread()); } __ end_if();
*** 4041,4051 **** false, NULL, 0); const TypePtr* offset_field_type = string_type->add_offset(offset_offset); int offset_field_idx = C->get_alias_index(offset_field_type); return make_load(ctrl, basic_plus_adr(str, str, offset_offset), ! TypeInt::INT, T_INT, offset_field_idx); } else { return intcon(0); } } --- 4047,4057 ---- false, NULL, 0); const TypePtr* offset_field_type = string_type->add_offset(offset_offset); int offset_field_idx = C->get_alias_index(offset_field_type); return make_load(ctrl, basic_plus_adr(str, str, offset_offset), ! TypeInt::INT, T_INT, offset_field_idx, false, LoadNode::unordered); } else { return intcon(0); } }
*** 4056,4066 **** false, NULL, 0); const TypePtr* count_field_type = string_type->add_offset(count_offset); int count_field_idx = C->get_alias_index(count_field_type); return make_load(ctrl, basic_plus_adr(str, str, count_offset), ! TypeInt::INT, T_INT, count_field_idx); } else { return load_array_length(load_String_value(ctrl, str)); } } --- 4062,4072 ---- false, NULL, 0); const TypePtr* count_field_type = string_type->add_offset(count_offset); int count_field_idx = C->get_alias_index(count_field_type); return make_load(ctrl, basic_plus_adr(str, str, count_offset), ! TypeInt::INT, T_INT, count_field_idx, false, LoadNode::unordered); } else { return load_array_length(load_String_value(ctrl, str)); } }
*** 4072,4082 **** const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull, TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0); int value_field_idx = C->get_alias_index(value_field_type); Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset), ! value_type, T_OBJECT, value_field_idx); // String.value field is known to be @Stable. if (UseImplicitStableValues) { load = cast_array_to_stable(load, value_type); } return load; --- 4078,4088 ---- const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull, TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0); int value_field_idx = C->get_alias_index(value_field_type); Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset), ! value_type, T_OBJECT, value_field_idx, false, LoadNode::unordered); // String.value field is known to be @Stable. if (UseImplicitStableValues) { load = cast_array_to_stable(load, value_type); } return load;
*** 4087,4117 **** const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* offset_field_type = string_type->add_offset(offset_offset); int offset_field_idx = C->get_alias_index(offset_field_type); store_to_memory(ctrl, basic_plus_adr(str, offset_offset), ! value, T_INT, offset_field_idx); } void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) { int value_offset = java_lang_String::value_offset_in_bytes(); const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* value_field_type = string_type->add_offset(value_offset); store_oop_to_object(ctrl, str, basic_plus_adr(str, value_offset), value_field_type, ! value, TypeAryPtr::CHARS, T_OBJECT); } void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) { int count_offset = java_lang_String::count_offset_in_bytes(); const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* count_field_type = string_type->add_offset(count_offset); int count_field_idx = C->get_alias_index(count_field_type); store_to_memory(ctrl, basic_plus_adr(str, count_offset), ! value, T_INT, count_field_idx); } Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) { // Reify the property as a CastPP node in Ideal graph to comply with monotonicity // assumption of CCP analysis. --- 4093,4123 ---- const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* offset_field_type = string_type->add_offset(offset_offset); int offset_field_idx = C->get_alias_index(offset_field_type); store_to_memory(ctrl, basic_plus_adr(str, offset_offset), ! value, T_INT, offset_field_idx, false, StoreNode::unordered); } void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) { int value_offset = java_lang_String::value_offset_in_bytes(); const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* value_field_type = string_type->add_offset(value_offset); store_oop_to_object(ctrl, str, basic_plus_adr(str, value_offset), value_field_type, ! value, TypeAryPtr::CHARS, T_OBJECT, false, StoreNode::unordered); } void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) { int count_offset = java_lang_String::count_offset_in_bytes(); const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* count_field_type = string_type->add_offset(count_offset); int count_field_idx = C->get_alias_index(count_field_type); store_to_memory(ctrl, basic_plus_adr(str, count_offset), ! value, T_INT, count_field_idx, false, StoreNode::unordered); } Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) { // Reify the property as a CastPP node in Ideal graph to comply with monotonicity // assumption of CCP analysis.