aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzgu <none@none>2012-07-19 06:24:46 -0700
committerzgu <none@none>2012-07-19 06:24:46 -0700
commit791311dbeed828ad7fff63d428c5eb72dac0a7b6 (patch)
tree12e2e98ddac7c20ce4d4c919d39fb309213b8cd5 /src
parentf239f2e29fc0c096e19fcd735886b7903a6b7910 (diff)
parent2b263800a616ffb35e9616db7c5a2a1efe76c316 (diff)
Merge
Diffstat (limited to 'src')
-rw-r--r--src/share/vm/classfile/classFileParser.cpp7
-rw-r--r--src/share/vm/compiler/compilerOracle.cpp13
-rw-r--r--src/share/vm/oops/instanceKlass.cpp23
-rw-r--r--src/share/vm/oops/instanceKlass.hpp8
-rw-r--r--src/share/vm/oops/instanceKlassKlass.cpp5
-rw-r--r--src/share/vm/opto/library_call.cpp225
-rw-r--r--src/share/vm/opto/parse2.cpp4
-rw-r--r--src/share/vm/opto/subnode.cpp14
-rw-r--r--src/share/vm/opto/subnode.hpp1
-rw-r--r--src/share/vm/prims/jvmtiClassFileReconstituter.cpp10
-rw-r--r--src/share/vm/prims/jvmtiEnv.cpp13
-rw-r--r--src/share/vm/prims/jvmtiRedefineClasses.cpp6
-rw-r--r--src/share/vm/prims/whitebox.cpp3
-rw-r--r--src/share/vm/runtime/arguments.cpp24
-rw-r--r--src/share/vm/runtime/vmStructs.cpp2
-rw-r--r--src/share/vm/services/diagnosticCommand.hpp12
-rw-r--r--src/share/vm/services/diagnosticFramework.cpp35
-rw-r--r--src/share/vm/services/diagnosticFramework.hpp12
18 files changed, 274 insertions, 143 deletions
diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp
index 1be1c7bf1..b2cec5375 100644
--- a/src/share/vm/classfile/classFileParser.cpp
+++ b/src/share/vm/classfile/classFileParser.cpp
@@ -2337,12 +2337,7 @@ void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantP
// Don't bother storing it if there is no way to retrieve it
if (JvmtiExport::can_get_source_debug_extension()) {
- // Optimistically assume that only 1 byte UTF format is used
- // (common case)
- TempNewSymbol sde_symbol = SymbolTable::new_symbol((const char*)sde_buffer, length, CHECK);
- k->set_source_debug_extension(sde_symbol);
- // Note that set_source_debug_extension() increments the reference count
- // for its copy of the Symbol*, so use a TempNewSymbol here.
+ k->set_source_debug_extension((char*)sde_buffer, length);
}
// Got utf8 string, set stream position forward
cfs->skip_u1(length, CHECK);
diff --git a/src/share/vm/compiler/compilerOracle.cpp b/src/share/vm/compiler/compilerOracle.cpp
index b9b6f0f26..54ebe6ee7 100644
--- a/src/share/vm/compiler/compilerOracle.cpp
+++ b/src/share/vm/compiler/compilerOracle.cpp
@@ -550,10 +550,12 @@ void CompilerOracle::parse_from_line(char* line) {
}
}
+static const char* default_cc_file = ".hotspot_compiler";
+
static const char* cc_file() {
#ifdef ASSERT
if (CompileCommandFile == NULL)
- return ".hotspot_compiler";
+ return default_cc_file;
#endif
return CompileCommandFile;
}
@@ -636,10 +638,17 @@ void compilerOracle_init() {
CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only);
if (CompilerOracle::has_command_file()) {
CompilerOracle::parse_from_file();
+ } else {
+ struct stat buf;
+ if (os::stat(default_cc_file, &buf) == 0) {
+ warning("%s file is present but has been ignored. "
+ "Run with -XX:CompileCommandFile=%s to load the file.",
+ default_cc_file, default_cc_file);
+ }
}
if (lists[PrintCommand] != NULL) {
if (PrintAssembly) {
- warning("CompileCommand and/or .hotspot_compiler file contains 'print' commands, but PrintAssembly is also enabled");
+ warning("CompileCommand and/or %s file contains 'print' commands, but PrintAssembly is also enabled", default_cc_file);
} else if (FLAG_IS_DEFAULT(DebugNonSafepoints)) {
warning("printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output");
DebugNonSafepoints = true;
diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp
index b742889b6..0c0fd34b6 100644
--- a/src/share/vm/oops/instanceKlass.cpp
+++ b/src/share/vm/oops/instanceKlass.cpp
@@ -847,7 +847,6 @@ void instanceKlass::shared_symbols_iterate(SymbolClosure* closure) {
Klass::shared_symbols_iterate(closure);
closure->do_symbol(&_generic_signature);
closure->do_symbol(&_source_file_name);
- closure->do_symbol(&_source_debug_extension);
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
int name_index = fs.name_index();
@@ -1944,9 +1943,10 @@ void instanceKlass::release_C_heap_structures() {
// class can't be referenced anymore).
if (_array_name != NULL) _array_name->decrement_refcount();
if (_source_file_name != NULL) _source_file_name->decrement_refcount();
- if (_source_debug_extension != NULL) _source_debug_extension->decrement_refcount();
// walk constant pool and decrement symbol reference counts
_constants->unreference_symbols();
+
+ if (_source_debug_extension != NULL) FREE_C_HEAP_ARRAY(char, _source_debug_extension, mtClass);
}
void instanceKlass::set_source_file_name(Symbol* n) {
@@ -1954,9 +1954,22 @@ void instanceKlass::set_source_file_name(Symbol* n) {
if (_source_file_name != NULL) _source_file_name->increment_refcount();
}
-void instanceKlass::set_source_debug_extension(Symbol* n) {
- _source_debug_extension = n;
- if (_source_debug_extension != NULL) _source_debug_extension->increment_refcount();
+void instanceKlass::set_source_debug_extension(char* array, int length) {
+ if (array == NULL) {
+ _source_debug_extension = NULL;
+ } else {
+ // Adding one to the attribute length in order to store a null terminator
+ // character could cause an overflow because the attribute length is
+ // already coded with an u4 in the classfile, but in practice, it's
+ // unlikely to happen.
+ assert((length+1) > length, "Overflow checking");
+ char* sde = NEW_C_HEAP_ARRAY(char, (length + 1), mtClass);
+ for (int i = 0; i < length; i++) {
+ sde[i] = array[i];
+ }
+ sde[length] = '\0';
+ _source_debug_extension = sde;
+ }
}
address instanceKlass::static_field_addr(int offset) {
diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp
index 93e804c28..3c24b3f69 100644
--- a/src/share/vm/oops/instanceKlass.hpp
+++ b/src/share/vm/oops/instanceKlass.hpp
@@ -226,7 +226,9 @@ class instanceKlass: public Klass {
// Name of source file containing this klass, NULL if not specified.
Symbol* _source_file_name;
// the source debug extension for this klass, NULL if not specified.
- Symbol* _source_debug_extension;
+ // Specified as UTF-8 string without terminating zero byte in the classfile,
+ // it is stored in the instanceklass as a NULL-terminated UTF-8 string
+ char* _source_debug_extension;
// Generic signature, or null if none.
Symbol* _generic_signature;
// Array name derived from this class which needs unreferencing
@@ -542,8 +544,8 @@ class instanceKlass: public Klass {
void set_major_version(u2 major_version) { _major_version = major_version; }
// source debug extension
- Symbol* source_debug_extension() const { return _source_debug_extension; }
- void set_source_debug_extension(Symbol* n);
+ char* source_debug_extension() const { return _source_debug_extension; }
+ void set_source_debug_extension(char* array, int length);
// symbol unloading support (refcount already added)
Symbol* array_name() { return _array_name; }
diff --git a/src/share/vm/oops/instanceKlassKlass.cpp b/src/share/vm/oops/instanceKlassKlass.cpp
index 12ea22344..d6ccd423f 100644
--- a/src/share/vm/oops/instanceKlassKlass.cpp
+++ b/src/share/vm/oops/instanceKlassKlass.cpp
@@ -421,8 +421,7 @@ instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int it
ik->set_protection_domain(NULL);
ik->set_signers(NULL);
ik->set_source_file_name(NULL);
- ik->set_source_debug_extension(NULL);
- ik->set_source_debug_extension(NULL);
+ ik->set_source_debug_extension(NULL, 0);
ik->set_array_name(NULL);
ik->set_inner_classes(NULL);
ik->set_static_oop_field_count(0);
@@ -531,7 +530,7 @@ void instanceKlassKlass::oop_print_on(oop obj, outputStream* st) {
}
if (ik->source_debug_extension() != NULL) {
st->print(BULLET"source debug extension: ");
- ik->source_debug_extension()->print_value_on(st);
+ st->print_cr("%s", ik->source_debug_extension());
st->cr();
}
diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp
index 785f5a0ae..981a241a4 100644
--- a/src/share/vm/opto/library_call.cpp
+++ b/src/share/vm/opto/library_call.cpp
@@ -160,6 +160,7 @@ class LibraryCallKit : public GraphKit {
bool inline_trans(vmIntrinsics::ID id);
bool inline_abs(vmIntrinsics::ID id);
bool inline_sqrt(vmIntrinsics::ID id);
+ void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName);
bool inline_pow(vmIntrinsics::ID id);
bool inline_exp(vmIntrinsics::ID id);
bool inline_min_max(vmIntrinsics::ID id);
@@ -1535,40 +1536,79 @@ bool LibraryCallKit::inline_abs(vmIntrinsics::ID id) {
return true;
}
+void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName) {
+ //-------------------
+ //result=(result.isNaN())? funcAddr():result;
+ // Check: If isNaN() by checking result!=result? then either trap
+ // or go to runtime
+ Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result));
+ // Build the boolean node
+ Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) );
+
+ if (!too_many_traps(Deoptimization::Reason_intrinsic)) {
+ {
+ BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT);
+ // End the current control-flow path
+ push_pair(x);
+ if (y != NULL) {
+ push_pair(y);
+ }
+ // The pow or exp intrinsic returned a NaN, which requires a call
+ // to the runtime. Recompile with the runtime call.
+ uncommon_trap(Deoptimization::Reason_intrinsic,
+ Deoptimization::Action_make_not_entrant);
+ }
+ push_pair(result);
+ } else {
+ // If this inlining ever returned NaN in the past, we compile a call
+ // to the runtime to properly handle corner cases
+
+ IfNode* iff = create_and_xform_if(control(), bolisnum, PROB_STATIC_FREQUENT, COUNT_UNKNOWN);
+ Node* if_slow = _gvn.transform( new (C, 1) IfFalseNode(iff) );
+ Node* if_fast = _gvn.transform( new (C, 1) IfTrueNode(iff) );
+
+ if (!if_slow->is_top()) {
+ RegionNode* result_region = new(C, 3) RegionNode(3);
+ PhiNode* result_val = new (C, 3) PhiNode(result_region, Type::DOUBLE);
+
+ result_region->init_req(1, if_fast);
+ result_val->init_req(1, result);
+
+ set_control(if_slow);
+
+ const TypePtr* no_memory_effects = NULL;
+ Node* rt = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName,
+ no_memory_effects,
+ x, top(), y, y ? top() : NULL);
+ Node* value = _gvn.transform(new (C, 1) ProjNode(rt, TypeFunc::Parms+0));
+#ifdef ASSERT
+ Node* value_top = _gvn.transform(new (C, 1) ProjNode(rt, TypeFunc::Parms+1));
+ assert(value_top == top(), "second value must be top");
+#endif
+
+ result_region->init_req(2, control());
+ result_val->init_req(2, value);
+ push_result(result_region, result_val);
+ } else {
+ push_pair(result);
+ }
+ }
+}
+
//------------------------------inline_exp-------------------------------------
// Inline exp instructions, if possible. The Intel hardware only misses
// really odd corner cases (+/- Infinity). Just uncommon-trap them.
bool LibraryCallKit::inline_exp(vmIntrinsics::ID id) {
assert(id == vmIntrinsics::_dexp, "Not exp");
- // If this inlining ever returned NaN in the past, we do not intrinsify it
- // every again. NaN results requires StrictMath.exp handling.
- if (too_many_traps(Deoptimization::Reason_intrinsic)) return false;
-
_sp += arg_size(); // restore stack pointer
Node *x = pop_math_arg();
Node *result = _gvn.transform(new (C, 2) ExpDNode(0,x));
- //-------------------
- //result=(result.isNaN())? StrictMath::exp():result;
- // Check: If isNaN() by checking result!=result? then go to Strict Math
- Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result));
- // Build the boolean node
- Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) );
-
- { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT);
- // End the current control-flow path
- push_pair(x);
- // Math.exp intrinsic returned a NaN, which requires StrictMath.exp
- // to handle. Recompile without intrinsifying Math.exp
- uncommon_trap(Deoptimization::Reason_intrinsic,
- Deoptimization::Action_make_not_entrant);
- }
+ finish_pow_exp(result, x, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP");
C->set_has_split_ifs(true); // Has chance for split-if optimization
- push_pair(result);
-
return true;
}
@@ -1577,17 +1617,12 @@ bool LibraryCallKit::inline_exp(vmIntrinsics::ID id) {
bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) {
assert(id == vmIntrinsics::_dpow, "Not pow");
- // If this inlining ever returned NaN in the past, we do not intrinsify it
- // every again. NaN results requires StrictMath.pow handling.
- if (too_many_traps(Deoptimization::Reason_intrinsic)) return false;
-
- // Do not intrinsify on older platforms which lack cmove.
- if (ConditionalMoveLimit == 0) return false;
-
// Pseudocode for pow
// if (x <= 0.0) {
- // if ((double)((int)y)==y) { // if y is int
- // result = ((1&(int)y)==0)?-DPow(abs(x), y):DPow(abs(x), y)
+ // long longy = (long)y;
+ // if ((double)longy == y) { // if y is long
+ // if (y + 1 == y) longy = 0; // huge number: even
+ // result = ((1&longy) == 0)?-DPow(abs(x), y):DPow(abs(x), y);
// } else {
// result = NaN;
// }
@@ -1595,7 +1630,7 @@ bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) {
// result = DPow(x,y);
// }
// if (result != result)? {
- // uncommon_trap();
+ // result = uncommon_trap() or runtime_call();
// }
// return result;
@@ -1603,15 +1638,14 @@ bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) {
Node* y = pop_math_arg();
Node* x = pop_math_arg();
- Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, x, y) );
+ Node* result = NULL;
- // Short form: if not top-level (i.e., Math.pow but inlining Math.pow
- // inside of something) then skip the fancy tests and just check for
- // NaN result.
- Node *result = NULL;
- if( jvms()->depth() >= 1 ) {
- result = fast_result;
+ if (!too_many_traps(Deoptimization::Reason_intrinsic)) {
+ // Short form: skip the fancy tests and just check for NaN result.
+ result = _gvn.transform( new (C, 3) PowDNode(0, x, y) );
} else {
+ // If this inlining ever returned NaN in the past, include all
+ // checks + call to the runtime.
// Set the merge point for If node with condition of (x <= 0.0)
// There are four possible paths to region node and phi node
@@ -1627,55 +1661,95 @@ bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) {
Node *bol1 = _gvn.transform( new (C, 2) BoolNode( cmp, BoolTest::le ) );
// Branch either way
IfNode *if1 = create_and_xform_if(control(),bol1, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN);
- Node *opt_test = _gvn.transform(if1);
- //assert( opt_test->is_If(), "Expect an IfNode");
- IfNode *opt_if1 = (IfNode*)opt_test;
// Fast path taken; set region slot 3
- Node *fast_taken = _gvn.transform( new (C, 1) IfFalseNode(opt_if1) );
+ Node *fast_taken = _gvn.transform( new (C, 1) IfFalseNode(if1) );
r->init_req(3,fast_taken); // Capture fast-control
// Fast path not-taken, i.e. slow path
- Node *complex_path = _gvn.transform( new (C, 1) IfTrueNode(opt_if1) );
+ Node *complex_path = _gvn.transform( new (C, 1) IfTrueNode(if1) );
// Set fast path result
- Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, y, x) );
+ Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, x, y) );
phi->init_req(3, fast_result);
// Complex path
- // Build the second if node (if y is int)
- // Node for (int)y
- Node *inty = _gvn.transform( new (C, 2) ConvD2INode(y));
- // Node for (double)((int) y)
- Node *doubleinty= _gvn.transform( new (C, 2) ConvI2DNode(inty));
- // Check (double)((int) y) : y
- Node *cmpinty= _gvn.transform(new (C, 3) CmpDNode(doubleinty, y));
- // Check if (y isn't int) then go to slow path
-
- Node *bol2 = _gvn.transform( new (C, 2) BoolNode( cmpinty, BoolTest::ne ) );
+ // Build the second if node (if y is long)
+ // Node for (long)y
+ Node *longy = _gvn.transform( new (C, 2) ConvD2LNode(y));
+ // Node for (double)((long) y)
+ Node *doublelongy= _gvn.transform( new (C, 2) ConvL2DNode(longy));
+ // Check (double)((long) y) : y
+ Node *cmplongy= _gvn.transform(new (C, 3) CmpDNode(doublelongy, y));
+ // Check if (y isn't long) then go to slow path
+
+ Node *bol2 = _gvn.transform( new (C, 2) BoolNode( cmplongy, BoolTest::ne ) );
// Branch either way
IfNode *if2 = create_and_xform_if(complex_path,bol2, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN);
- Node *slow_path = opt_iff(r,if2); // Set region path 2
+ Node* ylong_path = _gvn.transform( new (C, 1) IfFalseNode(if2));
+
+ Node *slow_path = _gvn.transform( new (C, 1) IfTrueNode(if2) );
- // Calculate DPow(abs(x), y)*(1 & (int)y)
+ // Calculate DPow(abs(x), y)*(1 & (long)y)
// Node for constant 1
- Node *conone = intcon(1);
- // 1& (int)y
- Node *signnode= _gvn.transform( new (C, 3) AndINode(conone, inty) );
+ Node *conone = longcon(1);
+ // 1& (long)y
+ Node *signnode= _gvn.transform( new (C, 3) AndLNode(conone, longy) );
+
+ // A huge number is always even. Detect a huge number by checking
+ // if y + 1 == y and set integer to be tested for parity to 0.
+ // Required for corner case:
+ // (long)9.223372036854776E18 = max_jlong
+ // (double)(long)9.223372036854776E18 = 9.223372036854776E18
+ // max_jlong is odd but 9.223372036854776E18 is even
+ Node* yplus1 = _gvn.transform( new (C, 3) AddDNode(y, makecon(TypeD::make(1))));
+ Node *cmpyplus1= _gvn.transform(new (C, 3) CmpDNode(yplus1, y));
+ Node *bolyplus1 = _gvn.transform( new (C, 2) BoolNode( cmpyplus1, BoolTest::eq ) );
+ Node* correctedsign = NULL;
+ if (ConditionalMoveLimit != 0) {
+ correctedsign = _gvn.transform( CMoveNode::make(C, NULL, bolyplus1, signnode, longcon(0), TypeLong::LONG));
+ } else {
+ IfNode *ifyplus1 = create_and_xform_if(ylong_path,bolyplus1, PROB_FAIR, COUNT_UNKNOWN);
+ RegionNode *r = new (C, 3) RegionNode(3);
+ Node *phi = new (C, 3) PhiNode(r, TypeLong::LONG);
+ r->init_req(1, _gvn.transform( new (C, 1) IfFalseNode(ifyplus1)));
+ r->init_req(2, _gvn.transform( new (C, 1) IfTrueNode(ifyplus1)));
+ phi->init_req(1, signnode);
+ phi->init_req(2, longcon(0));
+ correctedsign = _gvn.transform(phi);
+ ylong_path = _gvn.transform(r);
+ record_for_igvn(r);
+ }
+
// zero node
- Node *conzero = intcon(0);
- // Check (1&(int)y)==0?
- Node *cmpeq1 = _gvn.transform(new (C, 3) CmpINode(signnode, conzero));
- // Check if (1&(int)y)!=0?, if so the result is negative
+ Node *conzero = longcon(0);
+ // Check (1&(long)y)==0?
+ Node *cmpeq1 = _gvn.transform(new (C, 3) CmpLNode(correctedsign, conzero));
+ // Check if (1&(long)y)!=0?, if so the result is negative
Node *bol3 = _gvn.transform( new (C, 2) BoolNode( cmpeq1, BoolTest::ne ) );
// abs(x)
Node *absx=_gvn.transform( new (C, 2) AbsDNode(x));
// abs(x)^y
- Node *absxpowy = _gvn.transform( new (C, 3) PowDNode(0, y, absx) );
+ Node *absxpowy = _gvn.transform( new (C, 3) PowDNode(0, absx, y) );
// -abs(x)^y
Node *negabsxpowy = _gvn.transform(new (C, 2) NegDNode (absxpowy));
- // (1&(int)y)==1?-DPow(abs(x), y):DPow(abs(x), y)
- Node *signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE));
+ // (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y)
+ Node *signresult = NULL;
+ if (ConditionalMoveLimit != 0) {
+ signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE));
+ } else {
+ IfNode *ifyeven = create_and_xform_if(ylong_path,bol3, PROB_FAIR, COUNT_UNKNOWN);
+ RegionNode *r = new (C, 3) RegionNode(3);
+ Node *phi = new (C, 3) PhiNode(r, Type::DOUBLE);
+ r->init_req(1, _gvn.transform( new (C, 1) IfFalseNode(ifyeven)));
+ r->init_req(2, _gvn.transform( new (C, 1) IfTrueNode(ifyeven)));
+ phi->init_req(1, absxpowy);
+ phi->init_req(2, negabsxpowy);
+ signresult = _gvn.transform(phi);
+ ylong_path = _gvn.transform(r);
+ record_for_igvn(r);
+ }
// Set complex path fast result
+ r->init_req(2, ylong_path);
phi->init_req(2, signresult);
static const jlong nan_bits = CONST64(0x7ff8000000000000);
@@ -1689,27 +1763,10 @@ bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) {
result=_gvn.transform(phi);
}
- //-------------------
- //result=(result.isNaN())? uncommon_trap():result;
- // Check: If isNaN() by checking result!=result? then go to Strict Math
- Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result));
- // Build the boolean node
- Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) );
-
- { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT);
- // End the current control-flow path
- push_pair(x);
- push_pair(y);
- // Math.pow intrinsic returned a NaN, which requires StrictMath.pow
- // to handle. Recompile without intrinsifying Math.pow.
- uncommon_trap(Deoptimization::Reason_intrinsic,
- Deoptimization::Action_make_not_entrant);
- }
+ finish_pow_exp(result, x, y, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW");
C->set_has_split_ifs(true); // Has chance for split-if optimization
- push_pair(result);
-
return true;
}
diff --git a/src/share/vm/opto/parse2.cpp b/src/share/vm/opto/parse2.cpp
index 541f26dd5..4982a1d76 100644
--- a/src/share/vm/opto/parse2.cpp
+++ b/src/share/vm/opto/parse2.cpp
@@ -1278,9 +1278,9 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest,
// or the narrowOop equivalent.
const Type* obj_type = _gvn.type(obj);
const TypeOopPtr* tboth = obj_type->join(con_type)->isa_oopptr();
- if (tboth != NULL && tboth != obj_type && tboth->higher_equal(obj_type)) {
+ if (tboth != NULL && tboth->klass_is_exact() && tboth != obj_type &&
+ tboth->higher_equal(obj_type)) {
// obj has to be of the exact type Foo if the CmpP succeeds.
- assert(tboth->klass_is_exact(), "klass should be exact");
int obj_in_map = map()->find_edge(obj);
JVMState* jvms = this->jvms();
if (obj_in_map >= 0 &&
diff --git a/src/share/vm/opto/subnode.cpp b/src/share/vm/opto/subnode.cpp
index 4fbf54353..02a6a6495 100644
--- a/src/share/vm/opto/subnode.cpp
+++ b/src/share/vm/opto/subnode.cpp
@@ -554,9 +554,7 @@ const Type *CmpUNode::sub( const Type *t1, const Type *t2 ) const {
return TypeInt::CC_GE;
} else if (hi0 <= lo1) {
// Check for special case in Hashtable::get. (See below.)
- if ((jint)lo0 >= 0 && (jint)lo1 >= 0 &&
- in(1)->Opcode() == Op_ModI &&
- in(1)->in(2) == in(2) )
+ if ((jint)lo0 >= 0 && (jint)lo1 >= 0 && is_index_range_check())
return TypeInt::CC_LT;
return TypeInt::CC_LE;
}
@@ -567,13 +565,17 @@ const Type *CmpUNode::sub( const Type *t1, const Type *t2 ) const {
// to be positive.
// (This is a gross hack, since the sub method never
// looks at the structure of the node in any other case.)
- if ((jint)lo0 >= 0 && (jint)lo1 >= 0 &&
- in(1)->Opcode() == Op_ModI &&
- in(1)->in(2)->uncast() == in(2)->uncast())
+ if ((jint)lo0 >= 0 && (jint)lo1 >= 0 && is_index_range_check())
return TypeInt::CC_LT;
return TypeInt::CC; // else use worst case results
}
+bool CmpUNode::is_index_range_check() const {
+ // Check for the "(X ModI Y) CmpU Y" shape
+ return (in(1)->Opcode() == Op_ModI &&
+ in(1)->in(2)->eqv_uncast(in(2)));
+}
+
//------------------------------Idealize---------------------------------------
Node *CmpINode::Ideal( PhaseGVN *phase, bool can_reshape ) {
if (phase->type(in(2))->higher_equal(TypeInt::ZERO)) {
diff --git a/src/share/vm/opto/subnode.hpp b/src/share/vm/opto/subnode.hpp
index bacd1065a..2b33e90f9 100644
--- a/src/share/vm/opto/subnode.hpp
+++ b/src/share/vm/opto/subnode.hpp
@@ -158,6 +158,7 @@ public:
CmpUNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {}
virtual int Opcode() const;
virtual const Type *sub( const Type *, const Type * ) const;
+ bool is_index_range_check() const;
};
//------------------------------CmpPNode---------------------------------------
diff --git a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp
index d7dfea5a9..60a801213 100644
--- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp
+++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp
@@ -268,14 +268,18 @@ void JvmtiClassFileReconstituter::write_source_file_attribute() {
// JSR45| SourceDebugExtension_attribute {
// JSR45| u2 attribute_name_index;
// JSR45| u4 attribute_length;
-// JSR45| u2 sourcefile_index;
+// JSR45| u1 debug_extension[attribute_length];
// JSR45| }
void JvmtiClassFileReconstituter::write_source_debug_extension_attribute() {
assert(ikh()->source_debug_extension() != NULL, "caller must check");
write_attribute_name_index("SourceDebugExtension");
- write_u4(2); // always length 2
- write_u2(symbol_to_cpool_index(ikh()->source_debug_extension()));
+ int len = (int)strlen(ikh()->source_debug_extension());
+ write_u4(len);
+ u1* ext = (u1*)ikh()->source_debug_extension();
+ for (int i=0; i<len; i++) {
+ write_u1(ext[i]);
+ }
}
// Write (generic) Signature attribute
diff --git a/src/share/vm/prims/jvmtiEnv.cpp b/src/share/vm/prims/jvmtiEnv.cpp
index 637b6a3ce..20f5cf837 100644
--- a/src/share/vm/prims/jvmtiEnv.cpp
+++ b/src/share/vm/prims/jvmtiEnv.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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
@@ -2541,15 +2541,12 @@ JvmtiEnv::GetSourceDebugExtension(oop k_mirror, char** source_debug_extension_pt
if (!Klass::cast(k)->oop_is_instance()) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
- Symbol* sdeOop = instanceKlass::cast(k)->source_debug_extension();
- NULL_CHECK(sdeOop, JVMTI_ERROR_ABSENT_INFORMATION);
+ char* sde = instanceKlass::cast(k)->source_debug_extension();
+ NULL_CHECK(sde, JVMTI_ERROR_ABSENT_INFORMATION);
{
- JavaThread* current_thread = JavaThread::current();
- ResourceMark rm(current_thread);
- const char* sdecp = (const char*) sdeOop->as_C_string();
- *source_debug_extension_ptr = (char *) jvmtiMalloc(strlen(sdecp)+1);
- strcpy(*source_debug_extension_ptr, sdecp);
+ *source_debug_extension_ptr = (char *) jvmtiMalloc(strlen(sde)+1);
+ strcpy(*source_debug_extension_ptr, sde);
}
}
diff --git a/src/share/vm/prims/jvmtiRedefineClasses.cpp b/src/share/vm/prims/jvmtiRedefineClasses.cpp
index 0eb188a63..dbab30e43 100644
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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
@@ -3236,7 +3236,9 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
// Copy the "source debug extension" attribute from new class version
the_class->set_source_debug_extension(
- scratch_class->source_debug_extension());
+ scratch_class->source_debug_extension(),
+ scratch_class->source_debug_extension() == NULL ? 0 :
+ (int)strlen(scratch_class->source_debug_extension()));
// Use of javac -g could be different in the old and the new
if (scratch_class->access_flags().has_localvariable_table() !=
diff --git a/src/share/vm/prims/whitebox.cpp b/src/share/vm/prims/whitebox.cpp
index eadc7df52..e93b9104b 100644
--- a/src/share/vm/prims/whitebox.cpp
+++ b/src/share/vm/prims/whitebox.cpp
@@ -113,6 +113,9 @@ const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
int offset = offset_for_field(field_name, object,
vmSymbols::string_signature());
oop string = object->obj_field(offset);
+ if (string == NULL) {
+ return NULL;
+ }
const char* ret = java_lang_String::as_utf8_string(string);
return ret;
}
diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp
index 921b76fd9..185dd9643 100644
--- a/src/share/vm/runtime/arguments.cpp
+++ b/src/share/vm/runtime/arguments.cpp
@@ -2983,7 +2983,10 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
const char* tail;
// If flag "-XX:Flags=flags-file" is used it will be the first option to be processed.
+ const char* hotspotrc = ".hotspotrc";
bool settings_file_specified = false;
+ bool needs_hotspotrc_warning = false;
+
const char* flags_file;
int index;
for (index = 0; index < args->nOptions; index++) {
@@ -3031,16 +3034,19 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
if (!process_settings_file(flags_file, true, args->ignoreUnrecognized)) {
return JNI_EINVAL;
}
- }
-
+ } else {
#ifdef ASSERT
- // Parse default .hotspotrc settings file
- if (!settings_file_specified) {
+ // Parse default .hotspotrc settings file
if (!process_settings_file(".hotspotrc", false, args->ignoreUnrecognized)) {
return JNI_EINVAL;
}
- }
+#else
+ struct stat buf;
+ if (os::stat(hotspotrc, &buf) == 0) {
+ needs_hotspotrc_warning = true;
+ }
#endif
+ }
if (PrintVMOptions) {
for (index = 0; index < args->nOptions; index++) {
@@ -3057,6 +3063,14 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
return result;
}
+ // Delay warning until here so that we've had a chance to process
+ // the -XX:-PrintWarnings flag
+ if (needs_hotspotrc_warning) {
+ warning("%s file is present but has been ignored. "
+ "Run with -XX:Flags=%s to load the file.",
+ hotspotrc, hotspotrc);
+ }
+
#if (defined JAVASE_EMBEDDED || defined ARM)
UNSUPPORTED_OPTION(UseG1GC, "G1 GC");
#endif
diff --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp
index e1021cd19..fbda7f8ed 100644
--- a/src/share/vm/runtime/vmStructs.cpp
+++ b/src/share/vm/runtime/vmStructs.cpp
@@ -308,7 +308,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
nonstatic_field(instanceKlass, _protection_domain, oop) \
nonstatic_field(instanceKlass, _signers, objArrayOop) \
nonstatic_field(instanceKlass, _source_file_name, Symbol*) \
- nonstatic_field(instanceKlass, _source_debug_extension, Symbol*) \
+ nonstatic_field(instanceKlass, _source_debug_extension, char*) \
nonstatic_field(instanceKlass, _inner_classes, typeArrayOop) \
nonstatic_field(instanceKlass, _nonstatic_field_size, int) \
nonstatic_field(instanceKlass, _static_field_size, int) \
diff --git a/src/share/vm/services/diagnosticCommand.hpp b/src/share/vm/services/diagnosticCommand.hpp
index d5c5cd172..cf4134f41 100644
--- a/src/share/vm/services/diagnosticCommand.hpp
+++ b/src/share/vm/services/diagnosticCommand.hpp
@@ -48,7 +48,7 @@ public:
"With no argument this will show a list of available commands. "
"'help all' will show help for all commands.";
}
- static const char* impact() { return "Low: "; }
+ static const char* impact() { return "Low"; }
static int num_arguments();
virtual void execute(TRAPS);
};
@@ -60,7 +60,7 @@ public:
static const char* description() {
return "Print JVM version information.";
}
- static const char* impact() { return "Low: "; }
+ static const char* impact() { return "Low"; }
static int num_arguments() { return 0; }
virtual void execute(TRAPS);
};
@@ -72,7 +72,7 @@ public:
static const char* description() {
return "Print the command line used to start this VM instance.";
}
- static const char* impact() { return "Low: "; }
+ static const char* impact() { return "Low"; }
static int num_arguments() { return 0; }
virtual void execute(TRAPS) {
Arguments::print_on(_output);
@@ -88,7 +88,7 @@ public:
return "Print system properties.";
}
static const char* impact() {
- return "Low: ";
+ return "Low";
}
static int num_arguments() { return 0; }
virtual void execute(TRAPS);
@@ -105,7 +105,7 @@ public:
return "Print VM flag options and their current values.";
}
static const char* impact() {
- return "Low: ";
+ return "Low";
}
static int num_arguments();
virtual void execute(TRAPS);
@@ -121,7 +121,7 @@ public:
return "Print VM uptime.";
}
static const char* impact() {
- return "Low: ";
+ return "Low";
}
static int num_arguments();
virtual void execute(TRAPS);
diff --git a/src/share/vm/services/diagnosticFramework.cpp b/src/share/vm/services/diagnosticFramework.cpp
index 73e9bdc54..2ae7866f6 100644
--- a/src/share/vm/services/diagnosticFramework.cpp
+++ b/src/share/vm/services/diagnosticFramework.cpp
@@ -75,11 +75,13 @@ bool DCmdArgIter::next(TRAPS) {
}
// extracting first item, argument or option name
_key_addr = &_buffer[_cursor];
+ bool arg_had_quotes = false;
while (_cursor <= _len - 1 && _buffer[_cursor] != '=' && _buffer[_cursor] != _delim) {
// argument can be surrounded by single or double quotes
if (_buffer[_cursor] == '\"' || _buffer[_cursor] == '\'') {
_key_addr++;
char quote = _buffer[_cursor];
+ arg_had_quotes = true;
while (_cursor < _len - 1) {
_cursor++;
if (_buffer[_cursor] == quote && _buffer[_cursor - 1] != '\\') {
@@ -95,16 +97,22 @@ bool DCmdArgIter::next(TRAPS) {
_cursor++;
}
_key_len = &_buffer[_cursor] - _key_addr;
+ if (arg_had_quotes) {
+ // if the argument was quoted, we need to step past the last quote here
+ _cursor++;
+ }
// check if the argument has the <key>=<value> format
if (_cursor <= _len -1 && _buffer[_cursor] == '=') {
_cursor++;
_value_addr = &_buffer[_cursor];
+ bool value_had_quotes = false;
// extract the value
while (_cursor <= _len - 1 && _buffer[_cursor] != _delim) {
// value can be surrounded by simple or double quotes
if (_buffer[_cursor] == '\"' || _buffer[_cursor] == '\'') {
_value_addr++;
char quote = _buffer[_cursor];
+ value_had_quotes = true;
while (_cursor < _len - 1) {
_cursor++;
if (_buffer[_cursor] == quote && _buffer[_cursor - 1] != '\\') {
@@ -120,6 +128,10 @@ bool DCmdArgIter::next(TRAPS) {
_cursor++;
}
_value_len = &_buffer[_cursor] - _value_addr;
+ if (value_had_quotes) {
+ // if the value was quoted, we need to step past the last quote here
+ _cursor++;
+ }
} else {
_value_addr = NULL;
_value_len = 0;
@@ -185,8 +197,17 @@ void DCmdParser::parse(CmdLine* line, char delim, TRAPS) {
arg->read_value(iter.key_addr(), iter.key_length(), CHECK);
next_argument = next_argument->next();
} else {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Unknown argument in diagnostic command");
+ const size_t buflen = 120;
+ const size_t argbuflen = 30;
+ char buf[buflen];
+ char argbuf[argbuflen];
+ size_t len = MIN2<size_t>(iter.key_length(), argbuflen - 1);
+
+ strncpy(argbuf, iter.key_addr(), len);
+ argbuf[len] = '\0';
+ jio_snprintf(buf, buflen - 1, "Unknown argument '%s' in diagnostic command.", argbuf);
+
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
}
}
cont = iter.next(CHECK);
@@ -207,19 +228,21 @@ GenDCmdArgument* DCmdParser::lookup_dcmd_option(const char* name, size_t len) {
}
void DCmdParser::check(TRAPS) {
+ const size_t buflen = 256;
+ char buf[buflen];
GenDCmdArgument* arg = _arguments_list;
while (arg != NULL) {
if (arg->is_mandatory() && !arg->has_value()) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Missing argument for diagnostic command");
+ jio_snprintf(buf, buflen - 1, "The argument '%s' is mandatory.", arg->name());
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
}
arg = arg->next();
}
arg = _options;
while (arg != NULL) {
if (arg->is_mandatory() && !arg->has_value()) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Missing option for diagnostic command");
+ jio_snprintf(buf, buflen - 1, "The option '%s' is mandatory.", arg->name());
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
}
arg = arg->next();
}
diff --git a/src/share/vm/services/diagnosticFramework.hpp b/src/share/vm/services/diagnosticFramework.hpp
index f6863e477..08b24e07f 100644
--- a/src/share/vm/services/diagnosticFramework.hpp
+++ b/src/share/vm/services/diagnosticFramework.hpp
@@ -238,6 +238,16 @@ public:
static const char* name() { return "No Name";}
static const char* description() { return "No Help";}
static const char* disabled_message() { return "Diagnostic command currently disabled"; }
+ // The impact() method returns a description of the intrusiveness of the diagnostic
+ // command on the Java Virtual Machine behavior. The rational for this method is that some
+ // diagnostic commands can seriously disrupt the behavior of the Java Virtual Machine
+ // (for instance a Thread Dump for an application with several tens of thousands of threads,
+ // or a Head Dump with a 40GB+ heap size) and other diagnostic commands have no serious
+ // impact on the JVM (for instance, getting the command line arguments or the JVM version).
+ // The recommended format for the description is <impact level>: [longer description],
+ // where the impact level is selected among this list: {Low, Medium, High}. The optional
+ // longer description can provide more specific details like the fact that Thread Dump
+ // impact depends on the heap size.
static const char* impact() { return "Low: No impact"; }
static int num_arguments() { return 0; }
outputStream* output() { return _output; }
@@ -250,7 +260,7 @@ public:
bool has_arg = iter.next(CHECK);
if (has_arg) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Unknown argument in diagnostic command");
+ "The argument list of this diagnostic command should be empty.");
}
}
virtual void execute(TRAPS) { }