# HG changeset patch # User twisti # Date 1274362463 25200 # Node ID 5435e77aa3df806763d0c5605c06da99f32fe23e # Parent 261ecc5bb65eb095cc02872c738fdb1b72eefe57 6951083: oops and relocations should part of nmethod not CodeBlob Summary: This moves the oops from Codeblob to nmethod. Reviewed-by: kvn, never diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. 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 @@ -42,8 +42,6 @@ private static CIntegerField instructionsOffsetField; private static CIntegerField frameCompleteOffsetField; private static CIntegerField dataOffsetField; - private static CIntegerField oopsOffsetField; - private static CIntegerField oopsLengthField; private static CIntegerField frameSizeField; private static AddressField oopMapsField; @@ -72,8 +70,6 @@ frameCompleteOffsetField = type.getCIntegerField("_frame_complete_offset"); instructionsOffsetField = type.getCIntegerField("_instructions_offset"); dataOffsetField = type.getCIntegerField("_data_offset"); - oopsOffsetField = type.getCIntegerField("_oops_offset"); - oopsLengthField = type.getCIntegerField("_oops_length"); frameSizeField = type.getCIntegerField("_frame_size"); oopMapsField = type.getAddressField("_oop_maps"); @@ -131,19 +127,10 @@ return headerBegin().addOffsetTo(sizeField.getValue(addr)); } - public Address oopsBegin() { - return headerBegin().addOffsetTo(oopsOffsetField.getValue(addr)); - } - - public Address oopsEnd() { - return oopsBegin().addOffsetTo(getOopsLength()); - } - // Offsets public int getRelocationOffset() { return (int) headerSizeField.getValue(addr); } public int getInstructionsOffset() { return (int) instructionsOffsetField.getValue(addr); } public int getDataOffset() { return (int) dataOffsetField.getValue(addr); } - public int getOopsOffset() { return (int) oopsOffsetField.getValue(addr); } // Sizes public int getSize() { return (int) sizeField.getValue(addr); } @@ -157,19 +144,9 @@ // FIXME: add relocationContains public boolean instructionsContains(Address addr) { return instructionsBegin().lessThanOrEqual(addr) && instructionsEnd().greaterThan(addr); } public boolean dataContains(Address addr) { return dataBegin().lessThanOrEqual(addr) && dataEnd().greaterThan(addr); } - public boolean oopsContains(Address addr) { return oopsBegin().lessThanOrEqual(addr) && oopsEnd().greaterThan(addr); } public boolean contains(Address addr) { return instructionsContains(addr); } public boolean isFrameCompleteAt(Address a) { return instructionsContains(a) && a.minus(instructionsBegin()) >= frameCompleteOffsetField.getValue(addr); } - /** Support for oops in scopes and relocs. Note: index 0 is reserved for null. */ - public OopHandle getOopAt(int index) { - if (index == 0) return null; - if (Assert.ASSERTS_ENABLED) { - Assert.that(index > 0 && index <= getOopsLength(), "must be a valid non-zero index"); - } - return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize()); - } - // Reclamation support (really only used by the nmethods, but in order to get asserts to work // in the CodeCache they are defined virtual here) public boolean isZombie() { return false; } @@ -223,18 +200,8 @@ } protected void printComponentsOn(PrintStream tty) { - // FIXME: add relocation information tty.println(" instructions: [" + instructionsBegin() + ", " + instructionsEnd() + "), " + " data: [" + dataBegin() + ", " + dataEnd() + "), " + - " oops: [" + oopsBegin() + ", " + oopsEnd() + "), " + " frame size: " + getFrameSize()); } - - //-------------------------------------------------------------------------------- - // Internals only below this point - // - - private int getOopsLength() { - return (int) oopsLengthField.getValue(addr); - } } diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. 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 @@ -49,6 +49,7 @@ private static CIntegerField deoptOffsetField; private static CIntegerField origPCOffsetField; private static CIntegerField stubOffsetField; + private static CIntegerField oopsOffsetField; private static CIntegerField scopesDataOffsetField; private static CIntegerField scopesPCsOffsetField; private static CIntegerField dependenciesOffsetField; @@ -98,6 +99,7 @@ deoptOffsetField = type.getCIntegerField("_deoptimize_offset"); origPCOffsetField = type.getCIntegerField("_orig_pc_offset"); stubOffsetField = type.getCIntegerField("_stub_offset"); + oopsOffsetField = type.getCIntegerField("_oops_offset"); scopesDataOffsetField = type.getCIntegerField("_scopes_data_offset"); scopesPCsOffsetField = type.getCIntegerField("_scopes_pcs_offset"); dependenciesOffsetField = type.getCIntegerField("_dependencies_offset"); @@ -141,7 +143,9 @@ public Address exceptionBegin() { return headerBegin().addOffsetTo(getExceptionOffset()); } public Address deoptBegin() { return headerBegin().addOffsetTo(getDeoptOffset()); } public Address stubBegin() { return headerBegin().addOffsetTo(getStubOffset()); } - public Address stubEnd() { return headerBegin().addOffsetTo(getScopesDataOffset()); } + public Address stubEnd() { return headerBegin().addOffsetTo(getOopsOffset()); } + public Address oopsBegin() { return headerBegin().addOffsetTo(getOopsOffset()); } + public Address oopsEnd() { return headerBegin().addOffsetTo(getScopesDataOffset()); } public Address scopesDataBegin() { return headerBegin().addOffsetTo(getScopesDataOffset()); } public Address scopesDataEnd() { return headerBegin().addOffsetTo(getScopesPCsOffset()); } public Address scopesPCsBegin() { return headerBegin().addOffsetTo(getScopesPCsOffset()); } @@ -156,6 +160,7 @@ public int constantsSize() { return (int) constantsEnd() .minus(constantsBegin()); } public int codeSize() { return (int) codeEnd() .minus(codeBegin()); } public int stubSize() { return (int) stubEnd() .minus(stubBegin()); } + public int oopsSize() { return (int) oopsEnd() .minus(oopsBegin()); } public int scopesDataSize() { return (int) scopesDataEnd() .minus(scopesDataBegin()); } public int scopesPCsSize() { return (int) scopesPCsEnd() .minus(scopesPCsBegin()); } public int dependenciesSize() { return (int) dependenciesEnd().minus(dependenciesBegin()); } @@ -178,6 +183,7 @@ public boolean constantsContains (Address addr) { return constantsBegin() .lessThanOrEqual(addr) && constantsEnd() .greaterThan(addr); } public boolean codeContains (Address addr) { return codeBegin() .lessThanOrEqual(addr) && codeEnd() .greaterThan(addr); } public boolean stubContains (Address addr) { return stubBegin() .lessThanOrEqual(addr) && stubEnd() .greaterThan(addr); } + public boolean oopsContains (Address addr) { return oopsBegin() .lessThanOrEqual(addr) && oopsEnd() .greaterThan(addr); } public boolean scopesDataContains (Address addr) { return scopesDataBegin() .lessThanOrEqual(addr) && scopesDataEnd() .greaterThan(addr); } public boolean scopesPCsContains (Address addr) { return scopesPCsBegin() .lessThanOrEqual(addr) && scopesPCsEnd() .greaterThan(addr); } public boolean handlerTableContains(Address addr) { return handlerTableBegin().lessThanOrEqual(addr) && handlerTableEnd().greaterThan(addr); } @@ -187,6 +193,15 @@ public Address getEntryPoint() { return entryPointField.getValue(addr); } public Address getVerifiedEntryPoint() { return verifiedEntryPointField.getValue(addr); } + /** Support for oops in scopes and relocs. Note: index 0 is reserved for null. */ + public OopHandle getOopAt(int index) { + if (index == 0) return null; + if (Assert.ASSERTS_ENABLED) { + Assert.that(index > 0 && index <= oopsSize(), "must be a valid non-zero index"); + } + return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize()); + } + // FIXME: add interpreter_entry_point() // FIXME: add lazy_interpreter_entry_point() for C2 @@ -338,6 +353,14 @@ printOn(System.out); } + protected void printComponentsOn(PrintStream tty) { + // FIXME: add relocation information + tty.println(" instructions: [" + instructionsBegin() + ", " + instructionsEnd() + "), " + + " data: [" + dataBegin() + ", " + dataEnd() + "), " + + " oops: [" + oopsBegin() + ", " + oopsEnd() + "), " + + " frame size: " + getFrameSize()); + } + public String toString() { Method method = getMethod(); return "NMethod for " + @@ -367,6 +390,7 @@ private int getExceptionOffset() { return (int) exceptionOffsetField .getValue(addr); } private int getDeoptOffset() { return (int) deoptOffsetField .getValue(addr); } private int getStubOffset() { return (int) stubOffsetField .getValue(addr); } + private int getOopsOffset() { return (int) oopsOffsetField .getValue(addr); } private int getScopesDataOffset() { return (int) scopesDataOffsetField .getValue(addr); } private int getScopesPCsOffset() { return (int) scopesPCsOffsetField .getValue(addr); } private int getDependenciesOffset() { return (int) dependenciesOffsetField.getValue(addr); } diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. 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 @@ -98,7 +98,12 @@ } loc.inBlobInstructions = loc.blob.instructionsContains(a); loc.inBlobData = loc.blob.dataContains(a); - loc.inBlobOops = loc.blob.oopsContains(a); + + if (loc.blob.isNMethod()) { + NMethod nm = (NMethod) loc.blob; + loc.inBlobOops = nm.oopsContains(a); + } + loc.inBlobUnknownLocation = (!(loc.inBlobInstructions || loc.inBlobData || loc.inBlobOops)); diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -321,7 +321,8 @@ set_long_at(add_offset, set_data32_simm13( long_at(add_offset), x)); // also store the value into an oop_Relocation cell, if any - CodeBlob* nm = CodeCache::find_blob(instruction_address()); + CodeBlob* cb = CodeCache::find_blob(instruction_address()); + nmethod* nm = cb ? cb->as_nmethod_or_null() : NULL; if (nm != NULL) { RelocIterator iter(nm, instruction_address(), next_instruction_address()); oop* oop_addr = NULL; @@ -430,7 +431,8 @@ set_long_at(add_offset, set_data32_simm13(long_at(add_offset), x)); // also store the value into an oop_Relocation cell, if any - CodeBlob* nm = CodeCache::find_blob(instruction_address()); + CodeBlob* cb = CodeCache::find_blob(instruction_address()); + nmethod* nm = cb ? cb->as_nmethod_or_null() : NULL; if (nm != NULL) { RelocIterator iter(nm, instruction_address(), next_instruction_address()); oop* oop_addr = NULL; diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp --- a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. 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 @@ -232,12 +232,11 @@ GEN_OFFS(CodeBlob, _header_size); GEN_OFFS(CodeBlob, _instructions_offset); GEN_OFFS(CodeBlob, _data_offset); - GEN_OFFS(CodeBlob, _oops_offset); - GEN_OFFS(CodeBlob, _oops_length); GEN_OFFS(CodeBlob, _frame_size); printf("\n"); GEN_OFFS(nmethod, _method); + GEN_OFFS(nmethod, _oops_offset); GEN_OFFS(nmethod, _scopes_data_offset); GEN_OFFS(nmethod, _scopes_pcs_offset); GEN_OFFS(nmethod, _handler_table_offset); diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/os/solaris/dtrace/libjvm_db.c --- a/hotspot/src/os/solaris/dtrace/libjvm_db.c Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. 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 @@ -130,7 +130,7 @@ int32_t scopes_data_beg; /* _scopes_data_offset */ int32_t scopes_data_end; int32_t oops_beg; /* _oops_offset */ - int32_t oops_len; /* _oops_length */ + int32_t oops_end; int32_t scopes_pcs_beg; /* _scopes_pcs_offset */ int32_t scopes_pcs_end; @@ -597,9 +597,9 @@ CHECK_FAIL(err); /* Oops */ - err = ps_pread(J->P, nm + OFFSET_CodeBlob_oops_offset, &N->oops_beg, SZ32); + err = ps_pread(J->P, nm + OFFSET_nmethod_oops_offset, &N->oops_beg, SZ32); CHECK_FAIL(err); - err = ps_pread(J->P, nm + OFFSET_CodeBlob_oops_length, &N->oops_len, SZ32); + err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->oops_end, SZ32); CHECK_FAIL(err); /* scopes_pcs */ @@ -624,8 +624,8 @@ fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n", N->orig_pc_offset); - fprintf(stderr, "\t nmethod_info: oops_beg: %#x, oops_len: %#x\n", - N->oops_beg, N->oops_len); + fprintf(stderr, "\t nmethod_info: oops_beg: %#x, oops_end: %#x\n", + N->oops_beg, N->oops_end); fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n", N->scopes_data_beg, N->scopes_data_end); @@ -959,8 +959,8 @@ err = scope_desc_at(N, decode_offset, vf); CHECK_FAIL(err); - if (vf->methodIdx > N->oops_len) { - fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops_len) !\n"); + if (vf->methodIdx > ((N->oops_end - N->oops_beg) / POINTER_SIZE)) { + fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops length) !\n"); return -1; } err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE, diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/asm/codeBuffer.hpp --- a/hotspot/src/share/vm/asm/codeBuffer.hpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/asm/codeBuffer.hpp Thu May 20 06:34:23 2010 -0700 @@ -510,9 +510,9 @@ copy_relocations_to(blob); copy_code_to(blob); } - void copy_oops_to(CodeBlob* blob) { + void copy_oops_to(nmethod* nm) { if (!oop_recorder()->is_unused()) { - oop_recorder()->copy_to(blob); + oop_recorder()->copy_to(nm); } } diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/codeBlob.cpp --- a/hotspot/src/share/vm/code/codeBlob.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/codeBlob.cpp Thu May 20 06:34:23 2010 -0700 @@ -66,8 +66,6 @@ _relocation_size = locs_size; _instructions_offset = align_code_offset(header_size + locs_size); _data_offset = size; - _oops_offset = size; - _oops_length = 0; _frame_size = 0; set_oop_maps(NULL); } @@ -94,9 +92,6 @@ _relocation_size = round_to(cb->total_relocation_size(), oopSize); _instructions_offset = align_code_offset(header_size + _relocation_size); _data_offset = _instructions_offset + round_to(cb->total_code_size(), oopSize); - _oops_offset = _size - round_to(cb->total_oop_size(), oopSize); - _oops_length = 0; // temporary, until the copy_oops handshake - assert(_oops_offset >= _data_offset, "codeBlob is too small"); assert(_data_offset <= size, "codeBlob is too small"); cb->copy_code_and_locs_to(this); @@ -131,99 +126,6 @@ } -// Promote one word from an assembly-time handle to a live embedded oop. -inline void CodeBlob::initialize_immediate_oop(oop* dest, jobject handle) { - if (handle == NULL || - // As a special case, IC oops are initialized to 1 or -1. - handle == (jobject) Universe::non_oop_word()) { - (*dest) = (oop)handle; - } else { - (*dest) = JNIHandles::resolve_non_null(handle); - } -} - - -void CodeBlob::copy_oops(GrowableArray* array) { - assert(_oops_length == 0, "do this handshake just once, please"); - int length = array->length(); - assert((address)(oops_begin() + length) <= data_end(), "oops big enough"); - oop* dest = oops_begin(); - for (int index = 0 ; index < length; index++) { - initialize_immediate_oop(&dest[index], array->at(index)); - } - _oops_length = length; - - // Now we can fix up all the oops in the code. - // We need to do this in the code because - // the assembler uses jobjects as placeholders. - // The code and relocations have already been - // initialized by the CodeBlob constructor, - // so it is valid even at this early point to - // iterate over relocations and patch the code. - fix_oop_relocations(NULL, NULL, /*initialize_immediates=*/ true); -} - - -relocInfo::relocType CodeBlob::reloc_type_for_address(address pc) { - RelocIterator iter(this, pc, pc+1); - while (iter.next()) { - return (relocInfo::relocType) iter.type(); - } - // No relocation info found for pc - ShouldNotReachHere(); - return relocInfo::none; // dummy return value -} - - -bool CodeBlob::is_at_poll_return(address pc) { - RelocIterator iter(this, pc, pc+1); - while (iter.next()) { - if (iter.type() == relocInfo::poll_return_type) - return true; - } - return false; -} - - -bool CodeBlob::is_at_poll_or_poll_return(address pc) { - RelocIterator iter(this, pc, pc+1); - while (iter.next()) { - relocInfo::relocType t = iter.type(); - if (t == relocInfo::poll_return_type || t == relocInfo::poll_type) - return true; - } - return false; -} - - -void CodeBlob::fix_oop_relocations(address begin, address end, - bool initialize_immediates) { - // re-patch all oop-bearing instructions, just in case some oops moved - RelocIterator iter(this, begin, end); - while (iter.next()) { - if (iter.type() == relocInfo::oop_type) { - oop_Relocation* reloc = iter.oop_reloc(); - if (initialize_immediates && reloc->oop_is_immediate()) { - oop* dest = reloc->oop_addr(); - initialize_immediate_oop(dest, (jobject) *dest); - } - // Refresh the oop-related bits of this instruction. - reloc->fix_oop_relocation(); - } - - // There must not be any interfering patches or breakpoints. - assert(!(iter.type() == relocInfo::breakpoint_type - && iter.breakpoint_reloc()->active()), - "no active breakpoint"); - } -} - -void CodeBlob::do_unloading(BoolObjectClosure* is_alive, - OopClosure* keep_alive, - bool unloading_occurred) { - ShouldNotReachHere(); -} - OopMap* CodeBlob::oop_map_for_return_address(address return_address) { address pc = return_address ; assert (oop_maps() != NULL, "nope"); diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/codeBlob.hpp --- a/hotspot/src/share/vm/code/codeBlob.hpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/codeBlob.hpp Thu May 20 06:34:23 2010 -0700 @@ -54,17 +54,12 @@ // that range. There is a similar range(s) on returns // which we don't detect. int _data_offset; // offset to where data region begins - int _oops_offset; // offset to where embedded oop table begins (inside data) - int _oops_length; // number of embedded oops int _frame_size; // size of stack frame OopMapSet* _oop_maps; // OopMap for this CodeBlob CodeComments _comments; friend class OopRecorder; - void fix_oop_relocations(address begin, address end, bool initialize_immediates); - inline void initialize_immediate_oop(oop* dest, jobject handle); - public: // Returns the space needed for CodeBlob static unsigned int allocation_size(CodeBuffer* cb, int header_size); @@ -115,14 +110,11 @@ address instructions_end() const { return (address) header_begin() + _data_offset; } address data_begin() const { return (address) header_begin() + _data_offset; } address data_end() const { return (address) header_begin() + _size; } - oop* oops_begin() const { return (oop*) (header_begin() + _oops_offset); } - oop* oops_end() const { return oops_begin() + _oops_length; } // Offsets int relocation_offset() const { return _header_size; } int instructions_offset() const { return _instructions_offset; } int data_offset() const { return _data_offset; } - int oops_offset() const { return _oops_offset; } // Sizes int size() const { return _size; } @@ -130,40 +122,16 @@ int relocation_size() const { return (address) relocation_end() - (address) relocation_begin(); } int instructions_size() const { return instructions_end() - instructions_begin(); } int data_size() const { return data_end() - data_begin(); } - int oops_size() const { return (address) oops_end() - (address) oops_begin(); } // Containment bool blob_contains(address addr) const { return header_begin() <= addr && addr < data_end(); } bool relocation_contains(relocInfo* addr) const{ return relocation_begin() <= addr && addr < relocation_end(); } bool instructions_contains(address addr) const { return instructions_begin() <= addr && addr < instructions_end(); } bool data_contains(address addr) const { return data_begin() <= addr && addr < data_end(); } - bool oops_contains(oop* addr) const { return oops_begin() <= addr && addr < oops_end(); } bool contains(address addr) const { return instructions_contains(addr); } bool is_frame_complete_at(address addr) const { return instructions_contains(addr) && addr >= instructions_begin() + _frame_complete_offset; } - // Relocation support - void fix_oop_relocations(address begin, address end) { - fix_oop_relocations(begin, end, false); - } - void fix_oop_relocations() { - fix_oop_relocations(NULL, NULL, false); - } - relocInfo::relocType reloc_type_for_address(address pc); - bool is_at_poll_return(address pc); - bool is_at_poll_or_poll_return(address pc); - - // Support for oops in scopes and relocs: - // Note: index 0 is reserved for null. - oop oop_at(int index) const { return index == 0? (oop)NULL: *oop_addr_at(index); } - oop* oop_addr_at(int index) const{ // for GC - // relocation indexes are biased by 1 (because 0 is reserved) - assert(index > 0 && index <= _oops_length, "must be a valid non-zero index"); - return &oops_begin()[index-1]; - } - - void copy_oops(GrowableArray* oops); - // CodeCache support: really only used by the nmethods, but in order to get // asserts and certain bookkeeping to work in the CodeCache they are defined // virtual here. @@ -175,12 +143,6 @@ // GC support virtual bool is_alive() const = 0; - virtual void do_unloading(BoolObjectClosure* is_alive, - OopClosure* keep_alive, - bool unloading_occurred); - virtual void oops_do(OopClosure* f) = 0; - // (All CodeBlob subtypes other than NMethod currently have - // an empty oops_do() method. // OopMap for frame OopMapSet* oop_maps() const { return _oop_maps; } @@ -245,11 +207,6 @@ // GC/Verification support void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ } bool is_alive() const { return true; } - void do_unloading(BoolObjectClosure* is_alive, - OopClosure* keep_alive, - bool unloading_occurred) { /* do nothing */ } - - void oops_do(OopClosure* f) { /* do nothing*/ } void verify(); void print() const PRODUCT_RETURN; @@ -334,10 +291,6 @@ // GC/Verification support void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ } bool is_alive() const { return true; } - void do_unloading(BoolObjectClosure* is_alive, - OopClosure* keep_alive, - bool unloading_occurred) { /* do nothing */ } - void oops_do(OopClosure* f) { /* do-nothing*/ } void verify(); void print() const PRODUCT_RETURN; @@ -363,9 +316,6 @@ {}; bool is_alive() const { return true; } - void do_unloading(BoolObjectClosure* is_alive, - OopClosure* keep_alive, - bool unloading_occurred) { /* do-nothing*/ } void verify(); // does nothing void print() const PRODUCT_RETURN; @@ -423,9 +373,6 @@ // GC for args void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* Nothing to do */ } - // Iteration - void oops_do(OopClosure* f) {} - // Printing void print_value_on(outputStream* st) const PRODUCT_RETURN; @@ -477,9 +424,6 @@ // Typing bool is_uncommon_trap_stub() const { return true; } - - // Iteration - void oops_do(OopClosure* f) {} }; @@ -512,9 +456,6 @@ // Typing bool is_exception_stub() const { return true; } - - // Iteration - void oops_do(OopClosure* f) {} }; #endif // COMPILER2 @@ -548,7 +489,4 @@ // Typing bool is_safepoint_stub() const { return true; } - - // Iteration - void oops_do(OopClosure* f) {} }; diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/codeCache.cpp --- a/hotspot/src/share/vm/code/codeCache.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/codeCache.cpp Thu May 20 06:34:23 2010 -0700 @@ -74,12 +74,12 @@ total_size += cb->size(); header_size += cb->header_size(); relocation_size += cb->relocation_size(); - scopes_oop_size += cb->oops_size(); if (cb->is_nmethod()) { - nmethod *nm = (nmethod*)cb; + nmethod* nm = cb->as_nmethod_or_null(); code_size += nm->code_size(); stub_size += nm->stub_size(); + scopes_oop_size += nm->oops_size(); scopes_data_size += nm->scopes_data_size(); scopes_pcs_size += nm->scopes_pcs_size(); } else { @@ -262,14 +262,14 @@ } -// Mark code blobs for unloading if they contain otherwise -// unreachable oops. +// Mark nmethods for unloading if they contain otherwise unreachable +// oops. void CodeCache::do_unloading(BoolObjectClosure* is_alive, OopClosure* keep_alive, bool unloading_occurred) { assert_locked_or_safepoint(CodeCache_lock); - FOR_ALL_ALIVE_BLOBS(cb) { - cb->do_unloading(is_alive, keep_alive, unloading_occurred); + FOR_ALL_ALIVE_NMETHODS(nm) { + nm->do_unloading(is_alive, keep_alive, unloading_occurred); } } @@ -509,9 +509,9 @@ if (needs_cache_clean()) { nm->cleanup_inline_caches(); } - debug_only(nm->verify();) + DEBUG_ONLY(nm->verify()); + nm->fix_oop_relocations(); } - cb->fix_oop_relocations(); } set_needs_cache_clean(false); prune_scavenge_root_nmethods(); diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/compiledIC.cpp --- a/hotspot/src/share/vm/code/compiledIC.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/compiledIC.cpp Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -441,11 +441,11 @@ } -inline static RelocIterator parse_ic(CodeBlob* code, address ic_call, oop* &_oop_addr, bool *is_optimized) { +inline static RelocIterator parse_ic(nmethod* nm, address ic_call, oop* &_oop_addr, bool *is_optimized) { address first_oop = NULL; // Mergers please note: Sun SC5.x CC insists on an lvalue for a reference parameter. - CodeBlob *code1 = code; - return virtual_call_Relocation::parse_ic(code1, ic_call, first_oop, _oop_addr, is_optimized); + nmethod* tmp_nm = nm; + return virtual_call_Relocation::parse_ic(tmp_nm, ic_call, first_oop, _oop_addr, is_optimized); } CompiledIC::CompiledIC(NativeCall* ic_call) diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/nmethod.cpp Thu May 20 06:34:23 2010 -0700 @@ -99,12 +99,12 @@ code_size += nm->code_size(); stub_size += nm->stub_size(); consts_size += nm->consts_size(); + oops_size += nm->oops_size(); scopes_data_size += nm->scopes_data_size(); scopes_pcs_size += nm->scopes_pcs_size(); dependencies_size += nm->dependencies_size(); handler_table_size += nm->handler_table_size(); nul_chk_table_size += nm->nul_chk_table_size(); - oops_size += nm->oops_size(); } void print_nmethod_stats() { if (nmethod_count == 0) return; @@ -114,12 +114,12 @@ if (code_size != 0) tty->print_cr(" main code = %d", code_size); if (stub_size != 0) tty->print_cr(" stub code = %d", stub_size); if (consts_size != 0) tty->print_cr(" constants = %d", consts_size); + if (oops_size != 0) tty->print_cr(" oops = %d", oops_size); if (scopes_data_size != 0) tty->print_cr(" scopes data = %d", scopes_data_size); if (scopes_pcs_size != 0) tty->print_cr(" scopes pcs = %d", scopes_pcs_size); if (dependencies_size != 0) tty->print_cr(" dependencies = %d", dependencies_size); if (handler_table_size != 0) tty->print_cr(" handler table = %d", handler_table_size); if (nul_chk_table_size != 0) tty->print_cr(" nul chk table = %d", nul_chk_table_size); - if (oops_size != 0) tty->print_cr(" oops = %d", oops_size); } int native_nmethod_count; @@ -600,7 +600,8 @@ #endif // def HAVE_DTRACE_H _stub_offset = data_offset(); _consts_offset = data_offset(); - _scopes_data_offset = data_offset(); + _oops_offset = data_offset(); + _scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size(), oopSize); _scopes_pcs_offset = _scopes_data_offset; _dependencies_offset = _scopes_pcs_offset; _handler_table_offset = _dependencies_offset; @@ -690,7 +691,8 @@ _orig_pc_offset = 0; _stub_offset = data_offset(); _consts_offset = data_offset(); - _scopes_data_offset = data_offset(); + _oops_offset = data_offset(); + _scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size(), oopSize); _scopes_pcs_offset = _scopes_data_offset; _dependencies_offset = _scopes_pcs_offset; _handler_table_offset = _dependencies_offset; @@ -805,8 +807,9 @@ _unwind_handler_offset = -1; } _consts_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->consts()->start()); - _scopes_data_offset = data_offset(); - _scopes_pcs_offset = _scopes_data_offset + round_to(debug_info->data_size (), oopSize); + _oops_offset = data_offset(); + _scopes_data_offset = _oops_offset + round_to(code_buffer->total_oop_size (), oopSize); + _scopes_pcs_offset = _scopes_data_offset + round_to(debug_info->data_size (), oopSize); _dependencies_offset = _scopes_pcs_offset + adjust_pcs_size(debug_info->pcs_size()); _handler_table_offset = _dependencies_offset + round_to(dependencies->size_in_bytes (), oopSize); _nul_chk_table_offset = _handler_table_offset + round_to(handler_table->size_in_bytes(), oopSize); @@ -990,6 +993,79 @@ } +// Promote one word from an assembly-time handle to a live embedded oop. +inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) { + if (handle == NULL || + // As a special case, IC oops are initialized to 1 or -1. + handle == (jobject) Universe::non_oop_word()) { + (*dest) = (oop) handle; + } else { + (*dest) = JNIHandles::resolve_non_null(handle); + } +} + + +void nmethod::copy_oops(GrowableArray* array) { + //assert(oops_size() == 0, "do this handshake just once, please"); + int length = array->length(); + assert((address)(oops_begin() + length) <= data_end(), "oops big enough"); + oop* dest = oops_begin(); + for (int index = 0 ; index < length; index++) { + initialize_immediate_oop(&dest[index], array->at(index)); + } + + // Now we can fix up all the oops in the code. We need to do this + // in the code because the assembler uses jobjects as placeholders. + // The code and relocations have already been initialized by the + // CodeBlob constructor, so it is valid even at this early point to + // iterate over relocations and patch the code. + fix_oop_relocations(NULL, NULL, /*initialize_immediates=*/ true); +} + + +bool nmethod::is_at_poll_return(address pc) { + RelocIterator iter(this, pc, pc+1); + while (iter.next()) { + if (iter.type() == relocInfo::poll_return_type) + return true; + } + return false; +} + + +bool nmethod::is_at_poll_or_poll_return(address pc) { + RelocIterator iter(this, pc, pc+1); + while (iter.next()) { + relocInfo::relocType t = iter.type(); + if (t == relocInfo::poll_return_type || t == relocInfo::poll_type) + return true; + } + return false; +} + + +void nmethod::fix_oop_relocations(address begin, address end, bool initialize_immediates) { + // re-patch all oop-bearing instructions, just in case some oops moved + RelocIterator iter(this, begin, end); + while (iter.next()) { + if (iter.type() == relocInfo::oop_type) { + oop_Relocation* reloc = iter.oop_reloc(); + if (initialize_immediates && reloc->oop_is_immediate()) { + oop* dest = reloc->oop_addr(); + initialize_immediate_oop(dest, (jobject) *dest); + } + // Refresh the oop-related bits of this instruction. + reloc->fix_oop_relocation(); + } + + // There must not be any interfering patches or breakpoints. + assert(!(iter.type() == relocInfo::breakpoint_type + && iter.breakpoint_reloc()->active()), + "no active breakpoint"); + } +} + + ScopeDesc* nmethod::scope_desc_at(address pc) { PcDesc* pd = pc_desc_at(pc); guarantee(pd != NULL, "scope must be present"); @@ -2282,6 +2358,10 @@ consts_begin(), consts_end(), consts_size()); + if (oops_size () > 0) tty->print_cr(" oops [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + oops_begin(), + oops_end(), + oops_size()); if (scopes_data_size () > 0) tty->print_cr(" scopes data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", scopes_data_begin(), scopes_data_end(), diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/nmethod.hpp --- a/hotspot/src/share/vm/code/nmethod.hpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/nmethod.hpp Thu May 20 06:34:23 2010 -0700 @@ -105,6 +105,7 @@ // [Relocation] // - relocation information // - constant part (doubles, longs and floats used in nmethod) +// - oop table // [Code] // - code body // - exception handler @@ -161,6 +162,7 @@ #endif // def HAVE_DTRACE_H int _stub_offset; int _consts_offset; + int _oops_offset; // offset to where embedded oop table begins (inside data) int _scopes_data_offset; int _scopes_pcs_offset; int _dependencies_offset; @@ -347,7 +349,10 @@ address stub_begin () const { return header_begin() + _stub_offset ; } address stub_end () const { return header_begin() + _consts_offset ; } address consts_begin () const { return header_begin() + _consts_offset ; } - address consts_end () const { return header_begin() + _scopes_data_offset ; } + address consts_end () const { return header_begin() + _oops_offset ; } + oop* oops_begin () const { return (oop*) (header_begin() + _oops_offset) ; } + oop* oops_end () const { return (oop*) (header_begin() + _scopes_data_offset) ; } + address scopes_data_begin () const { return header_begin() + _scopes_data_offset ; } address scopes_data_end () const { return header_begin() + _scopes_pcs_offset ; } PcDesc* scopes_pcs_begin () const { return (PcDesc*)(header_begin() + _scopes_pcs_offset ); } @@ -359,20 +364,24 @@ address nul_chk_table_begin () const { return header_begin() + _nul_chk_table_offset ; } address nul_chk_table_end () const { return header_begin() + _nmethod_end_offset ; } - int code_size () const { return code_end () - code_begin (); } - int stub_size () const { return stub_end () - stub_begin (); } - int consts_size () const { return consts_end () - consts_begin (); } - int scopes_data_size () const { return scopes_data_end () - scopes_data_begin (); } - int scopes_pcs_size () const { return (intptr_t)scopes_pcs_end () - (intptr_t)scopes_pcs_begin (); } - int dependencies_size () const { return dependencies_end () - dependencies_begin (); } - int handler_table_size() const { return handler_table_end() - handler_table_begin(); } - int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); } + // Sizes + int code_size () const { return code_end () - code_begin (); } + int stub_size () const { return stub_end () - stub_begin (); } + int consts_size () const { return consts_end () - consts_begin (); } + int oops_size () const { return (address) oops_end () - (address) oops_begin (); } + int scopes_data_size () const { return scopes_data_end () - scopes_data_begin (); } + int scopes_pcs_size () const { return (intptr_t) scopes_pcs_end () - (intptr_t) scopes_pcs_begin (); } + int dependencies_size () const { return dependencies_end () - dependencies_begin (); } + int handler_table_size() const { return handler_table_end() - handler_table_begin(); } + int nul_chk_table_size() const { return nul_chk_table_end() - nul_chk_table_begin(); } int total_size () const; + // Containment bool code_contains (address addr) const { return code_begin () <= addr && addr < code_end (); } bool stub_contains (address addr) const { return stub_begin () <= addr && addr < stub_end (); } bool consts_contains (address addr) const { return consts_begin () <= addr && addr < consts_end (); } + bool oops_contains (oop* addr) const { return oops_begin () <= addr && addr < oops_end (); } bool scopes_data_contains (address addr) const { return scopes_data_begin () <= addr && addr < scopes_data_end (); } bool scopes_pcs_contains (PcDesc* addr) const { return scopes_pcs_begin () <= addr && addr < scopes_pcs_end (); } bool handler_table_contains(address addr) const { return handler_table_begin() <= addr && addr < handler_table_end(); } @@ -431,6 +440,29 @@ int version() const { return flags.version; } void set_version(int v); + // Support for oops in scopes and relocs: + // Note: index 0 is reserved for null. + oop oop_at(int index) const { return index == 0 ? (oop) NULL: *oop_addr_at(index); } + oop* oop_addr_at(int index) const { // for GC + // relocation indexes are biased by 1 (because 0 is reserved) + assert(index > 0 && index <= oops_size(), "must be a valid non-zero index"); + return &oops_begin()[index - 1]; + } + + void copy_oops(GrowableArray* oops); + + // Relocation support +private: + void fix_oop_relocations(address begin, address end, bool initialize_immediates); + inline void initialize_immediate_oop(oop* dest, jobject handle); + +public: + void fix_oop_relocations(address begin, address end) { fix_oop_relocations(begin, end, false); } + void fix_oop_relocations() { fix_oop_relocations(NULL, NULL, false); } + + bool is_at_poll_return(address pc); + bool is_at_poll_or_poll_return(address pc); + // Non-perm oop support bool on_scavenge_root_list() const { return (_scavenge_root_state & 1) != 0; } protected: @@ -511,8 +543,8 @@ void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f); - virtual void oops_do(OopClosure* f) { oops_do(f, false); } - void oops_do(OopClosure* f, bool do_strong_roots_only); + void oops_do(OopClosure* f) { oops_do(f, false); } + void oops_do(OopClosure* f, bool do_strong_roots_only); bool detect_scavenge_root_oops(); void verify_scavenge_root_oops() PRODUCT_RETURN; diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/oopRecorder.cpp --- a/hotspot/src/share/vm/code/oopRecorder.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/oopRecorder.cpp Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 Sun Microsystems, Inc. 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 @@ -50,10 +50,10 @@ return _handles->length() * sizeof(oop); } -void OopRecorder::copy_to(CodeBlob* code) { +void OopRecorder::copy_to(nmethod* nm) { assert(_complete, "must be frozen"); maybe_initialize(); // get non-null handles, even if we have no oops - code->copy_oops(_handles); + nm->copy_oops(_handles); } void OopRecorder::maybe_initialize() { diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/oopRecorder.hpp --- a/hotspot/src/share/vm/code/oopRecorder.hpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/oopRecorder.hpp Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 Sun Microsystems, Inc. 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 @@ -70,8 +70,8 @@ return _handles->length() + first_index; } - // copy the generated oop table to CodeBlob - void copy_to(CodeBlob* code); // => code->copy_oops(_handles) + // copy the generated oop table to nmethod + void copy_to(nmethod* nm); // => nm->copy_oops(_handles) bool is_unused() { return _handles == NULL && !_complete; } #ifdef ASSERT diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/relocInfo.cpp --- a/hotspot/src/share/vm/code/relocInfo.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/relocInfo.cpp Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -115,24 +115,25 @@ // ---------------------------------------------------------------------------------------------------- // Implementation of RelocIterator -void RelocIterator::initialize(CodeBlob* cb, address begin, address limit) { +void RelocIterator::initialize(nmethod* nm, address begin, address limit) { initialize_misc(); - if (cb == NULL && begin != NULL) { - // allow CodeBlob to be deduced from beginning address - cb = CodeCache::find_blob(begin); + if (nm == NULL && begin != NULL) { + // allow nmethod to be deduced from beginning address + CodeBlob* cb = CodeCache::find_blob(begin); + nm = cb->as_nmethod_or_null(); } - assert(cb != NULL, "must be able to deduce nmethod from other arguments"); + assert(nm != NULL, "must be able to deduce nmethod from other arguments"); - _code = cb; - _current = cb->relocation_begin()-1; - _end = cb->relocation_end(); - _addr = (address) cb->instructions_begin(); + _code = nm; + _current = nm->relocation_begin() - 1; + _end = nm->relocation_end(); + _addr = (address) nm->instructions_begin(); assert(!has_current(), "just checking"); - address code_end = cb->instructions_end(); + address code_end = nm->instructions_end(); - assert(begin == NULL || begin >= cb->instructions_begin(), "in bounds"); + assert(begin == NULL || begin >= nm->instructions_begin(), "in bounds"); // FIX THIS assert(limit == NULL || limit <= code_end, "in bounds"); set_limits(begin, limit); } @@ -754,7 +755,7 @@ // oop is stored in the code stream return (oop*) pd_address_in_code(); } else { - // oop is stored in table at CodeBlob::oops_begin + // oop is stored in table at nmethod::oops_begin return code()->oop_addr_at(n); } } @@ -776,26 +777,28 @@ } -RelocIterator virtual_call_Relocation::parse_ic(CodeBlob* &code, address &ic_call, address &first_oop, +RelocIterator virtual_call_Relocation::parse_ic(nmethod* &nm, address &ic_call, address &first_oop, oop* &oop_addr, bool *is_optimized) { assert(ic_call != NULL, "ic_call address must be set"); assert(ic_call != NULL || first_oop != NULL, "must supply a non-null input"); - if (code == NULL) { + if (nm == NULL) { + CodeBlob* code; if (ic_call != NULL) { code = CodeCache::find_blob(ic_call); } else if (first_oop != NULL) { code = CodeCache::find_blob(first_oop); } - assert(code != NULL, "address to parse must be in CodeBlob"); + nm = code->as_nmethod_or_null(); + assert(nm != NULL, "address to parse must be in nmethod"); } - assert(ic_call == NULL || code->contains(ic_call), "must be in CodeBlob"); - assert(first_oop == NULL || code->contains(first_oop), "must be in CodeBlob"); + assert(ic_call == NULL || nm->contains(ic_call), "must be in nmethod"); + assert(first_oop == NULL || nm->contains(first_oop), "must be in nmethod"); address oop_limit = NULL; if (ic_call != NULL) { // search for the ic_call at the given address - RelocIterator iter(code, ic_call, ic_call+1); + RelocIterator iter(nm, ic_call, ic_call+1); bool ret = iter.next(); assert(ret == true, "relocInfo must exist at this address"); assert(iter.addr() == ic_call, "must find ic_call"); @@ -814,7 +817,7 @@ } // search for the first_oop, to get its oop_addr - RelocIterator all_oops(code, first_oop); + RelocIterator all_oops(nm, first_oop); RelocIterator iter = all_oops; iter.set_limit(first_oop+1); bool found_oop = false; @@ -842,7 +845,7 @@ } } guarantee(!did_reset, "cannot find ic_call"); - iter = RelocIterator(code); // search the whole CodeBlob + iter = RelocIterator(nm); // search the whole nmethod did_reset = true; } @@ -1175,9 +1178,9 @@ // For the debugger: extern "C" -void print_blob_locs(CodeBlob* cb) { - cb->print(); - RelocIterator iter(cb); +void print_blob_locs(nmethod* nm) { + nm->print(); + RelocIterator iter(nm); iter.print(); } extern "C" diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/code/relocInfo.hpp --- a/hotspot/src/share/vm/code/relocInfo.hpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/code/relocInfo.hpp Thu May 20 06:34:23 2010 -0700 @@ -512,7 +512,7 @@ address _limit; // stop producing relocations after this _addr relocInfo* _current; // the current relocation information relocInfo* _end; // end marker; we're done iterating when _current == _end - CodeBlob* _code; // compiled method containing _addr + nmethod* _code; // compiled method containing _addr address _addr; // instruction to which the relocation applies short _databuf; // spare buffer for compressed data short* _data; // pointer to the relocation's data @@ -549,7 +549,7 @@ address compute_section_start(int n) const; // out-of-line helper - void initialize(CodeBlob* nm, address begin, address limit); + void initialize(nmethod* nm, address begin, address limit); friend class PatchingRelocIterator; // make an uninitialized one, for PatchingRelocIterator: @@ -557,7 +557,7 @@ public: // constructor - RelocIterator(CodeBlob* cb, address begin = NULL, address limit = NULL); + RelocIterator(nmethod* nm, address begin = NULL, address limit = NULL); RelocIterator(CodeSection* cb, address begin = NULL, address limit = NULL); // get next reloc info, return !eos @@ -592,7 +592,7 @@ relocType type() const { return current()->type(); } int format() const { return (relocInfo::have_format) ? current()->format() : 0; } address addr() const { return _addr; } - CodeBlob* code() const { return _code; } + nmethod* code() const { return _code; } short* data() const { return _data; } int datalen() const { return _datalen; } bool has_current() const { return _datalen >= 0; } @@ -790,9 +790,9 @@ public: // accessors which only make sense for a bound Relocation - address addr() const { return binding()->addr(); } - CodeBlob* code() const { return binding()->code(); } - bool addr_in_const() const { return binding()->addr_in_const(); } + address addr() const { return binding()->addr(); } + nmethod* code() const { return binding()->code(); } + bool addr_in_const() const { return binding()->addr_in_const(); } protected: short* data() const { return binding()->data(); } int datalen() const { return binding()->datalen(); } @@ -982,12 +982,12 @@ // Figure out where an ic_call is hiding, given a set-oop or call. // Either ic_call or first_oop must be non-null; the other is deduced. - // Code if non-NULL must be the CodeBlob, else it is deduced. + // Code if non-NULL must be the nmethod, else it is deduced. // The address of the patchable oop is also deduced. // The returned iterator will enumerate over the oops and the ic_call, // as well as any other relocations that happen to be in that span of code. // Recognize relevant set_oops with: oop_reloc()->oop_addr() == oop_addr. - static RelocIterator parse_ic(CodeBlob* &code, address &ic_call, address &first_oop, oop* &oop_addr, bool *is_optimized); + static RelocIterator parse_ic(nmethod* &nm, address &ic_call, address &first_oop, oop* &oop_addr, bool *is_optimized); }; @@ -1304,8 +1304,8 @@ APPLY_TO_RELOCATIONS(EACH_CASE); #undef EACH_CASE -inline RelocIterator::RelocIterator(CodeBlob* cb, address begin, address limit) { - initialize(cb, begin, limit); +inline RelocIterator::RelocIterator(nmethod* nm, address begin, address limit) { + initialize(nm, begin, limit); } // if you are going to patch code, you should use this subclass of @@ -1323,8 +1323,8 @@ void operator=(const RelocIterator&); public: - PatchingRelocIterator(CodeBlob* cb, address begin =NULL, address limit =NULL) - : RelocIterator(cb, begin, limit) { prepass(); } + PatchingRelocIterator(nmethod* nm, address begin = NULL, address limit = NULL) + : RelocIterator(nm, begin, limit) { prepass(); } ~PatchingRelocIterator() { postpass(); } }; diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/memory/iterator.cpp --- a/hotspot/src/share/vm/memory/iterator.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/memory/iterator.cpp Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 Sun Microsystems, Inc. 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 @@ -58,8 +58,8 @@ } void MarkingCodeBlobClosure::do_code_blob(CodeBlob* cb) { - if (!cb->is_nmethod()) return; - nmethod* nm = (nmethod*) cb; + nmethod* nm = cb->as_nmethod_or_null(); + if (nm == NULL) return; if (!nm->test_set_oops_do_mark()) { NOT_PRODUCT(if (TraceScavenge) nm->print_on(tty, "oops_do, 1st visit\n")); do_newly_marked_nmethod(nm); @@ -74,11 +74,14 @@ void CodeBlobToOopClosure::do_code_blob(CodeBlob* cb) { if (!_do_marking) { - NOT_PRODUCT(if (TraceScavenge && Verbose && cb->is_nmethod()) ((nmethod*)cb)->print_on(tty, "oops_do, unmarked visit\n")); + nmethod* nm = cb->as_nmethod_or_null(); + NOT_PRODUCT(if (TraceScavenge && Verbose && nm != NULL) nm->print_on(tty, "oops_do, unmarked visit\n")); // This assert won't work, since there are lots of mini-passes // (mostly in debug mode) that co-exist with marking phases. //assert(!(cb->is_nmethod() && ((nmethod*)cb)->test_oops_do_mark()), "found marked nmethod during mark-free phase"); - cb->oops_do(_cl); + if (nm != NULL) { + nm->oops_do(_cl); + } } else { MarkingCodeBlobClosure::do_code_blob(cb); } diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu May 20 06:34:23 2010 -0700 @@ -1435,7 +1435,7 @@ // for the rest of its life! Just another racing bug in the life of // fixup_callers_callsite ... // - RelocIterator iter(cb, call->instruction_address(), call->next_instruction_address()); + RelocIterator iter(nm, call->instruction_address(), call->next_instruction_address()); iter.next(); assert(iter.has_current(), "must have a reloc at java call site"); relocInfo::relocType typ = iter.reloc()->type(); diff -r 261ecc5bb65e -r 5435e77aa3df hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu May 20 01:34:22 2010 -0700 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu May 20 06:34:23 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. 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 @@ -607,8 +607,6 @@ nonstatic_field(CodeBlob, _instructions_offset, int) \ nonstatic_field(CodeBlob, _frame_complete_offset, int) \ nonstatic_field(CodeBlob, _data_offset, int) \ - nonstatic_field(CodeBlob, _oops_offset, int) \ - nonstatic_field(CodeBlob, _oops_length, int) \ nonstatic_field(CodeBlob, _frame_size, int) \ nonstatic_field(CodeBlob, _oop_maps, OopMapSet*) \ \ @@ -626,6 +624,8 @@ nonstatic_field(nmethod, _deoptimize_offset, int) \ nonstatic_field(nmethod, _orig_pc_offset, int) \ nonstatic_field(nmethod, _stub_offset, int) \ + nonstatic_field(nmethod, _consts_offset, int) \ + nonstatic_field(nmethod, _oops_offset, int) \ nonstatic_field(nmethod, _scopes_data_offset, int) \ nonstatic_field(nmethod, _scopes_pcs_offset, int) \ nonstatic_field(nmethod, _dependencies_offset, int) \