aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authornever <none@none>2010-01-15 11:53:33 -0800
committernever <none@none>2010-01-15 11:53:33 -0800
commit025714bc1f40750ed95cd0a795f057ee666d74e1 (patch)
tree4d027f0d1d843a2d3c8ffb1a175c90f0b2687d5e /src
parent76a8c2d50adc70f67a058d3c4322ec9f2ea8e52f (diff)
6849984: Value methods for platform dependent math functions constant fold incorrectly
Reviewed-by: kvn, twisti
Diffstat (limited to 'src')
-rw-r--r--src/cpu/sparc/vm/interpreter_sparc.cpp7
-rw-r--r--src/cpu/sparc/vm/stubGenerator_sparc.cpp5
-rw-r--r--src/cpu/x86/vm/stubGenerator_x86_32.cpp52
-rw-r--r--src/cpu/x86/vm/stubGenerator_x86_64.cpp77
-rw-r--r--src/cpu/x86/vm/templateInterpreter_x86_32.cpp19
-rw-r--r--src/cpu/x86/vm/templateInterpreter_x86_64.cpp19
-rw-r--r--src/share/vm/interpreter/abstractInterpreter.hpp4
-rw-r--r--src/share/vm/opto/subnode.cpp22
-rw-r--r--src/share/vm/runtime/compilationPolicy.cpp12
-rw-r--r--src/share/vm/runtime/stubRoutines.cpp10
-rw-r--r--src/share/vm/runtime/stubRoutines.hpp45
11 files changed, 248 insertions, 24 deletions
diff --git a/src/cpu/sparc/vm/interpreter_sparc.cpp b/src/cpu/sparc/vm/interpreter_sparc.cpp
index 9f0dd7166..d68d2b770 100644
--- a/src/cpu/sparc/vm/interpreter_sparc.cpp
+++ b/src/cpu/sparc/vm/interpreter_sparc.cpp
@@ -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
@@ -394,6 +394,11 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
}
+bool AbstractInterpreter::can_be_compiled(methodHandle m) {
+ // No special entry points that preclude compilation
+ return true;
+}
+
// This method tells the deoptimizer how big an interpreted frame must be:
int AbstractInterpreter::size_activation(methodOop method,
int tempcount,
diff --git a/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
index a2dc15014..66c5a218d 100644
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp
+++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
@@ -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
@@ -2862,6 +2862,9 @@ class StubGenerator: public StubCodeGenerator {
// arraycopy stubs used by compilers
generate_arraycopy_stubs();
+
+ // Don't initialize the platform math functions since sparc
+ // doesn't have intrinsics for these operations.
}
diff --git a/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/src/cpu/x86/vm/stubGenerator_x86_32.cpp
index 3d6ca91a0..ad4b745ab 100644
--- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp
+++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-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
@@ -2030,6 +2030,54 @@ class StubGenerator: public StubCodeGenerator {
entry_checkcast_arraycopy);
}
+ void generate_math_stubs() {
+ {
+ StubCodeMark mark(this, "StubRoutines", "log");
+ StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
+
+ __ fld_d(Address(rsp, 4));
+ __ flog();
+ __ ret(0);
+ }
+ {
+ StubCodeMark mark(this, "StubRoutines", "log10");
+ StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
+
+ __ fld_d(Address(rsp, 4));
+ __ flog10();
+ __ ret(0);
+ }
+ {
+ StubCodeMark mark(this, "StubRoutines", "sin");
+ StubRoutines::_intrinsic_sin = (double (*)(double)) __ pc();
+
+ __ fld_d(Address(rsp, 4));
+ __ trigfunc('s');
+ __ ret(0);
+ }
+ {
+ StubCodeMark mark(this, "StubRoutines", "cos");
+ StubRoutines::_intrinsic_cos = (double (*)(double)) __ pc();
+
+ __ fld_d(Address(rsp, 4));
+ __ trigfunc('c');
+ __ ret(0);
+ }
+ {
+ StubCodeMark mark(this, "StubRoutines", "tan");
+ StubRoutines::_intrinsic_tan = (double (*)(double)) __ pc();
+
+ __ fld_d(Address(rsp, 4));
+ __ trigfunc('t');
+ __ ret(0);
+ }
+
+ // The intrinsic version of these seem to return the same value as
+ // the strict version.
+ StubRoutines::_intrinsic_exp = SharedRuntime::dexp;
+ StubRoutines::_intrinsic_pow = SharedRuntime::dpow;
+ }
+
public:
// Information about frame layout at time of blocking runtime call.
// Note that we only have to preserve callee-saved registers since
@@ -2228,6 +2276,8 @@ class StubGenerator: public StubCodeGenerator {
MethodHandles::generate_method_handle_stub(_masm, ek);
}
}
+
+ generate_math_stubs();
}
diff --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index cc80a4df2..706208366 100644
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -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
@@ -2731,6 +2731,79 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy;
}
+ void generate_math_stubs() {
+ {
+ StubCodeMark mark(this, "StubRoutines", "log");
+ StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
+
+ __ subq(rsp, 8);
+ __ movdbl(Address(rsp, 0), xmm0);
+ __ fld_d(Address(rsp, 0));
+ __ flog();
+ __ fstp_d(Address(rsp, 0));
+ __ movdbl(xmm0, Address(rsp, 0));
+ __ addq(rsp, 8);
+ __ ret(0);
+ }
+ {
+ StubCodeMark mark(this, "StubRoutines", "log10");
+ StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
+
+ __ subq(rsp, 8);
+ __ movdbl(Address(rsp, 0), xmm0);
+ __ fld_d(Address(rsp, 0));
+ __ flog10();
+ __ fstp_d(Address(rsp, 0));
+ __ movdbl(xmm0, Address(rsp, 0));
+ __ addq(rsp, 8);
+ __ ret(0);
+ }
+ {
+ StubCodeMark mark(this, "StubRoutines", "sin");
+ StubRoutines::_intrinsic_sin = (double (*)(double)) __ pc();
+
+ __ subq(rsp, 8);
+ __ movdbl(Address(rsp, 0), xmm0);
+ __ fld_d(Address(rsp, 0));
+ __ trigfunc('s');
+ __ fstp_d(Address(rsp, 0));
+ __ movdbl(xmm0, Address(rsp, 0));
+ __ addq(rsp, 8);
+ __ ret(0);
+ }
+ {
+ StubCodeMark mark(this, "StubRoutines", "cos");
+ StubRoutines::_intrinsic_cos = (double (*)(double)) __ pc();
+
+ __ subq(rsp, 8);
+ __ movdbl(Address(rsp, 0), xmm0);
+ __ fld_d(Address(rsp, 0));
+ __ trigfunc('c');
+ __ fstp_d(Address(rsp, 0));
+ __ movdbl(xmm0, Address(rsp, 0));
+ __ addq(rsp, 8);
+ __ ret(0);
+ }
+ {
+ StubCodeMark mark(this, "StubRoutines", "tan");
+ StubRoutines::_intrinsic_tan = (double (*)(double)) __ pc();
+
+ __ subq(rsp, 8);
+ __ movdbl(Address(rsp, 0), xmm0);
+ __ fld_d(Address(rsp, 0));
+ __ trigfunc('t');
+ __ fstp_d(Address(rsp, 0));
+ __ movdbl(xmm0, Address(rsp, 0));
+ __ addq(rsp, 8);
+ __ ret(0);
+ }
+
+ // The intrinsic version of these seem to return the same value as
+ // the strict version.
+ StubRoutines::_intrinsic_exp = SharedRuntime::dexp;
+ StubRoutines::_intrinsic_pow = SharedRuntime::dpow;
+ }
+
#undef __
#define __ masm->
@@ -2945,6 +3018,8 @@ class StubGenerator: public StubCodeGenerator {
MethodHandles::generate_method_handle_stub(_masm, ek);
}
}
+
+ generate_math_stubs();
}
public:
diff --git a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
index e0d2d1fe6..eecfb3fd1 100644
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
+++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
@@ -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
@@ -1431,6 +1431,23 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
}
+// These should never be compiled since the interpreter will prefer
+// the compiled version to the intrinsic version.
+bool AbstractInterpreter::can_be_compiled(methodHandle m) {
+ switch (method_kind(m)) {
+ case Interpreter::java_lang_math_sin : // fall thru
+ case Interpreter::java_lang_math_cos : // fall thru
+ case Interpreter::java_lang_math_tan : // fall thru
+ case Interpreter::java_lang_math_abs : // fall thru
+ case Interpreter::java_lang_math_log : // fall thru
+ case Interpreter::java_lang_math_log10 : // fall thru
+ case Interpreter::java_lang_math_sqrt :
+ return false;
+ default:
+ return true;
+ }
+}
+
// How much stack a method activation needs in words.
int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
diff --git a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
index f8c260330..442254416 100644
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
@@ -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
@@ -1456,6 +1456,23 @@ address AbstractInterpreterGenerator::generate_method_entry(
generate_normal_entry(synchronized);
}
+// These should never be compiled since the interpreter will prefer
+// the compiled version to the intrinsic version.
+bool AbstractInterpreter::can_be_compiled(methodHandle m) {
+ switch (method_kind(m)) {
+ case Interpreter::java_lang_math_sin : // fall thru
+ case Interpreter::java_lang_math_cos : // fall thru
+ case Interpreter::java_lang_math_tan : // fall thru
+ case Interpreter::java_lang_math_abs : // fall thru
+ case Interpreter::java_lang_math_log : // fall thru
+ case Interpreter::java_lang_math_log10 : // fall thru
+ case Interpreter::java_lang_math_sqrt :
+ return false;
+ default:
+ return true;
+ }
+}
+
// How much stack a method activation needs in words.
int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
const int entry_size = frame::interpreter_frame_monitor_size();
diff --git a/src/share/vm/interpreter/abstractInterpreter.hpp b/src/share/vm/interpreter/abstractInterpreter.hpp
index 78323ee2a..8ab9e40d3 100644
--- a/src/share/vm/interpreter/abstractInterpreter.hpp
+++ b/src/share/vm/interpreter/abstractInterpreter.hpp
@@ -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
@@ -109,6 +109,8 @@ class AbstractInterpreter: AllStatic {
static void print_method_kind(MethodKind kind) PRODUCT_RETURN;
+ static bool can_be_compiled(methodHandle m);
+
// Runtime support
// length = invoke bytecode length (to advance to next bytecode)
diff --git a/src/share/vm/opto/subnode.cpp b/src/share/vm/opto/subnode.cpp
index 81e033f27..1a8c2f60e 100644
--- a/src/share/vm/opto/subnode.cpp
+++ b/src/share/vm/opto/subnode.cpp
@@ -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
@@ -1244,8 +1244,7 @@ const Type *CosDNode::Value( PhaseTransform *phase ) const {
if( t1 == Type::TOP ) return Type::TOP;
if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
double d = t1->getd();
- if( d < 0.0 ) return Type::DOUBLE;
- return TypeD::make( SharedRuntime::dcos( d ) );
+ return TypeD::make( StubRoutines::intrinsic_cos( d ) );
}
//=============================================================================
@@ -1256,8 +1255,7 @@ const Type *SinDNode::Value( PhaseTransform *phase ) const {
if( t1 == Type::TOP ) return Type::TOP;
if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
double d = t1->getd();
- if( d < 0.0 ) return Type::DOUBLE;
- return TypeD::make( SharedRuntime::dsin( d ) );
+ return TypeD::make( StubRoutines::intrinsic_sin( d ) );
}
//=============================================================================
@@ -1268,8 +1266,7 @@ const Type *TanDNode::Value( PhaseTransform *phase ) const {
if( t1 == Type::TOP ) return Type::TOP;
if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
double d = t1->getd();
- if( d < 0.0 ) return Type::DOUBLE;
- return TypeD::make( SharedRuntime::dtan( d ) );
+ return TypeD::make( StubRoutines::intrinsic_tan( d ) );
}
//=============================================================================
@@ -1280,8 +1277,7 @@ const Type *LogDNode::Value( PhaseTransform *phase ) const {
if( t1 == Type::TOP ) return Type::TOP;
if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
double d = t1->getd();
- if( d < 0.0 ) return Type::DOUBLE;
- return TypeD::make( SharedRuntime::dlog( d ) );
+ return TypeD::make( StubRoutines::intrinsic_log( d ) );
}
//=============================================================================
@@ -1292,8 +1288,7 @@ const Type *Log10DNode::Value( PhaseTransform *phase ) const {
if( t1 == Type::TOP ) return Type::TOP;
if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
double d = t1->getd();
- if( d < 0.0 ) return Type::DOUBLE;
- return TypeD::make( SharedRuntime::dlog10( d ) );
+ return TypeD::make( StubRoutines::intrinsic_log10( d ) );
}
//=============================================================================
@@ -1304,8 +1299,7 @@ const Type *ExpDNode::Value( PhaseTransform *phase ) const {
if( t1 == Type::TOP ) return Type::TOP;
if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
double d = t1->getd();
- if( d < 0.0 ) return Type::DOUBLE;
- return TypeD::make( SharedRuntime::dexp( d ) );
+ return TypeD::make( StubRoutines::intrinsic_exp( d ) );
}
@@ -1323,5 +1317,5 @@ const Type *PowDNode::Value( PhaseTransform *phase ) const {
double d2 = t2->getd();
if( d1 < 0.0 ) return Type::DOUBLE;
if( d2 < 0.0 ) return Type::DOUBLE;
- return TypeD::make( SharedRuntime::dpow( d1, d2 ) );
+ return TypeD::make( StubRoutines::intrinsic_pow( d1, d2 ) );
}
diff --git a/src/share/vm/runtime/compilationPolicy.cpp b/src/share/vm/runtime/compilationPolicy.cpp
index ac870e0cc..2892ef123 100644
--- a/src/share/vm/runtime/compilationPolicy.cpp
+++ b/src/share/vm/runtime/compilationPolicy.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2007 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
@@ -74,6 +74,16 @@ bool CompilationPolicy::canBeCompiled(methodHandle m) {
if (m->is_abstract()) return false;
if (DontCompileHugeMethods && m->code_size() > HugeMethodLimit) return false;
+ // Math intrinsics should never be compiled as this can lead to
+ // monotonicity problems because the interpreter will prefer the
+ // compiled code to the intrinsic version. This can't happen in
+ // production because the invocation counter can't be incremented
+ // but we shouldn't expose the system to this problem in testing
+ // modes.
+ if (!AbstractInterpreter::can_be_compiled(m)) {
+ return false;
+ }
+
return !m->is_not_compilable();
}
diff --git a/src/share/vm/runtime/stubRoutines.cpp b/src/share/vm/runtime/stubRoutines.cpp
index bdad678b0..25c02cd5f 100644
--- a/src/share/vm/runtime/stubRoutines.cpp
+++ b/src/share/vm/runtime/stubRoutines.cpp
@@ -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
@@ -97,6 +97,14 @@ address StubRoutines::_checkcast_arraycopy = NULL;
address StubRoutines::_unsafe_arraycopy = NULL;
address StubRoutines::_generic_arraycopy = NULL;
+double (* StubRoutines::_intrinsic_log )(double) = NULL;
+double (* StubRoutines::_intrinsic_log10 )(double) = NULL;
+double (* StubRoutines::_intrinsic_exp )(double) = NULL;
+double (* StubRoutines::_intrinsic_pow )(double, double) = NULL;
+double (* StubRoutines::_intrinsic_sin )(double) = NULL;
+double (* StubRoutines::_intrinsic_cos )(double) = NULL;
+double (* StubRoutines::_intrinsic_tan )(double) = NULL;
+
// Initialization
//
// Note: to break cycle with universe initialization, stubs are generated in two phases.
diff --git a/src/share/vm/runtime/stubRoutines.hpp b/src/share/vm/runtime/stubRoutines.hpp
index 677419164..2684f0475 100644
--- a/src/share/vm/runtime/stubRoutines.hpp
+++ b/src/share/vm/runtime/stubRoutines.hpp
@@ -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
@@ -148,6 +148,20 @@ class StubRoutines: AllStatic {
static address _unsafe_arraycopy;
static address _generic_arraycopy;
+ // These are versions of the java.lang.Math methods which perform
+ // the same operations as the intrinsic version. They are used for
+ // constant folding in the compiler to ensure equivalence. If the
+ // intrinsic version returns the same result as the strict version
+ // then they can be set to the appropriate function from
+ // SharedRuntime.
+ static double (*_intrinsic_log)(double);
+ static double (*_intrinsic_log10)(double);
+ static double (*_intrinsic_exp)(double);
+ static double (*_intrinsic_pow)(double, double);
+ static double (*_intrinsic_sin)(double);
+ static double (*_intrinsic_cos)(double);
+ static double (*_intrinsic_tan)(double);
+
public:
// Initialization/Testing
static void initialize1(); // must happen before universe::genesis
@@ -245,6 +259,35 @@ class StubRoutines: AllStatic {
static address unsafe_arraycopy() { return _unsafe_arraycopy; }
static address generic_arraycopy() { return _generic_arraycopy; }
+ static double intrinsic_log(double d) {
+ assert(_intrinsic_log != NULL, "must be defined");
+ return _intrinsic_log(d);
+ }
+ static double intrinsic_log10(double d) {
+ assert(_intrinsic_log != NULL, "must be defined");
+ return _intrinsic_log10(d);
+ }
+ static double intrinsic_exp(double d) {
+ assert(_intrinsic_exp != NULL, "must be defined");
+ return _intrinsic_exp(d);
+ }
+ static double intrinsic_pow(double d, double d2) {
+ assert(_intrinsic_pow != NULL, "must be defined");
+ return _intrinsic_pow(d, d2);
+ }
+ static double intrinsic_sin(double d) {
+ assert(_intrinsic_sin != NULL, "must be defined");
+ return _intrinsic_sin(d);
+ }
+ static double intrinsic_cos(double d) {
+ assert(_intrinsic_cos != NULL, "must be defined");
+ return _intrinsic_cos(d);
+ }
+ static double intrinsic_tan(double d) {
+ assert(_intrinsic_tan != NULL, "must be defined");
+ return _intrinsic_tan(d);
+ }
+
//
// Default versions of the above arraycopy functions for platforms which do
// not have specialized versions