diff --git a/src/cpu/sparc/vm/interpreter_sparc.cpp b/src/cpu/sparc/vm/interpreter_sparc.cpp index 9f0dd7166fdd930796a6ac582650bc04211a05c7..d68d2b7702c7f329aab9f316cc8e92ddbd095697 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 a2dc1501462f71dda981fd63ee1fd2f2edfc8323..66c5a218dcc2c3f33ac2bb34bc44ad8b141825fa 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 3d6ca91a0ea4a5aa8b4d3c23af6109131c198f41..ad4b745ab42f3f8ed69837cae3e321ca96c6152b 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 cc80a4df2a419dd69552aa6639d2d3eda25aa61a..7062083665346b5c0a700b95ec3d363c58cc9a83 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 e0d2d1fe6c7ee6e1eda3a1546f5adac5575fdea7..eecfb3fd114e638f6f7ba8ca66225ab33faec3c0 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 f8c2603305d8e2bcb7fb19627932f3fc76f6792c..4422544163580ff5da3c3d4cf4409766abb74d6b 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 78323ee2aee25d2e126eb675892d592432e65cac..8ab9e40d32bd31b31edcdf923c0d1453875e9017 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 81e033f276923c5a78c8bed283f590125d9096fa..1a8c2f60e66ebd7cd75b106a9652c1ded22823de 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 ac870e0cc756939b2fd888763573c23d8f451347..2892ef123edb3fac456ba4bfda21231b07dfbf8d 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 bdad678b0cbfce50bcfa68e51c467b0cfdff78cd..25c02cd5ff810af46f327a91206751fe797d1b49 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 677419164887974ebd874c7f75fc808b924ea712..2684f0475b4092a00bc0032c1477933f413e2c0c 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