--- a/make/autoconf/flags-cflags.m4 Tue Jan 15 16:40:31 2019 -0500
+++ b/make/autoconf/flags-cflags.m4 Tue Jan 15 22:54:09 2019 +0100
@@ -527,8 +527,8 @@
fi
if test "x$TOOLCHAIN_TYPE" = xgcc; then
- TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -fcheck-new"
- TOOLCHAIN_CFLAGS_JDK="-pipe"
+ TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -fcheck-new -fstack-protector"
+ TOOLCHAIN_CFLAGS_JDK="-pipe -fstack-protector"
TOOLCHAIN_CFLAGS_JDK_CONLY="-fno-strict-aliasing" # technically NOT for CXX (but since this gives *worse* performance, use no-strict-aliasing everywhere!)
CXXSTD_CXXFLAG="-std=gnu++98"
--- a/make/lib/Lib-java.base.gmk Tue Jan 15 16:40:31 2019 -0500
+++ b/make/lib/Lib-java.base.gmk Tue Jan 15 22:54:09 2019 +0100
@@ -56,7 +56,7 @@
LIBS_solaris := -lnsl -lsocket $(LIBDL), \
LIBS_aix := $(LIBDL),\
LIBS_windows := ws2_32.lib jvm.lib secur32.lib iphlpapi.lib winhttp.lib \
- delayimp.lib $(WIN_JAVA_LIB) advapi32.lib, \
+ urlmon.lib delayimp.lib $(WIN_JAVA_LIB) advapi32.lib, \
LIBS_macosx := -framework CoreFoundation -framework CoreServices, \
))
--- a/src/hotspot/cpu/x86/x86.ad Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/cpu/x86/x86.ad Tue Jan 15 22:54:09 2019 +0100
@@ -9936,6 +9936,7 @@
__ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
+ ins_cost(10);
%}
instruct vmuladdadd8S4I_reg(vecX dst, vecX src1, vecX src2) %{
@@ -9947,6 +9948,7 @@
__ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
+ ins_cost(10);
%}
instruct vmuladdadd16S8I_reg(vecY dst, vecY src1, vecY src2) %{
@@ -9958,6 +9960,7 @@
__ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
+ ins_cost(10);
%}
instruct vmuladdadd32S16I_reg(vecZ dst, vecZ src1, vecZ src2) %{
@@ -9969,6 +9972,7 @@
__ evpdpwssd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
+ ins_cost(10);
%}
// --------------------------------- PopCount --------------------------------------
--- a/src/hotspot/share/ci/ciMethodData.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/ci/ciMethodData.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -168,9 +168,12 @@
// in the prepare_metadata call above) as we translate the copy:
// update the copy as we go.
int tag = dp_src->tag();
- if (tag != DataLayout::arg_info_data_tag) {
- memcpy(dp_dst, dp_src, ((intptr_t)MethodData::next_extra(dp_src)) - ((intptr_t)dp_src));
+ size_t entry_size = DataLayout::header_size_in_bytes();
+ if (tag != DataLayout::no_tag) {
+ ProfileData* src_data = dp_src->data_in();
+ entry_size = src_data->size_in_bytes();
}
+ memcpy(dp_dst, dp_src, entry_size);
switch(tag) {
case DataLayout::speculative_trap_data_tag: {
--- a/src/hotspot/share/classfile/classFileParser.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/classfile/classFileParser.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -4486,33 +4486,6 @@
}
}
-// Attach super classes and interface classes to class loader data
-static void record_defined_class_dependencies(const InstanceKlass* defined_klass,
- TRAPS) {
- assert(defined_klass != NULL, "invariant");
-
- ClassLoaderData* const defining_loader_data = defined_klass->class_loader_data();
- if (defining_loader_data->is_the_null_class_loader_data()) {
- // Dependencies to null class loader data are implicit.
- return;
- } else {
- // add super class dependency
- Klass* const super = defined_klass->super();
- if (super != NULL) {
- defining_loader_data->record_dependency(super);
- }
-
- // add super interface dependencies
- const Array<InstanceKlass*>* const local_interfaces = defined_klass->local_interfaces();
- if (local_interfaces != NULL) {
- const int length = local_interfaces->length();
- for (int i = 0; i < length; i++) {
- defining_loader_data->record_dependency(local_interfaces->at(i));
- }
- }
- }
-}
-
// utility methods for appending an array with check for duplicates
static void append_interfaces(GrowableArray<InstanceKlass*>* result,
@@ -5719,9 +5692,6 @@
}
}
- // Update the loader_data graph.
- record_defined_class_dependencies(ik, CHECK);
-
ClassLoadingService::notify_class_loaded(ik, false /* not shared class */);
if (!is_internal()) {
--- a/src/hotspot/share/classfile/classLoaderDataGraph.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/classfile/classLoaderDataGraph.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -561,11 +561,6 @@
ClassLoaderData* data = _head;
while (data != NULL) {
- // Remove entries in the dictionary of live class loader that have
- // initiated loading classes in a dead class loader.
- if (data->dictionary() != NULL) {
- data->dictionary()->do_unloading();
- }
// Walk a ModuleEntry's reads, and a PackageEntry's exports
// lists to determine if there are modules on those lists that are now
// dead and should be removed. A module's life cycle is equivalent
--- a/src/hotspot/share/classfile/dictionary.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/classfile/dictionary.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -233,40 +233,6 @@
}
}
-
-void Dictionary::do_unloading() {
- assert_locked_or_safepoint(SystemDictionary_lock);
-
- // The NULL class loader doesn't initiate loading classes from other class loaders
- if (loader_data() == ClassLoaderData::the_null_class_loader_data()) {
- return;
- }
-
- // Remove unloaded entries and classes from this dictionary
- DictionaryEntry* probe = NULL;
- for (int index = 0; index < table_size(); index++) {
- for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
- probe = *p;
- InstanceKlass* ik = probe->instance_klass();
- ClassLoaderData* k_def_class_loader_data = ik->class_loader_data();
-
- // If the klass that this loader initiated is dead,
- // (determined by checking the defining class loader)
- // remove this entry.
- if (k_def_class_loader_data->is_unloading()) {
- assert(k_def_class_loader_data != loader_data(),
- "cannot have live defining loader and unreachable klass");
- *p = probe->next();
- free_entry(probe);
- continue;
- }
- // Clean pd_set
- clean_cached_protection_domains(probe);
- p = probe->next_addr();
- }
- }
-}
-
// Just the classes from defining class loaders
void Dictionary::classes_do(void f(InstanceKlass*)) {
for (int index = 0; index < table_size(); index++) {
--- a/src/hotspot/share/classfile/dictionary.hpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/classfile/dictionary.hpp Tue Jan 15 22:54:09 2019 +0100
@@ -74,9 +74,6 @@
void unlink();
- // Unload classes whose defining loaders are unloaded
- void do_unloading();
-
// Protection domains
InstanceKlass* find(unsigned int hash, Symbol* name, Handle protection_domain);
bool is_valid_protection_domain(unsigned int hash,
--- a/src/hotspot/share/classfile/systemDictionary.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -860,8 +860,15 @@
check_constraints(d_hash, k, class_loader, false, THREAD);
// Need to check for a PENDING_EXCEPTION again; check_constraints
- // can throw and doesn't use the CHECK macro.
+ // can throw but we may have to remove entry from the placeholder table below.
if (!HAS_PENDING_EXCEPTION) {
+ // Record dependency for non-parent delegation.
+ // This recording keeps the defining class loader of the klass (k) found
+ // from being unloaded while the initiating class loader is loaded
+ // even if the reference to the defining class loader is dropped
+ // before references to the initiating class loader.
+ loader_data->record_dependency(k);
+
{ // Grabbing the Compile_lock prevents systemDictionary updates
// during compilations.
MutexLocker mu(Compile_lock, THREAD);
@@ -2179,6 +2186,7 @@
InstanceKlass* sd_check = find_class(d_hash, name, dictionary);
if (sd_check == NULL) {
dictionary->add_klass(d_hash, name, k);
+
notice_modification();
}
#ifdef ASSERT
--- a/src/hotspot/share/classfile/verificationType.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/classfile/verificationType.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -50,7 +50,6 @@
Klass* this_class = SystemDictionary::resolve_or_fail(
name, Handle(THREAD, klass->class_loader()),
Handle(THREAD, klass->protection_domain()), true, CHECK_false);
- klass->class_loader_data()->record_dependency(this_class);
if (log_is_enabled(Debug, class, resolve)) {
Verifier::trace_class_resolution(this_class, klass);
}
@@ -68,7 +67,6 @@
Klass* from_class = SystemDictionary::resolve_or_fail(
from_name, Handle(THREAD, klass->class_loader()),
Handle(THREAD, klass->protection_domain()), true, CHECK_false);
- klass->class_loader_data()->record_dependency(from_class);
if (log_is_enabled(Debug, class, resolve)) {
Verifier::trace_class_resolution(from_class, klass);
}
--- a/src/hotspot/share/classfile/verifier.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/classfile/verifier.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -2015,7 +2015,6 @@
true, THREAD);
if (kls != NULL) {
- current_class()->class_loader_data()->record_dependency(kls);
if (log_is_enabled(Debug, class, resolve)) {
Verifier::trace_class_resolution(kls, current_class());
}
--- a/src/hotspot/share/oops/constantPool.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/oops/constantPool.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -504,10 +504,6 @@
}
}
- // Make this class loader depend upon the class loader owning the class reference
- ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data();
- this_key->record_dependency(k);
-
// logging for class+resolve.
if (log_is_enabled(Debug, class, resolve)){
trace_class_resolution(this_cp, k);
--- a/src/hotspot/share/oops/cpCache.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/oops/cpCache.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -253,11 +253,21 @@
if (byte_no == 1) {
assert(invoke_code != Bytecodes::_invokevirtual &&
invoke_code != Bytecodes::_invokeinterface, "");
+ bool do_resolve = true;
// Don't mark invokespecial to method as resolved if sender is an interface. The receiver
// has to be checked that it is a subclass of the current class every time this bytecode
// is executed.
- if (invoke_code != Bytecodes::_invokespecial || !sender_is_interface ||
- method->name() == vmSymbols::object_initializer_name()) {
+ if (invoke_code == Bytecodes::_invokespecial && sender_is_interface &&
+ method->name() != vmSymbols::object_initializer_name()) {
+ do_resolve = false;
+ }
+ // Don't mark invokestatic to method as resolved if the holder class has not yet completed
+ // initialization. An invokestatic must only proceed if the class is initialized, but if
+ // we resolve it before then that class initialization check is skipped.
+ if (invoke_code == Bytecodes::_invokestatic && !method->method_holder()->is_initialized()) {
+ do_resolve = false;
+ }
+ if (do_resolve) {
set_bytecode_1(invoke_code);
}
} else if (byte_no == 2) {
--- a/src/hotspot/share/opto/loopPredicate.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/opto/loopPredicate.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -1308,7 +1308,7 @@
// range checks between the pre and main loop to validate the value
// of the main loop induction variable. Make a copy of the predicates
// here with an opaque node as a place holder for the value (will be
-// updated by PhaseIdealLoop::update_skeleton_predicate()).
+// updated by PhaseIdealLoop::clone_skeleton_predicate()).
ProjNode* PhaseIdealLoop::insert_skeleton_predicate(IfNode* iff, IdealLoopTree *loop,
ProjNode* proj, ProjNode *predicate_proj,
ProjNode* upper_bound_proj,
--- a/src/hotspot/share/opto/loopTransform.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/opto/loopTransform.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -1067,8 +1067,9 @@
// CastII/ConvI2L nodes cause some data paths to die. For consistency,
// the control paths must die too but the range checks were removed by
// predication. The range checks that we add here guarantee that they do.
-void PhaseIdealLoop::duplicate_predicates_helper(Node* predicate, Node* castii, IdealLoopTree* outer_loop,
- LoopNode* outer_main_head, uint dd_main_head) {
+void PhaseIdealLoop::duplicate_predicates_helper(Node* predicate, Node* start, Node* end,
+ IdealLoopTree* outer_loop, LoopNode* outer_main_head,
+ uint dd_main_head) {
if (predicate != NULL) {
IfNode* iff = predicate->in(0)->as_If();
ProjNode* uncommon_proj = iff->proj_out(1 - predicate->as_Proj()->_con);
@@ -1084,13 +1085,14 @@
if (uncommon_proj->unique_ctrl_out() != rgn)
break;
if (iff->in(1)->Opcode() == Op_Opaque4) {
+ assert(skeleton_predicate_has_opaque(iff), "unexpected");
// Clone the predicate twice and initialize one with the initial
// value of the loop induction variable. Leave the other predicate
// to be initialized when increasing the stride during loop unrolling.
- prev_proj = update_skeleton_predicate(iff, castii, predicate, uncommon_proj, current_proj, outer_loop, prev_proj);
- Node* value = new Opaque1Node(C, castii);
- register_new_node(value, current_proj);
- prev_proj = update_skeleton_predicate(iff, value, predicate, uncommon_proj, current_proj, outer_loop, prev_proj);
+ prev_proj = clone_skeleton_predicate(iff, start, predicate, uncommon_proj, current_proj, outer_loop, prev_proj);
+ assert(skeleton_predicate_has_opaque(prev_proj->in(0)->as_If()) == (start->Opcode() == Op_Opaque1), "");
+ prev_proj = clone_skeleton_predicate(iff, end, predicate, uncommon_proj, current_proj, outer_loop, prev_proj);
+ assert(skeleton_predicate_has_opaque(prev_proj->in(0)->as_If()) == (end->Opcode() == Op_Opaque1), "");
// Remove the skeleton predicate from the pre-loop
_igvn.replace_input_of(iff, 1, _igvn.intcon(1));
}
@@ -1101,9 +1103,47 @@
}
}
-Node* PhaseIdealLoop::update_skeleton_predicate(Node* iff, Node* value, Node* predicate, Node* uncommon_proj,
- Node* current_proj, IdealLoopTree* outer_loop, Node* prev_proj) {
- bool clone = (outer_loop != NULL); // Clone the predicate?
+static bool skeleton_follow_inputs(Node* n, int op) {
+ return (n->is_Bool() ||
+ n->is_Cmp() ||
+ op == Op_AndL ||
+ op == Op_OrL ||
+ op == Op_RShiftL ||
+ op == Op_LShiftL ||
+ op == Op_AddL ||
+ op == Op_AddI ||
+ op == Op_MulL ||
+ op == Op_MulI ||
+ op == Op_SubL ||
+ op == Op_SubI ||
+ op == Op_ConvI2L);
+}
+
+bool PhaseIdealLoop::skeleton_predicate_has_opaque(IfNode* iff) {
+ ResourceMark rm;
+ Unique_Node_List wq;
+ wq.push(iff->in(1)->in(1));
+ for (uint i = 0; i < wq.size(); i++) {
+ Node* n = wq.at(i);
+ int op = n->Opcode();
+ if (skeleton_follow_inputs(n, op)) {
+ for (uint j = 1; j < n->req(); j++) {
+ Node* m = n->in(j);
+ if (m != NULL) {
+ wq.push(m);
+ }
+ }
+ continue;
+ }
+ if (op == Op_Opaque1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+Node* PhaseIdealLoop::clone_skeleton_predicate(Node* iff, Node* value, Node* predicate, Node* uncommon_proj,
+ Node* current_proj, IdealLoopTree* outer_loop, Node* prev_proj) {
Node_Stack to_clone(2);
to_clone.push(iff->in(1), 1);
uint current = C->unique();
@@ -1118,28 +1158,11 @@
uint i = to_clone.index();
Node* m = n->in(i);
int op = m->Opcode();
- if (m->is_Bool() ||
- m->is_Cmp() ||
- op == Op_AndL ||
- op == Op_OrL ||
- op == Op_RShiftL ||
- op == Op_LShiftL ||
- op == Op_AddL ||
- op == Op_AddI ||
- op == Op_MulL ||
- op == Op_MulI ||
- op == Op_SubL ||
- op == Op_SubI ||
- op == Op_ConvI2L) {
+ if (skeleton_follow_inputs(m, op)) {
to_clone.push(m, 1);
continue;
}
if (op == Op_Opaque1) {
- if (!clone) {
- // Update the input of the Opaque1Node and exit
- _igvn.replace_input_of(m, 1, value);
- return prev_proj;
- }
if (n->_idx < current) {
n = n->clone();
}
@@ -1161,20 +1184,17 @@
}
Node* next = to_clone.node();
j = to_clone.index();
- if (clone && cur->_idx >= current) {
+ if (next->in(j) != cur) {
+ assert(cur->_idx >= current || next->in(j)->Opcode() == Op_Opaque1, "new node or Opaque1 being replaced");
if (next->_idx < current) {
next = next->clone();
register_new_node(next, current_proj);
to_clone.set_node(next);
}
- assert(next->in(j) != cur, "input should have been cloned");
next->set_req(j, cur);
}
}
} while (result == NULL);
- if (!clone) {
- return NULL;
- }
assert(result->_idx >= current, "new node expected");
Node* proj = predicate->clone();
@@ -1197,8 +1217,9 @@
return proj;
}
-void PhaseIdealLoop::duplicate_predicates(CountedLoopNode* pre_head, Node* castii, IdealLoopTree* outer_loop,
- LoopNode* outer_main_head, uint dd_main_head) {
+void PhaseIdealLoop::duplicate_predicates(CountedLoopNode* pre_head, Node* start, Node* end,
+ IdealLoopTree* outer_loop, LoopNode* outer_main_head,
+ uint dd_main_head) {
if (UseLoopPredicate) {
Node* entry = pre_head->in(LoopNode::EntryControl);
Node* predicate = NULL;
@@ -1214,8 +1235,8 @@
}
}
predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
- duplicate_predicates_helper(predicate, castii, outer_loop, outer_main_head, dd_main_head);
- duplicate_predicates_helper(profile_predicate, castii, outer_loop, outer_main_head, dd_main_head);
+ duplicate_predicates_helper(predicate, start, end, outer_loop, outer_main_head, dd_main_head);
+ duplicate_predicates_helper(profile_predicate, start, end, outer_loop, outer_main_head, dd_main_head);
}
}
@@ -1362,7 +1383,9 @@
// CastII for the main loop:
Node* castii = cast_incr_before_loop( pre_incr, min_taken, main_head );
assert(castii != NULL, "no castII inserted");
- duplicate_predicates(pre_head, castii, outer_loop, outer_main_head, dd_main_head);
+ Node* opaque_castii = new Opaque1Node(C, castii);
+ register_new_node(opaque_castii, outer_main_head->in(LoopNode::EntryControl));
+ duplicate_predicates(pre_head, castii, opaque_castii, outer_loop, outer_main_head, dd_main_head);
// Step B4: Shorten the pre-loop to run only 1 iteration (for now).
// RCE and alignment may change this later.
@@ -1641,6 +1664,49 @@
return !is_member(_phase->get_loop(n_c));
}
+void PhaseIdealLoop::update_skeleton_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con) {
+ // Search for skeleton predicates and update them according to the new stride
+ Node* entry = ctrl;
+ Node* prev_proj = ctrl;
+ LoopNode* outer_loop_head = loop_head->skip_strip_mined();
+ IdealLoopTree* outer_loop = get_loop(outer_loop_head);
+ while (entry != NULL && entry->is_Proj() && entry->in(0)->is_If()) {
+ IfNode* iff = entry->in(0)->as_If();
+ ProjNode* proj = iff->proj_out(1 - entry->as_Proj()->_con);
+ if (proj->unique_ctrl_out()->Opcode() != Op_Halt) {
+ break;
+ }
+ if (iff->in(1)->Opcode() == Op_Opaque4) {
+ // Look for predicate with an Opaque1 node that can be used as a template
+ if (!skeleton_predicate_has_opaque(iff)) {
+ // No Opaque1 node? It's either the check for the first value
+ // of the first iteration or the check for the last value of
+ // the first iteration of an unrolled loop. We can't
+ // tell. Kill it in any case.
+ _igvn.replace_input_of(iff, 1, iff->in(1)->in(2));
+ } else {
+ // Add back the predicate for the value at the beginning of the first entry
+ prev_proj = clone_skeleton_predicate(iff, init, entry, proj, ctrl, outer_loop, prev_proj);
+ assert(!skeleton_predicate_has_opaque(prev_proj->in(0)->as_If()), "unexpected");
+ // Compute the value of the loop induction variable at the end of the
+ // first iteration of the unrolled loop: init + new_stride_con - init_inc
+ int init_inc = stride_con/loop_head->unrolled_count();
+ assert(init_inc != 0, "invalid loop increment");
+ int new_stride_con = stride_con * 2;
+ Node* max_value = _igvn.intcon(new_stride_con - init_inc);
+ max_value = new AddINode(init, max_value);
+ register_new_node(max_value, get_ctrl(iff->in(1)));
+ prev_proj = clone_skeleton_predicate(iff, max_value, entry, proj, ctrl, outer_loop, prev_proj);
+ assert(!skeleton_predicate_has_opaque(prev_proj->in(0)->as_If()), "unexpected");
+ }
+ }
+ entry = entry->in(0)->in(0);
+ }
+ if (prev_proj != ctrl) {
+ _igvn.replace_input_of(outer_loop_head, LoopNode::EntryControl, prev_proj);
+ set_idom(outer_loop_head, prev_proj, dom_depth(outer_loop_head));
+ }
+}
//------------------------------do_unroll--------------------------------------
// Unroll the loop body one step - make each trip do 2 iterations.
@@ -1706,29 +1772,7 @@
assert(old_trip_count > 1 &&
(!adjust_min_trip || stride_p <= (1<<3)*loop_head->unrolled_count()), "sanity");
- if (UseLoopPredicate) {
- // Search for skeleton predicates and update them according to the new stride
- Node* entry = ctrl;
- while (entry != NULL && entry->is_Proj() && entry->in(0)->is_If()) {
- IfNode* iff = entry->in(0)->as_If();
- ProjNode* proj = iff->proj_out(1 - entry->as_Proj()->_con);
- if (proj->unique_ctrl_out()->Opcode() != Op_Halt) {
- break;
- }
- if (iff->in(1)->Opcode() == Op_Opaque4) {
- // Compute the value of the loop induction variable at the end of the
- // first iteration of the unrolled loop: init + new_stride_con - init_inc
- int init_inc = stride_con/loop_head->unrolled_count();
- assert(init_inc != 0, "invalid loop increment");
- int new_stride_con = stride_con * 2;
- Node* max_value = _igvn.intcon(new_stride_con - init_inc);
- max_value = new AddINode(init, max_value);
- register_new_node(max_value, get_ctrl(iff->in(1)));
- update_skeleton_predicate(iff, max_value);
- }
- entry = entry->in(0)->in(0);
- }
- }
+ update_skeleton_predicates(ctrl, loop_head, init, stride_con);
// Adjust loop limit to keep valid iterations number after unroll.
// Use (limit - stride) instead of (((limit - init)/stride) & (-2))*stride
@@ -2296,9 +2340,9 @@
// eliminated by iteration splitting.
Node* PhaseIdealLoop::add_range_check_predicate(IdealLoopTree* loop, CountedLoopNode* cl,
Node* predicate_proj, int scale_con, Node* offset,
- Node* limit, jint stride_con) {
+ Node* limit, jint stride_con, Node* value) {
bool overflow = false;
- BoolNode* bol = rc_predicate(loop, predicate_proj, scale_con, offset, cl->init_trip(), NULL, stride_con, limit, (stride_con > 0) != (scale_con > 0), overflow);
+ BoolNode* bol = rc_predicate(loop, predicate_proj, scale_con, offset, value, NULL, stride_con, limit, (stride_con > 0) != (scale_con > 0), overflow);
Node* opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1));
register_new_node(opaque_bol, predicate_proj);
IfNode* new_iff = NULL;
@@ -2497,7 +2541,23 @@
add_constraint( stride_con, scale_con, offset, zero, limit, pre_ctrl, &pre_limit, &main_limit );
// (0-offset)/scale could be outside of loop iterations range.
conditional_rc = true;
- predicate_proj = add_range_check_predicate(loop, cl, predicate_proj, scale_con, offset, limit, stride_con);
+ Node* init = cl->init_trip();
+ Node* opaque_init = new Opaque1Node(C, init);
+ register_new_node(opaque_init, predicate_proj);
+ // template predicate so it can be updated on next unrolling
+ predicate_proj = add_range_check_predicate(loop, cl, predicate_proj, scale_con, offset, limit, stride_con, opaque_init);
+ assert(skeleton_predicate_has_opaque(predicate_proj->in(0)->as_If()), "unexpected");
+ // predicate on first value of first iteration
+ predicate_proj = add_range_check_predicate(loop, cl, predicate_proj, scale_con, offset, limit, stride_con, init);
+ assert(!skeleton_predicate_has_opaque(predicate_proj->in(0)->as_If()), "unexpected");
+ int init_inc = stride_con/cl->unrolled_count();
+ assert(init_inc != 0, "invalid loop increment");
+ Node* max_value = _igvn.intcon(stride_con - init_inc);
+ max_value = new AddINode(init, max_value);
+ register_new_node(max_value, predicate_proj);
+ // predicate on last value of first iteration (in case unrolling has already happened)
+ predicate_proj = add_range_check_predicate(loop, cl, predicate_proj, scale_con, offset, limit, stride_con, max_value);
+ assert(!skeleton_predicate_has_opaque(predicate_proj->in(0)->as_If()), "unexpected");
} else {
if (PrintOpto) {
tty->print_cr("missed RCE opportunity");
--- a/src/hotspot/share/opto/loopnode.hpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/opto/loopnode.hpp Tue Jan 15 22:54:09 2019 +0100
@@ -747,12 +747,14 @@
}
Node* cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop);
- void duplicate_predicates_helper(Node* predicate, Node* castii, IdealLoopTree* outer_loop,
+ void duplicate_predicates_helper(Node* predicate, Node* start, Node* end, IdealLoopTree* outer_loop,
LoopNode* outer_main_head, uint dd_main_head);
- void duplicate_predicates(CountedLoopNode* pre_head, Node* castii, IdealLoopTree* outer_loop,
+ void duplicate_predicates(CountedLoopNode* pre_head, Node* start, Node* end, IdealLoopTree* outer_loop,
LoopNode* outer_main_head, uint dd_main_head);
- Node* update_skeleton_predicate(Node* iff, Node* value, Node* predicate = NULL, Node* uncommon_proj = NULL,
- Node* current_proj = NULL, IdealLoopTree* outer_loop = NULL, Node* prev_proj = NULL);
+ Node* clone_skeleton_predicate(Node* iff, Node* value, Node* predicate, Node* uncommon_proj,
+ Node* current_proj, IdealLoopTree* outer_loop, Node* prev_proj);
+ bool skeleton_predicate_has_opaque(IfNode* iff);
+ void update_skeleton_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con);
void insert_loop_limit_check(ProjNode* limit_check_proj, Node* cmp_limit, Node* bol);
public:
@@ -1128,7 +1130,7 @@
Deoptimization::DeoptReason reason);
Node* add_range_check_predicate(IdealLoopTree* loop, CountedLoopNode* cl,
Node* predicate_proj, int scale_con, Node* offset,
- Node* limit, jint stride_con);
+ Node* limit, jint stride_con, Node* value);
// Helper function to collect predicate for eliminating the useless ones
void collect_potentially_useful_predicates(IdealLoopTree *loop, Unique_Node_List &predicate_opaque1);
@@ -1304,6 +1306,14 @@
bool identical_backtoback_ifs(Node *n);
bool can_split_if(Node *n_ctrl);
+ // Determine if a method is too big for a/another round of split-if, based on
+ // a magic (approximate) ratio derived from the equally magic constant 35000,
+ // previously used for this purpose (but without relating to the node limit).
+ bool must_throttle_split_if() {
+ uint threshold = C->max_node_limit() * 2 / 5;
+ return C->live_nodes() > threshold;
+ }
+
bool _created_loop_node;
public:
void set_created_loop_node() { _created_loop_node = true; }
--- a/src/hotspot/share/opto/loopopts.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/opto/loopopts.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -532,6 +532,12 @@
register_new_node(nn, get_ctrl(n));
_igvn.replace_node(n, nn);
return nn;
+ } else if ((adr1->in(AddPNode::Base) == adr4->in(AddPNode::Base)) &&
+ (adr2->in(AddPNode::Base) == adr3->in(AddPNode::Base))) {
+ nn = new MulAddS2INode(mul_in1, mul_in2, mul_in4, mul_in3);
+ register_new_node(nn, get_ctrl(n));
+ _igvn.replace_node(n, nn);
+ return nn;
}
}
}
@@ -1024,8 +1030,7 @@
}
}
- // Use same limit as split_if_with_blocks_post
- if( C->live_nodes() > 35000 ) return n; // Method too big
+ if (must_throttle_split_if()) return n;
// Split 'n' through the merge point if it is profitable
Node *phi = split_thru_phi( n, n_blk, policy );
@@ -1143,9 +1148,10 @@
return true;
}
-bool PhaseIdealLoop::can_split_if(Node *n_ctrl) {
- if (C->live_nodes() > 35000) {
- return false; // Method too big
+
+bool PhaseIdealLoop::can_split_if(Node* n_ctrl) {
+ if (must_throttle_split_if()) {
+ return false;
}
// Do not do 'split-if' if irreducible loops are present.
@@ -1462,12 +1468,13 @@
// Check for aggressive application of 'split-if' optimization,
// using basic block level info.
void PhaseIdealLoop::split_if_with_blocks(VectorSet &visited, Node_Stack &nstack, bool last_round) {
- Node *n = C->root();
- visited.set(n->_idx); // first, mark node as visited
+ Node* root = C->root();
+ visited.set(root->_idx); // first, mark root as visited
// Do pre-visit work for root
- n = split_if_with_blocks_pre( n );
- uint cnt = n->outcnt();
- uint i = 0;
+ Node* n = split_if_with_blocks_pre(root);
+ uint cnt = n->outcnt();
+ uint i = 0;
+
while (true) {
// Visit all children
if (i < cnt) {
@@ -1475,7 +1482,7 @@
++i;
if (use->outcnt() != 0 && !visited.test_set(use->_idx)) {
// Now do pre-visit work for this use
- use = split_if_with_blocks_pre( use );
+ use = split_if_with_blocks_pre(use);
nstack.push(n, i); // Save parent and next use's index.
n = use; // Process all children of current use.
cnt = use->outcnt();
@@ -1486,7 +1493,10 @@
// All of n's children have been processed, complete post-processing.
if (cnt != 0 && !n->is_Con()) {
assert(has_node(n), "no dead nodes");
- split_if_with_blocks_post( n, last_round );
+ split_if_with_blocks_post(n, last_round);
+ }
+ if (must_throttle_split_if()) {
+ nstack.clear();
}
if (nstack.is_empty()) {
// Finished all nodes on stack.
--- a/src/hotspot/share/opto/mulnode.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/opto/mulnode.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -1401,3 +1401,12 @@
return TypeF::make(fma(f1, f2, f3));
#endif
}
+
+//=============================================================================
+//------------------------------hash-------------------------------------------
+// Hash function for MulAddS2INode. Operation is commutative with commutative pairs.
+// The hash function must return the same value when edge swapping is performed.
+uint MulAddS2INode::hash() const {
+ return (uintptr_t)in(1) + (uintptr_t)in(2) + (uintptr_t)in(3) + (uintptr_t)in(4) + Opcode();
+}
+
--- a/src/hotspot/share/opto/mulnode.hpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/opto/mulnode.hpp Tue Jan 15 22:54:09 2019 +0100
@@ -289,6 +289,7 @@
// Multiply shorts into integers and add them.
// Semantics: I_OUT = S1 * S2 + S3 * S4
class MulAddS2INode : public Node {
+ virtual uint hash() const;
public:
MulAddS2INode(Node* in1, Node *in2, Node *in3, Node* in4) : Node(0, in1, in2, in3, in4) {}
virtual int Opcode() const;
--- a/src/hotspot/share/opto/superword.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/opto/superword.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -1445,7 +1445,7 @@
Node* t1 = s1->fast_out(i);
// Only allow operand swap on commuting operations
- if (!t1->is_Add() && !t1->is_Mul()) {
+ if (!t1->is_Add() && !t1->is_Mul() && !VectorNode::is_muladds2i(t1)) {
break;
}
@@ -1500,9 +1500,23 @@
if ((i1 == (3-i2)) && (u2->is_Add() || u2->is_Mul())) {
// Further analysis relies on operands position matching.
u2->swap_edges(i1, i2);
+ } else if (VectorNode::is_muladds2i(u2) && u1 != u2) {
+ if (i1 == 5 - i2) { // ((i1 == 3 && i2 == 2) || (i1 == 2 && i2 == 3) || (i1 == 1 && i2 == 4) || (i1 == 4 && i2 == 1))
+ u2->swap_edges(1, 2);
+ u2->swap_edges(3, 4);
+ }
+ if (i1 == 3 - i2 || i1 == 7 - i2) { // ((i1 == 1 && i2 == 2) || (i1 == 2 && i2 == 1) || (i1 == 3 && i2 == 4) || (i1 == 4 && i2 == 3))
+ u2->swap_edges(2, 3);
+ u2->swap_edges(1, 4);
+ }
+ return false; // Just swap the edges, the muladds2i nodes get packed in follow_use_defs
} else {
return false;
}
+ } else if (i1 == i2 && VectorNode::is_muladds2i(u2) && u1 != u2) {
+ u2->swap_edges(1, 3);
+ u2->swap_edges(2, 4);
+ return false; // Just swap the edges, the muladds2i nodes get packed in follow_use_defs
}
} while (i1 < ct);
return true;
--- a/src/hotspot/share/prims/jvm.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/prims/jvm.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -873,7 +873,6 @@
if (result != NULL) {
oop mirror = JNIHandles::resolve_non_null(result);
Klass* to_class = java_lang_Class::as_Klass(mirror);
- ClassLoaderData::class_loader_data(h_loader())->record_dependency(to_class);
}
if (log_is_enabled(Debug, class, resolve) && result != NULL) {
--- a/src/hotspot/share/runtime/sharedRuntime.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -1376,6 +1376,14 @@
}
#endif
+ // Do not patch call site for static call when the class is not
+ // fully initialized.
+ if (invoke_code == Bytecodes::_invokestatic &&
+ !callee_method->method_holder()->is_initialized()) {
+ assert(callee_method->method_holder()->is_linked(), "must be");
+ return callee_method;
+ }
+
// JSR 292 key invariant:
// If the resolved method is a MethodHandle invoke target, the call
// site must be a MethodHandle call site, because the lambda form might tail-call
--- a/src/java.base/share/classes/java/math/BigDecimal.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/share/classes/java/math/BigDecimal.java Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, 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
@@ -31,6 +31,7 @@
import static java.math.BigInteger.LONG_MASK;
import java.util.Arrays;
+import java.util.Objects;
/**
* Immutable, arbitrary-precision signed decimal numbers. A
@@ -424,9 +425,14 @@
* @since 1.5
*/
public BigDecimal(char[] in, int offset, int len, MathContext mc) {
- // protect against huge length.
- if (offset + len > in.length || offset < 0)
- throw new NumberFormatException("Bad offset or len arguments for char[] input.");
+ // protect against huge length, negative values, and integer overflow
+ try {
+ Objects.checkFromIndexSize(offset, len, in.length);
+ } catch (IndexOutOfBoundsException e) {
+ throw new NumberFormatException
+ ("Bad offset or len arguments for char[] input.");
+ }
+
// This is the primary string to BigDecimal constructor; all
// incoming strings end up here; it uses explicit (inline)
// parsing for speed and generates at most one intermediate
--- a/src/java.base/share/classes/java/math/BigInteger.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/share/classes/java/math/BigInteger.java Tue Jan 15 22:54:09 2019 +0100
@@ -307,10 +307,8 @@
public BigInteger(byte[] val, int off, int len) {
if (val.length == 0) {
throw new NumberFormatException("Zero length BigInteger");
- } else if ((off < 0) || (off >= val.length) || (len < 0) ||
- (len > val.length - off)) { // 0 <= off < val.length
- throw new IndexOutOfBoundsException();
}
+ Objects.checkFromIndexSize(off, len, val.length);
if (val[off] < 0) {
mag = makePositive(val, off, len);
@@ -395,12 +393,8 @@
public BigInteger(int signum, byte[] magnitude, int off, int len) {
if (signum < -1 || signum > 1) {
throw(new NumberFormatException("Invalid signum value"));
- } else if ((off < 0) || (len < 0) ||
- (len > 0 &&
- ((off >= magnitude.length) ||
- (len > magnitude.length - off)))) { // 0 <= off < magnitude.length
- throw new IndexOutOfBoundsException();
}
+ Objects.checkFromIndexSize(off, len, magnitude.length);
// stripLeadingZeroBytes() returns a zero length array if len == 0
this.mag = stripLeadingZeroBytes(magnitude, off, len);
@@ -1239,6 +1233,14 @@
private static final double LOG_TWO = Math.log(2.0);
static {
+ assert 0 < KARATSUBA_THRESHOLD
+ && KARATSUBA_THRESHOLD < TOOM_COOK_THRESHOLD
+ && TOOM_COOK_THRESHOLD < Integer.MAX_VALUE
+ && 0 < KARATSUBA_SQUARE_THRESHOLD
+ && KARATSUBA_SQUARE_THRESHOLD < TOOM_COOK_SQUARE_THRESHOLD
+ && TOOM_COOK_SQUARE_THRESHOLD < Integer.MAX_VALUE :
+ "Algorithm thresholds are inconsistent";
+
for (int i = 1; i <= MAX_CONSTANT; i++) {
int[] magnitude = new int[1];
magnitude[0] = i;
@@ -1562,6 +1564,18 @@
* @return {@code this * val}
*/
public BigInteger multiply(BigInteger val) {
+ return multiply(val, false);
+ }
+
+ /**
+ * Returns a BigInteger whose value is {@code (this * val)}. If
+ * the invocation is recursive certain overflow checks are skipped.
+ *
+ * @param val value to be multiplied by this BigInteger.
+ * @param isRecursion whether this is a recursive invocation
+ * @return {@code this * val}
+ */
+ private BigInteger multiply(BigInteger val, boolean isRecursion) {
if (val.signum == 0 || signum == 0)
return ZERO;
@@ -1589,6 +1603,63 @@
if ((xlen < TOOM_COOK_THRESHOLD) && (ylen < TOOM_COOK_THRESHOLD)) {
return multiplyKaratsuba(this, val);
} else {
+ //
+ // In "Hacker's Delight" section 2-13, p.33, it is explained
+ // that if x and y are unsigned 32-bit quantities and m and n
+ // are their respective numbers of leading zeros within 32 bits,
+ // then the number of leading zeros within their product as a
+ // 64-bit unsigned quantity is either m + n or m + n + 1. If
+ // their product is not to overflow, it cannot exceed 32 bits,
+ // and so the number of leading zeros of the product within 64
+ // bits must be at least 32, i.e., the leftmost set bit is at
+ // zero-relative position 31 or less.
+ //
+ // From the above there are three cases:
+ //
+ // m + n leftmost set bit condition
+ // ----- ---------------- ---------
+ // >= 32 x <= 64 - 32 = 32 no overflow
+ // == 31 x >= 64 - 32 = 32 possible overflow
+ // <= 30 x >= 64 - 31 = 33 definite overflow
+ //
+ // The "possible overflow" condition cannot be detected by
+ // examning data lengths alone and requires further calculation.
+ //
+ // By analogy, if 'this' and 'val' have m and n as their
+ // respective numbers of leading zeros within 32*MAX_MAG_LENGTH
+ // bits, then:
+ //
+ // m + n >= 32*MAX_MAG_LENGTH no overflow
+ // m + n == 32*MAX_MAG_LENGTH - 1 possible overflow
+ // m + n <= 32*MAX_MAG_LENGTH - 2 definite overflow
+ //
+ // Note however that if the number of ints in the result
+ // were to be MAX_MAG_LENGTH and mag[0] < 0, then there would
+ // be overflow. As a result the leftmost bit (of mag[0]) cannot
+ // be used and the constraints must be adjusted by one bit to:
+ //
+ // m + n > 32*MAX_MAG_LENGTH no overflow
+ // m + n == 32*MAX_MAG_LENGTH possible overflow
+ // m + n < 32*MAX_MAG_LENGTH definite overflow
+ //
+ // The foregoing leading zero-based discussion is for clarity
+ // only. The actual calculations use the estimated bit length
+ // of the product as this is more natural to the internal
+ // array representation of the magnitude which has no leading
+ // zero elements.
+ //
+ if (!isRecursion) {
+ // The bitLength() instance method is not used here as we
+ // are only considering the magnitudes as non-negative. The
+ // Toom-Cook multiplication algorithm determines the sign
+ // at its end from the two signum values.
+ if (bitLength(mag, mag.length) +
+ bitLength(val.mag, val.mag.length) >
+ 32L*MAX_MAG_LENGTH) {
+ reportOverflow();
+ }
+ }
+
return multiplyToomCook3(this, val);
}
}
@@ -1674,7 +1745,7 @@
int ystart = ylen - 1;
if (z == null || z.length < (xlen+ ylen))
- z = new int[xlen+ylen];
+ z = new int[xlen+ylen];
long carry = 0;
for (int j=ystart, k=ystart+1+xstart; j >= 0; j--, k--) {
@@ -1808,16 +1879,16 @@
BigInteger v0, v1, v2, vm1, vinf, t1, t2, tm1, da1, db1;
- v0 = a0.multiply(b0);
+ v0 = a0.multiply(b0, true);
da1 = a2.add(a0);
db1 = b2.add(b0);
- vm1 = da1.subtract(a1).multiply(db1.subtract(b1));
+ vm1 = da1.subtract(a1).multiply(db1.subtract(b1), true);
da1 = da1.add(a1);
db1 = db1.add(b1);
- v1 = da1.multiply(db1);
+ v1 = da1.multiply(db1, true);
v2 = da1.add(a2).shiftLeft(1).subtract(a0).multiply(
- db1.add(b2).shiftLeft(1).subtract(b0));
- vinf = a2.multiply(b2);
+ db1.add(b2).shiftLeft(1).subtract(b0), true);
+ vinf = a2.multiply(b2, true);
// The algorithm requires two divisions by 2 and one by 3.
// All divisions are known to be exact, that is, they do not produce
@@ -1983,6 +2054,17 @@
* @return {@code this<sup>2</sup>}
*/
private BigInteger square() {
+ return square(false);
+ }
+
+ /**
+ * Returns a BigInteger whose value is {@code (this<sup>2</sup>)}. If
+ * the invocation is recursive certain overflow checks are skipped.
+ *
+ * @param isRecursion whether this is a recursive invocation
+ * @return {@code this<sup>2</sup>}
+ */
+ private BigInteger square(boolean isRecursion) {
if (signum == 0) {
return ZERO;
}
@@ -1995,6 +2077,15 @@
if (len < TOOM_COOK_SQUARE_THRESHOLD) {
return squareKaratsuba();
} else {
+ //
+ // For a discussion of overflow detection see multiply()
+ //
+ if (!isRecursion) {
+ if (bitLength(mag, mag.length) > 16L*MAX_MAG_LENGTH) {
+ reportOverflow();
+ }
+ }
+
return squareToomCook3();
}
}
@@ -2146,13 +2237,13 @@
a0 = getToomSlice(k, r, 2, len);
BigInteger v0, v1, v2, vm1, vinf, t1, t2, tm1, da1;
- v0 = a0.square();
+ v0 = a0.square(true);
da1 = a2.add(a0);
- vm1 = da1.subtract(a1).square();
+ vm1 = da1.subtract(a1).square(true);
da1 = da1.add(a1);
- v1 = da1.square();
- vinf = a2.square();
- v2 = da1.add(a2).shiftLeft(1).subtract(a0).square();
+ v1 = da1.square(true);
+ vinf = a2.square(true);
+ v2 = da1.add(a2).shiftLeft(1).subtract(a0).square(true);
// The algorithm requires two divisions by 2 and one by 3.
// All divisions are known to be exact, that is, they do not produce
@@ -2323,10 +2414,11 @@
// The remaining part can then be exponentiated faster. The
// powers of two will be multiplied back at the end.
int powersOfTwo = partToSquare.getLowestSetBit();
- long bitsToShift = (long)powersOfTwo * exponent;
- if (bitsToShift > Integer.MAX_VALUE) {
+ long bitsToShiftLong = (long)powersOfTwo * exponent;
+ if (bitsToShiftLong > Integer.MAX_VALUE) {
reportOverflow();
}
+ int bitsToShift = (int)bitsToShiftLong;
int remainingBits;
@@ -2336,9 +2428,9 @@
remainingBits = partToSquare.bitLength();
if (remainingBits == 1) { // Nothing left but +/- 1?
if (signum < 0 && (exponent&1) == 1) {
- return NEGATIVE_ONE.shiftLeft(powersOfTwo*exponent);
+ return NEGATIVE_ONE.shiftLeft(bitsToShift);
} else {
- return ONE.shiftLeft(powersOfTwo*exponent);
+ return ONE.shiftLeft(bitsToShift);
}
}
} else {
@@ -2383,13 +2475,16 @@
if (bitsToShift + scaleFactor <= 62) { // Fits in long?
return valueOf((result << bitsToShift) * newSign);
} else {
- return valueOf(result*newSign).shiftLeft((int) bitsToShift);
+ return valueOf(result*newSign).shiftLeft(bitsToShift);
}
- }
- else {
+ } else {
return valueOf(result*newSign);
}
} else {
+ if ((long)bitLength() * exponent / Integer.SIZE > MAX_MAG_LENGTH) {
+ reportOverflow();
+ }
+
// Large number algorithm. This is basically identical to
// the algorithm above, but calls multiply() and square()
// which may use more efficient algorithms for large numbers.
@@ -2409,7 +2504,7 @@
// Multiply back the (exponentiated) powers of two (quickly,
// by shifting left)
if (powersOfTwo > 0) {
- answer = answer.shiftLeft(powersOfTwo*exponent);
+ answer = answer.shiftLeft(bitsToShift);
}
if (signum < 0 && (exponent&1) == 1) {
@@ -3584,7 +3679,7 @@
for (int i=1; i< len && pow2; i++)
pow2 = (mag[i] == 0);
- n = (pow2 ? magBitLength -1 : magBitLength);
+ n = (pow2 ? magBitLength - 1 : magBitLength);
} else {
n = magBitLength;
}
--- a/src/java.base/share/classes/javax/crypto/spec/GCMParameterSpec.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/share/classes/javax/crypto/spec/GCMParameterSpec.java Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, 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
@@ -120,7 +120,7 @@
// Input sanity check
if ((src == null) ||(len < 0) || (offset < 0)
- || ((len + offset) > src.length)) {
+ || (len > (src.length - offset))) {
throw new IllegalArgumentException("Invalid buffer arguments");
}
--- a/src/java.base/share/classes/sun/net/www/protocol/http/ntlm/NTLMAuthenticationCallback.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/share/classes/sun/net/www/protocol/http/ntlm/NTLMAuthenticationCallback.java Tue Jan 15 22:54:09 2019 +0100
@@ -33,8 +33,7 @@
* credentials without prompting) should only be tried with trusted sites.
*/
public abstract class NTLMAuthenticationCallback {
- private static volatile NTLMAuthenticationCallback callback =
- new DefaultNTLMAuthenticationCallback();
+ private static volatile NTLMAuthenticationCallback callback;
public static void setNTLMAuthenticationCallback(
NTLMAuthenticationCallback callback) {
@@ -50,10 +49,5 @@
* transparent Authentication.
*/
public abstract boolean isTrustedSite(URL url);
-
- static class DefaultNTLMAuthenticationCallback extends NTLMAuthenticationCallback {
- @Override
- public boolean isTrustedSite(URL url) { return true; }
- }
}
--- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Tue Jan 15 22:54:09 2019 +0100
@@ -624,11 +624,10 @@
{
// Untrusted target: Use a newly-erased buffer
int c = Math.min(icount, TRANSFER_SIZE);
- ByteBuffer bb = Util.getTemporaryDirectBuffer(c);
+ ByteBuffer bb = ByteBuffer.allocate(c);
long tw = 0; // Total bytes written
long pos = position;
try {
- Util.erase(bb);
while (tw < icount) {
bb.limit(Math.min((int)(icount - tw), TRANSFER_SIZE));
int nr = read(bb, pos);
@@ -649,8 +648,6 @@
if (tw > 0)
return tw;
throw x;
- } finally {
- Util.releaseTemporaryDirectBuffer(bb);
}
}
@@ -734,11 +731,10 @@
{
// Untrusted target: Use a newly-erased buffer
int c = (int)Math.min(count, TRANSFER_SIZE);
- ByteBuffer bb = Util.getTemporaryDirectBuffer(c);
+ ByteBuffer bb = ByteBuffer.allocate(c);
long tw = 0; // Total bytes written
long pos = position;
try {
- Util.erase(bb);
while (tw < count) {
bb.limit((int)Math.min((count - tw), (long)TRANSFER_SIZE));
// ## Bug: Will block reading src if this channel
@@ -759,8 +755,6 @@
if (tw > 0)
return tw;
throw x;
- } finally {
- Util.releaseTemporaryDirectBuffer(bb);
}
}
--- a/src/java.base/share/conf/net.properties Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/share/conf/net.properties Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
############################################################
-# Default Networking Configuration File
+# Default Networking Configuration File
#
# This file may contain default values for the networking system properties.
# These values are only used when the system properties are not specified
@@ -110,3 +110,23 @@
#
# jdk.httpclient.allowRestrictedHeaders=host
#
+#
+# Transparent NTLM HTTP authentication mode on Windows. Transparent authentication
+# can be used for the NTLM scheme, where the security credentials based on the
+# currently logged in user's name and password can be obtained directly from the
+# operating system, without prompting the user. This property has three possible
+# values which regulate the behavior as shown below. Other unrecognized values
+# are handled the same as 'disabled'. Note, that NTLM is not considered to be a
+# strongly secure authentication scheme and care should be taken before enabling
+# this mechanism.
+#
+# Transparent authentication never used.
+#jdk.http.ntlm.transparentAuth=disabled
+#
+# Enabled for all hosts.
+#jdk.http.ntlm.transparentAuth=allHosts
+#
+# Enabled for hosts that are trusted in Windows Internet settings
+#jdk.http.ntlm.transparentAuth=trustedHosts
+#
+jdk.http.ntlm.transparentAuth=disabled
--- a/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Tue Jan 15 22:54:09 2019 +0100
@@ -93,10 +93,13 @@
/**
* Returns true if the given site is trusted, i.e. we can try
- * transparent Authentication.
+ * transparent Authentication. Shouldn't be called since
+ * capability not supported on Unix
*/
public static boolean isTrustedSite(URL url) {
- return NTLMAuthCallback.isTrustedSite(url);
+ if (NTLMAuthCallback != null)
+ return NTLMAuthCallback.isTrustedSite(url);
+ return false;
}
private void init0() {
--- a/src/java.base/unix/native/libnet/net_util_md.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/unix/native/libnet/net_util_md.c Tue Jan 15 22:54:09 2019 +0100
@@ -584,6 +584,8 @@
if (loRoutesTemp == 0) {
free(loRoutes);
+ loRoutes = NULL;
+ nRoutes = 0;
fclose (f);
return;
}
--- a/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Tue Jan 15 22:54:09 2019 +0100
@@ -32,6 +32,7 @@
import java.net.URL;
import java.util.Objects;
import java.util.Properties;
+import sun.net.NetProperties;
import sun.net.www.HeaderParser;
import sun.net.www.protocol.http.AuthenticationInfo;
import sun.net.www.protocol.http.AuthScheme;
@@ -56,11 +57,33 @@
private static final String defaultDomain;
/* Whether cache is enabled for NTLM */
private static final boolean ntlmCache;
+
+ enum TransparentAuth {
+ DISABLED, // disable for all hosts (default)
+ TRUSTED_HOSTS, // use Windows trusted hosts settings
+ ALL_HOSTS // attempt for all hosts
+ }
+
+ private static final TransparentAuth authMode;
+
static {
Properties props = GetPropertyAction.privilegedGetProperties();
defaultDomain = props.getProperty("http.auth.ntlm.domain", "domain");
String ntlmCacheProp = props.getProperty("jdk.ntlm.cache", "true");
ntlmCache = Boolean.parseBoolean(ntlmCacheProp);
+ String modeProp = java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<String>() {
+ public String run() {
+ return NetProperties.get("jdk.http.ntlm.transparentAuth");
+ }
+ });
+
+ if ("trustedHosts".equalsIgnoreCase(modeProp))
+ authMode = TransparentAuth.TRUSTED_HOSTS;
+ else if ("allHosts".equalsIgnoreCase(modeProp))
+ authMode = TransparentAuth.ALL_HOSTS;
+ else
+ authMode = TransparentAuth.DISABLED;
}
private void init0() {
@@ -166,9 +189,21 @@
* transparent Authentication.
*/
public static boolean isTrustedSite(URL url) {
- return NTLMAuthCallback.isTrustedSite(url);
+ if (NTLMAuthCallback != null)
+ return NTLMAuthCallback.isTrustedSite(url);
+
+ switch (authMode) {
+ case TRUSTED_HOSTS:
+ return isTrustedSite(url.toString());
+ case ALL_HOSTS:
+ return true;
+ default:
+ return false;
+ }
}
+ static native boolean isTrustedSite(String url);
+
/**
* Not supported. Must use the setHeaders() method
*/
@@ -218,5 +253,4 @@
return false;
}
}
-
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/windows/native/libnet/NTLMAuthentication.c Tue Jan 15 22:54:09 2019 +0100
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+#include <windows.h>
+#include "jni_util.h"
+#include <urlmon.h>
+
+JNIEXPORT jboolean JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSite(JNIEnv *env, jclass clazz, jstring url )
+{
+
+ HRESULT hr;
+ DWORD dwZone;
+ DWORD pPolicy = 0;
+ IInternetSecurityManager *spSecurityManager;
+ jboolean ret;
+
+ // Create IInternetSecurityManager
+ hr = CoInternetCreateSecurityManager(NULL, &spSecurityManager, (DWORD)0);
+ if (FAILED(hr)) {
+ return JNI_FALSE;
+ }
+
+ const LPCWSTR bstrURL = (LPCWSTR)((*env)->GetStringChars(env, url, NULL));
+ if (bstrURL == NULL) {
+ if (!(*env)->ExceptionCheck(env))
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ spSecurityManager->lpVtbl->Release(spSecurityManager);
+ return JNI_FALSE;
+ }
+
+ // Determines the policy for the URLACTION_CREDENTIALS_USE action and display
+ // a user interface, if the policy indicates that the user should be queried
+ hr = spSecurityManager->lpVtbl->ProcessUrlAction(
+ spSecurityManager,
+ bstrURL,
+ URLACTION_CREDENTIALS_USE,
+ (LPBYTE)&pPolicy,
+ sizeof(DWORD), 0, 0, 0, 0);
+
+ if (FAILED(hr)) {
+ ret = JNI_FALSE;
+ goto cleanupAndReturn;
+ }
+
+ // If these two User Authentication Logon options is selected
+ // Anonymous logon
+ // Prompt for user name and password
+ if (pPolicy == URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY ||
+ pPolicy == URLPOLICY_CREDENTIALS_MUST_PROMPT_USER) {
+ ret = JNI_FALSE;
+ goto cleanupAndReturn;
+ }
+
+ // Option "Automatic logon with current user name and password" is selected
+ if (pPolicy == URLPOLICY_CREDENTIALS_SILENT_LOGON_OK) {
+ ret = JNI_TRUE;
+ goto cleanupAndReturn;
+ }
+
+ // Option "Automatic logon only in intranet zone" is selected
+ if (pPolicy == URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT) {
+
+ // Gets the zone index from the specified URL
+ hr = spSecurityManager->lpVtbl->MapUrlToZone(
+ spSecurityManager, bstrURL, &dwZone, 0);
+ if (FAILED(hr)) {
+ ret = JNI_FALSE;
+ goto cleanupAndReturn;
+ }
+
+ // Check if the URL is in Local or Intranet zone
+ if (dwZone == URLZONE_INTRANET || dwZone == URLZONE_LOCAL_MACHINE) {
+ ret = JNI_TRUE;
+ goto cleanupAndReturn;
+ }
+ }
+ ret = JNI_FALSE;
+
+cleanupAndReturn:
+ (*env)->ReleaseStringChars(env, url, bstrURL);
+ spSecurityManager->lpVtbl->Release(spSecurityManager);
+ return ret;
+}
--- a/src/java.base/windows/native/libnet/NetworkInterface.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/windows/native/libnet/NetworkInterface.c Tue Jan 15 22:54:09 2019 +0100
@@ -273,7 +273,7 @@
// But in rare case it fails, we allow 'char' to be displayed
curr->displayName = (char *)malloc(ifrowP->dwDescrLen + 1);
} else {
- curr->displayName = (wchar_t *)malloc(wlen*(sizeof(wchar_t))+1);
+ curr->displayName = (wchar_t *)malloc((wlen+1)*sizeof(wchar_t));
}
curr->name = (char *)malloc(strlen(dev_name) + 1);
@@ -316,7 +316,7 @@
free(curr);
return -1;
} else {
- curr->displayName[wlen*(sizeof(wchar_t))] = '\0';
+ ((wchar_t *)curr->displayName)[wlen] = L'\0';
curr->dNameIsUnicode = TRUE;
}
}
--- a/src/java.base/windows/native/libnio/ch/DatagramDispatcher.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/windows/native/libnio/ch/DatagramDispatcher.c Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -95,6 +95,10 @@
jint fd = fdval(env, fdo);
struct iovec *iovp = (struct iovec *)address;
WSABUF *bufs = malloc(len * sizeof(WSABUF));
+ if (bufs == NULL) {
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return IOS_THROWN;
+ }
/* copy iovec into WSABUF */
for(i=0; i<len; i++) {
@@ -182,6 +186,10 @@
jint fd = fdval(env, fdo);
struct iovec *iovp = (struct iovec *)address;
WSABUF *bufs = malloc(len * sizeof(WSABUF));
+ if (bufs == NULL) {
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return IOS_THROWN;
+ }
/* copy iovec into WSABUF */
for(i=0; i<len; i++) {
--- a/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -219,6 +219,10 @@
/* Prepare corresponding buffer if needed, and then read */
if (bytesToRead > WAKEUP_SOCKET_BUF_SIZE) {
char* buf = (char*)malloc(bytesToRead);
+ if (buf == NULL) {
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return;
+ }
recv(scinFd, buf, bytesToRead, 0);
free(buf);
} else {
--- a/src/java.desktop/share/classes/java/awt/Robot.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.desktop/share/classes/java/awt/Robot.java Tue Jan 15 22:54:09 2019 +0100
@@ -394,6 +394,7 @@
* @return Color of the pixel
*/
public synchronized Color getPixelColor(int x, int y) {
+ checkScreenCaptureAllowed();
AffineTransform tx = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration().getDefaultTransform();
--- a/src/java.desktop/share/native/libjavajpeg/jmemmgr.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.desktop/share/native/libjavajpeg/jmemmgr.c Tue Jan 15 22:54:09 2019 +0100
@@ -406,6 +406,9 @@
JDIMENSION rowsperchunk, currow, i;
long ltemp;
+ if (samplesperrow == 0) {
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+ }
/* Calculate max # of rows allowed in one allocation chunk */
ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
((long) samplesperrow * SIZEOF(JSAMPLE));
@@ -454,6 +457,10 @@
JDIMENSION rowsperchunk, currow, i;
long ltemp;
+ if (blocksperrow == 0) {
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+ }
+
/* Calculate max # of rows allowed in one allocation chunk */
ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
((long) blocksperrow * SIZEOF(JBLOCK));
--- a/src/java.desktop/share/native/liblcms/cmscgats.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.desktop/share/native/liblcms/cmscgats.c Tue Jan 15 22:54:09 2019 +0100
@@ -1535,10 +1535,16 @@
t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
- t-> Data = (char**)AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * ((cmsUInt32Number) t->nPatches + 1) *sizeof (char*));
- if (t->Data == NULL) {
-
- SynError(it8, "AllocateDataSet: Unable to allocate data array");
+ if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe)
+ {
+ SynError(it8, "AllocateDataSet: too much data");
+ }
+ else {
+ t->Data = (char**)AllocChunk(it8, ((cmsUInt32Number)t->nSamples + 1) * ((cmsUInt32Number)t->nPatches + 1) * sizeof(char*));
+ if (t->Data == NULL) {
+
+ SynError(it8, "AllocateDataSet: Unable to allocate data array");
+ }
}
}
--- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, 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
@@ -161,6 +161,7 @@
int len;
char *stock_id_str = NULL;
char *detail_str = NULL;
+ jboolean result = JNI_FALSE;
if (stock_id == NULL)
{
@@ -190,23 +191,15 @@
(*env)->GetStringUTFRegion(env, detail, 0, len, detail_str);
}
- if (!init_method(env, this) ) {
- free(stock_id_str);
- if (detail_str != NULL) {
- free(detail_str);
- }
- return JNI_FALSE;
+ if (init_method(env, this)) {
+ result = gtk->get_icon_data(env, widget_type, stock_id_str,
+ icon_size, text_direction, detail_str,
+ icon_upcall_method, this);
}
- jboolean result = gtk->get_icon_data(env, widget_type, stock_id_str,
- icon_size, text_direction, detail_str,
- icon_upcall_method, this);
-
/* Release the strings we've allocated. */
free(stock_id_str);
- if (detail_str != NULL)
- {
- free(detail_str);
- }
+ free(detail_str);
+
return result;
#else /* HEADLESS */
return JNI_FALSE;
--- a/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -962,9 +962,10 @@
if (!present) {
defIndices[0] = papers[0];
}
- if (papers != NULL) {
- free((char*)papers);
- }
+ }
+ // If DeviceCapabilities fails, then also free paper allocation
+ if (papers != NULL) {
+ free((char*)papers);
}
}
RESTORE_CONTROLWORD
--- a/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018 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
@@ -23,6 +23,7 @@
* questions.
*/
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -50,6 +51,10 @@
} else {
int len = last - path;
char* str = (char*)malloc(len+1);
+ if (str == NULL) {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
+ }
if (len > 0) {
memcpy(str, path, len);
}
@@ -80,6 +85,10 @@
if (n == 0) return strdup("/");
sb = (char*)malloc(strlen(pathname)+1);
+ if (sb == NULL) {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
+ }
sbLen = 0;
if (off > 0) {
@@ -128,6 +137,10 @@
len = parentEnd + cn - childStart;
if (child[0] == slash) {
theChars = (char*)malloc(len+1);
+ if (theChars == NULL) {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
+ }
if (parentEnd > 0)
memcpy(theChars, parent, parentEnd);
if (cn > 0)
@@ -135,6 +148,10 @@
theChars[len] = '\0';
} else {
theChars = (char*)malloc(len+2);
+ if (theChars == NULL) {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
+ }
if (parentEnd > 0)
memcpy(theChars, parent, parentEnd);
theChars[parentEnd] = slash;
@@ -150,10 +167,13 @@
if (len > 1 && path[len-1] == slash) {
// "/foo/" --> "/foo", but "/" --> "/"
char* str = (char*)malloc(len);
- if (str != NULL) {
- memcpy(str, path, len-1);
- str[len-1] = '\0';
+ if (str == NULL)
+ {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
}
+ memcpy(str, path, len-1);
+ str[len-1] = '\0';
return str;
} else {
return (char*)path;
--- a/src/java.instrument/windows/native/libinstrument/FileSystemSupport_md.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.instrument/windows/native/libinstrument/FileSystemSupport_md.c Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018 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
@@ -23,6 +23,7 @@
* questions.
*/
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
@@ -66,6 +67,10 @@
} else {
int len = (int)(last - path);
char* str = (char*)malloc(len+1);
+ if (str == NULL) {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
+ }
if (len > 0) {
memcpy(str, path, len);
}
@@ -135,6 +140,10 @@
if (off < 3) off = 0; /* Avoid fencepost cases with UNC pathnames */
sb = (char*)malloc(len+1);
+ if (sb == NULL) {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
+ }
sbLen = 0;
if (off == 0) {
@@ -261,11 +270,19 @@
if (child[childStart] == slash) {
theChars = (char*)malloc(len+1);
+ if (theChars == NULL) {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
+ }
memcpy(theChars, parent, parentEnd);
memcpy(theChars+parentEnd, child+childStart, (cn-childStart));
theChars[len] = '\0';
} else {
theChars = (char*)malloc(len+2);
+ if (theChars == NULL) {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
+ }
memcpy(theChars, parent, parentEnd);
theChars[parentEnd] = slash;
memcpy(theChars+parentEnd+1, child+childStart, (cn-childStart));
@@ -320,10 +337,12 @@
return (char*)path;
} else {
char* p = (char*)malloc(len+1);
- if (p != NULL) {
- memcpy(p, path+start, len);
- p[len] = '\0';
+ if (p == NULL) {
+ fprintf(stderr, "OOM error in native tmp buffer allocation");
+ return NULL;
}
+ memcpy(p, path+start, len);
+ p[len] = '\0';
return p;
}
}
--- a/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c Tue Jan 15 22:54:09 2019 +0100
@@ -78,7 +78,8 @@
BOOL PackageConnectLookup(PHANDLE,PULONG);
-NTSTATUS ConstructTicketRequest(UNICODE_STRING DomainName,
+NTSTATUS ConstructTicketRequest(JNIEnv *env,
+ UNICODE_STRING DomainName,
PKERB_RETRIEVE_TKT_REQUEST *outRequest,
ULONG *outSize);
@@ -104,6 +105,8 @@
jobject BuildTicketFlags(JNIEnv *env, PULONG flags);
jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime);
+void ThrowOOME(JNIEnv *env, const char *szMessage);
+
/*
* Class: sun_security_krb5_KrbCreds
* Method: JNI_OnLoad
@@ -497,7 +500,7 @@
}
// use domain to request Ticket
- Status = ConstructTicketRequest(msticket->TargetDomainName,
+ Status = ConstructTicketRequest(env, msticket->TargetDomainName,
&pTicketRequest, &requestSize);
if (!LSA_SUCCESS(Status)) {
ShowNTError("ConstructTicketRequest status", Status);
@@ -691,7 +694,7 @@
}
static NTSTATUS
-ConstructTicketRequest(UNICODE_STRING DomainName,
+ConstructTicketRequest(JNIEnv *env, UNICODE_STRING DomainName,
PKERB_RETRIEVE_TKT_REQUEST *outRequest, ULONG *outSize)
{
NTSTATUS Status;
@@ -738,8 +741,10 @@
pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST)
LocalAlloc(LMEM_ZEROINIT, RequestSize);
- if (!pTicketRequest)
+ if (!pTicketRequest) {
+ ThrowOOME(env, "Can't allocate memory for ticket");
return GetLastError();
+ }
//
// Concatenate the target prefix with the previous response's
@@ -896,7 +901,7 @@
jbyteArray ary;
ary = (*env)->NewByteArray(env,encodedTicketSize);
- if ((*env)->ExceptionOccurred(env)) {
+ if (ary == NULL) {
return (jobject) NULL;
}
@@ -942,6 +947,10 @@
realm = (WCHAR *) LocalAlloc(LMEM_ZEROINIT,
((domainName.Length)*sizeof(WCHAR) + sizeof(UNICODE_NULL)));
+ if (realm == NULL) {
+ ThrowOOME(env, "Can't allocate memory for realm");
+ return NULL;
+ }
wcsncpy(realm, domainName.Buffer, domainName.Length/sizeof(WCHAR));
if (native_debug) {
@@ -1016,6 +1025,9 @@
}
ary = (*env)->NewByteArray(env,cryptoKey->Length);
+ if (ary == NULL) {
+ return (jobject) NULL;
+ }
(*env)->SetByteArrayRegion(env, ary, (jsize) 0, cryptoKey->Length,
(jbyte *)cryptoKey->Value);
if ((*env)->ExceptionOccurred(env)) {
@@ -1038,6 +1050,9 @@
ULONG nlflags = htonl(*flags);
ary = (*env)->NewByteArray(env, sizeof(*flags));
+ if (ary == NULL) {
+ return (jobject) NULL;
+ }
(*env)->SetByteArrayRegion(env, ary, (jsize) 0, sizeof(*flags),
(jbyte *)&nlflags);
if ((*env)->ExceptionOccurred(env)) {
@@ -1090,3 +1105,10 @@
}
return kerberosTime;
}
+
+void ThrowOOME(JNIEnv *env, const char *szMessage) {
+ jclass exceptionClazz = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
+ if (exceptionClazz != NULL) {
+ (*env)->ThrowNew(env, exceptionClazz, szMessage);
+ }
+}
--- a/src/jdk.accessibility/windows/native/libwindowsaccessbridge/AccessBridgeMessageQueue.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/jdk.accessibility/windows/native/libwindowsaccessbridge/AccessBridgeMessageQueue.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, 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
@@ -32,6 +32,7 @@
#include "AccessBridgePackages.h" // for debugging only
#include <windows.h>
#include <malloc.h>
+#include <new>
DEBUG_CODE(extern HWND theDialogWindow);
extern "C" {
@@ -46,6 +47,9 @@
next = (AccessBridgeQueueElement *) 0;
previous = (AccessBridgeQueueElement *) 0;
buffer = (char *) malloc(bufsize);
+ if (buffer == NULL) {
+ throw std::bad_alloc();
+ }
memcpy(buffer, buf, bufsize);
}
--- a/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c Tue Jan 15 16:40:31 2019 -0500
+++ b/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
@@ -75,18 +75,20 @@
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
- (JNIEnv *env, jobject obj, jstring jPkcs11ModulePath, jstring jGetFunctionList)
+ (JNIEnv *env, jobject obj, jstring jPkcs11ModulePath,
+ jstring jGetFunctionList)
{
HINSTANCE hModule;
CK_C_GetFunctionList C_GetFunctionList;
- CK_RV rv;
+ CK_RV rv = CK_ASSERT_OK;
ModuleData *moduleData;
jobject globalPKCS11ImplementationReference;
- LPVOID lpMsgBuf;
- char *exceptionMessage;
+ LPVOID lpMsgBuf = NULL;
+ char *exceptionMessage = NULL;
const char *getFunctionListStr;
- const char *libraryNameStr = (*env)->GetStringUTFChars(env, jPkcs11ModulePath, 0);
+ const char *libraryNameStr = (*env)->GetStringUTFChars(env,
+ jPkcs11ModulePath, 0);
TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr);
@@ -106,21 +108,24 @@
0,
NULL
);
- exceptionMessage = (char *) malloc(sizeof(char) * (strlen((LPTSTR) lpMsgBuf) + strlen(libraryNameStr) + 1));
+ exceptionMessage = (char *) malloc(sizeof(char) *
+ (strlen((LPTSTR) lpMsgBuf) + strlen(libraryNameStr) + 1));
+ if (exceptionMessage == NULL) {
+ throwOutOfMemoryError(env, 0);
+ goto cleanup;
+ }
strcpy(exceptionMessage, (LPTSTR) lpMsgBuf);
strcat(exceptionMessage, libraryNameStr);
throwIOException(env, (LPTSTR) exceptionMessage);
- /* Free the buffer. */
- free(exceptionMessage);
- LocalFree(lpMsgBuf);
- return;
+ goto cleanup;
}
/*
* Get function pointer to C_GetFunctionList
*/
getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0);
- C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule, getFunctionListStr);
+ C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule,
+ getFunctionListStr);
(*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr);
if (C_GetFunctionList == NULL) {
FormatMessage(
@@ -135,24 +140,37 @@
NULL
);
throwIOException(env, (LPTSTR) lpMsgBuf);
- /* Free the buffer. */
- LocalFree( lpMsgBuf );
- return;
+ goto cleanup;
}
/*
* Get function pointers to all PKCS #11 functions
*/
moduleData = (ModuleData *) malloc(sizeof(ModuleData));
+ if (moduleData == NULL) {
+ throwOutOfMemoryError(env, 0);
+ goto cleanup;
+ }
moduleData->hModule = hModule;
moduleData->applicationMutexHandler = NULL;
rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr));
globalPKCS11ImplementationReference = (*env)->NewGlobalRef(env, obj);
putModuleEntry(env, globalPKCS11ImplementationReference, moduleData);
- (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr);
TRACE0("FINISHED\n");
+cleanup:
+ /* Free up allocated buffers we no longer need */
+ if (lpMsgBuf != NULL) {
+ LocalFree( lpMsgBuf );
+ }
+ if (libraryNameStr != NULL) {
+ (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr);
+ }
+ if (exceptionMessage != NULL) {
+ free(exceptionMessage);
+ }
+
if(ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
}
--- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyStore.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKeyStore.java Tue Jan 15 22:54:09 2019 +0100
@@ -754,7 +754,8 @@
new KeyEntry(alias, null, certChain));
} catch (Throwable e) {
// Ignore the exception and skip this entry
- // TODO - throw CertificateException?
+ // If e is thrown, remember to deal with it in
+ // native code.
}
}
@@ -781,7 +782,8 @@
certChain));
} catch (Throwable e) {
// Ignore the exception and skip this entry
- // TODO - throw CertificateException?
+ // If e is thrown, remember to deal with it in
+ // native code.
}
}
@@ -809,10 +811,14 @@
certCollection.addAll(c);
} catch (CertificateException e) {
// Ignore the exception and skip this certificate
- // TODO - throw CertificateException?
- } catch (Throwable te) {
+ // If e is thrown, remember to deal with it in
+ // native code.
+ }
+ catch (Throwable te)
+ {
// Ignore the exception and skip this certificate
- // TODO - throw CertificateException?
+ // If e is thrown, remember to deal with it in
+ // native code.
}
}
--- a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Tue Jan 15 16:40:31 2019 -0500
+++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Tue Jan 15 22:54:09 2019 +0100
@@ -544,6 +544,15 @@
// Create ArrayList to store certs in each chain
jobject jArrayList =
env->NewObject(clazzArrayList, mNewArrayList);
+ if (jArrayList == NULL) {
+ __leave;
+ }
+
+ // Cleanup the previous allocated name
+ if (pszNameString) {
+ delete [] pszNameString;
+ pszNameString = NULL;
+ }
for (unsigned int j=0; j < rgpChain->cElement; j++)
{
@@ -582,6 +591,9 @@
// Allocate and populate byte array
jbyteArray byteArray = env->NewByteArray(cbCertEncoded);
+ if (byteArray == NULL) {
+ __leave;
+ }
env->SetByteArrayRegion(byteArray, 0, cbCertEncoded,
(jbyte*) pbCertEncoded);
@@ -590,49 +602,67 @@
env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
}
- PP("%s: %s", pszNameString, pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
- if (bHasNoPrivateKey)
- {
- // Generate certificate chain and store into cert chain
- // collection
- env->CallVoidMethod(obj, mGenCertChain,
- env->NewStringUTF(pszNameString),
- jArrayList);
- }
- else
+ // Usually pszNameString should be non-NULL. It's either
+ // the friendly name or an element from the subject name
+ // or SAN.
+ if (pszNameString)
{
- if (hUserKey) {
- // Only accept RSA for CAPI
- DWORD dwData = CALG_RSA_KEYX;
- DWORD dwSize = sizeof(DWORD);
- ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated
- &dwSize, NULL);
- if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
- {
- // Generate RSA certificate chain and store into cert
- // chain collection
- env->CallVoidMethod(obj, mGenKeyAndCertChain,
- 1,
- env->NewStringUTF(pszNameString),
- (jlong) hCryptProv, (jlong) hUserKey,
- dwPublicKeyLength, jArrayList);
+ PP("%s: %s", pszNameString, pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
+ if (bHasNoPrivateKey)
+ {
+ // Generate certificate chain and store into cert chain
+ // collection
+ jstring name = env->NewStringUTF(pszNameString);
+ if (name == NULL) {
+ __leave;
}
- } else {
- // Only accept EC for CNG
- BYTE buffer[32];
- DWORD len = 0;
- if (::NCryptGetProperty(
- hCryptProv, NCRYPT_ALGORITHM_PROPERTY,
- (PBYTE)buffer, 32, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
- if (buffer[0] == 'E' && buffer[2] == 'C'
- && (dwPublicKeyLength == 256
- || dwPublicKeyLength == 384
- || dwPublicKeyLength == 521)) {
+ env->CallVoidMethod(obj, mGenCertChain,
+ name,
+ jArrayList);
+ }
+ else
+ {
+ if (hUserKey) {
+ // Only accept RSA for CAPI
+ DWORD dwData = CALG_RSA_KEYX;
+ DWORD dwSize = sizeof(DWORD);
+ ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated
+ &dwSize, NULL);
+ if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
+ {
+ // Generate RSA certificate chain and store into cert
+ // chain collection
+ jstring name = env->NewStringUTF(pszNameString);
+ if (name == NULL) {
+ __leave;
+ }
env->CallVoidMethod(obj, mGenKeyAndCertChain,
- 0,
- env->NewStringUTF(pszNameString),
- (jlong) hCryptProv, 0,
- dwPublicKeyLength, jArrayList);
+ 1,
+ name,
+ (jlong) hCryptProv, (jlong) hUserKey,
+ dwPublicKeyLength, jArrayList);
+ }
+ } else {
+ // Only accept EC for CNG
+ BYTE buffer[32];
+ DWORD len = 0;
+ if (::NCryptGetProperty(
+ hCryptProv, NCRYPT_ALGORITHM_PROPERTY,
+ (PBYTE)buffer, 32, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
+ if (buffer[0] == 'E' && buffer[2] == 'C'
+ && (dwPublicKeyLength == 256
+ || dwPublicKeyLength == 384
+ || dwPublicKeyLength == 521)) {
+ jstring name = env->NewStringUTF(pszNameString);
+ if (name == NULL) {
+ __leave;
+ }
+ env->CallVoidMethod(obj, mGenKeyAndCertChain,
+ 0,
+ name,
+ (jlong) hCryptProv, 0,
+ dwPublicKeyLength, jArrayList);
+ }
}
}
}
@@ -782,6 +812,9 @@
// Create new byte array
jbyteArray temp = env->NewByteArray(dwBufLen);
+ if (temp == NULL) {
+ __leave;
+ }
// Copy data from native buffer
env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);
@@ -900,6 +933,9 @@
// Create new byte array
jbyteArray temp = env->NewByteArray(jSignedHashSize);
+ if (temp == NULL) {
+ __leave;
+ }
// Copy data from native buffer
env->SetByteArrayRegion(temp, 0, jSignedHashSize, pSignedHashBuffer);
@@ -1417,6 +1453,9 @@
}
jCertAliasChars = env->GetStringChars(jCertAliasName, NULL);
+ if (jCertAliasChars == NULL) {
+ __leave;
+ }
memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR));
pszCertAliasName[size] = 0; // append the string terminator
@@ -1847,7 +1886,9 @@
}
// Create new byte array
- result = env->NewByteArray(dwBufLen);
+ if ((result = env->NewByteArray(dwBufLen)) == NULL) {
+ __leave;
+ }
// Copy data from native buffer to Java buffer
env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData);
@@ -1910,7 +1951,9 @@
}
// Create new byte array
- blob = env->NewByteArray(dwBlobLen);
+ if ((blob = env->NewByteArray(dwBlobLen)) == NULL) {
+ __leave;
+ }
// Copy data from native buffer to Java buffer
env->SetByteArrayRegion(blob, 0, dwBlobLen, (jbyte*) pbKeyBlob);
@@ -1939,6 +1982,13 @@
__try {
jsize length = env->GetArrayLength(jKeyBlob);
+ jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
+
+ if (length < headerLength) {
+ ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");
+ __leave;
+ }
+
if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {
__leave;
}
@@ -1965,7 +2015,9 @@
exponentBytes[i] = ((BYTE*) &pRsaPubKey->pubexp)[j];
}
- exponent = env->NewByteArray(len);
+ if ((exponent = env->NewByteArray(len)) == NULL) {
+ __leave;
+ }
env->SetByteArrayRegion(exponent, 0, len, exponentBytes);
}
__finally
@@ -1995,6 +2047,13 @@
__try {
jsize length = env->GetArrayLength(jKeyBlob);
+ jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
+
+ if (length < headerLength) {
+ ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");
+ __leave;
+ }
+
if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {
__leave;
}
@@ -2011,19 +2070,25 @@
(RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));
int len = pRsaPubKey->bitlen / 8;
+ if (len < 0 || len > length - headerLength) {
+ ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid key length");
+ __leave;
+ }
+
modulusBytes = new (env) jbyte[len];
if (modulusBytes == NULL) {
__leave;
}
- BYTE * pbModulus =
- (BYTE *) (keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
+ BYTE * pbModulus = (BYTE *) (keyBlob + headerLength);
// convert from little-endian while copying from blob
for (int i = 0, j = len - 1; i < len; i++, j--) {
modulusBytes[i] = pbModulus[j];
}
- modulus = env->NewByteArray(len);
+ if ((modulus = env->NewByteArray(len)) == NULL) {
+ __leave;
+ }
env->SetByteArrayRegion(modulus, 0, len, modulusBytes);
}
__finally
@@ -2240,7 +2305,9 @@
}
}
- jBlob = env->NewByteArray(jBlobLength);
+ if ((jBlob = env->NewByteArray(jBlobLength)) == NULL) {
+ __leave;
+ }
env->SetByteArrayRegion(jBlob, 0, jBlobLength, jBlobBytes);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactExceptionTest.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactExceptionTest.java Tue Jan 15 22:54:09 2019 +0100
@@ -86,6 +86,46 @@
}
}
+ public void testIntegerExactOverflowWithoutUse1(int input) {
+ Math.addExact(intCounter, input);
+ }
+
+ public void testIntegerExactOverflowWithoutUse2(int input, boolean cond) {
+ if (cond) {
+ Math.addExact(intCounter, input);
+ } else {
+ intCounter = Math.addExact(intCounter, input);
+ }
+ }
+
+ @Test
+ public void testIntegerExactWithoutUse1() throws InvalidInstalledCodeException {
+ ResolvedJavaMethod method = getResolvedJavaMethod("testIntegerExactOverflowWithoutUse1");
+ InstalledCode code = getCode(method);
+
+ boolean gotException = false;
+ try {
+ code.executeVarargs(this, Integer.MAX_VALUE);
+ } catch (ArithmeticException e) {
+ gotException = true;
+ }
+ assertTrue(gotException);
+ }
+
+ @Test
+ public void testIntegerExactWithoutUse2() throws InvalidInstalledCodeException {
+ ResolvedJavaMethod method = getResolvedJavaMethod("testIntegerExactOverflowWithoutUse2");
+ InstalledCode code = getCode(method);
+
+ boolean gotException = false;
+ try {
+ code.executeVarargs(this, Integer.MAX_VALUE, true);
+ } catch (ArithmeticException e) {
+ gotException = true;
+ }
+ assertTrue(gotException);
+ }
+
static long longCounter = 10;
public void testLongExactOverflowSnippet(long input) {
@@ -138,4 +178,44 @@
assertTrue(code.isValid());
}
}
+
+ public void testLongExactOverflowWithoutUse1(long input) {
+ Math.addExact(longCounter, input);
+ }
+
+ public void testLongExactOverflowWithoutUse2(long input, boolean cond) {
+ if (cond) {
+ Math.addExact(longCounter, input);
+ } else {
+ longCounter = Math.addExact(longCounter, input);
+ }
+ }
+
+ @Test
+ public void testLongExactWithoutUse1() throws InvalidInstalledCodeException {
+ ResolvedJavaMethod method = getResolvedJavaMethod("testLongExactOverflowWithoutUse1");
+ InstalledCode code = getCode(method);
+
+ boolean gotException = false;
+ try {
+ code.executeVarargs(this, Long.MAX_VALUE);
+ } catch (ArithmeticException e) {
+ gotException = true;
+ }
+ assertTrue(gotException);
+ }
+
+ @Test
+ public void testLongExactWithoutUse2() throws InvalidInstalledCodeException {
+ ResolvedJavaMethod method = getResolvedJavaMethod("testLongExactOverflowWithoutUse2");
+ InstalledCode code = getCode(method);
+
+ boolean gotException = false;
+ try {
+ code.executeVarargs(this, Long.MAX_VALUE, true);
+ } catch (ArithmeticException e) {
+ gotException = true;
+ }
+ assertTrue(gotException);
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java Tue Jan 15 22:54:09 2019 +0100
@@ -50,11 +50,13 @@
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticNode;
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticSplitNode;
import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+@Ignore
@RunWith(Parameterized.class)
public class IntegerExactFoldTest extends GraalCompilerTest {
private final long lowerBoundA;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Tue Jan 15 22:54:09 2019 +0100
@@ -559,26 +559,19 @@
}
}
- private static void createIntegerExactOperation(GraphBuilderContext b, JavaKind kind, ValueNode x, ValueNode y, IntegerExactOp op) {
- if (b.needsExplicitException()) {
+ private static boolean createIntegerExactOperation(GraphBuilderContext b, JavaKind kind, ValueNode x, ValueNode y, IntegerExactOp op) {
+ if (x.isConstant() && y.isConstant()) {
+ b.addPush(kind, createIntegerExactArithmeticNode(x, y, null, op));
+ return true;
+ } else {
BytecodeExceptionKind exceptionKind = kind == JavaKind.Int ? BytecodeExceptionKind.INTEGER_EXACT_OVERFLOW : BytecodeExceptionKind.LONG_EXACT_OVERFLOW;
AbstractBeginNode exceptionEdge = b.genExplicitExceptionEdge(exceptionKind);
- IntegerExactArithmeticSplitNode split = b.addPush(kind, createIntegerExactSplit(x, y, exceptionEdge, op));
- split.setNext(b.add(new BeginNode()));
- } else {
- SpeculationLog log = b.getGraph().getSpeculationLog();
- if (log == null || (x.isConstant() && y.isConstant())) {
- b.addPush(kind, createIntegerExactArithmeticNode(x, y, null, op));
- } else {
- SpeculationReason speculation = new IntegerExactOpSpeculation(b.getMethod(), op);
- if (log.maySpeculate(speculation)) {
- b.addPush(kind, createIntegerExactArithmeticNode(x, y, speculation, op));
- } else {
- BeginNode begin = b.add(new BeginNode());
- IntegerExactArithmeticNode node = (IntegerExactArithmeticNode) b.addPush(kind, createIntegerExactArithmeticNode(x, y, null, op));
- node.setAnchor(begin);
- }
+ if (exceptionEdge != null) {
+ IntegerExactArithmeticSplitNode split = b.addPush(kind, createIntegerExactSplit(x, y, exceptionEdge, op));
+ split.setNext(b.add(new BeginNode()));
+ return true;
}
+ return false;
}
}
@@ -592,8 +585,7 @@
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x) {
ConstantNode y = b.add(ConstantNode.forIntegerKind(kind, 1));
- createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_DECREMENT_EXACT);
- return true;
+ return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_DECREMENT_EXACT);
}
});
@@ -601,33 +593,29 @@
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x) {
ConstantNode y = b.add(ConstantNode.forIntegerKind(kind, 1));
- createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_INCREMENT_EXACT);
- return true;
+ return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_INCREMENT_EXACT);
}
});
r.register2("addExact", type, type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
- createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_ADD_EXACT);
- return true;
+ return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_ADD_EXACT);
}
});
r.register2("subtractExact", type, type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
- createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_SUBTRACT_EXACT);
- return true;
+ return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_SUBTRACT_EXACT);
}
});
r.register2("multiplyExact", type, type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
- createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_MULTIPLY_EXACT);
- return true;
- }
+ return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_MULTIPLY_EXACT);
+ }
});
}
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -40,6 +40,8 @@
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import java.util.Collections;
+
/**
* Writes a file that tries to redirect to an alternate page.
* The redirect uses JavaScript, if enabled, falling back on
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java Tue Jan 15 16:40:31 2019 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, 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
@@ -45,6 +45,8 @@
import javax.tools.Diagnostic.Kind;
import javax.tools.DocumentationTool;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import jdk.javadoc.doclet.Reporter;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Resources;
@@ -276,6 +278,12 @@
ModuleElement moduleElement = utils.containingModule(packageElement);
Map<String, Item> pkgMap = packageItems.get(utils.getModuleName(moduleElement));
item = (pkgMap != null) ? pkgMap.get(utils.getPackageName(packageElement)) : null;
+ if (item == null && isAutomaticModule(moduleElement)) {
+ pkgMap = packageItems.get(utils.getModuleName(null));
+ if (pkgMap != null) {
+ item = pkgMap.get(utils.getPackageName(packageElement));
+ }
+ }
}
return item;
}
@@ -420,12 +428,25 @@
path), null);
}
} else if (moduleName == null) {
- throw new Fault(resources.getText("doclet.linkMismatch_ModuleLinkedtoPackage",
- path), null);
+ // suppress the error message in the case of automatic modules
+ if (!isAutomaticModule(me)) {
+ throw new Fault(resources.getText("doclet.linkMismatch_ModuleLinkedtoPackage",
+ path), null);
+ }
}
}
}
+ // The following should be replaced by a new method such as Elements.isAutomaticModule
+ private boolean isAutomaticModule(ModuleElement me) {
+ if (me == null) {
+ return false;
+ } else {
+ ModuleSymbol msym = (ModuleSymbol) me;
+ return (msym.flags() & Flags.AUTOMATIC_MODULE) != 0;
+ }
+ }
+
public boolean isUrl (String urlCandidate) {
try {
new URL(urlCandidate);
--- a/test/hotspot/jtreg/ProblemList.txt Tue Jan 15 16:40:31 2019 -0500
+++ b/test/hotspot/jtreg/ProblemList.txt Tue Jan 15 22:54:09 2019 +0100
@@ -61,8 +61,6 @@
compiler/runtime/Test8168712.java 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x
-compiler/loopopts/PeelingZeroTripCount.java 8216135 generic-all
-
#############################################################################
# :hotspot_gc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/loopopts/Test8210392.java Tue Jan 15 22:54:09 2019 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8210392
+ * @summary C2 Assert failure: Live node limit exceeded
+ *
+ * @run main/othervm compiler.loopopts.Test8210392
+ */
+
+package compiler.loopopts;
+
+public class Test8210392 {
+ public static int ival = 17;
+
+ public static int intFn() {
+ int v = 0, k = 0;
+ for (int i = 17; i < 311; i += 3) {
+ v = Test8210392.ival;
+ int j = 1;
+ do {
+ v *= i;
+ v += j * v;
+ while (++k < 1)
+ ;
+ } while (++j < 13);
+ }
+ return v;
+ }
+
+ public void mainTest() {
+ for (int i = 0; i < 30000; i++) {
+ Test8210392.ival = intFn();
+ }
+ }
+
+ public static void main(String[] _args) {
+ Test8210392 tc = new Test8210392();
+ for (int i = 0; i < 10; i++) {
+ tc.mainTest();
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ClassUnload/ConstantPoolDependsTest.java Tue Jan 15 22:54:09 2019 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test ConstantPoolDependsTest
+ * @bug 8210094
+ * @summary Create ClassLoader dependency from initiating loader to class loader through constant pool reference
+ * @requires vm.opt.final.ClassUnloading
+ * @modules java.base/jdk.internal.misc
+ * java.compiler
+ * @library /runtime/testlibrary /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @compile p2/c2.java MyDiffClassLoader.java
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -Xlog:class+unload -XX:+WhiteBoxAPI ConstantPoolDependsTest
+ */
+
+import sun.hotspot.WhiteBox;
+
+
+public class ConstantPoolDependsTest {
+ public static WhiteBox wb = WhiteBox.getWhiteBox();
+ public static final String MY_TEST = "ConstantPoolDependsTest$c1c";
+
+ public static class c1c {
+ private void test() throws Exception {
+ // ConstantPool.klass_at_impl loads through constant pool and creates dependency
+ p2.c2 c2_obj = new p2.c2();
+ c2_obj.method2();
+ }
+
+ public c1c () throws Exception {
+ test();
+ ClassUnloadCommon.triggerUnloading(); // should not unload anything
+ test();
+ ClassUnloadCommon.triggerUnloading(); // should not unload anything
+ }
+ }
+
+ static void test() throws Throwable {
+
+ // now use the same loader to load class MyTest
+ Class MyTest_class = new MyDiffClassLoader(MY_TEST).loadClass(MY_TEST);
+
+ try {
+ // Call MyTest to load p2.c2 twice and call p2.c2.method2
+ MyTest_class.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Test FAILED if NoSuchMethodException is thrown");
+ }
+ ClassUnloadCommon.triggerUnloading(); // should not unload anything
+ ClassUnloadCommon.failIf(!wb.isClassAlive(MY_TEST), "should not be unloaded");
+ ClassUnloadCommon.failIf(!wb.isClassAlive("p2.c2"), "should not be unloaded");
+ // Unless MyTest_class is referenced here, the compiler can unload it.
+ System.out.println("Should not unload anything before here because " + MyTest_class + " is still alive.");
+ }
+
+ public static void main(String args[]) throws Throwable {
+ test();
+ ClassUnloadCommon.triggerUnloading(); // should unload
+ System.gc();
+ System.out.println("Should unload p2.c2 just now");
+ ClassUnloadCommon.failIf(wb.isClassAlive(MY_TEST), "should be unloaded");
+ ClassUnloadCommon.failIf(wb.isClassAlive("p2.c2"), "should be unloaded");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ClassUnload/DictionaryDependsTest.java Tue Jan 15 22:54:09 2019 +0100
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test DictionaryDependsTest
+ * @bug 8210094
+ * @summary Create ClassLoader dependency from initiating loader to class loader through reflection
+ * @requires vm.opt.final.ClassUnloading
+ * @modules java.base/jdk.internal.misc
+ * java.compiler
+ * @library /runtime/testlibrary /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @compile p2/c2.java MyDiffClassLoader.java
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -Xlog:class+unload -XX:+WhiteBoxAPI DictionaryDependsTest
+ */
+import sun.hotspot.WhiteBox;
+import java.lang.reflect.Method;
+
+public class DictionaryDependsTest {
+ public static WhiteBox wb = WhiteBox.getWhiteBox();
+ public static final String MY_TEST = "DictionaryDependsTest$c1r";
+
+ static public class c1r {
+
+ private void test() throws Exception {
+ // forName loads through reflection and doesn't create dependency
+ Class<?> x = Class.forName("p2.c2", true, c1r.class.getClassLoader());
+ Method m = x.getMethod("method2");
+ java.lang.Object t = x.newInstance();
+ m.invoke(t);
+ }
+
+ public c1r () throws Exception {
+ test();
+ ClassUnloadCommon.triggerUnloading(); // should unload p2.c2
+ test();
+ ClassUnloadCommon.triggerUnloading(); // should unload p2.c2
+ }
+ }
+
+ public void test() throws Throwable {
+
+ // now use the same loader to load class MyTest
+ Class MyTest_class = new MyDiffClassLoader(MY_TEST).loadClass(MY_TEST);
+
+ try {
+ // Call MyTest to load p2.c2 twice and call p2.c2.method2
+ MyTest_class.newInstance();
+ } catch (Exception e) {
+ System.out.println("Not expected NSME");
+ throw new RuntimeException("Not expecting NSME");
+ }
+ ClassUnloadCommon.triggerUnloading(); // should not unload anything
+ ClassUnloadCommon.failIf(!wb.isClassAlive(MY_TEST), "should not be unloaded");
+ ClassUnloadCommon.failIf(!wb.isClassAlive("p2.c2"), "should not be unloaded");
+ // Unless MyTest_class is referenced here, the compiler can unload it.
+ System.out.println("Should not unload anything before here because " + MyTest_class + " is still alive.");
+ }
+
+ public static void main(String args[]) throws Throwable {
+ DictionaryDependsTest d = new DictionaryDependsTest();
+ d.test();
+ ClassUnloadCommon.triggerUnloading(); // should not unload anything
+ System.out.println("Should unload MyTest and p2.c2 just now");
+ ClassUnloadCommon.failIf(wb.isClassAlive(MY_TEST), "should be unloaded");
+ ClassUnloadCommon.failIf(wb.isClassAlive("p2.c2"), "should be unloaded");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ClassUnload/MyDiffClassLoader.java Tue Jan 15 22:54:09 2019 +0100
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class MyDiffClassLoader extends ClassLoader {
+
+ public String loaderName;
+ public static boolean switchClassData = false;
+
+ MyDiffClassLoader(String name) {
+ this.loaderName = name;
+ }
+
+ public Class loadClass(String name) throws ClassNotFoundException {
+ if (!name.contains("c1r") &&
+ !name.contains("c1c") &&
+ !name.contains("c1s") &&
+ !name.equals("p2.c2")) {
+ return super.loadClass(name);
+ }
+
+ // new loader loads p2.c2
+ if (name.equals("p2.c2") && !loaderName.equals("C2Loader")) {
+ Class<?> c = new MyDiffClassLoader("C2Loader").loadClass(name);
+ switchClassData = true;
+ return c;
+ }
+
+ byte[] data = switchClassData ? getNewClassData(name) : getClassData(name);
+ System.out.println("name is " + name);
+ return defineClass(name, data, 0, data.length);
+ }
+ byte[] getClassData(String name) {
+ try {
+ String TempName = name.replaceAll("\\.", "/");
+ String currentDir = System.getProperty("test.classes");
+ String filename = currentDir + File.separator + TempName + ".class";
+ FileInputStream fis = new FileInputStream(filename);
+ byte[] b = new byte[5000];
+ int cnt = fis.read(b, 0, 5000);
+ byte[] c = new byte[cnt];
+ for (int i=0; i<cnt; i++) c[i] = b[i];
+ return c;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ // Return p2.c2 with everything removed
+ byte[] getNewClassData(String name) {
+ return InMemoryJavaCompiler.compile("p2.c2", "package p2; public class c2 { }");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ClassUnload/SuperDependsTest.java Tue Jan 15 22:54:09 2019 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test SuperDependsTest
+ * @bug 8210094
+ * @summary Create ClassLoader dependency from initiating loader to class loader through subclassing
+ * @requires vm.opt.final.ClassUnloading
+ * @modules java.base/jdk.internal.misc
+ * java.compiler
+ * @library /runtime/testlibrary /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @compile p2/c2.java MyDiffClassLoader.java
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -Xlog:class+unload -XX:+WhiteBoxAPI SuperDependsTest
+ */
+import sun.hotspot.WhiteBox;
+import p2.*;
+
+public class SuperDependsTest {
+ public static WhiteBox wb = WhiteBox.getWhiteBox();
+ public static final String MY_TEST = "SuperDependsTest$c1s";
+
+
+ // p2.c2 loads through super class and creates dependency
+ public static class c1s extends p2.c2 {
+
+ private void test() throws Exception {
+ method2();
+ }
+
+ public c1s () throws Exception {
+ test();
+ ClassUnloadCommon.triggerUnloading(); // should not unload anything
+ test();
+ }
+ }
+
+ public void test() throws Throwable {
+
+ // now use the same loader to load class MyTest
+ Class MyTest_class = new MyDiffClassLoader(MY_TEST).loadClass(MY_TEST);
+
+ // Call MyTest to load p2.c2 twice and call p2.c2.method2
+ MyTest_class.newInstance();
+ ClassUnloadCommon.triggerUnloading(); // should not unload anything
+ ClassUnloadCommon.failIf(!wb.isClassAlive(MY_TEST), "should not be unloaded");
+ ClassUnloadCommon.failIf(!wb.isClassAlive("p2.c2"), "should not be unloaded");
+ // Unless MyTest_class is referenced here, the compiler can unload it.
+ System.out.println("Should not unload anything before here because " + MyTest_class + " is still alive.");
+ }
+
+ public static void main(String args[]) throws Throwable {
+ SuperDependsTest d = new SuperDependsTest();
+ d.test();
+ ClassUnloadCommon.triggerUnloading(); // should not unload anything
+ System.out.println("Should unload MyTest and p2.c2 just now");
+ ClassUnloadCommon.failIf(wb.isClassAlive(MY_TEST), "should be unloaded");
+ ClassUnloadCommon.failIf(wb.isClassAlive("p2.c2"), "should be unloaded");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ClassUnload/p2/c2.java Tue Jan 15 22:54:09 2019 +0100
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package p2;
+
+public class c2 {
+ int i;
+ public void method2() { i = 5; System.out.println("c2 method2 called"); }
+}
--- a/test/jdk/java/math/BigDecimal/AddTests.java Tue Jan 15 16:40:31 2019 -0500
+++ b/test/jdk/java/math/BigDecimal/AddTests.java Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6362557
+ * @bug 6362557 8200698
* @summary Some tests of add(BigDecimal, mc)
* @author Joseph D. Darcy
*/
@@ -290,12 +290,35 @@
return failures;
}
+ private static int arithmeticExceptionTest() {
+ int failures = 0;
+ BigDecimal x;
+ try {
+ //
+ // The string representation "1e2147483647", which is equivalent
+ // to 10^Integer.MAX_VALUE, is used to create an augend with an
+ // unscaled value of 1 and a scale of -Integer.MAX_VALUE. The
+ // addend "1" has an unscaled value of 1 with a scale of 0. The
+ // addition is performed exactly and is specified to have a
+ // preferred scale of max(-Integer.MAX_VALUE, 0). As the scale
+ // of the result is 0, a value with Integer.MAX_VALUE + 1 digits
+ // would need to be created. Therefore the next statement is
+ // expected to overflow with an ArithmeticException.
+ //
+ x = new BigDecimal("1e2147483647").add(new BigDecimal(1));
+ failures++;
+ } catch (ArithmeticException ae) {
+ }
+ return failures;
+ }
+
public static void main(String argv[]) {
int failures = 0;
failures += extremaTests();
failures += roundingGradationTests();
failures += precisionConsistencyTest();
+ failures += arithmeticExceptionTest();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
--- a/test/jdk/java/math/BigDecimal/Constructor.java Tue Jan 15 16:40:31 2019 -0500
+++ b/test/jdk/java/math/BigDecimal/Constructor.java Tue Jan 15 22:54:09 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, 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
@@ -23,20 +23,48 @@
/*
* @test
- * @bug 4259453
- * @summary Test string constructor of BigDecimal
+ * @bug 4259453 8200698
+ * @summary Test constructors of BigDecimal
+ * @library ..
+ * @run testng Constructor
*/
+
import java.math.BigDecimal;
+import org.testng.annotations.Test;
public class Constructor {
- public static void main(String[] args) throws Exception {
- boolean nfe = false;
+ @Test(expectedExceptions=NumberFormatException.class)
+ public void stringConstructor() {
+ BigDecimal bd = new BigDecimal("1.2e");
+ }
+
+ @Test(expectedExceptions=NumberFormatException.class)
+ public void charArrayConstructorNegativeOffset() {
+ BigDecimal bd = new BigDecimal(new char[5], -1, 4, null);
+ }
+
+ @Test(expectedExceptions=NumberFormatException.class)
+ public void charArrayConstructorNegativeLength() {
+ BigDecimal bd = new BigDecimal(new char[5], 0, -1, null);
+ }
+
+ @Test(expectedExceptions=NumberFormatException.class)
+ public void charArrayConstructorIntegerOverflow() {
try {
- BigDecimal bd = new BigDecimal("1.2e");
- } catch (NumberFormatException e) {
- nfe = true;
+ BigDecimal bd = new BigDecimal(new char[5], Integer.MAX_VALUE - 5,
+ 6, null);
+ } catch (NumberFormatException nfe) {
+ if (nfe.getCause() instanceof IndexOutOfBoundsException) {
+ throw new RuntimeException
+ ("NumberFormatException should not have a cause");
+ } else {
+ throw nfe;
+ }
}
- if (!nfe)
- throw new Exception("Didn't throw NumberFormatException");
+ }
+
+ @Test(expectedExceptions=NumberFormatException.class)
+ public void charArrayConstructorIndexOutOfBounds() {
+ BigDecimal bd = new BigDecimal(new char[5], 1, 5, null);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/math/BigInteger/LargeValueExceptions.java Tue Jan 15 22:54:09 2019 +0100
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8200698
+ * @summary Tests that exceptions are thrown for ops which would overflow
+ * @requires os.maxMemory >= 4g
+ * @run testng/othervm -Xmx4g LargeValueExceptions
+ */
+import java.math.BigInteger;
+import static java.math.BigInteger.ONE;
+import org.testng.annotations.Test;
+
+//
+// The intent of this test is to probe the boundaries between overflow and
+// non-overflow, principally for multiplication and squaring, specifically
+// the largest values which should not overflow and the smallest values which
+// should. The transition values used are not necessarily at the exact
+// boundaries but should be "close." Quite a few different values were used
+// experimentally before settling on the ones in this test. For multiplication
+// and squaring all cases are exercised: definite overflow and non-overflow
+// which can be detected "up front," and "indefinite" overflow, i.e., overflow
+// which cannot be detected up front so further calculations are required.
+//
+// Testing negative values is unnecessary. For both multiplication and squaring
+// the paths lead to the Toom-Cook algorithm where the signum is used only to
+// determine the sign of the result and not in the intermediate calculations.
+// This is also true for exponentiation.
+//
+// @Test annotations with optional element "enabled" set to "false" should
+// succeed when "enabled" is set to "true" but they take too to run in the
+// course of the typical regression test execution scenario.
+//
+public class LargeValueExceptions {
+ // BigInteger.MAX_MAG_LENGTH
+ private static final int MAX_INTS = 1 << 26;
+
+ // Number of bits corresponding to MAX_INTS
+ private static final long MAX_BITS = (0xffffffffL & MAX_INTS) << 5L;
+
+ // Half BigInteger.MAX_MAG_LENGTH
+ private static final int MAX_INTS_HALF = MAX_INTS / 2;
+
+ // --- squaring ---
+
+ // Largest no overflow determined by examining data lengths alone.
+ @Test(enabled=false)
+ public void squareNoOverflow() {
+ BigInteger x = ONE.shiftLeft(16*MAX_INTS - 1).subtract(ONE);
+ BigInteger y = x.multiply(x);
+ }
+
+ // Smallest no overflow determined by extra calculations.
+ @Test(enabled=false)
+ public void squareIndefiniteOverflowSuccess() {
+ BigInteger x = ONE.shiftLeft(16*MAX_INTS - 1);
+ BigInteger y = x.multiply(x);
+ }
+
+ // Largest overflow detected by extra calculations.
+ @Test(expectedExceptions=ArithmeticException.class,enabled=false)
+ public void squareIndefiniteOverflowFailure() {
+ BigInteger x = ONE.shiftLeft(16*MAX_INTS).subtract(ONE);
+ BigInteger y = x.multiply(x);
+ }
+
+ // Smallest overflow detected by examining data lengths alone.
+ @Test(expectedExceptions=ArithmeticException.class)
+ public void squareDefiniteOverflow() {
+ BigInteger x = ONE.shiftLeft(16*MAX_INTS);
+ BigInteger y = x.multiply(x);
+ }
+
+ // --- multiplication ---
+
+ // Largest no overflow determined by examining data lengths alone.
+ @Test(enabled=false)
+ public void multiplyNoOverflow() {
+ final int halfMaxBits = MAX_INTS_HALF << 5;
+
+ BigInteger x = ONE.shiftLeft(halfMaxBits).subtract(ONE);
+ BigInteger y = ONE.shiftLeft(halfMaxBits - 1).subtract(ONE);
+ BigInteger z = x.multiply(y);
+ }
+
+ // Smallest no overflow determined by extra calculations.
+ @Test(enabled=false)
+ public void multiplyIndefiniteOverflowSuccess() {
+ BigInteger x = ONE.shiftLeft((int)(MAX_BITS/2) - 1);
+ long m = MAX_BITS - x.bitLength();
+
+ BigInteger y = ONE.shiftLeft((int)(MAX_BITS/2) - 1);
+ long n = MAX_BITS - y.bitLength();
+
+ if (m + n != MAX_BITS) {
+ throw new RuntimeException("Unexpected leading zero sum");
+ }
+
+ BigInteger z = x.multiply(y);
+ }
+
+ // Largest overflow detected by extra calculations.
+ @Test(expectedExceptions=ArithmeticException.class,enabled=false)
+ public void multiplyIndefiniteOverflowFailure() {
+ BigInteger x = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE);
+ long m = MAX_BITS - x.bitLength();
+
+ BigInteger y = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE);
+ long n = MAX_BITS - y.bitLength();
+
+ if (m + n != MAX_BITS) {
+ throw new RuntimeException("Unexpected leading zero sum");
+ }
+
+ BigInteger z = x.multiply(y);
+ }
+
+ // Smallest overflow detected by examining data lengths alone.
+ @Test(expectedExceptions=ArithmeticException.class)
+ public void multiplyDefiniteOverflow() {
+ // multiply by 4 as MAX_INTS_HALF refers to ints
+ byte[] xmag = new byte[4*MAX_INTS_HALF];
+ xmag[0] = (byte)0xff;
+ BigInteger x = new BigInteger(1, xmag);
+
+ byte[] ymag = new byte[4*MAX_INTS_HALF + 1];
+ ymag[0] = (byte)0xff;
+ BigInteger y = new BigInteger(1, ymag);
+
+ BigInteger z = x.multiply(y);
+ }
+
+ // --- exponentiation ---
+
+ @Test(expectedExceptions=ArithmeticException.class)
+ public void powOverflow() {
+ BigInteger.TEN.pow(Integer.MAX_VALUE);
+ }
+
+ @Test(expectedExceptions=ArithmeticException.class)
+ public void powOverflow1() {
+ int shift = 20;
+ int exponent = 1 << shift;
+ BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent));
+ BigInteger y = x.pow(exponent);
+ }
+
+ @Test(expectedExceptions=ArithmeticException.class)
+ public void powOverflow2() {
+ int shift = 20;
+ int exponent = 1 << shift;
+ BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).add(ONE);
+ BigInteger y = x.pow(exponent);
+ }
+
+ @Test(expectedExceptions=ArithmeticException.class,enabled=false)
+ public void powOverflow3() {
+ int shift = 20;
+ int exponent = 1 << shift;
+ BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).subtract(ONE);
+ BigInteger y = x.pow(exponent);
+ }
+
+ @Test(enabled=false)
+ public void powOverflow4() {
+ int shift = 20;
+ int exponent = 1 << shift;
+ BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent - 1)).add(ONE);
+ BigInteger y = x.pow(exponent);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOptionWithAutomaticModule.java Tue Jan 15 22:54:09 2019 +0100
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2019, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8212233
+ * @summary The code being documented uses modules but the packages defined in $URL are in the unnamed module.
+ * @library /tools/lib ../lib
+ * @modules
+ * jdk.javadoc/jdk.javadoc.internal.tool
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build JavadocTester toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder toolbox.ToolBox
+ * @run main TestLinkOptionWithAutomaticModule
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import toolbox.JarTask;
+import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
+import toolbox.ToolBox;
+
+public class TestLinkOptionWithAutomaticModule extends JavadocTester {
+
+ public static void main(String... args) throws Exception {
+ TestLinkOptionWithAutomaticModule tester = new TestLinkOptionWithAutomaticModule();
+ tester.runTests(m -> new Object[]{ Path.of(m.getName()) });
+ }
+
+ final ToolBox tb = new ToolBox();
+ private Path libJar;
+ private Path libAPI;
+
+ TestLinkOptionWithAutomaticModule() throws IOException {
+ initLib();
+ }
+
+ private void initLib() throws IOException {
+ // create library: write source, compile it, jar it
+ Path lib = Path.of("lib");
+ Path libSrc = lib.resolve("src");
+ tb.writeJavaFiles(libSrc, "package lib; public class LibClass { }");
+ Path libClasses = Files.createDirectories(lib.resolve("classes"));
+
+ new JavacTask(tb)
+ .outdir(libClasses)
+ .files(tb.findJavaFiles(libSrc))
+ .run()
+ .writeAll();
+
+ libJar = lib.resolve("MyLib.jar");
+ new JarTask(tb, libJar)
+ .baseDir(libClasses)
+ .files(".")
+ .run();
+
+ libAPI = lib.resolve("api");
+ javadoc("-d", libAPI.toString(),
+ "-sourcepath", libSrc.toString(),
+ "lib");
+ checkExit(Exit.OK);
+ }
+
+ @Test
+ public void testLinkUnnamedToAutomaticModule(Path base) throws IOException {
+
+ // create API referring to library
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src, "package p; public class MyClass extends lib.LibClass { }");
+
+ // run javadoc with library as automatic module
+ Path api = base.resolve("api");
+ javadoc("-d", api.toString(),
+ "-sourcepath", src.toString(),
+ "--add-modules", "MyLib",
+ "--module-path", libJar.toString(),
+ "-linkoffline", "http://myWebsite", libAPI.toAbsolutePath().toString(),
+ "p");
+ checkExit(Exit.OK);
+ checkOutput("p/MyClass.html", true,
+ "extends <a href=\"http://myWebsite/lib/LibClass.html?is-external=true\" "
+ + "title=\"class or interface in lib\" class=\"externalLink\">LibClass</a>");
+ }
+
+ @Test
+ public void testLinkNamedToAutomaticModule(Path base) throws IOException {
+
+ // create API referring to library
+ Path src = base.resolve("src");
+ new ModuleBuilder(tb, "my.module")
+ .exports("p")
+ .requires("MyLib")
+ .classes("package p; public class MyClass extends lib.LibClass { }")
+ .write(src);
+
+ // run javadoc with library as automatic module
+ Path api = base.resolve("api");
+ javadoc("-d", api.toString(),
+ "--module-source-path", src.toString(),
+ "--module-path", libJar.toString(),
+ "-linkoffline", "http://myWebsite", libAPI.toAbsolutePath().toString(),
+ "--module", "my.module");
+ checkExit(Exit.OK);
+ checkOutput("my.module/p/MyClass.html", true,
+ "extends <a href=\"http://myWebsite/lib/LibClass.html?is-external=true\" "
+ + "title=\"class or interface in lib\" class=\"externalLink\">LibClass</a>");
+ }
+
+ @Test
+ public void testLinkNamedToUnnamedModule(Path base) throws IOException {
+
+ // create API referring to library
+ Path src = base.resolve("src");
+ new ModuleBuilder(tb, "my.module")
+ .exports("p")
+ .classes("package p; public class MyClass extends lib.LibClass { }")
+ .write(src);
+
+ // run javadoc with library as unnamed module
+ Path api = base.resolve("api");
+ javadoc("-d", api.toString(),
+ "--module-source-path", src.toString(),
+ "--add-reads", "my.module=ALL-UNNAMED",
+ "--class-path", libJar.toString(),
+ "-linkoffline", "http://myWebsite", libAPI.toAbsolutePath().toString(),
+ "--module", "my.module");
+ checkExit(Exit.OK);
+ checkOutput("my.module/p/MyClass.html", true,
+ "extends <a href=\"http://myWebsite/lib/LibClass.html?is-external=true\" "
+ + "title=\"class or interface in lib\" class=\"externalLink\">LibClass</a>");
+ }
+}
--- a/test/nashorn/script/nosecurity/treeapi/diagnostic.js.EXPECTED Tue Jan 15 16:40:31 2019 -0500
+++ b/test/nashorn/script/nosecurity/treeapi/diagnostic.js.EXPECTED Tue Jan 15 22:54:09 2019 +0100
@@ -80,7 +80,7 @@
"columnNumber": "15",
"kind": "ERROR",
"position": "15",
- "message": "test.js:1:15 Unclosed group near index 9\n([a-z])+(\n ^\n /([a-z])+(/;\n ^",
+ "message": "test.js:1:15 Unclosed group near index 9\n([a-z])+(\n /([a-z])+(/;\n ^",
"lineNumber": "1"
},
{