aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/c1
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/vm/c1')
-rw-r--r--src/share/vm/c1/c1_Canonicalizer.cpp1
-rw-r--r--src/share/vm/c1/c1_Canonicalizer.hpp1
-rw-r--r--src/share/vm/c1/c1_GraphBuilder.cpp51
-rw-r--r--src/share/vm/c1/c1_GraphBuilder.hpp1
-rw-r--r--src/share/vm/c1/c1_Instruction.hpp23
-rw-r--r--src/share/vm/c1/c1_InstructionPrinter.cpp6
-rw-r--r--src/share/vm/c1/c1_InstructionPrinter.hpp1
-rw-r--r--src/share/vm/c1/c1_LIR.cpp12
-rw-r--r--src/share/vm/c1/c1_LIR.hpp20
-rw-r--r--src/share/vm/c1/c1_LIRAssembler.cpp5
-rw-r--r--src/share/vm/c1/c1_LIRAssembler.hpp2
-rw-r--r--src/share/vm/c1/c1_LIRGenerator.hpp1
-rw-r--r--src/share/vm/c1/c1_Optimizer.cpp2
-rw-r--r--src/share/vm/c1/c1_ValueMap.hpp1
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 */ }