# HG changeset patch # User Stefan Anzinger # Date 1444997180 -7200 # Node ID 3da4f19cf93b5ccbfd20b6c846d21e9aa34c97a2 # Parent f48b657b550d349ef177454b0ddfc5c6946c7b78 Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed) diff -r f48b657b550d -r 3da4f19cf93b src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp --- a/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp Fri Oct 16 13:44:47 2015 +0200 +++ b/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp Fri Oct 16 14:06:20 2015 +0200 @@ -66,7 +66,21 @@ void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) { address pc = _instructions->start() + pc_offset; - fatal(err_msg("unexpected inline metaspace constant at %p (+%d)", pc, pc_offset)); + if (HotSpotMetaspaceConstantImpl::compressed(constant)) { +#ifdef _LP64 + NativeMovConstReg32* move = nativeMovConstReg32_at(pc); + narrowKlass narrowOop = record_narrow_metadata_reference(constant); + move->set_data((intptr_t)narrowOop); + TRACE_jvmci_3("relocating (narrow metaspace constant) at %p/%p", pc, narrowOop); +#else + fatal("compressed Klass* on 32bit"); +#endif + } else { + NativeMovConstReg* move = nativeMovConstReg_at(pc); + Metadata* reference = record_metadata_reference(constant); + move->set_data((intptr_t)reference); + TRACE_jvmci_3("relocating (metaspace constant) at %p/%p", pc, reference); + } } void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) { diff -r f48b657b550d -r 3da4f19cf93b src/cpu/sparc/vm/nativeInst_sparc.cpp --- a/src/cpu/sparc/vm/nativeInst_sparc.cpp Fri Oct 16 13:44:47 2015 +0200 +++ b/src/cpu/sparc/vm/nativeInst_sparc.cpp Fri Oct 16 14:06:20 2015 +0200 @@ -423,6 +423,67 @@ //------------------------------------------------------------------- +void NativeMovConstReg32::verify() { + NativeInstruction::verify(); + // make sure code pattern is actually a "set_metadata" synthetic instruction + // see MacroAssembler::set_oop() + int i0 = long_at(sethi_offset); + int i1 = long_at(add_offset); + + // verify the pattern "sethi %hi22(imm), reg ; add reg, %lo10(imm), reg" + Register rd = inv_rd(i0); + if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) { + fatal("not a set_metadata"); + } +} + + +void NativeMovConstReg32::print() { + tty->print_cr(INTPTR_FORMAT ": mov reg, " INTPTR_FORMAT, instruction_address(), data()); +} + + +intptr_t NativeMovConstReg32::data() const { + return data32(long_at(sethi_offset), long_at(add_offset)); +} + + +void NativeMovConstReg32::set_data(intptr_t x) { + set_long_at(sethi_offset, set_data32_sethi( long_at(sethi_offset), x)); + 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* 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; + Metadata** metadata_addr = NULL; + while (iter.next()) { + if (iter.type() == relocInfo::oop_type) { + oop_Relocation *r = iter.oop_reloc(); + if (oop_addr == NULL) { + oop_addr = r->oop_addr(); + *oop_addr = cast_to_oop(x); + } else { + assert(oop_addr == r->oop_addr(), "must be only one set-oop here"); + } + } + if (iter.type() == relocInfo::metadata_type) { + metadata_Relocation *r = iter.metadata_reloc(); + if (metadata_addr == NULL) { + metadata_addr = r->metadata_addr(); + *metadata_addr = (Metadata*)x; + } else { + assert(metadata_addr == r->metadata_addr(), "must be only one set-metadata here"); + } + } + } + } +} + +//------------------------------------------------------------------- + void NativeMovConstRegPatching::verify() { NativeInstruction::verify(); // Make sure code pattern is sethi/nop/add. diff -r f48b657b550d -r 3da4f19cf93b src/cpu/sparc/vm/nativeInst_sparc.hpp --- a/src/cpu/sparc/vm/nativeInst_sparc.hpp Fri Oct 16 13:44:47 2015 +0200 +++ b/src/cpu/sparc/vm/nativeInst_sparc.hpp Fri Oct 16 14:06:20 2015 +0200 @@ -520,6 +520,46 @@ #endif // _LP64 +// An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions +// (used to manipulate inlined data references, etc.) +// set_metadata imm, reg +// == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg +class NativeMovConstReg32; +inline NativeMovConstReg32* nativeMovConstReg32_at(address address); +class NativeMovConstReg32: public NativeInstruction { + public: + enum Sparc_specific_constants { + sethi_offset = 0, + add_offset = 4, + instruction_size = 8 + }; + + address instruction_address() const { return addr_at(0); } + address next_instruction_address() const { return addr_at(instruction_size); } + + // (The [set_]data accessor respects oop_type relocs also.) + intptr_t data() const; + void set_data(intptr_t x); + + // report the destination register + Register destination() { return inv_rd(long_at(sethi_offset)); } + + void verify(); + void print(); + + // unit test stuff + static void test(); + + // Creation + friend inline NativeMovConstReg32* nativeMovConstReg32_at(address address) { + NativeMovConstReg32* test = (NativeMovConstReg32*)address; + #ifdef ASSERT + test->verify(); + #endif + return test; + } +}; + // An interface for accessing/manipulating native set_metadata imm, reg instructions. // (used to manipulate inlined data references, etc.) // set_metadata imm, reg