diff options
Diffstat (limited to 'src/share/vm/c1')
-rw-r--r-- | src/share/vm/c1/c1_Canonicalizer.cpp | 1 | ||||
-rw-r--r-- | src/share/vm/c1/c1_Canonicalizer.hpp | 1 | ||||
-rw-r--r-- | src/share/vm/c1/c1_GraphBuilder.cpp | 51 | ||||
-rw-r--r-- | src/share/vm/c1/c1_GraphBuilder.hpp | 1 | ||||
-rw-r--r-- | src/share/vm/c1/c1_Instruction.hpp | 23 | ||||
-rw-r--r-- | src/share/vm/c1/c1_InstructionPrinter.cpp | 6 | ||||
-rw-r--r-- | src/share/vm/c1/c1_InstructionPrinter.hpp | 1 | ||||
-rw-r--r-- | src/share/vm/c1/c1_LIR.cpp | 12 | ||||
-rw-r--r-- | src/share/vm/c1/c1_LIR.hpp | 20 | ||||
-rw-r--r-- | src/share/vm/c1/c1_LIRAssembler.cpp | 5 | ||||
-rw-r--r-- | src/share/vm/c1/c1_LIRAssembler.hpp | 2 | ||||
-rw-r--r-- | src/share/vm/c1/c1_LIRGenerator.hpp | 1 | ||||
-rw-r--r-- | src/share/vm/c1/c1_Optimizer.cpp | 2 | ||||
-rw-r--r-- | src/share/vm/c1/c1_ValueMap.hpp | 1 |
14 files changed, 122 insertions, 5 deletions
diff --git a/src/share/vm/c1/c1_Canonicalizer.cpp b/src/share/vm/c1/c1_Canonicalizer.cpp index 7d9ddf852..1fcdd64e6 100644 --- a/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/src/share/vm/c1/c1_Canonicalizer.cpp @@ -931,6 +931,7 @@ void Canonicalizer::do_UnsafeGetRaw(UnsafeGetRaw* x) { if (OptimizeUnsafes) do_U void Canonicalizer::do_UnsafePutRaw(UnsafePutRaw* x) { if (OptimizeUnsafes) do_UnsafeRawOp(x); } void Canonicalizer::do_UnsafeGetObject(UnsafeGetObject* x) {} void Canonicalizer::do_UnsafePutObject(UnsafePutObject* x) {} +void Canonicalizer::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {} void Canonicalizer::do_UnsafePrefetchRead (UnsafePrefetchRead* x) {} void Canonicalizer::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {} void Canonicalizer::do_ProfileCall(ProfileCall* x) {} diff --git a/src/share/vm/c1/c1_Canonicalizer.hpp b/src/share/vm/c1/c1_Canonicalizer.hpp index b7ab8f5ae..b7c9f7e87 100644 --- a/src/share/vm/c1/c1_Canonicalizer.hpp +++ b/src/share/vm/c1/c1_Canonicalizer.hpp @@ -100,6 +100,7 @@ class Canonicalizer: InstructionVisitor { virtual void do_UnsafePutRaw (UnsafePutRaw* x); virtual void do_UnsafeGetObject(UnsafeGetObject* x); virtual void do_UnsafePutObject(UnsafePutObject* x); + virtual void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x); virtual void do_UnsafePrefetchRead (UnsafePrefetchRead* x); virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); virtual void do_ProfileCall (ProfileCall* x); diff --git a/src/share/vm/c1/c1_GraphBuilder.cpp b/src/share/vm/c1/c1_GraphBuilder.cpp index 636fed2f2..95d99025b 100644 --- a/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/src/share/vm/c1/c1_GraphBuilder.cpp @@ -3383,6 +3383,41 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) { append_unsafe_CAS(callee); return true; + case vmIntrinsics::_getAndAddInt: + if (!VM_Version::supports_atomic_getadd4()) { + return false; + } + return append_unsafe_get_and_set_obj(callee, true); + case vmIntrinsics::_getAndAddLong: + if (!VM_Version::supports_atomic_getadd8()) { + return false; + } + return append_unsafe_get_and_set_obj(callee, true); + case vmIntrinsics::_getAndSetInt: + if (!VM_Version::supports_atomic_getset4()) { + return false; + } + return append_unsafe_get_and_set_obj(callee, false); + case vmIntrinsics::_getAndSetLong: + if (!VM_Version::supports_atomic_getset8()) { + return false; + } + return append_unsafe_get_and_set_obj(callee, false); + case vmIntrinsics::_getAndSetObject: +#ifdef _LP64 + if (!UseCompressedOops && !VM_Version::supports_atomic_getset8()) { + return false; + } + if (UseCompressedOops && !VM_Version::supports_atomic_getset4()) { + return false; + } +#else + if (!VM_Version::supports_atomic_getset4()) { + return false; + } +#endif + return append_unsafe_get_and_set_obj(callee, false); + case vmIntrinsics::_Reference_get: // Use the intrinsic version of Reference.get() so that the value in // the referent field can be registered by the G1 pre-barrier code. @@ -4106,6 +4141,22 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes } } +bool GraphBuilder::append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add) { + if (InlineUnsafeOps) { + Values* args = state()->pop_arguments(callee->arg_size()); + BasicType t = callee->return_type()->basic_type(); + null_check(args->at(0)); + Instruction* offset = args->at(2); +#ifndef _LP64 + offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); +#endif + Instruction* op = append(new UnsafeGetAndSetObject(t, args->at(1), offset, args->at(3), is_add)); + compilation()->set_has_unsafe_access(true); + kill_all(); + push(op->type(), op); + } + return InlineUnsafeOps; +} #ifndef PRODUCT void GraphBuilder::print_stats() { diff --git a/src/share/vm/c1/c1_GraphBuilder.hpp b/src/share/vm/c1/c1_GraphBuilder.hpp index 8d7e7de34..09970583c 100644 --- a/src/share/vm/c1/c1_GraphBuilder.hpp +++ b/src/share/vm/c1/c1_GraphBuilder.hpp @@ -367,6 +367,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { bool append_unsafe_put_raw(ciMethod* callee, BasicType t); bool append_unsafe_prefetch(ciMethod* callee, bool is_store, bool is_static); void append_unsafe_CAS(ciMethod* callee); + bool append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add); void print_inlining(ciMethod* callee, const char* msg, bool success = true); diff --git a/src/share/vm/c1/c1_Instruction.hpp b/src/share/vm/c1/c1_Instruction.hpp index 930a599aa..4fff026e0 100644 --- a/src/share/vm/c1/c1_Instruction.hpp +++ b/src/share/vm/c1/c1_Instruction.hpp @@ -102,6 +102,7 @@ class UnsafePutRaw; class UnsafeObjectOp; class UnsafeGetObject; class UnsafePutObject; +class UnsafeGetAndSetObject; class UnsafePrefetch; class UnsafePrefetchRead; class UnsafePrefetchWrite; @@ -202,6 +203,7 @@ class InstructionVisitor: public StackObj { virtual void do_UnsafePutRaw (UnsafePutRaw* x) = 0; virtual void do_UnsafeGetObject(UnsafeGetObject* x) = 0; virtual void do_UnsafePutObject(UnsafePutObject* x) = 0; + virtual void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) = 0; virtual void do_UnsafePrefetchRead (UnsafePrefetchRead* x) = 0; virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) = 0; virtual void do_ProfileCall (ProfileCall* x) = 0; @@ -2273,6 +2275,27 @@ LEAF(UnsafePutObject, UnsafeObjectOp) f->visit(&_value); } }; +LEAF(UnsafeGetAndSetObject, UnsafeObjectOp) + private: + Value _value; // Value to be stored + bool _is_add; + public: + UnsafeGetAndSetObject(BasicType basic_type, Value object, Value offset, Value value, bool is_add) + : UnsafeObjectOp(basic_type, object, offset, false, false) + , _value(value) + , _is_add(is_add) + { + ASSERT_VALUES + } + + // accessors + bool is_add() const { return _is_add; } + Value value() { return _value; } + + // generic + virtual void input_values_do(ValueVisitor* f) { UnsafeObjectOp::input_values_do(f); + f->visit(&_value); } +}; BASE(UnsafePrefetch, UnsafeObjectOp) public: diff --git a/src/share/vm/c1/c1_InstructionPrinter.cpp b/src/share/vm/c1/c1_InstructionPrinter.cpp index 383ffbb61..a2f6f86fd 100644 --- a/src/share/vm/c1/c1_InstructionPrinter.cpp +++ b/src/share/vm/c1/c1_InstructionPrinter.cpp @@ -831,6 +831,12 @@ void InstructionPrinter::do_UnsafePutObject(UnsafePutObject* x) { output()->put(')'); } +void InstructionPrinter::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { + print_unsafe_object_op(x, x->is_add()?"UnsafeGetAndSetObject (add)":"UnsafeGetAndSetObject"); + output()->print(", value "); + print_value(x->value()); + output()->put(')'); +} void InstructionPrinter::do_UnsafePrefetchRead(UnsafePrefetchRead* x) { print_unsafe_object_op(x, "UnsafePrefetchRead"); diff --git a/src/share/vm/c1/c1_InstructionPrinter.hpp b/src/share/vm/c1/c1_InstructionPrinter.hpp index 3d09ef02b..a89908c83 100644 --- a/src/share/vm/c1/c1_InstructionPrinter.hpp +++ b/src/share/vm/c1/c1_InstructionPrinter.hpp @@ -128,6 +128,7 @@ class InstructionPrinter: public InstructionVisitor { virtual void do_UnsafePutRaw (UnsafePutRaw* x); virtual void do_UnsafeGetObject(UnsafeGetObject* x); virtual void do_UnsafePutObject(UnsafePutObject* x); + virtual void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x); virtual void do_UnsafePrefetchRead (UnsafePrefetchRead* x); virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); virtual void do_ProfileCall (ProfileCall* x); diff --git a/src/share/vm/c1/c1_LIR.cpp b/src/share/vm/c1/c1_LIR.cpp index 9bc7ab8ed..178d18671 100644 --- a/src/share/vm/c1/c1_LIR.cpp +++ b/src/share/vm/c1/c1_LIR.cpp @@ -264,6 +264,7 @@ void LIR_Op2::verify() const { #ifdef ASSERT switch (code()) { case lir_cmove: + case lir_xchg: break; default: @@ -630,6 +631,8 @@ void LIR_OpVisitState::visit(LIR_Op* op) { case lir_shl: case lir_shr: case lir_ushr: + case lir_xadd: + case lir_xchg: { assert(op->as_Op2() != NULL, "must be"); LIR_Op2* op2 = (LIR_Op2*)op; @@ -641,6 +644,13 @@ void LIR_OpVisitState::visit(LIR_Op* op) { if (op2->_opr2->is_valid()) do_input(op2->_opr2); if (op2->_tmp1->is_valid()) do_temp(op2->_tmp1); if (op2->_result->is_valid()) do_output(op2->_result); + if (op->code() == lir_xchg || op->code() == lir_xadd) { + // on ARM and PPC, return value is loaded first so could + // destroy inputs. On other platforms that implement those + // (x86, sparc), the extra constrainsts are harmless. + if (op2->_opr1->is_valid()) do_temp(op2->_opr1); + if (op2->_opr2->is_valid()) do_temp(op2->_opr2); + } break; } @@ -1733,6 +1743,8 @@ const char * LIR_Op::name() const { case lir_shr: s = "shift_right"; break; case lir_ushr: s = "ushift_right"; break; case lir_alloc_array: s = "alloc_array"; break; + case lir_xadd: s = "xadd"; break; + case lir_xchg: s = "xchg"; break; // LIR_Op3 case lir_idiv: s = "idiv"; break; case lir_irem: s = "irem"; break; diff --git a/src/share/vm/c1/c1_LIR.hpp b/src/share/vm/c1/c1_LIR.hpp index a79a8ace4..122ebe8ce 100644 --- a/src/share/vm/c1/c1_LIR.hpp +++ b/src/share/vm/c1/c1_LIR.hpp @@ -963,6 +963,8 @@ enum LIR_Code { , lir_alloc_array , lir_throw , lir_compare_to + , lir_xadd + , lir_xchg , end_op2 , begin_op3 , lir_idiv @@ -2191,6 +2193,9 @@ class LIR_List: public CompilationResourceObj { void profile_call(ciMethod* method, int bci, ciMethod* callee, LIR_Opr mdo, LIR_Opr recv, LIR_Opr t1, ciKlass* cha_klass) { append(new LIR_OpProfileCall(lir_profile_call, method, bci, callee, mdo, recv, t1, cha_klass)); } + + void xadd(LIR_Opr src, LIR_Opr add, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xadd, src, add, res, tmp)); } + void xchg(LIR_Opr src, LIR_Opr set, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xchg, src, set, res, tmp)); } }; void print_LIR(BlockList* blocks); @@ -2287,16 +2292,21 @@ class LIR_OpVisitState: public StackObj { LIR_Address* address = opr->as_address_ptr(); if (address != NULL) { // special handling for addresses: add base and index register of the address - // both are always input operands! + // both are always input operands or temp if we want to extend + // their liveness! + if (mode == outputMode) { + mode = inputMode; + } + assert (mode == inputMode || mode == tempMode, "input or temp only for addresses"); if (address->_base->is_valid()) { assert(address->_base->is_register(), "must be"); - assert(_oprs_len[inputMode] < maxNumberOfOperands, "array overflow"); - _oprs_new[inputMode][_oprs_len[inputMode]++] = &address->_base; + assert(_oprs_len[mode] < maxNumberOfOperands, "array overflow"); + _oprs_new[mode][_oprs_len[mode]++] = &address->_base; } if (address->_index->is_valid()) { assert(address->_index->is_register(), "must be"); - assert(_oprs_len[inputMode] < maxNumberOfOperands, "array overflow"); - _oprs_new[inputMode][_oprs_len[inputMode]++] = &address->_index; + assert(_oprs_len[mode] < maxNumberOfOperands, "array overflow"); + _oprs_new[mode][_oprs_len[mode]++] = &address->_index; } } else { diff --git a/src/share/vm/c1/c1_LIRAssembler.cpp b/src/share/vm/c1/c1_LIRAssembler.cpp index e67987d78..a76f5bb2e 100644 --- a/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/src/share/vm/c1/c1_LIRAssembler.cpp @@ -773,6 +773,11 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { throw_op(op->in_opr1(), op->in_opr2(), op->info()); break; + case lir_xadd: + case lir_xchg: + atomic_op(op->code(), op->in_opr1(), op->in_opr2(), op->result_opr(), op->tmp1_opr()); + break; + default: Unimplemented(); break; diff --git a/src/share/vm/c1/c1_LIRAssembler.hpp b/src/share/vm/c1/c1_LIRAssembler.hpp index 226e4f83f..5cce9d0b7 100644 --- a/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/src/share/vm/c1/c1_LIRAssembler.hpp @@ -252,6 +252,8 @@ class LIR_Assembler: public CompilationResourceObj { void verify_oop_map(CodeEmitInfo* info); + void atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr dest, LIR_Opr tmp); + #ifdef TARGET_ARCH_x86 # include "c1_LIRAssembler_x86.hpp" #endif diff --git a/src/share/vm/c1/c1_LIRGenerator.hpp b/src/share/vm/c1/c1_LIRGenerator.hpp index ac20e7a33..aedd6a69c 100644 --- a/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/src/share/vm/c1/c1_LIRGenerator.hpp @@ -527,6 +527,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { virtual void do_UnsafePutRaw (UnsafePutRaw* x); virtual void do_UnsafeGetObject(UnsafeGetObject* x); virtual void do_UnsafePutObject(UnsafePutObject* x); + virtual void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x); virtual void do_UnsafePrefetchRead (UnsafePrefetchRead* x); virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); virtual void do_ProfileCall (ProfileCall* x); diff --git a/src/share/vm/c1/c1_Optimizer.cpp b/src/share/vm/c1/c1_Optimizer.cpp index 487a7a7ef..3ba17653d 100644 --- a/src/share/vm/c1/c1_Optimizer.cpp +++ b/src/share/vm/c1/c1_Optimizer.cpp @@ -505,6 +505,7 @@ public: void do_UnsafePutRaw (UnsafePutRaw* x); void do_UnsafeGetObject(UnsafeGetObject* x); void do_UnsafePutObject(UnsafePutObject* x); + void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x); void do_UnsafePrefetchRead (UnsafePrefetchRead* x); void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); void do_ProfileCall (ProfileCall* x); @@ -676,6 +677,7 @@ void NullCheckVisitor::do_UnsafeGetRaw (UnsafeGetRaw* x) {} void NullCheckVisitor::do_UnsafePutRaw (UnsafePutRaw* x) {} void NullCheckVisitor::do_UnsafeGetObject(UnsafeGetObject* x) {} void NullCheckVisitor::do_UnsafePutObject(UnsafePutObject* x) {} +void NullCheckVisitor::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {} void NullCheckVisitor::do_UnsafePrefetchRead (UnsafePrefetchRead* x) {} void NullCheckVisitor::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {} void NullCheckVisitor::do_ProfileCall (ProfileCall* x) { nce()->clear_last_explicit_null_check(); } diff --git a/src/share/vm/c1/c1_ValueMap.hpp b/src/share/vm/c1/c1_ValueMap.hpp index 6f89738d4..95fa73281 100644 --- a/src/share/vm/c1/c1_ValueMap.hpp +++ b/src/share/vm/c1/c1_ValueMap.hpp @@ -157,6 +157,7 @@ class ValueNumberingVisitor: public InstructionVisitor { void do_Invoke (Invoke* x) { kill_memory(); } void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); } void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); } + void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { kill_memory(); } void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); } void do_Phi (Phi* x) { /* nothing to do */ } |