changeset in /hg/icedtea: Forwardport Shark.
Andrew John Hughes
ahughes at redhat.com
Wed Jun 10 13:45:38 PDT 2009
changeset 085521a03c8b in /hg/icedtea
details: http://icedtea.classpath.org/hg/icedtea?cmd=changeset;node=085521a03c8b
description:
Forwardport Shark.
2009-06-06 Gary Benson <gbenson at redhat.com>
* ports/hotspot/src/share/vm/shark/sharkBlock.hpp
(SharkBlock::maybe_do_instanceof_if): New method.
* ports/hotspot/src/share/vm/shark/sharkBlock.cpp
(SharkBlock::maybe_do_instanceof_if): New method.
(SharkBlock::parse_bytecode): Use the above for
instanceof immediately followed by ifeq or ifne.
* ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
(SharkTopLevelBlock::do_if_helper): New method.
(SharkTopLevelBlock::static_subtype_check): Likewise.
(SharkTopLevelBlock::maybe_do_instanceof_if): Likewise.
(SharkTopLevelBlock::do_optimized_instance_check): Removed.
* ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp
(SharkTopLevelBlock::do_if_helper): New method.
(SharkTopLevelBlock::do_if): Use the above.
(SharkTopLevelBlock::static_subtype_check): New method.
(SharkTopLevelBlock::do_instance_check): Use the above.
(SharkTopLevelBlock::maybe_do_instanceof_if): New method.
(SharkTopLevelBlock::do_optimized_instance_check): Removed.
(SharkTopLevelBlock::do_full_instance_check): Removed
now-unnecessary state copy and merge.
* ports/hotspot/src/share/vm/shark/sharkState.hpp
(SharkState::replace_all): New method.
* ports/hotspot/src/share/vm/shark/sharkState.cpp
(SharkState::replace_all): Likewise.
diffstat:
7 files changed, 204 insertions(+), 42 deletions(-)
ChangeLog | 29 ++
ports/hotspot/src/share/vm/shark/sharkBlock.cpp | 37 +++
ports/hotspot/src/share/vm/shark/sharkBlock.hpp | 1
ports/hotspot/src/share/vm/shark/sharkState.cpp | 15 +
ports/hotspot/src/share/vm/shark/sharkState.hpp | 4
ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp | 152 +++++++++++----
ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp | 8
diffs (383 lines):
diff -r 8783e4b809e0 -r 085521a03c8b ChangeLog
--- a/ChangeLog Fri Jun 05 14:46:31 2009 +0100
+++ b/ChangeLog Wed Jun 10 17:17:50 2009 +0100
@@ -1,3 +1,32 @@ 2009-06-06 Gary Benson <gbenson at redhat
+2009-06-06 Gary Benson <gbenson at redhat.com>
+
+ * ports/hotspot/src/share/vm/shark/sharkBlock.hpp
+ (SharkBlock::maybe_do_instanceof_if): New method.
+ * ports/hotspot/src/share/vm/shark/sharkBlock.cpp
+ (SharkBlock::maybe_do_instanceof_if): New method.
+ (SharkBlock::parse_bytecode): Use the above for
+ instanceof immediately followed by ifeq or ifne.
+
+ * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
+ (SharkTopLevelBlock::do_if_helper): New method.
+ (SharkTopLevelBlock::static_subtype_check): Likewise.
+ (SharkTopLevelBlock::maybe_do_instanceof_if): Likewise.
+ (SharkTopLevelBlock::do_optimized_instance_check): Removed.
+ * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp
+ (SharkTopLevelBlock::do_if_helper): New method.
+ (SharkTopLevelBlock::do_if): Use the above.
+ (SharkTopLevelBlock::static_subtype_check): New method.
+ (SharkTopLevelBlock::do_instance_check): Use the above.
+ (SharkTopLevelBlock::maybe_do_instanceof_if): New method.
+ (SharkTopLevelBlock::do_optimized_instance_check): Removed.
+ (SharkTopLevelBlock::do_full_instance_check): Removed
+ now-unnecessary state copy and merge.
+
+ * ports/hotspot/src/share/vm/shark/sharkState.hpp
+ (SharkState::replace_all): New method.
+ * ports/hotspot/src/share/vm/shark/sharkState.cpp
+ (SharkState::replace_all): Likewise.
+
2009-06-06 Gary Benson <gbenson at redhat.com>
* ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
diff -r 8783e4b809e0 -r 085521a03c8b ports/hotspot/src/share/vm/shark/sharkBlock.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.cpp Fri Jun 05 14:46:31 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkBlock.cpp Wed Jun 10 17:17:50 2009 +0100
@@ -825,8 +825,38 @@ void SharkBlock::parse_bytecode(int star
do_call();
break;
+ case Bytecodes::_instanceof:
+ // This is a very common construct:
+ //
+ // if (object instanceof Klass) {
+ // something = (Klass) object;
+ // ...
+ // }
+ //
+ // which gets compiled to something like this:
+ //
+ // 28: aload 9
+ // 30: instanceof <Class Klass>
+ // 33: ifeq 52
+ // 36: aload 9
+ // 38: checkcast <Class Klass>
+ //
+ // Handling both bytecodes at once allows us
+ // to eliminate the checkcast.
+ if (iter()->next_bci() < limit &&
+ (iter()->next_bc() == Bytecodes::_ifeq ||
+ iter()->next_bc() == Bytecodes::_ifne) &&
+ (!UseLoopSafepoints ||
+ iter()->next_get_dest() > iter()->next_bci())) {
+ if (maybe_do_instanceof_if()) {
+ iter()->next();
+ if (SharkTraceBytecodes)
+ tty->print_cr("%4d: %s", bci(), Bytecodes::name(bc()));
+ break;
+ }
+ }
+ // fall through
case Bytecodes::_checkcast:
- case Bytecodes::_instanceof:
do_instance_check();
break;
@@ -1225,6 +1255,11 @@ void SharkBlock::do_instance_check()
ShouldNotCallThis();
}
+bool SharkBlock::maybe_do_instanceof_if()
+{
+ ShouldNotCallThis();
+}
+
void SharkBlock::do_new()
{
ShouldNotCallThis();
diff -r 8783e4b809e0 -r 085521a03c8b ports/hotspot/src/share/vm/shark/sharkBlock.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.hpp Fri Jun 05 14:46:31 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkBlock.hpp Wed Jun 10 17:17:50 2009 +0100
@@ -326,6 +326,7 @@ class SharkBlock : public ResourceObj {
// checkcast and instanceof
protected:
virtual void do_instance_check();
+ virtual bool maybe_do_instanceof_if();
// new and *newarray
protected:
diff -r 8783e4b809e0 -r 085521a03c8b ports/hotspot/src/share/vm/shark/sharkState.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkState.cpp Fri Jun 05 14:46:31 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkState.cpp Wed Jun 10 17:17:50 2009 +0100
@@ -223,6 +223,21 @@ void SharkState::merge(SharkState* other
// Safepointed status
set_has_safepointed(this->has_safepointed() && other->has_safepointed());
+}
+
+void SharkState::replace_all(SharkValue* old_value, SharkValue* new_value)
+{
+ // Local variables
+ for (int i = 0; i < max_locals(); i++) {
+ if (local(i) == old_value)
+ set_local(i, new_value);
+ }
+
+ // Expression stack
+ for (int i = 0; i < stack_depth(); i++) {
+ if (stack(i) == old_value)
+ set_stack(i, new_value);
+ }
}
void SharkState::decache_for_Java_call(ciMethod* callee)
diff -r 8783e4b809e0 -r 085521a03c8b ports/hotspot/src/share/vm/shark/sharkState.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkState.hpp Fri Jun 05 14:46:31 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkState.hpp Wed Jun 10 17:17:50 2009 +0100
@@ -187,6 +187,10 @@ class SharkState : public ResourceObj {
llvm::BasicBlock* other_block,
llvm::BasicBlock* this_block);
+ // Value replacement
+ public:
+ void replace_all(SharkValue* old_value, SharkValue* new_value);
+
// Cache and decache
public:
void decache_for_Java_call(ciMethod* callee);
diff -r 8783e4b809e0 -r 085521a03c8b ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp
--- a/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp Fri Jun 05 14:46:31 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp Wed Jun 10 17:17:50 2009 +0100
@@ -772,8 +772,11 @@ void SharkTopLevelBlock::do_ret()
}
// All propagation of state from one block to the next (via
-// dest->add_incoming) is handled by the next three methods
-// (do_branch, do_if and do_switch) and by handle_exception.
+// dest->add_incoming) is handled by these methods:
+// do_branch
+// do_if_helper
+// do_switch
+// handle_exception
void SharkTopLevelBlock::do_branch(int successor_index)
{
@@ -795,16 +798,24 @@ void SharkTopLevelBlock::do_if(ICmpInst:
llvm_a = a->jint_value();
llvm_b = b->jint_value();
}
-
+ do_if_helper(p, llvm_b, llvm_a, current_state(), current_state());
+}
+
+void SharkTopLevelBlock::do_if_helper(ICmpInst::Predicate p,
+ Value* b,
+ Value* a,
+ SharkState* if_taken_state,
+ SharkState* not_taken_state)
+{
SharkTopLevelBlock *if_taken = successor(ciTypeFlow::IF_TAKEN);
SharkTopLevelBlock *not_taken = successor(ciTypeFlow::IF_NOT_TAKEN);
builder()->CreateCondBr(
- builder()->CreateICmp(p, llvm_a, llvm_b),
+ builder()->CreateICmp(p, a, b),
if_taken->entry_block(), not_taken->entry_block());
- if_taken->add_incoming(current_state());
- not_taken->add_incoming(current_state());
+ if_taken->add_incoming(if_taken_state);
+ not_taken->add_incoming(not_taken_state);
}
void SharkTopLevelBlock::do_switch()
@@ -1164,40 +1175,48 @@ void SharkTopLevelBlock::do_call()
current_state()->set_has_safepointed(true);
}
+bool SharkTopLevelBlock::static_subtype_check(ciKlass* check_klass,
+ ciKlass* object_klass)
+{
+ // If the class we're checking against is java.lang.Object
+ // then this is a no brainer. Apparently this can happen
+ // in reflective code...
+ if (check_klass == function()->env()->Object_klass())
+ return true;
+
+ // Perform a subtype check. NB in opto's code for this
+ // (GraphKit::static_subtype_check) it says that static
+ // interface types cannot be trusted, and if opto can't
+ // trust them then I assume we can't either.
+ if (!object_klass->is_interface()) {
+ if (object_klass == check_klass)
+ return true;
+
+ if (object_klass->is_loaded() && check_klass->is_loaded()) {
+ if (object_klass->is_subtype_of(check_klass))
+ return true;
+ }
+ }
+
+ return false;
+}
+
void SharkTopLevelBlock::do_instance_check()
{
// Get the class we're checking against
bool will_link;
ciKlass *check_klass = iter()->get_klass(will_link);
- // If the class we're checking against is java.lang.Object
- // then this is a no brainer. Apparently this can happen
- // in reflective code...
- if (check_klass == function()->env()->Object_klass()) {
- do_optimized_instance_check();
- return;
- }
-
// Get the class of the object we're checking
ciKlass *object_klass = xstack(0)->type()->as_klass();
- // If the classes are defined enough now then we
- // don't need a runtime check. NB opto's code for
- // this (GraphKit::static_subtype_check) says we
- // cannot trust static interface types yet, hence
- // the extra check
- if (!object_klass->is_interface()) {
- if (object_klass == check_klass) {
- do_optimized_instance_check();
- return;
+ // Can we optimize this check away?
+ if (static_subtype_check(check_klass, object_klass)) {
+ if (bc() == Bytecodes::_instanceof) {
+ pop();
+ push(SharkValue::jint_constant(1));
}
-
- if (object_klass->is_loaded() && check_klass->is_loaded()) {
- if (object_klass->is_subtype_of(check_klass)) {
- do_optimized_instance_check();
- return;
- }
- }
+ return;
}
// Need to check this one at runtime
@@ -1207,14 +1226,69 @@ void SharkTopLevelBlock::do_instance_che
do_trapping_instance_check(check_klass);
}
-void SharkTopLevelBlock::do_optimized_instance_check()
-{
- if (bc() == Bytecodes::_instanceof) {
- pop();
- push(SharkValue::jint_constant(1));
- }
-}
-
+bool SharkTopLevelBlock::maybe_do_instanceof_if()
+{
+ // Get the class we're checking against
+ bool will_link;
+ ciKlass *check_klass = iter()->get_klass(will_link);
+
+ // If the class is unloaded then the instanceof
+ // cannot possibly succeed.
+ if (!will_link)
+ return false;
+
+ // Keep a copy of the object we're checking
+ SharkValue *old_object = xstack(0);
+
+ // Get the class of the object we're checking
+ ciKlass *object_klass = old_object->type()->as_klass();
+
+ // If the instanceof can be optimized away at compile time
+ // then any subsequent checkcasts will be too so we handle
+ // it normally.
+ if (static_subtype_check(check_klass, object_klass))
+ return false;
+
+ // Perform the instance check
+ do_full_instance_check(check_klass);
+ Value *result = pop()->jint_value();
+
+ // Create the casted object
+ SharkValue *new_object = SharkValue::create_generic(
+ check_klass, old_object->jobject_value(), old_object->zero_checked());
+
+ // Create two copies of the current state, one with the
+ // original object and one with all instances of the
+ // original object replaced with the new, casted object.
+ SharkState *new_state = current_state();
+ SharkState *old_state = new_state->copy();
+ new_state->replace_all(old_object, new_object);
+
+ // Perform the check-and-branch
+ switch (iter()->next_bc()) {
+ case Bytecodes::_ifeq:
+ // branch if not an instance
+ do_if_helper(
+ ICmpInst::ICMP_EQ,
+ LLVMValue::jint_constant(0), result,
+ old_state, new_state);
+ break;
+
+ case Bytecodes::_ifne:
+ // branch if an instance
+ do_if_helper(
+ ICmpInst::ICMP_NE,
+ LLVMValue::jint_constant(0), result,
+ new_state, old_state);
+ break;
+
+ default:
+ ShouldNotReachHere();
+ }
+
+ return true;
+}
+
void SharkTopLevelBlock::do_full_instance_check(ciKlass* klass)
{
BasicBlock *not_null = function()->CreateBlock("not_null");
@@ -1238,7 +1312,6 @@ void SharkTopLevelBlock::do_full_instanc
builder()->CreateICmpEQ(object, LLVMValue::null()),
merge2, not_null);
BasicBlock *null_block = builder()->GetInsertBlock();
- SharkState *null_state = current_state()->copy();
// Get the class we're checking against
builder()->SetInsertPoint(not_null);
@@ -1282,7 +1355,6 @@ void SharkTopLevelBlock::do_full_instanc
// Second merge
builder()->SetInsertPoint(merge2);
- current_state()->merge(null_state, null_block, nonnull_block);
PHINode *result = builder()->CreatePHI(
SharkType::jint_type(), "result");
result->addIncoming(LLVMValue::jint_constant(IC_IS_NULL), null_block);
diff -r 8783e4b809e0 -r 085521a03c8b ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp Fri Jun 05 14:46:31 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp Wed Jun 10 17:17:50 2009 +0100
@@ -358,6 +358,11 @@ class SharkTopLevelBlock : public SharkB
// if*
private:
+ void do_if_helper(llvm::ICmpInst::Predicate p,
+ llvm::Value* b,
+ llvm::Value* a,
+ SharkState* if_taken_state,
+ SharkState* not_taken_state);
void do_if(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a);
// tableswitch and lookupswitch
@@ -386,11 +391,12 @@ class SharkTopLevelBlock : public SharkB
// checkcast and instanceof
private:
- void do_optimized_instance_check();
+ bool static_subtype_check(ciKlass* check_klass, ciKlass* object_klass);
void do_full_instance_check(ciKlass* klass);
void do_trapping_instance_check(ciKlass* klass);
void do_instance_check();
+ bool maybe_do_instanceof_if();
// new and *newarray
private:
More information about the distro-pkg-dev
mailing list