src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File 8011646 Cdiff src/share/vm/opto/library_call.cpp

src/share/vm/opto/library_call.cpp

Print this page

        

*** 3976,3999 **** set_edges_for_java_call(slow_call); return slow_call; } ! //------------------------------inline_native_hashcode-------------------- ! // Build special case code for calls to hashCode on an object. bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { assert(is_static == callee()->is_static(), "correct intrinsic selection"); assert(!(is_virtual && is_static), "either virtual, special, or static"); enum { _slow_path = 1, _fast_path, _null_path, PATH_LIMIT }; RegionNode* result_reg = new(C) RegionNode(PATH_LIMIT); ! PhiNode* result_val = new(C) PhiNode(result_reg, ! TypeInt::INT); PhiNode* result_io = new(C) PhiNode(result_reg, Type::ABIO); ! PhiNode* result_mem = new(C) PhiNode(result_reg, Type::MEMORY, ! TypePtr::BOTTOM); Node* obj = NULL; if (!is_static) { // Check for hashing null object obj = null_check_receiver(); if (stopped()) return true; // unconditionally null --- 3976,4000 ---- set_edges_for_java_call(slow_call); return slow_call; } ! /** ! * Build special case code for calls to hashCode on an object. This call may ! * be virtual (invokevirtual) or bound (invokespecial). For each case we generate ! * slightly different code. ! */ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { assert(is_static == callee()->is_static(), "correct intrinsic selection"); assert(!(is_virtual && is_static), "either virtual, special, or static"); enum { _slow_path = 1, _fast_path, _null_path, PATH_LIMIT }; RegionNode* result_reg = new(C) RegionNode(PATH_LIMIT); ! PhiNode* result_val = new(C) PhiNode(result_reg, TypeInt::INT); PhiNode* result_io = new(C) PhiNode(result_reg, Type::ABIO); ! PhiNode* result_mem = new(C) PhiNode(result_reg, Type::MEMORY, TypePtr::BOTTOM); Node* obj = NULL; if (!is_static) { // Check for hashing null object obj = null_check_receiver(); if (stopped()) return true; // unconditionally null
*** 4015,4030 **** if (!stopped()) set_result(result_val->in(_null_path)); return true; } - // After null check, get the object's klass. - Node* obj_klass = load_object_klass(obj); - - // This call may be virtual (invokevirtual) or bound (invokespecial). - // For each case we generate slightly different code. - // We only go to the fast case code if we pass a number of guards. The // paths which do not pass are accumulated in the slow_region. RegionNode* slow_region = new (C) RegionNode(1); record_for_igvn(slow_region); --- 4016,4025 ----
*** 4033,4075 **** // If the target method which we are calling happens to be the native // Object hashCode() method, we pass the guard. We do not need this // guard for non-virtual calls -- the caller is known to be the native // Object hashCode(). if (is_virtual) { generate_virtual_guard(obj_klass, slow_region); } // Get the header out of the object, use LoadMarkNode when available Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); ! Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type(), MemNode::unordered); // Test the header to see if it is unlocked. ! Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place); ! Node *lmasked_header = _gvn.transform(new (C) AndXNode(header, lock_mask)); ! Node *unlocked_val = _gvn.MakeConX(markOopDesc::unlocked_value); ! Node *chk_unlocked = _gvn.transform(new (C) CmpXNode( lmasked_header, unlocked_val)); ! Node *test_unlocked = _gvn.transform(new (C) BoolNode( chk_unlocked, BoolTest::ne)); generate_slow_guard(test_unlocked, slow_region); // Get the hash value and check to see that it has been properly assigned. // We depend on hash_mask being at most 32 bits and avoid the use of // hash_mask_in_place because it could be larger than 32 bits in a 64-bit // vm: see markOop.hpp. ! Node *hash_mask = _gvn.intcon(markOopDesc::hash_mask); ! Node *hash_shift = _gvn.intcon(markOopDesc::hash_shift); ! Node *hshifted_header= _gvn.transform(new (C) URShiftXNode(header, hash_shift)); // This hack lets the hash bits live anywhere in the mark object now, as long // as the shift drops the relevant bits into the low 32 bits. Note that // Java spec says that HashCode is an int so there's no point in capturing // an 'X'-sized hashcode (32 in 32-bit build or 64 in 64-bit build). hshifted_header = ConvX2I(hshifted_header); ! Node *hash_val = _gvn.transform(new (C) AndINode(hshifted_header, hash_mask)); ! Node *no_hash_val = _gvn.intcon(markOopDesc::no_hash); ! Node *chk_assigned = _gvn.transform(new (C) CmpINode( hash_val, no_hash_val)); ! Node *test_assigned = _gvn.transform(new (C) BoolNode( chk_assigned, BoolTest::eq)); generate_slow_guard(test_assigned, slow_region); Node* init_mem = reset_memory(); // fill in the rest of the null path: --- 4028,4075 ---- // If the target method which we are calling happens to be the native // Object hashCode() method, we pass the guard. We do not need this // guard for non-virtual calls -- the caller is known to be the native // Object hashCode(). if (is_virtual) { + // After null check, get the object's klass. + Node* obj_klass = load_object_klass(obj); generate_virtual_guard(obj_klass, slow_region); } // Get the header out of the object, use LoadMarkNode when available Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes()); ! // The control of the load must be NULL. Otherwise, the load can move before ! // the null check after castPP removal. ! Node* no_ctrl = NULL; ! Node* header = make_load(no_ctrl, header_addr, TypeX_X, TypeX_X->basic_type(), MemNode::unordered); // Test the header to see if it is unlocked. ! Node* lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place); ! Node* lmasked_header = _gvn.transform(new (C) AndXNode(header, lock_mask)); ! Node* unlocked_val = _gvn.MakeConX(markOopDesc::unlocked_value); ! Node* chk_unlocked = _gvn.transform(new (C) CmpXNode( lmasked_header, unlocked_val)); ! Node* test_unlocked = _gvn.transform(new (C) BoolNode( chk_unlocked, BoolTest::ne)); generate_slow_guard(test_unlocked, slow_region); // Get the hash value and check to see that it has been properly assigned. // We depend on hash_mask being at most 32 bits and avoid the use of // hash_mask_in_place because it could be larger than 32 bits in a 64-bit // vm: see markOop.hpp. ! Node* hash_mask = _gvn.intcon(markOopDesc::hash_mask); ! Node* hash_shift = _gvn.intcon(markOopDesc::hash_shift); ! Node* hshifted_header= _gvn.transform(new (C) URShiftXNode(header, hash_shift)); // This hack lets the hash bits live anywhere in the mark object now, as long // as the shift drops the relevant bits into the low 32 bits. Note that // Java spec says that HashCode is an int so there's no point in capturing // an 'X'-sized hashcode (32 in 32-bit build or 64 in 64-bit build). hshifted_header = ConvX2I(hshifted_header); ! Node* hash_val = _gvn.transform(new (C) AndINode(hshifted_header, hash_mask)); ! Node* no_hash_val = _gvn.intcon(markOopDesc::no_hash); ! Node* chk_assigned = _gvn.transform(new (C) CmpINode( hash_val, no_hash_val)); ! Node* test_assigned = _gvn.transform(new (C) BoolNode( chk_assigned, BoolTest::eq)); generate_slow_guard(test_assigned, slow_region); Node* init_mem = reset_memory(); // fill in the rest of the null path:
src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File