From 71681ac4cbac84c196b3b2ed482d1b608ae30ca2 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Mon, 1 Feb 2016 15:00:02 -0800 Subject: [PATCH 001/311] 8148628: TIFFDirectory(getAsMetaData) created with one TIFFField having a IFD pointer tag throws ClassCastException & other naming differences (JEP 262) Clean up some handling of TIFFDirectory instances contained in TIFFFields and make a couple of minor changes to Exif and GeoTIFF tag names. Reviewed-by: prr --- .../imageio/plugins/tiff/TIFFFieldNode.java | 13 ++++++----- .../imageio/plugins/tiff/ExifTIFFTagSet.java | 4 ++-- .../imageio/plugins/tiff/GeoTIFFTagSet.java | 8 +++---- .../imageio/plugins/tiff/TIFFDirectory.java | 22 ++++++++++++++----- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java index ced248f9d7e..e78954b34e4 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -39,7 +39,7 @@ import javax.imageio.plugins.tiff.TIFFTagSet; */ public class TIFFFieldNode extends IIOMetadataNode { private static String getNodeName(TIFFField f) { - return f.getData() instanceof TIFFDirectory ? + return (f.hasDirectory() || f.getData() instanceof TIFFDirectory) ? "TIFFIFD" : "TIFFField"; } @@ -52,7 +52,8 @@ public class TIFFFieldNode extends IIOMetadataNode { public TIFFFieldNode(TIFFField field) { super(getNodeName(field)); - isIFD = field.getData() instanceof TIFFDirectory; + isIFD = field.hasDirectory() || + field.getData() instanceof TIFFDirectory; this.field = field; @@ -68,7 +69,8 @@ public class TIFFFieldNode extends IIOMetadataNode { setAttribute("parentTagName", tagName); } - TIFFDirectory dir = (TIFFDirectory)field.getData(); + TIFFDirectory dir = field.hasDirectory() ? + field.getDirectory() : (TIFFDirectory)field.getData(); TIFFTagSet[] tagSets = dir.getTagSets(); if(tagSets != null) { StringBuilder tagSetNames = new StringBuilder(); @@ -90,7 +92,8 @@ public class TIFFFieldNode extends IIOMetadataNode { if(isInitialized) return; if(isIFD) { - TIFFDirectory dir = (TIFFDirectory)field.getData(); + TIFFDirectory dir = field.hasDirectory() ? + field.getDirectory() : (TIFFDirectory)field.getData(); TIFFField[] fields = dir.getTIFFFields(); if(fields != null) { TIFFTagSet[] tagSets = dir.getTagSets(); diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java index 5867a0ffef5..792a78fcb23 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -1256,7 +1256,7 @@ public class ExifTIFFTagSet extends TIFFTagSet { static class ExifVersion extends TIFFTag { public ExifVersion() { - super("Exifversion", + super("ExifVersion", TAG_EXIF_VERSION, 1 << TIFFTag.TIFF_UNDEFINED, 4); diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java index c478f7c03e7..ec6e5f2a503 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -97,7 +97,7 @@ public class GeoTIFFTagSet extends TIFFTagSet { static class GeoKeyDirectory extends TIFFTag { public GeoKeyDirectory() { - super("GeoKeyDirectory", + super("GeoKeyDirectoryTag", TAG_GEO_KEY_DIRECTORY, 1 << TIFFTag.TIFF_SHORT); } @@ -105,7 +105,7 @@ public class GeoTIFFTagSet extends TIFFTagSet { static class GeoDoubleParams extends TIFFTag { public GeoDoubleParams() { - super("GeoDoubleParams", + super("GeoDoubleParamsTag", TAG_GEO_DOUBLE_PARAMS, 1 << TIFFTag.TIFF_DOUBLE); } @@ -113,7 +113,7 @@ public class GeoTIFFTagSet extends TIFFTagSet { static class GeoAsciiParams extends TIFFTag { public GeoAsciiParams() { - super("GeoAsciiParams", + super("GeoAsciiParamsTag", TAG_GEO_ASCII_PARAMS, 1 << TIFFTag.TIFF_ASCII); } diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java index ea13664767c..7f75db646db 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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,11 +219,23 @@ public class TIFFDirectory implements Cloneable { TIFFField f = fields[i]; TIFFTag tag = f.getTag(); if(tag.isIFDPointer()) { - TIFFDirectory subIFD = - getDirectoryAsIFD((TIFFDirectory)f.getData()); - f = new TIFFField(tag, f.getType(), (long)f.getCount(), subIFD); + TIFFDirectory subDir = null; + if (f.hasDirectory()) { + subDir = f.getDirectory(); + } else if (f.getData() instanceof TIFFDirectory) { + subDir = (TIFFDirectory)f.getData(); + } + if (subDir != null) { + TIFFDirectory subIFD = getDirectoryAsIFD(subDir); + f = new TIFFField(tag, f.getType(), (long)f.getCount(), + subIFD); + } else { + f = null; + } + } + if (f != null) { + ifd.addTIFFField(f); } - ifd.addTIFFField(f); } return ifd; From 8f887527571b6eb9a487cd0b3e408abc375ba489 Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Thu, 4 Feb 2016 08:22:26 +0100 Subject: [PATCH 002/311] 8149013: Remove unused and dead code from G1CollectorPolicy Reviewed-by: ehelin, jwilhelm --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 7 - .../src/share/vm/gc/g1/g1CollectorPolicy.cpp | 164 +----------------- .../src/share/vm/gc/g1/g1CollectorPolicy.hpp | 70 -------- .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 3 - 4 files changed, 2 insertions(+), 242 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index f62e2d5973c..d7546a121ff 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -2777,12 +2777,6 @@ void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const { } void G1CollectedHeap::print_tracing_info() const { - // We'll overload this to mean "trace GC pause statistics." - if (TraceYoungGenTime || TraceOldGenTime) { - // The "G1CollectorPolicy" is keeping track of these stats, so delegate - // to that. - g1_policy()->print_tracing_info(); - } g1_rem_set()->print_summary_info(); concurrent_mark()->print_summary_info(); g1_policy()->print_yg_surv_rate_info(); @@ -2908,7 +2902,6 @@ HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size, bool* succeeded, GCCause::Cause gc_cause) { assert_heap_not_locked_and_not_at_safepoint(); - g1_policy()->record_stop_world_start(); VM_G1IncCollectionPause op(gc_count_before, word_size, false, /* should_initiate_conc_mark */ diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index 566dfcc28ff..93b2cce3dd1 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -81,10 +81,8 @@ static double non_young_other_cost_per_region_ms_defaults[] = { G1CollectorPolicy::G1CollectorPolicy() : _predictor(G1ConfidencePercent / 100.0), - _parallel_gc_threads(ParallelGCThreads), _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), - _stop_world_start(0.0), _concurrent_mark_remark_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), _concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), @@ -129,7 +127,6 @@ G1CollectorPolicy::G1CollectorPolicy() : _inc_cset_head(NULL), _inc_cset_tail(NULL), _inc_cset_bytes_used_before(0), - _inc_cset_max_finger(NULL), _inc_cset_recorded_rs_lengths(0), _inc_cset_recorded_rs_lengths_diffs(0), _inc_cset_predicted_elapsed_time_ms(0.0), @@ -172,9 +169,9 @@ G1CollectorPolicy::G1CollectorPolicy() : _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; clear_ratio_check_data(); - _phase_times = new G1GCPhaseTimes(_parallel_gc_threads); + _phase_times = new G1GCPhaseTimes(ParallelGCThreads); - int index = MIN2(_parallel_gc_threads - 1, 7); + int index = MIN2(ParallelGCThreads - 1, 7u); _rs_length_diff_seq->add(rs_length_diff_defaults[index]); _cost_per_card_ms_seq->add(cost_per_card_ms_defaults[index]); @@ -872,8 +869,6 @@ void G1CollectorPolicy::record_full_collection_end() { double full_gc_time_sec = end_sec - _full_collection_start_sec; double full_gc_time_ms = full_gc_time_sec * 1000.0; - _trace_old_gen_time_data.record_full_collection(full_gc_time_ms); - update_recent_gc_times(end_sec, full_gc_time_ms); collector_state()->set_full_collection(false); @@ -904,10 +899,6 @@ void G1CollectorPolicy::record_full_collection_end() { record_pause(FullGC, _full_collection_start_sec, end_sec); } -void G1CollectorPolicy::record_stop_world_start() { - _stop_world_start = os::elapsedTime(); -} - void G1CollectorPolicy::record_collection_pause_start(double start_time_sec) { // We only need to do this here as the policy will only be applied // to the GC we're about to start. so, no point is calculating this @@ -918,10 +909,6 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec) { "sanity, used: " SIZE_FORMAT " recalculate_used: " SIZE_FORMAT, _g1->used(), _g1->recalculate_used()); - double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0; - _trace_young_gen_time_data.record_start_collection(s_w_t_ms); - _stop_world_start = 0.0; - phase_times()->record_cur_collection_start_sec(start_time_sec); _pending_cards = _g1->pending_card_num(); @@ -973,13 +960,6 @@ void G1CollectorPolicy::record_concurrent_mark_cleanup_completed() { collector_state()->set_in_marking_window(false); } -void G1CollectorPolicy::record_concurrent_pause() { - if (_stop_world_start > 0.0) { - double yield_ms = (os::elapsedTime() - _stop_world_start) * 1000.0; - _trace_young_gen_time_data.record_yield_time(yield_ms); - } -} - double G1CollectorPolicy::average_time_ms(G1GCPhaseTimes::GCParPhases phase) const { return phase_times()->average_time_ms(phase); } @@ -1064,7 +1044,6 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t } if (update_stats) { - _trace_young_gen_time_data.record_end_collection(pause_time_ms, phase_times()); // We maintain the invariant that all objects allocated by mutator // threads will be allocated out of eden regions. So, we can use // the eden region number allocated since the previous GC to @@ -1654,11 +1633,6 @@ size_t G1CollectorPolicy::expansion_amount() { return expand_bytes; } -void G1CollectorPolicy::print_tracing_info() const { - _trace_young_gen_time_data.print(); - _trace_old_gen_time_data.print(); -} - void G1CollectorPolicy::print_yg_surv_rate_info() const { #ifndef PRODUCT _short_lived_surv_rate_group->print_surv_rate_summary(); @@ -1869,7 +1843,6 @@ void G1CollectorPolicy::start_incremental_cset_building() { _inc_cset_tail = NULL; _inc_cset_bytes_used_before = 0; - _inc_cset_max_finger = 0; _inc_cset_recorded_rs_lengths = 0; _inc_cset_recorded_rs_lengths_diffs = 0; _inc_cset_predicted_elapsed_time_ms = 0.0; @@ -1981,9 +1954,6 @@ void G1CollectorPolicy::add_region_to_incremental_cset_common(HeapRegion* hr) { size_t rs_length = hr->rem_set()->occupied(); add_to_incremental_cset_info(hr, rs_length); - HeapWord* hr_end = hr->end(); - _inc_cset_max_finger = MAX2(_inc_cset_max_finger, hr_end); - assert(!hr->in_collection_set(), "invariant"); _g1->register_young_region_with_cset(hr); assert(hr->next_in_collection_set() == NULL, "invariant"); @@ -2190,12 +2160,6 @@ double G1CollectorPolicy::finalize_young_cset_part(double target_pause_time_ms) collector_state()->set_last_gc_was_young(collector_state()->gcs_are_young()); - if (collector_state()->last_gc_was_young()) { - _trace_young_gen_time_data.increment_young_collection_count(); - } else { - _trace_young_gen_time_data.increment_mixed_collection_count(); - } - // The young list is laid with the survivor regions from the previous // pause are appended to the RHS of the young list, i.e. // [Newly Young Regions ++ Survivors from last pause]. @@ -2335,127 +2299,3 @@ void G1CollectorPolicy::finalize_old_cset_part(double time_remaining_ms) { double non_young_end_time_sec = os::elapsedTime(); phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0); } - -void TraceYoungGenTimeData::record_start_collection(double time_to_stop_the_world_ms) { - if(TraceYoungGenTime) { - _all_stop_world_times_ms.add(time_to_stop_the_world_ms); - } -} - -void TraceYoungGenTimeData::record_yield_time(double yield_time_ms) { - if(TraceYoungGenTime) { - _all_yield_times_ms.add(yield_time_ms); - } -} - -void TraceYoungGenTimeData::record_end_collection(double pause_time_ms, G1GCPhaseTimes* phase_times) { - if(TraceYoungGenTime) { - _total.add(pause_time_ms); - _other.add(pause_time_ms - phase_times->accounted_time_ms()); - _root_region_scan_wait.add(phase_times->root_region_scan_wait_time_ms()); - _parallel.add(phase_times->cur_collection_par_time_ms()); - _ext_root_scan.add(phase_times->average_time_ms(G1GCPhaseTimes::ExtRootScan)); - _satb_filtering.add(phase_times->average_time_ms(G1GCPhaseTimes::SATBFiltering)); - _update_rs.add(phase_times->average_time_ms(G1GCPhaseTimes::UpdateRS)); - _scan_rs.add(phase_times->average_time_ms(G1GCPhaseTimes::ScanRS)); - _obj_copy.add(phase_times->average_time_ms(G1GCPhaseTimes::ObjCopy)); - _termination.add(phase_times->average_time_ms(G1GCPhaseTimes::Termination)); - - double parallel_known_time = phase_times->average_time_ms(G1GCPhaseTimes::ExtRootScan) + - phase_times->average_time_ms(G1GCPhaseTimes::SATBFiltering) + - phase_times->average_time_ms(G1GCPhaseTimes::UpdateRS) + - phase_times->average_time_ms(G1GCPhaseTimes::ScanRS) + - phase_times->average_time_ms(G1GCPhaseTimes::ObjCopy) + - phase_times->average_time_ms(G1GCPhaseTimes::Termination); - - double parallel_other_time = phase_times->cur_collection_par_time_ms() - parallel_known_time; - _parallel_other.add(parallel_other_time); - _clear_ct.add(phase_times->cur_clear_ct_time_ms()); - } -} - -void TraceYoungGenTimeData::increment_young_collection_count() { - if(TraceYoungGenTime) { - ++_young_pause_num; - } -} - -void TraceYoungGenTimeData::increment_mixed_collection_count() { - if(TraceYoungGenTime) { - ++_mixed_pause_num; - } -} - -void TraceYoungGenTimeData::print_summary(const char* str, - const NumberSeq* seq) const { - double sum = seq->sum(); - tty->print_cr("%-27s = %8.2lf s (avg = %8.2lf ms)", - str, sum / 1000.0, seq->avg()); -} - -void TraceYoungGenTimeData::print_summary_sd(const char* str, - const NumberSeq* seq) const { - print_summary(str, seq); - tty->print_cr("%45s = %5d, std dev = %8.2lf ms, max = %8.2lf ms)", - "(num", seq->num(), seq->sd(), seq->maximum()); -} - -void TraceYoungGenTimeData::print() const { - if (!TraceYoungGenTime) { - return; - } - - tty->print_cr("ALL PAUSES"); - print_summary_sd(" Total", &_total); - tty->cr(); - tty->cr(); - tty->print_cr(" Young GC Pauses: %8d", _young_pause_num); - tty->print_cr(" Mixed GC Pauses: %8d", _mixed_pause_num); - tty->cr(); - - tty->print_cr("EVACUATION PAUSES"); - - if (_young_pause_num == 0 && _mixed_pause_num == 0) { - tty->print_cr("none"); - } else { - print_summary_sd(" Evacuation Pauses", &_total); - print_summary(" Root Region Scan Wait", &_root_region_scan_wait); - print_summary(" Parallel Time", &_parallel); - print_summary(" Ext Root Scanning", &_ext_root_scan); - print_summary(" SATB Filtering", &_satb_filtering); - print_summary(" Update RS", &_update_rs); - print_summary(" Scan RS", &_scan_rs); - print_summary(" Object Copy", &_obj_copy); - print_summary(" Termination", &_termination); - print_summary(" Parallel Other", &_parallel_other); - print_summary(" Clear CT", &_clear_ct); - print_summary(" Other", &_other); - } - tty->cr(); - - tty->print_cr("MISC"); - print_summary_sd(" Stop World", &_all_stop_world_times_ms); - print_summary_sd(" Yields", &_all_yield_times_ms); -} - -void TraceOldGenTimeData::record_full_collection(double full_gc_time_ms) { - if (TraceOldGenTime) { - _all_full_gc_times.add(full_gc_time_ms); - } -} - -void TraceOldGenTimeData::print() const { - if (!TraceOldGenTime) { - return; - } - - if (_all_full_gc_times.num() > 0) { - tty->print("\n%4d full_gcs: total time = %8.2f s", - _all_full_gc_times.num(), - _all_full_gc_times.sum() / 1000.0); - tty->print_cr(" (avg = %8.2fms).", _all_full_gc_times.avg()); - tty->print_cr(" [std. dev = %8.2f ms, max = %8.2f ms]", - _all_full_gc_times.sd(), - _all_full_gc_times.maximum()); - } -} diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp index 81ba9f7b4c5..fbdc47742cf 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp @@ -45,52 +45,6 @@ class CollectionSetChooser; class G1IHOPControl; class G1YoungGenSizer; -// TraceYoungGenTime collects data on _both_ young and mixed evacuation pauses -// (the latter may contain non-young regions - i.e. regions that are -// technically in old) while TraceOldGenTime collects data about full GCs. -class TraceYoungGenTimeData : public CHeapObj { - private: - unsigned _young_pause_num; - unsigned _mixed_pause_num; - - NumberSeq _all_stop_world_times_ms; - NumberSeq _all_yield_times_ms; - - NumberSeq _total; - NumberSeq _other; - NumberSeq _root_region_scan_wait; - NumberSeq _parallel; - NumberSeq _ext_root_scan; - NumberSeq _satb_filtering; - NumberSeq _update_rs; - NumberSeq _scan_rs; - NumberSeq _obj_copy; - NumberSeq _termination; - NumberSeq _parallel_other; - NumberSeq _clear_ct; - - void print_summary(const char* str, const NumberSeq* seq) const; - void print_summary_sd(const char* str, const NumberSeq* seq) const; - -public: - TraceYoungGenTimeData() : _young_pause_num(0), _mixed_pause_num(0) {}; - void record_start_collection(double time_to_stop_the_world_ms); - void record_yield_time(double yield_time_ms); - void record_end_collection(double pause_time_ms, G1GCPhaseTimes* phase_times); - void increment_young_collection_count(); - void increment_mixed_collection_count(); - void print() const; -}; - -class TraceOldGenTimeData : public CHeapObj { - private: - NumberSeq _all_full_gc_times; - - public: - void record_full_collection(double full_gc_time_ms); - void print() const; -}; - class G1CollectorPolicy: public CollectorPolicy { private: G1IHOPControl* _ihop_control; @@ -107,13 +61,6 @@ class G1CollectorPolicy: public CollectorPolicy { double get_new_prediction(TruncatedSeq const* seq) const; size_t get_new_size_prediction(TruncatedSeq const* seq) const; - // either equal to the number of parallel threads, if ParallelGCThreads - // has been set, or 1 otherwise - int _parallel_gc_threads; - - // The number of GC threads currently active. - uintx _no_of_gc_threads; - G1MMUTracker* _mmu_tracker; void initialize_alignments(); @@ -134,11 +81,6 @@ class G1CollectorPolicy: public CollectorPolicy { double _ratio_over_threshold_sum; uint _pauses_since_start; - TraceYoungGenTimeData _trace_young_gen_time_data; - TraceOldGenTimeData _trace_old_gen_time_data; - - double _stop_world_start; - uint _young_list_target_length; uint _young_list_fixed_length; @@ -212,9 +154,6 @@ class G1CollectorPolicy: public CollectorPolicy { double update_rs_processed_buffers, double goal_ms); - uintx no_of_gc_threads() { return _no_of_gc_threads; } - void set_no_of_gc_threads(uintx v) { _no_of_gc_threads = v; } - double _pause_time_target_ms; size_t _pending_cards; @@ -389,9 +328,6 @@ private: // an evacuation pause. size_t _inc_cset_bytes_used_before; - // Used to record the highest end of heap region in collection set - HeapWord* _inc_cset_max_finger; - // The RSet lengths recorded for regions in the CSet. It is updated // by the thread that adds a new region to the CSet. We assume that // only one thread can be allocating a new CSet region (currently, @@ -573,9 +509,6 @@ public: virtual void print_phases(); - void record_stop_world_start(); - void record_concurrent_pause(); - // Record how much space we copied during a GC. This is typically // called when a GC alloc region is being retired. void record_bytes_copied_during_gc(size_t bytes) { @@ -685,9 +618,6 @@ public: // Clear ratio tracking data used by expansion_amount(). void clear_ratio_check_data(); - // Print tracing information. - void print_tracing_info() const; - // Print stats on young survival ratio void print_yg_surv_rate_info() const; diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index a6a1d056bd3..edfb510d6fe 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -2662,9 +2662,6 @@ void G1ConcurrentMark::print_on_error(outputStream* st) const { // We take a break if someone is trying to stop the world. bool G1ConcurrentMark::do_yield_check(uint worker_id) { if (SuspendibleThreadSet::should_yield()) { - if (worker_id == 0) { - _g1h->g1_policy()->record_concurrent_pause(); - } SuspendibleThreadSet::yield(); return true; } else { From b1ccba1fcb087e011877017e6e10077bd4fca31f Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Thu, 11 Feb 2016 00:19:38 +0400 Subject: [PATCH 003/311] 8139508: Debug option does not work in appletviewer Reviewed-by: prr, ssadetsky --- .../share/classes/sun/applet/Main.java | 76 ------------------- .../sun/applet/resources/MsgAppletViewer.java | 2 +- 2 files changed, 1 insertion(+), 77 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/sun/applet/Main.java b/jdk/src/java.desktop/share/classes/sun/applet/Main.java index 681fb81c6db..086b1113614 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/Main.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/Main.java @@ -30,8 +30,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.MalformedURLException; import java.util.Enumeration; @@ -75,7 +73,6 @@ public class Main { /** * Member variables set according to options passed in to AppletViewer. */ - private boolean debugFlag = false; private boolean helpFlag = false; private String encoding = null; private boolean noSecurityFlag = false; @@ -136,14 +133,6 @@ public class Main { return 1; } - if (debugFlag) { - // START A DEBUG SESSION - // Given the current architecture, we will end up decoding the - // arguments again, but at least we are guaranteed to have - // arguments which are valid. - return invokeDebugger(args); - } - // INSTALL THE SECURITY MANAGER (if necessary) if (!noSecurityFlag && (System.getSecurityManager() == null)) init(); @@ -191,9 +180,6 @@ public class Main { throw new ParseException(lookup("main.err.dupoption", arg)); encoding = args[++i]; return 2; - } else if ("-debug".equals(arg)) { - debugFlag = true; - return 1; } else if ("-Xnosecurity".equals(arg)) { // This is an undocumented (and, in the future, unsupported) // flag which prevents AppletViewer from installing its own @@ -267,68 +253,6 @@ public class Main { return u; } - /** - * Invoke the debugger with the arguments passed in to appletviewer. - * - * @param args The arguments passed into the debugger. - * @return {@code 0} if the debugger is invoked successfully, - * {@code 1} otherwise. - */ - private int invokeDebugger(String [] args) { - // CONSTRUCT THE COMMAND LINE - String [] newArgs = new String[args.length + 1]; - int current = 0; - - // Add a -classpath argument that prevents - // the debugger from launching appletviewer with the default of - // ".". appletviewer's classpath should never contain valid - // classes since they will result in security exceptions. - // Ideally, the classpath should be set to "", but the VM won't - // allow an empty classpath, so a phony directory name is used. - String phonyDir = System.getProperty("java.home") + - File.separator + "phony"; - newArgs[current++] = "-Djava.class.path=" + phonyDir; - - // Appletviewer's main class is the debuggee - newArgs[current++] = "sun.applet.Main"; - - // Append all the of the original appletviewer arguments, - // leaving out the "-debug" option. - for (int i = 0; i < args.length; i++) { - if (!("-debug".equals(args[i]))) { - newArgs[current++] = args[i]; - } - } - - // LAUNCH THE DEBUGGER - // Reflection is used for two reasons: - // 1) The debugger classes are on classpath and thus must be loaded - // by the application class loader. (Currently, appletviewer are - // loaded through the boot class path out of rt.jar.) - // 2) Reflection removes any build dependency between appletviewer - // and jdb. - try { - Class c = Class.forName("com.sun.tools.example.debug.tty.TTY", true, - ClassLoader.getSystemClassLoader()); - Method m = c.getDeclaredMethod("main", - new Class[] { String[].class }); - m.invoke(null, new Object[] { newArgs }); - } catch (ClassNotFoundException cnfe) { - System.err.println(lookup("main.debug.cantfinddebug")); - return 1; - } catch (NoSuchMethodException nsme) { - System.err.println(lookup("main.debug.cantfindmain")); - return 1; - } catch (InvocationTargetException ite) { - System.err.println(lookup("main.debug.exceptionindebug")); - return 1; - } catch (IllegalAccessException iae) { - System.err.println(lookup("main.debug.cantaccess")); - return 1; - } - return 0; - } - private void init() { // GET APPLETVIEWER USER-SPECIFIC PROPERTIES Properties avProps = getAVProps(); diff --git a/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java b/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java index f05729b972e..2b2bf2de74f 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java @@ -74,7 +74,7 @@ public class MsgAppletViewer extends ListResourceBundle { {"appletviewer.parse.warning.embed.requireswidth", "Warning: tag requires width attribute."}, {"appletviewer.parse.warning.appnotLongersupported", "Warning: tag no longer supported, use instead:"}, {"appletviewer.deprecated", "AppletViewer is deprecated."}, - {"appletviewer.usage", "Usage: appletviewer url(s)\n\nwhere include:\n -debug Start the applet viewer in the Java debugger\n -encoding Specify character encoding used by HTML files\n -J Pass argument to the java interpreter\n\nThe -J option is non-standard and subject to change without notice."}, + {"appletviewer.usage", "Usage: appletviewer url(s)\n\nwhere include:\n -encoding Specify character encoding used by HTML files\n -J Pass argument to the java interpreter\n\nThe -J option is non-standard and subject to change without notice."}, {"appletviewer.main.err.unsupportedopt", "Unsupported option: {0}"}, {"appletviewer.main.err.unrecognizedarg", "Unrecognized argument: {0}"}, {"appletviewer.main.err.dupoption", "Duplicate use of option: {0}"}, From a99085b4db9f5c6448637e257066ee128bbc34d8 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 10 Feb 2016 13:49:06 -0800 Subject: [PATCH 004/311] 8149120: TIFFField constructor throws ArrayIndexOutOfBoundsException and IllegalArgumentException for scenarios explained in description Clean up parameter checking in TIFFField. Reviewed-by: prr --- .../javax/imageio/plugins/tiff/TIFFField.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java index 7afc44520f9..010f841315b 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java @@ -519,6 +519,11 @@ public class TIFFField implements Cloneable { * @throws IllegalArgumentException if type is an unacceptable * data type for the supplied TIFFTag. * @throws IllegalArgumentException if count < 0. + * @throws IllegalArgumentException if count < 1 + * and type is TIFF_RATIONAL or + * TIFF_SRATIONAL. + * @throws IllegalArgumentException if count ≠ 1 + * and type is TIFF_IFD_POINTER. * @throws NullPointerException if data == null. * @throws IllegalArgumentException if data is an instance of * a class incompatible with the specified type. @@ -534,6 +539,14 @@ public class TIFFField implements Cloneable { + " for " + tag.getName() + " tag"); } else if(count < 0) { throw new IllegalArgumentException("count < 0!"); + } else if((type == TIFFTag.TIFF_RATIONAL + || type == TIFFTag.TIFF_SRATIONAL) + && count < 1) { + throw new IllegalArgumentException + ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1"); + } else if (type == TIFFTag.TIFF_IFD_POINTER && count != 1) { + throw new IllegalArgumentException + ("Type is TIFF_IFD_POINTER count != 1"); } else if(data == null) { throw new NullPointerException("data == null!"); } From 7f395c26ab406d415f7a52f05fdbc0bbb13b795f Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Wed, 10 Feb 2016 15:20:41 -0800 Subject: [PATCH 005/311] 8141491: Unaligned memory access in Bits.c Introduce alignment-safe Copy::conjoint_swap and j.i.m.Unsafe.copySwapMemory Reviewed-by: jrose, dholmes, psandoz --- jdk/make/lib/CoreLibraries.gmk | 8 +- jdk/make/mapfiles/libjava/mapfile-vers | 8 +- .../share/classes/java/nio/Bits.java | 142 +++++++++-- .../classes/jdk/internal/misc/Unsafe.java | 74 +++++- jdk/src/java.base/share/native/libjava/Bits.c | 233 ------------------ 5 files changed, 196 insertions(+), 269 deletions(-) delete mode 100644 jdk/src/java.base/share/native/libjava/Bits.c diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index 5cbeb4b03f7..18143462338 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, 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 @@ -137,12 +137,6 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) endif endif -ifeq ($(OPENJDK_TARGET_OS), linux) - ifeq ($(OPENJDK_TARGET_CPU), x86_64) - BUILD_LIBJAVA_Bits.c_CFLAGS := $(C_O_FLAG_NORM) - endif -endif - $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \ LIBRARY := java, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index faf1cc130fe..22d99e7bfcf 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2016, 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 @@ -229,12 +229,6 @@ SUNWprivate_1.1 { Java_java_lang_Throwable_fillInStackTrace; Java_java_lang_Throwable_getStackTraceDepth; Java_java_lang_Throwable_getStackTraceElement; - Java_java_nio_Bits_copyFromShortArray; - Java_java_nio_Bits_copyToShortArray; - Java_java_nio_Bits_copyFromIntArray; - Java_java_nio_Bits_copyToIntArray; - Java_java_nio_Bits_copyFromLongArray; - Java_java_nio_Bits_copyToLongArray; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2; diff --git a/jdk/src/java.base/share/classes/java/nio/Bits.java b/jdk/src/java.base/share/classes/java/nio/Bits.java index 09623eab845..ea4ba276e88 100644 --- a/jdk/src/java.base/share/classes/java/nio/Bits.java +++ b/jdk/src/java.base/share/classes/java/nio/Bits.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -807,31 +807,131 @@ class Bits { // package-private } } - static void copyFromCharArray(Object src, long srcPos, long dstAddr, - long length) - { - copyFromShortArray(src, srcPos, dstAddr, length); + /** + * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory + * + * @param src + * the source array, must be a 16-bit primitive array type + * @param srcPos + * byte offset within source array of the first element to read + * @param dstAddr + * destination address + * @param length + * number of bytes to copy + */ + static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) { + unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2); } - static void copyToCharArray(long srcAddr, Object dst, long dstPos, - long length) - { - copyToShortArray(srcAddr, dst, dstPos, length); + /** + * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array + * + * @param srcAddr + * source address + * @param dst + * destination array, must be a 16-bit primitive array type + * @param dstPos + * byte offset within the destination array of the first element to write + * @param length + * number of bytes to copy + */ + static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) { + unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2); } - static native void copyFromShortArray(Object src, long srcPos, long dstAddr, - long length); - static native void copyToShortArray(long srcAddr, Object dst, long dstPos, - long length); + /** + * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory + * + * @param src + * the source array, must be a 16-bit primitive array type + * @param srcPos + * byte offset within source array of the first element to read + * @param dstAddr + * destination address + * @param length + * number of bytes to copy + */ + static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) { + unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2); + } - static native void copyFromIntArray(Object src, long srcPos, long dstAddr, - long length); - static native void copyToIntArray(long srcAddr, Object dst, long dstPos, - long length); + /** + * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array + * + * @param srcAddr + * source address + * @param dst + * destination array, must be a 16-bit primitive array type + * @param dstPos + * byte offset within the destination array of the first element to write + * @param length + * number of bytes to copy + */ + static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) { + unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2); + } - static native void copyFromLongArray(Object src, long srcPos, long dstAddr, - long length); - static native void copyToLongArray(long srcAddr, Object dst, long dstPos, - long length); + /** + * Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory + * + * @param src + * the source array, must be a 32-bit primitive array type + * @param srcPos + * byte offset within source array of the first element to read + * @param dstAddr + * destination address + * @param length + * number of bytes to copy + */ + static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) { + unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4); + } + /** + * Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array + * + * @param srcAddr + * source address + * @param dst + * destination array, must be a 32-bit primitive array type + * @param dstPos + * byte offset within the destination array of the first element to write + * @param length + * number of bytes to copy + */ + static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) { + unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4); + } + + /** + * Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory + * + * @param src + * the source array, must be a 64-bit primitive array type + * @param srcPos + * byte offset within source array of the first element to read + * @param dstAddr + * destination address + * @param length + * number of bytes to copy + */ + static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) { + unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8); + } + + /** + * Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array + * + * @param srcAddr + * source address + * @param dst + * destination array, must be a 64-bit primitive array type + * @param dstPos + * byte offset within the destination array of the first element to write + * @param length + * number of bytes to copy + */ + static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) { + unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8); + } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index f130d383a84..f17111691f2 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -458,6 +458,78 @@ public final class Unsafe { copyMemory(null, srcAddress, null, destAddress, bytes); } + private boolean isPrimitiveArray(Class c) { + Class componentType = c.getComponentType(); + return componentType != null && componentType.isPrimitive(); + } + + private native void copySwapMemory0(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes, long elemSize); + + /** + * Copies all elements from one block of memory to another block, + * *unconditionally* byte swapping the elements on the fly. + * + *

This method determines each block's base address by means of two parameters, + * and so it provides (in effect) a double-register addressing mode, + * as discussed in {@link #getInt(Object,long)}. When the object reference is null, + * the offset supplies an absolute base address. + * + * @since 9 + */ + public void copySwapMemory(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes, long elemSize) { + if (bytes < 0) { + throw new IllegalArgumentException(); + } + if (elemSize != 2 && elemSize != 4 && elemSize != 8) { + throw new IllegalArgumentException(); + } + if (bytes % elemSize != 0) { + throw new IllegalArgumentException(); + } + if ((srcBase == null && srcOffset == 0) || + (destBase == null && destOffset == 0)) { + throw new NullPointerException(); + } + + // Must be off-heap, or primitive heap arrays + if (srcBase != null && (srcOffset < 0 || !isPrimitiveArray(srcBase.getClass()))) { + throw new IllegalArgumentException(); + } + if (destBase != null && (destOffset < 0 || !isPrimitiveArray(destBase.getClass()))) { + throw new IllegalArgumentException(); + } + + // Sanity check size and offsets on 32-bit platforms. Most + // significant 32 bits must be zero. + if (ADDRESS_SIZE == 4 && + (bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) { + throw new IllegalArgumentException(); + } + + if (bytes == 0) { + return; + } + + copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize); + } + + /** + * Copies all elements from one block of memory to another block, byte swapping the + * elements on the fly. + * + * This provides a single-register addressing mode, as + * discussed in {@link #getInt(Object,long)}. + * + * Equivalent to {@code copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize)}. + */ + public void copySwapMemory(long srcAddress, long destAddress, long bytes, long elemSize) { + copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize); + } + /** * Disposes of a block of native memory, as obtained from {@link * #allocateMemory} or {@link #reallocateMemory}. The address passed to diff --git a/jdk/src/java.base/share/native/libjava/Bits.c b/jdk/src/java.base/share/native/libjava/Bits.c deleted file mode 100644 index f3780199718..00000000000 --- a/jdk/src/java.base/share/native/libjava/Bits.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2002, 2010, 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 "jni_util.h" -#include "jlong.h" -#include - -#define MBYTE 1048576 - -#define GETCRITICAL_OR_RETURN(bytes, env, obj) { \ - bytes = (*env)->GetPrimitiveArrayCritical(env, obj, NULL); \ - if (bytes == NULL) { \ - if ((*env)->ExceptionOccurred(env) == NULL) \ - JNU_ThrowInternalError(env, "Unable to get array"); \ - return; \ - } \ -} - -#define RELEASECRITICAL(bytes, env, obj, mode) { \ - (*env)->ReleasePrimitiveArrayCritical(env, obj, bytes, mode); \ -} - -#define SWAPSHORT(x) ((jshort)(((x) << 8) | (((x) >> 8) & 0xff))) -#define SWAPINT(x) ((jint)((SWAPSHORT((jshort)(x)) << 16) | \ - (SWAPSHORT((jshort)((x) >> 16)) & 0xffff))) -#define SWAPLONG(x) ((jlong)(((jlong)SWAPINT((jint)(x)) << 32) | \ - ((jlong)SWAPINT((jint)((x) >> 32)) & 0xffffffff))) - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyFromShortArray(JNIEnv *env, jclass clazz, jobject src, - jlong srcPos, jlong dstAddr, jlong length) -{ - jbyte *bytes; - size_t size; - jshort *srcShort, *dstShort, *endShort; - jshort tmpShort; - - dstShort = (jshort *)jlong_to_ptr(dstAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, src); - - srcShort = (jshort *)(bytes + srcPos); - endShort = srcShort + (size / sizeof(jshort)); - while (srcShort < endShort) { - tmpShort = *srcShort++; - *dstShort++ = SWAPSHORT(tmpShort); - } - - RELEASECRITICAL(bytes, env, src, JNI_ABORT); - - length -= size; - srcPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jclass clazz, jlong srcAddr, - jobject dst, jlong dstPos, jlong length) -{ - jbyte *bytes; - size_t size; - jshort *srcShort, *dstShort, *endShort; - jshort tmpShort; - - srcShort = (jshort *)jlong_to_ptr(srcAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, dst); - - dstShort = (jshort *)(bytes + dstPos); - endShort = srcShort + (size / sizeof(jshort)); - while (srcShort < endShort) { - tmpShort = *srcShort++; - *dstShort++ = SWAPSHORT(tmpShort); - } - - RELEASECRITICAL(bytes, env, dst, 0); - - length -= size; - dstPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jclass clazz, jobject src, - jlong srcPos, jlong dstAddr, jlong length) -{ - jbyte *bytes; - size_t size; - jint *srcInt, *dstInt, *endInt; - jint tmpInt; - - dstInt = (jint *)jlong_to_ptr(dstAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, src); - - srcInt = (jint *)(bytes + srcPos); - endInt = srcInt + (size / sizeof(jint)); - while (srcInt < endInt) { - tmpInt = *srcInt++; - *dstInt++ = SWAPINT(tmpInt); - } - - RELEASECRITICAL(bytes, env, src, JNI_ABORT); - - length -= size; - srcPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jclass clazz, jlong srcAddr, - jobject dst, jlong dstPos, jlong length) -{ - jbyte *bytes; - size_t size; - jint *srcInt, *dstInt, *endInt; - jint tmpInt; - - srcInt = (jint *)jlong_to_ptr(srcAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, dst); - - dstInt = (jint *)(bytes + dstPos); - endInt = srcInt + (size / sizeof(jint)); - while (srcInt < endInt) { - tmpInt = *srcInt++; - *dstInt++ = SWAPINT(tmpInt); - } - - RELEASECRITICAL(bytes, env, dst, 0); - - length -= size; - dstPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jclass clazz, jobject src, - jlong srcPos, jlong dstAddr, jlong length) -{ - jbyte *bytes; - size_t size; - jlong *srcLong, *dstLong, *endLong; - jlong tmpLong; - - dstLong = (jlong *)jlong_to_ptr(dstAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, src); - - srcLong = (jlong *)(bytes + srcPos); - endLong = srcLong + (size / sizeof(jlong)); - while (srcLong < endLong) { - tmpLong = *srcLong++; - *dstLong++ = SWAPLONG(tmpLong); - } - - RELEASECRITICAL(bytes, env, src, JNI_ABORT); - - length -= size; - srcPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jclass clazz, jlong srcAddr, - jobject dst, jlong dstPos, jlong length) -{ - jbyte *bytes; - size_t size; - jlong *srcLong, *dstLong, *endLong; - jlong tmpLong; - - srcLong = (jlong *)jlong_to_ptr(srcAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, dst); - - dstLong = (jlong *)(bytes + dstPos); - endLong = srcLong + (size / sizeof(jlong)); - while (srcLong < endLong) { - tmpLong = *srcLong++; - *dstLong++ = SWAPLONG(tmpLong); - } - - RELEASECRITICAL(bytes, env, dst, 0); - - length -= size; - dstPos += size; - } -} From 243c8598d5af47d47f82195afaa91d14877f95f6 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Wed, 10 Feb 2016 19:55:57 -0800 Subject: [PATCH 006/311] 8149611: Add tests for Unsafe.copySwapMemory Reviewed-by: dholmes --- .../jdk/internal/misc/Unsafe/CopySwap.java | 711 ++++++++++++++++++ 1 file changed, 711 insertions(+) create mode 100644 jdk/test/jdk/internal/misc/Unsafe/CopySwap.java diff --git a/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java b/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java new file mode 100644 index 00000000000..ba61e23fcc9 --- /dev/null +++ b/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2016, 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 jdk.internal.misc.Unsafe; +import java.lang.reflect.Field; + +/* + * @test + * @summary Test Unsafe.copySwapMemory + * @modules java.base/jdk.internal.misc + */ +public class CopySwap { + private static final boolean DEBUG = Boolean.getBoolean("CopySwap.DEBUG"); + + public static final long KB = 1024; + public static final long MB = KB * 1024; + public static final long GB = MB * 1024; + + private static final Unsafe UNSAFE; + private static final int SMALL_COPY_SIZE = 32; + private static final int BASE_ALIGNMENT = 16; + + static { + try { + Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + UNSAFE = (jdk.internal.misc.Unsafe) f.get(null); + } catch (Exception e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + + private static long alignDown(long value, long alignment) { + return value & ~(alignment - 1); + } + + private static long alignUp(long value, long alignment) { + return (value + alignment - 1) & ~(alignment - 1); + } + + private static boolean isAligned(long value, long alignment) { + return value == alignDown(value, alignment); + } + + private CopySwap() { + } + + /** + * Generate verification data for a given offset + * + * The verification data is used to verify that the correct bytes + * have indeed been copied and byte swapped. + * + * The data is generated based on the offset (in bytes) into the + * source buffer. For a native buffer the offset is relative to + * the base pointer. For a heap array it is relative to the + * address of the first array element. + * + * This method will return the result of doing an elementSize byte + * read starting at offset (in bytes). + * + * @param offset offset into buffer + * @param elemSize size (in bytes) of the element + * + * @return the verification data, only the least significant + * elemSize*8 bits are set, zero extended + */ + private long getVerificationDataForOffset(long offset, long elemSize) { + byte[] bytes = new byte[(int)elemSize]; + + for (long i = 0; i < elemSize; i++) { + bytes[(int)i] = (byte)(offset + i); + } + + long o = UNSAFE.arrayBaseOffset(byte[].class); + + switch ((int)elemSize) { + case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o)); + case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o)); + case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o)); + case 8: return UNSAFE.getLongUnaligned(bytes, o); + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Verify byte swapped data + * + * @param ptr the data to verify + * @param srcOffset the srcOffset (in bytes) from which the copy started, + * used as key to regenerate the verification data + * @param dstOffset the offset (in bytes) in the array at which to start + * the verification, relative to the first element in the array + * @param size size (in bytes) of data to to verify + * @param elemSize size (in bytes) of the individual array elements + * + * @throws RuntimeException if an error is found + */ + private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) { + for (long offset = 0; offset < size; offset += elemSize) { + long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize); + long expected = byteSwap(expectedUnswapped, elemSize); + + long actual = getArrayElem(ptr, dstOffset + offset, elemSize); + + if (expected != actual) { + throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) + + " dstOffset: 0x" + Long.toHexString(dstOffset) + + " size: 0x" + Long.toHexString(size) + + " offset: 0x" + Long.toHexString(offset) + + " expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) + + " expected: 0x" + Long.toHexString(expected) + + " != actual: 0x" + Long.toHexString(actual)); + } + } + } + + /** + * Initialize an array with verification friendly data + * + * @param ptr pointer to the data to initialize + * @param size size (in bytes) of the data + * @param elemSize size (in bytes) of the individual elements + */ + private void initVerificationData(GenericPointer ptr, long size, long elemSize) { + for (long offset = 0; offset < size; offset++) { + byte data = (byte)getVerificationDataForOffset(offset, 1); + + if (ptr.isOnHeap()) { + UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data); + } else { + UNSAFE.putByte(ptr.getOffset() + offset, data); + } + } + } + + /** + * Allocate a primitive array + * + * @param size size (in bytes) of all the array elements (elemSize * length) + * @param elemSize the size of the array elements + * + * @return a newly allocated primitive array + */ + Object allocArray(long size, long elemSize) { + int length = (int)(size / elemSize); + + switch ((int)elemSize) { + case 2: return new short[length]; + case 4: return new int[length]; + case 8: return new long[length]; + default: + throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Get the value of a primitive array entry + * + * @param ptr pointer to the data + * @param offset offset (in bytes) of the array element, relative to the first element in the array + * + * @return the array element, as an unsigned long + */ + private long getArrayElem(GenericPointer ptr, long offset, long elemSize) { + if (ptr.isOnHeap()) { + Object o = ptr.getObject(); + int index = (int)(offset / elemSize); + + if (o instanceof short[]) { + short[] arr = (short[])o; + return Short.toUnsignedLong(arr[index]); + } else if (o instanceof int[]) { + int[] arr = (int[])o; + return Integer.toUnsignedLong(arr[index]); + } else if (o instanceof long[]) { + long[] arr = (long[])o; + return arr[index]; + } else { + throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); + } + } else { + long addr = ptr.getOffset() + offset; + + switch ((int)elemSize) { + case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr)); + case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr)); + case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr)); + case 8: return UNSAFE.getLongUnaligned(null, addr); + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + } + + private void putValue(long addr, long elemSize, long value) { + switch ((int)elemSize) { + case 1: UNSAFE.putByte(addr, (byte)value); break; + case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break; + case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break; + case 8: UNSAFE.putLongUnaligned(null, addr, value); break; + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Get the size of the elements for an array + * + * @param o a primitive heap array + * + * @return the size (in bytes) of the individual array elements + */ + private long getArrayElemSize(Object o) { + if (o instanceof short[]) { + return 2; + } else if (o instanceof int[]) { + return 4; + } else if (o instanceof long[]) { + return 8; + } else { + throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); + } + } + + /** + * Byte swap a value + * + * @param value the value to swap, only the bytes*8 least significant bits are used + * @param size size (in bytes) of the value + * + * @return the byte swapped value in the bytes*8 least significant bits + */ + private long byteSwap(long value, long size) { + switch ((int)size) { + case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value)); + case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value)); + case 8: return Long.reverseBytes(value); + default: throw new IllegalArgumentException("Invalid element size: " + size); + } + } + + /** + * Verify data in a heap array which has *not* been byte swapped + * + * @param ptr the data to verify + * @param startOffset the offset (in bytes) at which to start the verification + * @param size size (in bytes) of the data to verify + * + * @throws RuntimeException if an error is found + */ + private void verifyUnswappedData(GenericPointer ptr, long startOffset, long size) { + for (long elemOffset = startOffset; elemOffset < startOffset + size; elemOffset++) { + byte expected = (byte)getVerificationDataForOffset(elemOffset, 1); + + byte actual; + if (ptr.isOnHeap()) { + actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + elemOffset); + } else { + actual = UNSAFE.getByte(ptr.getOffset() + elemOffset); + } + + if (expected != actual) { + throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) + + " size: 0x" + Long.toHexString(size) + + " elemOffset: 0x" + Long.toHexString(elemOffset) + + " expected: 0x" + Long.toHexString(expected) + + " != actual: 0x" + Long.toHexString(actual)); + } + } + } + + + /** + * Copy and byte swap data from the source to the destination + * + * This method will pre-populate the whole source and destination + * buffers with verification friendly data. It will then use + * copySwapMemory to fill part of the destination buffer with + * swapped data from the source. Some space (padding) will be + * left before and after the data in the destination buffer, which + * should not be touched/overwritten by the copy call. + * + * Note: Both source and destination buffers will be overwritten! + * + * @param src source buffer to copy from + * @param srcOffset the offset (in bytes) in the source buffer, relative to + * the first array element, at which to start reading data + * @param dst destination buffer to copy to + * @param dstOffset the offset (in bytes) in the destination + * buffer, relative to the first array element, at which to + * start writing data + * @param bufSize the size (in bytes) of the src and dst arrays + * @param copyBytes the size (in bytes) of the copy to perform, + * must be a multiple of elemSize + * @param elemSize the size (in bytes) of the elements to byte swap + * + * @throws RuntimeException if an error is found + */ + private void testCopySwap(GenericPointer src, long srcOffset, + GenericPointer dst, long dstOffset, + long bufSize, long copyBytes, long elemSize) { + if (!isAligned(copyBytes, elemSize)) { + throw new IllegalArgumentException( + "copyBytes (" + copyBytes + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (src.isOnHeap() && !isAligned(srcOffset, elemSize)) { + throw new IllegalArgumentException( + "srcOffset (" + srcOffset + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (dst.isOnHeap() && !isAligned(dstOffset, elemSize)) { + throw new IllegalArgumentException( + "dstOffset (" + dstOffset + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (srcOffset + copyBytes > bufSize) { + throw new IllegalArgumentException( + "srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); + } + if (dstOffset + copyBytes > bufSize) { + throw new IllegalArgumentException( + "dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); + } + + // Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes) + initVerificationData(src, bufSize, elemSize); + if (!src.equals(dst)) { + initVerificationData(dst, bufSize, elemSize); + } + + if (DEBUG) { + System.out.println("===before==="); + for (int offset = 0; offset < bufSize; offset += elemSize) { + long srcValue = getArrayElem(src, offset, elemSize); + long dstValue = getArrayElem(dst, offset, elemSize); + + System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + + " src=0x" + Long.toHexString(srcValue) + + " dst=0x" + Long.toHexString(dstValue)); + } + } + + // Copy & swap data into the middle of the destination buffer + UNSAFE.copySwapMemory(src.getObject(), + src.getOffset() + srcOffset, + dst.getObject(), + dst.getOffset() + dstOffset, + copyBytes, + elemSize); + + if (DEBUG) { + System.out.println("===after==="); + for (int offset = 0; offset < bufSize; offset += elemSize) { + long srcValue = getArrayElem(src, offset, elemSize); + long dstValue = getArrayElem(dst, offset, elemSize); + + System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + + " src=0x" + Long.toHexString(srcValue) + + " dst=0x" + Long.toHexString(dstValue)); + } + } + + // Verify the the front padding is unchanged + verifyUnswappedData(dst, 0, dstOffset); + + // Verify swapped data + verifySwappedData(dst, srcOffset, dstOffset, copyBytes, elemSize); + + // Verify that the back back padding is unchanged + long frontAndDataBytes = dstOffset + copyBytes; + long trailingBytes = bufSize - frontAndDataBytes; + verifyUnswappedData(dst, frontAndDataBytes, trailingBytes); + } + + /** + * Test various configurations copy-swapping from one buffer to the other + * + * @param src the source buffer to copy from + * @param dst the destination buffer to copy to + * @param size size (in bytes) of the buffers + * @param elemSize size (in bytes) of the individual elements + * + * @throws RuntimeException if an error is found + */ + public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize) { + // offset in source from which to start reading data + for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) { + + // offset in destination at which to start writing data + for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) { + + // number of bytes to copy + long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset); + for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) { + try { + testCopySwap(src, srcOffset, dst, dstOffset, size, copyBytes, elemSize); + } catch (RuntimeException e) { + // Wrap the exception in another exception to catch the relevant configuration data + throw new RuntimeException("testBufferPair: " + + "src=" + src + + " dst=" + dst + + " elemSize=0x" + Long.toHexString(elemSize) + + " copyBytes=0x" + Long.toHexString(copyBytes) + + " srcOffset=0x" + Long.toHexString(srcOffset) + + " dstOffset=0x" + Long.toHexString(dstOffset), + e); + } + } + } + } + } + + /** + * Test copying between various permutations of buffers + * + * @param buffers buffers to permute (src x dst) + * @param size size (in bytes) of buffers + * @param elemSize size (in bytes) of individual elements + * + * @throws RuntimeException if an error is found + */ + public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize) { + for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) { + for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) { + testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize); + } + } + } + + /** + * Test copying of a specific element size + * + * @param size size (in bytes) of buffers to allocate + * @param elemSize size (in bytes) of individual elements + * + * @throws RuntimeException if an error is found + */ + private void testElemSize(long size, long elemSize) { + long buf1Raw = 0; + long buf2Raw = 0; + + try { + buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT); + + buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT); + + GenericPointer[] buffers = { + new GenericPointer(buf1), + new GenericPointer(buf2), + new GenericPointer(allocArray(size, elemSize)), + new GenericPointer(allocArray(size, elemSize)) + }; + + testPermuteBuffers(buffers, size, elemSize); + } finally { + if (buf1Raw != 0) { + UNSAFE.freeMemory(buf1Raw); + } + if (buf2Raw != 0) { + UNSAFE.freeMemory(buf2Raw); + } + } + } + + /** + * Verify that small copy swaps work + */ + private void testSmallCopy() { + int smallBufSize = SMALL_COPY_SIZE; + + // Test various element types and heap/native combinations + for (long elemSize = 2; elemSize <= 8; elemSize <<= 1) { + testElemSize(smallBufSize, elemSize); + } + } + + + /** + * Verify that large copy swaps work + */ + private void testLargeCopy() { + long size = 2 * GB + 8; + long bufRaw = 0; + + // Check that a large native copy succeeds + try { + try { + bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + } catch (OutOfMemoryError e) { + // Accept failure, skip test + return; + } + + long buf = alignUp(bufRaw, BASE_ALIGNMENT); + + UNSAFE.copySwapMemory(null, buf, null, buf, size, 8); + } catch (Exception e) { + throw new RuntimeException("copySwapMemory of large buffer failed"); + } finally { + if (bufRaw != 0) { + UNSAFE.freeMemory(bufRaw); + } + } + } + + /** + * Run positive tests + * + * @throws RuntimeException if an error is found + */ + private void testPositive() { + testSmallCopy(); + testLargeCopy(); + } + + /** + * Run negative tests, testing corner cases and the various exceptions + * + * @throws RuntimeException if an error is found + */ + private void testNegative() { + long bufRaw = 0; + + try { + bufRaw = UNSAFE.allocateMemory(1024); + long buf = alignUp(bufRaw, BASE_ALIGNMENT); + short[] arr = new short[16]; + + // Check various illegal element sizes + for (int elemSize = 2; elemSize <= 8; elemSize <<= 1) { + long[] illegalSizes = { -1, 1, elemSize - 1, elemSize + 1, elemSize * 2 - 1 }; + for (long size : illegalSizes) { + try { + // Check that illegal elemSize throws an IAE + UNSAFE.copySwapMemory(null, buf, null, buf, size, elemSize); + throw new RuntimeException("copySwapMemory failed to throw IAE for size=" + size + " elemSize=" + elemSize); + } catch (IllegalArgumentException e) { + // good + } + } + } + + try { + // Check that negative srcOffset throws an IAE + UNSAFE.copySwapMemory(arr, -1, arr, UNSAFE.arrayBaseOffset(arr.getClass()), 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset=-1"); + } catch (IllegalArgumentException e) { + // good + } + + try { + // Check that negative dstOffset throws an IAE + UNSAFE.copySwapMemory(arr, UNSAFE.arrayBaseOffset(arr.getClass()), arr, -1, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset=-1"); + } catch (IllegalArgumentException e) { + // good + } + + long illegalElemSizes[] = { 0, 1, 3, 5, 6, 7, 9, 10, -1 }; + for (long elemSize : illegalElemSizes) { + try { + // Check that elemSize 1 throws an IAE + UNSAFE.copySwapMemory(null, buf, null, buf, 16, elemSize); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (IllegalArgumentException e) { + // good + } + } + + try { + // Check that a NULL source throws NPE + UNSAFE.copySwapMemory(null, 0, null, buf, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (NullPointerException e) { + // good + } + + try { + // Check that a NULL destination throws NPE + UNSAFE.copySwapMemory(null, buf, null, 0, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (NullPointerException e) { + // good + } + + try { + // Check that a reference array destination throws IAE + UNSAFE.copySwapMemory(null, buf, new Object[16], UNSAFE.arrayBaseOffset(Object[].class), 16, 8); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (IllegalArgumentException e) { + // good + } + + // Check that invalid source & dest pointers throw IAEs (only relevant on 32-bit platforms) + if (UNSAFE.addressSize() == 4) { + long invalidPtr = (long)1 << 35; // Pick a random bit in upper 32 bits + + try { + // Check that an invalid (not 32-bit clean) source pointer throws IAE + UNSAFE.copySwapMemory(null, invalidPtr, null, buf, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset 0x" + + Long.toHexString(invalidPtr)); + } catch (IllegalArgumentException e) { + // good + } + + try { + // Check that an invalid (not 32-bit clean) source pointer throws IAE + UNSAFE.copySwapMemory(null, buf, null, invalidPtr, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset 0x" + + Long.toHexString(invalidPtr)); + } catch (IllegalArgumentException e) { + // good + } + } + } finally { + if (bufRaw != 0) { + UNSAFE.freeMemory(bufRaw); + } + } + } + + /** + * Run all tests + * + * @throws RuntimeException if an error is found + */ + private void test() { + testPositive(); + testNegative(); + } + + public static void main(String[] args) { + CopySwap cs = new CopySwap(); + cs.test(); + } + + /** + * Helper class to represent a "pointer" - either a heap array or + * a pointer to a native buffer. + * + * In the case of a native pointer, the Object is null and the offset is + * the absolute address of the native buffer. + * + * In the case of a heap object, the Object is a primitive array, and + * the offset will be set to the base offset to the first element, meaning + * the object and the offset together form a double-register pointer. + */ + static class GenericPointer { + private final Object o; + private final long offset; + + private GenericPointer(Object o, long offset) { + this.o = o; + this.offset = offset; + } + + public String toString() { + return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")"; + } + + public boolean equals(Object other) { + if (!(other instanceof GenericPointer)) { + return false; + } + + GenericPointer otherp = (GenericPointer)other; + + return o == otherp.o && offset == otherp.offset; + } + + GenericPointer(Object o) { + this(o, UNSAFE.arrayBaseOffset(o.getClass())); + } + + GenericPointer(long offset) { + this(null, offset); + } + + public boolean isOnHeap() { + return o != null; + } + + public Object getObject() { + return o; + } + + public long getOffset() { + return offset; + } + } +} From 073470bedbb36f543f9015df4b473621465896d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Bourg=C3=A8s?= Date: Thu, 11 Feb 2016 09:08:15 +0100 Subject: [PATCH 007/311] 8149338: JVM Crash caused by Marlin renderer not handling NaN coordinates Use first / last Y crossings to compute edge min/max Y and ensure consistency with edgeBuckets / edgeBucketCounts arrays Reviewed-by: flar, prr --- .../classes/sun/java2d/marlin/Renderer.java | 55 ++++--- jdk/test/sun/java2d/marlin/CrashNaNTest.java | 143 ++++++++++++++++++ .../sun/java2d/marlin/TextClipErrorTest.java | 22 +-- 3 files changed, 178 insertions(+), 42 deletions(-) create mode 100644 jdk/test/sun/java2d/marlin/CrashNaNTest.java diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java index aacd8b2062d..cd063867280 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java @@ -148,8 +148,8 @@ final class Renderer implements PathConsumer2D, MarlinConst { ////////////////////////////////////////////////////////////////////////////// // EDGE LIST ////////////////////////////////////////////////////////////////////////////// - private float edgeMinY = Float.POSITIVE_INFINITY; - private float edgeMaxY = Float.NEGATIVE_INFINITY; + private int edgeMinY = Integer.MAX_VALUE; + private int edgeMaxY = Integer.MIN_VALUE; private float edgeMinX = Float.POSITIVE_INFINITY; private float edgeMaxX = Float.NEGATIVE_INFINITY; @@ -357,18 +357,21 @@ final class Renderer implements PathConsumer2D, MarlinConst { } return; } - // edge min/max X/Y are in subpixel space (inclusive) - if (y1 < edgeMinY) { - edgeMinY = y1; + + // edge min/max X/Y are in subpixel space (inclusive) within bounds: + // note: Use integer crossings to ensure consistent range within + // edgeBuckets / edgeBucketCounts arrays in case of NaN values (int = 0) + if (firstCrossing < edgeMinY) { + edgeMinY = firstCrossing; } - if (y2 > edgeMaxY) { - edgeMaxY = y2; + if (lastCrossing > edgeMaxY) { + edgeMaxY = lastCrossing; } // Use double-precision for improved accuracy: final double x1d = x1; final double y1d = y1; - final double slope = (x2 - x1d) / (y2 - y1d); + final double slope = (x1d - x2) / (y1d - y2); if (slope >= 0.0) { // <==> x1 < x2 if (x1 < edgeMinX) { @@ -504,7 +507,7 @@ final class Renderer implements PathConsumer2D, MarlinConst { private float x0, y0; // Position of most recent 'moveTo' command - private float pix_sx0, pix_sy0; + private float sx0, sy0; // per-thread renderer context final RendererContext rdrCtx; @@ -570,8 +573,8 @@ final class Renderer implements PathConsumer2D, MarlinConst { edgeBucketCounts = rdrCtx.getIntArray(edgeBucketsLength); } - edgeMinY = Float.POSITIVE_INFINITY; - edgeMaxY = Float.NEGATIVE_INFINITY; + edgeMinY = Integer.MAX_VALUE; + edgeMaxY = Integer.MIN_VALUE; edgeMinX = Float.POSITIVE_INFINITY; edgeMaxX = Float.NEGATIVE_INFINITY; @@ -628,7 +631,7 @@ final class Renderer implements PathConsumer2D, MarlinConst { blkFlags = blkFlags_initial; } - if (edgeMinY != Float.POSITIVE_INFINITY) { + if (edgeMinY != Integer.MAX_VALUE) { // if context is maked as DIRTY: if (rdrCtx.dirty) { // may happen if an exception if thrown in the pipeline processing: @@ -688,16 +691,18 @@ final class Renderer implements PathConsumer2D, MarlinConst { @Override public void moveTo(float pix_x0, float pix_y0) { closePath(); - this.pix_sx0 = pix_x0; - this.pix_sy0 = pix_y0; - this.y0 = tosubpixy(pix_y0); - this.x0 = tosubpixx(pix_x0); + final float sx = tosubpixx(pix_x0); + final float sy = tosubpixy(pix_y0); + this.sx0 = sx; + this.sy0 = sy; + this.x0 = sx; + this.y0 = sy; } @Override public void lineTo(float pix_x1, float pix_y1) { - float x1 = tosubpixx(pix_x1); - float y1 = tosubpixy(pix_y1); + final float x1 = tosubpixx(pix_x1); + final float y1 = tosubpixy(pix_y1); addLine(x0, y0, x1, y1); x0 = x1; y0 = y1; @@ -729,8 +734,9 @@ final class Renderer implements PathConsumer2D, MarlinConst { @Override public void closePath() { - // lineTo expects its input in pixel coordinates. - lineTo(pix_sx0, pix_sy0); + addLine(x0, y0, sx0, sy0); + x0 = sx0; + y0 = sy0; } @Override @@ -1396,7 +1402,7 @@ final class Renderer implements PathConsumer2D, MarlinConst { if (doMonitors) { RendererContext.stats.mon_rdr_endRendering.start(); } - if (edgeMinY == Float.POSITIVE_INFINITY) { + if (edgeMinY == Integer.MAX_VALUE) { return false; // undefined edges bounds } @@ -1407,11 +1413,10 @@ final class Renderer implements PathConsumer2D, MarlinConst { final int spminX = FloatMath.max(FloatMath.ceil_int(edgeMinX - 0.5f), boundsMinX); final int spmaxX = FloatMath.min(FloatMath.ceil_int(edgeMaxX - 0.5f), boundsMaxX - 1); - // y1 (and y2) are already biased by -0.5 in tosubpixy(): - final int spminY = FloatMath.max(FloatMath.ceil_int(edgeMinY), _boundsMinY); - int maxY = FloatMath.ceil_int(edgeMaxY); - + // edge Min/Max Y are already rounded to subpixels within bounds: + final int spminY = edgeMinY; final int spmaxY; + int maxY = edgeMaxY; if (maxY <= _boundsMaxY - 1) { spmaxY = maxY; diff --git a/jdk/test/sun/java2d/marlin/CrashNaNTest.java b/jdk/test/sun/java2d/marlin/CrashNaNTest.java new file mode 100644 index 00000000000..01e32dd6c11 --- /dev/null +++ b/jdk/test/sun/java2d/marlin/CrashNaNTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016, 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.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Path2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import static java.lang.Double.NaN; +import java.util.Locale; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8149338 + * @summary Verifies that Marlin supports NaN coordinates and no JVM crash happens ! + * @run main CrashNaNTest + */ +public class CrashNaNTest { + + static final boolean SAVE_IMAGE = false; + + public static void main(String argv[]) { + Locale.setDefault(Locale.US); + + // initialize j.u.l Looger: + final Logger log = Logger.getLogger("sun.java2d.marlin"); + log.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + Throwable th = record.getThrown(); + // detect any Throwable: + if (th != null) { + System.out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(System.out); + + throw new RuntimeException("Test failed: ", th); + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }); + + // enable Marlin logging & internal checks: + System.setProperty("sun.java2d.renderer.log", "true"); + System.setProperty("sun.java2d.renderer.useLogger", "true"); + System.setProperty("sun.java2d.renderer.doChecks", "true"); + + final int width = 400; + final int height = 400; + + final BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setBackground(Color.WHITE); + g2d.clearRect(0, 0, width, height); + + final Path2D.Double path = new Path2D.Double(); + path.moveTo(30, 30); + path.lineTo(100, 100); + + for (int i = 0; i < 20000; i++) { + path.lineTo(110 + 0.01 * i, 110); + path.lineTo(111 + 0.01 * i, 100); + } + + path.lineTo(NaN, 200); + path.lineTo(200, 200); + path.lineTo(200, NaN); + path.lineTo(300, 300); + path.lineTo(NaN, NaN); + path.lineTo(100, 100); + path.closePath(); + + final Path2D.Double path2 = new Path2D.Double(); + path2.moveTo(0,0); + path2.lineTo(width,height); + path2.lineTo(10, 10); + path2.closePath(); + + for (int i = 0; i < 1; i++) { + final long start = System.nanoTime(); + g2d.setColor(Color.BLUE); + g2d.fill(path); + + g2d.fill(path2); + + final long time = System.nanoTime() - start; + System.out.println("paint: duration= " + (1e-6 * time) + " ms."); + } + + if (SAVE_IMAGE) { + try { + final File file = new File("CrashNaNTest.png"); + System.out.println("Writing file: " + + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } catch (IOException ex) { + System.out.println("Writing file failure:"); + ex.printStackTrace(); + } + } + } finally { + g2d.dispose(); + } + } +} diff --git a/jdk/test/sun/java2d/marlin/TextClipErrorTest.java b/jdk/test/sun/java2d/marlin/TextClipErrorTest.java index efce137256c..c6d42ceb305 100644 --- a/jdk/test/sun/java2d/marlin/TextClipErrorTest.java +++ b/jdk/test/sun/java2d/marlin/TextClipErrorTest.java @@ -69,24 +69,12 @@ public class TextClipErrorTest { @Override public void publish(LogRecord record) { Throwable th = record.getThrown(); - // detect potential Throwable thrown by XxxArrayCache.check(): - if (th != null && th.getClass() == Throwable.class) { - StackTraceElement[] stackElements = th.getStackTrace(); + // detect any Throwable: + if (th != null) { + System.out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(System.out); - for (int i = 0; i < stackElements.length; i++) { - StackTraceElement e = stackElements[i]; - - if (e.getClassName().startsWith("sun.java2d.marlin") - && e.getClassName().contains("ArrayCache") - && "check".equals(e.getMethodName())) - { - System.out.println("Test failed:\n" - + record.getMessage()); - th.printStackTrace(System.out); - - throw new RuntimeException("Test failed: ", th); - } - } + throw new RuntimeException("Test failed: ", th); } } From 5b56cd34c174414d624ea333d0a0ece66c522ace Mon Sep 17 00:00:00 2001 From: Vikrant Agarwal Date: Thu, 11 Feb 2016 12:24:28 +0300 Subject: [PATCH 008/311] 8131751: [TEST_BUG] Test javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java fails UnsupportedOperationException Reviewed-by: alexsch, ssadetsky --- .../swing/plaf/gtk/crash/RenderBadPictureCrash.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java b/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java index 0ef16996cf5..71a2e6f4b58 100644 --- a/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java +++ b/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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,16 +23,15 @@ /* @test - @bug 8056151 + @bug 8056151 8131751 @summary Switching to GTK L&F on-the-fly leads to X Window System error RenderBadPicture @run main/othervm -Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel -Dsun.java2d.xrender=T RenderBadPictureCrash */ - import java.awt.Color; +import java.awt.GraphicsDevice; import java.lang.reflect.InvocationTargetException; import javax.swing.JFrame; import javax.swing.SwingUtilities; - import javax.swing.UIManager; public class RenderBadPictureCrash { @@ -41,7 +40,10 @@ public class RenderBadPictureCrash { SwingUtilities.invokeAndWait(() -> { JFrame f = new JFrame(); f.setUndecorated(true); - f.setBackground(new Color(0, 0, 0, 0)); + GraphicsDevice gd = f.getGraphicsConfiguration().getDevice(); + if (gd.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) { + f.setBackground(new Color(0, 0, 0, 0)); + } f.setSize(200, 300); f.setVisible(true); From 3e6267d50c014c46c420b7dbd9828f228810e90d Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 11 Feb 2016 13:42:53 -0800 Subject: [PATCH 009/311] 8149593: Change foo to {@code foo} in TIFF plugin classes Change foo to {@code foo} in TIFF plugin classes and 2015 to 2016 where needed. Reviewed-by: prr, darcy --- .../plugins/tiff/TIFFBaseJPEGCompressor.java | 22 +- .../plugins/tiff/TIFFColorConverter.java | 24 +- .../imageio/plugins/tiff/TIFFCompressor.java | 64 +-- .../plugins/tiff/TIFFDecompressor.java | 504 +++++++++--------- .../plugins/tiff/TIFFExifJPEGCompressor.java | 4 +- .../plugins/tiff/TIFFFaxCompressor.java | 10 +- .../imageio/plugins/tiff/TIFFFieldNode.java | 2 +- .../com/sun/imageio/plugins/tiff/TIFFIFD.java | 10 +- .../plugins/tiff/TIFFImageMetadata.java | 6 +- .../imageio/plugins/tiff/TIFFImageReader.java | 4 +- .../plugins/tiff/TIFFImageWriteParam.java | 18 +- .../imageio/plugins/tiff/TIFFImageWriter.java | 52 +- .../plugins/tiff/TIFFJPEGCompressor.java | 6 +- .../plugins/tiff/TIFFLZWDecompressor.java | 4 +- .../sun/imageio/plugins/tiff/TIFFLZWUtil.java | 4 +- .../plugins/tiff/TIFFNullDecompressor.java | 10 +- .../plugins/tiff/TIFFOldJPEGDecompressor.java | 4 +- .../plugins/tiff/TIFFRLECompressor.java | 6 +- .../plugins/tiff/TIFFRenderedImage.java | 14 +- .../plugins/tiff/TIFFT4Compressor.java | 8 +- .../plugins/tiff/TIFFT6Compressor.java | 4 +- .../plugins/tiff/BaselineTIFFTagSet.java | 6 +- .../imageio/plugins/tiff/ExifGPSTagSet.java | 8 +- .../tiff/ExifInteroperabilityTagSet.java | 6 +- .../plugins/tiff/ExifParentTIFFTagSet.java | 6 +- .../imageio/plugins/tiff/ExifTIFFTagSet.java | 12 +- .../imageio/plugins/tiff/FaxTIFFTagSet.java | 6 +- .../imageio/plugins/tiff/GeoTIFFTagSet.java | 8 +- .../imageio/plugins/tiff/TIFFDirectory.java | 118 ++-- .../javax/imageio/plugins/tiff/TIFFField.java | 368 ++++++------- .../plugins/tiff/TIFFImageReadParam.java | 44 +- .../javax/imageio/plugins/tiff/TIFFTag.java | 84 +-- .../imageio/plugins/tiff/TIFFTagSet.java | 40 +- 33 files changed, 743 insertions(+), 743 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java index 5bb49a5bef7..46185618913 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -86,16 +86,16 @@ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { /** * Whether to write abbreviated JPEG streams (default == false). - * A subclass which sets this to true should also + * A subclass which sets this to {@code true} should also * initialized {@link #JPEGStreamMetadata}. */ protected boolean writeAbbreviatedStream = false; /** * Stream metadata equivalent to a tables-only stream such as in - * the JPEGTables. Default value is null. + * the {@code JPEGTables}. Default value is {@code null}. * This should be set by any subclass which sets - * {@link writeAbbreviatedStream} to true. + * {@link writeAbbreviatedStream} to {@code true}. */ protected IIOMetadata JPEGStreamMetadata = null; @@ -108,15 +108,15 @@ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { /** * Removes nonessential nodes from a JPEG native image metadata tree. * All nodes derived from JPEG marker segments other than DHT, DQT, - * SOF, SOS segments are removed unless pruneTables is - * true in which case the nodes derived from the DHT and + * SOF, SOS segments are removed unless {@code pruneTables} is + * {@code true} in which case the nodes derived from the DHT and * DQT marker segments are also removed. * * @param tree A javax_imageio_jpeg_image_1.0 tree. * @param pruneTables Whether to prune Huffman and quantization tables. - * @throws NullPointerException if tree is - * null. - * @throws IllegalArgumentException if tree is not the root + * @throws NullPointerException if {@code tree} is + * {@code null}. + * @throws IllegalArgumentException if {@code tree} is not the root * of a JPEG native image metadata tree. */ private static void pruneNodes(Node tree, boolean pruneTables) { @@ -182,8 +182,8 @@ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { } /** - * A ByteArrayOutputStream which allows writing to an - * ImageOutputStream. + * A {@code ByteArrayOutputStream} which allows writing to an + * {@code ImageOutputStream}. */ private static class IIOByteArrayOutputStream extends ByteArrayOutputStream { IIOByteArrayOutputStream() { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java index 3138974ad00..14aa2540acb 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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,39 +31,39 @@ package com.sun.imageio.plugins.tiff; public abstract class TIFFColorConverter { /** - * Constructs an instance of a TIFFColorConverter. + * Constructs an instance of a {@code TIFFColorConverter}. */ public TIFFColorConverter() {} /** * Converts an RGB triple into the native color space of this * TIFFColorConverter, and stores the result in the first three - * entries of the result array. + * entries of the {@code result} array. * * @param r the red value. * @param g the green value. * @param b the blue value. - * @param result an array of floats containing three elements. - * @throws NullPointerException if result is - * null. + * @param result an array of {@code float}s containing three elements. + * @throws NullPointerException if {@code result} is + * {@code null}. * @throws ArrayIndexOutOfBoundsException if - * result.length < 3. + * {@code result.length < 3}. */ public abstract void fromRGB(float r, float g, float b, float[] result); /** * Converts a triple in the native color space of this * TIFFColorConverter into an RGB triple, and stores the result in - * the first three entries of the rgb array. + * the first three entries of the {@code rgb} array. * * @param x0 the value of channel 0. * @param x1 the value of channel 1. * @param x2 the value of channel 2. - * @param rgb an array of floats containing three elements. - * @throws NullPointerException if rgb is - * null. + * @param rgb an array of {@code float}s containing three elements. + * @throws NullPointerException if {@code rgb} is + * {@code null}. * @throws ArrayIndexOutOfBoundsException if - * rgb.length < 3. + * {@code rgb.length < 3}. */ public abstract void toRGB(float x0, float x1, float x2, float[] rgb); } diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java index cc72f85cea8..ce1b2a58fa1 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -35,13 +35,13 @@ import javax.imageio.stream.ImageOutputStream; public abstract class TIFFCompressor { /** - * The ImageWriter calling this - * TIFFCompressor. + * The {@code ImageWriter} calling this + * {@code TIFFCompressor}. */ protected ImageWriter writer; /** - * The IIOMetadata object containing metadata for the + * The {@code IIOMetadata} object containing metadata for the * current image. */ protected IIOMetadata metadata; @@ -63,7 +63,7 @@ public abstract class TIFFCompressor { protected boolean isCompressionLossless; /** - * The ImageOutputStream to be written. + * The {@code ImageOutputStream} to be written. */ protected ImageOutputStream stream; @@ -75,26 +75,26 @@ public abstract class TIFFCompressor { * to provide the implementation of the compression algorithm of an * unsupported compression type. * - *

The parameters compressionTagValue and - * isCompressionLossless are provided to accomodate + *

The parameters {@code compressionTagValue} and + * {@code isCompressionLossless} are provided to accomodate * compression types which are unknown. A compression type is * "known" if it is either among those already supported by the * TIFF writer (see {@link TIFFImageWriteParam}), or is listed in * the TIFF 6.0 specification but not supported. If the compression - * type is unknown, the compressionTagValue and - * isCompressionLossless parameters are ignored.

+ * type is unknown, the {@code compressionTagValue} and + * {@code isCompressionLossless} parameters are ignored.

* * @param compressionType The name of the compression type. * @param compressionTagValue The value to be assigned to the TIFF * Compression tag in the TIFF image metadata; ignored if - * compressionType is a known type. + * {@code compressionType} is a known type. * @param isCompressionLossless Whether the compression is lossless; - * ignored if compressionType is a known type. + * ignored if {@code compressionType} is a known type. * - * @throws NullPointerException if compressionType is - * null. - * @throws IllegalArgumentException if compressionTagValue is - * less 1. + * @throws NullPointerException if {@code compressionType} is + * {@code null}. + * @throws IllegalArgumentException if {@code compressionTagValue} is + * less {@code 1}. */ public TIFFCompressor(String compressionType, int compressionTagValue, @@ -163,9 +163,9 @@ public abstract class TIFFCompressor { } /** - * Sets the ImageOutputStream to be written. + * Sets the {@code ImageOutputStream} to be written. * - * @param stream an ImageOutputStream to be written. + * @param stream an {@code ImageOutputStream} to be written. * * @see #getStream */ @@ -174,9 +174,9 @@ public abstract class TIFFCompressor { } /** - * Returns the ImageOutputStream that will be written. + * Returns the {@code ImageOutputStream} that will be written. * - * @return an ImageOutputStream. + * @return an {@code ImageOutputStream}. * * @see #setStream(ImageOutputStream) */ @@ -185,9 +185,9 @@ public abstract class TIFFCompressor { } /** - * Sets the value of the writer field. + * Sets the value of the {@code writer} field. * - * @param writer the current ImageWriter. + * @param writer the current {@code ImageWriter}. * * @see #getWriter() */ @@ -196,9 +196,9 @@ public abstract class TIFFCompressor { } /** - * Returns the current ImageWriter. + * Returns the current {@code ImageWriter}. * - * @return an ImageWriter. + * @return an {@code ImageWriter}. * * @see #setWriter(ImageWriter) */ @@ -207,9 +207,9 @@ public abstract class TIFFCompressor { } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() @@ -219,9 +219,9 @@ public abstract class TIFFCompressor { } /** - * Returns the current IIOMetadata object. + * Returns the current {@code IIOMetadata} object. * - * @return the IIOMetadata object for the image being + * @return the {@code IIOMetadata} object for the image being * written. * * @see #setMetadata(IIOMetadata) @@ -232,15 +232,15 @@ public abstract class TIFFCompressor { /** * Encodes the supplied image data, writing to the currently set - * ImageOutputStream. + * {@code ImageOutputStream}. * - * @param b an array of bytes containing the packed + * @param b an array of {@code byte}s containing the packed * but uncompressed image data. * @param off the starting offset of the data to be written in the - * array b. + * array {@code b}. * @param width the width of the rectangle of pixels to be written. * @param height the height of the rectangle of pixels to be written. - * @param bitsPerSample an array of ints indicting + * @param bitsPerSample an array of {@code int}s indicting * the number of bits used to represent each image sample within * a pixel. * @param scanlineStride the number of bytes separating each @@ -249,7 +249,7 @@ public abstract class TIFFCompressor { * @return the number of bytes written. * * @throws IOException if the supplied data cannot be encoded by - * this TIFFCompressor, or if any I/O error occurs + * this {@code TIFFCompressor}, or if any I/O error occurs * during writing. */ public abstract int encode(byte[] b, int off, diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java index fdc29f26016..bdd31218e03 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -81,7 +81,7 @@ import com.sun.imageio.plugins.common.SimpleCMYKColorSpace; * *

Decompressors may be written with various levels of complexity. * The most complex decompressors will override the - * decode method, and will perform all the work of + * {@code decode} method, and will perform all the work of * decoding, subsampling, offsetting, clipping, and format conversion. * This approach may be the most efficient, since it is possible to * avoid the use of extra image buffers, and it may be possible to @@ -89,35 +89,35 @@ import com.sun.imageio.plugins.common.SimpleCMYKColorSpace; * the destination. * *

Less ambitious decompressors may override the - * decodeRaw method, which is responsible for + * {@code decodeRaw} method, which is responsible for * decompressing the entire tile or strip into a byte array (or other * appropriate datatype). The default implementation of - * decode will perform all necessary setup of buffers, - * call decodeRaw to perform the actual decoding, perform + * {@code decode} will perform all necessary setup of buffers, + * call {@code decodeRaw} to perform the actual decoding, perform * subsampling, and copy the results into the final destination image. * Where possible, it will pass the real image buffer to - * decodeRaw in order to avoid making an extra copy. + * {@code decodeRaw} in order to avoid making an extra copy. * *

Slightly more ambitious decompressors may override - * decodeRaw, but avoid writing pixels that will be + * {@code decodeRaw}, but avoid writing pixels that will be * discarded in the subsampling phase. */ public abstract class TIFFDecompressor { /** - * The ImageReader calling this - * TIFFDecompressor. + * The {@code ImageReader} calling this + * {@code TIFFDecompressor}. */ protected ImageReader reader; /** - * The IIOMetadata object containing metadata for the + * The {@code IIOMetadata} object containing metadata for the * current image. */ protected IIOMetadata metadata; /** - * The value of the PhotometricInterpretation tag. + * The value of the {@code PhotometricInterpretation} tag. * Legal values are {@link * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO }, * {@link @@ -135,7 +135,7 @@ public abstract class TIFFDecompressor { protected int photometricInterpretation; /** - * The value of the Compression tag. Legal values are + * The value of the {@code Compression} tag. Legal values are * {@link BaselineTIFFTagSet#COMPRESSION_NONE}, {@link * BaselineTIFFTagSet#COMPRESSION_CCITT_RLE}, {@link * BaselineTIFFTagSet#COMPRESSION_CCITT_T_4}, {@link @@ -151,23 +151,23 @@ public abstract class TIFFDecompressor { protected int compression; /** - * true if the image is encoded using separate planes. + * {@code true} if the image is encoded using separate planes. */ protected boolean planar; /** - * The value of the SamplesPerPixel tag. + * The value of the {@code SamplesPerPixel} tag. */ protected int samplesPerPixel; /** - * The value of the BitsPerSample tag. + * The value of the {@code BitsPerSample} tag. * */ protected int[] bitsPerSample; /** - * The value of the SampleFormat tag. Legal values + * The value of the {@code SampleFormat} tag. Legal values * are {@link BaselineTIFFTagSet#SAMPLE_FORMAT_UNSIGNED_INTEGER}, * {@link BaselineTIFFTagSet#SAMPLE_FORMAT_SIGNED_INTEGER}, {@link * BaselineTIFFTagSet#SAMPLE_FORMAT_FLOATING_POINT}, {@link @@ -178,7 +178,7 @@ public abstract class TIFFDecompressor { new int[] {BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER}; /** - * The value of the ExtraSamples tag. Legal values + * The value of the {@code ExtraSamples} tag. Legal values * are {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNSPECIFIED}, * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_ASSOCIATED_ALPHA}, * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNASSOCIATED_ALPHA}, @@ -187,7 +187,7 @@ public abstract class TIFFDecompressor { protected int[] extraSamples; /** - * The value of the ColorMap tag. + * The value of the {@code ColorMap} tag. * */ protected char[] colorMap; @@ -195,20 +195,20 @@ public abstract class TIFFDecompressor { // Region of input stream containing the data /** - * The ImageInputStream containing the TIFF source + * The {@code ImageInputStream} containing the TIFF source * data. */ protected ImageInputStream stream; /** - * The offset in the source ImageInputStream of the + * The offset in the source {@code ImageInputStream} of the * start of the data to be decompressed. */ protected long offset; /** * The number of bytes of data from the source - * ImageInputStream to be decompressed. + * {@code ImageInputStream} to be decompressed. */ protected int byteCount; @@ -244,15 +244,15 @@ public abstract class TIFFDecompressor { // Subsampling to be performed /** - * The source X offset used, along with dstXOffset - * and subsampleX, to map between horizontal source + * The source X offset used, along with {@code dstXOffset} + * and {@code subsampleX}, to map between horizontal source * and destination pixel coordinates. */ protected int sourceXOffset; /** * The horizontal destination offset used, along with - * sourceXOffset and subsampleX, to map + * {@code sourceXOffset} and {@code subsampleX}, to map * between horizontal source and destination pixel coordinates. * See the comment for {@link #sourceXOffset sourceXOffset} for * the mapping equations. @@ -260,15 +260,15 @@ public abstract class TIFFDecompressor { protected int dstXOffset; /** - * The source Y offset used, along with dstYOffset - * and subsampleY, to map between vertical source and + * The source Y offset used, along with {@code dstYOffset} + * and {@code subsampleY}, to map between vertical source and * destination pixel coordinates. */ protected int sourceYOffset; /** * The vertical destination offset used, along with - * sourceYOffset and subsampleY, to map + * {@code sourceYOffset} and {@code subsampleY}, to map * between horizontal source and destination pixel coordinates. * See the comment for {@link #sourceYOffset sourceYOffset} for * the mapping equations. @@ -305,7 +305,7 @@ public abstract class TIFFDecompressor { // Destination for decodeRaw /** - * A BufferedImage for the decodeRaw + * A {@code BufferedImage} for the {@code decodeRaw} * method to write into. */ protected BufferedImage rawImage; @@ -345,15 +345,15 @@ public abstract class TIFFDecompressor { * The X coordinate of the upper-left source pixel that will * actually be copied into the destination image, taking into * account all subsampling, offsetting, and clipping. That is, - * the pixel at (activeSrcMinX, - * activeSrcMinY) is to be copied into the - * destination pixel at (dstMinX, - * dstMinY). + * the pixel at ({@code activeSrcMinX}, + * {@code activeSrcMinY}) is to be copied into the + * destination pixel at ({@code dstMinX}, + * {@code dstMinY}). * *

The pixels in the source region to be copied are - * those with X coordinates of the form activeSrcMinX + - * k*subsampleX, where k is an integer such - * that 0 ≤ k < dstWidth. + * those with X coordinates of the form {@code activeSrcMinX + + * k*subsampleX}, where {@code k} is an integer such + * that {@code 0 ≤ k < dstWidth}. */ protected int activeSrcMinX; @@ -363,9 +363,9 @@ public abstract class TIFFDecompressor { * all subsampling, offsetting, and clipping. * *

The pixels in the source region to be copied are - * those with Y coordinates of the form activeSrcMinY + - * k*subsampleY, where k is an integer such - * that 0 ≤ k < dstHeight. + * those with Y coordinates of the form {@code activeSrcMinY + + * k*subsampleY}, where {@code k} is an integer such + * that {@code 0 ≤ k < dstHeight}. */ protected int activeSrcMinY; @@ -375,7 +375,7 @@ public abstract class TIFFDecompressor { * susbampling, offsetting, and clipping. * *

The active source width will always be equal to - * (dstWidth - 1)*subsampleX + 1. + * {@code (dstWidth - 1)*subsampleX + 1}. */ protected int activeSrcWidth; @@ -385,13 +385,13 @@ public abstract class TIFFDecompressor { * susbampling, offsetting, and clipping. * *

The active source height will always be equal to - * (dstHeight - 1)*subsampleY + 1. + * {@code (dstHeight - 1)*subsampleY + 1}. */ protected int activeSrcHeight; /** - * A TIFFColorConverter object describing the color space of - * the encoded pixel data, or null. + * A {@code TIFFColorConverter} object describing the color space of + * the encoded pixel data, or {@code null}. */ protected TIFFColorConverter colorConverter; @@ -420,13 +420,13 @@ public abstract class TIFFDecompressor { // to exactly those dest pixels that are present in the source region. /** - * Create a PixelInterleavedSampleModel for use in creating - * an ImageTypeSpecifier. Its dimensions will be 1x1 and + * Create a {@code PixelInterleavedSampleModel} for use in creating + * an {@code ImageTypeSpecifier}. Its dimensions will be 1x1 and * it will have ascending band offsets as {0, 1, 2, ..., numBands}. * * @param dataType The data type (DataBuffer.TYPE_*). * @param numBands The number of bands. - * @return A PixelInterleavedSampleModel. + * @return A {@code PixelInterleavedSampleModel}. */ static SampleModel createInterleavedSM(int dataType, int numBands) { @@ -443,8 +443,8 @@ public abstract class TIFFDecompressor { } /** - * Create a ComponentColorModel for use in creating - * an ImageTypeSpecifier. + * Create a {@code ComponentColorModel} for use in creating + * an {@code ImageTypeSpecifier}. */ // This code was copied from javax.imageio.ImageTypeSpecifier. static ColorModel createComponentCM(ColorSpace colorSpace, @@ -518,8 +518,8 @@ public abstract class TIFFDecompressor { } /** - * Return the number of bits occupied by dataType - * which must be one of the DataBuffer TYPEs. + * Return the number of bits occupied by {@code dataType} + * which must be one of the {@code DataBuffer} {@code TYPE}s. */ private static int getDataTypeSize(int dataType) throws IIOException { int dataTypeSize = 0; @@ -578,7 +578,7 @@ public abstract class TIFFDecompressor { } /** - * Determines whether the DataBuffer is filled without + * Determines whether the {@code DataBuffer} is filled without * any interspersed padding bits. */ private static boolean isDataBufferBitContiguous(SampleModel sm) @@ -678,8 +678,8 @@ public abstract class TIFFDecompressor { } /** - * Reformats bit-discontiguous data into the DataBuffer - * of the supplied WritableRaster. + * Reformats bit-discontiguous data into the {@code DataBuffer} + * of the supplied {@code WritableRaster}. */ private static void reformatDiscontiguousData(byte[] buf, int stride, @@ -715,21 +715,21 @@ public abstract class TIFFDecompressor { /** * A utility method that returns an - * ImageTypeSpecifier suitable for decoding an image + * {@code ImageTypeSpecifier} suitable for decoding an image * with the given parameters. * * @param photometricInterpretation the value of the - * PhotometricInterpretation field. - * @param compression the value of the Compression field. + * {@code PhotometricInterpretation} field. + * @param compression the value of the {@code Compression} field. * @param samplesPerPixel the value of the - * SamplesPerPixel field. - * @param bitsPerSample the value of the BitsPerSample field. - * @param sampleFormat the value of the SampleFormat field. - * @param extraSamples the value of the ExtraSamples field. - * @param colorMap the value of the ColorMap field. + * {@code SamplesPerPixel} field. + * @param bitsPerSample the value of the {@code BitsPerSample} field. + * @param sampleFormat the value of the {@code SampleFormat} field. + * @param extraSamples the value of the {@code ExtraSamples} field. + * @param colorMap the value of the {@code ColorMap} field. * - * @return a suitable ImageTypeSpecifier, or - * null if it is not possible to create one. + * @return a suitable {@code ImageTypeSpecifier}, or + * {@code null} if it is not possible to create one. */ public static ImageTypeSpecifier getRawImageTypeSpecifier(int photometricInterpretation, @@ -1216,26 +1216,26 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the reader field. + * Sets the value of the {@code reader} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param reader the current ImageReader. + * @param reader the current {@code ImageReader}. */ public void setReader(ImageReader reader) { this.reader = reader; } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being read. */ public void setMetadata(IIOMetadata metadata) { @@ -1243,10 +1243,10 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the photometricInterpretation + * Sets the value of the {@code photometricInterpretation} * field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1258,9 +1258,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the compression field. + * Sets the value of the {@code compression} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1271,13 +1271,13 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the planar field. + * Sets the value of the {@code planar} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param planar true if the image to be decoded is + * @param planar {@code true} if the image to be decoded is * stored in planar format. */ public void setPlanar(boolean planar) { @@ -1285,9 +1285,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the samplesPerPixel field. + * Sets the value of the {@code samplesPerPixel} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1299,9 +1299,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the bitsPerSample field. + * Sets the value of the {@code bitsPerSample} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1314,9 +1314,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the sampleFormat field. + * Sets the value of the {@code sampleFormat} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1330,9 +1330,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the extraSamples field. + * Sets the value of the {@code extraSamples} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1346,14 +1346,14 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the colorMap field. + * Sets the value of the {@code colorMap} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * * @param colorMap the color map to apply to the source data, - * as an array of chars. + * as an array of {@code char}s. */ public void setColorMap(char[] colorMap) { this.colorMap = colorMap == null ? @@ -1361,22 +1361,22 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the stream field. + * Sets the value of the {@code stream} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param stream the ImageInputStream to be read. + * @param stream the {@code ImageInputStream} to be read. */ public void setStream(ImageInputStream stream) { this.stream = stream; } /** - * Sets the value of the offset field. + * Sets the value of the {@code offset} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1388,9 +1388,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the byteCount field. + * Sets the value of the {@code byteCount} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1403,9 +1403,9 @@ public abstract class TIFFDecompressor { // Region of the file image represented in the stream /** - * Sets the value of the srcMinX field. + * Sets the value of the {@code srcMinX} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1418,9 +1418,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the srcMinY field. + * Sets the value of the {@code srcMinY} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1433,9 +1433,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the srcWidth field. + * Sets the value of the {@code srcWidth} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1447,9 +1447,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the srcHeight field. + * Sets the value of the {@code srcHeight} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1463,9 +1463,9 @@ public abstract class TIFFDecompressor { // First source pixel to be read /** - * Sets the value of the sourceXOffset field. + * Sets the value of the {@code sourceXOffset} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1477,9 +1477,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstXOffset field. + * Sets the value of the {@code dstXOffset} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1491,9 +1491,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the sourceYOffset. + * Sets the value of the {@code sourceYOffset}. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1505,9 +1505,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstYOffset field. + * Sets the value of the {@code dstYOffset} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1521,15 +1521,15 @@ public abstract class TIFFDecompressor { // Subsampling to be performed /** - * Sets the value of the subsampleX field. + * Sets the value of the {@code subsampleX} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * * @param subsampleX the horizontal subsampling factor. * - * @throws IllegalArgumentException if subsampleX is + * @throws IllegalArgumentException if {@code subsampleX} is * less than or equal to 0. */ public void setSubsampleX(int subsampleX) { @@ -1540,15 +1540,15 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the subsampleY field. + * Sets the value of the {@code subsampleY} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * * @param subsampleY the vertical subsampling factor. * - * @throws IllegalArgumentException if subsampleY is + * @throws IllegalArgumentException if {@code subsampleY} is * less than or equal to 0. */ public void setSubsampleY(int subsampleY) { @@ -1561,13 +1561,13 @@ public abstract class TIFFDecompressor { // Band subsetting/rearrangement /** - * Sets the value of the sourceBands field. + * Sets the value of the {@code sourceBands} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param sourceBands an array of ints + * @param sourceBands an array of {@code int}s * specifying the source bands to be read. */ public void setSourceBands(int[] sourceBands) { @@ -1576,13 +1576,13 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the destinationBands field. + * Sets the value of the {@code destinationBands} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param destinationBands an array of ints + * @param destinationBands an array of {@code int}s * specifying the destination bands to be written. */ public void setDestinationBands(int[] destinationBands) { @@ -1593,22 +1593,22 @@ public abstract class TIFFDecompressor { // Destination image and region /** - * Sets the value of the image field. + * Sets the value of the {@code image} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param image the destination BufferedImage. + * @param image the destination {@code BufferedImage}. */ public void setImage(BufferedImage image) { this.image = image; } /** - * Sets the value of the dstMinX field. + * Sets the value of the {@code dstMinX} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1620,9 +1620,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstMinY field. + * Sets the value of the {@code dstMinY} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1634,9 +1634,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstWidth field. + * Sets the value of the {@code dstWidth} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1647,9 +1647,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstHeight field. + * Sets the value of the {@code dstHeight} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1662,9 +1662,9 @@ public abstract class TIFFDecompressor { // Active source region /** - * Sets the value of the activeSrcMinX field. + * Sets the value of the {@code activeSrcMinX} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1676,9 +1676,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the activeSrcMinY field. + * Sets the value of the {@code activeSrcMinY} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1690,9 +1690,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the activeSrcWidth field. + * Sets the value of the {@code activeSrcWidth} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1703,9 +1703,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the activeSrcHeight field. + * Sets the value of the {@code activeSrcHeight} field. * - *

If this method is called, the beginDecoding + *

If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1716,23 +1716,23 @@ public abstract class TIFFDecompressor { } /** - * Sets the TIFFColorConverter object describing the color + * Sets the {@code TIFFColorConverter} object describing the color * space of the encoded data in the input stream. If no - * TIFFColorConverter is set, no conversion will be performed. + * {@code TIFFColorConverter} is set, no conversion will be performed. * - * @param colorConverter a TIFFColorConverter object, or - * null. + * @param colorConverter a {@code TIFFColorConverter} object, or + * {@code null}. */ public void setColorConverter(TIFFColorConverter colorConverter) { this.colorConverter = colorConverter; } /** - * Returns an ImageTypeSpecifier describing an image + * Returns an {@code ImageTypeSpecifier} describing an image * whose underlying data array has the same format as the raw * source pixel data. * - * @return an ImageTypeSpecifier. + * @return an {@code ImageTypeSpecifier}. */ public ImageTypeSpecifier getRawImageType() { ImageTypeSpecifier its = @@ -1747,18 +1747,18 @@ public abstract class TIFFDecompressor { } /** - * Creates a BufferedImage whose underlying data + * Creates a {@code BufferedImage} whose underlying data * array will be suitable for holding the raw decoded output of - * the decodeRaw method. + * the {@code decodeRaw} method. * *

The default implementation calls - * getRawImageType, and calls the resulting - * ImageTypeSpecifier's - * createBufferedImage method. + * {@code getRawImageType}, and calls the resulting + * {@code ImageTypeSpecifier}'s + * {@code createBufferedImage} method. * - * @return a BufferedImage whose underlying data + * @return a {@code BufferedImage} whose underlying data * array has the same format as the raw source pixel data, or - * null if it is not possible to create such an + * {@code null} if it is not possible to create such an * image. */ public BufferedImage createRawImage() { @@ -1811,22 +1811,22 @@ public abstract class TIFFDecompressor { } /** - * Decodes the source data into the provided byte - * array b, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * bytes. + * Decodes the source data into the provided {@code byte} + * array {@code b}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code byte}s. * - * @param b a byte array to be written. - * @param dstOffset the starting offset in b to be + * @param b a {@code byte} array to be written. + * @param dstOffset the starting offset in {@code b} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of bytes to + * @param scanlineStride the number of {@code byte}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public abstract void decodeRaw(byte[] b, int dstOffset, @@ -1834,25 +1834,25 @@ public abstract class TIFFDecompressor { int scanlineStride) throws IOException; /** - * Decodes the source data into the provided short - * array s, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * shorts + * Decodes the source data into the provided {@code short} + * array {@code s}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code short}s * - *

The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into s. + *

The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code s}. * - * @param s a short array to be written. - * @param dstOffset the starting offset in s to be + * @param s a {@code short} array to be written. + * @param dstOffset the starting offset in {@code s} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of shorts to + * @param scanlineStride the number of {@code short}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(short[] s, int dstOffset, @@ -1891,25 +1891,25 @@ public abstract class TIFFDecompressor { } /** - * Decodes the source data into the provided int - * array i, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * ints. + * Decodes the source data into the provided {@code int} + * array {@code i}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code int}s. * - *

The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into i. + *

The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code i}. * - * @param i an int array to be written. - * @param dstOffset the starting offset in i to be + * @param i an {@code int} array to be written. + * @param dstOffset the starting offset in {@code i} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of ints to + * @param scanlineStride the number of {@code int}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(int[] i, int dstOffset, @@ -1953,25 +1953,25 @@ public abstract class TIFFDecompressor { } /** - * Decodes the source data into the provided float - * array f, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * floats. + * Decodes the source data into the provided {@code float} + * array {@code f}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code float}s. * - *

The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into f. + *

The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code f}. * - * @param f a float array to be written. - * @param dstOffset the starting offset in f to be + * @param f a {@code float} array to be written. + * @param dstOffset the starting offset in {@code f} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of floats to + * @param scanlineStride the number of {@code float}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(float[] f, int dstOffset, @@ -2017,25 +2017,25 @@ public abstract class TIFFDecompressor { } /** - * Decodes the source data into the provided double - * array f, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * doubles. + * Decodes the source data into the provided {@code double} + * array {@code f}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code double}s. * - *

The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into f. + *

The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code f}. * - * @param f a double array to be written. - * @param dstOffset the starting offset in f to be + * @param f a {@code double} array to be written. + * @param dstOffset the starting offset in {@code f} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of doubles to + * @param scanlineStride the number of {@code double}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(double[] d, int dstOffset, @@ -2104,16 +2104,16 @@ public abstract class TIFFDecompressor { /** * This routine is called prior to a sequence of calls to the - * decode method, in order to allow any necessary + * {@code decode} method, in order to allow any necessary * tables or other structures to be initialized based on metadata * values. This routine is guaranteed to be called any time the * metadata values have changed. * *

The default implementation computes tables used by the - * decode method to rescale components to different + * {@code decode} method to rescale components to different * bit depths. Thus, if this method is overridden, it is - * important for the subclass method to call super(), - * unless it overrides decode as well. + * important for the subclass method to call {@code super()}, + * unless it overrides {@code decode} as well. */ public void beginDecoding() { // Note: This method assumes that sourceBands, destinationBands, @@ -2242,35 +2242,35 @@ public abstract class TIFFDecompressor { /** * Decodes the input bit stream (located in the - * ImageInputStream stream, at offset - * offset, and continuing for byteCount - * bytes) into the output BufferedImage - * image. + * {@code ImageInputStream} {@code stream}, at offset + * {@code offset}, and continuing for {@code byteCount} + * bytes) into the output {@code BufferedImage} + * {@code image}. * *

The default implementation analyzes the destination image * to determine if it is suitable as the destination for the - * decodeRaw method. If not, a suitable image is - * created. Next, decodeRaw is called to perform the + * {@code decodeRaw} method. If not, a suitable image is + * created. Next, {@code decodeRaw} is called to perform the * actual decoding, and the results are copied into the * destination image if necessary. Subsampling and offsetting are * performed automatically. * *

The precise responsibilities of this routine are as * follows. The input bit stream is defined by the instance - * variables stream, offset, and - * byteCount. These bits contain the data for the - * region of the source image defined by srcMinX, - * srcMinY, srcWidth, and - * srcHeight. + * variables {@code stream}, {@code offset}, and + * {@code byteCount}. These bits contain the data for the + * region of the source image defined by {@code srcMinX}, + * {@code srcMinY}, {@code srcWidth}, and + * {@code srcHeight}. * *

The source data is required to be subsampling, starting at - * the sourceXOffsetth column and including - * every subsampleXth pixel thereafter (and similarly - * for sourceYOffset and - * subsampleY). + * the {@code sourceXOffset}th column and including + * every {@code subsampleX}th pixel thereafter (and similarly + * for {@code sourceYOffset} and + * {@code subsampleY}). * *

Pixels are copied into the destination with an addition shift of - * (dstXOffset, dstYOffset). The complete + * ({@code dstXOffset}, {@code dstYOffset}). The complete * set of formulas relating the source and destination coordinate spaces * are: * @@ -2279,9 +2279,9 @@ public abstract class TIFFDecompressor { * dy = (sy - sourceYOffset)/subsampleY + dstYOffset; * * - * Only source pixels such that (sx - sourceXOffset) % - * subsampleX == 0 and (sy - sourceYOffset) % - * subsampleY == 0 are copied. + * Only source pixels such that {@code (sx - sourceXOffset) % + * subsampleX == 0} and {@code (sy - sourceYOffset) % + * subsampleY == 0} are copied. * *

The inverse mapping, from destination to source coordinates, * is one-to-one: @@ -2292,9 +2292,9 @@ public abstract class TIFFDecompressor { * * *

The region of the destination image to be updated is given - * by the instance variables dstMinX, - * dstMinY, dstWidth, and - * dstHeight. + * by the instance variables {@code dstMinX}, + * {@code dstMinY}, {@code dstWidth}, and + * {@code dstHeight}. * *

It is possible that not all of the source data being read * will contribute to the destination image. For example, the @@ -2303,32 +2303,32 @@ public abstract class TIFFDecompressor { * convenience, the bounds of the active source region (that is, * the region of the strip or tile being read that actually * contributes to the destination image, taking clipping into - * account) are available as activeSrcMinX, - * activeSrcMinY, activeSrcWidth and - * activeSrcHeight. Thus, the source pixel at - * (activeSrcMinX, activeSrcMinY) will - * map to the destination pixel (dstMinX, - * dstMinY). + * account) are available as {@code activeSrcMinX}, + * {@code activeSrcMinY}, {@code activeSrcWidth} and + * {@code activeSrcHeight}. Thus, the source pixel at + * ({@code activeSrcMinX}, {@code activeSrcMinY}) will + * map to the destination pixel ({@code dstMinX}, + * {@code dstMinY}). * *

The sequence of source bands given by - * sourceBands are to be copied into the sequence of + * {@code sourceBands} are to be copied into the sequence of * bands in the destination given by - * destinationBands. + * {@code destinationBands}. * *

Some standard tag information is provided the instance - * variables photometricInterpretation, - * compression, samplesPerPixel, - * bitsPerSample, sampleFormat, - * extraSamples, and colorMap. + * variables {@code photometricInterpretation}, + * {@code compression}, {@code samplesPerPixel}, + * {@code bitsPerSample}, {@code sampleFormat}, + * {@code extraSamples}, and {@code colorMap}. * *

In practice, unless there is a significant performance * advantage to be gained by overriding this routine, most users * will prefer to use the default implementation of this routine, - * and instead override the decodeRaw and/or - * getRawImageType methods. + * and instead override the {@code decodeRaw} and/or + * {@code getRawImageType} methods. * * @exception IOException if an error occurs in - * decodeRaw. + * {@code decodeRaw}. */ public void decode() throws IOException { byte[] byteData = null; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java index b3e202cb2cd..3541ce110db 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -29,7 +29,7 @@ import javax.imageio.metadata.IIOMetadata; import javax.imageio.plugins.tiff.BaselineTIFFTagSet; /** - * A TIFFCompressor for the JPEG variant of Exif. + * A {@code TIFFCompressor} for the JPEG variant of Exif. */ public class TIFFExifJPEGCompressor extends TIFFBaseJPEGCompressor { public TIFFExifJPEGCompressor(ImageWriteParam param) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java index 9cbf49eb84b..5c126acab53 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -232,12 +232,12 @@ abstract class TIFFFaxCompressor extends TIFFCompressor { } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * *

The implementation in this class also sets local options * from the FILL_ORDER field if it exists.

* - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() @@ -253,8 +253,8 @@ abstract class TIFFFaxCompressor extends TIFFCompressor { } /** - * Return min of maxOffset or offset of first pixel - * different from pixel at bitOffset. + * Return min of {@code maxOffset} or offset of first pixel + * different from pixel at {@code bitOffset}. */ public int nextState(byte[] data, int base, diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java index e78954b34e4..994d10d7810 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java @@ -34,7 +34,7 @@ import javax.imageio.plugins.tiff.TIFFTag; import javax.imageio.plugins.tiff.TIFFTagSet; /** - * The Node representation of a TIFFField + * The {@code Node} representation of a {@code TIFFField} * wherein the child node is procedural rather than buffered. */ public class TIFFFieldNode extends IIOMetadataNode { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java index c60a98c793b..46d1419ee4c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -153,7 +153,7 @@ public class TIFFIFD extends TIFFDirectory { } /** - * Returns an Iterator over the TIFF fields. The + * Returns an {@code Iterator} over the TIFF fields. The * traversal is in the order of increasing tag number. */ // Note: the sort is guaranteed for low fields by the use of an @@ -164,7 +164,7 @@ public class TIFFIFD extends TIFFDirectory { } /** - * Read the value of a field. The data parameter should be + * Read the value of a field. The {@code data} parameter should be * an array of length 1 of Object. * * @param stream the input stream @@ -762,8 +762,8 @@ public class TIFFIFD extends TIFFDirectory { } /** - * Returns a TIFFIFD wherein all fields from the - * BaselineTIFFTagSet are copied by value and all other + * Returns a {@code TIFFIFD} wherein all fields from the + * {@code BaselineTIFFTagSet} are copied by value and all other * fields copied by reference. */ public TIFFIFD getShallowClone() { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java index decebe16f0c..933c2da5a6c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -1620,8 +1620,8 @@ public class TIFFImageMetadata extends IIOMetadata { } /** - * Returns a TIFFImageMetadata wherein all fields in the - * root IFD from the BaselineTIFFTagSet are copied by value + * Returns a {@code TIFFImageMetadata} wherein all fields in the + * root IFD from the {@code BaselineTIFFTagSet} are copied by value * and all other fields copied by reference. */ public TIFFImageMetadata getShallowClone() { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java index 47356e0d6a2..317027351fc 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -83,7 +83,7 @@ public class TIFFImageReader extends ImageReader { // Metadata for image at 'currIndex', or null. private TIFFImageMetadata imageMetadata = null; - // A List of Longs indicating the stream + // A {@code List} of {@code Long}s indicating the stream // positions of the start of the IFD for each image. Entries // are added as needed. private List imageStartPosition = new ArrayList(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java index 21dc5cb7eb4..c30f7ec70f9 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -122,11 +122,11 @@ import javax.imageio.ImageWriteParam; * quality value is passed directly to the JPEG writer plug-in which * interprets it in the usual way.

* - *

The canWriteTiles and - * canWriteCompressed methods will return - * true; the canOffsetTiles and - * canWriteProgressive methods will return - * false.

+ *

The {@code canWriteTiles} and + * {@code canWriteCompressed} methods will return + * {@code true}; the {@code canOffsetTiles} and + * {@code canWriteProgressive} methods will return + * {@code false}.

* *

If tiles are being written, then each of their dimensions will be * rounded to the nearest multiple of 16 per the TIFF specification. If @@ -140,10 +140,10 @@ import javax.imageio.ImageWriteParam; public class TIFFImageWriteParam extends ImageWriteParam { /** - * Constructs a TIFFImageWriteParam instance - * for a given Locale. + * Constructs a {@code TIFFImageWriteParam} instance + * for a given {@code Locale}. * - * @param locale the Locale for which messages + * @param locale the {@code Locale} for which messages * should be localized. */ public TIFFImageWriteParam(Locale locale) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java index ea819e9e968..d0d5c3e5ce0 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -221,11 +221,11 @@ public class TIFFImageWriter extends ImageWriter { * relative to a given tile grid layout specified by its X offset * and tile width. * - *

If tileWidth < 0, the results of this method - * are undefined. If tileWidth == 0, an - * ArithmeticException will be thrown. + *

If {@code tileWidth < 0}, the results of this method + * are undefined. If {@code tileWidth == 0}, an + * {@code ArithmeticException} will be thrown. * - * @throws ArithmeticException If tileWidth == 0. + * @throws ArithmeticException If {@code tileWidth == 0}. */ public static int XToTileX(int x, int tileGridXOffset, int tileWidth) { x -= tileGridXOffset; @@ -240,11 +240,11 @@ public class TIFFImageWriter extends ImageWriter { * relative to a given tile grid layout specified by its Y offset * and tile height. * - *

If tileHeight < 0, the results of this method - * are undefined. If tileHeight == 0, an - * ArithmeticException will be thrown. + *

If {@code tileHeight < 0}, the results of this method + * are undefined. If {@code tileHeight == 0}, an + * {@code ArithmeticException} will be thrown. * - * @throws ArithmeticException If tileHeight == 0. + * @throws ArithmeticException If {@code tileHeight == 0}. */ public static int YToTileY(int y, int tileGridYOffset, int tileHeight) { y -= tileGridYOffset; @@ -424,17 +424,17 @@ public class TIFFImageWriter extends ImageWriter { } /** - * Converts a standard javax_imageio_1.0 tree to a - * TIFFImageMetadata object. + * Converts a standard {@code javax_imageio_1.0} tree to a + * {@code TIFFImageMetadata} object. * * @param inData The metadata object. - * @return a TIFFImageMetadata or null if - * the standard tree derived from the input object is null. - * @throws IllegalArgumentException if inData is - * null. - * @throws IllegalArgumentException if inData does not support + * @return a {@code TIFFImageMetadata} or {@code null} if + * the standard tree derived from the input object is {@code null}. + * @throws IllegalArgumentException if {@code inData} is + * {@code null}. + * @throws IllegalArgumentException if {@code inData} does not support * the standard metadata format. - * @throws IIOInvalidTreeException if inData generates an + * @throws IIOInvalidTreeException if {@code inData} generates an * invalid standard metadata tree. */ private TIFFImageMetadata convertStandardImageMetadata(IIOMetadata inData) @@ -463,15 +463,15 @@ public class TIFFImageWriter extends ImageWriter { /** * Converts a native - * javax_imageio_tiff_image_1.0 tree to a - * TIFFImageMetadata object. + * {@code javax_imageio_tiff_image_1.0} tree to a + * {@code TIFFImageMetadata} object. * * @param inData The metadata object. - * @return a TIFFImageMetadata or null if - * the native tree derived from the input object is null. - * @throws IllegalArgumentException if inData is - * null or does not support the native metadata format. - * @throws IIOInvalidTreeException if inData generates an + * @return a {@code TIFFImageMetadata} or {@code null} if + * the native tree derived from the input object is {@code null}. + * @throws IllegalArgumentException if {@code inData} is + * {@code null} or does not support the native metadata format. + * @throws IIOInvalidTreeException if {@code inData} generates an * invalid native metadata tree. */ private TIFFImageMetadata convertNativeImageMetadata(IIOMetadata inData) @@ -504,8 +504,8 @@ public class TIFFImageWriter extends ImageWriter { * as needed. The destination image dimensions are provided as parameters * because these might differ from those of the source due to subsampling. * - * @param cm The ColorModel of the image being written. - * @param sm The SampleModel of the image being written. + * @param cm The {@code ColorModel} of the image being written. + * @param sm The {@code SampleModel} of the image being written. * @param destWidth The width of the written image after subsampling. * @param destHeight The height of the written image after subsampling. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java index a631a3a926c..7b6cfcf5b28 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -102,14 +102,14 @@ public class TIFFJPEGCompressor extends TIFFBaseJPEGCompressor { } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * *

The implementation in this class also adds the TIFF fields * JPEGTables, YCbCrSubSampling, YCbCrPositioning, and * ReferenceBlackWhite superseding any prior settings of those * fields.

* - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java index d53a275955f..cbf3b504f63 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -245,7 +245,7 @@ class TIFFLZWDecompressor extends TIFFDecompressor { } /** - * Append newString to the end of oldString. + * Append {@code newString} to the end of {@code oldString}. */ public byte[] composeString(byte oldString[], byte newString) { int length = oldString.length; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java index 92656697d2c..2a61535cff3 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -188,7 +188,7 @@ class TIFFLZWUtil { } /** - * Append newString to the end of oldString. + * Append {@code newString} to the end of {@code oldString}. */ public byte[] composeString(byte oldString[], byte newString) { int length = oldString.length; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java index 657bd28861b..6ffc1f0acb7 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -34,16 +34,16 @@ public class TIFFNullDecompressor extends TIFFDecompressor { */ private boolean isReadActiveOnly = false; - /** The original value of srcMinX. */ + /** The original value of {@code srcMinX}. */ private int originalSrcMinX; - /** The original value of srcMinY. */ + /** The original value of {@code srcMinY}. */ private int originalSrcMinY; - /** The original value of srcWidth. */ + /** The original value of {@code srcWidth}. */ private int originalSrcWidth; - /** The original value of srcHeight. */ + /** The original value of {@code srcHeight}. */ private int originalSrcHeight; public TIFFNullDecompressor() {} diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java index 264657ddb2a..2837754ddb2 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -34,7 +34,7 @@ import javax.imageio.plugins.tiff.BaselineTIFFTagSet; import javax.imageio.plugins.tiff.TIFFField; /** - * TIFFDecompressor for "Old JPEG" compression. + * {@code TIFFDecompressor} for "Old JPEG" compression. */ public class TIFFOldJPEGDecompressor extends TIFFJPEGDecompressor { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java index cebfdfb2221..523f9eaa574 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -42,8 +42,8 @@ public class TIFFRLECompressor extends TIFFFaxCompressor { * CCITT RLE (Run Lenth Encoding). * * @param data The row of data to compress. - * @param rowOffset Starting index in data. - * @param colOffset Bit offset within first data[rowOffset]. + * @param rowOffset Starting index in {@code data}. + * @param colOffset Bit offset within first {@code data[rowOffset]}. * @param rowLength Number of bits in the row. * @param compData The compressed data. * diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java index 98a336f8c8f..77e0c9a109c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -85,15 +85,15 @@ public class TIFFRenderedImage implements RenderedImage { } /** - * Creates a copy of param. The source subsampling and + * Creates a copy of {@code param}. The source subsampling and * and bands settings and the destination bands and offset settings - * are copied. If param is a TIFFImageReadParam - * then the TIFFDecompressor and - * TIFFColorConverter settings are also copied; otherwise - * they are explicitly set to null. + * are copied. If {@code param} is a {@code TIFFImageReadParam} + * then the {@code TIFFDecompressor} and + * {@code TIFFColorConverter} settings are also copied; otherwise + * they are explicitly set to {@code null}. * * @param param the parameters to be copied. - * @param copyTagSets whether the TIFFTagSet settings + * @param copyTagSets whether the {@code TIFFTagSet} settings * should be copied if set. * @return copied parameters. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java index fa2652ef902..55088e34dfe 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -41,13 +41,13 @@ public class TIFFT4Compressor extends TIFFFaxCompressor { } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * *

The implementation in this class also sets local options * from the T4_OPTIONS field if it exists, and if it doesn't, adds * it with default values.

* - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() @@ -86,7 +86,7 @@ public class TIFFT4Compressor extends TIFFFaxCompressor { * @param isEOLAligned Whether EOL bit sequences should be padded. * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. - * @param colOffset Bit offset within first data[rowOffset]. + * @param colOffset Bit offset within first {@code data[rowOffset]}. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java index 964bba05032..517c23bde54 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -42,7 +42,7 @@ public class TIFFT6Compressor extends TIFFFaxCompressor { * * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. - * @param colOffset Bit offset within first data[rowOffset]. + * @param colOffset Bit offset within first {@code data[rowOffset]}. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java index d434acf8ab3..d1dbd3cf4fb 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -2175,9 +2175,9 @@ public class BaselineTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of a BaselineTIFFTagSet. + * Returns a shared instance of a {@code BaselineTIFFTagSet}. * - * @return a BaselineTIFFTagSet instance. + * @return a {@code BaselineTIFFTagSet} instance. */ public synchronized static BaselineTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java index d37a1330d12..03198c45c51 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -51,7 +51,7 @@ public class ExifGPSTagSet extends TIFFTagSet { /** * A value to be used with the "GPSVersionID" tag to indicate GPS version * 2.2. The value equals the US-ASCII encoding of the byte array - * {'2', '2', '0', '0'}. + * {@code {'2', '2', '0', '0'}}. * * @see #TAG_GPS_VERSION_ID */ @@ -711,9 +711,9 @@ public class ExifGPSTagSet extends TIFFTagSet { } /** - * Returns a shared instance of an ExifGPSTagSet. + * Returns a shared instance of an {@code ExifGPSTagSet}. * - * @return an ExifGPSTagSet instance. + * @return an {@code ExifGPSTagSet} instance. */ public synchronized static ExifGPSTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java index b2a52790f0b..7089c653fbe 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -88,9 +88,9 @@ public class ExifInteroperabilityTagSet extends TIFFTagSet { /** * Returns the shared instance of - * ExifInteroperabilityTagSet. + * {@code ExifInteroperabilityTagSet}. * - * @return the ExifInteroperabilityTagSet instance. + * @return the {@code ExifInteroperabilityTagSet} instance. */ public synchronized static ExifInteroperabilityTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java index 29647711fc4..108e1a16852 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -80,9 +80,9 @@ public class ExifParentTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of an ExifParentTIFFTagSet. + * Returns a shared instance of an {@code ExifParentTIFFTagSet}. * - * @return an ExifParentTIFFTagSet instance. + * @return an {@code ExifParentTIFFTagSet} instance. */ public synchronized static ExifParentTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java index 792a78fcb23..c5be97c88c2 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java @@ -33,7 +33,7 @@ import java.util.List; * standard for annotating images used by most digital camera * manufacturers. The Exif specification may be found at * - * http://www.exif.org/Exif2-2.PDF + * {@code http://www.exif.org/Exif2-2.PDF} * . * *

The definitions of the data types referenced by the field @@ -67,7 +67,7 @@ public class ExifTIFFTagSet extends TIFFTagSet { /** * A value to be used with the "ExifVersion" tag to indicate Exif version * 2.1. The value equals the US-ASCII encoding of the byte array - * {'0', '2', '1', '0'}. + * {@code {'0', '2', '1', '0'}}. * * @see #TAG_EXIF_VERSION */ @@ -78,7 +78,7 @@ public class ExifTIFFTagSet extends TIFFTagSet { /** * A value to be used with the "ExifVersion" tag to indicate Exif version * 2.2. The value equals the US-ASCII encoding of the byte array - * {'0', '2', '2', '0'}. + * {@code {'0', '2', '2', '0'}}. * * @see #TAG_EXIF_VERSION */ @@ -94,7 +94,7 @@ public class ExifTIFFTagSet extends TIFFTagSet { /** * A tag indicating the color space information (type SHORT). The - * legal values are given by the COLOR_SPACE_* + * legal values are given by the {@code COLOR_SPACE_*} * constants. * * @see #COLOR_SPACE_SRGB @@ -1992,9 +1992,9 @@ public class ExifTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of an ExifTIFFTagSet. + * Returns a shared instance of an {@code ExifTIFFTagSet}. * - * @return an ExifTIFFTagSet instance. + * @return an {@code ExifTIFFTagSet} instance. */ public synchronized static ExifTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java index fa9733cd3f0..8a3043da122 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -131,9 +131,9 @@ public class FaxTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of a FaxTIFFTagSet. + * Returns a shared instance of a {@code FaxTIFFTagSet}. * - * @return a FaxTIFFTagSet instance. + * @return a {@code FaxTIFFTagSet} instance. */ public synchronized static FaxTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java index ec6e5f2a503..28ee56abd3c 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java @@ -32,7 +32,7 @@ import java.util.List; * standard for annotating georeferenced or geocoded raster imagery. * The GeoTIFF specification may be found at - * http://www.remotesensing.org/geotiff/spec/geotiffhome.html + * {@code http://www.remotesensing.org/geotiff/spec/geotiffhome.html} * . This class does not handle the GeoKeys referenced * from a GeoKeyDirectoryTag as those are not TIFF tags per se. * @@ -63,7 +63,7 @@ public class GeoTIFFTagSet extends TIFFTagSet { /** A tag used to store the GeoKey directory. */ public static final int TAG_GEO_KEY_DIRECTORY = 34735; - /** A tag used to store all double-values GeoKeys. */ + /** A tag used to store all {@code double}-values GeoKeys. */ public static final int TAG_GEO_DOUBLE_PARAMS = 34736; /** A tag used to store all ASCII-values GeoKeys. */ @@ -137,9 +137,9 @@ public class GeoTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of a GeoTIFFTagSet. + * Returns a shared instance of a {@code GeoTIFFTagSet}. * - * @return a GeoTIFFTagSet instance. + * @return a {@code GeoTIFFTagSet} instance. */ public synchronized static GeoTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java index 7f75db646db..f3e5577716a 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java @@ -41,58 +41,58 @@ import com.sun.imageio.plugins.tiff.TIFFImageMetadata; * image metadata. A TIFF image metadata tree represents an Image File * Directory (IFD) from a TIFF 6.0 stream. An IFD consists of a number of * IFD Entries each of which associates an identifying tag number with - * a compatible value. A TIFFDirectory instance corresponds + * a compatible value. A {@code TIFFDirectory} instance corresponds * to an IFD and contains a set of {@link TIFFField}s each of which * corresponds to an IFD Entry in the IFD. * - *

When reading, a TIFFDirectory may be created by passing + *

When reading, a {@code TIFFDirectory} may be created by passing * the value returned by {@link javax.imageio.ImageReader#getImageMetadata * ImageReader.getImageMetadata()} to {@link #createFromMetadata * createFromMetadata()}. The {@link TIFFField}s in the directory may then * be obtained using the accessor methods provided in this class.

* *

When writing, an {@link IIOMetadata} object for use by one of the - * write() methods of {@link javax.imageio.ImageWriter} may be - * created from a TIFFDirectory by {@link #getAsMetadata()}. - * The TIFFDirectory itself may be created by construction or - * from the IIOMetadata object returned by + * {@code write()} methods of {@link javax.imageio.ImageWriter} may be + * created from a {@code TIFFDirectory} by {@link #getAsMetadata()}. + * The {@code TIFFDirectory} itself may be created by construction or + * from the {@code IIOMetadata} object returned by * {@link javax.imageio.ImageWriter#getDefaultImageMetadata - * ImageWriter.getDefaultImageMetadata()}. The TIFFFields in the + * ImageWriter.getDefaultImageMetadata()}. The {@code TIFFField}s in the * directory may be set using the mutator methods provided in this class.

* - *

A TIFFDirectory is aware of the tag numbers in the + *

A {@code TIFFDirectory} is aware of the tag numbers in the * group of {@link TIFFTagSet}s associated with it. When - * a TIFFDirectory is created from a native image metadata + * a {@code TIFFDirectory} is created from a native image metadata * object, these tag sets are derived from the tagSets attribute * of the TIFFIFD node.

* - *

A TIFFDirectory might also have a parent {@link TIFFTag}. + *

A {@code TIFFDirectory} might also have a parent {@link TIFFTag}. * This will occur if the directory represents an IFD other than the root * IFD of the image. The parent tag is the tag of the IFD Entry which is a - * pointer to the IFD represented by this TIFFDirectory. The - * {@link TIFFTag#isIFDPointer} method of this parent TIFFTag - * must return true. When a TIFFDirectory is + * pointer to the IFD represented by this {@code TIFFDirectory}. The + * {@link TIFFTag#isIFDPointer} method of this parent {@code TIFFTag} + * must return {@code true}. When a {@code TIFFDirectory} is * created from a native image metadata object, the parent tag set is set * from the parentTagName attribute of the corresponding - * TIFFIFD node. Note that a TIFFDirectory instance - * which has a non-null parent tag will be contained in the - * data field of a TIFFField instance which has a tag field + * TIFFIFD node. Note that a {@code TIFFDirectory} instance + * which has a non-{@code null} parent tag will be contained in the + * data field of a {@code TIFFField} instance which has a tag field * equal to the contained directory's parent tag.

* - *

As an example consider an Exif image. The TIFFDirectory + *

As an example consider an Exif image. The {@code TIFFDirectory} * instance corresponding to the Exif IFD in the Exif stream would have parent * tag {@link ExifParentTIFFTagSet#TAG_EXIF_IFD_POINTER TAG_EXIF_IFD_POINTER} * and would include {@link ExifTIFFTagSet} in its group of known tag sets. - * The TIFFDirectory corresponding to this Exif IFD will be - * contained in the data field of a TIFFField which will in turn - * be contained in the TIFFDirectory corresponding to the primary - * IFD of the Exif image which will itself have a null-valued + * The {@code TIFFDirectory} corresponding to this Exif IFD will be + * contained in the data field of a {@code TIFFField} which will in turn + * be contained in the {@code TIFFDirectory} corresponding to the primary + * IFD of the Exif image which will itself have a {@code null}-valued * parent tag.

* *

Note that this implementation is not synchronized. If multiple - * threads use a TIFFDirectory instance concurrently, and at + * threads use a {@code TIFFDirectory} instance concurrently, and at * least one of the threads modifies the directory, for example, by adding - * or removing TIFFFields or TIFFTagSets, it + * or removing {@code TIFFField}s or {@code TIFFTagSet}s, it * must be synchronized externally.

* * @since 9 @@ -107,10 +107,10 @@ public class TIFFDirectory implements Cloneable { private static final int MAX_LOW_FIELD_TAG_NUM = BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE; - /** The TIFFTagSets associated with this directory. */ + /** The {@code TIFFTagSets} associated with this directory. */ private List tagSets; - /** The parent TIFFTag of this directory. */ + /** The parent {@code TIFFTag} of this directory. */ private TIFFTag parentTag; /** @@ -123,13 +123,13 @@ public class TIFFDirectory implements Cloneable { private int numLowFields = 0; /** - * A mapping of Integer tag numbers to TIFFFields + * A mapping of {@code Integer} tag numbers to {@code TIFFField}s * for fields which are not low tag numbered. */ private Map highFields = new TreeMap(); /** - * Creates a TIFFDirectory instance from the contents of + * Creates a {@code TIFFDirectory} instance from the contents of * an image metadata object. The supplied object must support an image * metadata format supported by the TIFF {@link javax.imageio.ImageWriter} * plug-in. This will usually be either the TIFF native image metadata @@ -139,12 +139,12 @@ public class TIFFDirectory implements Cloneable { * @param tiffImageMetadata A metadata object which supports a compatible * image metadata format. * - * @return A TIFFDirectory populated from the contents of + * @return A {@code TIFFDirectory} populated from the contents of * the supplied metadata object. * - * @throws NullPointerException if tiffImageMetadata - * is null. - * @throws IllegalArgumentException if tiffImageMetadata + * @throws NullPointerException if {@code tiffImageMetadata} + * is {@code null}. + * @throws IllegalArgumentException if {@code tiffImageMetadata} * does not support a compatible image metadata format. * @throws IIOInvalidTreeException if the supplied metadata object * cannot be parsed. @@ -204,7 +204,7 @@ public class TIFFDirectory implements Cloneable { } /** - * Converts a TIFFDirectory to a TIFFIFD. + * Converts a {@code TIFFDirectory} to a {@code TIFFIFD}. */ private static TIFFIFD getDirectoryAsIFD(TIFFDirectory dir) { if(dir instanceof TIFFIFD) { @@ -242,16 +242,16 @@ public class TIFFDirectory implements Cloneable { } /** - * Constructs a TIFFDirectory which is aware of a given + * Constructs a {@code TIFFDirectory} which is aware of a given * group of {@link TIFFTagSet}s. An optional parent {@link TIFFTag} * may also be specified. * - * @param tagSets The TIFFTagSets associated with this + * @param tagSets The {@code TIFFTagSets} associated with this * directory. - * @param parentTag The parent TIFFTag of this directory; - * may be null. - * @throws NullPointerException if tagSets is - * null. + * @param parentTag The parent {@code TIFFTag} of this directory; + * may be {@code null}. + * @throws NullPointerException if {@code tagSets} is + * {@code null}. */ public TIFFDirectory(TIFFTagSet[] tagSets, TIFFTag parentTag) { if(tagSets == null) { @@ -268,8 +268,8 @@ public class TIFFDirectory implements Cloneable { /** * Returns the {@link TIFFTagSet}s of which this directory is aware. * - * @return The TIFFTagSets associated with this - * TIFFDirectory. + * @return The {@code TIFFTagSet}s associated with this + * {@code TIFFDirectory}. */ public TIFFTagSet[] getTagSets() { return tagSets.toArray(new TIFFTagSet[tagSets.size()]); @@ -279,9 +279,9 @@ public class TIFFDirectory implements Cloneable { * Adds an element to the group of {@link TIFFTagSet}s of which this * directory is aware. * - * @param tagSet The TIFFTagSet to add. - * @throws NullPointerException if tagSet is - * null. + * @param tagSet The {@code TIFFTagSet} to add. + * @throws NullPointerException if {@code tagSet} is + * {@code null}. */ public void addTagSet(TIFFTagSet tagSet) { if(tagSet == null) { @@ -297,9 +297,9 @@ public class TIFFDirectory implements Cloneable { * Removes an element from the group of {@link TIFFTagSet}s of which this * directory is aware. * - * @param tagSet The TIFFTagSet to remove. - * @throws NullPointerException if tagSet is - * null. + * @param tagSet The {@code TIFFTagSet} to remove. + * @throws NullPointerException if {@code tagSet} is + * {@code null}. */ public void removeTagSet(TIFFTagSet tagSet) { if(tagSet == null) { @@ -313,10 +313,10 @@ public class TIFFDirectory implements Cloneable { /** * Returns the parent {@link TIFFTag} of this directory if one - * has been defined or null otherwise. + * has been defined or {@code null} otherwise. * - * @return The parent TIFFTag of this - * TIFFDiectory or null. + * @return The parent {@code TIFFTag} of this + * {@code TIFFDiectory} or {@code null}. */ public TIFFTag getParentTag() { return parentTag; @@ -324,12 +324,12 @@ public class TIFFDirectory implements Cloneable { /** * Returns the {@link TIFFTag} which has tag number equal to - * tagNumber or null if no such tag + * {@code tagNumber} or {@code null} if no such tag * exists in the {@link TIFFTagSet}s associated with this * directory. * * @param tagNumber The tag number of interest. - * @return The corresponding TIFFTag or null. + * @return The corresponding {@code TIFFTag} or {@code null}. */ public TIFFTag getTag(int tagNumber) { return TIFFIFD.getTag(tagNumber, tagSets); @@ -338,8 +338,8 @@ public class TIFFDirectory implements Cloneable { /** * Returns the number of {@link TIFFField}s in this directory. * - * @return The number of TIFFFields in this - * TIFFDirectory. + * @return The number of {@code TIFFField}s in this + * {@code TIFFDirectory}. */ public int getNumTIFFFields() { return numLowFields + highFields.size(); @@ -351,7 +351,7 @@ public class TIFFDirectory implements Cloneable { * * @param tagNumber The tag number. * @return Whether a {@link TIFFTag} with tag number equal to - * tagNumber is present in this TIFFDirectory. + * {@code tagNumber} is present in this {@code TIFFDirectory}. */ public boolean containsTIFFField(int tagNumber) { return (tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM && @@ -363,7 +363,7 @@ public class TIFFDirectory implements Cloneable { * Adds a TIFF field to the directory. * * @param f The field to add. - * @throws NullPointerException if f is null. + * @throws NullPointerException if {@code f} is {@code null}. */ public void addTIFFField(TIFFField f) { if(f == null) { @@ -384,8 +384,8 @@ public class TIFFDirectory implements Cloneable { * Retrieves a TIFF field from the directory. * * @param tagNumber The tag number of the tag associated with the field. - * @return A TIFFField with the requested tag number of - * null if no such field is present. + * @return A {@code TIFFField} with the requested tag number of + * {@code null} if no such field is present. */ public TIFFField getTIFFField(int tagNumber) { TIFFField f; @@ -456,7 +456,7 @@ public class TIFFDirectory implements Cloneable { * Converts the directory to a metadata object. * * @return A metadata instance initialized from the contents of this - * TIFFDirectory. + * {@code TIFFDirectory}. */ public IIOMetadata getAsMetadata() { return new TIFFImageMetadata(getDirectoryAsIFD(this)); @@ -465,7 +465,7 @@ public class TIFFDirectory implements Cloneable { /** * Clones the directory and all the fields contained therein. * - * @return A clone of this TIFFDirectory. + * @return A clone of this {@code TIFFDirectory}. * @throws CloneNotSupportedException if the instance cannot be cloned. */ @Override diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java index 010f841315b..336f81550b7 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -35,7 +35,7 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * *

A field in a TIFF Image File Directory (IFD) is defined as a * tag number accompanied by a sequence of values of identical data type. - * TIFF 6.0 defines 12 data types; a 13th type IFD is + * TIFF 6.0 defines 12 data types; a 13th type {@code IFD} is * defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These * TIFF data types are referred to by Java constants and mapped internally * onto Java language data types and type names as follows: @@ -68,10 +68,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_BYTE} * * - * byte + * {@code byte} * * - * "Byte" + * {@code "Byte"} * * * @@ -83,10 +83,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_ASCII} * * - * String + * {@code String} * * - * "Ascii" + * {@code "Ascii"} * * * @@ -98,10 +98,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SHORT} * * - * char + * {@code char} * * - * "Short" + * {@code "Short"} * * * @@ -113,10 +113,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_LONG} * * - * long + * {@code long} * * - * "Long" + * {@code "Long"} * * * @@ -128,10 +128,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_RATIONAL} * * - * long[2] {numerator, denominator} + * {@code long[2]} {numerator, denominator} * * - * "Rational" + * {@code "Rational"} * * * @@ -143,10 +143,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SBYTE} * * - * byte + * {@code byte} * * - * "SByte" + * {@code "SByte"} * * * @@ -158,10 +158,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_UNDEFINED} * * - * byte + * {@code byte} * * - * "Undefined" + * {@code "Undefined"} * * * @@ -173,10 +173,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SSHORT} * * - * short + * {@code short} * * - * "SShort" + * {@code "SShort"} * * * @@ -188,10 +188,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SLONG} * * - * int + * {@code int} * * - * "SLong" + * {@code "SLong"} * * * @@ -203,10 +203,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SRATIONAL} * * - * int[2] {numerator, denominator} + * {@code int[2]} {numerator, denominator} * * - * "SRational" + * {@code "SRational"} * * * @@ -218,10 +218,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_FLOAT} * * - * float + * {@code float} * * - * "Float" + * {@code "Float"} * * * @@ -233,10 +233,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_DOUBLE} * * - * double + * {@code double} * * - * "Double" + * {@code "Double"} * * * @@ -248,10 +248,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_IFD_POINTER} * * - * long + * {@code long} * * - * "IFDPointer" + * {@code "IFDPointer"} * * * @@ -411,19 +411,19 @@ public class TIFFField implements Cloneable { } /** - * Creates a TIFFField from a TIFF native image + * Creates a {@code TIFFField} from a TIFF native image * metadata node. If the value of the "tagNumber" attribute - * of the node is not found in tagSet then a new - * TIFFTag with name TIFFTag.UNKNOWN_TAG_NAME + * of the node is not found in {@code tagSet} then a new + * {@code TIFFTag} with name {@code TIFFTag.UNKNOWN_TAG_NAME} * will be created and assigned to the field. * - * @param tagSet The TIFFTagSet to which the - * TIFFTag of the field belongs. - * @param node A native TIFF image metadata TIFFField node. - * @throws NullPointerException if node is - * null. + * @param tagSet The {@code TIFFTagSet} to which the + * {@code TIFFTag} of the field belongs. + * @param node A native TIFF image metadata {@code TIFFField} node. + * @throws NullPointerException if {@code node} is + * {@code null}. * @throws IllegalArgumentException if the name of the node is not - * "TIFFField". + * {@code "TIFFField"}. * @return A new {@code TIFFField}. */ public static TIFFField createFromMetadataNode(TIFFTagSet tagSet, @@ -487,14 +487,14 @@ public class TIFFField implements Cloneable { } /** - * Constructs a TIFFField with arbitrary data. The - * type parameter must be a value for which + * Constructs a {@code TIFFField} with arbitrary data. The + * {@code type} parameter must be a value for which * {@link TIFFTag#isDataTypeOK tag.isDataTypeOK()} - * returns true. The data parameter must + * returns {@code true}. The {@code data} parameter must * be an array of a Java type appropriate for the type of the TIFF * field. * - *

Note that the value (data) of the TIFFField + *

Note that the value (data) of the {@code TIFFField} * will always be the actual field value regardless of the number of * bytes required for that value. This is the case despite the fact * that the TIFF IFD Entry corresponding to the field may @@ -503,29 +503,29 @@ public class TIFFField implements Cloneable { * value fits into 4 bytes). In other words, the value of the * field will already have been read from the TIFF stream. (An exception * to this case may occur when the field represents the contents of a - * non-baseline IFD. In that case the data will be a long[] - * containing the offset to the IFD and the TIFFDirectory + * non-baseline IFD. In that case the data will be a {@code long[]} + * containing the offset to the IFD and the {@code TIFFDirectory} * returned by {@link #getDirectory()} will be its contents.) * * @param tag The tag to associated with this field. - * @param type One of the TIFFTag.TIFF_* constants + * @param type One of the {@code TIFFTag.TIFF_*} constants * indicating the data type of the field as written to the TIFF stream. * @param count The number of data values. * @param data The actual data content of the field. * - * @throws NullPointerException if tag == null. - * @throws IllegalArgumentException if type is not - * one of the TIFFTag.TIFF_* data type constants. - * @throws IllegalArgumentException if type is an unacceptable - * data type for the supplied TIFFTag. - * @throws IllegalArgumentException if count < 0. - * @throws IllegalArgumentException if count < 1 - * and type is TIFF_RATIONAL or - * TIFF_SRATIONAL. - * @throws IllegalArgumentException if count ≠ 1 - * and type is TIFF_IFD_POINTER. - * @throws NullPointerException if data == null. - * @throws IllegalArgumentException if data is an instance of + * @throws NullPointerException if {@code tag == null}. + * @throws IllegalArgumentException if {@code type} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. + * @throws IllegalArgumentException if {@code type} is an unacceptable + * data type for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code count < 0}. + * @throws IllegalArgumentException if {@code count < 1} + * and {@code type} is {@code TIFF_RATIONAL} or + * {@code TIFF_SRATIONAL}. + * @throws IllegalArgumentException if {@code count ≠ 1} + * and {@code type} is {@code TIFF_IFD_POINTER}. + * @throws NullPointerException if {@code data == null}. + * @throws IllegalArgumentException if {@code data} is an instance of * a class incompatible with the specified type. * @throws IllegalArgumentException if the size of the data array is wrong. */ @@ -625,15 +625,15 @@ public class TIFFField implements Cloneable { * parameters and the created array. * * @param tag The tag to associated with this field. - * @param type One of the TIFFTag.TIFF_* constants + * @param type One of the {@code TIFFTag.TIFF_*} constants * indicating the data type of the field as written to the TIFF stream. * @param count The number of data values. - * @throws NullPointerException if tag == null. - * @throws IllegalArgumentException if type is not - * one of the TIFFTag.TIFF_* data type constants. - * @throws IllegalArgumentException if type is an unacceptable - * data type for the supplied TIFFTag. - * @throws IllegalArgumentException if count < 0. + * @throws NullPointerException if {@code tag == null}. + * @throws IllegalArgumentException if {@code type} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. + * @throws IllegalArgumentException if {@code type} is an unacceptable + * data type for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code count < 0}. * @see #TIFFField(TIFFTag,int,int,Object) */ public TIFFField(TIFFTag tag, int type, int count) { @@ -641,20 +641,20 @@ public class TIFFField implements Cloneable { } /** - * Constructs a TIFFField with a single non-negative integral + * Constructs a {@code TIFFField} with a single non-negative integral * value. * The field will have type * {@link TIFFTag#TIFF_SHORT TIFF_SHORT} if - * val < 65536 and type + * {@code val < 65536} and type * {@link TIFFTag#TIFF_LONG TIFF_LONG} otherwise. The count * of the field will be unity. * * @param tag The tag to associate with this field. * @param value The value to associate with this field. - * @throws NullPointerException if tag == null. + * @throws NullPointerException if {@code tag == null}. * @throws IllegalArgumentException if the derived type is unacceptable - * for the supplied TIFFTag. - * @throws IllegalArgumentException if value < 0. + * for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code value < 0}. */ public TIFFField(TIFFTag tag, int value) { if(tag == null) { @@ -690,24 +690,24 @@ public class TIFFField implements Cloneable { } /** - * Constructs a TIFFField with an IFD offset and contents. + * Constructs a {@code TIFFField} with an IFD offset and contents. * The offset will be stored as the data of this field as - * long[] {offset}. The directory will not be cloned. The count + * {@code long[] {offset}}. The directory will not be cloned. The count * of the field will be unity. * * @param tag The tag to associated with this field. - * @param type One of the constants TIFFTag.TIFF_LONG or - * TIFFTag.TIFF_IFD_POINTER. + * @param type One of the constants {@code TIFFTag.TIFF_LONG} or + * {@code TIFFTag.TIFF_IFD_POINTER}. * @param offset The IFD offset. * @param dir The directory. * - * @throws NullPointerException if tag == null. - * @throws IllegalArgumentException if type is neither - * TIFFTag.TIFF_LONG nor TIFFTag.TIFF_IFD_POINTER. - * @throws IllegalArgumentException if type is an unacceptable - * data type for the supplied TIFFTag. - * @throws IllegalArgumentException if offset is non-positive. - * @throws NullPointerException if dir == null. + * @throws NullPointerException if {@code tag == null}. + * @throws IllegalArgumentException if {@code type} is neither + * {@code TIFFTag.TIFF_LONG} nor {@code TIFFTag.TIFF_IFD_POINTER}. + * @throws IllegalArgumentException if {@code type} is an unacceptable + * data type for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code offset} is non-positive. + * @throws NullPointerException if {@code dir == null}. * * @see #TIFFField(TIFFTag,int,int,Object) */ @@ -728,14 +728,14 @@ public class TIFFField implements Cloneable { /** * Retrieves the tag associated with this field. * - * @return The associated TIFFTag. + * @return The associated {@code TIFFTag}. */ public TIFFTag getTag() { return tag; } /** - * Retrieves the tag number in the range [0, 65535]. + * Retrieves the tag number in the range {@code [0, 65535]}. * * @return The tag number. */ @@ -745,7 +745,7 @@ public class TIFFField implements Cloneable { /** * Returns the type of the data stored in the field. For a TIFF 6.0 - * stream, the value will equal one of the TIFFTag.TIFF_* + * stream, the value will equal one of the {@code TIFFTag.TIFF_*} * constants. For future revisions of TIFF, higher values are possible. * * @return The data type of the field value. @@ -757,11 +757,11 @@ public class TIFFField implements Cloneable { /** * Returns the name of the supplied data type constant. * - * @param dataType One of the TIFFTag.TIFF_* constants + * @param dataType One of the {@code TIFFTag.TIFF_*} constants * indicating the data type of the field as written to the TIFF stream. * @return The type name corresponding to the supplied type constant. - * @throws IllegalArgumentException if dataType is not - * one of the TIFFTag.TIFF_* data type constants. + * @throws IllegalArgumentException if {@code dataType} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. */ public static String getTypeName(int dataType) { if (dataType < TIFFTag.MIN_DATATYPE || @@ -774,11 +774,11 @@ public class TIFFField implements Cloneable { /** * Returns the data type constant corresponding to the supplied data - * type name. If the name is unknown -1 will be returned. + * type name. If the name is unknown {@code -1} will be returned. * * @param typeName The type name. - * @return One of the TIFFTag.TIFF_* constants or - * -1 if the name is not recognized. + * @return One of the {@code TIFFTag.TIFF_*} constants or + * {@code -1} if the name is not recognized. */ public static int getTypeByName(String typeName) { for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) { @@ -793,14 +793,14 @@ public class TIFFField implements Cloneable { /** * Creates an array appropriate for the indicated data type. * - * @param dataType One of the TIFFTag.TIFF_* data type + * @param dataType One of the {@code TIFFTag.TIFF_*} data type * constants. * @param count The number of values in the array. * @return An array appropriate for the specified data type. * - * @throws IllegalArgumentException if dataType is not - * one of the TIFFTag.TIFF_* data type constants. - * @throws IllegalArgumentException if count < 0. + * @throws IllegalArgumentException if {@code dataType} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. + * @throws IllegalArgumentException if {@code count < 0}. */ public static Object createArrayForType(int dataType, int count) { if(count < 0) { @@ -836,15 +836,15 @@ public class TIFFField implements Cloneable { } /** - * Returns the TIFFField as a node named either + * Returns the {@code TIFFField} as a node named either * "TIFFField" or "TIFFIFD" as described in the * TIFF native image metadata specification. The node will be named * "TIFFIFD" if and only if the field's data object is an * instance of {@link TIFFDirectory} or equivalently * {@link TIFFTag#isIFDPointer getTag.isIFDPointer()} returns - * true. + * {@code true}. * - * @return a Node named "TIFFField" or + * @return a {@code Node} named "TIFFField" or * "TIFFIFD". */ public Node getAsNativeNode() { @@ -863,8 +863,8 @@ public class TIFFField implements Cloneable { /** * Returns the number of data items present in the field. For - * TIFFTag.TIFF_ASCII fields, the value returned is the - * number of Strings, not the total length of the + * {@code TIFFTag.TIFF_ASCII} fields, the value returned is the + * number of {@code String}s, not the total length of the * data as in the file representation. * * @return The number of data items present in the field. @@ -884,17 +884,17 @@ public class TIFFField implements Cloneable { /** * Returns the data as an uninterpreted array of - * bytes. The type of the field must be one of - * TIFFTag.TIFF_BYTE, TIFF_SBYTE, or - * TIFF_UNDEFINED. + * {@code byte}s. The type of the field must be one of + * {@code TIFFTag.TIFF_BYTE}, {@code TIFF_SBYTE}, or + * {@code TIFF_UNDEFINED}. * - *

For data in TIFFTag.TIFF_BYTE format, the application + *

For data in {@code TIFFTag.TIFF_BYTE} format, the application * must take care when promoting the data to longer integral types * to avoid sign extension. * * @throws ClassCastException if the field is not of type - * TIFF_BYTE, TIFF_SBYTE, or - * TIFF_UNDEFINED. + * {@code TIFF_BYTE}, {@code TIFF_SBYTE}, or + * {@code TIFF_UNDEFINED}. * @return The data as an uninterpreted array of bytes. */ public byte[] getAsBytes() { @@ -902,11 +902,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_SHORT data as an array of - * chars (unsigned 16-bit integers). + * Returns {@code TIFFTag.TIFF_SHORT} data as an array of + * {@code char}s (unsigned 16-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_SHORT. + * {@code TIFF_SHORT}. * @return The data as an array of {@code char}s. */ public char[] getAsChars() { @@ -914,11 +914,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_SSHORT data as an array of - * shorts (signed 16-bit integers). + * Returns {@code TIFFTag.TIFF_SSHORT} data as an array of + * {@code short}s (signed 16-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_SSHORT. + * {@code TIFF_SSHORT}. * @return The data as an array of {@code short}s. */ public short[] getAsShorts() { @@ -926,12 +926,12 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_SLONG data as an array of - * ints (signed 32-bit integers). + * Returns {@code TIFFTag.TIFF_SLONG} data as an array of + * {@code int}s (signed 32-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_SHORT, TIFF_SSHORT, or - * TIFF_SLONG. + * {@code TIFF_SHORT}, {@code TIFF_SSHORT}, or + * {@code TIFF_SLONG}. * @return The data as an array of {@code int}s. */ public int[] getAsInts() { @@ -957,12 +957,12 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_LONG or - * TIFF_IFD_POINTER data as an array of - * longs (signed 64-bit integers). + * Returns {@code TIFFTag.TIFF_LONG} or + * {@code TIFF_IFD_POINTER} data as an array of + * {@code long}s (signed 64-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_LONG or TIFF_IFD_POINTER. + * {@code TIFF_LONG} or {@code TIFF_IFD_POINTER}. * @return The data as an array of {@code long}s. */ public long[] getAsLongs() { @@ -970,11 +970,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_FLOAT data as an array of - * floats (32-bit floating-point values). + * Returns {@code TIFFTag.TIFF_FLOAT} data as an array of + * {@code float}s (32-bit floating-point values). * * @throws ClassCastException if the field is not of type - * TIFF_FLOAT. + * {@code TIFF_FLOAT}. * @return The data as an array of {@code float}s. */ public float[] getAsFloats() { @@ -982,11 +982,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_DOUBLE data as an array of - * doubles (64-bit floating-point values). + * Returns {@code TIFFTag.TIFF_DOUBLE} data as an array of + * {@code double}s (64-bit floating-point values). * * @throws ClassCastException if the field is not of type - * TIFF_DOUBLE. + * {@code TIFF_DOUBLE}. * @return The data as an array of {@code double}s. */ public double[] getAsDoubles() { @@ -994,11 +994,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_SRATIONAL data as an array of - * 2-element arrays of ints. + * Returns {@code TIFFTag.TIFF_SRATIONAL} data as an array of + * 2-element arrays of {@code int}s. * * @throws ClassCastException if the field is not of type - * TIFF_SRATIONAL. + * {@code TIFF_SRATIONAL}. * @return The data as an array of signed rationals. */ public int[][] getAsSRationals() { @@ -1006,11 +1006,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_RATIONAL data as an array of - * 2-element arrays of longs. + * Returns {@code TIFFTag.TIFF_RATIONAL} data as an array of + * 2-element arrays of {@code long}s. * * @throws ClassCastException if the field is not of type - * TIFF_RATIONAL. + * {@code TIFF_RATIONAL}. * @return The data as an array of unsigned rationals. */ public long[][] getAsRationals() { @@ -1018,30 +1018,30 @@ public class TIFFField implements Cloneable { } /** - * Returns data in any format as an int. + * Returns data in any format as an {@code int}. * - *

TIFFTag.TIFF_BYTE values are treated as unsigned; that + *

{@code TIFFTag.TIFF_BYTE} values are treated as unsigned; that * is, no sign extension will take place and the returned value - * will be in the range [0, 255]. TIFF_SBYTE data + * will be in the range [0, 255]. {@code TIFF_SBYTE} data * will be returned in the range [-128, 127]. * - *

A TIFF_UNDEFINED value is treated as though - * it were a TIFF_BYTE. + *

A {@code TIFF_UNDEFINED} value is treated as though + * it were a {@code TIFF_BYTE}. * - *

Data in TIFF_SLONG, TIFF_LONG, - * TIFF_FLOAT, TIFF_DOUBLE or - * TIFF_IFD_POINTER format are simply cast to - * int and may suffer from truncation. + *

Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, + * {@code TIFF_FLOAT}, {@code TIFF_DOUBLE} or + * {@code TIFF_IFD_POINTER} format are simply cast to + * {@code int} and may suffer from truncation. * - *

Data in TIFF_SRATIONAL or - * TIFF_RATIONAL format are evaluated by dividing the + *

Data in {@code TIFF_SRATIONAL} or + * {@code TIFF_RATIONAL} format are evaluated by dividing the * numerator into the denominator using double-precision - * arithmetic and then casting to int. Loss of + * arithmetic and then casting to {@code int}. Loss of * precision and truncation may occur. * - *

Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method, with the result - * case to int. + *

Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method, with the result + * case to {@code int}. * * @param index The index of the data. * @return The data at the given index as an {@code int}. @@ -1081,17 +1081,17 @@ public class TIFFField implements Cloneable { } /** - * Returns data in any format as a long. + * Returns data in any format as a {@code long}. * - *

TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data + *

{@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. - * TIFF_SBYTE data will be returned in the range + * {@code TIFF_SBYTE} data will be returned in the range * [-128, 127]. * - *

Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method, with the result - * cast to long. + *

Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method, with the result + * cast to {@code long}. * * @param index The index of the data. * @return The data at the given index as a {@code long}. @@ -1127,27 +1127,27 @@ public class TIFFField implements Cloneable { } /** - * Returns data in any format as a float. + * Returns data in any format as a {@code float}. * - *

TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data + *

{@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. - * TIFF_SBYTE data will be returned in the range + * {@code TIFF_SBYTE} data will be returned in the range * [-128, 127]. * - *

Data in TIFF_SLONG, TIFF_LONG, - * TIFF_DOUBLE, or TIFF_IFD_POINTER format are - * simply cast to float and may suffer from + *

Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, + * {@code TIFF_DOUBLE}, or {@code TIFF_IFD_POINTER} format are + * simply cast to {@code float} and may suffer from * truncation. * - *

Data in TIFF_SRATIONAL or - * TIFF_RATIONAL format are evaluated by dividing the + *

Data in {@code TIFF_SRATIONAL} or + * {@code TIFF_RATIONAL} format are evaluated by dividing the * numerator into the denominator using double-precision - * arithmetic and then casting to float. + * arithmetic and then casting to {@code float}. * - *

Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method, with the result - * cast to float. + *

Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method, with the result + * cast to {@code float}. * * @param index The index of the data. * @return The data at the given index as a {@code float}. @@ -1187,21 +1187,21 @@ public class TIFFField implements Cloneable { } /** - * Returns data in any format as a double. + * Returns data in any format as a {@code double}. * - *

TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data + *

{@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. - * TIFF_SBYTE data will be returned in the range + * {@code TIFF_SBYTE} data will be returned in the range * [-128, 127]. * - *

Data in TIFF_SRATIONAL or - * TIFF_RATIONAL format are evaluated by dividing the + *

Data in {@code TIFF_SRATIONAL} or + * {@code TIFF_RATIONAL} format are evaluated by dividing the * numerator into the denominator using double-precision * arithmetic. * - *

Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method. + *

Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method. * * @param index The index of the data. * @return The data at the given index as a {@code double}. @@ -1241,11 +1241,11 @@ public class TIFFField implements Cloneable { } /** - * Returns a TIFFTag.TIFF_ASCII value as a - * String. + * Returns a {@code TIFFTag.TIFF_ASCII} value as a + * {@code String}. * * @throws ClassCastException if the field is not of type - * TIFF_ASCII. + * {@code TIFF_ASCII}. * * @param index The index of the data. * @return The data at the given index as a {@code String}. @@ -1255,13 +1255,13 @@ public class TIFFField implements Cloneable { } /** - * Returns a TIFFTag.TIFF_SRATIONAL data item as a - * two-element array of ints. + * Returns a {@code TIFFTag.TIFF_SRATIONAL} data item as a + * two-element array of {@code int}s. * * @param index The index of the data. * @return The data at the given index as a signed rational. * @throws ClassCastException if the field is not of type - * TIFF_SRATIONAL. + * {@code TIFF_SRATIONAL}. */ public int[] getAsSRational(int index) { return ((int[][])data)[index]; @@ -1274,7 +1274,7 @@ public class TIFFField implements Cloneable { * @param index The index of the data. * @return The data at the given index as an unsigned rational. * @throws ClassCastException if the field is not of type - * TIFF_RATIONAL. + * {@code TIFF_RATIONAL}. */ public long[] getAsRational(int index) { return ((long[][])data)[index]; @@ -1282,11 +1282,11 @@ public class TIFFField implements Cloneable { /** - * Returns a String containing a human-readable + * Returns a {@code String} containing a human-readable * version of the data item. Data of type - * TIFFTag.TIFF_RATIONAL or TIFF_SRATIONAL are + * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} are * represented as a pair of integers separated by a - * '/' character. + * {@code '/'} character. * * @param index The index of the data. * @return The data at the given index as a {@code String}. @@ -1355,7 +1355,7 @@ public class TIFFField implements Cloneable { } /** - * Returns whether the field has a TIFFDirectory. + * Returns whether the field has a {@code TIFFDirectory}. * * @return true if and only if getDirectory() returns non-null. */ @@ -1364,8 +1364,8 @@ public class TIFFField implements Cloneable { } /** - * Returns the associated TIFFDirectory, if available. If no - * directory is set, then null will be returned. + * Returns the associated {@code TIFFDirectory}, if available. If no + * directory is set, then {@code null} will be returned. * * @return the TIFFDirectory instance or null. */ @@ -1376,7 +1376,7 @@ public class TIFFField implements Cloneable { /** * Clones the field and all the information contained therein. * - * @return A clone of this TIFFField. + * @return A clone of this {@code TIFFField}. * @throws CloneNotSupportedException if the instance cannot be cloned. */ @Override diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java index 27f633c7cfd..9c120d094ef 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -39,11 +39,11 @@ import javax.imageio.ImageReadParam; * be provided by this interface. * *

Additional TIFF tags must be organized into - * TIFFTagSets. A TIFFTagSet may be + * {@code TIFFTagSet}s. A {@code TIFFTagSet} may be * provided to the reader by means of the - * addAllowedTagSet method. By default, the tag sets - * BaselineTIFFTagSet, FaxTIFFTagSet, - * ExifParentTIFFTagSet, and GeoTIFFTagSet + * {@code addAllowedTagSet} method. By default, the tag sets + * {@code BaselineTIFFTagSet}, {@code FaxTIFFTagSet}, + * {@code ExifParentTIFFTagSet}, and {@code GeoTIFFTagSet} * are included. * * @since 9 @@ -53,10 +53,10 @@ public class TIFFImageReadParam extends ImageReadParam { private List allowedTagSets = new ArrayList(4); /** - * Constructs a TIFFImageReadParam. Tags defined by - * the TIFFTagSets BaselineTIFFTagSet, - * FaxTIFFTagSet, ExifParentTIFFTagSet, and - * GeoTIFFTagSet will be supported. + * Constructs a {@code TIFFImageReadParam}. Tags defined by + * the {@code TIFFTagSet}s {@code BaselineTIFFTagSet}, + * {@code FaxTIFFTagSet}, {@code ExifParentTIFFTagSet}, and + * {@code GeoTIFFTagSet} will be supported. * * @see BaselineTIFFTagSet * @see FaxTIFFTagSet @@ -71,13 +71,13 @@ public class TIFFImageReadParam extends ImageReadParam { } /** - * Adds a TIFFTagSet object to the list of allowed + * Adds a {@code TIFFTagSet} object to the list of allowed * tag sets. * - * @param tagSet a TIFFTagSet. + * @param tagSet a {@code TIFFTagSet}. * - * @throws IllegalArgumentException if tagSet is - * null. + * @throws IllegalArgumentException if {@code tagSet} is + * {@code null}. */ public void addAllowedTagSet(TIFFTagSet tagSet) { if (tagSet == null) { @@ -87,15 +87,15 @@ public class TIFFImageReadParam extends ImageReadParam { } /** - * Removes a TIFFTagSet object from the list of - * allowed tag sets. Removal is based on the equals - * method of the TIFFTagSet, which is normally + * Removes a {@code TIFFTagSet} object from the list of + * allowed tag sets. Removal is based on the {@code equals} + * method of the {@code TIFFTagSet}, which is normally * defined as reference equality. * - * @param tagSet a TIFFTagSet. + * @param tagSet a {@code TIFFTagSet}. * - * @throws IllegalArgumentException if tagSet is - * null. + * @throws IllegalArgumentException if {@code tagSet} is + * {@code null}. */ public void removeAllowedTagSet(TIFFTagSet tagSet) { if (tagSet == null) { @@ -105,10 +105,10 @@ public class TIFFImageReadParam extends ImageReadParam { } /** - * Returns a List containing the allowed - * TIFFTagSet objects. + * Returns a {@code List} containing the allowed + * {@code TIFFTagSet} objects. * - * @return a List of TIFFTagSets. + * @return a {@code List} of {@code TIFFTagSet}s. */ public List getAllowedTagSets() { return allowedTagSets; diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java index 68542c4078d..c312bd55419 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -105,7 +105,7 @@ public class TIFFTag { * The name assigned to a tag with an unknown tag number. Such * a tag may be created for example when reading an IFD and a * tag number is encountered which is not in any of the - * TIFFTagSets known to the reader. + * {@code TIFFTagSet}s known to the reader. */ public static final String UNKNOWN_TAG_NAME = "UnknownTag"; @@ -141,12 +141,12 @@ public class TIFFTag { private SortedMap valueNames = null; /** - * Constructs a TIFFTag with a given name, tag number, set + * Constructs a {@code TIFFTag} with a given name, tag number, set * of legal data types, and value count. A negative value count signifies * that either an arbitrary number of values is legal or the required count * is determined by the values of other fields in the IFD. A non-negative * count specifies the number of values which an associated field must - * contain. The tag will have no associated TIFFTagSet. + * contain. The tag will have no associated {@code TIFFTagSet}. * *

If there are mnemonic names to be associated with the legal * data values for the tag, {@link #addValueName(int, String) @@ -183,18 +183,18 @@ public class TIFFTag { } /** - * Constructs a TIFFTag with a given name, tag number and - * TIFFTagSet to which it refers. The legal data types are + * Constructs a {@code TIFFTag} with a given name, tag number and + * {@code TIFFTagSet} to which it refers. The legal data types are * set to include {@link #TIFF_LONG} and {@link #TIFF_IFD_POINTER} and the - * value count is unity. The TIFFTagSet will - * represent the set of TIFFTags which appear in the IFD - * pointed to. A TIFFTag represents an IFD pointer if and - * only if tagSet is non-null or the data - * type TIFF_IFD_POINTER is legal. + * value count is unity. The {@code TIFFTagSet} will + * represent the set of {@code TIFFTag}s which appear in the IFD + * pointed to. A {@code TIFFTag} represents an IFD pointer if and + * only if {@code tagSet} is non-{@code null} or the data + * type {@code TIFF_IFD_POINTER} is legal. * * @param name the name of the tag. * @param number the number used to represent the tag. - * @param tagSet the TIFFTagSet to which this tag belongs. + * @param tagSet the {@code TIFFTagSet} to which this tag belongs. * @throws NullPointerException if name or tagSet is null. * @throws IllegalArgumentException if number is negative. * @@ -210,9 +210,9 @@ public class TIFFTag { } /** - * Constructs a TIFFTag with a given name, tag number, + * Constructs a {@code TIFFTag} with a given name, tag number, * and set of legal data types. The value count of the tag will be - * undefined and it will have no associated TIFFTagSet. + * undefined and it will have no associated {@code TIFFTagSet}. * * @param name the name of the tag. * @param number the number used to represent the tag. @@ -236,9 +236,9 @@ public class TIFFTag { * * @return the number of bytes used to store the given data type. * - * @throws IllegalArgumentException if datatype is - * less than MIN_DATATYPE or greater than - * MAX_DATATYPE. + * @throws IllegalArgumentException if {@code datatype} is + * less than {@code MIN_DATATYPE} or greater than + * {@code MAX_DATATYPE}. */ public static int getSizeOfType(int dataType) { if (dataType < MIN_DATATYPE ||dataType > MAX_DATATYPE) { @@ -251,7 +251,7 @@ public class TIFFTag { /** * Returns the name of the tag, as it will appear in image metadata. * - * @return the tag name, as a String. + * @return the tag name, as a {@code String}. */ public String getName() { return name; @@ -260,7 +260,7 @@ public class TIFFTag { /** * Returns the integer used to represent the tag. * - * @return the tag number, as an int. + * @return the tag number, as an {@code int}. */ public int getNumber() { return number; @@ -276,7 +276,7 @@ public class TIFFTag { * (1 << TIFFTag.TIFF_SHORT) | (1 << TIFFTag.TIFF_LONG) * * - * @return an int containing a bitmask encoding the + * @return an {@code int} containing a bitmask encoding the * set of valid data types. */ public int getDataTypes() { @@ -285,11 +285,11 @@ public class TIFFTag { /** * Returns the value count of this tag. If this value is positive, it - * represents the required number of values for a TIFFField + * represents the required number of values for a {@code TIFFField} * which has this tag. If the value is negative, the count is undefined. * In the latter case the count may be derived, e.g., the number of values - * of the BitsPerSample field is SamplesPerPixel, - * or it may be variable as in the case of most US-ASCII + * of the {@code BitsPerSample} field is {@code SamplesPerPixel}, + * or it may be variable as in the case of most {@code US-ASCII} * fields. * * @return the value count of this tag. @@ -299,18 +299,18 @@ public class TIFFTag { } /** - * Returns true if the given data type + * Returns {@code true} if the given data type * may be used for the data associated with this tag. * * @param dataType the data type to be queried, one of - * TIFF_BYTE, TIFF_SHORT, etc. + * {@code TIFF_BYTE}, {@code TIFF_SHORT}, etc. * - * @return a boolean indicating whether the given + * @return a {@code boolean} indicating whether the given * data type may be used with this tag. * - * @throws IllegalArgumentException if datatype is - * less than MIN_DATATYPE or greater than - * MAX_DATATYPE. + * @throws IllegalArgumentException if {@code datatype} is + * less than {@code MIN_DATATYPE} or greater than + * {@code MAX_DATATYPE}. */ public boolean isDataTypeOK(int dataType) { if (dataType < MIN_DATATYPE || dataType > MAX_DATATYPE) { @@ -320,38 +320,38 @@ public class TIFFTag { } /** - * Returns the TIFFTagSet of which this tag is a part. + * Returns the {@code TIFFTagSet} of which this tag is a part. * - * @return the containing TIFFTagSet. + * @return the containing {@code TIFFTagSet}. */ public TIFFTagSet getTagSet() { return tagSet; } /** - * Returns true if this tag is used to point to an IFD - * structure containing additional tags. A TIFFTag represents - * an IFD pointer if and only if its TIFFTagSet is - * non-null or the data type TIFF_IFD_POINTER is + * Returns {@code true} if this tag is used to point to an IFD + * structure containing additional tags. A {@code TIFFTag} represents + * an IFD pointer if and only if its {@code TIFFTagSet} is + * non-{@code null} or the data type {@code TIFF_IFD_POINTER} is * legal. This condition will be satisfied if and only if either - * getTagSet() != null or - * isDataTypeOK(TIFF_IFD_POINTER) == true. + * {@code getTagSet() != null} or + * {@code isDataTypeOK(TIFF_IFD_POINTER) == true}. * *

Many TIFF extensions use the IFD mechanism in order to limit the * number of new tags that may appear in the root IFD.

* - * @return true if this tag points to an IFD. + * @return {@code true} if this tag points to an IFD. */ public boolean isIFDPointer() { return tagSet != null || isDataTypeOK(TIFF_IFD_POINTER); } /** - * Returns true if there are mnemonic names associated with + * Returns {@code true} if there are mnemonic names associated with * the set of legal values for the data associated with this tag. Mnemonic * names apply only to tags which have integral data type. * - * @return true if mnemonic value names are available. + * @return {@code true} if mnemonic value names are available. */ public boolean hasValueNames() { return valueNames != null; @@ -373,14 +373,14 @@ public class TIFFTag { /** * Returns the mnemonic name associated with a particular value - * that this tag's data may take on, or null if + * that this tag's data may take on, or {@code null} if * no name is present. Mnemonic names apply only to tags which have * integral data type. * * @param value the data value. * * @return the mnemonic name associated with the value, as a - * String. + * {@code String}. */ public String getValueName(int value) { if (valueNames == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java index 8082fba86b8..793bafce1b7 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -39,7 +39,7 @@ import java.util.TreeSet; * specification itself). * *

This class and its subclasses are responsible for mapping - * between raw tag numbers and TIFFTag objects, which + * between raw tag numbers and {@code TIFFTag} objects, which * contain additional information about each tag, such as the tag's * name, legal data types, and mnemonic names for some or all of ts * data values. @@ -59,15 +59,15 @@ public class TIFFTagSet { private TIFFTagSet() {} /** - * Constructs a TIFFTagSet, given a List - * of TIFFTag objects. + * Constructs a {@code TIFFTagSet}, given a {@code List} + * of {@code TIFFTag} objects. * - * @param tags a List object containing - * TIFFTag objects to be added to this tag set. + * @param tags a {@code List} object containing + * {@code TIFFTag} objects to be added to this tag set. * - * @throws IllegalArgumentException if tags is - * null, or contains objects that are not instances - * of the TIFFTag class. + * @throws IllegalArgumentException if {@code tags} is + * {@code null}, or contains objects that are not instances + * of the {@code TIFFTag} class. */ public TIFFTagSet(List tags) { if (tags == null) { @@ -88,29 +88,29 @@ public class TIFFTagSet { } /** - * Returns the TIFFTag from this set that is - * associated with the given tag number, or null if + * Returns the {@code TIFFTag} from this set that is + * associated with the given tag number, or {@code null} if * no tag exists for that number. * * @param tagNumber the number of the tag to be retrieved. * - * @return the numbered TIFFTag, or null. + * @return the numbered {@code TIFFTag}, or {@code null}. */ public TIFFTag getTag(int tagNumber) { return allowedTagsByNumber.get(Integer.valueOf(tagNumber)); } /** - * Returns the TIFFTag having the given tag name, or - * null if the named tag does not belong to this tag set. + * Returns the {@code TIFFTag} having the given tag name, or + * {@code null} if the named tag does not belong to this tag set. * * @param tagName the name of the tag to be retrieved, as a - * String. + * {@code String}. * - * @return the named TIFFTag, or null. + * @return the named {@code TIFFTag}, or {@code null}. * - * @throws IllegalArgumentException if tagName is - * null. + * @throws IllegalArgumentException if {@code tagName} is + * {@code null}. */ public TIFFTag getTag(String tagName) { if (tagName == null) { @@ -123,7 +123,7 @@ public class TIFFTagSet { * Retrieves an unmodifiable numerically increasing set of tag numbers. * *

The returned object is unmodifiable and contains the tag - * numbers of all TIFFTags in this TIFFTagSet + * numbers of all {@code TIFFTag}s in this {@code TIFFTagSet} * sorted into ascending order according to * {@link Integer#compareTo(Object)}.

* @@ -145,7 +145,7 @@ public class TIFFTagSet { * Retrieves an unmodifiable lexicographically increasing set of tag names. * *

The returned object is unmodifiable and contains the tag - * names of all TIFFTags in this TIFFTagSet + * names of all {@code TIFFTag}s in this {@code TIFFTagSet} * sorted into ascending order according to * {@link String#compareTo(Object)}.

* From 4e4a6d18abe0f4633947128e16c29987ce34dd99 Mon Sep 17 00:00:00 2001 From: Ambarish Rapte Date: Mon, 15 Feb 2016 14:36:54 +0530 Subject: [PATCH 010/311] 8025001: setFocusTraversalPolicy() to ContainerOrderFocusTraversalPolicy results in an infinite loop Reviewed-by: ssadetsky, psadhukhan --- .../ContainerOrderFocusTraversalPolicy.java | 4 +- .../ContainerOrderFTPTest.java | 90 +++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java diff --git a/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java b/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java index d23e672779c..9b04496f65b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java @@ -231,7 +231,9 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy // Before all the checks below we first see if it's an FTP provider or a focus cycle root. // If it's the case just go down cycle (if it's set to "implicit"). Component comp = getComponentDownCycle(aComponent, FORWARD_TRAVERSAL); - if (comp != null) { + // Check if aComponent is focus-cycle-root's default Component, i.e. + // focus cycle root & focus-cycle-root's default Component is same. + if (comp != null && comp != aComponent) { return comp; } diff --git a/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java b/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java new file mode 100644 index 00000000000..5957204ee79 --- /dev/null +++ b/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016, 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 8025001 + @summary Tests java.awt.ContainerOrderFocusTraversalPolicy functionality. + @run main ContainerOrderFTPTest +*/ + +import java.awt.Frame; +import java.awt.Button; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.ContainerOrderFocusTraversalPolicy; + +public class ContainerOrderFTPTest { + + private final ContainerOrderFocusTraversalPolicy coftp; + private final Frame frame; + private final Button b1; + private final Button b2; + private final String expectedTraversal; + + public ContainerOrderFTPTest() { + expectedTraversal = "B1B2F1"; + b1 = new Button("B1"); + b2 = new Button("B2"); + frame = new Frame("F1"); + + frame.setLayout(new FlowLayout()); + frame.setSize(200, 200); + coftp = new ContainerOrderFocusTraversalPolicy(); + frame.setFocusTraversalPolicy(coftp); + frame.add(b1); + frame.add(b2); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + ContainerOrderFTPTest test = new ContainerOrderFTPTest(); + test.performTest(); + test.dispose(); + } + + public void performTest() { + int count = 0; + Component comp = coftp.getFirstComponent(frame); + String traversal = ""; + do { + comp = coftp.getComponentAfter(frame, comp); + if (comp instanceof Button) { + traversal += ((Button)comp).getLabel(); + } else if (comp instanceof Frame) { + traversal += ((Frame)comp).getTitle(); + } + count++; + } while(count < 3); + + if (!expectedTraversal.equals(traversal)) { + dispose(); + throw new RuntimeException("Incorrect Traversal. Expected : " + + expectedTraversal + "Actual : " + traversal); + } + } + + public void dispose() { + frame.dispose(); + } +} From 0b936de72ace703e09d5f2100b8197a89d52123a Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 12 Feb 2016 16:08:39 +0300 Subject: [PATCH 011/311] 8130061: java.beans.EventHandler.create does not specify how it fails when an EventHandler cannot be created Reviewed-by: alanb --- .../share/classes/java/beans/EventHandler.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java b/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java index 6f1427fe54a..1ab720f7555 100644 --- a/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java +++ b/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -526,8 +526,11 @@ public class EventHandler implements InvocationHandler { * @throws NullPointerException if {@code listenerInterface} is null * @throws NullPointerException if {@code target} is null * @throws NullPointerException if {@code action} is null - * + * @throws IllegalArgumentException if creating a Proxy for + * {@code listenerInterface} fails for any of the restrictions + * specified by {@link Proxy#newProxyInstance} * @see #create(Class, Object, String, String) + * @see Proxy#newProxyInstance */ public static T create(Class listenerInterface, Object target, String action) @@ -584,8 +587,11 @@ public class EventHandler implements InvocationHandler { * @throws NullPointerException if {@code listenerInterface} is null * @throws NullPointerException if {@code target} is null * @throws NullPointerException if {@code action} is null - * + * @throws IllegalArgumentException if creating a Proxy for + * {@code listenerInterface} fails for any of the restrictions + * specified by {@link Proxy#newProxyInstance} * @see #create(Class, Object, String, String, String) + * @see Proxy#newProxyInstance */ public static T create(Class listenerInterface, Object target, String action, @@ -675,8 +681,11 @@ public class EventHandler implements InvocationHandler { * @throws NullPointerException if {@code listenerInterface} is null * @throws NullPointerException if {@code target} is null * @throws NullPointerException if {@code action} is null - * + * @throws IllegalArgumentException if creating a Proxy for + * {@code listenerInterface} fails for any of the restrictions + * specified by {@link Proxy#newProxyInstance} * @see EventHandler + * @see Proxy#newProxyInstance */ public static T create(Class listenerInterface, Object target, String action, From 8eb27fd4d39087b3f12cf7156ceedc9d6fd88cb7 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 12 Feb 2016 16:09:39 +0300 Subject: [PATCH 012/311] 8136382: SimpleBeanInfo.loadImage succeeds when running with a security manager Reviewed-by: alanb --- .../classes/java/beans/SimpleBeanInfo.java | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java b/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java index ddef0cffad5..ba2cbcd2dc9 100644 --- a/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java +++ b/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -27,7 +27,8 @@ package java.beans; import java.awt.Image; import java.awt.Toolkit; -import java.io.InputStream; +import java.awt.image.ImageProducer; +import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; @@ -171,19 +172,24 @@ public class SimpleBeanInfo implements BeanInfo { } /** - * This is a utility method to help in loading icon images. - * It takes the name of a resource file associated with the - * current object's class file and loads an image object - * from that file. Typically images will be GIFs. + * This is a utility method to help in loading icon images. It takes the + * name of a resource file associated with the current object's class file + * and loads an image object from that file. Typically images will be GIFs. * - * @param resourceName A pathname relative to the directory - * holding the class file of the current class. For example, - * "wombat.gif". - * @return an image object. May be null if the load failed. + * @param resourceName A pathname relative to the directory holding the + * class file of the current class. For example, "wombat.gif". + * @return an image object or null if the resource is not found or the + * resource could not be loaded as an Image */ public Image loadImage(final String resourceName) { - try (InputStream in = getClass().getResourceAsStream(resourceName)) { - return Toolkit.getDefaultToolkit().createImage(in.readAllBytes()); + try { + final URL url = getClass().getResource(resourceName); + if (url != null) { + final ImageProducer ip = (ImageProducer) url.getContent(); + if (ip != null) { + return Toolkit.getDefaultToolkit().createImage(ip); + } + } } catch (final Exception ignored) { } return null; From 4458220d4a5b5c77ff2575c45ab18032d501a575 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 15 Feb 2016 20:27:12 +0300 Subject: [PATCH 013/311] 8148994: Replacing MH::invokeBasic with a direct call breaks LF customization Reviewed-by: jrose, redestad --- .../classes/java/lang/invoke/MethodHandleImpl.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index ebaf2a393ad..9b4029cc7b5 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -778,8 +778,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return (asTypeCache = wrapper); } + // Customize target if counting happens for too long. + private int invocations = CUSTOMIZE_THRESHOLD; + private void maybeCustomizeTarget() { + int c = invocations; + if (c >= 0) { + if (c == 1) { + target.customize(); + } + invocations = c - 1; + } + } + boolean countDown() { int c = count; + maybeCustomizeTarget(); if (c <= 1) { // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility. if (isCounting) { From 4ccb461831829d8e241ba9ae350da18d85e6119e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Mon, 15 Feb 2016 16:59:56 -0800 Subject: [PATCH 014/311] 8150204: (fs) Enhance java/nio/file/Files/probeContentType/Basic.java debugging output Add debugging information to the test. Reviewed-by: alanb --- .../file/Files/probeContentType/Basic.java | 80 ++++++++++++++++--- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/jdk/test/java/nio/file/Files/probeContentType/Basic.java b/jdk/test/java/nio/file/Files/probeContentType/Basic.java index 02298b48fef..ec90ed6b18c 100644 --- a/jdk/test/java/nio/file/Files/probeContentType/Basic.java +++ b/jdk/test/java/nio/file/Files/probeContentType/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -29,8 +29,9 @@ * @run main/othervm Basic */ -import java.nio.file.*; import java.io.*; +import java.nio.file.*; +import java.util.stream.Stream; /** * Uses Files.probeContentType to probe html file, custom file type, and minimal @@ -38,6 +39,9 @@ import java.io.*; */ public class Basic { + private static final boolean IS_UNIX = + ! System.getProperty("os.name").startsWith("Windows"); + static Path createHtmlFile() throws IOException { Path file = Files.createTempFile("foo", ".html"); try (OutputStream out = Files.newOutputStream(file)) { @@ -51,10 +55,61 @@ public class Basic { return Files.createTempFile("red", ".grape"); } - static void checkContentTypes(String[] extensions, String[] expectedTypes) + private static int checkContentTypes(String expected, String actual) { + assert expected != null; + assert actual != null; + + if (!expected.equals(actual)) { + if (IS_UNIX) { + Path userMimeTypes = + Paths.get(System.getProperty("user.home"), ".mime.types"); + if (!Files.exists(userMimeTypes)) { + System.out.println(userMimeTypes + " does not exist"); + } else if (!Files.isReadable(userMimeTypes)) { + System.out.println(userMimeTypes + " is not readable"); + } else { + System.out.println(userMimeTypes + " contents:"); + try (Stream lines = Files.lines(userMimeTypes)) { + lines.forEach(System.out::println); + System.out.println(""); + } catch (IOException ioe) { + System.err.println("Problem reading " + + userMimeTypes); + } + } + + Path etcMimeTypes = Paths.get("/etc/mime.types"); + if (!Files.exists(etcMimeTypes)) { + System.out.println(etcMimeTypes + " does not exist"); + } else if (!Files.isReadable(etcMimeTypes)) { + System.out.println(etcMimeTypes + " is not readable"); + } else { + System.out.println(etcMimeTypes + " contents:"); + try (Stream lines = Files.lines(etcMimeTypes)) { + lines.forEach(System.out::println); + System.out.println(""); + } catch (IOException ioe) { + System.err.println("Problem reading " + + etcMimeTypes); + } + } + } + + System.err.println("Expected \"" + expected + + "\" but obtained \"" + + actual + "\""); + + return 1; + } + + return 0; + } + + static int checkOSXContentTypes(String[] extensions, String[] expectedTypes) throws IOException { if (extensions.length != expectedTypes.length) { - throw new IllegalArgumentException("Parameter array lengths differ"); + throw new IllegalArgumentException + ("Parameter array lengths differ"); } int failures = 0; @@ -79,12 +134,11 @@ public class Basic { } } - if (failures > 0) { - throw new RuntimeException("Test failed!"); - } + return failures; } public static void main(String[] args) throws IOException { + int failures = 0; // exercise default file type detector Path file = createHtmlFile(); @@ -93,8 +147,7 @@ public class Basic { if (type == null) { System.err.println("Content type cannot be determined - test skipped"); } else { - if (!type.equals("text/html")) - throw new RuntimeException("Unexpected type: " + type); + failures += checkContentTypes("text/html", type); } } finally { Files.delete(file); @@ -106,8 +159,7 @@ public class Basic { String type = Files.probeContentType(file); if (type == null) throw new RuntimeException("Custom file type detector not installed?"); - if (!type.equals("grape/unknown")) - throw new RuntimeException("Unexpected type: " + type); + failures += checkContentTypes("grape/unknown", type); } finally { Files.delete(file); } @@ -122,7 +174,11 @@ public class Basic { "image/jpeg", "audio/mpeg", "video/mp4", "application/pdf", "image/png" }; - checkContentTypes(extensions, expectedTypes); + failures += checkOSXContentTypes(extensions, expectedTypes); + } + + if (failures > 0) { + throw new RuntimeException("Test failed!"); } } } From 4054254344ded96254cc750a063f4159a4395457 Mon Sep 17 00:00:00 2001 From: Steve Drach Date: Mon, 15 Feb 2016 17:47:53 -0800 Subject: [PATCH 015/311] 8132734: JDK 9 runtime changes to support multi-release jar files JEP 238 Multi-Release JAR Files runtime support Reviewed-by: alanb, psandoz, sherman --- .../classes/java/net/JarURLConnection.java | 8 + .../classes/java/util/jar/Attributes.java | 10 +- .../share/classes/java/util/jar/JarFile.java | 478 ++++++++++++++++-- .../share/classes/sun/misc/URLClassPath.java | 10 +- .../sun/net/www/protocol/jar/URLJarFile.java | 27 +- .../net/www/protocol/jar/JarFileFactory.java | 12 +- .../net/www/protocol/jar/JarFileFactory.java | 12 +- .../util/jar/JarFile/MultiReleaseJarAPI.java | 177 +++++++ .../MultiReleaseJarHttpProperties.java | 156 ++++++ .../jar/JarFile/MultiReleaseJarIterators.java | 228 +++++++++ .../JarFile/MultiReleaseJarProperties.java | 200 ++++++++ .../jar/JarFile/MultiReleaseJarSecurity.java | 108 ++++ .../jar/MultiReleaseJarURLConnection.java | 117 +++++ 13 files changed, 1483 insertions(+), 60 deletions(-) create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java create mode 100644 jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java diff --git a/jdk/src/java.base/share/classes/java/net/JarURLConnection.java b/jdk/src/java.base/share/classes/java/net/JarURLConnection.java index 70dedec795e..4c7e0ab6f94 100644 --- a/jdk/src/java.base/share/classes/java/net/JarURLConnection.java +++ b/jdk/src/java.base/share/classes/java/net/JarURLConnection.java @@ -173,6 +173,14 @@ public abstract class JarURLConnection extends URLConnection { } jarFileURL = new URL(spec.substring(0, separator++)); + /* + * The url argument may have had a runtime fragment appended, so + * we need to add a runtime fragment to the jarFileURL to enable + * runtime versioning when the underlying jar file is opened. + */ + if ("runtime".equals(url.getRef())) { + jarFileURL = new URL(jarFileURL, "#runtime"); + } entryName = null; /* if ! is the last letter of the innerURL, entryName is null */ diff --git a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java index f2a01acbdba..b99755b4bb6 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java +++ b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -646,5 +646,13 @@ public class Attributes implements Map, Cloneable { * manifest attribute used for package versioning. */ public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor"); + + /** + * {@code Name} object for {@code Multi-Release} + * manifest attribute that indicates this is a multi-release JAR file. + * + * @since 9 + */ + public static final Name MULTI_RELEASE = new Name("Multi-Release"); } } diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java index 62734ceefbd..d5032fed2fd 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java @@ -28,6 +28,7 @@ package java.util.jar; import java.io.*; import java.lang.ref.SoftReference; import java.net.URL; +import java.security.PrivilegedAction; import java.util.*; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -37,28 +38,91 @@ import java.security.cert.Certificate; import java.security.AccessController; import java.security.CodeSource; import jdk.internal.misc.SharedSecrets; -import sun.security.action.GetPropertyAction; import sun.security.util.ManifestEntryVerifier; import sun.security.util.SignatureFileVerifier; +import static java.util.jar.Attributes.Name.MULTI_RELEASE; + /** * The {@code JarFile} class is used to read the contents of a jar file * from any file that can be opened with {@code java.io.RandomAccessFile}. * It extends the class {@code java.util.zip.ZipFile} with support - * for reading an optional {@code Manifest} entry. The - * {@code Manifest} can be used to specify meta-information about the - * jar file and its entries. + * for reading an optional {@code Manifest} entry, and support for + * processing multi-release jar files. The {@code Manifest} can be used + * to specify meta-information about the jar file and its entries. + * + *

A multi-release jar file is a jar file that contains + * a manifest with a main attribute named "Multi-Release", + * a set of "base" entries, some of which are public classes with public + * or protected methods that comprise the public interface of the jar file, + * and a set of "versioned" entries contained in subdirectories of the + * "META-INF/versions" directory. The versioned entries are partitioned by the + * major version of the Java platform. A versioned entry, with a version + * {@code n}, {@code 8 < n}, in the "META-INF/versions/{n}" directory overrides + * the base entry as well as any entry with a version number {@code i} where + * {@code 8 < i < n}. + * + *

By default, a {@code JarFile} for a multi-release jar file is configured + * to process the multi-release jar file as if it were a plain (unversioned) jar + * file, and as such an entry name is associated with at most one base entry. + * The {@code JarFile} may be configured to process a multi-release jar file by + * creating the {@code JarFile} with the + * {@link JarFile#JarFile(File, boolean, int, Release)} constructor. The + * {@code Release} object sets a maximum version used when searching for + * versioned entries. When so configured, an entry name + * can correspond with at most one base entry and zero or more versioned + * entries. A search is required to associate the entry name with the latest + * versioned entry whose version is less than or equal to the maximum version + * (see {@link #getEntry(String)}). + * + *

Class loaders that utilize {@code JarFile} to load classes from the + * contents of {@code JarFile} entries should construct the {@code JarFile} + * by invoking the {@link JarFile#JarFile(File, boolean, int, Release)} + * constructor with the value {@code Release.RUNTIME} assigned to the last + * argument. This assures that classes compatible with the major + * version of the running JVM are loaded from multi-release jar files. + * + *

If the verify flag is on when opening a signed jar file, the content of + * the file is verified against its signature embedded inside the file. Please + * note that the verification process does not include validating the signer's + * certificate. A caller should inspect the return value of + * {@link JarEntry#getCodeSigners()} to further determine if the signature + * can be trusted. * *

Unless otherwise noted, passing a {@code null} argument to a constructor * or method in this class will cause a {@link NullPointerException} to be * thrown. * - * If the verify flag is on when opening a signed jar file, the content of the - * file is verified against its signature embedded inside the file. Please note - * that the verification process does not include validating the signer's - * certificate. A caller should inspect the return value of - * {@link JarEntry#getCodeSigners()} to further determine if the signature - * can be trusted. + * @implNote + *

+ * If the API can not be used to configure a {@code JarFile} (e.g. to override + * the configuration of a compiled application or library), two {@code System} + * properties are available. + *
    + *
  • + * {@code jdk.util.jar.version} can be assigned a value that is the + * {@code String} representation of a non-negative integer + * {@code <= Version.current().major()}. The value is used to set the effective + * runtime version to something other than the default value obtained by + * evaluating {@code Version.current().major()}. The effective runtime version + * is the version that the {@link JarFile#JarFile(File, boolean, int, Release)} + * constructor uses when the value of the last argument is + * {@code Release.RUNTIME}. + *
  • + *
  • + * {@code jdk.util.jar.enableMultiRelease} can be assigned one of the three + * {@code String} values true, false, or force. The + * value true, the default value, enables multi-release jar file + * processing. The value false disables multi-release jar processing, + * ignoring the "Multi-Release" manifest attribute, and the versioned + * directories in a multi-release jar file if they exist. Furthermore, + * the method {@link JarFile#isMultiRelease()} returns false. The value + * force causes the {@code JarFile} to be initialized to runtime + * versioning after construction. It effectively does the same as this code: + * {@code (new JarFile(File, boolean, int, Release.RUNTIME)}. + *
  • + *
+ *
* * @author David Connelly * @see Manifest @@ -68,26 +132,126 @@ import sun.security.util.SignatureFileVerifier; */ public class JarFile extends ZipFile { + private final static int BASE_VERSION; + private final static int RUNTIME_VERSION; + private final static boolean MULTI_RELEASE_ENABLED; + private final static boolean MULTI_RELEASE_FORCED; private SoftReference manRef; private JarEntry manEntry; private JarVerifier jv; private boolean jvInitialized; private boolean verify; + private final int version; + private boolean notVersioned; + private final boolean runtimeVersioned; // indicates if Class-Path attribute present (only valid if hasCheckedSpecialAttributes true) private boolean hasClassPathAttribute; // true if manifest checked for special attributes private volatile boolean hasCheckedSpecialAttributes; - // Set up JavaUtilJarAccess in SharedSecrets static { + // Set up JavaUtilJarAccess in SharedSecrets SharedSecrets.setJavaUtilJarAccess(new JavaUtilJarAccessImpl()); + + BASE_VERSION = 8; // one less than lowest version for versioned entries + RUNTIME_VERSION = AccessController.doPrivileged( + new PrivilegedAction() { + public Integer run() { + Integer v = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 Version integrated + Integer i = Integer.getInteger("jdk.util.jar.version", v); + i = i < 0 ? 0 : i; + return i > v ? v : i; + } + } + ); + String multi_release = AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return System.getProperty("jdk.util.jar.enableMultiRelease", "true"); + } + } + ); + switch (multi_release) { + case "true": + default: + MULTI_RELEASE_ENABLED = true; + MULTI_RELEASE_FORCED = false; + break; + case "false": + MULTI_RELEASE_ENABLED = false; + MULTI_RELEASE_FORCED = false; + break; + case "force": + MULTI_RELEASE_ENABLED = true; + MULTI_RELEASE_FORCED = true; + break; + } } + /** + * A set of constants that represent the entries in either the base directory + * or one of the versioned directories in a multi-release jar file. It's + * possible for a multi-release jar file to contain versioned directories + * that are not represented by the constants of the {@code Release} enum. + * In those cases, the entries will not be located by this {@code JarFile} + * through the aliasing mechanism, but they can be directly accessed by + * specifying the full path name of the entry. + * + * @since 9 + */ + public enum Release { + /** + * Represents unversioned entries, or entries in "regular", as opposed + * to multi-release jar files. + */ + BASE(BASE_VERSION), + + /** + * Represents entries found in the META-INF/versions/9 directory of a + * multi-release jar file. + */ + VERSION_9(9), + + // fill in the "blanks" for future releases + + /** + * Represents entries found in the META-INF/versions/{n} directory of a + * multi-release jar file, where {@code n} is the effective runtime + * version of the jar file. + * + * @implNote + *
+ * The effective runtime version is determined + * by evaluating {@code Version.current().major()} or by using the value + * of the {@code jdk.util.jar.version} System property if it exists. + *
+ */ + RUNTIME(RUNTIME_VERSION); + + Release(int version) { + this.version = version; + } + + private static Release valueOf(int version) { + return version <= BASE.value() ? BASE : valueOf("VERSION_" + version); + } + + private final int version; + + private int value() { + return this.version; + } + } + + private static final String META_INF = "META-INF/"; + + private static final String META_INF_VERSIONS = META_INF + "versions/"; + /** * The JAR manifest file name. */ - public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; + public static final String MANIFEST_NAME = META_INF + "MANIFEST.MF"; /** * Creates a new {@code JarFile} to read from the specified @@ -129,7 +293,6 @@ class JarFile extends ZipFile { this(file, true, ZipFile.OPEN_READ); } - /** * Creates a new {@code JarFile} to read from the specified * {@code File} object. @@ -144,7 +307,6 @@ class JarFile extends ZipFile { this(file, verify, ZipFile.OPEN_READ); } - /** * Creates a new {@code JarFile} to read from the specified * {@code File} object in the specified mode. The mode argument @@ -162,10 +324,104 @@ class JarFile extends ZipFile { * @since 1.3 */ public JarFile(File file, boolean verify, int mode) throws IOException { - super(file, mode); - this.verify = verify; + this(file, verify, mode, Release.BASE); + this.notVersioned = true; } + /** + * Creates a new {@code JarFile} to read from the specified + * {@code File} object in the specified mode. The mode argument + * must be either {@code OPEN_READ} or {@code OPEN_READ | OPEN_DELETE}. + * The version argument configures the {@code JarFile} for processing + * multi-release jar files. + * + * @param file the jar file to be opened for reading + * @param verify whether or not to verify the jar file if + * it is signed. + * @param mode the mode in which the file is to be opened + * @param version specifies the release version for a multi-release jar file + * @throws IOException if an I/O error has occurred + * @throws IllegalArgumentException + * if the {@code mode} argument is invalid + * @throws SecurityException if access to the file is denied + * by the SecurityManager + * @throws NullPointerException if {@code version} is {@code null} + * @since 9 + */ + public JarFile(File file, boolean verify, int mode, Release version) throws IOException { + super(file, mode); + Objects.requireNonNull(version); + this.verify = verify; + // version applies to multi-release jar files, ignored for regular jar files + this.version = MULTI_RELEASE_FORCED ? RUNTIME_VERSION : version.value(); + this.runtimeVersioned = version == Release.RUNTIME; + assert runtimeVersionExists(); + } + + private boolean runtimeVersionExists() { + int version = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 integrated + try { + Release.valueOf(version); + return true; + } catch (IllegalArgumentException x) { + System.err.println("No JarFile.Release object for release " + version); + return false; + } + } + + /** + * Returns the maximum version used when searching for versioned entries. + * + * @return the maximum version, or {@code Release.BASE} if this jar file is + * processed as if it is an unversioned jar file or is not a + * multi-release jar file + * @since 9 + */ + public final Release getVersion() { + if (isMultiRelease()) { + return runtimeVersioned ? Release.RUNTIME : Release.valueOf(version); + } else { + return Release.BASE; + } + } + + /** + * Indicates whether or not this jar file is a multi-release jar file. + * + * @return true if this JarFile is a multi-release jar file + * @since 9 + */ + public final boolean isMultiRelease() { + // do not call this code in a constructor because some subclasses use + // lazy loading of manifest so it won't be available at construction time + if (MULTI_RELEASE_ENABLED) { + // Doubled-checked locking pattern + Boolean result = isMultiRelease; + if (result == null) { + synchronized (this) { + result = isMultiRelease; + if (result == null) { + Manifest man = null; + try { + man = getManifest(); + } catch (IOException e) { + //Ignored, manifest cannot be read + } + isMultiRelease = result = (man != null) + && man.getMainAttributes().containsKey(MULTI_RELEASE) + ? Boolean.TRUE : Boolean.FALSE; + } + } + } + return result == Boolean.TRUE; + } else { + return false; + } + } + // the following field, isMultiRelease, should only be used in the method + // isMultiRelease(), like a static local + private volatile Boolean isMultiRelease; // is jar multi-release? + /** * Returns the jar file manifest, or {@code null} if none. * @@ -209,40 +465,87 @@ class JarFile extends ZipFile { } /** - * Returns the {@code JarEntry} for the given entry name or + * Returns the {@code JarEntry} for the given base entry name or * {@code null} if not found. * + *

If this {@code JarFile} is a multi-release jar file and is configured + * to be processed as such, then a search is performed to find and return + * a {@code JarEntry} that is the latest versioned entry associated with the + * given entry name. The returned {@code JarEntry} is the versioned entry + * corresponding to the given base entry name prefixed with the string + * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for + * which an entry exists. If such a versioned entry does not exist, then + * the {@code JarEntry} for the base entry is returned, otherwise + * {@code null} is returned if no entries are found. The initial value for + * the version {@code n} is the maximum version as returned by the method + * {@link JarFile#getVersion()}. + * * @param name the jar file entry name - * @return the {@code JarEntry} for the given entry name or - * {@code null} if not found. + * @return the {@code JarEntry} for the given entry name, or + * the versioned entry name, or {@code null} if not found * * @throws IllegalStateException * may be thrown if the jar file has been closed * * @see java.util.jar.JarEntry + * + * @implSpec + *

+ * This implementation invokes {@link JarFile#getEntry(String)}. + *
*/ public JarEntry getJarEntry(String name) { return (JarEntry)getEntry(name); } /** - * Returns the {@code ZipEntry} for the given entry name or + * Returns the {@code ZipEntry} for the given base entry name or * {@code null} if not found. * + *

If this {@code JarFile} is a multi-release jar file and is configured + * to be processed as such, then a search is performed to find and return + * a {@code ZipEntry} that is the latest versioned entry associated with the + * given entry name. The returned {@code ZipEntry} is the versioned entry + * corresponding to the given base entry name prefixed with the string + * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for + * which an entry exists. If such a versioned entry does not exist, then + * the {@code ZipEntry} for the base entry is returned, otherwise + * {@code null} is returned if no entries are found. The initial value for + * the version {@code n} is the maximum version as returned by the method + * {@link JarFile#getVersion()}. + * * @param name the jar file entry name * @return the {@code ZipEntry} for the given entry name or - * {@code null} if not found + * the versioned entry name or {@code null} if not found * * @throws IllegalStateException * may be thrown if the jar file has been closed * * @see java.util.zip.ZipEntry + * + * @implSpec + *

+ * This implementation may return a versioned entry for the requested name + * even if there is not a corresponding base entry. This can occur + * if there is a private or package-private versioned entry that matches. + * If a subclass overrides this method, assure that the override method + * invokes {@code super.getEntry(name)} to obtain all versioned entries. + *
*/ public ZipEntry getEntry(String name) { ZipEntry ze = super.getEntry(name); if (ze != null) { return new JarFileEntry(ze); } + // no matching base entry, but maybe there is a versioned entry, + // like a new private class + if (isMultiRelease()) { + ze = new ZipEntry(name); + ZipEntry vze = getVersionedEntry(ze); + if (ze != vze) { + return new JarFileEntry(name, vze); + } + } return null; } @@ -250,14 +553,42 @@ class JarFile extends ZipFile { Iterator { final Enumeration e = JarFile.super.entries(); + ZipEntry ze; public boolean hasNext() { - return e.hasMoreElements(); + if (notVersioned) { + return e.hasMoreElements(); + } + if (ze != null) { + return true; + } + return findNext(); + } + + private boolean findNext() { + while (e.hasMoreElements()) { + ZipEntry ze2 = e.nextElement(); + if (!ze2.getName().startsWith(META_INF_VERSIONS)) { + ze = ze2; + return true; + } + } + return false; } public JarEntry next() { - ZipEntry ze = e.nextElement(); - return new JarFileEntry(ze); + ZipEntry ze2; + + if (notVersioned) { + ze2 = e.nextElement(); + return new JarFileEntry(ze2.getName(), ze2); + } + if (ze != null || findNext()) { + ze2 = ze; + ze = null; + return new JarFileEntry(ze2); + } + throw new NoSuchElementException(); } public boolean hasMoreElements() { @@ -274,7 +605,19 @@ class JarFile extends ZipFile { } /** - * Returns an enumeration of the jar file entries. + * Returns an enumeration of the jar file entries. The set of entries + * returned depends on whether or not the jar file is a multi-release jar + * file, and on the constructor used to create the {@code JarFile}. If the + * jar file is not a multi-release jar file, all entries are returned, + * regardless of how the {@code JarFile} is created. If the constructor + * does not take a {@code Release} argument, all entries are returned. + * If the jar file is a multi-release jar file and the constructor takes a + * {@code Release} argument, then the set of entries returned is equivalent + * to the set of entries that would be returned if the set was built by + * invoking {@link JarFile#getEntry(String)} or + * {@link JarFile#getJarEntry(String)} with the name of each base entry in + * the jar file. A base entry is an entry whose path name does not start + * with "META-INF/versions/". * * @return an enumeration of the jar file entries * @throws IllegalStateException @@ -285,10 +628,21 @@ class JarFile extends ZipFile { } /** - * Returns an ordered {@code Stream} over the jar file entries. + * Returns an ordered {@code Stream} over all the jar file entries. * Entries appear in the {@code Stream} in the order they appear in - * the central directory of the jar file. - * + * the central directory of the jar file. The set of entries + * returned depends on whether or not the jar file is a multi-release jar + * file, and on the constructor used to create the {@code JarFile}. If the + * jar file is not a multi-release jar file, all entries are returned, + * regardless of how the {@code JarFile} is created. If the constructor + * does not take a {@code Release} argument, all entries are returned. + * If the jar file is a multi-release jar file and the constructor takes a + * {@code Release} argument, then the set of entries returned is equivalent + * to the set of entries that would be returned if the set was built by + * invoking {@link JarFile#getEntry(String)} or + * {@link JarFile#getJarEntry(String)} with the name of each base entry in + * the jar file. A base entry is an entry whose path name does not start + * with "META-INF/versions/". * @return an ordered {@code Stream} of entries in this jar file * @throws IllegalStateException if the jar file has been closed * @since 1.8 @@ -300,14 +654,44 @@ class JarFile extends ZipFile { Spliterator.IMMUTABLE | Spliterator.NONNULL), false); } + private ZipEntry searchForVersionedEntry(final int version, String name) { + ZipEntry vze = null; + String sname = "/" + name; + int i = version; + while (i > BASE_VERSION) { + vze = super.getEntry(META_INF_VERSIONS + i + sname); + if (vze != null) break; + i--; + } + return vze; + } + + private ZipEntry getVersionedEntry(ZipEntry ze) { + ZipEntry vze = null; + if (version > BASE_VERSION && !ze.isDirectory()) { + String name = ze.getName(); + if (!name.startsWith(META_INF)) { + vze = searchForVersionedEntry(version, name); + } + } + return vze == null ? ze : vze; + } + private class JarFileEntry extends JarEntry { + final private String name; + JarFileEntry(ZipEntry ze) { - super(ze); + super(isMultiRelease() ? getVersionedEntry(ze) : ze); + this.name = ze.getName(); + } + JarFileEntry(String name, ZipEntry vze) { + super(vze); + this.name = name; } public Attributes getAttributes() throws IOException { Manifest man = JarFile.this.getManifest(); if (man != null) { - return man.getAttributes(getName()); + return man.getAttributes(super.getName()); } else { return null; } @@ -319,7 +703,7 @@ class JarFile extends ZipFile { throw new RuntimeException(e); } if (certs == null && jv != null) { - certs = jv.getCerts(JarFile.this, this); + certs = jv.getCerts(JarFile.this, reifiedEntry()); } return certs == null ? null : certs.clone(); } @@ -330,10 +714,22 @@ class JarFile extends ZipFile { throw new RuntimeException(e); } if (signers == null && jv != null) { - signers = jv.getCodeSigners(JarFile.this, this); + signers = jv.getCodeSigners(JarFile.this, reifiedEntry()); } return signers == null ? null : signers.clone(); } + JarFileEntry reifiedEntry() { + if (isMultiRelease()) { + String entryName = super.getName(); + return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this); + } + return this; + } + + @Override + public String getName() { + return name; + } } /* @@ -491,12 +887,19 @@ class JarFile extends ZipFile { // wrap a verifier stream around the real stream return new JarVerifier.VerifierStream( getManifestFromReference(), - ze instanceof JarFileEntry ? - (JarEntry) ze : getJarEntry(ze.getName()), + verifiableEntry(ze), super.getInputStream(ze), jv); } + private JarEntry verifiableEntry(ZipEntry ze) { + if (!(ze instanceof JarFileEntry)) { + ze = getJarEntry(ze.getName()); + } + // assure the name and entry match for verification + return ze == null ? null : ((JarFileEntry)ze).reifiedEntry(); + } + // Statics for hand-coded Boyer-Moore search private static final char[] CLASSPATH_CHARS = {'c','l','a','s','s','-','p','a','t','h'}; // The bad character shift for "class-path" @@ -523,7 +926,7 @@ class JarFile extends ZipFile { private JarEntry getManEntry() { if (manEntry == null) { // First look up manifest entry using standard name - manEntry = getJarEntry(MANIFEST_NAME); + ZipEntry manEntry = super.getEntry(MANIFEST_NAME); if (manEntry == null) { // If not found, then iterate through all the "META-INF/" // entries to find a match. @@ -531,12 +934,15 @@ class JarFile extends ZipFile { if (names != null) { for (String name : names) { if (MANIFEST_NAME.equals(name.toUpperCase(Locale.ENGLISH))) { - manEntry = getJarEntry(name); + manEntry = super.getEntry(name); break; } } } } + this.manEntry = (manEntry == null) + ? null + : new JarFileEntry(manEntry.getName(), manEntry); } return manEntry; } diff --git a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java index 1ad9a2776b6..01afb44a159 100644 --- a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java +++ b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java @@ -63,6 +63,7 @@ import java.util.jar.JarEntry; import java.util.jar.Manifest; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; +import java.util.zip.ZipFile; import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; @@ -727,9 +728,10 @@ public class URLClassPath { if (!p.exists()) { throw new FileNotFoundException(p.getPath()); } - return checkJar(new JarFile(p.getPath())); + return checkJar(new JarFile(new File(p.getPath()), true, ZipFile.OPEN_READ, + JarFile.Release.RUNTIME)); } - URLConnection uc = getBaseURL().openConnection(); + URLConnection uc = (new URL(getBaseURL(), "#runtime")).openConnection(); uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION); JarFile jarFile = ((JarURLConnection)uc).getJarFile(); return checkJar(jarFile); @@ -756,7 +758,9 @@ public class URLClassPath { final URL url; try { - url = new URL(getBaseURL(), ParseUtil.encodePath(name, false)); + // add #runtime fragment to tell JarURLConnection to use + // runtime versioning if the underlying jar file is multi-release + url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime"); if (check) { URLClassPath.check(url); } diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java index 1e8697ba237..fe1a1f3c8f2 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java @@ -65,9 +65,10 @@ public class URLJarFile extends JarFile { } static JarFile getJarFile(URL url, URLJarFileCloseController closeController) throws IOException { - if (isFileURL(url)) - return new URLJarFile(url, closeController); - else { + if (isFileURL(url)) { + Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE; + return new URLJarFile(url, closeController, version); + } else { return retrieve(url, closeController); } } @@ -89,8 +90,13 @@ public class URLJarFile extends JarFile { this.closeController = closeController; } - private URLJarFile(URL url, URLJarFileCloseController closeController) throws IOException { - super(ParseUtil.decode(url.getFile())); + private URLJarFile(File file, URLJarFileCloseController closeController, Release version) throws IOException { + super(file, true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE, version); + this.closeController = closeController; + } + + private URLJarFile(URL url, URLJarFileCloseController closeController, Release version) throws IOException { + super(new File(ParseUtil.decode(url.getFile())), true, ZipFile.OPEN_READ, version); this.closeController = closeController; } @@ -175,14 +181,6 @@ public class URLJarFile extends JarFile { return false; } - /** - * Given a URL, retrieves a JAR file, caches it to disk, and creates a - * cached JAR file object. - */ - private static JarFile retrieve(final URL url) throws IOException { - return retrieve(url, null); - } - /** * Given a URL, retrieves a JAR file, caches it to disk, and creates a * cached JAR file object. @@ -202,6 +200,7 @@ public class URLJarFile extends JarFile { { JarFile result = null; + Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE; /* get the stream before asserting privileges */ try (final InputStream in = url.openConnection().getInputStream()) { @@ -211,7 +210,7 @@ public class URLJarFile extends JarFile { Path tmpFile = Files.createTempFile("jar_cache", null); try { Files.copy(in, tmpFile, StandardCopyOption.REPLACE_EXISTING); - JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController); + JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController, version); tmpFile.toFile().deleteOnExit(); return jarFile; } catch (Throwable thr) { diff --git a/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java index 559fda4144f..2001c382324 100644 --- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -85,7 +85,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { result = getCachedJarFile(url); if (result == null) { - fileCache.put(URLUtil.urlNoFragString(url), local_result); + fileCache.put(urlKey(url), local_result); urlCache.put(local_result, url); result = local_result; } else { @@ -113,13 +113,13 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { URL urlRemoved = urlCache.remove(jarFile); if (urlRemoved != null) - fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); + fileCache.remove(urlKey(urlRemoved)); } } private JarFile getCachedJarFile(URL url) { assert Thread.holdsLock(instance); - JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); + JarFile result = fileCache.get(urlKey(url)); /* if the JAR file is cached, the permission will always be there */ if (result != null) { @@ -149,6 +149,12 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { return result; } + private String urlKey(URL url) { + String urlstr = URLUtil.urlNoFragString(url); + if ("runtime".equals(url.getRef())) urlstr += "#runtime"; + return urlstr; + } + private Permission getPermission(JarFile jarFile) { try { URLConnection uc = getConnection(jarFile); diff --git a/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java index 07db32fc079..91bf5388460 100644 --- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -95,7 +95,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { result = getCachedJarFile(url); if (result == null) { - fileCache.put(URLUtil.urlNoFragString(url), local_result); + fileCache.put(urlKey(url), local_result); urlCache.put(local_result, url); result = local_result; } else { @@ -123,13 +123,13 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { URL urlRemoved = urlCache.remove(jarFile); if (urlRemoved != null) - fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); + fileCache.remove(urlKey(urlRemoved)); } } private JarFile getCachedJarFile(URL url) { assert Thread.holdsLock(instance); - JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); + JarFile result = fileCache.get(urlKey(url)); /* if the JAR file is cached, the permission will always be there */ if (result != null) { @@ -159,6 +159,12 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { return result; } + private String urlKey(URL url) { + String urlstr = URLUtil.urlNoFragString(url); + if ("runtime".equals(url.getRef())) urlstr += "#runtime"; + return urlstr; + } + private Permission getPermission(JarFile jarFile) { try { URLConnection uc = getConnection(jarFile); diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java new file mode 100644 index 00000000000..7f7653e9eab --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015, 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 8132734 + * @summary Test the extended API and the aliasing additions in JarFile that + * support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarAPI + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import static java.util.jar.JarFile.Release; +import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + + +public class MultiReleaseJarAPI { + String userdir = System.getProperty("user.dir","."); + File unversioned = new File(userdir, "unversioned.jar"); + File multirelease = new File(userdir, "multi-release.jar"); + File signedmultirelease = new File(userdir, "signed-multi-release.jar"); + Release[] values = JarFile.Release.values(); + + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildUnversionedJar(); + creator.buildMultiReleaseJar(); + creator.buildSignedMultiReleaseJar(); + } + + @AfterClass + public void close() throws IOException { + Files.delete(unversioned.toPath()); + Files.delete(multirelease.toPath()); + Files.delete(signedmultirelease.toPath()); + } + + @Test + public void isMultiReleaseJar() throws Exception { + try (JarFile jf = new JarFile(unversioned)) { + Assert.assertFalse(jf.isMultiRelease()); + } + + try (JarFile jf = new JarFile(multirelease)) { + Assert.assertTrue(jf.isMultiRelease()); + } + } + + @Test + public void testVersioning() throws Exception { + // multi-release jar + JarFile jar = new JarFile(multirelease); + Assert.assertEquals(Release.BASE, jar.getVersion()); + jar.close(); + + for (Release value : values) { + System.err.println("test versioning for Release " + value); + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, value)) { + Assert.assertEquals(value, jf.getVersion()); + } + } + + // regular, unversioned, jar + for (Release value : values) { + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, value)) { + Assert.assertEquals(Release.BASE, jf.getVersion()); + } + } + + // assure that we have a Release object corresponding to the actual runtime version + String version = "VERSION_" + jdkMajorVersion(); + boolean runtimeVersionExists = false; + for (Release value : values) { + if (version.equals(value.name())) runtimeVersionExists = true; + } + Assert.assertTrue(runtimeVersionExists); + } + + @Test + public void testAliasing() throws Exception { + for (Release value : values) { + System.err.println("test aliasing for Release " + value); + String name = value.name(); + String prefix; + if (name.equals("BASE")) { + prefix = ""; + } else if (name.equals("RUNTIME")) { + prefix = "META-INF/versions/" + jdkMajorVersion() + "/"; + } else { + prefix = "META-INF/versions/" + name.substring(8) + "/"; + } + // test both multi-release jars + readAndCompare(multirelease, value, "README", prefix + "README"); + readAndCompare(multirelease, value, "version/Version.class", prefix + "version/Version.class"); + // and signed multi-release jars + readAndCompare(signedmultirelease, value, "README", prefix + "README"); + readAndCompare(signedmultirelease, value, "version/Version.class", prefix + "version/Version.class"); + } + } + + private void readAndCompare(File jar, Release version, String name, String realName) throws Exception { + byte[] baseBytes; + byte[] versionedBytes; + try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, Release.BASE)) { + ZipEntry ze = jf.getEntry(realName); + try (InputStream is = jf.getInputStream(ze)) { + baseBytes = is.readAllBytes(); + } + } + assert baseBytes.length > 0; + + try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, version)) { + ZipEntry ze = jf.getEntry(name); + try (InputStream is = jf.getInputStream(ze)) { + versionedBytes = is.readAllBytes(); + } + } + assert versionedBytes.length > 0; + + Assert.assertTrue(Arrays.equals(baseBytes, versionedBytes)); + } + + @Test + public void testNames() throws Exception { + String rname = "version/Version.class"; + String vname = "META-INF/versions/9/version/Version.class"; + ZipEntry ze1; + ZipEntry ze2; + try (JarFile jf = new JarFile(multirelease)) { + ze1 = jf.getEntry(vname); + } + Assert.assertEquals(ze1.getName(), vname); + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) { + ze2 = jf.getEntry(rname); + } + Assert.assertEquals(ze2.getName(), rname); + Assert.assertNotEquals(ze1.getName(), ze2.getName()); + } +} diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java new file mode 100644 index 00000000000..f80991d09d5 --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2015, 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 8132734 + * @summary Test the System properties for JarFile that support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + */ + +import com.sun.net.httpserver.*; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { + private SimpleHttpServer server; + + @BeforeClass + public void initialize() throws Exception { + server = new SimpleHttpServer(); + server.start(); + super.initialize(); + } + + @Override + protected void initializeClassLoader() throws Exception { + URL[] urls = new URL[]{ + new URL("http://localhost:" + server.getPort() + "/multi-release-jar") + }; + cldr = new URLClassLoader(urls); + // load any class, Main is convenient and in the root entries + rootClass = cldr.loadClass("version.Main"); + } + + @AfterClass + public void close() throws IOException { + // Windows requires server to stop before file is deleted + if (server != null) + server.stop(); + super.close(); + } + + /* + * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader + */ + + @Test + public void testURLClassLoader() throws Throwable { + Class vcls = cldr.loadClass("version.Version"); + invokeMethod(vcls, rtVersion); + } + + @Test + public void testGetResourceAsStream() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use rootClass as a base for getting resources + getResourceAsStream(rootClass, resource); + } + + @Test + public void testGetResource() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use rootClass as a base for getting resources + getResource(rootClass, resource); + } +} + +/** + * Extremely simple server that only performs one task. The server listens for + * requests on the ephemeral port. If it sees a request that begins with + * "/multi-release-jar", it consumes the request and returns a stream of bytes + * representing the jar file multi-release.jar found in "userdir". + */ +class SimpleHttpServer { + private static final String userdir = System.getProperty("user.dir", "."); + private static final Path multirelease = Paths.get(userdir, "multi-release.jar"); + + private final HttpServer server; + + public SimpleHttpServer() throws IOException { + server = HttpServer.create(); + } + + public void start() throws IOException { + server.bind(new InetSocketAddress(0), 0); + server.createContext("/multi-release-jar", t -> { + try (InputStream is = t.getRequestBody()) { + is.readAllBytes(); // probably not necessary to consume request + byte[] bytes = Files.readAllBytes(multirelease); + t.sendResponseHeaders(200, bytes.length); + try (OutputStream os = t.getResponseBody()) { + os.write(bytes); + } + } + }); + server.setExecutor(null); // creates a default executor + server.start(); + } + + public void stop() { + server.stop(0); + } + + int getPort() { + return server.getAddress().getPort(); + } +} + diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java new file mode 100644 index 00000000000..587bf6e5da1 --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2015, 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 8132734 + * @summary Test the extended API and the aliasing additions in JarFile that + * support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarIterators + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.stream.Collectors; +import java.util.zip.ZipFile; + +import static java.util.jar.JarFile.Release; +import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + + +public class MultiReleaseJarIterators { + String userdir = System.getProperty("user.dir", "."); + File unversioned = new File(userdir, "unversioned.jar"); + File multirelease = new File(userdir, "multi-release.jar"); + Map uvEntries = new HashMap<>(); + Map mrEntries = new HashMap<>(); + Map baseEntries = new HashMap<>(); + Map v9Entries = new HashMap<>(); + Map v10Entries = new HashMap<>(); + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildUnversionedJar(); + creator.buildMultiReleaseJar(); + + try (JarFile jf = new JarFile(multirelease)) { + for (Enumeration e = jf.entries(); e.hasMoreElements(); ) { + JarEntry je = e.nextElement(); + String name = je.getName(); + mrEntries.put(name, je); + if (name.startsWith("META-INF/versions/")) { + if (name.startsWith("META-INF/versions/9/")) { + v9Entries.put(name.substring(20), je); + } else if (name.startsWith("META-INF/versions/10/")) { + v10Entries.put(name.substring(21), je); + } + } else { + baseEntries.put(name, je); + } + } + } + Assert.assertEquals(mrEntries.size(), 14); + Assert.assertEquals(baseEntries.size(), 6); + Assert.assertEquals(v9Entries.size(), 5); + Assert.assertEquals(v10Entries.size(), 3); + + try (JarFile jf = new JarFile(unversioned)) { + jf.entries().asIterator().forEachRemaining(je -> uvEntries.put(je.getName(), je)); + } + Assert.assertEquals(uvEntries.size(), 6); + } + + @AfterClass + public void close() throws IOException { + Files.delete(unversioned.toPath()); + Files.delete(multirelease.toPath()); + } + + @Test + public void testMultiReleaseJar() throws IOException { + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ)) { + testEnumeration(jf, mrEntries); + testStream(jf, mrEntries); + } + + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.BASE)) { + testEnumeration(jf, baseEntries); + testStream(jf, baseEntries); + } + + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) { + testEnumeration(jf, v9Entries); + testStream(jf, v9Entries); + } + + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) { + Map expectedEntries; + switch (jdkMajorVersion()) { + case 9: + expectedEntries = v9Entries; + break; + case 10: // won't get here until JDK 10 + expectedEntries = v10Entries; + break; + default: + expectedEntries = baseEntries; + break; + } + + testEnumeration(jf, expectedEntries); + testStream(jf, expectedEntries); + } + } + + @Test + public void testUnversionedJar() throws IOException { + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.BASE)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.VERSION_9)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + } + + private void testEnumeration(JarFile jf, Map expectedEntries) { + Map actualEntries = new HashMap<>(); + for (Enumeration e = jf.entries(); e.hasMoreElements(); ) { + JarEntry je = e.nextElement(); + actualEntries.put(je.getName(), je); + } + + testEntries(jf, actualEntries, expectedEntries); + } + + + private void testStream(JarFile jf, Map expectedEntries) { + Map actualEntries = jf.stream().collect(Collectors.toMap(je -> je.getName(), je -> je)); + + testEntries(jf, actualEntries, expectedEntries); + } + + private void testEntries(JarFile jf, Map actualEntries, Map expectedEntries) { + /* For multi-release jar files constructed with a Release object, + * actualEntries contain versionedEntries that are considered part of the + * public API. They have a 1-1 correspondence with baseEntries, + * so entries that are not part of the public API won't be present, + * i.e. those entries with a name that starts with version/PackagePrivate + * in this particular jar file (multi-release.jar) + */ + + Map entries; + if (expectedEntries == mrEntries) { + Assert.assertEquals(actualEntries.size(), mrEntries.size()); + entries = mrEntries; + } else if (expectedEntries == uvEntries) { + Assert.assertEquals(actualEntries.size(), uvEntries.size()); + entries = uvEntries; + } else { + Assert.assertEquals(actualEntries.size(), baseEntries.size()); // this is correct + entries = baseEntries; + } + + entries.keySet().forEach(name -> { + JarEntry ee = expectedEntries.get(name); + if (ee == null) ee = entries.get(name); + JarEntry ae = actualEntries.get(name); + try { + compare(jf, ae, ee); + } catch (IOException x) { + throw new RuntimeException(x); + } + }); + } + + private void compare(JarFile jf, JarEntry actual, JarEntry expected) throws IOException { + byte[] abytes; + byte[] ebytes; + + try (InputStream is = jf.getInputStream(actual)) { + abytes = is.readAllBytes(); + } + + try (InputStream is = jf.getInputStream(expected)) { + ebytes = is.readAllBytes(); + } + + Assert.assertEquals(abytes, ebytes); + } +} diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java new file mode 100644 index 00000000000..978ba328be6 --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2015, 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 8132734 + * @summary Test the System properties for JarFile that support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarProperties { + final static int ROOTVERSION = 8; // magic number from knowledge of internals + final static String userdir = System.getProperty("user.dir", "."); + final static File multirelease = new File(userdir, "multi-release.jar"); + protected int rtVersion; + boolean force; + protected ClassLoader cldr; + protected Class rootClass; + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildMultiReleaseJar(); + + rtVersion = Integer.getInteger("jdk.util.jar.version", jdkMajorVersion()); + String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", ""); + if (mrprop.equals("false")) { + rtVersion = ROOTVERSION; + } else if (rtVersion < ROOTVERSION) { + rtVersion = ROOTVERSION; + } else if (rtVersion > jdkMajorVersion()) { + rtVersion = jdkMajorVersion(); + } + force = mrprop.equals("force"); + + initializeClassLoader(); + } + + protected void initializeClassLoader() throws Exception { + URL[] urls = new URL[]{multirelease.toURI().toURL()}; + cldr = new URLClassLoader(urls); + // load any class, Main is convenient and in the root entries + rootClass = cldr.loadClass("version.Main"); + } + + @AfterClass + public void close() throws IOException { + ((URLClassLoader)cldr).close(); + Files.delete(multirelease.toPath()); + } + + /* + * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader + */ + @Test + public void testURLClassLoader() throws Throwable { + Class vcls = cldr.loadClass("version.Version"); + invokeMethod(vcls, rtVersion); + } + + protected void invokeMethod(Class vcls, int expected) throws Throwable { + MethodType mt = MethodType.methodType(int.class); + MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt); + Assert.assertEquals(expected, (int) mh.invoke(vcls.newInstance())); + } + + /* + * jdk.util.jar.enableMultiRelease=force should affect a custom class loader + */ + @Test + public void testClassLoader() throws Throwable { + try (JarFile jf = new JarFile(multirelease)) { // do not set runtime versioning + ClassLoader cldr = new CustomClassLoader(jf); + Class vcls = cldr.loadClass("version.Version"); + if (rtVersion == 9) { + try { + cldr.loadClass("version.PackagePrivate"); + } catch (ClassNotFoundException x) { + if (force) throw x; + } + } + invokeMethod(vcls, force ? rtVersion : ROOTVERSION); + } + } + + private static class CustomClassLoader extends ClassLoader { + private final JarFile jf; + + CustomClassLoader(JarFile jf) throws Exception { + super(null); + this.jf = jf; + } + + protected Class findClass(String name) throws ClassNotFoundException { + try { + byte[] b; + String entryName = name.replace(".", "/") + ".class"; + JarEntry je = jf.getJarEntry(entryName); + if (je != null) { + try (InputStream is = jf.getInputStream(je)) { + b = new byte[(int) je.getSize()]; + is.read(b); + } + return defineClass(name, b, 0, b.length); + } + throw new ClassNotFoundException(name); + } catch (IOException x) { + throw new ClassNotFoundException(x.getMessage()); + } + } + } + + @Test + public void testGetResourceAsStream() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use fileRootClass as a base for getting resources + getResourceAsStream(rootClass, resource); + } + + protected void getResourceAsStream(Class rootClass, String resource) throws Exception { + try (InputStream is = rootClass.getResourceAsStream(resource)) { + byte[] bytes = is.readAllBytes(); + resource = new String(bytes); + } + String match = "return " + rtVersion + ";"; + Assert.assertTrue(resource.contains(match)); + } + + @Test + public void testGetResource() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use rootClass as a base for getting resources + getResource(rootClass, resource); + } + + protected void getResource(Class rootClass, String resource) throws Exception { + URL url = rootClass.getResource(resource); + try (InputStream is = url.openStream()) { + byte[] bytes = is.readAllBytes(); + resource = new String(bytes); + } + String match = "return " + rtVersion + ";"; + Assert.assertTrue(resource.contains(match)); + } +} diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java new file mode 100644 index 00000000000..6547c990b2a --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015, 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 8132734 + * @summary Test potential security related issues + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarSecurity + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.security.CodeSigner; +import java.security.cert.Certificate; +import java.util.Arrays; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarSecurity { + String userdir = System.getProperty("user.dir","."); + File multirelease = new File(userdir, "multi-release.jar"); + File signedmultirelease = new File(userdir, "signed-multi-release.jar"); + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildMultiReleaseJar(); + creator.buildSignedMultiReleaseJar(); + } + + @AfterClass + public void close() throws IOException { + Files.delete(multirelease.toPath()); + Files.delete(signedmultirelease.toPath()); + } + + @Test + public void testCertsAndSigners() throws IOException { + try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) { + int version = sun.misc.Version.jdkMajorVersion(); // fixme JEP 223 Version + CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class")); + CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + version + "/version/Version.class")); + Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates())); + Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners())); + } + } + + private static class CertsAndSigners { + final private JarFile jf; + final private JarEntry je; + private boolean readComplete; + + CertsAndSigners(JarFile jf, JarEntry je) { + this.jf = jf; + this.je = je; + } + + Certificate[] getCertificates() throws IOException { + readEntry(); + return je.getCertificates(); + } + + CodeSigner[] getCodeSigners() throws IOException { + readEntry(); + return je.getCodeSigners(); + } + + private void readEntry() throws IOException { + if (!readComplete) { + try (InputStream is = jf.getInputStream(je)) { + is.readAllBytes(); + } + readComplete = true; + } + } + } +} diff --git a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java new file mode 100644 index 00000000000..a500eb2e25c --- /dev/null +++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, 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 8132734 + * @summary Test that URL connections to multi-release jars can be runtime versioned + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarURLConnection + */ + +import java.io.IOException; +import java.io.InputStream; +import java.net.JarURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.jar.JarFile; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarURLConnection { + String userdir = System.getProperty("user.dir","."); + String urlFile = "jar:file:" + userdir + "/multi-release.jar!/"; + String urlEntry = urlFile + "version/Version.java"; + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildMultiReleaseJar(); + } + + @AfterClass + public void close() throws IOException { + Files.delete(Paths.get(userdir, "multi-release.jar")); + } + + @Test + public void testRuntimeVersioning() throws Exception { + Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); + // #runtime is "magic" + Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9")); + // #fragment or any other fragment is not magic + Assert.assertTrue(readAndCompare(new URL(urlEntry + "#fragment"), "return 8")); + // cached entities not affected + Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); + } + + @Test + public void testCachedJars() throws Exception { + URL rootUrl = new URL(urlFile); + JarURLConnection juc = (JarURLConnection)rootUrl.openConnection(); + JarFile rootJar = juc.getJarFile(); + JarFile.Release root = rootJar.getVersion(); + + URL runtimeUrl = new URL(urlFile + "#runtime"); + juc = (JarURLConnection)runtimeUrl.openConnection(); + JarFile runtimeJar = juc.getJarFile(); + JarFile.Release runtime = runtimeJar.getVersion(); + Assert.assertNotEquals(root, runtime); + + juc = (JarURLConnection)rootUrl.openConnection(); + JarFile jar = juc.getJarFile(); + Assert.assertEquals(jar.getVersion(), root); + Assert.assertEquals(jar, rootJar); + + juc = (JarURLConnection)runtimeUrl.openConnection(); + jar = juc.getJarFile(); + Assert.assertEquals(jar.getVersion(), runtime); + Assert.assertEquals(jar, runtimeJar); + + rootJar.close(); + runtimeJar.close(); + jar.close(); // probably not needed + } + + private boolean readAndCompare(URL url, String match) throws Exception { + boolean result; + // necessary to do it this way, instead of openStream(), so we can + // close underlying JarFile, otherwise windows can't delete the file + URLConnection conn = url.openConnection(); + try (InputStream is = conn.getInputStream()) { + byte[] bytes = is.readAllBytes(); + result = (new String(bytes)).contains(match); + } + if (conn instanceof JarURLConnection) { + ((JarURLConnection)conn).getJarFile().close(); + } + return result; + } +} From 6d0ef1b692d806a211da08cf09d9f20561b39c56 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 16 Feb 2016 21:58:49 -0500 Subject: [PATCH 016/311] 8146728: TestPrintGCDetailsVerbose is never run by jtreg Remove requirement for fastdebug, update logging option Reviewed-by: sjohanss, brutisso, dfazunen --- hotspot/test/TEST.ROOT | 4 ++-- hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index 57f0e0ae061..8dd7c84e9ee 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2016, 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 @@ -30,7 +30,7 @@ keys=cte_test jcmd nmt regression gc stress groups=TEST.groups [closed/TEST.groups] -requires.properties=sun.arch.data.model java.version +requires.properties=sun.arch.data.model # Tests using jtreg 4.1 b12 features requiredVersion=4.1 b12 diff --git a/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java b/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java index 8e138db694d..1a7501e0981 100644 --- a/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java +++ b/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -24,12 +24,11 @@ /* * @test TestPrintGCDetailsVerbose * @bug 8016740 - * @summary Tests that jvm with PrintGCDetails and Verbose flags do not crash when ParOldGC has no memory + * @summary Tests that jvm with maximally verbose GC logging does not crash when ParOldGC has no memory * @key gc - * @requires java.version ~= ".*fastdebug" * @requires vm.gc=="Parallel" | vm.gc=="null" * @library /testlibrary - * @run main/othervm -Xmx50m -XX:+UseParallelOldGC -XX:+PrintGCDetails -XX:+Verbose TestPrintGCDetailsVerbose + * @run main/othervm -Xmx50m -XX:+UseParallelGC -Xlog:gc*=trace TestPrintGCDetailsVerbose */ public class TestPrintGCDetailsVerbose { From a4d0bc4a4e5236ed9dca5dd43412b9e3308cfd44 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Wed, 17 Feb 2016 11:00:57 +0300 Subject: [PATCH 017/311] 8144578: TestOptionsWithRanges test only ever uses the default collector Reviewed-by: sangheki, dholmes --- .../TestOptionsWithRanges.java | 9 +++- .../common/optionsvalidation/JVMOption.java | 54 ++++++++++--------- .../optionsvalidation/JVMOptionsUtils.java | 37 ++++++++++--- .../common/optionsvalidation/JVMStartup.java | 51 ++++++++++++++++++ 4 files changed, 118 insertions(+), 33 deletions(-) create mode 100644 hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java index f762017bff2..24f7ad70a53 100644 --- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -83,6 +83,13 @@ public class TestOptionsWithRanges { setAllowedExitCodes("SharedMiscDataSize", 2); setAllowedExitCodes("SharedMiscCodeSize", 2); + /* + * JDK-8145204 + * Temporarily remove testing of max range for ParGCArrayScanChunk because + * JVM can hang when ParGCArrayScanChunk=4294967296 and ParallelGC is used + */ + excludeTestMaxRange("ParGCArrayScanChunk"); + /* * Remove CICompilerCount from testing because currently it can hang system */ diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java index d4d54669987..031d6a2cc64 100644 --- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -37,6 +37,7 @@ import jdk.test.lib.dcmd.JMXExecutor; import sun.tools.attach.HotSpotVirtualMachine; import static optionsvalidation.JVMOptionsUtils.failedMessage; +import static optionsvalidation.JVMOptionsUtils.GCType; import static optionsvalidation.JVMOptionsUtils.printOutputContent; import static optionsvalidation.JVMOptionsUtils.VMType; @@ -374,17 +375,21 @@ public abstract class JVMOption { private boolean runJavaWithParam(String optionValue, boolean valid) throws Exception { int exitCode; boolean result = true; - String value = optionValue.substring(optionValue.lastIndexOf("=") + 1); - String fullOptionString = prependString.toString() + optionValue; + String errorMessage = null; List runJava = new ArrayList<>(); OutputAnalyzer out; if (VMType != null) { runJava.add(VMType); } + + if (GCType != null) { + runJava.add(GCType); + } + runJava.addAll(prepend); runJava.add(optionValue); - runJava.add(JVMOptionsUtils.class.getName()); + runJava.add(JVMStartup.class.getName()); out = new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])).start()); @@ -392,40 +397,37 @@ public abstract class JVMOption { if (out.getOutput().contains("A fatal error has been detected by the Java Runtime Environment")) { /* Always consider "fatal error" in output as fail */ - failedMessage(name, fullOptionString, valid, "JVM output reports a fatal error. JVM exited with code " + exitCode + "!"); - printOutputContent(out); - result = false; + errorMessage = "JVM output reports a fatal error. JVM exited with code " + exitCode + "!"; } else if (valid == true) { if (!allowedExitCodes.contains(exitCode)) { - failedMessage(name, fullOptionString, valid, "JVM exited with unexpected error code = " + exitCode); - printOutputContent(out); - result = false; + errorMessage = "JVM exited with unexpected error code = " + exitCode; } else if ((exitCode != 0) && (out.getOutput().isEmpty() == true)) { - failedMessage(name, fullOptionString, valid, "JVM exited with error(exitcode == " + exitCode + - "), but with empty stdout and stderr. Description of error is needed!"); - result = false; + errorMessage = "JVM exited with error(exitcode == " + exitCode + "), but with empty stdout and stderr. " + + "Description of error is needed!"; } else if (out.getOutput().contains("is outside the allowed range")) { - failedMessage(name, fullOptionString, valid, "JVM output contains \"is outside the allowed range\""); - printOutputContent(out); - result = false; + errorMessage = "JVM output contains \"is outside the allowed range\""; } } else { // valid == false + String value = optionValue.substring(optionValue.lastIndexOf("=") + 1); + String errorMessageCommandLineValue = getErrorMessageCommandLine(value); if (exitCode == 0) { - failedMessage(name, fullOptionString, valid, "JVM successfully exit"); - result = false; + errorMessage = "JVM successfully exit"; } else if (exitCode != 1) { - failedMessage(name, fullOptionString, valid, "JVM exited with code " - + exitCode + " which not equal to 1"); - result = false; - } else if (!out.getOutput().contains(getErrorMessageCommandLine(value))) { - failedMessage(name, fullOptionString, valid, "JVM output does not contain " - + "expected output \"" + getErrorMessageCommandLine(value) + "\""); - printOutputContent(out); - result = false; + errorMessage = "JVM exited with code " + exitCode + " which not equal to 1"; + } else if (!out.getOutput().contains(errorMessageCommandLineValue)) { + errorMessage = "JVM output does not contain expected output \"" + errorMessageCommandLineValue + "\""; } } + if (errorMessage != null) { + String fullOptionString = String.format("%s %s %s %s", + VMType == null ? "" : VMType, GCType == null ? "" : GCType, prependString.toString(), optionValue).trim().replaceAll(" +", " "); + failedMessage(name, fullOptionString, valid, errorMessage); + printOutputContent(out); + result = false; + } + System.out.println(""); return result; diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java index 944b8d5964c..cfde0ee0e3d 100644 --- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -27,6 +27,8 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; @@ -50,6 +52,9 @@ public class JVMOptionsUtils { /* Used to start the JVM with the same type as current */ static String VMType; + /* Used to start the JVM with the same GC type as current */ + static String GCType; + private static Map optionsAsMap; static { @@ -64,6 +69,27 @@ public class JVMOptionsUtils { } else { VMType = null; } + + List gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans(); + + GCType = null; + + for (GarbageCollectorMXBean gcMxBean : gcMxBeans) { + switch (gcMxBean.getName()) { + case "ConcurrentMarkSweep": + GCType = "-XX:+UseConcMarkSweepGC"; + break; + case "MarkSweepCompact": + GCType = "-XX:+UseSerialGC"; + break; + case "PS Scavenge": + GCType = "-XX:+UseParallelGC"; + break; + case "G1 Old Generation": + GCType = "-XX:+UseG1GC"; + break; + } + } } public static boolean fitsRange(String optionName, BigDecimal number) throws Exception { @@ -443,6 +469,10 @@ public class JVMOptionsUtils { if (VMType != null) { runJava.add(VMType); } + + if (GCType != null) { + runJava.add(GCType); + } runJava.add(PRINT_FLAGS_RANGES); runJava.add("-version"); @@ -534,9 +564,4 @@ public class JVMOptionsUtils { public static Map getOptionsWithRangeAsMap(String... additionalArgs) throws Exception { return getOptionsWithRangeAsMap(origin -> true, additionalArgs); } - - /* Simple method to test that java start-up. Used for testing options. */ - public static void main(String[] args) { - System.out.print("Java start-up!"); - } } diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java new file mode 100644 index 00000000000..5b5d96e5576 --- /dev/null +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, 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 optionsvalidation; + +import java.lang.ref.WeakReference; + +class JVMStartup { + private static volatile WeakReference weakRef; + + private static synchronized void createWeakRef() { + Object o = new Object(); + weakRef = new WeakReference<>(o); + } + + /* Simple method to test that java start-up. Used for testing options. */ + public static void main(String[] args) throws Exception { + byte[] garbage = new byte[8192]; + int i = 0; + createWeakRef(); + do { + garbage = new byte[8192]; + i++; + /* Initiate GC after 5 iterations */ + if (i > 5) { + System.gc(); + } + } while(weakRef.get() != null); + System.out.println("Java start-up!"); + } +} From a81f4a10da20d493b639313cc0f6d0501d913a6b Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Wed, 17 Feb 2016 11:11:47 +0100 Subject: [PATCH 018/311] 8148219: Add decorator hostname to UL Reviewed-by: dholmes, mlarsson --- hotspot/src/os/posix/vm/os_posix.cpp | 4 +--- hotspot/src/os/windows/vm/os_windows.cpp | 2 -- .../src/share/vm/logging/logConfiguration.cpp | 5 ++--- hotspot/src/share/vm/logging/logDecorations.cpp | 17 ++++++++++++++++- hotspot/src/share/vm/logging/logDecorations.hpp | 9 ++++----- hotspot/src/share/vm/logging/logDecorators.hpp | 4 +++- hotspot/src/share/vm/runtime/os.hpp | 4 +++- 7 files changed, 29 insertions(+), 16 deletions(-) diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index 68ab843bf44..8cccda34d21 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -238,14 +238,12 @@ void os::Posix::print_uname_info(outputStream* st) { st->cr(); } -#ifndef PRODUCT bool os::get_host_name(char* buf, size_t buflen) { struct utsname name; uname(&name); jio_snprintf(buf, buflen, "%s", name.nodename); return true; } -#endif // PRODUCT bool os::has_allocatable_memory_limit(julong* limit) { struct rlimit rlim; diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 1df102a7607..19d7319e7e1 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1531,12 +1531,10 @@ int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *pa return result; } -#ifndef PRODUCT bool os::get_host_name(char* buf, size_t buflen) { DWORD size = (DWORD)buflen; return (GetComputerNameEx(ComputerNameDnsHostname, buf, &size) == TRUE); } -#endif // PRODUCT void os::get_summary_os_info(char* buf, size_t buflen) { stringStream sst(buf, buflen); diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index 2ff86004cce..2bdd8682f93 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -82,8 +82,7 @@ void LogConfiguration::post_initialize() { void LogConfiguration::initialize(jlong vm_start_time) { LogFileOutput::set_file_name_parameters(vm_start_time); - LogDecorations::set_vm_start_time_millis(vm_start_time); - + LogDecorations::initialize(vm_start_time); assert(_outputs == NULL, "Should not initialize _outputs before this function, initialize called twice?"); _outputs = NEW_C_HEAP_ARRAY(LogOutput*, 2, mtLogging); _outputs[0] = LogOutput::Stdout; diff --git a/hotspot/src/share/vm/logging/logDecorations.cpp b/hotspot/src/share/vm/logging/logDecorations.cpp index 3438b8ad734..210ab31313a 100644 --- a/hotspot/src/share/vm/logging/logDecorations.cpp +++ b/hotspot/src/share/vm/logging/logDecorations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -29,12 +29,21 @@ #include "services/management.hpp" jlong LogDecorations::_vm_start_time_millis = 0; +const char* LogDecorations::_host_name = ""; LogDecorations::LogDecorations(LogLevelType level, const LogTagSet &tagset, const LogDecorators &decorators) : _level(level), _tagset(tagset), _millis(-1) { create_decorations(decorators); } +void LogDecorations::initialize(jlong vm_start_time) { + char buffer[1024]; + if (os::get_host_name(buffer, sizeof(buffer))){ + _host_name = os::strdup_check_oom(buffer); + } + _vm_start_time_millis = vm_start_time; +} + void LogDecorations::create_decorations(const LogDecorators &decorators) { char* position = _decorations_buffer; #define DECORATOR(full_name, abbr) \ @@ -109,3 +118,9 @@ char* LogDecorations::create_tags_decoration(char* pos) { int written = _tagset.label(pos, DecorationsBufferSize - (pos - _decorations_buffer)); ASSERT_AND_RETURN(written, pos) } + +char* LogDecorations::create_hostname_decoration(char* pos) { + int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), "%s", _host_name); + ASSERT_AND_RETURN(written, pos) +} + diff --git a/hotspot/src/share/vm/logging/logDecorations.hpp b/hotspot/src/share/vm/logging/logDecorations.hpp index 08a675f225b..fcc166147e8 100644 --- a/hotspot/src/share/vm/logging/logDecorations.hpp +++ b/hotspot/src/share/vm/logging/logDecorations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -39,6 +39,7 @@ class LogDecorations VALUE_OBJ_CLASS_SPEC { LogTagSet _tagset; jlong _millis; static jlong _vm_start_time_millis; + static const char* _host_name; jlong java_millis(); void create_decorations(const LogDecorators& decorators); @@ -48,15 +49,13 @@ class LogDecorations VALUE_OBJ_CLASS_SPEC { #undef DECORATOR public: + static void initialize(jlong vm_start_time); + LogDecorations(LogLevelType level, const LogTagSet& tagset, const LogDecorators& decorators); const char* decoration(LogDecorators::Decorator decorator) const { return _decoration_offset[decorator]; } - - static void set_vm_start_time_millis(jlong start_time) { - _vm_start_time_millis = start_time; - } }; #endif // SHARE_VM_LOGGING_LOGDECORATIONS_HPP diff --git a/hotspot/src/share/vm/logging/logDecorators.hpp b/hotspot/src/share/vm/logging/logDecorators.hpp index 56a4778b034..1e52124060f 100644 --- a/hotspot/src/share/vm/logging/logDecorators.hpp +++ b/hotspot/src/share/vm/logging/logDecorators.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -34,6 +34,7 @@ // uptimemillis - Milliseconds since the JVM started // timenanos - The same value as generated by System.nanoTime() // uptimenanos - Nanoseconds since the JVM started +// hostname - The hostname // pid - The process identifier // tid - The thread identifier // level - The level associated with the log message @@ -45,6 +46,7 @@ DECORATOR(uptimemillis, um) \ DECORATOR(timenanos, tn) \ DECORATOR(uptimenanos, un) \ + DECORATOR(hostname, hn) \ DECORATOR(pid, p) \ DECORATOR(tid, ti) \ DECORATOR(level, l) \ diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 9668104ef5d..128c73c3194 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -152,7 +152,6 @@ class os: AllStatic { static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned); // Get summary strings for system information in buffer provided - static bool get_host_name(char* buf, size_t buflen) PRODUCT_RETURN_(return false;); // true if available static void get_summary_cpu_info(char* buf, size_t buflen); static void get_summary_os_info(char* buf, size_t buflen); @@ -595,6 +594,9 @@ class os: AllStatic { // Write to stream static int log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) ATTRIBUTE_PRINTF(3, 0); + // Get host name in buffer provided + static bool get_host_name(char* buf, size_t buflen); + // Print out system information; they are called by fatal error handler. // Output format may be different on different platforms. static void print_os_info(outputStream* st); From c867b023b670ef369a0447f454c30cca363f8f4d Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Tue, 16 Feb 2016 13:20:38 -0800 Subject: [PATCH 019/311] 8149643: Remove check of counters in VirtualSpaceNode::inc_container_count Reviewed-by: brutisso, kbarrett, mgerdin --- hotspot/src/share/vm/memory/metaspace.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index 72ec52da3d1..199702e083e 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -791,7 +791,6 @@ Mutex* const SpaceManager::_expand_lock = void VirtualSpaceNode::inc_container_count() { assert_lock_strong(SpaceManager::expand_lock()); _container_count++; - DEBUG_ONLY(verify_container_count();) } void VirtualSpaceNode::dec_container_count() { @@ -1073,6 +1072,7 @@ void VirtualSpaceList::purge(ChunkManager* chunk_manager) { VirtualSpaceNode* next_vsl = prev_vsl; while (next_vsl != NULL) { VirtualSpaceNode* vsl = next_vsl; + DEBUG_ONLY(vsl->verify_container_count();) next_vsl = vsl->next(); // Don't free the current virtual space since it will likely // be needed soon. @@ -1137,19 +1137,19 @@ void VirtualSpaceList::retire_current_virtual_space() { } void VirtualSpaceNode::retire(ChunkManager* chunk_manager) { + DEBUG_ONLY(verify_container_count();) for (int i = (int)MediumIndex; i >= (int)ZeroIndex; --i) { ChunkIndex index = (ChunkIndex)i; size_t chunk_size = chunk_manager->free_chunks(index)->size(); while (free_words_in_vs() >= chunk_size) { - DEBUG_ONLY(verify_container_count();) Metachunk* chunk = get_chunk_vs(chunk_size); assert(chunk != NULL, "allocation should have been successful"); chunk_manager->return_chunks(index, chunk); chunk_manager->inc_free_chunks_total(chunk_size); - DEBUG_ONLY(verify_container_count();) } + DEBUG_ONLY(verify_container_count();) } assert(free_words_in_vs() == 0, "should be empty now"); } From 58fe974cb716c70be3a7f304d582546141b6e0f1 Mon Sep 17 00:00:00 2001 From: Peter Brunet Date: Tue, 16 Feb 2016 19:38:26 -0600 Subject: [PATCH 020/311] 8149161: CSM call Class.forName in com.sun.java.accessibility.util.Translator Add call to checkPackageAccess Reviewed-by: serb, prr --- .../com/sun/java/accessibility/util/Translator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java index 177fbb4403c..224b5375283 100644 --- a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java +++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java @@ -32,6 +32,7 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; +import java.security.AccessControlException; // Do not import Swing classes. This module is intended to work // with both Swing and AWT. // import javax.swing.*; @@ -77,7 +78,7 @@ public class Translator extends AccessibleContext return null; } try { - t = Class.forName("com.sun.java.accessibility.util.internal" + t = Class.forName("com.sun.java.accessibility.util.internal." + c.getSimpleName() + "Translator"); return t; @@ -105,6 +106,10 @@ public class Translator extends AccessibleContext if (o instanceof Accessible) { a = (Accessible)o; } else { + // About to "newInstance" an object of a class of a restricted package + // so ensure the caller is allowed access to that package. + String pkg = "com.sun.java.accessibility.util.internal"; + System.getSecurityManager().checkPackageAccess(pkg); Class translatorClass = getTranslatorClass(o.getClass()); if (translatorClass != null) { try { From 8372c1c09a468d5c09ff115873c15721a22d2197 Mon Sep 17 00:00:00 2001 From: Avik Niyogi Date: Wed, 17 Feb 2016 11:44:07 +0530 Subject: [PATCH 021/311] 8146321: [macosx] JInternalFrame frame icon in wrong position on Mac L&F if icon is not ImageIcon Reviewed-by: serb, alexsch, rchamyal --- .../apple/laf/AquaInternalFrameBorder.java | 49 +++- .../8146321/JInternalFrameIconTest.java | 275 ++++++++++++++++++ 2 files changed, 309 insertions(+), 15 deletions(-) create mode 100644 jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java index ef5ca43cf23..4a72d0fd371 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java @@ -40,6 +40,7 @@ import apple.laf.JRSUIState.TitleBarHeightState; import com.apple.laf.AquaUtils.RecyclableSingleton; import com.apple.laf.AquaInternalFrameBorderMetrics; +import java.awt.geom.AffineTransform; public class AquaInternalFrameBorder implements Border, UIResource { private static final int kCloseButton = 0; @@ -309,18 +310,40 @@ public class AquaInternalFrameBorder implements Border, UIResource { return isInsideYButtonArea(i, y) && x >= startX && x <= endX; } - protected void paintTitleIcon(final Graphics g, final JInternalFrame frame, final int x, final int y) { - Icon icon = frame.getFrameIcon(); - if (icon == null) icon = UIManager.getIcon("InternalFrame.icon"); - if (icon == null) return; + protected void paintTitleIcon(final Graphics g, final JInternalFrame frame, + final int x, final int y) { - // Resize to 16x16 if necessary. - if (icon instanceof ImageIcon && (icon.getIconWidth() > sMaxIconWidth || icon.getIconHeight() > sMaxIconHeight)) { - final Image img = ((ImageIcon)icon).getImage(); - ((ImageIcon)icon).setImage(img.getScaledInstance(sMaxIconWidth, sMaxIconHeight, Image.SCALE_SMOOTH)); + Icon icon = frame.getFrameIcon(); + if (icon == null) { + icon = UIManager.getIcon("InternalFrame.icon"); } - icon.paintIcon(frame, g, x, y); + if (icon == null) { + return; + } + + if (icon.getIconWidth() > sMaxIconWidth + || icon.getIconHeight() > sMaxIconHeight) { + final Graphics2D g2 = (Graphics2D) g; + final AffineTransform savedAT = g2.getTransform(); + double xScaleFactor = (double) sMaxIconWidth / icon.getIconWidth(); + double yScaleFactor = (double) sMaxIconHeight / icon.getIconHeight(); + + //Coordinates are after a translation hence relative origin shifts + g2.translate(x, y); + + //scaling factor is needed to scale while maintaining aspect ratio + double scaleMaintainAspectRatio = Math.min(xScaleFactor, yScaleFactor); + + //minimum value is taken to set to a maximum Icon Dimension + g2.scale(scaleMaintainAspectRatio, scaleMaintainAspectRatio); + + icon.paintIcon(frame, g2, 0, 0); + g2.setTransform(savedAT); + + } else { + icon.paintIcon(frame, g, x, y); + } } protected int getIconWidth(final JInternalFrame frame) { @@ -330,9 +353,7 @@ public class AquaInternalFrameBorder implements Border, UIResource { if (icon == null) { icon = UIManager.getIcon("InternalFrame.icon"); } - - if (icon != null && icon instanceof ImageIcon) { - // Resize to 16x16 if necessary. + if (icon != null) { width = Math.min(icon.getIconWidth(), sMaxIconWidth); } @@ -346,9 +367,7 @@ public class AquaInternalFrameBorder implements Border, UIResource { if (icon == null) { icon = UIManager.getIcon("InternalFrame.icon"); } - - if (icon != null && icon instanceof ImageIcon) { - // Resize to 16x16 if necessary. + if (icon != null) { height = Math.min(icon.getIconHeight(), sMaxIconHeight); } diff --git a/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java b/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java new file mode 100644 index 00000000000..4ff95c5bc30 --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2015, 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 8146321 + * @summary verifies JInternalFrame Icon and ImageIcon + * @library ../../regtesthelpers + * @build Util + * @run main JInternalFrameIconTest + */ +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class JInternalFrameIconTest { + + private static JFrame frame; + private static JDesktopPane desktopPane; + private static JInternalFrame internalFrame; + private static ImageIcon titleImageIcon; + private static Icon titleIcon; + private static BufferedImage imageIconImage; + private static BufferedImage iconImage; + + private static Robot robot; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.delay(2000); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + executeCase(lookAndFeelItem.getClassName()); + } + + } + + private static void executeCase(String lookAndFeelString) throws Exception { + if (tryLookAndFeel(lookAndFeelString)) { + createImageIconUI(lookAndFeelString); + robot.delay(1000); + getImageIconBufferedImage(); + robot.waitForIdle(); + cleanUp(); + robot.waitForIdle(); + + createIconUI(lookAndFeelString); + robot.delay(1000); + getIconBufferedImage(); + robot.waitForIdle(); + cleanUp(); + robot.waitForIdle(); + testIfSame(); + robot.waitForIdle(); + } + + } + + private static void createImageIconUI(final String lookAndFeelString) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + desktopPane = new JDesktopPane(); + internalFrame = new JInternalFrame(); + frame = new JFrame(); + internalFrame.setTitle(lookAndFeelString); + titleImageIcon = new ImageIcon() { + @Override + public int getIconWidth() { + return 16; + } + + @Override + public int getIconHeight() { + return 16; + } + + @Override + public void paintIcon( + Component c, Graphics g, int x, int y) { + g.setColor(java.awt.Color.black); + g.fillRect(x, y, 16, 16); + } + }; + internalFrame.setFrameIcon(titleImageIcon); + internalFrame.setSize(500, 200); + internalFrame.setVisible(true); + desktopPane.add(internalFrame); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(desktopPane, "Center"); + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); + } + }); + } + + private static void createIconUI(final String lookAndFeelString) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + desktopPane = new JDesktopPane(); + internalFrame = new JInternalFrame(); + frame = new JFrame(); + internalFrame.setTitle(lookAndFeelString); + titleIcon = new Icon() { + @Override + public int getIconWidth() { + return 16; + } + + @Override + public int getIconHeight() { + return 16; + } + + @Override + public void paintIcon( + Component c, Graphics g, int x, int y) { + g.setColor(java.awt.Color.black); + g.fillRect(x, y, 16, 16); + } + }; + internalFrame.setFrameIcon(titleIcon); + internalFrame.setSize(500, 200); + internalFrame.setVisible(true); + desktopPane.add(internalFrame); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(desktopPane, "Center"); + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); + } + }); + } + + private static void getImageIconBufferedImage() throws Exception { + Point point = internalFrame.getLocationOnScreen(); + Rectangle rect = internalFrame.getBounds(); + Rectangle captureRect = new Rectangle( + point.x + internalFrame.getInsets().left, + point.y, + rect.width, + internalFrame.getInsets().top); + imageIconImage + = robot.createScreenCapture(captureRect); + } + + private static void getIconBufferedImage() throws Exception { + Point point = internalFrame.getLocationOnScreen(); + Rectangle rect = internalFrame.getBounds(); + Rectangle captureRect = new Rectangle( + point.x + internalFrame.getInsets().left, + point.y, + rect.width, + internalFrame.getInsets().top); + iconImage + = robot.createScreenCapture(captureRect); + } + + private static void testIfSame() throws Exception { + if (!bufferedImagesEqual(imageIconImage, iconImage)) { + System.err.println("ERROR: icon and imageIcon not same."); + } else { + System.out.println("SUCCESS: icon and imageIcon same."); + } + } + + private static boolean bufferedImagesEqual( + BufferedImage bufferedImage1, BufferedImage bufferedImage2) { + boolean flag = true; + + if (bufferedImage1.getWidth() == bufferedImage2.getWidth() + && bufferedImage1.getHeight() == bufferedImage2.getHeight()) { + final int colorTolerance = 25; + final int mismatchTolerance = (int) (0.1 + * bufferedImage1.getWidth() * bufferedImage1.getHeight()); + int mismatchCounter = 0; + for (int x = 0; x < bufferedImage1.getWidth(); x++) { + for (int y = 0; y < bufferedImage1.getHeight(); y++) { + + int color1 = bufferedImage1.getRGB(x, y); + int red1 = (color1 >> 16) & 0x000000FF; + int green1 = (color1 >> 8) & 0x000000FF; + int blue1 = (color1) & 0x000000FF; + + int color2 = bufferedImage2.getRGB(x, y); + int red2 = (color2 >> 16) & 0x000000FF; + int green2 = (color2 >> 8) & 0x000000FF; + int blue2 = (color2) & 0x000000FF; + if (red1 != red2 || green1 != green2 || blue1 != blue2) { + ++mismatchCounter; + if ((Math.abs(red1 - red2) > colorTolerance) + || (Math.abs(green1 - green2) > colorTolerance) + || (Math.abs(blue1 - blue2) > colorTolerance)) { + + flag = false; + } + } + } + } + if (mismatchCounter > mismatchTolerance) { + flag = false; + } + } else { + System.err.println("ERROR: size is different"); + flag = false; + } + return flag; + } + + private static void cleanUp() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + + private static boolean tryLookAndFeel(String lookAndFeelString) + throws Exception { + try { + UIManager.setLookAndFeel( + lookAndFeelString); + + } catch (UnsupportedLookAndFeelException + | ClassNotFoundException + | InstantiationException + | IllegalAccessException e) { + return false; + } + return true; + } +} From 88575c5de777893560d39060bc5e65725b2f1487 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Wed, 24 Feb 2016 09:22:45 -0800 Subject: [PATCH 022/311] 8150561: [AArch64] JVMCI improvements Reviewed-by: kvn --- hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp | 2 +- hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp | 7 +++++++ .../src/jdk/vm/ci/hotspot/HotSpotVMConfig.java | 7 ++----- hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp | 8 ++++++++ hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp | 8 ++++++++ hotspot/src/share/vm/runtime/frame.cpp | 4 ++-- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp index 3e65f538de5..b302548557b 100644 --- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp @@ -74,7 +74,7 @@ void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, T void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) { address pc = _instructions->start() + pc_offset; NativeInstruction* inst = nativeInstruction_at(pc); - if (inst->is_adr_aligned()) { + if (inst->is_adr_aligned() || inst->is_ldr_literal()) { address dest = _constants->start() + data_offset; _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS)); TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset); diff --git a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp index 72c3479659c..d83017c1770 100644 --- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp @@ -105,13 +105,20 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { inline friend NativeInstruction* nativeInstruction_at(address address); static bool is_adrp_at(address instr); + static bool is_ldr_literal_at(address instr); + + bool is_ldr_literal() { + return is_ldr_literal_at(addr_at(0)); + } + static bool is_ldrw_to_zr(address instr); static bool is_call_at(address instr) { const uint32_t insn = (*(uint32_t*)instr); return (insn >> 26) == 0b100101; } + bool is_call() { return is_call_at(addr_at(0)); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 3e90a4d73b0..88da9e5b32a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -1141,7 +1141,7 @@ public class HotSpotVMConfig { @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_sp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaSpOffset; @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_pc", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaPcOffset; - @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset; + @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"aarch64, amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset; @HotSpotVMField(name = "JavaFrameAnchor::_flags", type = "int", get = HotSpotVMField.Type.OFFSET, archs = {"sparc"}) @Stable private int javaFrameAnchorFlagsOffset; public int threadLastJavaSpOffset() { @@ -1152,11 +1152,8 @@ public class HotSpotVMConfig { return javaThreadAnchorOffset + javaFrameAnchorLastJavaPcOffset; } - /** - * This value is only valid on AMD64. - */ public int threadLastJavaFpOffset() { - // TODO add an assert for AMD64 + assert getHostArchitectureName().equals("aarch64") || getHostArchitectureName().equals("amd64"); return javaThreadAnchorOffset + javaFrameAnchorLastJavaFpOffset; } diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp index cb06c34d4b6..2043b59d5e1 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp @@ -551,6 +551,14 @@ JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Hand compiler, _debug_recorder, _dependencies, env, id, has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log); cb = nm; + if (nm != NULL && env == NULL) { + DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler); + bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption; + if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) { + nm->print_nmethod(printnmethods); + } + DirectivesStack::release(directive); + } } if (cb != NULL) { diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp index 9456f34a0eb..99a7fbd3ac9 100644 --- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp +++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp @@ -592,6 +592,14 @@ #endif // TARGET_OS_FAMILY_bsd +#ifdef TARGET_ARCH_aarch64 + +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ + volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) + +#endif // TARGET_ARCH_aarch64 + + #ifdef TARGET_ARCH_x86 #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 3abf884cfbb..1a72cec46a8 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -662,14 +662,14 @@ void frame::print_on_error(outputStream* st, char* buf, int buflen, bool verbose st->print("J %d%s %s ", nm->compile_id(), (nm->is_osr_method() ? "%" : ""), ((nm->compiler() != NULL) ? nm->compiler()->name() : "")); + st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]", + buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin()); #if INCLUDE_JVMCI char* jvmciName = nm->jvmci_installed_code_name(buf, buflen); if (jvmciName != NULL) { st->print(" (%s)", jvmciName); } #endif - st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]", - buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin()); } else { st->print("J " PTR_FORMAT, p2i(pc())); } From abebc2da5c26b42098d9bd95d9a7d790916183ab Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 26 Feb 2016 01:58:26 +0300 Subject: [PATCH 023/311] 8150186: Folding mismatched accesses with @Stable is incorrect Reviewed-by: kvn, jrose, shade --- hotspot/src/share/vm/ci/ciArray.cpp | 3 +- hotspot/src/share/vm/opto/memnode.cpp | 14 +++- .../unsafe/UnsafeGetStableArrayElement.java | 68 +++++++++++++++++++ 3 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java diff --git a/hotspot/src/share/vm/ci/ciArray.cpp b/hotspot/src/share/vm/ci/ciArray.cpp index f527d3ed538..04a6db8df3f 100644 --- a/hotspot/src/share/vm/ci/ciArray.cpp +++ b/hotspot/src/share/vm/ci/ciArray.cpp @@ -107,8 +107,9 @@ ciConstant ciArray::element_value_by_offset(intptr_t element_offset) { intptr_t header = arrayOopDesc::base_offset_in_bytes(elembt); intptr_t index = (element_offset - header) >> shift; intptr_t offset = header + ((intptr_t)index << shift); - if (offset != element_offset || index != (jint)index) + if (offset != element_offset || index != (jint)index || index < 0 || index >= length()) { return ciConstant(); + } return element_value((jint) index); } diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 75a699349f8..55ca4581485 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -1582,6 +1582,15 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls, return NULL; } +static bool is_mismatched_access(ciConstant con, BasicType loadbt) { + BasicType conbt = con.basic_type(); + assert(conbt != T_NARROWOOP, "sanity"); + if (loadbt == T_NARROWOOP || loadbt == T_ARRAY) { + loadbt = T_OBJECT; + } + return (conbt != loadbt); +} + // Try to constant-fold a stable array element. static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) { assert(ary->const_oop(), "array should be constant"); @@ -1590,8 +1599,7 @@ static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicTyp // Decode the results of GraphKit::array_element_address. ciArray* aobj = ary->const_oop()->as_array(); ciConstant con = aobj->element_value_by_offset(off); - - if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) { + if (con.basic_type() != T_ILLEGAL && !is_mismatched_access(con, loadbt) && !con.is_null_or_zero()) { const Type* con_type = Type::make_from_constant(con); if (con_type != NULL) { if (con_type->isa_aryptr()) { @@ -1642,7 +1650,7 @@ const Type* LoadNode::Value(PhaseGVN* phase) const { const bool off_beyond_header = ((uint)off >= (uint)min_base_off); // Try to constant-fold a stable array element. - if (FoldStableValues && ary->is_stable() && ary->const_oop() != NULL) { + if (FoldStableValues && !is_mismatched_access() && ary->is_stable() && ary->const_oop() != NULL) { // Make sure the reference is not into the header and the offset is constant if (off_beyond_header && adr->is_AddP() && off != Type::OffsetBot) { const Type* con_type = fold_stable_ary_elem(ary, off, memory_type()); diff --git a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java new file mode 100644 index 00000000000..afdb1a6e7a3 --- /dev/null +++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, 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. + */ + +/* + * @test + * @summary tests on constant folding of unsafe get operations + * @library /testlibrary /test/lib + * + * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions + * -Xbatch -XX:-TieredCompilation + * -XX:+FoldStableValues + * UnsafeGetStableArrayElement + * + * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions + * -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * UnsafeGetStableArrayElement + */ +import jdk.internal.misc.Unsafe; +import jdk.internal.vm.annotation.Stable; +import java.util.concurrent.Callable; + +import static jdk.internal.misc.Unsafe.*; +import static jdk.test.lib.Asserts.*; + +public class UnsafeGetStableArrayElement { + @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[] { 0, 1, -128, 127}; + + static final Unsafe U = Unsafe.getUnsafe(); + + static int testChar() { + return U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 0 * ARRAY_CHAR_INDEX_SCALE) + + U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 1 * ARRAY_CHAR_INDEX_SCALE); + } + + static void run(Callable c) throws Exception { + Object first = c.call(); + for (int i = 0; i < 20_000; i++) { + assertEQ(first, c.call()); + } + } + + public static void main(String[] args) throws Exception { + run(UnsafeGetStableArrayElement::testChar); + } +} From a7d78599d772bff1a3b24c179370a55bec9a1f63 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 26 Feb 2016 01:58:29 +0300 Subject: [PATCH 024/311] 8150436: Incorrect invocation mode when linkToInteface linker is eliminated Reviewed-by: kvn, shade --- .../src/share/vm/runtime/sharedRuntime.cpp | 19 +++++++++++++------ .../jsr292/NonInlinedCall/InvokeTest.java | 5 ++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 5b862a01fab..4adec0c45ca 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1134,12 +1134,19 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, MethodHandles::is_signature_polymorphic_intrinsic(id)) { bc = MethodHandles::signature_polymorphic_intrinsic_bytecode(id); - // Need to adjust invokehandle since inlining through signature-polymorphic - // method happened. - if (bc == Bytecodes::_invokehandle && - !MethodHandles::is_signature_polymorphic_method(attached_method())) { - bc = attached_method->is_static() ? Bytecodes::_invokestatic - : Bytecodes::_invokevirtual; + // Adjust invocation mode according to the attached method. + switch (bc) { + case Bytecodes::_invokeinterface: + if (!attached_method->method_holder()->is_interface()) { + bc = Bytecodes::_invokevirtual; + } + break; + case Bytecodes::_invokehandle: + if (!MethodHandles::is_signature_polymorphic_method(attached_method())) { + bc = attached_method->is_static() ? Bytecodes::_invokestatic + : Bytecodes::_invokevirtual; + } + break; } } } else { diff --git a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java index 02bdef91a10..90724b371a8 100644 --- a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java +++ b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java @@ -180,7 +180,10 @@ public class InvokeTest { static void testInterface() { System.out.println("linkToInterface"); - // Monomorphic case (optimized virtual call) + // Monomorphic case (optimized virtual call), concrete target method + run(() -> linkToInterface(new P1(), P1.class)); + + // Monomorphic case (optimized virtual call), default target method run(() -> linkToInterface(new T(), I.class)); // Megamorphic case (virtual call) From 782e6b33f2d63d73b14021f46fb36fdc218abed5 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 26 Feb 2016 15:54:55 +0300 Subject: [PATCH 025/311] 8068038: C2: large constant offsets aren't handled on SPARC Reviewed-by: kvn --- hotspot/src/cpu/sparc/vm/sparc.ad | 368 ++++++++++++++---------------- 1 file changed, 175 insertions(+), 193 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 6bbef4e5708..5cf884a5501 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -948,28 +948,28 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, PhaseRegAlloc* ra, const MachNode* n, } #endif - uint instr; - instr = (Assembler::ldst_op << 30) - | (dst_enc << 25) - | (primary << 19) - | (src1_enc << 14); + uint instr = (Assembler::ldst_op << 30) + | (dst_enc << 25) + | (primary << 19) + | (src1_enc << 14); uint index = src2_enc; int disp = disp32; if (src1_enc == R_SP_enc || src1_enc == R_FP_enc) { disp += STACK_BIAS; - // Quick fix for JDK-8029668: check that stack offset fits, bailout if not + // Check that stack offset fits, load into O7 if not if (!Assembler::is_simm13(disp)) { - ra->C->record_method_not_compilable("unable to handle large constant offsets"); - return; + MacroAssembler _masm(&cbuf); + __ set(disp, O7); + if (index != R_G0_enc) { + __ add(O7, reg_to_register_object(index), O7); + } + index = R_O7_enc; + disp = 0; } } - // We should have a compiler bailout here rather than a guarantee. - // Better yet would be some mechanism to handle variable-size matches correctly. - guarantee(Assembler::is_simm13(disp), "Do not match large constant offsets" ); - if( disp == 0 ) { // use reg-reg form // bit 13 is already zero @@ -983,7 +983,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, PhaseRegAlloc* ra, const MachNode* n, cbuf.insts()->emit_int32(instr); #ifdef ASSERT - { + if (VerifyOops) { MacroAssembler _masm(&cbuf); if (is_verified_oop_base) { __ verify_oop(reg_to_register_object(src1_enc)); @@ -1342,7 +1342,7 @@ int MachEpilogNode::safepoint_offset() const { // Figure out which register class each belongs in: rc_int, rc_float, rc_stack enum RC { rc_bad, rc_int, rc_float, rc_stack }; static enum RC rc_class( OptoReg::Name reg ) { - if( !OptoReg::is_valid(reg) ) return rc_bad; + if (!OptoReg::is_valid(reg)) return rc_bad; if (OptoReg::is_stack(reg)) return rc_stack; VMReg r = OptoReg::as_VMReg(reg); if (r->is_Register()) return rc_int; @@ -1350,66 +1350,79 @@ static enum RC rc_class( OptoReg::Name reg ) { return rc_float; } -static int impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size, outputStream* st ) { +#ifndef PRODUCT +ATTRIBUTE_PRINTF(2, 3) +static void print_helper(outputStream* st, const char* format, ...) { + if (st->position() > 0) { + st->cr(); + st->sp(); + } + va_list ap; + va_start(ap, format); + st->vprint(format, ap); + va_end(ap); +} +#endif // !PRODUCT + +static void impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool is_load, int offset, int reg, int opcode, const char *op_str, outputStream* st) { if (cbuf) { emit_form3_mem_reg(*cbuf, ra, mach, opcode, -1, R_SP_enc, offset, 0, Matcher::_regEncode[reg]); } #ifndef PRODUCT - else if (!do_size) { - if (size != 0) st->print("\n\t"); - if (is_load) st->print("%s [R_SP + #%d],R_%s\t! spill",op_str,offset,OptoReg::regname(reg)); - else st->print("%s R_%s,[R_SP + #%d]\t! spill",op_str,OptoReg::regname(reg),offset); + else { + if (is_load) { + print_helper(st, "%s [R_SP + #%d],R_%s\t! spill", op_str, offset, OptoReg::regname(reg)); + } else { + print_helper(st, "%s R_%s,[R_SP + #%d]\t! spill", op_str, OptoReg::regname(reg), offset); + } } #endif - return size+4; } -static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int op1, int op2, const char *op_str, int size, outputStream* st ) { - if( cbuf ) emit3( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src] ); +static void impl_mov_helper(CodeBuffer *cbuf, int src, int dst, int op1, int op2, const char *op_str, outputStream* st) { + if (cbuf) { + emit3(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src]); + } #ifndef PRODUCT - else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("%s R_%s,R_%s\t! spill",op_str,OptoReg::regname(src),OptoReg::regname(dst)); + else { + print_helper(st, "%s R_%s,R_%s\t! spill", op_str, OptoReg::regname(src), OptoReg::regname(dst)); } #endif - return size+4; } -uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, - PhaseRegAlloc *ra_, - bool do_size, - outputStream* st ) const { +static void mach_spill_copy_implementation_helper(const MachNode* mach, + CodeBuffer *cbuf, + PhaseRegAlloc *ra_, + outputStream* st) { // Get registers to move - OptoReg::Name src_second = ra_->get_reg_second(in(1)); - OptoReg::Name src_first = ra_->get_reg_first(in(1)); - OptoReg::Name dst_second = ra_->get_reg_second(this ); - OptoReg::Name dst_first = ra_->get_reg_first(this ); + OptoReg::Name src_second = ra_->get_reg_second(mach->in(1)); + OptoReg::Name src_first = ra_->get_reg_first(mach->in(1)); + OptoReg::Name dst_second = ra_->get_reg_second(mach); + OptoReg::Name dst_first = ra_->get_reg_first(mach); enum RC src_second_rc = rc_class(src_second); - enum RC src_first_rc = rc_class(src_first); + enum RC src_first_rc = rc_class(src_first); enum RC dst_second_rc = rc_class(dst_second); - enum RC dst_first_rc = rc_class(dst_first); + enum RC dst_first_rc = rc_class(dst_first); - assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" ); + assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register"); - // Generate spill code! - int size = 0; - - if( src_first == dst_first && src_second == dst_second ) - return size; // Self copy, no move + if (src_first == dst_first && src_second == dst_second) { + return; // Self copy, no move + } // -------------------------------------- // Check for mem-mem move. Load into unused float registers and fall into // the float-store case. - if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) { + if (src_first_rc == rc_stack && dst_first_rc == rc_stack) { int offset = ra_->reg2offset(src_first); // Further check for aligned-adjacent pair, so we can use a double load - if( (src_first&1)==0 && src_first+1 == src_second ) { + if ((src_first&1) == 0 && src_first+1 == src_second) { src_second = OptoReg::Name(R_F31_num); src_second_rc = rc_float; - size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::lddf_op3,"LDDF",size, st); + impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::lddf_op3, "LDDF", st); } else { - size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::ldf_op3 ,"LDF ",size, st); + impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::ldf_op3, "LDF ", st); } src_first = OptoReg::Name(R_F30_num); src_first_rc = rc_float; @@ -1417,7 +1430,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) { int offset = ra_->reg2offset(src_second); - size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F31_num,Assembler::ldf_op3,"LDF ",size, st); + impl_helper(mach, cbuf, ra_, true, offset, R_F31_num, Assembler::ldf_op3, "LDF ", st); src_second = OptoReg::Name(R_F31_num); src_second_rc = rc_float; } @@ -1427,36 +1440,38 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS < 3) { int offset = frame::register_save_words*wordSize; if (cbuf) { - emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16 ); - impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); - impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); - emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16 ); + emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16); + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st); + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st); + emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16); } #ifndef PRODUCT - else if (!do_size) { - if (size != 0) st->print("\n\t"); - st->print( "SUB R_SP,16,R_SP\n"); - impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); - impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); - st->print("\tADD R_SP,16,R_SP\n"); + else { + print_helper(st, "SUB R_SP,16,R_SP"); + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st); + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st); + print_helper(st, "ADD R_SP,16,R_SP"); } #endif - size += 16; } // Check for float->int copy on T4 if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS >= 3) { // Further check for aligned-adjacent pair, so we can use a double move - if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) - return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mdtox_opf,"MOVDTOX",size, st); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mstouw_opf,"MOVSTOUW",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mdtox_opf, "MOVDTOX", st); + return; + } + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mstouw_opf, "MOVSTOUW", st); } // Check for int->float copy on T4 if (src_first_rc == rc_int && dst_first_rc == rc_float && UseVIS >= 3) { // Further check for aligned-adjacent pair, so we can use a double move - if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) - return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mxtod_opf,"MOVXTOD",size, st); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mwtos_opf,"MOVWTOS",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mxtod_opf, "MOVXTOD", st); + return; + } + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mwtos_opf, "MOVWTOS", st); } // -------------------------------------- @@ -1466,10 +1481,10 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, // there. Misaligned sources only come from native-long-returns (handled // special below). #ifndef _LP64 - if( src_first_rc == rc_int && // source is already big-endian + if (src_first_rc == rc_int && // source is already big-endian src_second_rc != rc_bad && // 64-bit move - ((dst_first&1)!=0 || dst_second != dst_first+1) ) { // misaligned dst - assert( (src_first&1)==0 && src_second == src_first+1, "source must be aligned" ); + ((dst_first & 1) != 0 || dst_second != dst_first + 1)) { // misaligned dst + assert((src_first & 1) == 0 && src_second == src_first + 1, "source must be aligned"); // Do the big-endian flop. OptoReg::Name tmp = dst_first ; dst_first = dst_second ; dst_second = tmp ; enum RC tmp_rc = dst_first_rc; dst_first_rc = dst_second_rc; dst_second_rc = tmp_rc; @@ -1478,30 +1493,28 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, // -------------------------------------- // Check for integer reg-reg copy - if( src_first_rc == rc_int && dst_first_rc == rc_int ) { + if (src_first_rc == rc_int && dst_first_rc == rc_int) { #ifndef _LP64 - if( src_first == R_O0_num && src_second == R_O1_num ) { // Check for the evil O0/O1 native long-return case + if (src_first == R_O0_num && src_second == R_O1_num) { // Check for the evil O0/O1 native long-return case // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value // as stored in memory. On a big-endian machine like SPARC, this means that the _second // operand contains the least significant word of the 64-bit value and vice versa. OptoReg::Name tmp = OptoReg::Name(R_O7_num); - assert( (dst_first&1)==0 && dst_second == dst_first+1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" ); + assert((dst_first & 1) == 0 && dst_second == dst_first + 1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" ); // Shift O0 left in-place, zero-extend O1, then OR them into the dst - if( cbuf ) { - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020 ); - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000 ); - emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second] ); + if ( cbuf ) { + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020); + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000); + emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second]); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp)); - st->print("SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second)); - st->print("OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first)); + } else { + print_helper(st, "SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp)); + print_helper(st, "SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second)); + print_helper(st, "OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first)); #endif } - return size+12; - } - else if( dst_first == R_I0_num && dst_second == R_I1_num ) { + return; + } else if (dst_first == R_I0_num && dst_second == R_I1_num) { // returning a long value in I0/I1 // a SpillCopy must be able to target a return instruction's reg_class // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value @@ -1511,27 +1524,25 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, if (src_first == dst_first) { tdest = OptoReg::Name(R_O7_num); - size += 4; } - if( cbuf ) { - assert( (src_first&1) == 0 && (src_first+1) == src_second, "return value was in an aligned-adjacent 64-bit reg"); + if (cbuf) { + assert((src_first & 1) == 0 && (src_first + 1) == src_second, "return value was in an aligned-adjacent 64-bit reg"); // Shift value in upper 32-bits of src to lower 32-bits of I0; move lower 32-bits to I1 // ShrL_reg_imm6 - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000 ); + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000); // ShrR_reg_imm6 src, 0, dst - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000 ); + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000); if (tdest != dst_first) { - emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest] ); + emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest]); } } #ifndef PRODUCT - else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); // %%%%% !!!!! - st->print("SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest)); - st->print("SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second)); + else { + print_helper(st, "SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest)); + print_helper(st, "SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second)); if (tdest != dst_first) { - st->print("MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first)); + print_helper(st, "MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first)); } } #endif // PRODUCT @@ -1539,65 +1550,77 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, } #endif // !_LP64 // Else normal reg-reg copy - assert( src_second != dst_first, "smashed second before evacuating it" ); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::or_op3,0,"MOV ",size, st); - assert( (src_first&1) == 0 && (dst_first&1) == 0, "never move second-halves of int registers" ); + assert(src_second != dst_first, "smashed second before evacuating it"); + impl_mov_helper(cbuf, src_first, dst_first, Assembler::or_op3, 0, "MOV ", st); + assert((src_first & 1) == 0 && (dst_first & 1) == 0, "never move second-halves of int registers"); // This moves an aligned adjacent pair. // See if we are done. - if( src_first+1 == src_second && dst_first+1 == dst_second ) - return size; + if (src_first + 1 == src_second && dst_first + 1 == dst_second) { + return; + } } // Check for integer store - if( src_first_rc == rc_int && dst_first_rc == rc_stack ) { + if (src_first_rc == rc_int && dst_first_rc == rc_stack) { int offset = ra_->reg2offset(dst_first); // Further check for aligned-adjacent pair, so we can use a double store - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stx_op3,"STX ",size, st); - size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stw_op3,"STW ",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stx_op3, "STX ", st); + return; + } + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stw_op3, "STW ", st); } // Check for integer load - if( dst_first_rc == rc_int && src_first_rc == rc_stack ) { + if (dst_first_rc == rc_int && src_first_rc == rc_stack) { int offset = ra_->reg2offset(src_first); // Further check for aligned-adjacent pair, so we can use a double load - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldx_op3 ,"LDX ",size, st); - size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldx_op3, "LDX ", st); + return; + } + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st); } // Check for float reg-reg copy - if( src_first_rc == rc_float && dst_first_rc == rc_float ) { + if (src_first_rc == rc_float && dst_first_rc == rc_float) { // Further check for aligned-adjacent pair, so we can use a double move - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovd_opf,"FMOVD",size, st); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovs_opf,"FMOVS",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovd_opf, "FMOVD", st); + return; + } + impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovs_opf, "FMOVS", st); } // Check for float store - if( src_first_rc == rc_float && dst_first_rc == rc_stack ) { + if (src_first_rc == rc_float && dst_first_rc == rc_stack) { int offset = ra_->reg2offset(dst_first); // Further check for aligned-adjacent pair, so we can use a double store - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stdf_op3,"STDF",size, st); - size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stdf_op3, "STDF", st); + return; + } + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st); } // Check for float load - if( dst_first_rc == rc_float && src_first_rc == rc_stack ) { + if (dst_first_rc == rc_float && src_first_rc == rc_stack) { int offset = ra_->reg2offset(src_first); // Further check for aligned-adjacent pair, so we can use a double load - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lddf_op3,"LDDF",size, st); - size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldf_op3 ,"LDF ",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lddf_op3, "LDDF", st); + return; + } + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldf_op3, "LDF ", st); } // -------------------------------------------------------------------- // Check for hi bits still needing moving. Only happens for misaligned // arguments to native calls. - if( src_second == dst_second ) - return size; // Self copy; no move - assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); + if (src_second == dst_second) { + return; // Self copy; no move + } + assert(src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad"); #ifndef _LP64 // In the LP64 build, all registers can be moved as aligned/adjacent @@ -1609,52 +1632,57 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, // 32-bits of a 64-bit register, but are needed in low bits of another // register (else it's a hi-bits-to-hi-bits copy which should have // happened already as part of a 64-bit move) - if( src_second_rc == rc_int && dst_second_rc == rc_int ) { - assert( (src_second&1)==1, "its the evil O0/O1 native return case" ); - assert( (dst_second&1)==0, "should have moved with 1 64-bit move" ); + if (src_second_rc == rc_int && dst_second_rc == rc_int) { + assert((src_second & 1) == 1, "its the evil O0/O1 native return case"); + assert((dst_second & 1) == 0, "should have moved with 1 64-bit move"); // Shift src_second down to dst_second's low bits. - if( cbuf ) { - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 ); + if (cbuf) { + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(dst_second)); + } else { + print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second - 1), OptoReg::regname(dst_second)); #endif } - return size+4; + return; } // Check for high word integer store. Must down-shift the hi bits // into a temp register, then fall into the case of storing int bits. - if( src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second&1)==1 ) { + if (src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second & 1) == 1) { // Shift src_second down to dst_second's low bits. - if( cbuf ) { - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 ); + if (cbuf) { + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(R_O7_num)); + } else { + print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second-1), OptoReg::regname(R_O7_num)); #endif } - size+=4; src_second = OptoReg::Name(R_O7_num); // Not R_O7H_num! } // Check for high word integer load - if( dst_second_rc == rc_int && src_second_rc == rc_stack ) - return impl_helper(this,cbuf,ra_,do_size,true ,ra_->reg2offset(src_second),dst_second,Assembler::lduw_op3,"LDUW",size, st); + if (dst_second_rc == rc_int && src_second_rc == rc_stack) + return impl_helper(this, cbuf, ra_, true, ra_->reg2offset(src_second), dst_second, Assembler::lduw_op3, "LDUW", size, st); // Check for high word integer store - if( src_second_rc == rc_int && dst_second_rc == rc_stack ) - return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stw_op3 ,"STW ",size, st); + if (src_second_rc == rc_int && dst_second_rc == rc_stack) + return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stw_op3, "STW ", size, st); // Check for high word float store - if( src_second_rc == rc_float && dst_second_rc == rc_stack ) - return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stf_op3 ,"STF ",size, st); + if (src_second_rc == rc_float && dst_second_rc == rc_stack) + return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stf_op3, "STF ", size, st); #endif // !_LP64 Unimplemented(); +} + +uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, + PhaseRegAlloc *ra_, + bool do_size, + outputStream* st) const { + assert(!do_size, "not supported"); + mach_spill_copy_implementation_helper(this, cbuf, ra_, st); return 0; } @@ -1669,19 +1697,19 @@ void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { } uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { - return implementation( NULL, ra_, true, NULL ); + return MachNode::size(ra_); } //============================================================================= #ifndef PRODUCT -void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const { +void MachNopNode::format(PhaseRegAlloc *, outputStream *st) const { st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count); } #endif -void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const { +void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *) const { MacroAssembler _masm(&cbuf); - for(int i = 0; i < _count; i += 1) { + for (int i = 0; i < _count; i += 1) { __ nop(); } } @@ -5197,7 +5225,6 @@ instruct stkI_to_regF(regF dst, stackSlotI src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $src,$dst\t! stkI to regF" %} opcode(Assembler::ldf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -5208,7 +5235,6 @@ instruct stkL_to_regD(regD dst, stackSlotL src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDDF $src,$dst\t! stkL to regD" %} opcode(Assembler::lddf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -5219,7 +5245,6 @@ instruct regF_to_stkI(stackSlotI dst, regF src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$dst\t! regF to stkI" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -5230,7 +5255,6 @@ instruct regD_to_stkL(stackSlotL dst, regD src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STDF $src,$dst\t! regD to stkL" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -5240,7 +5264,6 @@ instruct regD_to_stkL(stackSlotL dst, regD src) %{ instruct regI_to_stkLHi(stackSlotL dst, iRegI src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST*2); - size(8); format %{ "STW $src,$dst.hi\t! long\n\t" "STW R_G0,$dst.lo" %} opcode(Assembler::stw_op3); @@ -5252,7 +5275,6 @@ instruct regL_to_stkD(stackSlotD dst, iRegL src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t! regL to stkD" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5266,7 +5288,6 @@ instruct stkI_to_regI( iRegI dst, stackSlotI src ) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDUW $src,$dst\t!stk" %} opcode(Assembler::lduw_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -5278,7 +5299,6 @@ instruct regI_to_stkI( stackSlotI dst, iRegI src ) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$dst\t!stk" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5290,7 +5310,6 @@ instruct stkL_to_regL( iRegL dst, stackSlotL src ) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDX $src,$dst\t! long" %} opcode(Assembler::ldx_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -5302,7 +5321,6 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t! long" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5314,7 +5332,6 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDX $src,$dst\t!ptr" %} opcode(Assembler::ldx_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -5325,7 +5342,6 @@ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ instruct regP_to_stkP(stackSlotP dst, iRegP src) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t!ptr" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5771,7 +5787,6 @@ instruct loadL_unaligned(iRegL dst, memory mem, o7RegI tmp) %{ match(Set dst (LoadL_unaligned mem)); effect(KILL tmp); ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); - size(16); format %{ "LDUW $mem+4,R_O7\t! misaligned long\n" "\tLDUW $mem ,$dst\n" "\tSLLX #32, $dst, $dst\n" @@ -5786,7 +5801,6 @@ instruct loadRange(iRegI dst, memory mem) %{ match(Set dst (LoadRange mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDUW $mem,$dst\t! range" %} opcode(Assembler::lduw_op3); ins_encode(simple_form3_mem_reg( mem, dst ) ); @@ -5797,7 +5811,6 @@ instruct loadRange(iRegI dst, memory mem) %{ instruct loadI_freg(regF dst, memory mem) %{ match(Set dst (LoadI mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $mem,$dst\t! for fitos/fitod" %} opcode(Assembler::ldf_op3); @@ -5876,7 +5889,6 @@ instruct loadD(regD dst, memory mem) %{ match(Set dst (LoadD mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDDF $mem,$dst" %} opcode(Assembler::lddf_op3); ins_encode(simple_form3_mem_reg( mem, dst ) ); @@ -5887,7 +5899,6 @@ instruct loadD(regD dst, memory mem) %{ instruct loadD_unaligned(regD_low dst, memory mem ) %{ match(Set dst (LoadD_unaligned mem)); ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); - size(8); format %{ "LDF $mem ,$dst.hi\t! misaligned double\n" "\tLDF $mem+4,$dst.lo\t!" %} opcode(Assembler::ldf_op3); @@ -5900,7 +5911,6 @@ instruct loadF(regF dst, memory mem) %{ match(Set dst (LoadF mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $mem,$dst" %} opcode(Assembler::ldf_op3); ins_encode(simple_form3_mem_reg( mem, dst ) ); @@ -6119,7 +6129,6 @@ instruct prefetchAlloc( memory mem ) %{ predicate(AllocatePrefetchInstr == 0); match( PrefetchAllocation mem ); ins_cost(MEMORY_REF_COST); - size(4); format %{ "PREFETCH $mem,2\t! Prefetch allocation" %} opcode(Assembler::prefetch_op3); @@ -6175,7 +6184,6 @@ instruct storeB(memory mem, iRegI src) %{ match(Set mem (StoreB mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6186,7 +6194,6 @@ instruct storeB0(memory mem, immI0 src) %{ match(Set mem (StoreB mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6197,7 +6204,6 @@ instruct storeCM0(memory mem, immI0 src) %{ match(Set mem (StoreCM mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STB $src,$mem\t! CMS card-mark byte 0" %} opcode(Assembler::stb_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6209,7 +6215,6 @@ instruct storeC(memory mem, iRegI src) %{ match(Set mem (StoreC mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6220,7 +6225,6 @@ instruct storeC0(memory mem, immI0 src) %{ match(Set mem (StoreC mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6232,7 +6236,6 @@ instruct storeI(memory mem, iRegI src) %{ match(Set mem (StoreI mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6243,7 +6246,6 @@ instruct storeI(memory mem, iRegI src) %{ instruct storeL(memory mem, iRegL src) %{ match(Set mem (StoreL mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$mem\t! long" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6254,7 +6256,6 @@ instruct storeI0(memory mem, immI0 src) %{ match(Set mem (StoreI mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6265,7 +6266,6 @@ instruct storeL0(memory mem, immL0 src) %{ match(Set mem (StoreL mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6277,7 +6277,6 @@ instruct storeI_Freg(memory mem, regF src) %{ match(Set mem (StoreI mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$mem\t! after fstoi/fdtoi" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6288,7 +6287,6 @@ instruct storeI_Freg(memory mem, regF src) %{ instruct storeP(memory dst, sp_ptr_RegP src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); - size(4); #ifndef _LP64 format %{ "STW $src,$dst\t! ptr" %} @@ -6304,7 +6302,6 @@ instruct storeP(memory dst, sp_ptr_RegP src) %{ instruct storeP0(memory dst, immP0 src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); - size(4); #ifndef _LP64 format %{ "STW $src,$dst\t! ptr" %} @@ -6379,7 +6376,6 @@ instruct storeD( memory mem, regD src) %{ match(Set mem (StoreD mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STDF $src,$mem" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6390,7 +6386,6 @@ instruct storeD0( memory mem, immD0 src) %{ match(Set mem (StoreD mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6402,7 +6397,6 @@ instruct storeF( memory mem, regF src) %{ match(Set mem (StoreF mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$mem" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6413,7 +6407,6 @@ instruct storeF0( memory mem, immF0 src) %{ match(Set mem (StoreF mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$mem\t! storeF0" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -7068,7 +7061,6 @@ instruct loadPLocked(iRegP dst, memory mem) %{ ins_cost(MEMORY_REF_COST); #ifndef _LP64 - size(4); format %{ "LDUW $mem,$dst\t! ptr" %} opcode(Assembler::lduw_op3, 0, REGP_OP); #else @@ -8138,7 +8130,6 @@ instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDUW $src,$dst\t! MoveF2I" %} opcode(Assembler::lduw_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -8150,7 +8141,6 @@ instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $src,$dst\t! MoveI2F" %} opcode(Assembler::ldf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -8162,7 +8152,6 @@ instruct MoveD2L_stack_reg(iRegL dst, stackSlotD src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDX $src,$dst\t! MoveD2L" %} opcode(Assembler::ldx_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -8174,7 +8163,6 @@ instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDDF $src,$dst\t! MoveL2D" %} opcode(Assembler::lddf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -8186,7 +8174,6 @@ instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$dst\t! MoveF2I" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -8198,7 +8185,6 @@ instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$dst\t! MoveI2F" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -8210,7 +8196,6 @@ instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STDF $src,$dst\t! MoveD2L" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -8222,7 +8207,6 @@ instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t! MoveL2D" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -8427,7 +8411,6 @@ instruct convI2D_reg(regD_low dst, iRegI src) %{ instruct convI2D_mem(regD_low dst, memory mem) %{ match(Set dst (ConvI2D (LoadI mem))); ins_cost(DEFAULT_COST + MEMORY_REF_COST); - size(8); format %{ "LDF $mem,$dst\n\t" "FITOD $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitod_opf); @@ -8468,7 +8451,6 @@ instruct convI2F_reg(regF dst, iRegI src) %{ instruct convI2F_mem( regF dst, memory mem ) %{ match(Set dst (ConvI2F (LoadI mem))); ins_cost(DEFAULT_COST + MEMORY_REF_COST); - size(8); format %{ "LDF $mem,$dst\n\t" "FITOS $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitos_opf); From f9a6dbd5fd802b319c897b00c3cfda3e1e397d8a Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Fri, 26 Feb 2016 11:13:25 -1000 Subject: [PATCH 026/311] 8150738: [JVMCI] runtime/CommandLine/TraceExceptionsTest.java fails with: java.lang.RuntimeException: '' missing Reviewed-by: coleenp --- hotspot/src/share/vm/jvmci/jvmciRuntime.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp index 716f73c06b1..d5a10f4660f 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp @@ -293,13 +293,11 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t // tracing if (log_is_enabled(Info, exceptions)) { ResourceMark rm; - log_info(exceptions)("Exception <%s> (" INTPTR_FORMAT ") thrown in" - " compiled method <%s> at PC " INTPTR_FORMAT - " for thread " INTPTR_FORMAT, - exception->print_value_string(), - p2i((address)exception()), - nm->method()->print_value_string(), p2i(pc), - p2i(thread)); + stringStream tempst; + tempst.print("compiled method <%s>\n" + " at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT, + nm->method()->print_value_string(), p2i(pc), p2i(thread)); + Exceptions::log_exception(exception, tempst); } // for AbortVMOnException flag NOT_PRODUCT(Exceptions::debug_check_abort(exception)); From babca8523287e182f5683992935c11bce2d754d6 Mon Sep 17 00:00:00 2001 From: Zoltan Majo Date: Mon, 29 Feb 2016 13:02:10 +0100 Subject: [PATCH 027/311] 8150349: Reduce the execution time of the hotspot_compiler_3 group Exclude long-running intrinsic-related tests that check functionality that is not likely to be changed soon. Reviewed-by: kvn, neliasso --- hotspot/test/TEST.groups | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index f7d983f5a8f..11b95da776b 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -297,7 +297,8 @@ hotspot_compiler_3 = \ compiler/types/ \ compiler/uncommontrap/ \ compiler/unsafe/ \ - -compiler/intrinsics/bmi/verifycode \ + -compiler/intrinsics/adler32 \ + -compiler/intrinsics/bmi \ -compiler/intrinsics/mathexact \ -compiler/intrinsics/multiplytolen \ -compiler/intrinsics/sha \ From ea5a3565b8618fd0746082e0d82e423f47fcd7ce Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Mon, 29 Feb 2016 15:05:45 +0100 Subject: [PATCH 028/311] 8150720: Cleanup code around PrintOptoStatistics Reviewed-by: kvn, shade, vlivanov --- hotspot/src/share/vm/opto/graphKit.cpp | 17 ++++++---- hotspot/src/share/vm/opto/ifnode.cpp | 20 ++++++++---- hotspot/src/share/vm/opto/lcm.cpp | 2 ++ hotspot/src/share/vm/opto/matcher.cpp | 2 ++ hotspot/src/share/vm/opto/node.cpp | 28 ++-------------- hotspot/src/share/vm/opto/parse.hpp | 10 ------ hotspot/src/share/vm/opto/parse1.cpp | 45 ++++++++++++-------------- hotspot/src/share/vm/opto/parse2.cpp | 8 +++-- 8 files changed, 56 insertions(+), 76 deletions(-) diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index a47897db8c1..73f7c3e1254 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1179,8 +1179,10 @@ Node* GraphKit::load_array_length(Node* array) { // Helper function to do a NULL pointer check. Returned value is // the incoming address with NULL casted away. You are allowed to use the // not-null value only if you are control dependent on the test. +#ifndef PRODUCT extern int explicit_null_checks_inserted, explicit_null_checks_elided; +#endif Node* GraphKit::null_check_common(Node* value, BasicType type, // optional arguments for variations: bool assert_null, @@ -1193,7 +1195,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, value = cast_not_null(value); // Make it appear to be non-null (4962416). return value; } - explicit_null_checks_inserted++; + NOT_PRODUCT(explicit_null_checks_inserted++); // Construct NULL check Node *chk = NULL; @@ -1233,7 +1235,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, // See if the type is contained in NULL_PTR. // If so, then the value is already null. if (t->higher_equal(TypePtr::NULL_PTR)) { - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); return value; // Elided null assert quickly! } } else { @@ -1242,7 +1244,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, // type. In other words, "value" was not-null. if (t->meet(TypePtr::NULL_PTR) != t->remove_speculative()) { // same as: if (!TypePtr::NULL_PTR->higher_equal(t)) ... - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); return value; // Elided null check quickly! } } @@ -1282,7 +1284,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, set_control(cfg); Node *res = cast_not_null(value); set_control(oldcontrol); - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); return res; } cfg = IfNode::up_one_dom(cfg, /*linear_only=*/ true); @@ -1326,15 +1328,18 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, IfNode* iff = create_and_map_if(control(), tst, ok_prob, COUNT_UNKNOWN); Node* null_true = _gvn.transform( new IfFalseNode(iff)); set_control( _gvn.transform( new IfTrueNode(iff))); - if (null_true == top()) +#ifndef PRODUCT + if (null_true == top()) { explicit_null_checks_elided++; + } +#endif (*null_control) = null_true; } else { BuildCutout unless(this, tst, ok_prob); // Check for optimizer eliding test at parse time if (stopped()) { // Failure not possible; do not bother making uncommon trap. - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); } else if (assert_null) { uncommon_trap(reason, Deoptimization::Action_make_not_entrant, diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index a2cea88273f..9e315739008 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -40,7 +40,9 @@ // Optimization - Graph Style +#ifndef PRODUCT extern int explicit_null_checks_elided; +#endif //============================================================================= //------------------------------Value------------------------------------------ @@ -1504,24 +1506,28 @@ Node* IfNode::search_identical(int dist) { Node* prev_dom = this; int op = Opcode(); // Search up the dominator tree for an If with an identical test - while( dom->Opcode() != op || // Not same opcode? + while (dom->Opcode() != op || // Not same opcode? dom->in(1) != in(1) || // Not same input 1? (req() == 3 && dom->in(2) != in(2)) || // Not same input 2? - prev_dom->in(0) != dom ) { // One path of test does not dominate? - if( dist < 0 ) return NULL; + prev_dom->in(0) != dom) { // One path of test does not dominate? + if (dist < 0) return NULL; dist--; prev_dom = dom; - dom = up_one_dom( dom ); - if( !dom ) return NULL; + dom = up_one_dom(dom); + if (!dom) return NULL; } // Check that we did not follow a loop back to ourselves - if( this == dom ) + if (this == dom) { return NULL; + } - if( dist > 2 ) // Add to count of NULL checks elided +#ifndef PRODUCT + if (dist > 2) { // Add to count of NULL checks elided explicit_null_checks_elided++; + } +#endif return prev_dom; } diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 3edfc5e0ef0..431bba14c7e 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -348,8 +348,10 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo } // ---- Found an implicit null check +#ifndef PRODUCT extern int implicit_null_checks; implicit_null_checks++; +#endif if( is_decoden ) { // Check if we need to hoist decodeHeapOop_not_null first. diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index edb69afb43d..1df9f7ca1c0 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -2415,8 +2415,10 @@ void Matcher::collect_null_checks( Node *proj, Node *orig_proj ) { bool push_it = false; if( proj->Opcode() == Op_IfTrue ) { +#ifndef PRODUCT extern int all_null_checks_found; all_null_checks_found++; +#endif if( b->_test._test == BoolTest::ne ) { push_it = true; } diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index 42ca23d212a..78dcacc550b 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -576,17 +576,11 @@ void Node::setup_is_top() { //------------------------------~Node------------------------------------------ // Fancy destructor; eagerly attempt to reclaim Node numberings and storage -extern int reclaim_idx ; -extern int reclaim_in ; -extern int reclaim_node; void Node::destruct() { // Eagerly reclaim unique Node numberings Compile* compile = Compile::current(); if ((uint)_idx+1 == compile->unique()) { compile->set_unique(compile->unique()-1); -#ifdef ASSERT - reclaim_idx++; -#endif } // Clear debug info: Node_Notes* nn = compile->node_notes_at(_idx); @@ -604,43 +598,25 @@ void Node::destruct() { int out_edge_size = _outmax*sizeof(void*); char *edge_end = ((char*)_in) + edge_size; char *out_array = (char*)(_out == NO_OUT_ARRAY? NULL: _out); - char *out_edge_end = out_array + out_edge_size; int node_size = size_of(); // Free the output edge array if (out_edge_size > 0) { -#ifdef ASSERT - if( out_edge_end == compile->node_arena()->hwm() ) - reclaim_in += out_edge_size; // count reclaimed out edges with in edges -#endif compile->node_arena()->Afree(out_array, out_edge_size); } // Free the input edge array and the node itself if( edge_end == (char*)this ) { -#ifdef ASSERT - if( edge_end+node_size == compile->node_arena()->hwm() ) { - reclaim_in += edge_size; - reclaim_node+= node_size; - } -#else // It was; free the input array and object all in one hit +#ifndef ASSERT compile->node_arena()->Afree(_in,edge_size+node_size); #endif } else { - // Free just the input array -#ifdef ASSERT - if( edge_end == compile->node_arena()->hwm() ) - reclaim_in += edge_size; -#endif compile->node_arena()->Afree(_in,edge_size); // Free just the object -#ifdef ASSERT - if( ((char*)this) + node_size == compile->node_arena()->hwm() ) - reclaim_node+= node_size; -#else +#ifndef ASSERT compile->node_arena()->Afree(this,node_size); #endif } diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index c8a35c9ba53..b26a59f8497 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -104,13 +104,6 @@ public: // For temporary (stack-allocated, stateless) ilts: InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio, int max_inline_level); - // InlineTree enum - enum InlineStyle { - Inline_do_not_inline = 0, // - Inline_cha_is_monomorphic = 1, // - Inline_type_profile_monomorphic = 2 // - }; - // See if it is OK to inline. // The receiver is the inline tree for the caller. // @@ -349,9 +342,6 @@ class Parse : public GraphKit { Block* _block; // block currently getting parsed ciBytecodeStream _iter; // stream of this method's bytecodes - int _blocks_merged; // Progress meter: state merges from BB preds - int _blocks_parsed; // Progress meter: BBs actually parsed - const FastLockNode* _synch_lock; // FastLockNode for synchronized method #ifndef PRODUCT diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index e051b5e1e5c..503f3c7f400 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -45,6 +45,7 @@ // the most. Some of the non-static variables are needed in bytecodeInfo.cpp // and eventually should be encapsulated in a proper class (gri 8/18/98). +#ifndef PRODUCT int nodes_created = 0; int methods_parsed = 0; int methods_seen = 0; @@ -53,42 +54,42 @@ int blocks_seen = 0; int explicit_null_checks_inserted = 0; int explicit_null_checks_elided = 0; -int all_null_checks_found = 0, implicit_null_checks = 0; -int implicit_null_throws = 0; +int all_null_checks_found = 0; +int implicit_null_checks = 0; -int reclaim_idx = 0; -int reclaim_in = 0; -int reclaim_node = 0; - -#ifndef PRODUCT bool Parse::BytecodeParseHistogram::_initialized = false; uint Parse::BytecodeParseHistogram::_bytecodes_parsed [Bytecodes::number_of_codes]; uint Parse::BytecodeParseHistogram::_nodes_constructed[Bytecodes::number_of_codes]; uint Parse::BytecodeParseHistogram::_nodes_transformed[Bytecodes::number_of_codes]; uint Parse::BytecodeParseHistogram::_new_values [Bytecodes::number_of_codes]; -#endif //------------------------------print_statistics------------------------------- -#ifndef PRODUCT void Parse::print_statistics() { tty->print_cr("--- Compiler Statistics ---"); tty->print("Methods seen: %d Methods parsed: %d", methods_seen, methods_parsed); tty->print(" Nodes created: %d", nodes_created); tty->cr(); - if (methods_seen != methods_parsed) + if (methods_seen != methods_parsed) { tty->print_cr("Reasons for parse failures (NOT cumulative):"); + } tty->print_cr("Blocks parsed: %d Blocks seen: %d", blocks_parsed, blocks_seen); - if( explicit_null_checks_inserted ) - tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,", explicit_null_checks_inserted, explicit_null_checks_elided, (100*explicit_null_checks_elided)/explicit_null_checks_inserted, all_null_checks_found); - if( all_null_checks_found ) + if (explicit_null_checks_inserted) { + tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,", + explicit_null_checks_inserted, explicit_null_checks_elided, + (100*explicit_null_checks_elided)/explicit_null_checks_inserted, + all_null_checks_found); + } + if (all_null_checks_found) { tty->print_cr("%d made implicit (%2d%%)", implicit_null_checks, (100*implicit_null_checks)/all_null_checks_found); - if( implicit_null_throws ) + } + if (SharedRuntime::_implicit_null_throws) { tty->print_cr("%d implicit null exceptions at runtime", - implicit_null_throws); + SharedRuntime::_implicit_null_throws); + } - if( PrintParseStatistics && BytecodeParseHistogram::initialized() ) { + if (PrintParseStatistics && BytecodeParseHistogram::initialized()) { BytecodeParseHistogram::print(); } } @@ -495,7 +496,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) C->dependencies()->assert_evol_method(method()); } - methods_seen++; + NOT_PRODUCT(methods_seen++); // Do some special top-level things. if (depth() == 1 && C->is_osr_compilation()) { @@ -530,8 +531,8 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) } #endif - methods_parsed++; #ifndef PRODUCT + methods_parsed++; // add method size here to guarantee that inlined methods are added too if (CITime) _total_bytes_compiled += method()->code_size(); @@ -652,7 +653,7 @@ void Parse::do_all_blocks() { continue; } - blocks_parsed++; + NOT_PRODUCT(blocks_parsed++); progress = true; if (block->is_loop_head() || block->is_handler() || has_irreducible && !block->is_ready()) { @@ -712,9 +713,9 @@ void Parse::do_all_blocks() { } } +#ifndef PRODUCT blocks_seen += block_count(); -#ifndef PRODUCT // Make sure there are no half-processed blocks remaining. // Every remaining unprocessed block is dead and may be ignored now. for (int rpo = 0; rpo < block_count(); rpo++) { @@ -1446,7 +1447,6 @@ void Parse::do_one_block() { assert(block()->is_merged(), "must be merged before being parsed"); block()->mark_parsed(); - ++_blocks_parsed; // Set iterator to start of block. iter().reset_to_bci(block()->start()); @@ -1596,9 +1596,6 @@ void Parse::merge_common(Parse::Block* target, int pnum) { return; } - // Record that a new block has been merged. - ++_blocks_merged; - // Make a region if we know there are multiple or unpredictable inputs. // (Also, if this is a plain fall-through, we might see another region, // which must not be allowed into this block's map.) diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index e03abd4f931..8004ef246e5 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -44,8 +44,10 @@ #include "runtime/deoptimization.hpp" #include "runtime/sharedRuntime.hpp" +#ifndef PRODUCT extern int explicit_null_checks_inserted, explicit_null_checks_elided; +#endif //---------------------------------array_load---------------------------------- void Parse::array_load(BasicType elem_type) { @@ -997,7 +999,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { return; } - explicit_null_checks_inserted++; + NOT_PRODUCT(explicit_null_checks_inserted++); // Generate real control flow Node *tst = _gvn.transform( new BoolNode( c, btest ) ); @@ -1013,7 +1015,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { set_control(iftrue); if (stopped()) { // Path is dead? - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); if (C->eliminate_boxing()) { // Mark the successor block as parsed branch_block->next_path_num(); @@ -1033,7 +1035,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { set_control(iffalse); if (stopped()) { // Path is dead? - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); if (C->eliminate_boxing()) { // Mark the successor block as parsed next_block->next_path_num(); From bb51ea7a06a1c95184940b26e45957731b2ae5f1 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 29 Feb 2016 23:46:55 +0300 Subject: [PATCH 029/311] 8150543: Mismatched access detection is inaccurate Reviewed-by: kvn, shade --- hotspot/src/share/vm/opto/library_call.cpp | 8 +- hotspot/src/share/vm/opto/memnode.cpp | 18 +- .../unsafe/UnsafeGetConstantField.java | 3 + .../unsafe/UnsafeGetStableArrayElement.java | 278 +++++++++++++++++- 4 files changed, 284 insertions(+), 23 deletions(-) diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index de751bc1a97..240321cb231 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -2541,10 +2541,12 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor if (alias_type->element() != NULL || alias_type->field() != NULL) { BasicType bt; if (alias_type->element() != NULL) { - const Type* element = alias_type->element(); + // Use address type to get the element type. Alias type doesn't provide + // enough information (e.g., doesn't differentiate between byte[] and boolean[]). + const Type* element = adr_type->is_aryptr()->elem(); bt = element->isa_narrowoop() ? T_OBJECT : element->array_element_basic_type(); } else { - bt = alias_type->field()->type()->basic_type(); + bt = alias_type->field()->layout_type(); } if (bt == T_ARRAY) { // accessing an array field with getObject is not a mismatch @@ -2561,7 +2563,7 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor // Try to constant fold a load from a constant field ciField* field = alias_type->field(); if (heap_base_oop != top() && - field != NULL && field->is_constant() && field->layout_type() == type) { + field != NULL && field->is_constant() && !mismatched) { // final or stable field const Type* con_type = Type::make_constant(alias_type->field(), heap_base_oop); if (con_type != NULL) { diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 55ca4581485..2d2b40d334e 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -1582,14 +1582,22 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls, return NULL; } +#ifdef ASSERT static bool is_mismatched_access(ciConstant con, BasicType loadbt) { BasicType conbt = con.basic_type(); - assert(conbt != T_NARROWOOP, "sanity"); - if (loadbt == T_NARROWOOP || loadbt == T_ARRAY) { - loadbt = T_OBJECT; + switch (conbt) { + case T_BOOLEAN: conbt = T_BYTE; break; + case T_ARRAY: conbt = T_OBJECT; break; + } + switch (loadbt) { + case T_BOOLEAN: loadbt = T_BYTE; break; + case T_NARROWOOP: loadbt = T_OBJECT; break; + case T_ARRAY: loadbt = T_OBJECT; break; + case T_ADDRESS: loadbt = T_OBJECT; break; } return (conbt != loadbt); } +#endif // ASSERT // Try to constant-fold a stable array element. static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) { @@ -1599,7 +1607,9 @@ static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicTyp // Decode the results of GraphKit::array_element_address. ciArray* aobj = ary->const_oop()->as_array(); ciConstant con = aobj->element_value_by_offset(off); - if (con.basic_type() != T_ILLEGAL && !is_mismatched_access(con, loadbt) && !con.is_null_or_zero()) { + if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) { + assert(!is_mismatched_access(con, loadbt), + "conbt=%s; loadbt=%s", type2name(con.basic_type()), type2name(loadbt)); const Type* con_type = Type::make_from_constant(con); if (con_type != NULL) { if (con_type->isa_aryptr()) { diff --git a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java index 8c144143d62..c1d6b057e14 100644 --- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java +++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java @@ -27,6 +27,9 @@ * @test * @summary tests on constant folding of unsafe get operations * @library /testlibrary /test/lib + * + * @requires vm.flavor != "client" + * * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions * -Xbatch -XX:-TieredCompilation * -XX:+FoldStableValues diff --git a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java index afdb1a6e7a3..0cf5f44dc85 100644 --- a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java +++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java @@ -25,17 +25,15 @@ /* * @test - * @summary tests on constant folding of unsafe get operations + * @summary tests on constant folding of unsafe get operations from stable arrays * @library /testlibrary /test/lib * + * @requires vm.flavor != "client" + * * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions * -Xbatch -XX:-TieredCompilation * -XX:+FoldStableValues - * UnsafeGetStableArrayElement - * - * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions - * -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 - * -XX:+FoldStableValues + * -XX:CompileCommand=dontinline,*Test::test* * UnsafeGetStableArrayElement */ import jdk.internal.misc.Unsafe; @@ -46,23 +44,271 @@ import static jdk.internal.misc.Unsafe.*; import static jdk.test.lib.Asserts.*; public class UnsafeGetStableArrayElement { - @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[] { 0, 1, -128, 127}; + @Stable static final boolean[] STABLE_BOOLEAN_ARRAY = new boolean[16]; + @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[16]; + @Stable static final short[] STABLE_SHORT_ARRAY = new short[8]; + @Stable static final char[] STABLE_CHAR_ARRAY = new char[8]; + @Stable static final int[] STABLE_INT_ARRAY = new int[4]; + @Stable static final long[] STABLE_LONG_ARRAY = new long[2]; + @Stable static final float[] STABLE_FLOAT_ARRAY = new float[4]; + @Stable static final double[] STABLE_DOUBLE_ARRAY = new double[2]; + @Stable static final Object[] STABLE_OBJECT_ARRAY = new Object[4]; + static { + Setter.reset(); + } static final Unsafe U = Unsafe.getUnsafe(); - static int testChar() { - return U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 0 * ARRAY_CHAR_INDEX_SCALE) + - U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 1 * ARRAY_CHAR_INDEX_SCALE); - } + static class Setter { + private static void setZ(boolean defaultVal) { STABLE_BOOLEAN_ARRAY[0] = defaultVal ? false : true; } + private static void setB(boolean defaultVal) { STABLE_BYTE_ARRAY[0] = defaultVal ? 0 : Byte.MAX_VALUE; } + private static void setS(boolean defaultVal) { STABLE_SHORT_ARRAY[0] = defaultVal ? 0 : Short.MAX_VALUE; } + private static void setC(boolean defaultVal) { STABLE_CHAR_ARRAY[0] = defaultVal ? 0 : Character.MAX_VALUE; } + private static void setI(boolean defaultVal) { STABLE_INT_ARRAY[0] = defaultVal ? 0 : Integer.MAX_VALUE; } + private static void setJ(boolean defaultVal) { STABLE_LONG_ARRAY[0] = defaultVal ? 0 : Long.MAX_VALUE; } + private static void setF(boolean defaultVal) { STABLE_FLOAT_ARRAY[0] = defaultVal ? 0 : Float.MAX_VALUE; } + private static void setD(boolean defaultVal) { STABLE_DOUBLE_ARRAY[0] = defaultVal ? 0 : Double.MAX_VALUE; } + private static void setL(boolean defaultVal) { STABLE_OBJECT_ARRAY[0] = defaultVal ? null : new Object(); } - static void run(Callable c) throws Exception { - Object first = c.call(); - for (int i = 0; i < 20_000; i++) { - assertEQ(first, c.call()); + static void reset() { + setZ(false); + setB(false); + setS(false); + setC(false); + setI(false); + setJ(false); + setF(false); + setD(false); + setL(false); } } + static class Test { + static void changeZ() { Setter.setZ(true); } + static void changeB() { Setter.setB(true); } + static void changeS() { Setter.setS(true); } + static void changeC() { Setter.setC(true); } + static void changeI() { Setter.setI(true); } + static void changeJ() { Setter.setJ(true); } + static void changeF() { Setter.setF(true); } + static void changeD() { Setter.setD(true); } + static void changeL() { Setter.setL(true); } + + static boolean testZ_Z() { return U.getBoolean(STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static byte testZ_B() { return U.getByte( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static short testZ_S() { return U.getShort( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static char testZ_C() { return U.getChar( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static int testZ_I() { return U.getInt( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static long testZ_J() { return U.getLong( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static float testZ_F() { return U.getFloat( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static double testZ_D() { return U.getDouble( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + + static boolean testB_Z() { return U.getBoolean(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static byte testB_B() { return U.getByte( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static short testB_S() { return U.getShort( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static char testB_C() { return U.getChar( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static int testB_I() { return U.getInt( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static long testB_J() { return U.getLong( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static float testB_F() { return U.getFloat( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static double testB_D() { return U.getDouble( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + + static boolean testS_Z() { return U.getBoolean(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static byte testS_B() { return U.getByte( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static short testS_S() { return U.getShort( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static char testS_C() { return U.getChar( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static int testS_I() { return U.getInt( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static long testS_J() { return U.getLong( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static float testS_F() { return U.getFloat( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static double testS_D() { return U.getDouble( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + + static boolean testC_Z() { return U.getBoolean(STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static byte testC_B() { return U.getByte( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static short testC_S() { return U.getShort( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static char testC_C() { return U.getChar( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static int testC_I() { return U.getInt( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static long testC_J() { return U.getLong( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static float testC_F() { return U.getFloat( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static double testC_D() { return U.getDouble( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + + static boolean testI_Z() { return U.getBoolean(STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static byte testI_B() { return U.getByte( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static short testI_S() { return U.getShort( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static char testI_C() { return U.getChar( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static int testI_I() { return U.getInt( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static long testI_J() { return U.getLong( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static float testI_F() { return U.getFloat( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static double testI_D() { return U.getDouble( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + + static boolean testJ_Z() { return U.getBoolean(STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static byte testJ_B() { return U.getByte( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static short testJ_S() { return U.getShort( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static char testJ_C() { return U.getChar( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static int testJ_I() { return U.getInt( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static long testJ_J() { return U.getLong( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static float testJ_F() { return U.getFloat( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static double testJ_D() { return U.getDouble( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + + static boolean testF_Z() { return U.getBoolean(STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static byte testF_B() { return U.getByte( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static short testF_S() { return U.getShort( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static char testF_C() { return U.getChar( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static int testF_I() { return U.getInt( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static long testF_J() { return U.getLong( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static float testF_F() { return U.getFloat( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static double testF_D() { return U.getDouble( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + + static boolean testD_Z() { return U.getBoolean(STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static byte testD_B() { return U.getByte( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static short testD_S() { return U.getShort( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static char testD_C() { return U.getChar( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static int testD_I() { return U.getInt( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static long testD_J() { return U.getLong( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static float testD_F() { return U.getFloat( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static double testD_D() { return U.getDouble( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + + static Object testL_L() { return U.getObject( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static boolean testL_Z() { return U.getBoolean(STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static byte testL_B() { return U.getByte( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static short testL_S() { return U.getShort( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static char testL_C() { return U.getChar( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static int testL_I() { return U.getInt( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static long testL_J() { return U.getLong( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static float testL_F() { return U.getFloat( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static double testL_D() { return U.getDouble( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + + static short testS_U() { return U.getShortUnaligned(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET + 1); } + static char testC_U() { return U.getCharUnaligned( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET + 1); } + static int testI_U() { return U.getIntUnaligned( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET + 1); } + static long testJ_U() { return U.getLongUnaligned( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET + 1); } + } + + static void run(Callable c, Runnable sameResultAction, Runnable changeResultAction) throws Exception { + Object first = c.call(); + + // Trigger compilation. + for (int i = 0; i < 20_000; i++) { + // Don't compare results here, since most of Test::testL_* results vary across iterations (due to GC). + c.call(); + } + + if (sameResultAction != null) { + sameResultAction.run(); + assertEQ(first, c.call()); + } + + if (changeResultAction != null) { + changeResultAction.run(); + assertNE(first, c.call()); + assertEQ(c.call(), c.call()); + } + } + + static void testMatched(Callable c, Runnable setDefaultAction) throws Exception { + run(c, setDefaultAction, null); + Setter.reset(); + } + + static void testMismatched(Callable c, Runnable setDefaultAction) throws Exception { + run(c, null, setDefaultAction); + Setter.reset(); + } + public static void main(String[] args) throws Exception { - run(UnsafeGetStableArrayElement::testChar); + // boolean[], aligned accesses + testMatched( Test::testZ_Z, Test::changeZ); + testMismatched(Test::testZ_B, Test::changeZ); + testMismatched(Test::testZ_S, Test::changeZ); + testMismatched(Test::testZ_C, Test::changeZ); + testMismatched(Test::testZ_I, Test::changeZ); + testMismatched(Test::testZ_J, Test::changeZ); + testMismatched(Test::testZ_F, Test::changeZ); + testMismatched(Test::testZ_D, Test::changeZ); + + // byte[], aligned accesses + testMismatched(Test::testB_Z, Test::changeB); + testMatched( Test::testB_B, Test::changeB); + testMismatched(Test::testB_S, Test::changeB); + testMismatched(Test::testB_C, Test::changeB); + testMismatched(Test::testB_I, Test::changeB); + testMismatched(Test::testB_J, Test::changeB); + testMismatched(Test::testB_F, Test::changeB); + testMismatched(Test::testB_D, Test::changeB); + + // short[], aligned accesses + testMismatched(Test::testS_Z, Test::changeS); + testMismatched(Test::testS_B, Test::changeS); + testMatched( Test::testS_S, Test::changeS); + testMismatched(Test::testS_C, Test::changeS); + testMismatched(Test::testS_I, Test::changeS); + testMismatched(Test::testS_J, Test::changeS); + testMismatched(Test::testS_F, Test::changeS); + testMismatched(Test::testS_D, Test::changeS); + + // char[], aligned accesses + testMismatched(Test::testC_Z, Test::changeC); + testMismatched(Test::testC_B, Test::changeC); + testMismatched(Test::testC_S, Test::changeC); + testMatched( Test::testC_C, Test::changeC); + testMismatched(Test::testC_I, Test::changeC); + testMismatched(Test::testC_J, Test::changeC); + testMismatched(Test::testC_F, Test::changeC); + testMismatched(Test::testC_D, Test::changeC); + + // int[], aligned accesses + testMismatched(Test::testI_Z, Test::changeI); + testMismatched(Test::testI_B, Test::changeI); + testMismatched(Test::testI_S, Test::changeI); + testMismatched(Test::testI_C, Test::changeI); + testMatched( Test::testI_I, Test::changeI); + testMismatched(Test::testI_J, Test::changeI); + testMismatched(Test::testI_F, Test::changeI); + testMismatched(Test::testI_D, Test::changeI); + + // long[], aligned accesses + testMismatched(Test::testJ_Z, Test::changeJ); + testMismatched(Test::testJ_B, Test::changeJ); + testMismatched(Test::testJ_S, Test::changeJ); + testMismatched(Test::testJ_C, Test::changeJ); + testMismatched(Test::testJ_I, Test::changeJ); + testMatched( Test::testJ_J, Test::changeJ); + testMismatched(Test::testJ_F, Test::changeJ); + testMismatched(Test::testJ_D, Test::changeJ); + + // float[], aligned accesses + testMismatched(Test::testF_Z, Test::changeF); + testMismatched(Test::testF_B, Test::changeF); + testMismatched(Test::testF_S, Test::changeF); + testMismatched(Test::testF_C, Test::changeF); + testMismatched(Test::testF_I, Test::changeF); + testMismatched(Test::testF_J, Test::changeF); + testMatched( Test::testF_F, Test::changeF); + testMismatched(Test::testF_D, Test::changeF); + + // double[], aligned accesses + testMismatched(Test::testD_Z, Test::changeD); + testMismatched(Test::testD_B, Test::changeD); + testMismatched(Test::testD_S, Test::changeD); + testMismatched(Test::testD_C, Test::changeD); + testMismatched(Test::testD_I, Test::changeD); + testMismatched(Test::testD_J, Test::changeD); + testMismatched(Test::testD_F, Test::changeD); + testMatched( Test::testD_D, Test::changeD); + + // Object[], aligned accesses + testMismatched(Test::testL_Z, Test::changeL); + testMismatched(Test::testL_B, Test::changeL); + testMismatched(Test::testL_S, Test::changeL); + testMismatched(Test::testL_C, Test::changeL); + testMismatched(Test::testL_I, Test::changeL); + testMismatched(Test::testL_J, Test::changeL); + testMismatched(Test::testL_F, Test::changeL); + testMismatched(Test::testL_D, Test::changeL); + testMatched( Test::testL_L, Test::changeL); + + // Unaligned accesses + testMismatched(Test::testS_U, Test::changeS); + testMismatched(Test::testC_U, Test::changeC); + testMismatched(Test::testI_U, Test::changeI); + testMismatched(Test::testJ_U, Test::changeJ); } } From f73f7433d015641095e8a10b5f2c6ea15153214e Mon Sep 17 00:00:00 2001 From: Hui Shi Date: Wed, 24 Feb 2016 04:45:50 -0800 Subject: [PATCH 030/311] 8149733: AArch64: refactor array_equals/string_equals Combine similar code for string_equals/char_array_equals/byte_array_equals into same implemenation Reviewed-by: aph, shade --- hotspot/src/cpu/aarch64/vm/aarch64.ad | 25 +- .../cpu/aarch64/vm/macroAssembler_aarch64.cpp | 297 ++++++------------ .../cpu/aarch64/vm/macroAssembler_aarch64.hpp | 12 +- 3 files changed, 118 insertions(+), 216 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index 18ba1e44cf3..e980a2332f3 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -14783,19 +14783,19 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, %} instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt, - iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr) + iRegI_R0 result, rFlagsReg cr) %{ predicate(!CompactStrings); match(Set result (StrEquals (Binary str1 str2) cnt)); - effect(KILL tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); - format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %} + format %{ "String Equals $str1,$str2,$cnt -> $result" %} ins_encode %{ // Count is in 8-bit bytes; non-Compact chars are 16 bits. __ asrw($cnt$$Register, $cnt$$Register, 1); - __ string_equals($str1$$Register, $str2$$Register, - $cnt$$Register, $result$$Register, - $tmp$$Register); + __ arrays_equals($str1$$Register, $str2$$Register, + $result$$Register, $cnt$$Register, + 2, /*is_string*/true); %} ins_pipe(pipe_class_memory); %} @@ -14809,9 +14809,10 @@ instruct array_equalsB(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %} ins_encode %{ - __ byte_arrays_equals($ary1$$Register, $ary2$$Register, - $result$$Register, $tmp$$Register); - %} + __ arrays_equals($ary1$$Register, $ary2$$Register, + $result$$Register, $tmp$$Register, + 1, /*is_string*/false); + %} ins_pipe(pipe_class_memory); %} @@ -14824,12 +14825,14 @@ instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %} ins_encode %{ - __ char_arrays_equals($ary1$$Register, $ary2$$Register, - $result$$Register, $tmp$$Register); + __ arrays_equals($ary1$$Register, $ary2$$Register, + $result$$Register, $tmp$$Register, + 2, /*is_string*/false); %} ins_pipe(pipe_class_memory); %} + // encode char[] to byte[] in ISO_8859_1 instruct encode_iso_array(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len, vRegD_V0 Vtmp1, vRegD_V1 Vtmp2, diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index 8c7f9465622..942518b116b 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -4481,225 +4481,126 @@ void MacroAssembler::string_compare(Register str1, Register str2, BLOCK_COMMENT("} string_compare"); } +// Compare Strings or char/byte arrays. -void MacroAssembler::string_equals(Register str1, Register str2, - Register cnt, Register result, - Register tmp1) { - Label SAME_CHARS, DONE, SHORT_LOOP, SHORT_STRING, - NEXT_WORD; +// is_string is true iff this is a string comparison. - const Register tmp2 = rscratch1; - assert_different_registers(str1, str2, cnt, result, tmp1, tmp2, rscratch2); +// For Strings we're passed the address of the first characters in a1 +// and a2 and the length in cnt1. - BLOCK_COMMENT("string_equals {"); +// For byte and char arrays we're passed the arrays themselves and we +// have to extract length fields and do null checks here. - // Start by assuming that the strings are not equal. - mov(result, zr); +// elem_size is the element size in bytes: either 1 or 2. - // A very short string - cmpw(cnt, 4); - br(Assembler::LT, SHORT_STRING); +// There are two implementations. For arrays >= 8 bytes, all +// comparisons (including the final one, which may overlap) are +// performed 8 bytes at a time. For arrays < 8 bytes, we compare a +// halfword, then a short, and then a byte. - // Check if the strings start at the same location. - cmp(str1, str2); - br(Assembler::EQ, SAME_CHARS); +void MacroAssembler::arrays_equals(Register a1, Register a2, + Register result, Register cnt1, + int elem_size, bool is_string) +{ + Label SAME, DONE, SHORT, NEXT_WORD, ONE; + Register tmp1 = rscratch1; + Register tmp2 = rscratch2; + Register cnt2 = tmp2; // cnt2 only used in array length compare + int elem_per_word = wordSize/elem_size; + int log_elem_size = exact_log2(elem_size); + int length_offset = arrayOopDesc::length_offset_in_bytes(); + int base_offset + = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); - // Compare longwords - { - subw(cnt, cnt, 4); // The last longword is a special case + assert(elem_size == 1 || elem_size == 2, "must be char or byte"); + assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2); - // Move both string pointers to the last longword of their - // strings, negate the remaining count, and convert it to bytes. - lea(str1, Address(str1, cnt, Address::uxtw(1))); - lea(str2, Address(str2, cnt, Address::uxtw(1))); - sub(cnt, zr, cnt, LSL, 1); + BLOCK_COMMENT(is_string ? "string_equals {" : "array_equals {"); - // Loop, loading longwords and comparing them into rscratch2. - bind(NEXT_WORD); - ldr(tmp1, Address(str1, cnt)); - ldr(tmp2, Address(str2, cnt)); - adds(cnt, cnt, wordSize); - eor(rscratch2, tmp1, tmp2); - cbnz(rscratch2, DONE); - br(Assembler::LT, NEXT_WORD); + mov(result, false); - // Last longword. In the case where length == 4 we compare the - // same longword twice, but that's still faster than another - // conditional branch. + if (!is_string) { + // if (a==a2) + // return true; + eor(rscratch1, a1, a2); + cbz(rscratch1, SAME); + // if (a==null || a2==null) + // return false; + cbz(a1, DONE); + cbz(a2, DONE); + // if (a1.length != a2.length) + // return false; + ldrw(cnt1, Address(a1, length_offset)); + ldrw(cnt2, Address(a2, length_offset)); + eorw(tmp1, cnt1, cnt2); + cbnzw(tmp1, DONE); - ldr(tmp1, Address(str1)); - ldr(tmp2, Address(str2)); - eor(rscratch2, tmp1, tmp2); - cbz(rscratch2, SAME_CHARS); - b(DONE); + lea(a1, Address(a1, base_offset)); + lea(a2, Address(a2, base_offset)); } - bind(SHORT_STRING); - // Is the length zero? - cbz(cnt, SAME_CHARS); - - bind(SHORT_LOOP); - load_unsigned_short(tmp1, Address(post(str1, 2))); - load_unsigned_short(tmp2, Address(post(str2, 2))); - subw(tmp1, tmp1, tmp2); + // Check for short strings, i.e. smaller than wordSize. + subs(cnt1, cnt1, elem_per_word); + br(Assembler::LT, SHORT); + // Main 8 byte comparison loop. + bind(NEXT_WORD); { + ldr(tmp1, Address(post(a1, wordSize))); + ldr(tmp2, Address(post(a2, wordSize))); + subs(cnt1, cnt1, elem_per_word); + eor(tmp1, tmp1, tmp2); + cbnz(tmp1, DONE); + } br(GT, NEXT_WORD); + // Last longword. In the case where length == 4 we compare the + // same longword twice, but that's still faster than another + // conditional branch. + // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when + // length == 4. + if (log_elem_size > 0) + lsl(cnt1, cnt1, log_elem_size); + ldr(tmp1, Address(a1, cnt1)); + ldr(tmp2, Address(a2, cnt1)); + eor(tmp1, tmp1, tmp2); cbnz(tmp1, DONE); - sub(cnt, cnt, 1); - cbnz(cnt, SHORT_LOOP); + b(SAME); - // Strings are equal. - bind(SAME_CHARS); + bind(SHORT); + Label TAIL03, TAIL01; + + tbz(cnt1, 2 - log_elem_size, TAIL03); // 0-7 bytes left. + { + ldrw(tmp1, Address(post(a1, 4))); + ldrw(tmp2, Address(post(a2, 4))); + eorw(tmp1, tmp1, tmp2); + cbnzw(tmp1, DONE); + } + bind(TAIL03); + tbz(cnt1, 1 - log_elem_size, TAIL01); // 0-3 bytes left. + { + ldrh(tmp1, Address(post(a1, 2))); + ldrh(tmp2, Address(post(a2, 2))); + eorw(tmp1, tmp1, tmp2); + cbnzw(tmp1, DONE); + } + bind(TAIL01); + if (elem_size == 1) { // Only needed when comparing byte arrays. + tbz(cnt1, 0, SAME); // 0-1 bytes left. + { + ldrb(tmp1, a1); + ldrb(tmp2, a2); + eorw(tmp1, tmp1, tmp2); + cbnzw(tmp1, DONE); + } + } + // Arrays are equal. + bind(SAME); mov(result, true); - // That's it + // That's it. bind(DONE); - - BLOCK_COMMENT("} string_equals"); + BLOCK_COMMENT(is_string ? "} string_equals" : "} array_equals"); } -void MacroAssembler::byte_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1) -{ - Register cnt1 = rscratch1; - Register cnt2 = rscratch2; - Register tmp2 = rscratch2; - - Label SAME, DIFFER, NEXT, TAIL07, TAIL03, TAIL01; - - int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); - - BLOCK_COMMENT("byte_arrays_equals {"); - - // different until proven equal - mov(result, false); - - // same array? - cmp(ary1, ary2); - br(Assembler::EQ, SAME); - - // ne if either null - cbz(ary1, DIFFER); - cbz(ary2, DIFFER); - - // lengths ne? - ldrw(cnt1, Address(ary1, length_offset)); - ldrw(cnt2, Address(ary2, length_offset)); - cmp(cnt1, cnt2); - br(Assembler::NE, DIFFER); - - lea(ary1, Address(ary1, base_offset)); - lea(ary2, Address(ary2, base_offset)); - - subs(cnt1, cnt1, 8); - br(LT, TAIL07); - - BIND(NEXT); - ldr(tmp1, Address(post(ary1, 8))); - ldr(tmp2, Address(post(ary2, 8))); - subs(cnt1, cnt1, 8); - eor(tmp1, tmp1, tmp2); - cbnz(tmp1, DIFFER); - br(GE, NEXT); - - BIND(TAIL07); // 0-7 bytes left, cnt1 = #bytes left - 4 - tst(cnt1, 0b100); - br(EQ, TAIL03); - ldrw(tmp1, Address(post(ary1, 4))); - ldrw(tmp2, Address(post(ary2, 4))); - cmp(tmp1, tmp2); - br(NE, DIFFER); - - BIND(TAIL03); // 0-3 bytes left, cnt1 = #bytes left - 4 - tst(cnt1, 0b10); - br(EQ, TAIL01); - ldrh(tmp1, Address(post(ary1, 2))); - ldrh(tmp2, Address(post(ary2, 2))); - cmp(tmp1, tmp2); - br(NE, DIFFER); - BIND(TAIL01); // 0-1 byte left - tst(cnt1, 0b01); - br(EQ, SAME); - ldrb(tmp1, ary1); - ldrb(tmp2, ary2); - cmp(tmp1, tmp2); - br(NE, DIFFER); - - BIND(SAME); - mov(result, true); - BIND(DIFFER); // result already set - - BLOCK_COMMENT("} byte_arrays_equals"); -} - -// Compare char[] arrays aligned to 4 bytes -void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1) -{ - Register cnt1 = rscratch1; - Register cnt2 = rscratch2; - Register tmp2 = rscratch2; - - Label SAME, DIFFER, NEXT, TAIL03, TAIL01; - - int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); - - BLOCK_COMMENT("char_arrays_equals {"); - - // different until proven equal - mov(result, false); - - // same array? - cmp(ary1, ary2); - br(Assembler::EQ, SAME); - - // ne if either null - cbz(ary1, DIFFER); - cbz(ary2, DIFFER); - - // lengths ne? - ldrw(cnt1, Address(ary1, length_offset)); - ldrw(cnt2, Address(ary2, length_offset)); - cmp(cnt1, cnt2); - br(Assembler::NE, DIFFER); - - lea(ary1, Address(ary1, base_offset)); - lea(ary2, Address(ary2, base_offset)); - - subs(cnt1, cnt1, 4); - br(LT, TAIL03); - - BIND(NEXT); - ldr(tmp1, Address(post(ary1, 8))); - ldr(tmp2, Address(post(ary2, 8))); - subs(cnt1, cnt1, 4); - eor(tmp1, tmp1, tmp2); - cbnz(tmp1, DIFFER); - br(GE, NEXT); - - BIND(TAIL03); // 0-3 chars left, cnt1 = #chars left - 4 - tst(cnt1, 0b10); - br(EQ, TAIL01); - ldrw(tmp1, Address(post(ary1, 4))); - ldrw(tmp2, Address(post(ary2, 4))); - cmp(tmp1, tmp2); - br(NE, DIFFER); - BIND(TAIL01); // 0-1 chars left - tst(cnt1, 0b01); - br(EQ, SAME); - ldrh(tmp1, ary1); - ldrh(tmp2, ary2); - cmp(tmp1, tmp2); - br(NE, DIFFER); - - BIND(SAME); - mov(result, true); - BIND(DIFFER); // result already set - - BLOCK_COMMENT("} char_arrays_equals"); -} - // encode char[] to byte[] in ISO_8859_1 void MacroAssembler::encode_iso_array(Register src, Register dst, Register len, Register result, diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp index d22c581bc41..e042b5055eb 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -1186,13 +1186,11 @@ public: void string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register result, Register tmp1); - void string_equals(Register str1, Register str2, - Register cnt, Register result, - Register tmp1); - void char_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1); - void byte_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1); + + void arrays_equals(Register a1, Register a2, + Register result, Register cnt1, + int elem_size, bool is_string); + void encode_iso_array(Register src, Register dst, Register len, Register result, FloatRegister Vtmp1, FloatRegister Vtmp2, From a30c46aa74610773458947247315459e487ec9f3 Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Wed, 17 Feb 2016 20:19:24 +0800 Subject: [PATCH 031/311] 8150038: aarch64: make use of CBZ and CBNZ when comparing narrow pointer with zero Aarch64: c2 make use of CBZ and CBNZ when comparing narrow pointer with zero Reviewed-by: aph --- hotspot/src/cpu/aarch64/vm/aarch64.ad | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index e980a2332f3..8483c709564 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -14191,6 +14191,25 @@ instruct cmpP_imm0_branch(cmpOp cmp, iRegP op1, immP0 op2, label labl, rFlagsReg ins_pipe(pipe_cmp_branch); %} +instruct cmpN_imm0_branch(cmpOp cmp, iRegN op1, immN0 op2, label labl, rFlagsReg cr) %{ + match(If cmp (CmpN op1 op2)); + predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne + || n->in(1)->as_Bool()->_test._test == BoolTest::eq); + effect(USE labl); + + ins_cost(BRANCH_COST); + format %{ "cbw$cmp $op1, $labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; + if (cond == Assembler::EQ) + __ cbzw($op1$$Register, *L); + else + __ cbnzw($op1$$Register, *L); + %} + ins_pipe(pipe_cmp_branch); +%} + instruct cmpP_narrowOop_imm0_branch(cmpOp cmp, iRegN oop, immP0 zero, label labl, rFlagsReg cr) %{ match(If cmp (CmpP (DecodeN oop) zero)); predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne From 410f75949f5dd91000130189111d86ec62adfb68 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Wed, 17 Feb 2016 18:49:38 +0300 Subject: [PATCH 032/311] 8148518: Unsafe.getCharUnaligned() loads aren't folded in case of -XX:-UseUnalignedAccesses Reviewed-by: kvn, shade --- .../java.base/share/classes/jdk/internal/misc/Unsafe.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index f130d383a84..e48e4ef9d6a 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -1159,7 +1159,12 @@ public final class Unsafe { /** @see #getLongUnaligned(Object, long) */ @HotSpotIntrinsicCandidate public final char getCharUnaligned(Object o, long offset) { - return (char)getShortUnaligned(o, offset); + if ((offset & 1) == 0) { + return getChar(o, offset); + } else { + return (char)makeShort(getByte(o, offset), + getByte(o, offset + 1)); + } } /** @see #getLongUnaligned(Object, long, boolean) */ From 92f9c27eec3b37339e9f1b04d920e155a3fb90fe Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Wed, 17 Feb 2016 14:03:18 -0500 Subject: [PATCH 033/311] 8148630: Convert TraceStartupTime to Unified Logging The former -XX:+TraceStartupTime flag has been converted to the UL option -Xlog:startuptime=info Reviewed-by: coleenp, dholmes --- .../share/vm/interpreter/cppInterpreter.cpp | 3 +- .../vm/interpreter/templateInterpreter.cpp | 3 +- .../share/vm/interpreter/templateTable.cpp | 5 +- hotspot/src/share/vm/logging/logTag.hpp | 3 +- .../src/share/vm/memory/metaspaceShared.cpp | 144 +++++++++--------- hotspot/src/share/vm/memory/universe.cpp | 5 +- hotspot/src/share/vm/prims/methodHandles.cpp | 5 +- hotspot/src/share/vm/runtime/globals.hpp | 3 - hotspot/src/share/vm/runtime/logTimer.hpp | 43 ++++++ hotspot/src/share/vm/runtime/stubRoutines.cpp | 8 +- hotspot/src/share/vm/runtime/thread.cpp | 12 +- hotspot/src/share/vm/runtime/timer.cpp | 35 +++-- hotspot/src/share/vm/runtime/timer.hpp | 12 +- .../test/runtime/logging/StartupTimeTest.java | 68 +++++++++ 14 files changed, 242 insertions(+), 107 deletions(-) create mode 100644 hotspot/src/share/vm/runtime/logTimer.hpp create mode 100644 hotspot/test/runtime/logging/StartupTimeTest.java diff --git a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp index cbcfccbd759..2dcef77ef53 100644 --- a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp @@ -27,6 +27,7 @@ #include "interpreter/cppInterpreterGenerator.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" +#include "runtime/logTimer.hpp" #ifdef CC_INTERP @@ -42,7 +43,7 @@ void CppInterpreter::initialize() { // generate interpreter { ResourceMark rm; - TraceTime timer("Interpreter generation", TraceStartupTime); + TraceStartupTime timer("Interpreter generation"); int code_size = InterpreterCodeSize; NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp index c68f6858da6..8c2363be0d8 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp @@ -31,6 +31,7 @@ #include "interpreter/templateInterpreterGenerator.hpp" #include "interpreter/templateTable.hpp" #include "memory/resourceArea.hpp" +#include "runtime/logTimer.hpp" #ifndef CC_INTERP @@ -48,7 +49,7 @@ void TemplateInterpreter::initialize() { // generate interpreter { ResourceMark rm; - TraceTime timer("Interpreter generation", TraceStartupTime); + TraceStartupTime timer("Interpreter generation"); int code_size = InterpreterCodeSize; NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space #if INCLUDE_JVMTI diff --git a/hotspot/src/share/vm/interpreter/templateTable.cpp b/hotspot/src/share/vm/interpreter/templateTable.cpp index ddd7fc6470c..c71ebd28263 100644 --- a/hotspot/src/share/vm/interpreter/templateTable.cpp +++ b/hotspot/src/share/vm/interpreter/templateTable.cpp @@ -26,8 +26,7 @@ #include "gc/shared/collectedHeap.hpp" #include "interpreter/interp_masm.hpp" #include "interpreter/templateTable.hpp" -#include "runtime/timer.hpp" - +#include "runtime/logTimer.hpp" #ifdef CC_INTERP @@ -246,7 +245,7 @@ void TemplateTable::initialize() { if (_is_initialized) return; // Initialize table - TraceTime timer("TemplateTable initialization", TraceStartupTime); + TraceStartupTime timer("TemplateTable initialization"); _bs = Universe::heap()->barrier_set(); diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index d4ff40bd0dd..b4b72f20cfe 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -73,6 +73,7 @@ LOG_TAG(scavenge) \ LOG_TAG(scrub) \ LOG_TAG(start) \ + LOG_TAG(startuptime) \ LOG_TAG(state) \ LOG_TAG(stats) \ LOG_TAG(stringdedup) \ diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index d71f9292511..3f10488bf7f 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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,7 @@ #include "memory/metaspaceShared.hpp" #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" +#include "runtime/logTimer.hpp" #include "runtime/os.hpp" #include "runtime/signature.hpp" #include "runtime/vmThread.hpp" @@ -771,88 +772,89 @@ void MetaspaceShared::prepare_for_dumping() { // Preload classes from a list, populate the shared spaces and dump to a // file. void MetaspaceShared::preload_and_dump(TRAPS) { - TraceTime timer("Dump Shared Spaces", TraceStartupTime); - ResourceMark rm; - char class_list_path_str[JVM_MAXPATHLEN]; + { TraceStartupTime timer("Dump Shared Spaces"); + ResourceMark rm; + char class_list_path_str[JVM_MAXPATHLEN]; - tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT, - MetaspaceShared::shared_rs()->size(), - p2i(MetaspaceShared::shared_rs()->base())); + tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT, + MetaspaceShared::shared_rs()->size(), + p2i(MetaspaceShared::shared_rs()->base())); - // Preload classes to be shared. - // Should use some os:: method rather than fopen() here. aB. - const char* class_list_path; - if (SharedClassListFile == NULL) { - // Construct the path to the class list (in jre/lib) - // Walk up two directories from the location of the VM and - // optionally tack on "lib" (depending on platform) - os::jvm_path(class_list_path_str, sizeof(class_list_path_str)); - for (int i = 0; i < 3; i++) { - char *end = strrchr(class_list_path_str, *os::file_separator()); - if (end != NULL) *end = '\0'; - } - int class_list_path_len = (int)strlen(class_list_path_str); - if (class_list_path_len >= 3) { - if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) { - if (class_list_path_len < JVM_MAXPATHLEN - 4) { - jio_snprintf(class_list_path_str + class_list_path_len, - sizeof(class_list_path_str) - class_list_path_len, - "%slib", os::file_separator()); - class_list_path_len += 4; + // Preload classes to be shared. + // Should use some os:: method rather than fopen() here. aB. + const char* class_list_path; + if (SharedClassListFile == NULL) { + // Construct the path to the class list (in jre/lib) + // Walk up two directories from the location of the VM and + // optionally tack on "lib" (depending on platform) + os::jvm_path(class_list_path_str, sizeof(class_list_path_str)); + for (int i = 0; i < 3; i++) { + char *end = strrchr(class_list_path_str, *os::file_separator()); + if (end != NULL) *end = '\0'; + } + int class_list_path_len = (int)strlen(class_list_path_str); + if (class_list_path_len >= 3) { + if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) { + if (class_list_path_len < JVM_MAXPATHLEN - 4) { + jio_snprintf(class_list_path_str + class_list_path_len, + sizeof(class_list_path_str) - class_list_path_len, + "%slib", os::file_separator()); + class_list_path_len += 4; + } } } + if (class_list_path_len < JVM_MAXPATHLEN - 10) { + jio_snprintf(class_list_path_str + class_list_path_len, + sizeof(class_list_path_str) - class_list_path_len, + "%sclasslist", os::file_separator()); + } + class_list_path = class_list_path_str; + } else { + class_list_path = SharedClassListFile; } - if (class_list_path_len < JVM_MAXPATHLEN - 10) { - jio_snprintf(class_list_path_str + class_list_path_len, - sizeof(class_list_path_str) - class_list_path_len, - "%sclasslist", os::file_separator()); - } - class_list_path = class_list_path_str; - } else { - class_list_path = SharedClassListFile; - } - int class_count = 0; - GrowableArray* class_promote_order = new GrowableArray(); + int class_count = 0; + GrowableArray* class_promote_order = new GrowableArray(); - // sun.io.Converters - static const char obj_array_sig[] = "[[Ljava/lang/Object;"; - SymbolTable::new_permanent_symbol(obj_array_sig, THREAD); + // sun.io.Converters + static const char obj_array_sig[] = "[[Ljava/lang/Object;"; + SymbolTable::new_permanent_symbol(obj_array_sig, THREAD); - // java.util.HashMap - static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; - SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD); + // java.util.HashMap + static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; + SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD); - // Need to allocate the op here: - // op.misc_data_space_alloc() will be called during preload_and_dump(). - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); - VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); + // Need to allocate the op here: + // op.misc_data_space_alloc() will be called during preload_and_dump(). + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); - tty->print_cr("Loading classes to share ..."); - _has_error_classes = false; - class_count += preload_and_dump(class_list_path, class_promote_order, - THREAD); - if (ExtraSharedClassListFile) { - class_count += preload_and_dump(ExtraSharedClassListFile, class_promote_order, + tty->print_cr("Loading classes to share ..."); + _has_error_classes = false; + class_count += preload_and_dump(class_list_path, class_promote_order, THREAD); + if (ExtraSharedClassListFile) { + class_count += preload_and_dump(ExtraSharedClassListFile, class_promote_order, + THREAD); + } + tty->print_cr("Loading classes to share: done."); + + if (PrintSharedSpaces) { + tty->print_cr("Shared spaces: preloaded %d classes", class_count); + } + + // Rewrite and link classes + tty->print_cr("Rewriting and linking classes ..."); + + // Link any classes which got missed. This would happen if we have loaded classes that + // were not explicitly specified in the classlist. E.g., if an interface implemented by class K + // fails verification, all other interfaces that were not specified in the classlist but + // are implemented by K are not verified. + link_and_cleanup_shared_classes(CATCH); + tty->print_cr("Rewriting and linking classes: done"); + + VMThread::execute(&op); } - tty->print_cr("Loading classes to share: done."); - - if (PrintSharedSpaces) { - tty->print_cr("Shared spaces: preloaded %d classes", class_count); - } - - // Rewrite and link classes - tty->print_cr("Rewriting and linking classes ..."); - - // Link any classes which got missed. This would happen if we have loaded classes that - // were not explicitly specified in the classlist. E.g., if an interface implemented by class K - // fails verification, all other interfaces that were not specified in the classlist but - // are implemented by K are not verified. - link_and_cleanup_shared_classes(CATCH); - tty->print_cr("Rewriting and linking classes: done"); - - VMThread::execute(&op); // Since various initialization steps have been undone by this process, // it is not reasonable to continue running a java process. exit(0); diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index ac36a988d97..3a7945768e8 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -64,6 +64,7 @@ #include "runtime/init.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/logTimer.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.inline.hpp" @@ -626,7 +627,9 @@ jint universe_init() { guarantee(sizeof(oop) >= sizeof(HeapWord), "HeapWord larger than oop?"); guarantee(sizeof(oop) % sizeof(HeapWord) == 0, "oop size is not not a multiple of HeapWord size"); - TraceTime timer("Genesis", TraceStartupTime); + + TraceStartupTime timer("Genesis"); + JavaClasses::compute_hard_coded_offsets(); jint status = Universe::initialize_heap(); diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 00c33b644d3..24370f4c165 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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,7 @@ #include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/compilationPolicy.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/logTimer.hpp" #include "runtime/reflection.hpp" #include "runtime/signature.hpp" #include "runtime/stubRoutines.hpp" @@ -76,7 +77,7 @@ bool MethodHandles::generate_adapters() { assert(_adapter_code == NULL, "generate only once"); ResourceMark rm; - TraceTime timer("MethodHandles adapters generation", TraceStartupTime); + TraceStartupTime timer("MethodHandles adapters generation"); _adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size); if (_adapter_code == NULL) { return false; diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index a15ea7db325..86cd7328dd2 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1482,9 +1482,6 @@ public: develop(bool, TraceCompiledIC, false, \ "Trace changes of compiled IC") \ \ - develop(bool, TraceStartupTime, false, \ - "Trace setup time") \ - \ develop(bool, TraceProtectionDomainVerification, false, \ "Trace protection domain verification") \ \ diff --git a/hotspot/src/share/vm/runtime/logTimer.hpp b/hotspot/src/share/vm/runtime/logTimer.hpp new file mode 100644 index 00000000000..81bbd085eb3 --- /dev/null +++ b/hotspot/src/share/vm/runtime/logTimer.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 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. + * + */ + +#ifndef SHARE_VM_RUNTIME_LOG_TIMER_HPP +#define SHARE_VM_RUNTIME_LOG_TIMER_HPP + +#include "logging/log.hpp" +#include "runtime/timer.hpp" + +// TraceStartupTime is used for tracing the execution time of a block with logging +// Usage: +// { TraceStartupTime t("block time") +// some_code(); +// } +// + +class TraceStartupTime : public TraceTime { + public: + TraceStartupTime(const char* s) : TraceTime(s, log_is_enabled(Info, startuptime), LogTag::_startuptime) {} +}; + +#endif // SHARE_VM_RUNTIME_LOG_TIMER_HPP diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp index 0f2c5b65e17..71080e5b76c 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -28,9 +28,9 @@ #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/interfaceSupport.hpp" +#include "runtime/logTimer.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#include "runtime/timer.hpp" #include "utilities/copy.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" @@ -183,7 +183,7 @@ extern void StubGenerator_generate(CodeBuffer* code, bool all); // only interfac void StubRoutines::initialize1() { if (_code1 == NULL) { ResourceMark rm; - TraceTime timer("StubRoutines generation 1", TraceStartupTime); + TraceStartupTime timer("StubRoutines generation 1"); _code1 = BufferBlob::create("StubRoutines (1)", code_size1); if (_code1 == NULL) { vm_exit_out_of_memory(code_size1, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (1)"); @@ -276,7 +276,7 @@ static void test_safefetchN() { void StubRoutines::initialize2() { if (_code2 == NULL) { ResourceMark rm; - TraceTime timer("StubRoutines generation 2", TraceStartupTime); + TraceStartupTime timer("StubRoutines generation 2"); _code2 = BufferBlob::create("StubRoutines (2)", code_size2); if (_code2 == NULL) { vm_exit_out_of_memory(code_size2, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (2)"); diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index b0fca00705a..5b9faf084d3 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -67,6 +67,7 @@ #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniPeriodicChecker.hpp" +#include "runtime/logTimer.hpp" #include "runtime/memprofiler.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" @@ -3341,7 +3342,7 @@ void Threads::threads_do(ThreadClosure* tc) { } void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { - TraceTime timer("Initialize java.lang classes", TraceStartupTime); + TraceStartupTime timer("Initialize java.lang classes"); if (EagerXrunInit && Arguments::init_libraries_at_startup()) { create_vm_init_libraries(); @@ -3388,6 +3389,8 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { } void Threads::initialize_jsr292_core_classes(TRAPS) { + TraceStartupTime timer("Initialize java.lang.invoke classes"); + initialize_class(vmSymbols::java_lang_invoke_MethodHandle(), CHECK); initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK); initialize_class(vmSymbols::java_lang_invoke_MethodHandleNatives(), CHECK); @@ -3457,7 +3460,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { HOTSPOT_VM_INIT_BEGIN(); // Timing (must come after argument parsing) - TraceTime timer("Create VM", TraceStartupTime); + TraceStartupTime timer("Create VM"); // Initialize the os module after parsing the args jint os_init_2_result = os::init_2(); @@ -3542,8 +3545,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { JvmtiExport::transition_pending_onload_raw_monitors(); // Create the VMThread - { TraceTime timer("Start VMThread", TraceStartupTime); - VMThread::create(); + { TraceStartupTime timer("Start VMThread"); + + VMThread::create(); Thread* vmthread = VMThread::vm_thread(); if (!os::create_thread(vmthread, os::vm_thread)) { diff --git a/hotspot/src/share/vm/runtime/timer.cpp b/hotspot/src/share/vm/runtime/timer.cpp index ec4ec0fa662..dddf328b302 100644 --- a/hotspot/src/share/vm/runtime/timer.cpp +++ b/hotspot/src/share/vm/runtime/timer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ */ #include "precompiled.hpp" +#include "logging/log.hpp" #include "oops/oop.inline.hpp" #include "runtime/timer.hpp" #include "utilities/ostream.hpp" @@ -114,14 +115,15 @@ jlong TimeStamp::ticks_since_update() const { } TraceTime::TraceTime(const char* title, - bool doit) { + bool doit, + LogTagType tag) { _active = doit; _verbose = true; + _tag = tag; + _title = title; if (_active) { _accum = NULL; - tty->print("[%s", title); - tty->flush(); _t.start(); } } @@ -129,14 +131,14 @@ TraceTime::TraceTime(const char* title, TraceTime::TraceTime(const char* title, elapsedTimer* accumulator, bool doit, - bool verbose) { - _active = doit; - _verbose = verbose; + bool verbose, + LogTagType tag) { + _active = doit; + _verbose = verbose; + _tag = tag; + _title = title; + if (_active) { - if (_verbose) { - tty->print("[%s", title); - tty->flush(); - } _accum = accumulator; _t.start(); } @@ -147,8 +149,15 @@ TraceTime::~TraceTime() { _t.stop(); if (_accum!=NULL) _accum->add(_t); if (_verbose) { - tty->print_cr(", %3.7f secs]", _t.seconds()); - tty->flush(); + switch (_tag) { + case LogTag::_startuptime : + log_info(startuptime)("%s, %3.7f secs", _title, _t.seconds()); + break; + case LogTag::__NO_TAG : + default : + tty->print_cr("[%s, %3.7f secs]", _title, _t.seconds()); + tty->flush(); + } } } } diff --git a/hotspot/src/share/vm/runtime/timer.hpp b/hotspot/src/share/vm/runtime/timer.hpp index bd003eb40e6..c14e2522917 100644 --- a/hotspot/src/share/vm/runtime/timer.hpp +++ b/hotspot/src/share/vm/runtime/timer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_RUNTIME_TIMER_HPP #define SHARE_VM_RUNTIME_TIMER_HPP +#include "logging/logTag.hpp" #include "utilities/globalDefinitions.hpp" // Timers for simple measurement. @@ -85,14 +86,19 @@ class TraceTime: public StackObj { bool _verbose; // report every timing elapsedTimer _t; // timer elapsedTimer* _accum; // accumulator + const char* _title; // name of timer + LogTagType _tag; // stream to print to + public: // Constructors TraceTime(const char* title, - bool doit = true); + bool doit = true, + LogTagType tag = LogTag::__NO_TAG); TraceTime(const char* title, elapsedTimer* accumulator, bool doit = true, - bool verbose = false); + bool verbose = false, + LogTagType tag = LogTag::__NO_TAG); ~TraceTime(); // Accessors diff --git a/hotspot/test/runtime/logging/StartupTimeTest.java b/hotspot/test/runtime/logging/StartupTimeTest.java new file mode 100644 index 00000000000..1c8c0a0f87f --- /dev/null +++ b/hotspot/test/runtime/logging/StartupTimeTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, 2016, 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 8148630 + * @summary -Xlog:startuptime should produce logging from the source code + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver StartupTimeTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; + +public class StartupTimeTest { + static void analyzeOutputOn(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldMatch("(Genesis, [0-9]+.[0-9]+ secs)"); + output.shouldMatch("(Start VMThread, [0-9]+.[0-9]+ secs)"); + output.shouldMatch("(Create VM, [0-9]+.[0-9]+ secs)"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputOff(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("[startuptime]"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:startuptime", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:startuptime=off", + InnerClass.class.getName()); + analyzeOutputOff(pb); + } + + public static class InnerClass { + public static void main(String[] args) throws Exception { + System.out.println("Testing startuptime."); + } + } +} From 7c684d52497b1ad72ecedfda0a6bfd14ce2bd1d8 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 17 Feb 2016 16:00:27 -0500 Subject: [PATCH 034/311] 8149793: DirtyCardQueueSet::apply_closure_to_completed_buffer_helper isn't helpful Merge helper into sole caller. Reviewed-by: brutisso, jwilhelm, tschatzl --- .../vm/gc/g1/concurrentG1RefineThread.cpp | 5 ++- hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp | 45 ++++++++----------- hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp | 13 ++---- 3 files changed, 27 insertions(+), 36 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index dc1b5ea1352..df9de0ee337 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -154,7 +154,10 @@ void ConcurrentG1RefineThread::run_service() { if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { _next->activate(); } - } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, _worker_id + _worker_id_offset, cg1r()->green_zone())); + } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, + _worker_id + _worker_id_offset, + cg1r()->green_zone(), + false /* during_pause */)); // We can exit the loop above while being active if there was a yield request. if (is_active()) { diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp index 155faa0be5a..4c33fb9b211 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -228,37 +228,30 @@ BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) { return nd; } -bool DirtyCardQueueSet::apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - uint worker_i, - BufferNode* nd) { - if (nd != NULL) { - void **buf = BufferNode::make_buffer_from_node(nd); - size_t index = nd->index(); - bool b = - DirtyCardQueue::apply_closure_to_buffer(cl, buf, - index, _sz, - true, worker_i); - if (b) { - deallocate_buffer(buf); - return true; // In normal case, go on to next buffer. - } else { - enqueue_complete_buffer(buf, index); - return false; - } - } else { - return false; - } -} - bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, uint worker_i, int stop_at, bool during_pause) { assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); BufferNode* nd = get_completed_buffer(stop_at); - bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd); - if (res) Atomic::inc(&_processed_buffers_rs_thread); - return res; + if (nd == NULL) { + return false; + } else { + void** buf = BufferNode::make_buffer_from_node(nd); + size_t index = nd->index(); + if (DirtyCardQueue::apply_closure_to_buffer(cl, + buf, index, _sz, + true, worker_i)) { + // Done with fully processed buffer. + deallocate_buffer(buf); + Atomic::inc(&_processed_buffers_rs_thread); + return true; + } else { + // Return partially processed buffer to the queue. + enqueue_complete_buffer(buf, index); + return false; + } + } } void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) { diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp index 9fa3c3da069..17c92bb8ecf 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -133,14 +133,9 @@ public: // partially completed buffer (with its processed elements set to NULL) // is returned to the completed buffer set, and this call returns false. bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl, - uint worker_i = 0, - int stop_at = 0, - bool during_pause = false); - - // Helper routine for the above. - bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - uint worker_i, - BufferNode* nd); + uint worker_i, + int stop_at, + bool during_pause); BufferNode* get_completed_buffer(int stop_at); From 3a99569b6f6c3b712ef4b74a561f00861bba4111 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 17 Feb 2016 17:03:31 -0500 Subject: [PATCH 035/311] 8143245: Zero build requires disabled warnings Reviewed-by: dholmes, coleenp --- hotspot/make/linux/makefiles/zeroshark.make | 8 +------- hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp | 2 +- hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp | 4 ++-- .../src/os_cpu/linux_zero/vm/os_linux_zero.cpp | 17 ++++++++++++++--- .../os_cpu/linux_zero/vm/thread_linux_zero.hpp | 3 ++- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/hotspot/make/linux/makefiles/zeroshark.make b/hotspot/make/linux/makefiles/zeroshark.make index 240946fee3a..4f9a70c98fa 100644 --- a/hotspot/make/linux/makefiles/zeroshark.make +++ b/hotspot/make/linux/makefiles/zeroshark.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # Copyright 2007, 2008 Red Hat, Inc. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -29,12 +29,6 @@ ifeq ($(USE_CLANG), true) WARNING_FLAGS += -Wno-undef endif -# Suppress some warning flags that are normally turned on for hotspot, -# because some of the zero code has not been updated accordingly. -WARNING_FLAGS += -Wno-return-type \ - -Wno-format-nonliteral -Wno-format-security \ - -Wno-maybe-uninitialized - # The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT) diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 387733de06d..4dc68335b6a 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -773,7 +773,7 @@ InterpreterFrame *InterpreterFrame::build(int size, TRAPS) { } BasicType CppInterpreter::result_type_of(Method* method) { - BasicType t; + BasicType t = T_ILLEGAL; // silence compiler warnings switch (method->result_index()) { case 0 : t = T_BOOLEAN; break; case 1 : t = T_CHAR; break; diff --git a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp index 8fb45375262..2e2dc3cab60 100644 --- a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp +++ b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -62,7 +62,7 @@ void InterpreterRuntime::SignatureHandlerGeneratorBase::pass_object() { } void InterpreterRuntime::SignatureHandlerGeneratorBase::push(BasicType type) { - ffi_type *ftype; + ffi_type *ftype = NULL; switch (type) { case T_VOID: ftype = &ffi_type_void; diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp index f57f89ad02f..b1e93a82dc8 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -65,6 +65,7 @@ address os::current_stack_pointer() { frame os::get_sender_for_C_frame(frame* fr) { ShouldNotCallThis(); + return frame(NULL, NULL); // silence compile warning. } frame os::current_frame() { @@ -102,6 +103,7 @@ void os::initialize_thread(Thread * thr){ address os::Linux::ucontext_get_pc(const ucontext_t* uc) { ShouldNotCallThis(); + return NULL; // silence compile warnings } void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) { @@ -112,10 +114,12 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { ShouldNotCallThis(); + return NULL; // silence compile warnings } frame os::fetch_frame_from_context(const void* ucVoid) { ShouldNotCallThis(); + return frame(NULL, NULL); // silence compile warnings } extern "C" JNIEXPORT int @@ -262,11 +266,16 @@ JVM_handle_linux_signal(int sig, } #endif // !PRODUCT - const char *fmt = "caught unhandled signal %d"; char buf[64]; - sprintf(buf, fmt, sig); + sprintf(buf, "caught unhandled signal %d", sig); + +// Silence -Wformat-security warning for fatal() +PRAGMA_DIAG_PUSH +PRAGMA_FORMAT_NONLITERAL_IGNORED fatal(buf); +PRAGMA_DIAG_POP + return true; // silence compiler warnings } void os::Linux::init_thread_fpu_state(void) { @@ -275,6 +284,7 @@ void os::Linux::init_thread_fpu_state(void) { int os::Linux::get_fpu_control_word() { ShouldNotCallThis(); + return -1; // silence compile warnings } void os::Linux::set_fpu_control_word(int fpu) { @@ -419,6 +429,7 @@ void os::print_register_info(outputStream *st, const void *context) { extern "C" { int SpinPause() { + return -1; // silence compile warnings } diff --git a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp index 39f77f858d0..b9c73dc48c1 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -110,6 +110,7 @@ void* ucontext, bool isInJava) { ShouldNotCallThis(); + return false; // silence compile warning } // These routines are only used on cpu architectures that From a5c5a3b6096b9248db46d028128b973e51ccdce7 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 17 Feb 2016 22:17:49 -0500 Subject: [PATCH 036/311] 8150079: MSVC prior to VS 2013 doesn't know the 'va_copy' macro Reviewed-by: dholmes --- hotspot/src/share/vm/prims/jni.cpp | 6 ------ hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp | 2 ++ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index d4808682944..419963ef412 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -930,13 +930,7 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { _arguments->push_oop(Handle((oop *)l, false)); } inline void set_ap(va_list rap) { -#ifdef va_copy va_copy(_ap, rap); -#elif defined (__va_copy) - __va_copy(_ap, rap); -#else - _ap = rap; -#endif } public: diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp index f594bafbc2f..038f348a434 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp @@ -174,6 +174,8 @@ const jlong max_jlong = CONST64(0x7fffffffffffffff); #if _MSC_VER < 1800 // Visual Studio 2013 introduced strtoull(); before, one has to use _strtoui64() instead. #define strtoull _strtoui64 +// Visual Studio prior to 2013 had no va_copy, but could safely copy va_list by assignement +#define va_copy(dest, src) dest = src // Fixes some wrong warnings about 'this' : used in base member initializer list #pragma warning( disable : 4355 ) #endif From af854404be490ce59847fc0e502ec24366279806 Mon Sep 17 00:00:00 2001 From: Alexander Kulyakhtin Date: Thu, 18 Feb 2016 14:56:53 +0300 Subject: [PATCH 037/311] 8150067: Quarantine serviceability/tmtools/jstat/GcCapacityTest.java Quarantine a falsely failing test until the test issue is fixed Reviewed-by: sla --- hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java index 3b63e0210d1..6ec4db9829b 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java @@ -27,6 +27,7 @@ import utils.*; * @test * @summary Test checks the consistency of the output * displayed with jstat -gccapacity. + * @ignore 8149778 * @library /test/lib/share/classes * @library ../share * @requires vm.opt.ExplicitGCInvokesConcurrent != true From 3cf4e3909cb5592b657c7f271274dae75889ff65 Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Thu, 18 Feb 2016 17:10:48 -0500 Subject: [PATCH 038/311] 8149383: Convert TraceBiasedLocking to Unified Logging The former -XX:+TraceBiasedLocking flag has been converted to the UL option -Xlog:biasedlocking=info and =trace, with the old option being aliased. Reviewed-by: dholmes, dcubed --- hotspot/src/share/vm/logging/logTag.hpp | 1 + hotspot/src/share/vm/runtime/arguments.cpp | 1 + .../src/share/vm/runtime/biasedLocking.cpp | 121 ++++++++++-------- hotspot/src/share/vm/runtime/globals.hpp | 3 - hotspot/src/share/vm/runtime/thread.cpp | 9 +- .../runtime/logging/BiasedLockingTest.java | 78 +++++++++++ 6 files changed, 153 insertions(+), 60 deletions(-) create mode 100644 hotspot/test/runtime/logging/BiasedLockingTest.java diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index b4b72f20cfe..60e39f710f5 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -34,6 +34,7 @@ LOG_TAG(alloc) \ LOG_TAG(age) \ LOG_TAG(barrier) \ + LOG_TAG(biasedlocking) \ LOG_TAG(bot) \ LOG_TAG(census) \ LOG_TAG(classhisto) \ diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index fc891394d4a..f43a7a1372f 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -409,6 +409,7 @@ static AliasedLoggingFlag const aliased_logging_flags[] = { { "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve }, { "TraceExceptions", LogLevel::Info, true, LogTag::_exceptions }, { "TraceMonitorInflation", LogLevel::Debug, true, LogTag::_monitorinflation }, + { "TraceBiasedLocking", LogLevel::Info, true, LogTag::_biasedlocking }, { NULL, LogLevel::Off, false, LogTag::__NO_TAG } }; diff --git a/hotspot/src/share/vm/runtime/biasedLocking.cpp b/hotspot/src/share/vm/runtime/biasedLocking.cpp index c02d232139b..1be0d111e56 100644 --- a/hotspot/src/share/vm/runtime/biasedLocking.cpp +++ b/hotspot/src/share/vm/runtime/biasedLocking.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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,8 @@ */ #include "precompiled.hpp" +#include "logging/log.hpp" +#include "memory/resourceArea.hpp" #include "oops/klass.inline.hpp" #include "oops/markOop.hpp" #include "oops/oop.inline.hpp" @@ -60,9 +62,7 @@ class VM_EnableBiasedLocking: public VM_Operation { // Indicate that future instances should enable it as well _biased_locking_enabled = true; - if (TraceBiasedLocking) { - tty->print_cr("Biased locking enabled"); - } + log_info(biasedlocking)("Biased locking enabled"); } bool allow_nested_vm_operations() const { return false; } @@ -144,14 +144,14 @@ static GrowableArray* get_or_compute_monitor_info(JavaThread* thre return info; } - static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) { markOop mark = obj->mark(); if (!mark->has_bias_pattern()) { - if (TraceBiasedLocking) { + if (log_is_enabled(Info, biasedlocking)) { ResourceMark rm; - tty->print_cr(" (Skipping revocation of object of type %s because it's no longer biased)", - obj->klass()->external_name()); + log_info(biasedlocking)(" (Skipping revocation of object of type %s " + "because it's no longer biased)", + obj->klass()->external_name()); } return BiasedLocking::NOT_BIASED; } @@ -160,10 +160,29 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ markOop biased_prototype = markOopDesc::biased_locking_prototype()->set_age(age); markOop unbiased_prototype = markOopDesc::prototype()->set_age(age); - if (TraceBiasedLocking && (Verbose || !is_bulk)) { + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { ResourceMark rm; - tty->print_cr("Revoking bias of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT " , allow rebias %d , requesting thread " INTPTR_FORMAT, - p2i((void *)obj), (intptr_t) mark, obj->klass()->external_name(), (intptr_t) obj->klass()->prototype_header(), (allow_rebias ? 1 : 0), (intptr_t) requesting_thread); + log_info(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark " + INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT + " , allow rebias %d , requesting thread " INTPTR_FORMAT, + p2i((void *)obj), + (intptr_t) mark, + obj->klass()->external_name(), + (intptr_t) obj->klass()->prototype_header(), + (allow_rebias ? 1 : 0), + (intptr_t) requesting_thread); + } else { + ResourceMark rm; + log_trace(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark " + INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT + " , allow rebias %d , requesting thread " INTPTR_FORMAT, + p2i((void *)obj), + (intptr_t) mark, + obj->klass()->external_name(), + (intptr_t) obj->klass()->prototype_header(), + (allow_rebias ? 1 : 0), + (intptr_t) requesting_thread); } JavaThread* biased_thread = mark->biased_locker(); @@ -174,8 +193,11 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ if (!allow_rebias) { obj->set_mark(unbiased_prototype); } - if (TraceBiasedLocking && (Verbose || !is_bulk)) { - tty->print_cr(" Revoked bias of anonymously-biased object"); + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { + log_info(biasedlocking)(" Revoked bias of anonymously-biased object"); + } else { + log_trace(biasedlocking)(" Revoked bias of anonymously-biased object"); } return BiasedLocking::BIAS_REVOKED; } @@ -198,8 +220,11 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ } else { obj->set_mark(unbiased_prototype); } - if (TraceBiasedLocking && (Verbose || !is_bulk)) { - tty->print_cr(" Revoked bias of object biased toward dead thread"); + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { + log_info(biasedlocking)(" Revoked bias of object biased toward dead thread"); + } else { + log_trace(biasedlocking)(" Revoked bias of object biased toward dead thread"); } return BiasedLocking::BIAS_REVOKED; } @@ -214,21 +239,17 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ for (int i = 0; i < cached_monitor_info->length(); i++) { MonitorInfo* mon_info = cached_monitor_info->at(i); if (mon_info->owner() == obj) { - if (TraceBiasedLocking && Verbose) { - tty->print_cr(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")", - p2i((void *) mon_info->owner()), - p2i((void *) obj)); - } + log_trace(biasedlocking)(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")", + p2i((void *) mon_info->owner()), + p2i((void *) obj)); // Assume recursive case and fix up highest lock later markOop mark = markOopDesc::encode((BasicLock*) NULL); highest_lock = mon_info->lock(); highest_lock->set_displaced_header(mark); } else { - if (TraceBiasedLocking && Verbose) { - tty->print_cr(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")", - p2i((void *) mon_info->owner()), - p2i((void *) obj)); - } + log_trace(biasedlocking)(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")", + p2i((void *) mon_info->owner()), + p2i((void *) obj)); } } if (highest_lock != NULL) { @@ -240,12 +261,18 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ // ordering (e.g. ppc). obj->release_set_mark(markOopDesc::encode(highest_lock)); assert(!obj->mark()->has_bias_pattern(), "illegal mark state: stack lock used bias bit"); - if (TraceBiasedLocking && (Verbose || !is_bulk)) { - tty->print_cr(" Revoked bias of currently-locked object"); + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { + log_info(biasedlocking)(" Revoked bias of currently-locked object"); + } else { + log_trace(biasedlocking)(" Revoked bias of currently-locked object"); } } else { - if (TraceBiasedLocking && (Verbose || !is_bulk)) { - tty->print_cr(" Revoked bias of currently-unlocked object"); + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { + log_info(biasedlocking)(" Revoked bias of currently-unlocked object"); + } else { + log_trace(biasedlocking)(" Revoked bias of currently-unlocked object"); } if (allow_rebias) { obj->set_mark(biased_prototype); @@ -326,12 +353,12 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, JavaThread* requesting_thread) { assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint"); - if (TraceBiasedLocking) { - tty->print_cr("* Beginning bulk revocation (kind == %s) because of object " - INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", - (bulk_rebias ? "rebias" : "revoke"), - p2i((void *) o), (intptr_t) o->mark(), o->klass()->external_name()); - } + log_info(biasedlocking)("* Beginning bulk revocation (kind == %s) because of object " + INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", + (bulk_rebias ? "rebias" : "revoke"), + p2i((void *) o), + (intptr_t) o->mark(), + o->klass()->external_name()); jlong cur_time = os::javaTimeMillis(); o->klass()->set_last_biased_lock_bulk_revocation_time(cur_time); @@ -377,9 +404,9 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, // adjust the header of the given object to revoke its bias. revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread); } else { - if (TraceBiasedLocking) { + if (log_is_enabled(Info, biasedlocking)) { ResourceMark rm; - tty->print_cr("* Disabling biased locking for type %s", klass->external_name()); + log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name()); } // Disable biased locking for this data type. Not only will this @@ -407,9 +434,7 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, revoke_bias(o, false, true, requesting_thread); } - if (TraceBiasedLocking) { - tty->print_cr("* Ending bulk revocation"); - } + log_info(biasedlocking)("* Ending bulk revocation"); BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED; @@ -420,9 +445,7 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, klass->prototype_header()->bias_epoch()); o->set_mark(new_mark); status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED; - if (TraceBiasedLocking) { - tty->print_cr(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread); - } + log_info(biasedlocking)(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread); } assert(!o->mark()->has_bias_pattern() || @@ -485,16 +508,12 @@ public: virtual void doit() { if (_obj != NULL) { - if (TraceBiasedLocking) { - tty->print_cr("Revoking bias with potentially per-thread safepoint:"); - } + log_info(biasedlocking)("Revoking bias with potentially per-thread safepoint:"); _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread); clean_up_cached_monitor_info(); return; } else { - if (TraceBiasedLocking) { - tty->print_cr("Revoking bias with global safepoint:"); - } + log_info(biasedlocking)("Revoking bias with global safepoint:"); BiasedLocking::revoke_at_safepoint(_objs); } } @@ -608,9 +627,7 @@ BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attem // can come in with a CAS to steal the bias of an object that has a // stale epoch. ResourceMark rm; - if (TraceBiasedLocking) { - tty->print_cr("Revoking bias by walking my own stack:"); - } + log_info(biasedlocking)("Revoking bias by walking my own stack:"); BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD); ((JavaThread*) THREAD)->set_cached_monitor_info(NULL); assert(cond == BIAS_REVOKED, "why not?"); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 86cd7328dd2..ce36ff1db49 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1488,9 +1488,6 @@ public: develop(bool, TraceClearedExceptions, false, \ "Print when an exception is forcibly cleared") \ \ - product(bool, TraceBiasedLocking, false, \ - "Trace biased locking in JVM") \ - \ /* gc */ \ \ product(bool, UseSerialGC, false, \ diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 5b9faf084d3..9f5bab030a6 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -170,11 +170,10 @@ void* Thread::allocate(size_t size, bool throw_excpt, MEMFLAGS flags) { assert(((uintptr_t) aligned_addr + (uintptr_t) size) <= ((uintptr_t) real_malloc_addr + (uintptr_t) aligned_size), "JavaThread alignment code overflowed allocated storage"); - if (TraceBiasedLocking) { - if (aligned_addr != real_malloc_addr) { - tty->print_cr("Aligned thread " INTPTR_FORMAT " to " INTPTR_FORMAT, - p2i(real_malloc_addr), p2i(aligned_addr)); - } + if (aligned_addr != real_malloc_addr) { + log_info(biasedlocking)("Aligned thread " INTPTR_FORMAT " to " INTPTR_FORMAT, + p2i(real_malloc_addr), + p2i(aligned_addr)); } ((Thread*) aligned_addr)->_real_malloc_address = real_malloc_addr; return aligned_addr; diff --git a/hotspot/test/runtime/logging/BiasedLockingTest.java b/hotspot/test/runtime/logging/BiasedLockingTest.java new file mode 100644 index 00000000000..36afcea3c75 --- /dev/null +++ b/hotspot/test/runtime/logging/BiasedLockingTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, 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 8149383 + * @summary -Xlog:biasedlocking should have logging from statements in the source code + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver BiasedLockingTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; + +public class BiasedLockingTest { + static void analyzeOutputOn(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Biased locking enabled"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputOff(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("[biasedlocking]"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:biasedlocking", + "-XX:BiasedLockingStartupDelay=0", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+TraceBiasedLocking", + "-XX:BiasedLockingStartupDelay=0", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:biasedlocking=off", + "-XX:BiasedLockingStartupDelay=0", + InnerClass.class.getName()); + analyzeOutputOff(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:-TraceBiasedLocking", + "-XX:BiasedLockingStartupDelay=0", + InnerClass.class.getName()); + analyzeOutputOff(pb); + } + + public static class InnerClass { + public static void main(String[] args) { + System.out.println("Biased Locking test"); + } + } +} From 98289a12c931713c41c367d9a96a50cb94b5aff0 Mon Sep 17 00:00:00 2001 From: Derek White Date: Wed, 17 Feb 2016 18:02:03 -0500 Subject: [PATCH 039/311] 8149837: String.intern creates morre work than necessary for G1 Only use the SATB read barrier when reading existing strings from string table, not when adding new strings. Reviewed-by: stefank, kbarrett --- hotspot/src/share/vm/classfile/stringTable.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/classfile/stringTable.cpp b/hotspot/src/share/vm/classfile/stringTable.cpp index ee303426f3c..167ec28449c 100644 --- a/hotspot/src/share/vm/classfile/stringTable.cpp +++ b/hotspot/src/share/vm/classfile/stringTable.cpp @@ -200,7 +200,6 @@ oop StringTable::lookup(jchar* name, int len) { return string; } - oop StringTable::intern(Handle string_or_null, jchar* name, int len, TRAPS) { oop found_string = lookup_shared(name, len); @@ -214,7 +213,9 @@ oop StringTable::intern(Handle string_or_null, jchar* name, // Found if (found_string != NULL) { - ensure_string_alive(found_string); + if (found_string != string_or_null()) { + ensure_string_alive(found_string); + } return found_string; } @@ -249,7 +250,9 @@ oop StringTable::intern(Handle string_or_null, jchar* name, hashValue, CHECK_NULL); } - ensure_string_alive(added_or_found); + if (added_or_found != string()) { + ensure_string_alive(added_or_found); + } return added_or_found; } From 40cdd7a181d53e5a533b1a6644fdcc58a2601664 Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Thu, 18 Feb 2016 21:53:24 +0800 Subject: [PATCH 040/311] 8149907: aarch64: use load/store pair instructions in call_stub Aarch64: make use of load/store pair instructions in call_stub to save space Reviewed-by: aph --- .../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 94 +++++-------------- 1 file changed, 26 insertions(+), 68 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index 64833c5ccc4..942d7bc5cb7 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -163,30 +163,20 @@ class StubGenerator: public StubCodeGenerator { sp_after_call_off = -26, d15_off = -26, - d14_off = -25, d13_off = -24, - d12_off = -23, d11_off = -22, - d10_off = -21, d9_off = -20, - d8_off = -19, r28_off = -18, - r27_off = -17, r26_off = -16, - r25_off = -15, r24_off = -14, - r23_off = -13, r22_off = -12, - r21_off = -11, r20_off = -10, - r19_off = -9, call_wrapper_off = -8, result_off = -7, result_type_off = -6, method_off = -5, entry_point_off = -4, - parameters_off = -3, parameter_size_off = -2, thread_off = -1, fp_f = 0, @@ -208,30 +198,20 @@ class StubGenerator: public StubCodeGenerator { const Address result_type (rfp, result_type_off * wordSize); const Address method (rfp, method_off * wordSize); const Address entry_point (rfp, entry_point_off * wordSize); - const Address parameters (rfp, parameters_off * wordSize); const Address parameter_size(rfp, parameter_size_off * wordSize); const Address thread (rfp, thread_off * wordSize); const Address d15_save (rfp, d15_off * wordSize); - const Address d14_save (rfp, d14_off * wordSize); const Address d13_save (rfp, d13_off * wordSize); - const Address d12_save (rfp, d12_off * wordSize); const Address d11_save (rfp, d11_off * wordSize); - const Address d10_save (rfp, d10_off * wordSize); const Address d9_save (rfp, d9_off * wordSize); - const Address d8_save (rfp, d8_off * wordSize); const Address r28_save (rfp, r28_off * wordSize); - const Address r27_save (rfp, r27_off * wordSize); const Address r26_save (rfp, r26_off * wordSize); - const Address r25_save (rfp, r25_off * wordSize); const Address r24_save (rfp, r24_off * wordSize); - const Address r23_save (rfp, r23_off * wordSize); const Address r22_save (rfp, r22_off * wordSize); - const Address r21_save (rfp, r21_off * wordSize); const Address r20_save (rfp, r20_off * wordSize); - const Address r19_save (rfp, r19_off * wordSize); // stub code @@ -254,31 +234,20 @@ class StubGenerator: public StubCodeGenerator { // rthread because we want to sanity check rthread later __ str(c_rarg7, thread); __ strw(c_rarg6, parameter_size); - __ str(c_rarg5, parameters); - __ str(c_rarg4, entry_point); - __ str(c_rarg3, method); - __ str(c_rarg2, result_type); - __ str(c_rarg1, result); - __ str(c_rarg0, call_wrapper); - __ str(r19, r19_save); - __ str(r20, r20_save); - __ str(r21, r21_save); - __ str(r22, r22_save); - __ str(r23, r23_save); - __ str(r24, r24_save); - __ str(r25, r25_save); - __ str(r26, r26_save); - __ str(r27, r27_save); - __ str(r28, r28_save); + __ stp(c_rarg4, c_rarg5, entry_point); + __ stp(c_rarg2, c_rarg3, result_type); + __ stp(c_rarg0, c_rarg1, call_wrapper); - __ strd(v8, d8_save); - __ strd(v9, d9_save); - __ strd(v10, d10_save); - __ strd(v11, d11_save); - __ strd(v12, d12_save); - __ strd(v13, d13_save); - __ strd(v14, d14_save); - __ strd(v15, d15_save); + __ stp(r20, r19, r20_save); + __ stp(r22, r21, r22_save); + __ stp(r24, r23, r24_save); + __ stp(r26, r25, r26_save); + __ stp(r28, r27, r28_save); + + __ stpd(v9, v8, d9_save); + __ stpd(v11, v10, d11_save); + __ stpd(v13, v12, d13_save); + __ stpd(v15, v14, d15_save); // install Java thread in global register now we have saved // whatever value it held @@ -385,33 +354,22 @@ class StubGenerator: public StubCodeGenerator { #endif // restore callee-save registers - __ ldrd(v15, d15_save); - __ ldrd(v14, d14_save); - __ ldrd(v13, d13_save); - __ ldrd(v12, d12_save); - __ ldrd(v11, d11_save); - __ ldrd(v10, d10_save); - __ ldrd(v9, d9_save); - __ ldrd(v8, d8_save); + __ ldpd(v15, v14, d15_save); + __ ldpd(v13, v12, d13_save); + __ ldpd(v11, v10, d11_save); + __ ldpd(v9, v8, d9_save); - __ ldr(r28, r28_save); - __ ldr(r27, r27_save); - __ ldr(r26, r26_save); - __ ldr(r25, r25_save); - __ ldr(r24, r24_save); - __ ldr(r23, r23_save); - __ ldr(r22, r22_save); - __ ldr(r21, r21_save); - __ ldr(r20, r20_save); - __ ldr(r19, r19_save); - __ ldr(c_rarg0, call_wrapper); - __ ldr(c_rarg1, result); + __ ldp(r28, r27, r28_save); + __ ldp(r26, r25, r26_save); + __ ldp(r24, r23, r24_save); + __ ldp(r22, r21, r22_save); + __ ldp(r20, r19, r20_save); + + __ ldp(c_rarg0, c_rarg1, call_wrapper); __ ldrw(c_rarg2, result_type); __ ldr(c_rarg3, method); - __ ldr(c_rarg4, entry_point); - __ ldr(c_rarg5, parameters); - __ ldr(c_rarg6, parameter_size); - __ ldr(c_rarg7, thread); + __ ldp(c_rarg4, c_rarg5, entry_point); + __ ldp(c_rarg6, c_rarg7, parameter_size); #ifndef PRODUCT // tell the simulator we are about to end Java execution From 2cfe5a01c4f351fc19e662a4d28d611e9e1845d1 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Thu, 18 Feb 2016 23:26:43 +0900 Subject: [PATCH 041/311] 8147388: Add diagnostic commands to attach JVMTI agent Reviewed-by: jbachorik, sspitsyn --- hotspot/src/share/vm/prims/jvmtiExport.cpp | 15 ++- hotspot/src/share/vm/prims/jvmtiExport.hpp | 1 + .../share/vm/services/diagnosticCommand.cpp | 61 ++++++++++ .../share/vm/services/diagnosticCommand.hpp | 20 ++++ .../dcmd/jvmti/LoadAgentDcmdTest.java | 111 ++++++++++++++++++ .../dcmd/jvmti/LoadJavaAgentDcmdTest.java | 81 +++++++++++++ .../dcmd/jvmti/SimpleJvmtiAgent.java | 29 +++++ 7 files changed, 313 insertions(+), 5 deletions(-) create mode 100644 hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java create mode 100644 hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java create mode 100644 hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 2c352044f02..7ad054138c6 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -2200,6 +2200,16 @@ extern "C" { } jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { + // get agent name and options + const char* agent = op->arg(0); + const char* absParam = op->arg(1); + const char* options = op->arg(2); + + return load_agent_library(agent, absParam, options, st); +} + +jint JvmtiExport::load_agent_library(const char *agent, const char *absParam, + const char *options, outputStream* st) { char ebuf[1024]; char buffer[JVM_MAXPATHLEN]; void* library = NULL; @@ -2207,11 +2217,6 @@ jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { const char *on_attach_symbols[] = AGENT_ONATTACH_SYMBOLS; size_t num_symbol_entries = ARRAY_SIZE(on_attach_symbols); - // get agent name and options - const char* agent = op->arg(0); - const char* absParam = op->arg(1); - const char* options = op->arg(2); - // The abs paramter should be "true" or "false" bool is_absolute_path = (absParam != NULL) && (strcmp(absParam,"true")==0); diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp index 4b1ff34cf61..8b06d62104b 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp @@ -372,6 +372,7 @@ class JvmtiExport : public AllStatic { static void transition_pending_onload_raw_monitors() NOT_JVMTI_RETURN; // attach support + static jint load_agent_library(const char *agent, const char *absParam, const char *options, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR); static jint load_agent_library(AttachOperation* op, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR); // SetNativeMethodPrefix support diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index d6dde5eef83..2a81ae7bfad 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -71,6 +71,7 @@ void DCmdRegistrant::register_dcmds(){ #endif // INCLUDE_SERVICES #if INCLUDE_JVMTI DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); #endif // INCLUDE_JVMTI DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); @@ -254,6 +255,66 @@ void JVMTIDataDumpDCmd::execute(DCmdSource source, TRAPS) { } } +JVMTIAgentLoadDCmd::JVMTIAgentLoadDCmd(outputStream* output, bool heap) : + DCmdWithParser(output, heap), + _libpath("library path", "Absolute path of the JVMTI agent to load.", + "STRING", true), + _option("agent option", "Option string to pass the agent.", "STRING", false) { + _dcmdparser.add_dcmd_argument(&_libpath); + _dcmdparser.add_dcmd_argument(&_option); +} + +void JVMTIAgentLoadDCmd::execute(DCmdSource source, TRAPS) { + + if (_libpath.value() == NULL) { + output()->print_cr("JVMTI.agent_load dcmd needs library path."); + return; + } + + char *suffix = strrchr(_libpath.value(), '.'); + bool is_java_agent = (suffix != NULL) && (strncmp(".jar", suffix, 4) == 0); + + if (is_java_agent) { + if (_option.value() == NULL) { + JvmtiExport::load_agent_library("instrument", "false", + _libpath.value(), output()); + } else { + size_t opt_len = strlen(_libpath.value()) + strlen(_option.value()) + 2; + if (opt_len > 4096) { + output()->print_cr("JVMTI agent attach failed: Options is too long."); + return; + } + + char *opt = (char *)os::malloc(opt_len, mtInternal); + if (opt == NULL) { + output()->print_cr("JVMTI agent attach failed: " + "Could not allocate %zu bytes for argument.", + opt_len); + return; + } + + jio_snprintf(opt, opt_len, "%s=%s", _libpath.value(), _option.value()); + JvmtiExport::load_agent_library("instrument", "false", opt, output()); + + os::free(opt); + } + } else { + JvmtiExport::load_agent_library(_libpath.value(), "true", + _option.value(), output()); + } +} + +int JVMTIAgentLoadDCmd::num_arguments() { + ResourceMark rm; + JVMTIAgentLoadDCmd* dcmd = new JVMTIAgentLoadDCmd(NULL, false); + if (dcmd != NULL) { + DCmdMark mark(dcmd); + return dcmd->_dcmdparser.num_arguments(); + } else { + return 0; + } +} + void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) { // load sun.misc.VMSupport Symbol* klass = vmSymbols::sun_misc_VMSupport(); diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index ea3ddfe588a..8f5dc9172ae 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -174,6 +174,26 @@ public: virtual void execute(DCmdSource source, TRAPS); }; +class JVMTIAgentLoadDCmd : public DCmdWithParser { +protected: + DCmdArgument _libpath; + DCmdArgument _option; +public: + JVMTIAgentLoadDCmd(outputStream* output, bool heap); + static const char* name() { return "JVMTI.agent_load"; } + static const char* description() { + return "Load JVMTI native agent."; + } + static const char* impact() { return "Low"; } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "control", NULL}; + return p; + } + static int num_arguments(); + virtual void execute(DCmdSource source, TRAPS); +}; + class VMDynamicLibrariesDCmd : public DCmd { public: VMDynamicLibrariesDCmd(outputStream* output, bool heap); diff --git a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java new file mode 100644 index 00000000000..ad4d5871a20 --- /dev/null +++ b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2016, 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 java.nio.file.*; +import jdk.test.lib.*; +import jdk.test.lib.dcmd.*; +import org.testng.annotations.Test; + +/* + * Test to attach JVMTI java agent. + * + * @test + * @bug 8147388 + * @library /testlibrary + * @modules java.base/sun.misc + * java.compiler + * java.instrument + * java.management + * jdk.jvmstat/sun.jvmstat.monitor + * @build ClassFileInstaller jdk.test.lib.* SimpleJvmtiAgent + * @run main ClassFileInstaller SimpleJvmtiAgent + * @run testng LoadAgentDcmdTest + */ +public class LoadAgentDcmdTest { + + public String getLibInstrumentPath() throws FileNotFoundException { + String jdkPath = System.getProperty("test.jdk"); + + if (jdkPath == null) { + throw new RuntimeException( + "System property 'test.jdk' not set. " + + "This property is normally set by jtreg. " + + "When running test separately, set this property using " + + "'-Dtest.jdk=/path/to/jdk'."); + } + + Path libpath; + if (Platform.isWindows()) { + libpath = Paths.get(jdkPath, "bin", "instrument.dll"); + } else { + libpath = Paths.get(jdkPath, "lib", Platform.getOsArch(), "libinstrument.so"); + } + + if (!libpath.toFile().exists()) { + throw new FileNotFoundException( + "Could not find " + libpath.toAbsolutePath()); + } + + return libpath.toAbsolutePath().toString(); + } + + public void run(CommandExecutor executor) { + try{ + PrintWriter pw = new PrintWriter("MANIFEST.MF"); + pw.println("Agent-Class: SimpleJvmtiAgent"); + pw.close(); + + ProcessBuilder pb = new ProcessBuilder(); + pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), + "cmf", + "MANIFEST.MF", + "agent.jar", + "SimpleJvmtiAgent.class"}); + pb.start().waitFor(); + + String libpath = getLibInstrumentPath(); + + // Test 1: No argument + OutputAnalyzer output = executor.execute("JVMTI.agent_load " + + libpath + " agent.jar"); + output.stderrShouldBeEmpty(); + + // Test 2: With argument + output = executor.execute("JVMTI.agent_load " + + libpath + " \"agent.jar=foo=bar\""); + output.stderrShouldBeEmpty(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void jmx() throws Throwable { + run(new JMXExecutor()); + } + + @Test + public void cli() throws Throwable { + run(new PidJcmdExecutor()); + } +} diff --git a/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java b/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java new file mode 100644 index 00000000000..6c0c17760aa --- /dev/null +++ b/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, 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.*; +import jdk.test.lib.dcmd.*; +import org.testng.annotations.Test; + +/* + * Test to attach JVMTI java agent. + * + * @test + * @bug 8147388 + * @library /testlibrary + * @modules java.base/sun.misc + * java.compiler + * java.instrument + * java.management + * jdk.jvmstat/sun.jvmstat.monitor + * @build ClassFileInstaller jdk.test.lib.* SimpleJvmtiAgent + * @run main ClassFileInstaller SimpleJvmtiAgent + * @run testng LoadJavaAgentDcmdTest + */ +public class LoadJavaAgentDcmdTest { + public void run(CommandExecutor executor) { + try{ + PrintWriter pw = new PrintWriter("MANIFEST.MF"); + pw.println("Agent-Class: SimpleJvmtiAgent"); + pw.close(); + + ProcessBuilder pb = new ProcessBuilder(); + pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), + "cmf", + "MANIFEST.MF", + "agent.jar", + "SimpleJvmtiAgent.class"}); + pb.start().waitFor(); + + // Test 1: No argument + OutputAnalyzer output = executor.execute("JVMTI.agent_load " + + "agent.jar"); + output.stderrShouldBeEmpty(); + + // Test 2: With argument + output = executor.execute("JVMTI.agent_load " + + "\"agent.jar=foo=bar\""); + output.stderrShouldBeEmpty(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void jmx() throws Throwable { + run(new JMXExecutor()); + } + + @Test + public void cli() throws Throwable { + run(new PidJcmdExecutor()); + } +} diff --git a/hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java b/hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java new file mode 100644 index 00000000000..6d92ff32f66 --- /dev/null +++ b/hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, 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.lang.instrument.*; + +public class SimpleJvmtiAgent { + public static void agentmain(String agentArgs, Instrumentation instrumentation) { + System.out.println("attach succeeded (args: \"" + agentArgs + "\")"); + } +} From 3a1062775ada000b51703c3c38acaf5f7eab3bdf Mon Sep 17 00:00:00 2001 From: Andreas Eriksson Date: Thu, 18 Feb 2016 16:15:15 +0100 Subject: [PATCH 042/311] 8149743: JVM crash after debugger hotswap with lambdas Reviewed-by: sspitsyn, coleenp, dcubed --- .../com/sun/jdi/RedefineAddPrivateMethod.sh | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh diff --git a/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh b/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh new file mode 100644 index 00000000000..bb9eefd8968 --- /dev/null +++ b/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +# +# Copyright (c) 2016, 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 8149743 +# @summary crash when adding a breakpoint after redefining to add a private static method +# @run shell RedefineAddPrivateMethod.sh + +compileOptions=-g + +createJavaFile() +{ + cat < $1.java.1 +public class $1 { + static public void main(String[] args) { + // @1 breakpoint @2 breakpoint + } + + // @1 uncomment private static void test() {} +} +EOF +} + +# This is called to feed cmds to jdb. +dojdbCmds() +{ + setBkpts @1 + runToBkpt @1 + redefineClass @1 + setBkpts @2 + cmd allowExit cont +} + + +mysetup() +{ + if [ -z "$TESTSRC" ] ; then + TESTSRC=. + fi + + for ii in . $TESTSRC $TESTSRC/.. ; do + if [ -r "$ii/ShellScaffold.sh" ] ; then + . $ii/ShellScaffold.sh + break + fi + done +} + +# You could replace this next line with the contents +# of ShellScaffold.sh and this script will run just the same. +mysetup + +runit +debuggeeFailIfPresent "Internal exception:" +pass From 35a916a2a186a093ef4c4b759edc1164793ef82a Mon Sep 17 00:00:00 2001 From: Andreas Eriksson Date: Thu, 18 Feb 2016 16:15:28 +0100 Subject: [PATCH 043/311] 8149743: JVM crash after debugger hotswap with lambdas Reviewed-by: sspitsyn, coleenp, dcubed --- hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 8823e6670a6..6b176ec1f70 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -3940,6 +3940,10 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, scratch_class->set_methods(_old_methods); // To prevent potential GCing of the old methods, // and to be able to undo operation easily. + Array* old_ordering = the_class->method_ordering(); + the_class->set_method_ordering(scratch_class->method_ordering()); + scratch_class->set_method_ordering(old_ordering); + ConstantPool* old_constants = the_class->constants(); the_class->set_constants(scratch_class->constants()); scratch_class->set_constants(old_constants); // See the previous comment. From 717ad7019c3aae78f4336c22fa2362f00dd1c763 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Thu, 18 Feb 2016 22:11:29 +0300 Subject: [PATCH 044/311] 8038139: AudioInputStream.getFrameLength() returns wrong value for floating-point WAV Reviewed-by: prr, amenkov --- .../com/sun/media/sound/AiffFileReader.java | 75 ++----- .../com/sun/media/sound/AiffFileWriter.java | 37 +--- .../media/sound/WaveExtensibleFileReader.java | 9 +- .../sun/media/sound/WaveFloatFileReader.java | 9 +- .../FrameLengthAfterConversion.java | 209 ++++++++++++++++++ 5 files changed, 244 insertions(+), 95 deletions(-) create mode 100644 jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java index 8c9dc3c78be..c0ac8bf6d40 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -26,11 +26,11 @@ package com.sun.media.sound; import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFileFormat.Type; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.UnsupportedAudioFileException; @@ -49,11 +49,6 @@ public final class AiffFileReader extends SunFileReader { throws UnsupportedAudioFileException, IOException { DataInputStream dis = new DataInputStream(stream); - // assumes a stream at the beginning of the file which has already - // passed the magic number test... - // leaves the input stream at the beginning of the audio data - int fileRead = 0; - int dataLength = 0; AudioFormat format = null; // Read the magic number @@ -65,9 +60,9 @@ public final class AiffFileReader extends SunFileReader { throw new UnsupportedAudioFileException("not an AIFF file"); } + int frameLength = 0; int length = dis.readInt(); int iffType = dis.readInt(); - fileRead += 12; int totallength; if(length <= 0 ) { @@ -91,7 +86,6 @@ public final class AiffFileReader extends SunFileReader { // Read the chunk name int chunkName = dis.readInt(); int chunkLen = dis.readInt(); - fileRead += 8; int chunkRead = 0; @@ -112,7 +106,13 @@ public final class AiffFileReader extends SunFileReader { if (channels <= 0) { throw new UnsupportedAudioFileException("Invalid number of channels"); } - dis.readInt(); // numSampleFrames + frameLength = dis.readInt(); // numSampleFrames + if (frameLength < 0) { + // AiffFileFormat uses int, unlike AIS which uses long + //TODO this (negative) value should be passed as long to AIS + frameLength = AudioSystem.NOT_SPECIFIED; + } + int sampleSizeInBits = dis.readUnsignedShort(); if (sampleSizeInBits < 1 || sampleSizeInBits > 32) { throw new UnsupportedAudioFileException("Invalid AIFF/COMM sampleSize"); @@ -149,38 +149,17 @@ public final class AiffFileReader extends SunFileReader { break; case AiffFileFormat.SSND_MAGIC: // Data chunk. - // we are getting *weird* numbers for chunkLen sometimes; - // this really should be the size of the data chunk.... - int dataOffset = dis.readInt(); - int blocksize = dis.readInt(); + int dataOffset = dis.readInt(); // for now unused in javasound + int blocksize = dis.readInt(); // for now unused in javasound chunkRead += 8; - - // okay, now we are done reading the header. we need to set the size - // of the data segment. we know that sometimes the value we get for - // the chunksize is absurd. this is the best i can think of:if the - // value seems okay, use it. otherwise, we get our value of - // length by assuming that everything left is the data segment; - // its length should be our original length (for all AIFF data chunks) - // minus what we've read so far. - // $$kk: we should be able to get length for the data chunk right after - // we find "SSND." however, some aiff files give *weird* numbers. what - // is going on?? - - if (chunkLen < length) { - dataLength = chunkLen - chunkRead; - } else { - // $$kk: 11.03.98: this seems dangerous! - dataLength = length - (fileRead + chunkRead); - } ssndFound = true; break; } // switch - fileRead += chunkRead; // skip the remainder of this chunk if (!ssndFound) { int toSkip = chunkLen - chunkRead; if (toSkip > 0) { - fileRead += dis.skipBytes(toSkip); + dis.skipBytes(toSkip); } } } // while @@ -188,36 +167,12 @@ public final class AiffFileReader extends SunFileReader { if (format == null) { throw new UnsupportedAudioFileException("missing COMM chunk"); } - AudioFileFormat.Type type = aifc?AudioFileFormat.Type.AIFC:AudioFileFormat.Type.AIFF; + Type type = aifc ? Type.AIFC : Type.AIFF; - return new AiffFileFormat(type, totallength, format, dataLength / format.getFrameSize()); + return new AiffFileFormat(type, totallength, format, frameLength); } // HELPER METHODS - /** write_ieee_extended(DataOutputStream dos, double f) throws IOException { - * Extended precision IEEE floating-point conversion routine. - * @argument DataOutputStream - * @argument double - * @return void - * @exception IOException - */ - private void write_ieee_extended(DataOutputStream dos, double f) throws IOException { - - int exponent = 16398; - double highMantissa = f; - - // For now write the integer portion of f - // $$jb: 03.30.99: stay in synch with JMF on this!!!! - while (highMantissa < 44000) { - highMantissa *= 2; - exponent--; - } - dos.writeShort(exponent); - dos.writeInt( ((int) highMantissa) << 16); - dos.writeInt(0); // low Mantissa - } - - /** * read_ieee_extended * Extended precision IEEE floating-point conversion routine. diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java index 0a4788df804..9b5ebac2f6b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java @@ -59,7 +59,6 @@ public final class AiffFileWriter extends SunFileWriter { super(new AudioFileFormat.Type[]{AudioFileFormat.Type.AIFF}); } - // METHODS TO IMPLEMENT AudioFileWriter @Override @@ -83,7 +82,6 @@ public final class AiffFileWriter extends SunFileWriter { return new AudioFileFormat.Type[0]; } - @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException { Objects.requireNonNull(stream); @@ -102,11 +100,9 @@ public final class AiffFileWriter extends SunFileWriter { throw new IOException("stream length not specified"); } - int bytesWritten = writeAiffFile(stream, aiffFileFormat, out); - return bytesWritten; + return writeAiffFile(stream, aiffFileFormat, out); } - @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException { Objects.requireNonNull(stream); @@ -129,12 +125,15 @@ public final class AiffFileWriter extends SunFileWriter { // $$kk: 10.22.99: jan: please either implement this or throw an exception! // $$fb: 2001-07-13: done. Fixes Bug 4479981 - int ssndBlockSize = (aiffFileFormat.getFormat().getChannels() * aiffFileFormat.getFormat().getSampleSizeInBits()); + int channels = aiffFileFormat.getFormat().getChannels(); + int sampleSize = aiffFileFormat.getFormat().getSampleSizeInBits(); + int ssndBlockSize = channels * ((sampleSize + 7) / 8); int aiffLength=bytesWritten; int ssndChunkSize=aiffLength-aiffFileFormat.getHeaderSize()+16; long dataSize=ssndChunkSize-16; - int numFrames=(int) (dataSize*8/ssndBlockSize); + //TODO possibly incorrect round + int numFrames = (int) (dataSize / ssndBlockSize); RandomAccessFile raf=new RandomAccessFile(out, "rw"); // skip FORM magic @@ -173,12 +172,7 @@ public final class AiffFileWriter extends SunFileWriter { AudioFormat streamFormat = stream.getFormat(); AudioFormat.Encoding streamEncoding = streamFormat.getEncoding(); - - float sampleRate; int sampleSizeInBits; - int channels; - int frameSize; - float frameRate; int fileSize; boolean convert8to16 = false; @@ -235,7 +229,6 @@ public final class AiffFileWriter extends SunFileWriter { return fileFormat; } - private int writeAiffFile(InputStream in, AiffFileFormat aiffFileFormat, OutputStream out) throws IOException { int bytesRead = 0; @@ -275,25 +268,20 @@ public final class AiffFileWriter extends SunFileWriter { AudioFormat.Encoding encoding = null; //$$fb a little bit nicer handling of constants - - //int headerSize = 54; int headerSize = aiffFileFormat.getHeaderSize(); - //int fverChunkSize = 0; int fverChunkSize = aiffFileFormat.getFverChunkSize(); - //int commChunkSize = 26; int commChunkSize = aiffFileFormat.getCommChunkSize(); int aiffLength = -1; int ssndChunkSize = -1; - //int ssndOffset = headerSize - 16; int ssndOffset = aiffFileFormat.getSsndChunkOffset(); short channels = (short) format.getChannels(); short sampleSize = (short) format.getSampleSizeInBits(); - int ssndBlockSize = (channels * sampleSize); - int numFrames = aiffFileFormat.getFrameLength(); - long dataSize = -1; + int ssndBlockSize = channels * ((sampleSize + 7) / 8); + int numFrames = aiffFileFormat.getFrameLength(); + long dataSize = -1; if( numFrames != AudioSystem.NOT_SPECIFIED) { - dataSize = (long) numFrames * ssndBlockSize / 8; + dataSize = (long) numFrames * ssndBlockSize; ssndChunkSize = (int)dataSize + 16; aiffLength = (int)dataSize+headerSize; } @@ -403,9 +391,6 @@ public final class AiffFileWriter extends SunFileWriter { } - - - // HELPER METHODS private static final int DOUBLE_MANTISSA_LENGTH = 52; @@ -452,6 +437,4 @@ public final class AiffFileWriter extends SunFileWriter { dos.writeShort(extendedBits79To64); dos.writeLong(extendedBits63To0); } - - } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java index 240c6d27c58..9085c58b530 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java @@ -255,16 +255,17 @@ public final class WaveExtensibleFileReader extends SunFileReader { public AudioInputStream getAudioInputStream(final InputStream stream) throws UnsupportedAudioFileException, IOException { - AudioFileFormat format = getAudioFileFormat(stream); + final AudioFileFormat format = getAudioFileFormat(stream); // we've got everything, the stream is supported and it is at the // beginning of the header, so find the data chunk again and return an // AudioInputStream - RIFFReader riffiterator = new RIFFReader(stream); + final RIFFReader riffiterator = new RIFFReader(stream); while (riffiterator.hasNextChunk()) { RIFFReader chunk = riffiterator.nextChunk(); if (chunk.getFormat().equals("data")) { - return new AudioInputStream(chunk, format.getFormat(), chunk - .getSize()); + final AudioFormat af = format.getFormat(); + final long length = chunk.getSize() / af.getFrameSize(); + return new AudioInputStream(chunk, af, length); } } throw new UnsupportedAudioFileException(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java index afecd0e34be..6639cf040e8 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java @@ -95,16 +95,17 @@ public final class WaveFloatFileReader extends SunFileReader { public AudioInputStream getAudioInputStream(final InputStream stream) throws UnsupportedAudioFileException, IOException { - AudioFileFormat format = getAudioFileFormat(stream); + final AudioFileFormat format = getAudioFileFormat(stream); // we've got everything, the stream is supported and it is at the // beginning of the header, so find the data chunk again and return an // AudioInputStream - RIFFReader riffiterator = new RIFFReader(stream); + final RIFFReader riffiterator = new RIFFReader(stream); while (riffiterator.hasNextChunk()) { RIFFReader chunk = riffiterator.nextChunk(); if (chunk.getFormat().equals("data")) { - return new AudioInputStream(chunk, format.getFormat(), - chunk.getSize()); + final AudioFormat af = format.getFormat(); + final long length = chunk.getSize() / af.getFrameSize(); + return new AudioInputStream(chunk, af, length); } } throw new UnsupportedAudioFileException(); diff --git a/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java b/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java new file mode 100644 index 00000000000..e32e7723db5 --- /dev/null +++ b/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2016, 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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileWriter; +import javax.sound.sampled.spi.FormatConversionProvider; + +import static java.util.ServiceLoader.load; +import static javax.sound.sampled.AudioFileFormat.Type.AIFC; +import static javax.sound.sampled.AudioFileFormat.Type.AIFF; +import static javax.sound.sampled.AudioFileFormat.Type.AU; +import static javax.sound.sampled.AudioFileFormat.Type.SND; +import static javax.sound.sampled.AudioFileFormat.Type.WAVE; +import static javax.sound.sampled.AudioSystem.NOT_SPECIFIED; + +/** + * @test + * @bug 8038139 + */ +public final class FrameLengthAfterConversion { + + /** + * We will try to use all formats, in this case all our providers will be + * covered by supported/unsupported formats. + */ + private static final List formats = new ArrayList<>(23000); + + private static final AudioFormat.Encoding[] encodings = { + AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW, + AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED, + AudioFormat.Encoding.PCM_FLOAT, new AudioFormat.Encoding("Test") + }; + + private static final int[] sampleBits = { + 1, 4, 8, 11, 16, 20, 24, 32 + }; + + private static final int[] channels = { + 1, 2, 3, 4, 5 + }; + + private static final AudioFileFormat.Type[] types = { + WAVE, AU, AIFF, AIFC, SND, + new AudioFileFormat.Type("TestName", "TestExt") + }; + + private static final int FRAME_LENGTH = 10; + + static { + for (final int sampleSize : sampleBits) { + for (final int channel : channels) { + for (final AudioFormat.Encoding enc : encodings) { + final int frameSize = ((sampleSize + 7) / 8) * channel; + formats.add(new AudioFormat(enc, 44100, sampleSize, channel, + frameSize, 44100, true)); + formats.add(new AudioFormat(enc, 44100, sampleSize, channel, + frameSize, 44100, false)); + } + } + } + } + + public static void main(final String[] args) { + for (final FormatConversionProvider fcp : load( + FormatConversionProvider.class)) { + System.out.println("fcp = " + fcp); + for (final AudioFormat from : formats) { + for (final AudioFormat to : formats) { + testAfterConversion(fcp, to, getStream(from, true)); + } + } + } + + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + System.out.println("afw = " + afw); + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat from : formats) { + testAfterSaveToStream(afw, type, getStream(from, true)); + } + } + } + + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + System.out.println("afw = " + afw); + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat from : formats) { + testAfterSaveToFile(afw, type, getStream(from, true)); + } + } + } + + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + System.out.println("afw = " + afw); + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat from : formats) { + testAfterSaveToFile(afw, type, getStream(from, false)); + } + } + } + } + + /** + * Verifies the frame length after the stream was saved/read to/from + * stream. + */ + private static void testAfterSaveToStream(final AudioFileWriter afw, + final AudioFileFormat.Type type, + final AudioInputStream ais) { + try { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + afw.write(ais, type, out); + final InputStream input = new ByteArrayInputStream( + out.toByteArray()); + validate(AudioSystem.getAudioInputStream(input).getFrameLength()); + } catch (IllegalArgumentException | UnsupportedAudioFileException + | IOException ignored) { + } + } + + /** + * Verifies the frame length after the stream was saved/read to/from file. + */ + private static void testAfterSaveToFile(final AudioFileWriter afw, + final AudioFileFormat.Type type, + AudioInputStream ais) { + try { + final File temp = File.createTempFile("sound", ".tmp"); + temp.deleteOnExit(); + afw.write(ais, type, temp); + ais = AudioSystem.getAudioInputStream(temp); + final long frameLength = ais.getFrameLength(); + ais.close(); + temp.delete(); + validate(frameLength); + } catch (IllegalArgumentException | UnsupportedAudioFileException + | IOException ignored) { + } + } + + /** + * Verifies the frame length after the stream was converted to other + * stream. + * + * @see FormatConversionProvider#getAudioInputStream(AudioFormat, + * AudioInputStream) + */ + private static void testAfterConversion(final FormatConversionProvider fcp, + final AudioFormat to, + final AudioInputStream ais) { + if (fcp.isConversionSupported(to, ais.getFormat())) { + validate(fcp.getAudioInputStream(to, ais).getFrameLength()); + } + } + + /** + * Throws an exception if the frameLength is specified and is not equal to + * the gold value. + */ + private static void validate(final long frameLength) { + if (frameLength != FRAME_LENGTH) { + System.err.println("Expected: " + FRAME_LENGTH); + System.err.println("Actual: " + frameLength); + throw new RuntimeException(); + } + } + + private static AudioInputStream getStream(final AudioFormat format, + final boolean frameLength) { + final int dataSize = FRAME_LENGTH * format.getFrameSize(); + final InputStream in = new ByteArrayInputStream(new byte[dataSize]); + if (frameLength) { + return new AudioInputStream(in, format, FRAME_LENGTH); + } else { + return new AudioInputStream(in, format, NOT_SPECIFIED); + } + } +} From d466ce4948fd6b5099da43453621a1437a40fc18 Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Fri, 19 Feb 2016 17:12:14 +0800 Subject: [PATCH 045/311] 8150229: aarch64: pipeline class for several instructions is not set correctly Aarch64: c2 fix pipeline class for several instructions. Reviewed-by: aph --- hotspot/src/cpu/aarch64/vm/aarch64.ad | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index 8483c709564..acc65080e2f 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -13281,7 +13281,7 @@ instruct MoveF2I_reg_reg(iRegINoSp dst, vRegF src) %{ __ fmovs($dst$$Register, as_FloatRegister($src$$reg)); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_f2i); %} @@ -13299,7 +13299,7 @@ instruct MoveI2F_reg_reg(vRegF dst, iRegI src) %{ __ fmovs(as_FloatRegister($dst$$reg), $src$$Register); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_i2f); %} @@ -13317,7 +13317,7 @@ instruct MoveD2L_reg_reg(iRegLNoSp dst, vRegD src) %{ __ fmovd($dst$$Register, as_FloatRegister($src$$reg)); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_d2l); %} @@ -13335,7 +13335,7 @@ instruct MoveL2D_reg_reg(vRegD dst, iRegL src) %{ __ fmovd(as_FloatRegister($dst$$reg), $src$$Register); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_l2d); %} @@ -16502,7 +16502,7 @@ instruct vsll2I(vecD dst, vecD src, vecX shift) %{ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift64_imm); + ins_pipe(vshift64); %} instruct vsll4I(vecX dst, vecX src, vecX shift) %{ @@ -16516,7 +16516,7 @@ instruct vsll4I(vecX dst, vecX src, vecX shift) %{ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift128_imm); + ins_pipe(vshift128); %} instruct vsrl2I(vecD dst, vecD src, vecX shift) %{ @@ -16529,7 +16529,7 @@ instruct vsrl2I(vecD dst, vecD src, vecX shift) %{ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift64_imm); + ins_pipe(vshift64); %} instruct vsrl4I(vecX dst, vecX src, vecX shift) %{ @@ -16542,7 +16542,7 @@ instruct vsrl4I(vecX dst, vecX src, vecX shift) %{ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift128_imm); + ins_pipe(vshift128); %} instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ @@ -16660,7 +16660,7 @@ instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ as_FloatRegister($src$$reg), (int)$shift$$constant & 63); %} - ins_pipe(vshift128); + ins_pipe(vshift128_imm); %} instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ From 04d2edfca3b5f342a694c2bb88bfea7266c88dfc Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Fri, 19 Feb 2016 13:24:21 +0300 Subject: [PATCH 046/311] 8146187: Print develop and nonproduct flags by -XX:+PrintFlags* options in debug build Reviewed-by: gtriantafill, gziemski, dholmes --- hotspot/src/share/vm/runtime/globals.cpp | 28 ++++++------------- .../TestOptionsWithRanges.java | 2 +- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 638b15eaffc..ade6900975b 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -403,25 +403,20 @@ void Flag::print_on(outputStream* st, bool withComments, bool printRanges) { st->cr(); } else if (!is_bool() && !is_ccstr()) { + st->print("%9s %-50s ", _type, _name); - if (printRanges) { + CommandLineFlagRangeList::print(_name, st, true); - st->print("%9s %-50s ", _type, _name); - - CommandLineFlagRangeList::print(_name, st, true); - - st->print(" %-20s", " "); - print_kind(st); + st->print(" %-20s", " "); + print_kind(st); #ifndef PRODUCT - if (withComments) { - st->print("%s", _doc); - } + if (withComments) { + st->print("%s", _doc); + } #endif - st->cr(); - - } + st->cr(); } } @@ -1255,8 +1250,6 @@ void CommandLineFlags::verify() { #endif // PRODUCT -#define ONLY_PRINT_PRODUCT_FLAGS - void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool printRanges) { // Print the flags sorted by name // note: this method is called before the thread structure is in place @@ -1281,9 +1274,6 @@ void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool pri for (size_t i = 0; i < length; i++) { if (array[i]->is_unlocked()) { -#ifdef ONLY_PRINT_PRODUCT_FLAGS - if (!array[i]->is_notproduct() && !array[i]->is_develop()) -#endif // ONLY_PRINT_PRODUCT_FLAGS array[i]->print_on(out, withComments, printRanges); } } diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java index 24f7ad70a53..27ccc5d546b 100644 --- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java @@ -75,7 +75,7 @@ public class TestOptionsWithRanges { int failedTests; List allOptions; - allOptionsAsMap = JVMOptionsUtils.getOptionsWithRangeAsMap(); + allOptionsAsMap = JVMOptionsUtils.getOptionsWithRangeAsMap(origin -> (!(origin.contains("develop") || origin.contains("notproduct")))); /* Shared flags can cause JVM to exit with error code 2 */ setAllowedExitCodes("SharedReadWriteSize", 2); From f1812d9e9f20aeb50403eb0ab51ec4d2adc3d414 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Fri, 19 Feb 2016 14:04:20 +0100 Subject: [PATCH 047/311] 8150201: Restore missing -g flags to files with OPT_CFLAGS/per-file Reviewed-by: dholmes, erikj --- hotspot/make/bsd/makefiles/amd64.make | 10 +++++++++- hotspot/make/bsd/makefiles/gcc.make | 9 ++++++++- hotspot/make/linux/makefiles/amd64.make | 10 +++++++++- hotspot/make/linux/makefiles/gcc.make | 12 +++++++++++- hotspot/make/linux/makefiles/i486.make | 10 +++++++++- hotspot/make/solaris/makefiles/amd64.make | 10 +++++++++- hotspot/make/solaris/makefiles/product.make | 18 +++++++++++++++++- hotspot/make/solaris/makefiles/sparcWorks.make | 11 +++++++++++ 8 files changed, 83 insertions(+), 7 deletions(-) diff --git a/hotspot/make/bsd/makefiles/amd64.make b/hotspot/make/bsd/makefiles/amd64.make index ecdac17ee3a..6512375259e 100644 --- a/hotspot/make/bsd/makefiles/amd64.make +++ b/hotspot/make/bsd/makefiles/amd64.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, 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 @@ -37,3 +37,11 @@ ifndef USE_SUNCC endif OPT_CFLAGS/compactingPermGenGen.o = -O1 + +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/sharedRuntimeTrig.o += -g + OPT_CFLAGS/sharedRuntimeTrans.o += -g + OPT_CFLAGS/compactingPermGenGen.o += -g +endif diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index 05a07052963..1bf6521a892 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2016, 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 @@ -330,6 +330,13 @@ ifeq ($(USE_CLANG), true) ), 1) OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT) OPT_CFLAGS/unsafe.o += -O1 + + # The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides + # of OPT_CFLAGS. Restore it here. + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/loopTransform.o += -g + OPT_CFLAGS/unsafe.o += -g + endif else $(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)") endif diff --git a/hotspot/make/linux/makefiles/amd64.make b/hotspot/make/linux/makefiles/amd64.make index 2b77dbab605..c98a5827820 100644 --- a/hotspot/make/linux/makefiles/amd64.make +++ b/hotspot/make/linux/makefiles/amd64.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, 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,3 +32,11 @@ CFLAGS += -DVM_LITTLE_ENDIAN CFLAGS += -D_LP64=1 OPT_CFLAGS/compactingPermGenGen.o = -O1 + +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/sharedRuntimeTrig.o += -g + OPT_CFLAGS/sharedRuntimeTrans.o += -g + OPT_CFLAGS/compactingPermGenGen.o += -g +endif diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index c8ee95d932b..a2e5c6c03b6 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2016, 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 @@ -265,6 +265,11 @@ ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& # GCC >= 4.3 # Gcc 4.1.2 does not support this flag, nor does it have problems compiling the file. OPT_CFLAGS/vmStructs.o += -fno-var-tracking-assignments + # The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides + # of OPT_CFLAGS. Restore it here. + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/vmStructs.o += -g + endif endif # The gcc compiler segv's on ia64 when compiling bytecodeInterpreter.cpp @@ -277,6 +282,11 @@ endif ifeq ($(USE_CLANG), true) ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1) OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT) + # The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides + # of OPT_CFLAGS. Restore it here. + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/loopTransform.o += -g + endif endif else # Do not allow GCC 4.1.1 diff --git a/hotspot/make/linux/makefiles/i486.make b/hotspot/make/linux/makefiles/i486.make index 86e825d3e9d..a1adda6477c 100644 --- a/hotspot/make/linux/makefiles/i486.make +++ b/hotspot/make/linux/makefiles/i486.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2016, 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,3 +32,11 @@ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT) CFLAGS += -DVM_LITTLE_ENDIAN OPT_CFLAGS/compactingPermGenGen.o = -O1 + +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/sharedRuntimeTrig.o += -g + OPT_CFLAGS/sharedRuntimeTrans.o += -g + OPT_CFLAGS/compactingPermGenGen.o += -g +endif diff --git a/hotspot/make/solaris/makefiles/amd64.make b/hotspot/make/solaris/makefiles/amd64.make index f88d743fe7c..7b1bdf3d8b3 100644 --- a/hotspot/make/solaris/makefiles/amd64.make +++ b/hotspot/make/solaris/makefiles/amd64.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2016, 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 @@ -34,6 +34,14 @@ ifeq ("${Platform_compiler}", "sparcWorks") OPT_CFLAGS/generateOptoStub.o = -xO2 # Temporary util SS12u1 C++ compiler is fixed OPT_CFLAGS/c1_LinearScan.o = -xO2 + +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/generateOptoStub.o += -g0 -xs + OPT_CFLAGS/LinearScan.o += -g0 -xs +endif + else ifeq ("${Platform_compiler}", "gcc") diff --git a/hotspot/make/solaris/makefiles/product.make b/hotspot/make/solaris/makefiles/product.make index 7f378b17d95..b36159fdcc8 100644 --- a/hotspot/make/solaris/makefiles/product.make +++ b/hotspot/make/solaris/makefiles/product.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2016, 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 @@ -35,11 +35,21 @@ OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@)) # for this method for now. (fix this when dtrace bug 6258412 is fixed) ifndef USE_GCC OPT_CFLAGS/ciEnv.o = $(OPT_CFLAGS) -xinline=no%__1cFciEnvbFpost_compiled_method_load_event6MpnHnmethod__v_ +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/ciEnv.o += -g0 -xs +endif endif # Need extra inlining to get oop_ps_push_contents functions to perform well enough. ifndef USE_GCC OPT_CFLAGS/psPromotionManager.o = $(OPT_CFLAGS) -W2,-Ainline:inc=1000 +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/psPromotionManager.o += -g0 -xs +endif endif # (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) @@ -55,6 +65,12 @@ endif # COMPILER_REV_NUMERIC == 510 ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) # dtrace cannot handle tail call optimization (6672627, 6693876) OPT_CFLAGS/jni.o = $(OPT_CFLAGS/DEFAULT) $(OPT_CCFLAGS/NO_TAIL_CALL_OPT) +# The -g0 -xs flag is added to OPT_CFLAGS in sparcWorks.make, but lost in case of +# per-file overrides of OPT_CFLAGS. Restore it here. This is mainly needed +# to provide a good baseline to compare the new build against. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/jni.o += -g0 -xs +endif endif # COMPILER_NUMERIC_REV >= 509 # Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12) diff --git a/hotspot/make/solaris/makefiles/sparcWorks.make b/hotspot/make/solaris/makefiles/sparcWorks.make index cbd902ef0fe..5c66b2f3d20 100644 --- a/hotspot/make/solaris/makefiles/sparcWorks.make +++ b/hotspot/make/solaris/makefiles/sparcWorks.make @@ -158,9 +158,20 @@ OPT_CFLAGS/NO_TAIL_CALL_OPT = -Wu,-O~yz OPT_CCFLAGS/NO_TAIL_CALL_OPT = -Qoption ube -O~yz OPT_CFLAGS/stubGenerator_x86_32.o = $(OPT_CFLAGS) -xspace OPT_CFLAGS/stubGenerator_x86_64.o = $(OPT_CFLAGS) -xspace +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/stubGenerator_x86_32.o += -g0 -xs + OPT_CFLAGS/stubGenerator_x86_64.o += -g0 -xs +endif endif # Platform_arch == x86 ifeq ("${Platform_arch}", "sparc") OPT_CFLAGS/stubGenerator_sparc.o = $(OPT_CFLAGS) -xspace +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/stubGenerator_sparc.o += -g0 -xs +endif endif endif # COMPILER_REV_NUMERIC >= 509 From 390295caf1b807dc9b32eafcef372be62171d84f Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Fri, 19 Feb 2016 15:14:59 -0500 Subject: [PATCH 048/311] 8150134: Simplify concurrent refinement thread deactivation Remove explicit deactivation and use green stop_at value. Reviewed-by: jmasa, tschatzl --- .../vm/gc/g1/concurrentG1RefineThread.cpp | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index df9de0ee337..cefcab3065b 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -89,8 +89,6 @@ bool ConcurrentG1RefineThread::is_active() { void ConcurrentG1RefineThread::activate() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); if (!is_primary()) { - log_debug(gc, refine)("G1-Refine-activated worker %d, on threshold %d, current %d", - _worker_id, _threshold, JavaThread::dirty_card_queue_set().completed_buffers_num()); set_active(true); } else { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); @@ -102,8 +100,6 @@ void ConcurrentG1RefineThread::activate() { void ConcurrentG1RefineThread::deactivate() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); if (!is_primary()) { - log_debug(gc, refine)("G1-Refine-deactivated worker %d, off threshold %d, current %d", - _worker_id, _deactivation_threshold, JavaThread::dirty_card_queue_set().completed_buffers_num()); set_active(false); } else { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); @@ -130,9 +126,12 @@ void ConcurrentG1RefineThread::run_service() { break; } + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + log_debug(gc, refine)("Activated %d, on threshold: %d, current: %d", + _worker_id, _threshold, dcqs.completed_buffers_num()); + { SuspendibleThreadSetJoiner sts_join; - DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); do { int curr_buffer_num = (int)dcqs.completed_buffers_num(); @@ -142,27 +141,19 @@ void ConcurrentG1RefineThread::run_service() { dcqs.set_completed_queue_padding(0); } - if (!is_primary() && curr_buffer_num <= _deactivation_threshold) { - // If the number of the buffer has fallen below our threshold - // we should deactivate. The predecessor will reactivate this - // thread should the number of the buffers cross the threshold again. - deactivate(); - break; - } - // Check if we need to activate the next thread. if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { _next->activate(); } } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, _worker_id + _worker_id_offset, - cg1r()->green_zone(), + _deactivation_threshold, false /* during_pause */)); - // We can exit the loop above while being active if there was a yield request. - if (is_active()) { - deactivate(); - } + deactivate(); + log_debug(gc, refine)("Deactivated %d, off threshold: %d, current: %d", + _worker_id, _deactivation_threshold, + dcqs.completed_buffers_num()); } if (os::supports_vtime()) { @@ -172,7 +163,7 @@ void ConcurrentG1RefineThread::run_service() { } } - log_debug(gc, refine)("G1-Refine-stop"); + log_debug(gc, refine)("Stopping %d", _worker_id); } void ConcurrentG1RefineThread::stop() { From 5d04cc8e61dee4a8621863f1eae550ea963ac24a Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Fri, 19 Feb 2016 10:44:54 +0100 Subject: [PATCH 049/311] 8150232: AIX cleanup: Integrate changes of 7178026 and others Reviewed-by: simonis --- hotspot/src/os/aix/vm/attachListener_aix.cpp | 12 ++-- hotspot/src/os/aix/vm/perfMemory_aix.cpp | 59 +++++++++++--------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/hotspot/src/os/aix/vm/attachListener_aix.cpp b/hotspot/src/os/aix/vm/attachListener_aix.cpp index cb56efc26f7..4e69822008a 100644 --- a/hotspot/src/os/aix/vm/attachListener_aix.cpp +++ b/hotspot/src/os/aix/vm/attachListener_aix.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. 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 @@ -225,7 +225,7 @@ int AixAttachListener::init() { // We must call bind with the actual socketaddr length. This is obligatory for AS400. int res = ::bind(listener, (struct sockaddr*)&addr, SUN_LEN(&addr)); if (res == -1) { - RESTARTABLE(::close(listener), res); + ::close(listener); return -1; } @@ -238,7 +238,7 @@ int AixAttachListener::init() { } } if (res == -1) { - RESTARTABLE(::close(listener), res); + ::close(listener); ::unlink(initial_path); return -1; } @@ -400,7 +400,7 @@ AixAttachOperation* AixAttachListener::dequeue() { AixAttachOperation* op = read_request(s); if (op == NULL) { int res; - RESTARTABLE(::close(s), res); + ::close(s); continue; } else { return op; @@ -452,7 +452,7 @@ void AixAttachOperation::complete(jint result, bufferedStream* st) { } // done - RESTARTABLE(::close(this->socket()), rc); + ::close(this->socket()); // were we externally suspended while we were waiting? thread->check_and_wait_while_suspended(); diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp index 2604a03dae8..c2e7c0e4e90 100644 --- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. 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 @@ -121,7 +121,7 @@ static void save_memory_to_file(char* addr, size_t size) { addr += result; } - RESTARTABLE(::close(fd), result); + result = ::close(fd); if (PrintMiscellaneous && Verbose) { if (result == OS_ERR) { warning("Could not close %s: %s\n", destfile, strerror(errno)); @@ -299,10 +299,13 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u bool create; int error; int fd; + int result; create = false; - if (lstat(path, &orig_st) != 0) { + RESTARTABLE(::lstat(path, &orig_st), result); + + if (result == OS_ERR) { if (errno == ENOENT && (oflag & O_CREAT) != 0) { // File doesn't exist, but_we want to create it, add O_EXCL flag // to make sure no-one creates it (or a symlink) before us @@ -316,7 +319,7 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u return OS_ERR; } } else { - // Lstat success, check if existing file is a link. + // lstat success, check if existing file is a link. if ((orig_st.st_mode & S_IFMT) == S_IFLNK) { // File is a symlink. errno = ELOOP; @@ -325,9 +328,9 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u } if (use_mode == true) { - fd = open(path, oflag, mode); + RESTARTABLE(::open(path, oflag, mode), fd); } else { - fd = open(path, oflag); + RESTARTABLE(::open(path, oflag), fd); } if (fd == OS_ERR) { @@ -336,7 +339,8 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u // Can't do inode checks on before/after if we created the file. if (create == false) { - if (fstat(fd, &new_st) != 0) { + RESTARTABLE(::fstat(fd, &new_st), result); + if (result == OS_ERR) { // Keep errno from fstat, in case close also fails. error = errno; ::close(fd); @@ -384,7 +388,7 @@ static DIR *open_directory_secure(const char* dirname) { RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result); #else // workaround (jdk6 coding) - RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result); + result = open_o_nofollow(dirname, O_RDONLY); #endif if (result == OS_ERR) { @@ -888,7 +892,7 @@ static int create_sharedmem_resources(const char* dirname, const char* filename, RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); #else // workaround function (jdk6 code) - RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result); + result = open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE); #endif if (result == OS_ERR) { @@ -931,7 +935,7 @@ static int create_sharedmem_resources(const char* dirname, const char* filename, if (PrintMiscellaneous && Verbose) { warning("could not set shared memory file size: %s\n", strerror(errno)); } - RESTARTABLE(::close(fd), result); + ::close(fd); return -1; } @@ -951,7 +955,7 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) { #ifdef O_NOFOLLOW RESTARTABLE(::open(filename, oflags), result); #else - RESTARTABLE(::open_o_nofollow(filename, oflags), result); + open_o_nofollow(filename, oflags); #endif if (result == OS_ERR) { @@ -1006,8 +1010,7 @@ static char* mmap_create_shared(size_t size) { char* dirname = get_user_tmp_dir(user_name); char* filename = get_sharedmem_filename(dirname, vmid); - - // Get the short filename. + // get the short filename. char* short_filename = strrchr(filename, '/'); if (short_filename == NULL) { short_filename = filename; @@ -1033,9 +1036,7 @@ static char* mmap_create_shared(size_t size) { mapAddress = (char*)::mmap((char*)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - // attempt to close the file - restart it if it was interrupted, - // but ignore other failures - RESTARTABLE(::close(fd), result); + result = ::close(fd); assert(result != OS_ERR, "could not close file"); if (mapAddress == MAP_FAILED) { @@ -1142,7 +1143,6 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor // constructs for the file and the shared memory mapping. if (mode == PerfMemory::PERF_MODE_RO) { mmap_prot = PROT_READ; - // No O_NOFOLLOW defined at buildtime, and it is not documented for open. #ifdef O_NOFOLLOW file_flags = O_RDONLY | O_NOFOLLOW; @@ -1205,21 +1205,28 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor FREE_C_HEAP_ARRAY(char, filename); // open the shared memory file for the give vmid - fd = open_sharedmem_file(rfilename, file_flags, CHECK); - assert(fd != OS_ERR, "unexpected value"); + fd = open_sharedmem_file(rfilename, file_flags, THREAD); + + if (fd == OS_ERR) { + return; + } + + if (HAS_PENDING_EXCEPTION) { + ::close(fd); + return; + } if (*sizep == 0) { size = sharedmem_filesize(fd, CHECK); - assert(size != 0, "unexpected size"); } else { size = *sizep; } + assert(size > 0, "unexpected size <= 0"); + mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0); - // attempt to close the file - restart if it gets interrupted, - // but ignore other failures - RESTARTABLE(::close(fd), result); + result = ::close(fd); assert(result != OS_ERR, "could not close file"); if (mapAddress == MAP_FAILED) { @@ -1230,7 +1237,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor "Could not map PerfMemory"); } - // It does not go through os api, the operation has to record from here. + // it does not go through os api, the operation has to record from here. MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal); *addr = mapAddress; @@ -1238,7 +1245,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor if (PerfTraceMemOps) { tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at " - INTPTR_FORMAT "\n", size, vmid, (void*)mapAddress); + INTPTR_FORMAT "\n", size, vmid, p2i((void*)mapAddress)); } } From 516438f368d53be93596baaf2d1f35d26770934c Mon Sep 17 00:00:00 2001 From: Konstantin Shefov Date: Sat, 20 Feb 2016 11:43:13 +0300 Subject: [PATCH 050/311] 8141616: Add new methods to the java Whitebox API Reviewed-by: kvn, dpochepk --- test/lib/sun/hotspot/WhiteBox.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index 6b7863ad938..9964831c3c9 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -119,6 +119,28 @@ public class WhiteBox { return getConstantPool0(aClass); } + private native int getConstantPoolCacheIndexTag0(); + public int getConstantPoolCacheIndexTag() { + return getConstantPoolCacheIndexTag0(); + } + + private native int getConstantPoolCacheLength0(Class aClass); + public int getConstantPoolCacheLength(Class aClass) { + Objects.requireNonNull(aClass); + return getConstantPoolCacheLength0(aClass); + } + + private native int remapInstructionOperandFromCPCache0(Class aClass, int index); + public int remapInstructionOperandFromCPCache(Class aClass, int index) { + Objects.requireNonNull(aClass); + return remapInstructionOperandFromCPCache0(aClass, index); + } + + private native int encodeConstantPoolIndyIndex0(int index); + public int encodeConstantPoolIndyIndex(int index) { + return encodeConstantPoolIndyIndex0(index); + } + // JVMTI private native void addToBootstrapClassLoaderSearch0(String segment); public void addToBootstrapClassLoaderSearch(String segment){ From 694727f144557feb6d568d1777b21d61488dfc68 Mon Sep 17 00:00:00 2001 From: Pavel Punegov Date: Tue, 1 Mar 2016 20:17:27 +0300 Subject: [PATCH 051/311] 8148563: compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java timesout Decrease amount of directives and threads Reviewed-by: neliasso --- .../jcmd/StressAddJcmdBase.java | 79 ++++++++++++------- .../jcmd/StressAddMultiThreadedTest.java | 29 +++---- .../jcmd/StressAddSequentiallyTest.java | 55 ------------- 3 files changed, 63 insertions(+), 100 deletions(-) delete mode 100644 hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java index 1da46dedf00..580d9b614ff 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java @@ -32,74 +32,99 @@ import jdk.test.lib.TimeLimitedRunner; import jdk.test.lib.Utils; import pool.PoolHelper; +import java.util.ArrayList; import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import java.util.stream.Stream; public abstract class StressAddJcmdBase { private static final int DIRECTIVES_AMOUNT = Integer.getInteger( "compiler.compilercontrol.jcmd.StressAddJcmdBase.directivesAmount", - 1000); - private static final int DIRECTIVE_FILES = Integer.getInteger( - "compiler.compilercontrol.jcmd.StressAddJcmdBase.directiveFiles", - 5); + 200); + private static final int TIMEOUT = Integer.getInteger( + "compiler.compilercontrol.jcmd.StressAddJcmdBase.timeout", + 30); private static final List DESCRIPTORS = new PoolHelper() .getAllMethods().stream() .map(pair -> AbstractTestBase .getValidMethodDescriptor(pair.first)) .collect(Collectors.toList()); + private static final String DIRECTIVE_FILE = "directives.json"; + private static final List VM_OPTIONS = new ArrayList<>(); + private static final Random RANDOM = Utils.getRandomInstance(); + + static { + VM_OPTIONS.add("-Xmixed"); + VM_OPTIONS.add("-XX:+UnlockDiagnosticVMOptions"); + VM_OPTIONS.add("-XX:+LogCompilation"); + VM_OPTIONS.add("-XX:CompilerDirectivesLimit=1001"); + } /** * Performs test */ public void test() { - List commands = prepareCommands(); - Executor executor = new TimeLimitedExecutor(commands); + HugeDirectiveUtil.createHugeFile(DESCRIPTORS, DIRECTIVE_FILE, + DIRECTIVES_AMOUNT); + Executor executor = new TimeLimitedExecutor(); List outputAnalyzers = executor.execute(); outputAnalyzers.get(0).shouldHaveExitValue(0); } /** - * Makes connection to the test VM + * Makes connection to the test VM and performs a diagnostic command * - * @param pid a pid of the VM under test - * @param commands a list of jcmd commands to be executed + * @param pid a pid of the VM under test * @return true if the test should continue invocation of this method */ - protected abstract boolean makeConnection(int pid, List commands); + protected abstract boolean makeConnection(int pid); /** * Finish test executions */ protected void finish() { } - private List prepareCommands() { - String[] files = new String[DIRECTIVE_FILES]; - for (int i = 0; i < DIRECTIVE_FILES; i++) { - files[i] = "directives" + i + ".json"; - HugeDirectiveUtil.createHugeFile(DESCRIPTORS, files[i], - DIRECTIVES_AMOUNT); + protected String nextCommand() { + int i = RANDOM.nextInt(JcmdCommand.values().length); + JcmdCommand jcmdCommand = JcmdCommand.values()[i]; + switch (jcmdCommand) { + case ADD: + return jcmdCommand.command + " " + DIRECTIVE_FILE; + case PRINT: + case CLEAR: + case REMOVE: + return jcmdCommand.command; + default: + throw new Error("TESTBUG: incorrect command: " + jcmdCommand); + } + } + + private enum JcmdCommand { + ADD("Compiler.directives_add"), + PRINT("Compiler.directives_print"), + CLEAR("Compiler.directives_clear"), + REMOVE("Compiler.directives_remove"); + + public final String command; + + JcmdCommand(String command) { + this.command = command; } - return Stream.of(files) - .map(file -> "Compiler.directives_add " + file) - .collect(Collectors.toList()); } private class TimeLimitedExecutor extends Executor { - private final List jcmdCommands; - - public TimeLimitedExecutor(List jcmdCommands) { + public TimeLimitedExecutor() { /* There are no need to check the state */ - super(true, null, null, jcmdCommands); - this.jcmdCommands = jcmdCommands; + super(true, VM_OPTIONS, null, null); } @Override protected OutputAnalyzer[] executeJCMD(int pid) { TimeLimitedRunner runner = new TimeLimitedRunner( - Utils.DEFAULT_TEST_TIMEOUT, + TimeUnit.SECONDS.toMillis(TIMEOUT), Utils.TIMEOUT_FACTOR, - () -> makeConnection(pid, jcmdCommands)); + () -> makeConnection(pid)); try { runner.call(); } catch (Exception e) { diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java index b2ad879351a..5bf1464fd55 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java @@ -27,21 +27,19 @@ * @summary Tests jcmd to be able to add a lot of huge directive files with * parallel executed jcmds until timeout has reached * @library /testlibrary /test/lib /compiler/testlibrary ../share / - * @ignore 8148563 * @build compiler.compilercontrol.jcmd.StressAddMultiThreadedTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils * compiler.compilercontrol.share.actions.* * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=360 compiler.compilercontrol.jcmd.StressAddMultiThreadedTest + * @run driver compiler.compilercontrol.jcmd.StressAddMultiThreadedTest */ package compiler.compilercontrol.jcmd; import jdk.test.lib.dcmd.PidJcmdExecutor; -import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; @@ -49,16 +47,15 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class StressAddMultiThreadedTest extends StressAddJcmdBase { - private static final int THREADS; + private static final int THREADS = Integer.getInteger( + "compiler.compilercontrol.jcmd.StressAddMultiThreadedTest.threads", + 5); + private volatile int commands = Integer.getInteger( + "compiler.compilercontrol.jcmd.StressAddMultiThreadedTest.commands", + 20); private final BlockingQueue queue; private final ExecutorService executor; - static { - THREADS = Runtime.getRuntime().availableProcessors() - * Integer.getInteger("compiler.compilercontrol.jcmd" + - ".StressAddMultiThreadedTest.threadFactor", 10); - } - public StressAddMultiThreadedTest() { queue = new ArrayBlockingQueue<>(THREADS); executor = new ThreadPoolExecutor(THREADS, THREADS, 100, @@ -71,14 +68,10 @@ public class StressAddMultiThreadedTest extends StressAddJcmdBase { } @Override - protected boolean makeConnection(int pid, List commands) { - commands.forEach(command -> { - if (!executor.isShutdown()) { - executor.submit(() -> new PidJcmdExecutor(String.valueOf(pid)) - .execute(command)); - } - }); - return !executor.isShutdown(); + protected boolean makeConnection(int pid) { + executor.submit(() -> new PidJcmdExecutor(String.valueOf(pid)) + .execute(nextCommand())); + return (--commands != 0); } @Override diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java deleted file mode 100644 index f8509128321..00000000000 --- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2015, 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 8137167 - * @summary Tests jcmd to be able to add a lot of huge directives - * @library /testlibrary /test/lib /compiler/testlibrary ../share / - * @build compiler.compilercontrol.jcmd.StressAddSequentiallyTest - * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox - * compiler.testlibrary.CompilerUtils - * compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=300 compiler.compilercontrol.jcmd.StressAddSequentiallyTest - */ - -package compiler.compilercontrol.jcmd; - -import jdk.test.lib.dcmd.PidJcmdExecutor; - -import java.util.List; - -public class StressAddSequentiallyTest extends StressAddJcmdBase { - public static void main(String[] args) { - new StressAddSequentiallyTest().test(); - } - - @Override - protected boolean makeConnection(int pid, List commands) { - commands.forEach(command -> new PidJcmdExecutor(String.valueOf(pid)) - .execute(command)); - return true; - } -} From c40e7bc21fe5a0fb0f6e441b5da92a67add4b0b5 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Thu, 3 Mar 2016 09:33:30 -0800 Subject: [PATCH 052/311] 8149159: Clean up Unsafe Reviewed-by: jrose, kvn, stsmirno, chegar, aph, psandoz, redestad, twisti --- hotspot/src/share/vm/classfile/vmSymbols.hpp | 3 +- hotspot/src/share/vm/oops/method.cpp | 75 -- hotspot/src/share/vm/opto/library_call.cpp | 6 +- hotspot/src/share/vm/prims/nativeLookup.cpp | 4 +- hotspot/src/share/vm/prims/unsafe.cpp | 961 +++++++----------- hotspot/src/share/vm/prims/unsafe.hpp | 39 + .../src/share/vm/runtime/interfaceSupport.hpp | 8 +- hotspot/src/share/vm/shark/sharkBuilder.cpp | 2 +- .../intrinsics/IntrinsicDisabledTest.java | 8 +- 9 files changed, 428 insertions(+), 678 deletions(-) create mode 100644 hotspot/src/share/vm/prims/unsafe.hpp diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 4cce6873268..fcc4ad8be25 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -1035,14 +1035,13 @@ do_name( updateByteBuffer_A_name, "updateByteBuffer") \ \ /* support for Unsafe */ \ - do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ do_class(jdk_internal_misc_Unsafe, "jdk/internal/misc/Unsafe") \ \ do_intrinsic(_allocateInstance, jdk_internal_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \ do_name( allocateInstance_name, "allocateInstance") \ do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \ do_intrinsic(_copyMemory, jdk_internal_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \ - do_name( copyMemory_name, "copyMemory") \ + do_name( copyMemory_name, "copyMemory0") \ do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \ do_intrinsic(_loadFence, jdk_internal_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \ do_name( loadFence_name, "loadFence") \ diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 7620ea9f985..8c6029e6fef 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -1338,73 +1338,6 @@ vmSymbols::SID Method::klass_id_for_intrinsics(const Klass* holder) { return vmSymbols::find_sid(klass_name); } -static bool is_unsafe_alias(vmSymbols::SID name_id) { - // All 70 intrinsic candidate methods from sun.misc.Unsafe in 1.8. - // Some have the same method name but different signature, e.g. - // getByte(long), getByte(Object,long) - switch (name_id) { - case vmSymbols::VM_SYMBOL_ENUM_NAME(allocateInstance_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(copyMemory_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(loadFence_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(storeFence_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(fullFence_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getBoolean_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getByte_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getShort_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getChar_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloat_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getDouble_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putBoolean_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putByte_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putShort_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putChar_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloat_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putDouble_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getObjectVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getBooleanVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getByteVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getShortVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getCharVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getIntVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getLongVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloatVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getDoubleVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putObjectVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putBooleanVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putByteVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putShortVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putCharVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putIntVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putLongVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloatVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putDoubleVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAddress_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putAddress_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(park_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(unpark_name): - return true; - } - - return false; -} - void Method::init_intrinsic_id() { assert(_intrinsic_id == vmIntrinsics::_none, "do this just once"); const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte)); @@ -1457,14 +1390,6 @@ void Method::init_intrinsic_id() { if (is_static() != MethodHandles::is_signature_polymorphic_static(id)) id = vmIntrinsics::_none; break; - - case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Unsafe): - // Map sun.misc.Unsafe to jdk.internal.misc.Unsafe - if (!is_unsafe_alias(name_id)) break; - // pretend it is the corresponding method in the internal Unsafe class: - klass_id = vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_misc_Unsafe); - id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); - break; } if (id != vmIntrinsics::_none) { diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 240321cb231..4ecca52fb3d 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -48,6 +48,7 @@ #include "opto/runtime.hpp" #include "opto/subnode.hpp" #include "prims/nativeLookup.hpp" +#include "prims/unsafe.hpp" #include "runtime/sharedRuntime.hpp" #include "trace/traceMacros.hpp" @@ -2306,9 +2307,6 @@ void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset, } -// Interpret Unsafe.fieldOffset cookies correctly: -extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); - const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr) { // Attempt to infer a sharper value type from the offset and base type. ciKlass* sharpened_klass = NULL; @@ -4466,7 +4464,7 @@ bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { } //----------------------inline_unsafe_copyMemory------------------------- -// public native void Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); +// public native void Unsafe.copyMemory0(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); bool LibraryCallKit::inline_unsafe_copyMemory() { if (callee()->is_static()) return false; // caller must have the capability! null_check_receiver(); // null-check receiver diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp index c89e4f10c32..51525c26f2d 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.cpp +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp @@ -35,6 +35,7 @@ #include "oops/symbol.hpp" #include "prims/jvm_misc.hpp" #include "prims/nativeLookup.hpp" +#include "prims/unsafe.hpp" #include "runtime/arguments.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" @@ -107,8 +108,6 @@ char* NativeLookup::long_jni_name(const methodHandle& method) { } extern "C" { - void JNICALL JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafecls); - void JNICALL JVM_RegisterSunMiscUnsafeMethods(JNIEnv *env, jclass unsafecls); void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls); void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass); @@ -123,7 +122,6 @@ extern "C" { static JNINativeMethod lookup_special_native_methods[] = { { CC"Java_jdk_internal_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterJDKInternalMiscUnsafeMethods) }, - { CC"Java_sun_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterSunMiscUnsafeMethods) }, { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) }, { CC"Java_jdk_internal_perf_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) }, { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index cdd4334e229..dc60ebfd208 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -30,6 +30,7 @@ #include "oops/oop.inline.hpp" #include "prims/jni.h" #include "prims/jvm.h" +#include "prims/unsafe.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/globals.hpp" #include "runtime/interfaceSupport.hpp" @@ -45,8 +46,8 @@ #include "gc/g1/g1SATBCardTableModRefBS.hpp" #endif // INCLUDE_ALL_GCS -/* - * Implementation of class Unsafe +/** + * Implementation of the jdk.internal.misc.Unsafe class */ @@ -56,25 +57,15 @@ #define UNSAFE_ENTRY(result_type, header) \ - JVM_ENTRY(result_type, header) + JVM_ENTRY(static result_type, header) -// Can't use UNSAFE_LEAF because it has the signature of a straight -// call into the runtime (just like JVM_LEAF, funny that) but it's -// called like a Java Native and thus the wrapper built for it passes -// arguments like a JNI call. It expects those arguments to be popped -// from the stack on Intel like all good JNI args are, and adjusts the -// stack according. Since the JVM_LEAF call expects no extra -// arguments the stack isn't popped in the C code, is pushed by the -// wrapper and we get sick. -//#define UNSAFE_LEAF(result_type, header) \ -// JVM_LEAF(result_type, header) +#define UNSAFE_LEAF(result_type, header) \ + JVM_LEAF(static result_type, header) #define UNSAFE_END JVM_END -#define UnsafeWrapper(arg) /*nothing, for the present*/ - -inline void* addr_from_java(jlong addr) { +static inline void* addr_from_java(jlong addr) { // This assert fails in a variety of ways on 32-bit systems. // It is impossible to predict whether native code that converts // pointers to longs will sign-extend or zero-extend the addresses. @@ -82,7 +73,7 @@ inline void* addr_from_java(jlong addr) { return (void*)(uintptr_t)addr; } -inline jlong addr_to_java(void* p) { +static inline jlong addr_to_java(void* p) { assert(p == (void*)(uintptr_t)p, "must not be odd high bits"); return (uintptr_t)p; } @@ -98,24 +89,17 @@ inline jlong addr_to_java(void* p) { // through conversion functions when going between the VM and the Unsafe API. // The conversion functions just happen to be no-ops at present. -inline jlong field_offset_to_byte_offset(jlong field_offset) { +static inline jlong field_offset_to_byte_offset(jlong field_offset) { return field_offset; } -inline jlong field_offset_from_byte_offset(jlong byte_offset) { +static inline jlong field_offset_from_byte_offset(jlong byte_offset) { return byte_offset; } -inline jint invocation_key_from_method_slot(jint slot) { - return slot; -} - -inline jint invocation_key_to_method_slot(jint key) { - return key; -} - -inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { +static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { jlong byte_offset = field_offset_to_byte_offset(field_offset); + #ifdef ASSERT if (p != NULL) { assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset"); @@ -128,10 +112,12 @@ inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { assert(byte_offset < p_size, "Unsafe access: offset " INT64_FORMAT " > object's size " INT64_FORMAT, byte_offset, p_size); } #endif - if (sizeof(char*) == sizeof(jint)) // (this constant folds!) + + if (sizeof(char*) == sizeof(jint)) { // (this constant folds!) return (address)p + (jint) byte_offset; - else + } else { return (address)p + byte_offset; + } } // Externally callable versions: @@ -142,12 +128,6 @@ jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) { jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { return byte_offset; } -jint Unsafe_invocation_key_from_method_slot(jint slot) { - return invocation_key_from_method_slot(slot); -} -jint Unsafe_invocation_key_to_method_slot(jint key) { - return invocation_key_to_method_slot(key); -} ///// Data in the Java heap. @@ -177,17 +157,19 @@ jint Unsafe_invocation_key_to_method_slot(jint key) { // These functions allow a null base pointer with an arbitrary address. // But if the base pointer is non-null, the offset should make some sense. // That is, it should be in the range [0, MAX_OBJECT_SIZE]. -UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) - UnsafeWrapper("Unsafe_GetObject"); +UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj); oop v; + if (UseCompressedOops) { narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); v = oopDesc::decode_heap_oop(n); } else { v = *(oop*)index_oop_from_field_offset_long(p, offset); } + jobject ret = JNIHandles::make_local(env, v); + #if INCLUDE_ALL_GCS // We could be accessing the referent field in a reference // object. If G1 is enabled then we need to register non-null @@ -212,67 +194,71 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, } } #endif // INCLUDE_ALL_GCS - return ret; -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) - UnsafeWrapper("Unsafe_SetObject"); + return ret; +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); + if (UseCompressedOops) { oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); } else { oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) - UnsafeWrapper("Unsafe_GetObjectVolatile"); +UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj); void* addr = index_oop_from_field_offset_long(p, offset); + volatile oop v; + if (UseCompressedOops) { volatile narrowOop n = *(volatile narrowOop*) addr; (void)const_cast(v = oopDesc::decode_heap_oop(n)); } else { (void)const_cast(v = *(volatile oop*) addr); } + OrderAccess::acquire(); return JNIHandles::make_local(env, v); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) - UnsafeWrapper("Unsafe_SetObjectVolatile"); +UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); void* addr = index_oop_from_field_offset_long(p, offset); OrderAccess::release(); + if (UseCompressedOops) { oop_store((narrowOop*)addr, x); } else { oop_store((oop*)addr, x); } + OrderAccess::fence(); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) - UnsafeWrapper("Unsafe_GetUncompressedObject"); +UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) { oop v = *(oop*) (address) addr; + return JNIHandles::make_local(env, v); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jclass, Unsafe_GetJavaMirror(JNIEnv *env, jobject unsafe, jlong metaspace_klass)) - UnsafeWrapper("Unsafe_GetJavaMirror"); +UNSAFE_ENTRY(jclass, Unsafe_GetJavaMirror(JNIEnv *env, jobject unsafe, jlong metaspace_klass)) { Klass* klass = (Klass*) (address) metaspace_klass; - return (jclass) JNIHandles::make_local(klass->java_mirror()); -UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_GetKlassPointer(JNIEnv *env, jobject unsafe, jobject obj)) - UnsafeWrapper("Unsafe_GetKlassPointer"); + return (jclass) JNIHandles::make_local(klass->java_mirror()); +} UNSAFE_END + +UNSAFE_ENTRY(jlong, Unsafe_GetKlassPointer(JNIEnv *env, jobject unsafe, jobject obj)) { oop o = JNIHandles::resolve(obj); jlong klass = (jlong) (address) o->klass(); + return klass; -UNSAFE_END +} UNSAFE_END #ifndef SUPPORTS_NATIVE_CX8 @@ -303,83 +289,54 @@ UNSAFE_END // the address of the field _after_ we have acquired the lock, else the object may have // been moved by the GC -UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) - UnsafeWrapper("Unsafe_GetLongVolatile"); - { - if (VM_Version::supports_cx8()) { - GET_FIELD_VOLATILE(obj, offset, jlong, v); - return v; - } - else { - Handle p (THREAD, JNIHandles::resolve(obj)); - jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); - jlong value = Atomic::load(addr); - return value; - } +UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { + if (VM_Version::supports_cx8()) { + GET_FIELD_VOLATILE(obj, offset, jlong, v); + return v; + } else { + Handle p (THREAD, JNIHandles::resolve(obj)); + jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong value = Atomic::load(addr); + return value; } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) - UnsafeWrapper("Unsafe_SetLongVolatile"); - { - if (VM_Version::supports_cx8()) { - SET_FIELD_VOLATILE(obj, offset, jlong, x); - } - else { - Handle p (THREAD, JNIHandles::resolve(obj)); - jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); - Atomic::store(x, addr); - } +UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) { + if (VM_Version::supports_cx8()) { + SET_FIELD_VOLATILE(obj, offset, jlong, x); + } else { + Handle p (THREAD, JNIHandles::resolve(obj)); + jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + Atomic::store(x, addr); } -UNSAFE_END +} UNSAFE_END #endif // not SUPPORTS_NATIVE_CX8 -UNSAFE_ENTRY(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_IsBigEndian0"); - { +UNSAFE_LEAF(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) { #ifdef VM_LITTLE_ENDIAN - return false; + return false; #else - return true; + return true; #endif - } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_UnalignedAccess0"); - { - return UseUnalignedAccesses; - } -UNSAFE_END +UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) { + return UseUnalignedAccesses; +} UNSAFE_END -#define DEFINE_GETSETOOP(jboolean, Boolean) \ +#define DEFINE_GETSETOOP(java_type, Type) \ \ -UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) \ - UnsafeWrapper("Unsafe_Get"#Boolean); \ - if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); \ - GET_FIELD(obj, offset, jboolean, v); \ +UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ + GET_FIELD(obj, offset, java_type, v); \ return v; \ -UNSAFE_END \ +} UNSAFE_END \ \ -UNSAFE_ENTRY(void, Unsafe_Set##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset, jboolean x)) \ - UnsafeWrapper("Unsafe_Set"#Boolean); \ - if (obj == NULL) THROW(vmSymbols::java_lang_NullPointerException()); \ - SET_FIELD(obj, offset, jboolean, x); \ -UNSAFE_END \ - \ -UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \ - UnsafeWrapper("Unsafe_Get"#Boolean); \ - GET_FIELD(obj, offset, jboolean, v); \ - return v; \ -UNSAFE_END \ - \ -UNSAFE_ENTRY(void, Unsafe_Set##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \ - UnsafeWrapper("Unsafe_Set"#Boolean); \ - SET_FIELD(obj, offset, jboolean, x); \ -UNSAFE_END \ +UNSAFE_ENTRY(void, Unsafe_Set##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ + SET_FIELD(obj, offset, java_type, x); \ +} UNSAFE_END \ \ // END DEFINE_GETSETOOP. @@ -394,18 +351,16 @@ DEFINE_GETSETOOP(jdouble, Double); #undef DEFINE_GETSETOOP -#define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \ +#define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \ \ -UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \ - UnsafeWrapper("Unsafe_Get"#Boolean); \ - GET_FIELD_VOLATILE(obj, offset, jboolean, v); \ +UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ + GET_FIELD_VOLATILE(obj, offset, java_type, v); \ return v; \ -UNSAFE_END \ +} UNSAFE_END \ \ -UNSAFE_ENTRY(void, Unsafe_Set##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \ - UnsafeWrapper("Unsafe_Set"#Boolean); \ - SET_FIELD_VOLATILE(obj, offset, jboolean, x); \ -UNSAFE_END \ +UNSAFE_ENTRY(void, Unsafe_Set##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ + SET_FIELD_VOLATILE(obj, offset, java_type, x); \ +} UNSAFE_END \ \ // END DEFINE_GETSETOOP_VOLATILE. @@ -425,59 +380,53 @@ DEFINE_GETSETOOP_VOLATILE(jlong, Long); // The non-intrinsified versions of setOrdered just use setVolatile -UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) - UnsafeWrapper("Unsafe_SetOrderedInt"); +UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) { SET_FIELD_VOLATILE(obj, offset, jint, x); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) - UnsafeWrapper("Unsafe_SetOrderedObject"); +UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); void* addr = index_oop_from_field_offset_long(p, offset); OrderAccess::release(); + if (UseCompressedOops) { oop_store((narrowOop*)addr, x); } else { oop_store((oop*)addr, x); } - OrderAccess::fence(); -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) - UnsafeWrapper("Unsafe_SetOrderedLong"); + OrderAccess::fence(); +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) { #ifdef SUPPORTS_NATIVE_CX8 SET_FIELD_VOLATILE(obj, offset, jlong, x); #else + // Keep old code for platforms which may not have atomic long (8 bytes) instructions - { - if (VM_Version::supports_cx8()) { - SET_FIELD_VOLATILE(obj, offset, jlong, x); - } - else { - Handle p (THREAD, JNIHandles::resolve(obj)); - jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); - Atomic::store(x, addr); - } + if (VM_Version::supports_cx8()) { + SET_FIELD_VOLATILE(obj, offset, jlong, x); + } else { + Handle p(THREAD, JNIHandles::resolve(obj)); + jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + Atomic::store(x, addr); } #endif -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_LoadFence"); +UNSAFE_LEAF(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) { OrderAccess::acquire(); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_StoreFence(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_StoreFence"); +UNSAFE_LEAF(void, Unsafe_StoreFence(JNIEnv *env, jobject unsafe)) { OrderAccess::release(); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_FullFence"); +UNSAFE_LEAF(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) { OrderAccess::fence(); -UNSAFE_END +} UNSAFE_END ////// Data in the C heap. @@ -486,24 +435,22 @@ UNSAFE_END // #define DEFINE_GETSETNATIVE(java_type, Type, native_type) \ \ -UNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) \ - UnsafeWrapper("Unsafe_GetNative"#Type); \ +UNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) { \ void* p = addr_from_java(addr); \ JavaThread* t = JavaThread::current(); \ t->set_doing_unsafe_access(true); \ java_type x = *(volatile native_type*)p; \ t->set_doing_unsafe_access(false); \ return x; \ -UNSAFE_END \ +} UNSAFE_END \ \ -UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) \ - UnsafeWrapper("Unsafe_SetNative"#Type); \ +UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) { \ JavaThread* t = JavaThread::current(); \ t->set_doing_unsafe_access(true); \ void* p = addr_from_java(addr); \ *(volatile native_type*)p = x; \ t->set_doing_unsafe_access(false); \ -UNSAFE_END \ +} UNSAFE_END \ \ // END DEFINE_GETSETNATIVE. @@ -517,8 +464,7 @@ DEFINE_GETSETNATIVE(jdouble, Double, double); #undef DEFINE_GETSETNATIVE -UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr)) - UnsafeWrapper("Unsafe_GetNativeLong"); +UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr)) { JavaThread* t = JavaThread::current(); // We do it this way to avoid problems with access to heap using 64 // bit loads, as jlong in heap could be not 64-bit aligned, and on @@ -526,7 +472,8 @@ UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr t->set_doing_unsafe_access(true); void* p = addr_from_java(addr); jlong x; - if (((intptr_t)p & 7) == 0) { + + if (is_ptr_aligned(p, sizeof(jlong)) == 0) { // jlong is aligned, do a volatile access x = *(volatile jlong*)p; } else { @@ -535,17 +482,19 @@ UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr acc.words[1] = ((volatile jint*)p)[1]; x = acc.long_value; } - t->set_doing_unsafe_access(false); - return x; -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) - UnsafeWrapper("Unsafe_SetNativeLong"); + t->set_doing_unsafe_access(false); + + return x; +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) { JavaThread* t = JavaThread::current(); // see comment for Unsafe_GetNativeLong t->set_doing_unsafe_access(true); void* p = addr_from_java(addr); - if (((intptr_t)p & 7) == 0) { + + if (is_ptr_aligned(p, sizeof(jlong))) { // jlong is aligned, do a volatile access *(volatile jlong*)p = x; } else { @@ -554,119 +503,81 @@ UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, ((volatile jint*)p)[0] = acc.words[0]; ((volatile jint*)p)[1] = acc.words[1]; } + t->set_doing_unsafe_access(false); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr)) - UnsafeWrapper("Unsafe_GetNativeAddress"); +UNSAFE_LEAF(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr)) { void* p = addr_from_java(addr); - return addr_to_java(*(void**)p); -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) - UnsafeWrapper("Unsafe_SetNativeAddress"); + return addr_to_java(*(void**)p); +} UNSAFE_END + +UNSAFE_LEAF(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) { void* p = addr_from_java(addr); *(void**)p = addr_from_java(x); -UNSAFE_END +} UNSAFE_END ////// Allocation requests -UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) - UnsafeWrapper("Unsafe_AllocateInstance"); - { - ThreadToNativeFromVM ttnfv(thread); - return env->AllocObject(cls); - } -UNSAFE_END +UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) { + ThreadToNativeFromVM ttnfv(thread); + return env->AllocObject(cls); +} UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory(JNIEnv *env, jobject unsafe, jlong size)) - UnsafeWrapper("Unsafe_AllocateMemory"); +UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory0(JNIEnv *env, jobject unsafe, jlong size)) { size_t sz = (size_t)size; - if (sz != (julong)size || size < 0) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); - } - if (sz == 0) { - return 0; - } + sz = round_to(sz, HeapWordSize); void* x = os::malloc(sz, mtInternal); - if (x == NULL) { - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); - } - //Copy::fill_to_words((HeapWord*)x, sz / HeapWordSize); - return addr_to_java(x); -UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory(JNIEnv *env, jobject unsafe, jlong addr, jlong size)) - UnsafeWrapper("Unsafe_ReallocateMemory"); + return addr_to_java(x); +} UNSAFE_END + +UNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory0(JNIEnv *env, jobject unsafe, jlong addr, jlong size)) { void* p = addr_from_java(addr); size_t sz = (size_t)size; - if (sz != (julong)size || size < 0) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); - } - if (sz == 0) { - os::free(p); - return 0; - } sz = round_to(sz, HeapWordSize); - void* x = (p == NULL) ? os::malloc(sz, mtInternal) : os::realloc(p, sz, mtInternal); - if (x == NULL) { - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); - } + + void* x = os::realloc(p, sz, mtInternal); + return addr_to_java(x); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_FreeMemory(JNIEnv *env, jobject unsafe, jlong addr)) - UnsafeWrapper("Unsafe_FreeMemory"); +UNSAFE_ENTRY(void, Unsafe_FreeMemory0(JNIEnv *env, jobject unsafe, jlong addr)) { void* p = addr_from_java(addr); - if (p == NULL) { - return; - } - os::free(p); -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetMemory(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong size, jbyte value)) - UnsafeWrapper("Unsafe_SetMemory"); + os::free(p); +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetMemory0(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong size, jbyte value)) { size_t sz = (size_t)size; - if (sz != (julong)size || size < 0) { - THROW(vmSymbols::java_lang_IllegalArgumentException()); - } + oop base = JNIHandles::resolve(obj); void* p = index_oop_from_field_offset_long(base, offset); - Copy::fill_to_memory_atomic(p, sz, value); -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_CopyMemory(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size)) - UnsafeWrapper("Unsafe_CopyMemory"); - if (size == 0) { - return; - } + Copy::fill_to_memory_atomic(p, sz, value); +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_CopyMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size)) { size_t sz = (size_t)size; - if (sz != (julong)size || size < 0) { - THROW(vmSymbols::java_lang_IllegalArgumentException()); - } + oop srcp = JNIHandles::resolve(srcObj); oop dstp = JNIHandles::resolve(dstObj); - if (dstp != NULL && !dstp->is_typeArray()) { - // NYI: This works only for non-oop arrays at present. - // Generalizing it would be reasonable, but requires card marking. - // Also, autoboxing a Long from 0L in copyMemory(x,y, 0L,z, n) would be bad. - THROW(vmSymbols::java_lang_IllegalArgumentException()); - } + void* src = index_oop_from_field_offset_long(srcp, srcOffset); void* dst = index_oop_from_field_offset_long(dstp, dstOffset); + Copy::conjoint_memory_atomic(src, dst, sz); -UNSAFE_END +} UNSAFE_END // This function is a leaf since if the source and destination are both in native memory // the copy may potentially be very large, and we don't want to disable GC if we can avoid it. // If either source or destination (or both) are on the heap, the function will enter VM using // JVM_ENTRY_FROM_LEAF -JVM_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size, jlong elemSize)) { - UnsafeWrapper("Unsafe_CopySwapMemory0"); - +UNSAFE_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size, jlong elemSize)) { size_t sz = (size_t)size; size_t esz = (size_t)elemSize; @@ -689,32 +600,24 @@ JVM_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcOb Copy::conjoint_swap(src, dst, sz, esz); } JVM_END } -} JVM_END +} UNSAFE_END ////// Random queries -// See comment at file start about UNSAFE_LEAF -//UNSAFE_LEAF(jint, Unsafe_AddressSize()) -UNSAFE_ENTRY(jint, Unsafe_AddressSize(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_AddressSize"); +UNSAFE_LEAF(jint, Unsafe_AddressSize0(JNIEnv *env, jobject unsafe)) { return sizeof(void*); -UNSAFE_END +} UNSAFE_END -// See comment at file start about UNSAFE_LEAF -//UNSAFE_LEAF(jint, Unsafe_PageSize()) -UNSAFE_ENTRY(jint, Unsafe_PageSize(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_PageSize"); +UNSAFE_LEAF(jint, Unsafe_PageSize()) { return os::vm_page_size(); -UNSAFE_END +} UNSAFE_END -jint find_field_offset(jobject field, int must_be_static, TRAPS) { - if (field == NULL) { - THROW_0(vmSymbols::java_lang_NullPointerException()); - } +static jint find_field_offset(jobject field, int must_be_static, TRAPS) { + assert(field != NULL, "field must not be NULL"); oop reflected = JNIHandles::resolve_non_null(field); oop mirror = java_lang_reflect_Field::clazz(reflected); - Klass* k = java_lang_Class::as_Klass(mirror); + Klass* k = java_lang_Class::as_Klass(mirror); int slot = java_lang_reflect_Field::slot(reflected); int modifiers = java_lang_reflect_Field::modifiers(reflected); @@ -729,18 +632,17 @@ jint find_field_offset(jobject field, int must_be_static, TRAPS) { return field_offset_from_byte_offset(offset); } -UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset(JNIEnv *env, jobject unsafe, jobject field)) - UnsafeWrapper("Unsafe_ObjectFieldOffset"); +UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset0(JNIEnv *env, jobject unsafe, jobject field)) { return find_field_offset(field, 0, THREAD); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_StaticFieldOffset(JNIEnv *env, jobject unsafe, jobject field)) - UnsafeWrapper("Unsafe_StaticFieldOffset"); +UNSAFE_ENTRY(jlong, Unsafe_StaticFieldOffset0(JNIEnv *env, jobject unsafe, jobject field)) { return find_field_offset(field, 1, THREAD); -UNSAFE_END +} UNSAFE_END + +UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBase0(JNIEnv *env, jobject unsafe, jobject field)) { + assert(field != NULL, "field must not be NULL"); -UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsafe, jobject field)) - UnsafeWrapper("Unsafe_StaticFieldBase"); // Note: In this VM implementation, a field address is always a short // offset from the base of a a klass metaobject. Thus, the full dynamic // range of the return type is never used. However, some implementations @@ -749,8 +651,6 @@ UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsaf // large. In that last case, this function would return NULL, since // the address would operate alone, without any base pointer. - if (field == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); - oop reflected = JNIHandles::resolve_non_null(field); oop mirror = java_lang_reflect_Field::clazz(reflected); int modifiers = java_lang_reflect_Field::modifiers(reflected); @@ -760,13 +660,11 @@ UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsaf } return JNIHandles::make_local(env, mirror); -UNSAFE_END +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized0(JNIEnv *env, jobject unsafe, jobject clazz)) { + assert(clazz != NULL, "clazz must not be NULL"); -UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized(JNIEnv *env, jobject unsafe, jobject clazz)) { - UnsafeWrapper("Unsafe_EnsureClassInitialized"); - if (clazz == NULL) { - THROW(vmSymbols::java_lang_NullPointerException()); - } oop mirror = JNIHandles::resolve_non_null(clazz); Klass* klass = java_lang_Class::as_Klass(mirror); @@ -777,26 +675,26 @@ UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized(JNIEnv *env, jobject unsafe, jo } UNSAFE_END -UNSAFE_ENTRY(jboolean, Unsafe_ShouldBeInitialized(JNIEnv *env, jobject unsafe, jobject clazz)) { - UnsafeWrapper("Unsafe_ShouldBeInitialized"); - if (clazz == NULL) { - THROW_(vmSymbols::java_lang_NullPointerException(), false); - } +UNSAFE_ENTRY(jboolean, Unsafe_ShouldBeInitialized0(JNIEnv *env, jobject unsafe, jobject clazz)) { + assert(clazz != NULL, "clazz must not be NULL"); + oop mirror = JNIHandles::resolve_non_null(clazz); Klass* klass = java_lang_Class::as_Klass(mirror); + if (klass != NULL && klass->should_be_initialized()) { return true; } + return false; } UNSAFE_END -static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) { - if (acls == NULL) { - THROW(vmSymbols::java_lang_NullPointerException()); - } - oop mirror = JNIHandles::resolve_non_null(acls); - Klass* k = java_lang_Class::as_Klass(mirror); +static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) { + assert(clazz != NULL, "clazz must not be NULL"); + + oop mirror = JNIHandles::resolve_non_null(clazz); + Klass* k = java_lang_Class::as_Klass(mirror); + if (k == NULL || !k->is_array_klass()) { THROW(vmSymbols::java_lang_InvalidClassException()); } else if (k->is_objArray_klass()) { @@ -812,18 +710,18 @@ static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) { } } -UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset(JNIEnv *env, jobject unsafe, jclass acls)) - UnsafeWrapper("Unsafe_ArrayBaseOffset"); +UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) { int base = 0, scale = 0; - getBaseAndScale(base, scale, acls, CHECK_0); + getBaseAndScale(base, scale, clazz, CHECK_0); + return field_offset_from_byte_offset(base); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass acls)) - UnsafeWrapper("Unsafe_ArrayIndexScale"); +UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) { int base = 0, scale = 0; - getBaseAndScale(base, scale, acls, CHECK_0); + getBaseAndScale(base, scale, clazz, CHECK_0); + // This VM packs both fields and array elements down to the byte. // But watch out: If this changes, so that array references for // a given primitive type (say, T_BOOLEAN) use different memory units @@ -839,100 +737,88 @@ UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass ac // The following allows for a pretty general fieldOffset cookie scheme, // but requires it to be linear in byte offset. return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0); -UNSAFE_END +} UNSAFE_END static inline void throw_new(JNIEnv *env, const char *ename) { char buf[100]; + jio_snprintf(buf, 100, "%s%s", "java/lang/", ename); + jclass cls = env->FindClass(buf); if (env->ExceptionCheck()) { env->ExceptionClear(); tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", buf); return; } - char* msg = NULL; - env->ThrowNew(cls, msg); + + env->ThrowNew(cls, NULL); } static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) { - { - // Code lifted from JDK 1.3 ClassLoader.c + // Code lifted from JDK 1.3 ClassLoader.c - jbyte *body; - char *utfName; - jclass result = 0; - char buf[128]; + jbyte *body; + char *utfName = NULL; + jclass result = 0; + char buf[128]; - if (UsePerfData) { - ClassLoader::unsafe_defineClassCallCounter()->inc(); - } + assert(data != NULL, "Class bytes must not be NULL"); + assert(length >= 0, "length must not be negative: %d", length); - if (data == NULL) { - throw_new(env, "NullPointerException"); - return 0; - } + if (UsePerfData) { + ClassLoader::unsafe_defineClassCallCounter()->inc(); + } - /* Work around 4153825. malloc crashes on Solaris when passed a - * negative size. - */ - if (length < 0) { - throw_new(env, "ArrayIndexOutOfBoundsException"); - return 0; - } + body = NEW_C_HEAP_ARRAY(jbyte, length, mtInternal); + if (body == NULL) { + throw_new(env, "OutOfMemoryError"); + return 0; + } - body = NEW_C_HEAP_ARRAY(jbyte, length, mtInternal); + env->GetByteArrayRegion(data, offset, length, body); + if (env->ExceptionOccurred()) { + goto free_body; + } - if (body == 0) { + if (name != NULL) { + uint len = env->GetStringUTFLength(name); + int unicode_len = env->GetStringLength(name); + + if (len >= sizeof(buf)) { + utfName = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); + if (utfName == NULL) { throw_new(env, "OutOfMemoryError"); - return 0; - } - - env->GetByteArrayRegion(data, offset, length, body); - - if (env->ExceptionOccurred()) goto free_body; - - if (name != NULL) { - uint len = env->GetStringUTFLength(name); - int unicode_len = env->GetStringLength(name); - if (len >= sizeof(buf)) { - utfName = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); - if (utfName == NULL) { - throw_new(env, "OutOfMemoryError"); - goto free_body; - } - } else { - utfName = buf; - } - env->GetStringUTFRegion(name, 0, unicode_len, utfName); - //VerifyFixClassname(utfName); - for (uint i = 0; i < len; i++) { - if (utfName[i] == '.') utfName[i] = '/'; - } + } } else { - utfName = NULL; + utfName = buf; } - result = JVM_DefineClass(env, utfName, loader, body, length, pd); + env->GetStringUTFRegion(name, 0, unicode_len, utfName); - if (utfName && utfName != buf) - FREE_C_HEAP_ARRAY(char, utfName); + for (uint i = 0; i < len; i++) { + if (utfName[i] == '.') utfName[i] = '/'; + } + } + + result = JVM_DefineClass(env, utfName, loader, body, length, pd); + + if (utfName && utfName != buf) { + FREE_C_HEAP_ARRAY(char, utfName); + } free_body: - FREE_C_HEAP_ARRAY(jbyte, body); - return result; - } + FREE_C_HEAP_ARRAY(jbyte, body); + return result; } -UNSAFE_ENTRY(jclass, Unsafe_DefineClass(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd)) - UnsafeWrapper("Unsafe_DefineClass"); - { - ThreadToNativeFromVM ttnfv(thread); - return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd); - } -UNSAFE_END +UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd)) { + ThreadToNativeFromVM ttnfv(thread); + + return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd); +} UNSAFE_END // define a class but do not make it known to the class loader or system dictionary @@ -986,45 +872,35 @@ UNSAFE_END static instanceKlassHandle Unsafe_DefineAnonymousClass_impl(JNIEnv *env, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh, - HeapWord* *temp_alloc, + u1** temp_alloc, TRAPS) { + assert(host_class != NULL, "host_class must not be NULL"); + assert(data != NULL, "data must not be NULL"); if (UsePerfData) { ClassLoader::unsafe_defineClassCallCounter()->inc(); } - if (data == NULL) { - THROW_0(vmSymbols::java_lang_NullPointerException()); - } - jint length = typeArrayOop(JNIHandles::resolve_non_null(data))->length(); - jint word_length = (length + sizeof(HeapWord)-1) / sizeof(HeapWord); - HeapWord* body = NEW_C_HEAP_ARRAY(HeapWord, word_length, mtInternal); - if (body == NULL) { + assert(length >= 0, "class_bytes_length must not be negative: %d", length); + + int class_bytes_length = (int) length; + + u1* class_bytes = NEW_C_HEAP_ARRAY(u1, length, mtInternal); + if (class_bytes == NULL) { THROW_0(vmSymbols::java_lang_OutOfMemoryError()); } // caller responsible to free it: - (*temp_alloc) = body; + *temp_alloc = class_bytes; - { - jbyte* array_base = typeArrayOop(JNIHandles::resolve_non_null(data))->byte_at_addr(0); - Copy::conjoint_words((HeapWord*) array_base, body, word_length); - } - - u1* class_bytes = (u1*) body; - int class_bytes_length = (int) length; - if (class_bytes_length < 0) class_bytes_length = 0; - if (class_bytes == NULL - || host_class == NULL - || length != class_bytes_length) - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + jbyte* array_base = typeArrayOop(JNIHandles::resolve_non_null(data))->byte_at_addr(0); + Copy::conjoint_jbytes(array_base, class_bytes, length); objArrayHandle cp_patches_h; if (cp_patches_jh != NULL) { oop p = JNIHandles::resolve_non_null(cp_patches_jh); - if (!p->is_objArray()) - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + assert(p->is_objArray(), "cp_patches must be an object[]"); cp_patches_h = objArrayHandle(THREAD, (objArrayOop)p); } @@ -1036,60 +912,56 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env, Handle host_domain(THREAD, host_klass->protection_domain()); GrowableArray* cp_patches = NULL; + if (cp_patches_h.not_null()) { int alen = cp_patches_h->length(); + for (int i = alen-1; i >= 0; i--) { oop p = cp_patches_h->obj_at(i); if (p != NULL) { Handle patch(THREAD, p); - if (cp_patches == NULL) + + if (cp_patches == NULL) { cp_patches = new GrowableArray(i+1, i+1, Handle()); + } + cp_patches->at_put(i, patch); } } } - ClassFileStream st(class_bytes, - class_bytes_length, - host_source, - ClassFileStream::verify); + ClassFileStream st(class_bytes, class_bytes_length, host_source, ClassFileStream::verify); - instanceKlassHandle anon_klass; - { - Symbol* no_class_name = NULL; - Klass* anonk = SystemDictionary::parse_stream(no_class_name, - host_loader, - host_domain, - &st, - host_klass, - cp_patches, - CHECK_NULL); - if (anonk == NULL) return NULL; - anon_klass = instanceKlassHandle(THREAD, anonk); + Symbol* no_class_name = NULL; + Klass* anonk = SystemDictionary::parse_stream(no_class_name, + host_loader, + host_domain, + &st, + host_klass, + cp_patches, + CHECK_NULL); + if (anonk == NULL) { + return NULL; } - return anon_klass; + return instanceKlassHandle(THREAD, anonk); } -UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh)) -{ - instanceKlassHandle anon_klass; - jobject res_jh = NULL; - - UnsafeWrapper("Unsafe_DefineAnonymousClass"); +UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass0(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh)) { ResourceMark rm(THREAD); - HeapWord* temp_alloc = NULL; + instanceKlassHandle anon_klass; + jobject res_jh = NULL; + u1* temp_alloc = NULL; - anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data, - cp_patches_jh, - &temp_alloc, THREAD); - if (anon_klass() != NULL) + anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data, cp_patches_jh, &temp_alloc, THREAD); + if (anon_klass() != NULL) { res_jh = JNIHandles::make_local(env, anon_klass->java_mirror()); + } // try/finally clause: if (temp_alloc != NULL) { - FREE_C_HEAP_ARRAY(HeapWord, temp_alloc); + FREE_C_HEAP_ARRAY(u1, temp_alloc); } // The anonymous class loader data has been artificially been kept alive to @@ -1102,100 +974,103 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jc // let caller initialize it as needed... return (jclass) res_jh; -} -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr)) - UnsafeWrapper("Unsafe_ThrowException"); - { - ThreadToNativeFromVM ttnfv(thread); - env->Throw(thr); - } -UNSAFE_END +UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr)) { + ThreadToNativeFromVM ttnfv(thread); + env->Throw(thr); +} UNSAFE_END // JSR166 ------------------------------------------------------------------ -UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) - UnsafeWrapper("Unsafe_CompareAndExchangeObject"); +UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop e = JNIHandles::resolve(e_h); oop p = JNIHandles::resolve(obj); HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset); oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true); - if (res == e) + if (res == e) { update_barrier_set((void*)addr, x); + } return JNIHandles::make_local(env, res); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) - UnsafeWrapper("Unsafe_CompareAndExchangeInt"); +UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) { oop p = JNIHandles::resolve(obj); jint* addr = (jint *) index_oop_from_field_offset_long(p, offset); - return (jint)(Atomic::cmpxchg(x, addr, e)); -UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) - UnsafeWrapper("Unsafe_CompareAndExchangeLong"); + return (jint)(Atomic::cmpxchg(x, addr, e)); +} UNSAFE_END + +UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) { Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + #ifdef SUPPORTS_NATIVE_CX8 return (jlong)(Atomic::cmpxchg(x, addr, e)); #else - if (VM_Version::supports_cx8()) + if (VM_Version::supports_cx8()) { return (jlong)(Atomic::cmpxchg(x, addr, e)); - else { + } else { MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong val = Atomic::load(addr); - if (val == e) + if (val == e) { Atomic::store(x, addr); + } return val; } #endif -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) - UnsafeWrapper("Unsafe_CompareAndSwapObject"); +UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop e = JNIHandles::resolve(e_h); oop p = JNIHandles::resolve(obj); HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset); oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true); - jboolean success = (res == e); - if (success) - update_barrier_set((void*)addr, x); - return success; -UNSAFE_END + if (res != e) { + return false; + } -UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) - UnsafeWrapper("Unsafe_CompareAndSwapInt"); + update_barrier_set((void*)addr, x); + + return true; +} UNSAFE_END + +UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) { oop p = JNIHandles::resolve(obj); jint* addr = (jint *) index_oop_from_field_offset_long(p, offset); - return (jint)(Atomic::cmpxchg(x, addr, e)) == e; -UNSAFE_END -UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) - UnsafeWrapper("Unsafe_CompareAndSwapLong"); - Handle p (THREAD, JNIHandles::resolve(obj)); - jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + return (jint)(Atomic::cmpxchg(x, addr, e)) == e; +} UNSAFE_END + +UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) { + Handle p(THREAD, JNIHandles::resolve(obj)); + jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset); + #ifdef SUPPORTS_NATIVE_CX8 return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; #else - if (VM_Version::supports_cx8()) + if (VM_Version::supports_cx8()) { return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; - else { - jboolean success = false; + } else { MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong val = Atomic::load(addr); - if (val == e) { Atomic::store(x, addr); success = true; } - return success; + if (val != e) { + return false; + } + + Atomic::store(x, addr); + return true; } #endif -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) - UnsafeWrapper("Unsafe_Park"); +UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) { EventThreadPark event; HOTSPOT_THREAD_PARK_BEGIN((uintptr_t) thread->parker(), (int) isAbsolute, time); @@ -1203,6 +1078,7 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, thread->parker()->park(isAbsolute != 0, time); HOTSPOT_THREAD_PARK_END((uintptr_t) thread->parker()); + if (event.should_commit()) { oop obj = thread->current_park_blocker(); event.set_klass((obj != NULL) ? obj->klass() : NULL); @@ -1210,11 +1086,11 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, event.set_address((obj != NULL) ? (TYPE_ADDRESS) cast_from_oop(obj) : 0); event.commit(); } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) - UnsafeWrapper("Unsafe_Unpark"); +UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) { Parker* p = NULL; + if (jthread != NULL) { oop java_thread = JNIHandles::resolve_non_null(jthread); if (java_thread != NULL) { @@ -1228,6 +1104,7 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) // Grab lock if apparently null or using older version of library MutexLocker mu(Threads_lock); java_thread = JNIHandles::resolve_non_null(jthread); + if (java_thread != NULL) { JavaThread* thr = java_lang_Thread::thread(java_thread); if (thr != NULL) { @@ -1240,14 +1117,14 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) } } } + if (p != NULL) { HOTSPOT_THREAD_UNPARK((uintptr_t) p); p->unpark(); } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem)) - UnsafeWrapper("Unsafe_Loadavg"); +UNSAFE_ENTRY(jint, Unsafe_GetLoadAverage0(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem)) { const int max_nelem = 3; double la[max_nelem]; jint ret; @@ -1255,15 +1132,11 @@ UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray load typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(loadavg)); assert(a->is_typeArray(), "must be type array"); - if (nelem < 0 || nelem > max_nelem || a->length() < nelem) { - ThreadToNativeFromVM ttnfv(thread); - throw_new(env, "ArrayIndexOutOfBoundsException"); + ret = os::loadavg(la, nelem); + if (ret == -1) { return -1; } - ret = os::loadavg(la, nelem); - if (ret == -1) return -1; - // if successful, ret is the number of samples actually retrieved. assert(ret >= 0 && ret <= max_nelem, "Unexpected loadavg return value"); switch(ret) { @@ -1271,8 +1144,9 @@ UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray load case 2: a->double_at_put(1, (jdouble)la[1]); // fall through case 1: a->double_at_put(0, (jdouble)la[0]); break; } + return ret; -UNSAFE_END +} UNSAFE_END /// JVM_RegisterUnsafeMethods @@ -1292,87 +1166,17 @@ UNSAFE_END #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) -#define DECLARE_GETPUTOOP(Boolean, Z) \ - {CC "get" #Boolean, CC "(" OBJ "J)" #Z, FN_PTR(Unsafe_Get##Boolean)}, \ - {CC "put" #Boolean, CC "(" OBJ "J" #Z ")V", FN_PTR(Unsafe_Set##Boolean)}, \ - {CC "get" #Boolean "Volatile", CC "(" OBJ "J)" #Z, FN_PTR(Unsafe_Get##Boolean##Volatile)}, \ - {CC "put" #Boolean "Volatile", CC "(" OBJ "J" #Z ")V", FN_PTR(Unsafe_Set##Boolean##Volatile)} +#define DECLARE_GETPUTOOP(Type, Desc) \ + {CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \ + {CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type)}, \ + {CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \ + {CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type##Volatile)} #define DECLARE_GETPUTNATIVE(Byte, B) \ {CC "get" #Byte, CC "(" ADR ")" #B, FN_PTR(Unsafe_GetNative##Byte)}, \ {CC "put" #Byte, CC "(" ADR#B ")V", FN_PTR(Unsafe_SetNative##Byte)} - -static JNINativeMethod sun_misc_Unsafe_methods[] = { - {CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)}, - {CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObject)}, - {CC "getObjectVolatile",CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObjectVolatile)}, - {CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObjectVolatile)}, - - {CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)}, - {CC "getJavaMirror", CC "(" ADR ")" CLS, FN_PTR(Unsafe_GetJavaMirror)}, - {CC "getKlassPointer", CC "(" OBJ ")" ADR, FN_PTR(Unsafe_GetKlassPointer)}, - - DECLARE_GETPUTOOP(Boolean, Z), - DECLARE_GETPUTOOP(Byte, B), - DECLARE_GETPUTOOP(Short, S), - DECLARE_GETPUTOOP(Char, C), - DECLARE_GETPUTOOP(Int, I), - DECLARE_GETPUTOOP(Long, J), - DECLARE_GETPUTOOP(Float, F), - DECLARE_GETPUTOOP(Double, D), - - DECLARE_GETPUTNATIVE(Byte, B), - DECLARE_GETPUTNATIVE(Short, S), - DECLARE_GETPUTNATIVE(Char, C), - DECLARE_GETPUTNATIVE(Int, I), - DECLARE_GETPUTNATIVE(Long, J), - DECLARE_GETPUTNATIVE(Float, F), - DECLARE_GETPUTNATIVE(Double, D), - - {CC "getAddress", CC "(" ADR ")" ADR, FN_PTR(Unsafe_GetNativeAddress)}, - {CC "putAddress", CC "(" ADR "" ADR ")V", FN_PTR(Unsafe_SetNativeAddress)}, - - {CC "allocateMemory", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory)}, - {CC "reallocateMemory", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory)}, - {CC "freeMemory", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory)}, - - {CC "objectFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset)}, - {CC "staticFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset)}, - {CC "staticFieldBase", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)}, - {CC "ensureClassInitialized",CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized)}, - {CC "arrayBaseOffset", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset)}, - {CC "arrayIndexScale", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale)}, - {CC "addressSize", CC "()I", FN_PTR(Unsafe_AddressSize)}, - {CC "pageSize", CC "()I", FN_PTR(Unsafe_PageSize)}, - - {CC "defineClass", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass)}, - {CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)}, - {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)}, - {CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)}, - {CC "compareAndSwapInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)}, - {CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)}, - {CC "putOrderedObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetOrderedObject)}, - {CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)}, - {CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)}, - {CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)}, - {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)}, - - {CC "getLoadAverage", CC "([DI)I", FN_PTR(Unsafe_Loadavg)}, - - {CC "copyMemory", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory)}, - {CC "setMemory", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory)}, - - {CC "defineAnonymousClass", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass)}, - - {CC "shouldBeInitialized",CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized)}, - - {CC "loadFence", CC "()V", FN_PTR(Unsafe_LoadFence)}, - {CC "storeFence", CC "()V", FN_PTR(Unsafe_StoreFence)}, - {CC "fullFence", CC "()V", FN_PTR(Unsafe_FullFence)}, -}; - static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)}, {CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObject)}, @@ -1403,20 +1207,20 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "getAddress", CC "(" ADR ")" ADR, FN_PTR(Unsafe_GetNativeAddress)}, {CC "putAddress", CC "(" ADR "" ADR ")V", FN_PTR(Unsafe_SetNativeAddress)}, - {CC "allocateMemory", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory)}, - {CC "reallocateMemory", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory)}, - {CC "freeMemory", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory)}, + {CC "allocateMemory0", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory0)}, + {CC "reallocateMemory0", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory0)}, + {CC "freeMemory0", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory0)}, - {CC "objectFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset)}, - {CC "staticFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset)}, - {CC "staticFieldBase", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)}, - {CC "ensureClassInitialized",CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized)}, - {CC "arrayBaseOffset", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset)}, - {CC "arrayIndexScale", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale)}, - {CC "addressSize", CC "()I", FN_PTR(Unsafe_AddressSize)}, + {CC "objectFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset0)}, + {CC "staticFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset0)}, + {CC "staticFieldBase0", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBase0)}, + {CC "ensureClassInitialized0", CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized0)}, + {CC "arrayBaseOffset0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset0)}, + {CC "arrayIndexScale0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale0)}, + {CC "addressSize0", CC "()I", FN_PTR(Unsafe_AddressSize0)}, {CC "pageSize", CC "()I", FN_PTR(Unsafe_PageSize)}, - {CC "defineClass", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass)}, + {CC "defineClass0", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass0)}, {CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)}, {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)}, {CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)}, @@ -1432,15 +1236,15 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)}, {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)}, - {CC "getLoadAverage", CC "([DI)I", FN_PTR(Unsafe_Loadavg)}, + {CC "getLoadAverage0", CC "([DI)I", FN_PTR(Unsafe_GetLoadAverage0)}, - {CC "copyMemory", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory)}, + {CC "copyMemory0", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)}, {CC "copySwapMemory0", CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)}, - {CC "setMemory", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory)}, + {CC "setMemory0", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory0)}, - {CC "defineAnonymousClass", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass)}, + {CC "defineAnonymousClass0", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass0)}, - {CC "shouldBeInitialized",CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized)}, + {CC "shouldBeInitialized0", CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized0)}, {CC "loadFence", CC "()V", FN_PTR(Unsafe_LoadFence)}, {CC "storeFence", CC "()V", FN_PTR(Unsafe_StoreFence)}, @@ -1466,27 +1270,14 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { #undef DECLARE_GETPUTNATIVE -// These two functions are exported, used by NativeLookup. +// This function is exported, used by NativeLookup. // The Unsafe_xxx functions above are called only from the interpreter. // The optimizer looks at names and signatures to recognize // individual functions. -JVM_ENTRY(void, JVM_RegisterSunMiscUnsafeMethods(JNIEnv *env, jclass unsafeclass)) - UnsafeWrapper("JVM_RegisterSunMiscUnsafeMethods"); - { - ThreadToNativeFromVM ttnfv(thread); +JVM_ENTRY(void, JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafeclass)) { + ThreadToNativeFromVM ttnfv(thread); - int ok = env->RegisterNatives(unsafeclass, sun_misc_Unsafe_methods, sizeof(sun_misc_Unsafe_methods)/sizeof(JNINativeMethod)); - guarantee(ok == 0, "register sun.misc.Unsafe natives"); - } -JVM_END - -JVM_ENTRY(void, JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafeclass)) - UnsafeWrapper("JVM_RegisterJDKInternalMiscUnsafeMethods"); - { - ThreadToNativeFromVM ttnfv(thread); - - int ok = env->RegisterNatives(unsafeclass, jdk_internal_misc_Unsafe_methods, sizeof(jdk_internal_misc_Unsafe_methods)/sizeof(JNINativeMethod)); - guarantee(ok == 0, "register jdk.internal.misc.Unsafe natives"); - } -JVM_END + int ok = env->RegisterNatives(unsafeclass, jdk_internal_misc_Unsafe_methods, sizeof(jdk_internal_misc_Unsafe_methods)/sizeof(JNINativeMethod)); + guarantee(ok == 0, "register jdk.internal.misc.Unsafe natives"); +} JVM_END diff --git a/hotspot/src/share/vm/prims/unsafe.hpp b/hotspot/src/share/vm/prims/unsafe.hpp new file mode 100644 index 00000000000..e8ed3a2ad02 --- /dev/null +++ b/hotspot/src/share/vm/prims/unsafe.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, 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. + * + */ + + +#ifndef SHARE_VM_PRIMS_UNSAFE_HPP +#define SHARE_VM_PRIMS_UNSAFE_HPP + +#include "jni.h" + +extern "C" { + void JNICALL JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafecls); +} + +jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); + +jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset); + +#endif // SHARE_VM_PRIMS_UNSAFE_HPP diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp index 84a6d6afafd..8dbc6be317c 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp @@ -521,9 +521,9 @@ class RuntimeHistogramElement : public HistogramElement { JNI_ENTRY_NO_PRESERVE(result_type, header) \ WeakPreserveExceptionMark __wem(thread); -#define JNI_ENTRY_NO_PRESERVE(result_type, header) \ +#define JNI_ENTRY_NO_PRESERVE(result_type, header) \ extern "C" { \ - result_type JNICALL header { \ + result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ ThreadInVMfromNative __tiv(thread); \ @@ -535,7 +535,7 @@ extern "C" { \ // a GC, is called outside the NoHandleMark (set via VM_QUICK_ENTRY_BASE). #define JNI_QUICK_ENTRY(result_type, header) \ extern "C" { \ - result_type JNICALL header { \ + result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ ThreadInVMfromNative __tiv(thread); \ @@ -545,7 +545,7 @@ extern "C" { \ #define JNI_LEAF(result_type, header) \ extern "C" { \ - result_type JNICALL header { \ + result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ VM_LEAF_BASE(result_type, header) diff --git a/hotspot/src/share/vm/shark/sharkBuilder.cpp b/hotspot/src/share/vm/shark/sharkBuilder.cpp index 0fcc8107fc9..ab4dcdcefbf 100644 --- a/hotspot/src/share/vm/shark/sharkBuilder.cpp +++ b/hotspot/src/share/vm/shark/sharkBuilder.cpp @@ -29,6 +29,7 @@ #include "gc/shared/cardTableModRefBS.hpp" #include "memory/resourceArea.hpp" #include "oops/method.hpp" +#include "prims/unsafe.hpp" #include "runtime/os.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.hpp" @@ -326,7 +327,6 @@ Value* SharkBuilder::fabs() { } Value* SharkBuilder::unsafe_field_offset_to_byte_offset() { - extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); return make_function((address) Unsafe_field_offset_to_byte_offset, "l", "l"); } diff --git a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java index d96de812faa..1fdaf805f9a 100644 --- a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java +++ b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java @@ -33,8 +33,8 @@ * -XX:+WhiteBoxAPI * -XX:DisableIntrinsic=_putCharVolatile,_putInt * -XX:DisableIntrinsic=_putIntVolatile - * -XX:CompileCommand=option,sun.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt - * -XX:CompileCommand=option,sun.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile + * -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt + * -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile * IntrinsicDisabledTest */ @@ -60,7 +60,7 @@ public class IntrinsicDisabledTest { return Boolean.valueOf(Objects.toString(wb.getVMFlag("TieredCompilation"))); } - /* This test uses several methods from sun.misc.Unsafe. The method + /* This test uses several methods from jdk.internal.misc.Unsafe. The method * getMethod() returns a different Executable for each different * combination of its input parameters. There are eight possible * combinations, getMethod can return an Executable representing @@ -74,7 +74,7 @@ public class IntrinsicDisabledTest { String methodTypeName = isChar ? "Char" : "Int"; try { - Class aClass = Class.forName("sun.misc.Unsafe"); + Class aClass = Class.forName("jdk.internal.misc.Unsafe"); if (isPut) { aMethod = aClass.getDeclaredMethod("put" + methodTypeName + (isVolatile ? "Volatile" : ""), Object.class, From 890f94d7e6be731ac2ebae2f1ad3cc20ec836115 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 3 Mar 2016 22:17:38 +0300 Subject: [PATCH 053/311] 8150669: C1 intrinsic for Class.isPrimitive Reviewed-by: twisti, vlivanov, redestad --- hotspot/src/share/vm/c1/c1_Canonicalizer.cpp | 13 +- hotspot/src/share/vm/c1/c1_Compiler.cpp | 1 + hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 20 +++ hotspot/src/share/vm/c1/c1_LIRGenerator.hpp | 1 + .../class/TestClassIsPrimitive.java | 166 ++++++++++++++++++ 5 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp index 033beb0d25e..d70a769e93b 100644 --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp @@ -471,7 +471,7 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) { InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant(); if (c != NULL && !c->value()->is_null_object()) { // ciInstance::java_mirror_type() returns non-NULL only for Java mirrors - ciType* t = c->value()->as_instance()->java_mirror_type(); + ciType* t = c->value()->java_mirror_type(); if (t->is_klass()) { // substitute cls.isInstance(obj) of a constant Class into // an InstantOf instruction @@ -487,6 +487,17 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) { } break; } + case vmIntrinsics::_isPrimitive : { + assert(x->number_of_arguments() == 1, "wrong type"); + + // Class.isPrimitive is known on constant classes: + InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant(); + if (c != NULL && !c->value()->is_null_object()) { + ciType* t = c->value()->java_mirror_type(); + set_constant(t->is_primitive_type()); + } + break; + } } } diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp index 5dbe6c209f3..75974669b35 100644 --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp @@ -148,6 +148,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_longBitsToDouble: case vmIntrinsics::_getClass: case vmIntrinsics::_isInstance: + case vmIntrinsics::_isPrimitive: case vmIntrinsics::_currentThread: case vmIntrinsics::_dabs: case vmIntrinsics::_dsqrt: diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 30ae8f86e9f..bfe367453c9 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -1293,6 +1293,25 @@ void LIRGenerator::do_getClass(Intrinsic* x) { __ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result); } +// java.lang.Class::isPrimitive() +void LIRGenerator::do_isPrimitive(Intrinsic* x) { + assert(x->number_of_arguments() == 1, "wrong type"); + + LIRItem rcvr(x->argument_at(0), this); + rcvr.load_item(); + LIR_Opr temp = new_register(T_METADATA); + LIR_Opr result = rlock_result(x); + + CodeEmitInfo* info = NULL; + if (x->needs_null_check()) { + info = state_for(x); + } + + __ move(new LIR_Address(rcvr.result(), java_lang_Class::klass_offset_in_bytes(), T_ADDRESS), temp, info); + __ cmp(lir_cond_notEqual, temp, LIR_OprFact::intConst(0)); + __ cmove(lir_cond_notEqual, LIR_OprFact::intConst(0), LIR_OprFact::intConst(1), result, T_BOOLEAN); +} + // Example: Thread.currentThread() void LIRGenerator::do_currentThread(Intrinsic* x) { @@ -3132,6 +3151,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { case vmIntrinsics::_Object_init: do_RegisterFinalizer(x); break; case vmIntrinsics::_isInstance: do_isInstance(x); break; + case vmIntrinsics::_isPrimitive: do_isPrimitive(x); break; case vmIntrinsics::_getClass: do_getClass(x); break; case vmIntrinsics::_currentThread: do_currentThread(x); break; diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index 9438d77288c..b673f566723 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -246,6 +246,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void do_RegisterFinalizer(Intrinsic* x); void do_isInstance(Intrinsic* x); + void do_isPrimitive(Intrinsic* x); void do_getClass(Intrinsic* x); void do_currentThread(Intrinsic* x); void do_MathIntrinsic(Intrinsic* x); diff --git a/hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java b/hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java new file mode 100644 index 00000000000..76a2812e733 --- /dev/null +++ b/hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016, 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 8150669 + * @summary C1 intrinsic for Class.isPrimitive + * @modules java.base/jdk.internal.misc + * @run main/othervm -ea -Diters=200 -Xint TestClassIsPrimitive + * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1 TestClassIsPrimitive + * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4 TestClassIsPrimitive + */ +import java.lang.reflect.Field; +import java.lang.reflect.Array; +import java.util.concurrent.Callable; + +public class TestClassIsPrimitive { + static final int ITERS = Integer.getInteger("iters", 1); + + public static void main(String... args) throws Exception { + testOK(true, InlineConstants::testBoolean); + testOK(true, InlineConstants::testByte); + testOK(true, InlineConstants::testShort); + testOK(true, InlineConstants::testChar); + testOK(true, InlineConstants::testInt); + testOK(true, InlineConstants::testFloat); + testOK(true, InlineConstants::testLong); + testOK(true, InlineConstants::testDouble); + testOK(false, InlineConstants::testObject); + testOK(false, InlineConstants::testArray); + + testOK(true, StaticConstants::testBoolean); + testOK(true, StaticConstants::testByte); + testOK(true, StaticConstants::testShort); + testOK(true, StaticConstants::testChar); + testOK(true, StaticConstants::testInt); + testOK(true, StaticConstants::testFloat); + testOK(true, StaticConstants::testLong); + testOK(true, StaticConstants::testDouble); + testOK(false, StaticConstants::testObject); + testOK(false, StaticConstants::testArray); + testNPE( StaticConstants::testNull); + + testOK(true, NoConstants::testBoolean); + testOK(true, NoConstants::testByte); + testOK(true, NoConstants::testShort); + testOK(true, NoConstants::testChar); + testOK(true, NoConstants::testInt); + testOK(true, NoConstants::testFloat); + testOK(true, NoConstants::testLong); + testOK(true, NoConstants::testDouble); + testOK(false, NoConstants::testObject); + testOK(false, NoConstants::testArray); + testNPE( NoConstants::testNull); + } + + public static void testOK(boolean expected, Callable test) throws Exception { + for (int c = 0; c < ITERS; c++) { + Object res = test.call(); + if (!res.equals(expected)) { + throw new IllegalStateException("Wrong result: expected = " + expected + ", but got " + res); + } + } + } + + static volatile Object sink; + + public static void testNPE(Callable test) throws Exception { + for (int c = 0; c < ITERS; c++) { + try { + sink = test.call(); + throw new IllegalStateException("Expected NPE"); + } catch (NullPointerException iae) { + // expected + } + } + } + + static volatile Class classBoolean = boolean.class; + static volatile Class classByte = byte.class; + static volatile Class classShort = short.class; + static volatile Class classChar = char.class; + static volatile Class classInt = int.class; + static volatile Class classFloat = float.class; + static volatile Class classLong = long.class; + static volatile Class classDouble = double.class; + static volatile Class classObject = Object.class; + static volatile Class classArray = Object[].class; + static volatile Class classNull = null; + + static final Class staticClassBoolean = boolean.class; + static final Class staticClassByte = byte.class; + static final Class staticClassShort = short.class; + static final Class staticClassChar = char.class; + static final Class staticClassInt = int.class; + static final Class staticClassFloat = float.class; + static final Class staticClassLong = long.class; + static final Class staticClassDouble = double.class; + static final Class staticClassObject = Object.class; + static final Class staticClassArray = Object[].class; + static final Class staticClassNull = null; + + static class InlineConstants { + static boolean testBoolean() { return boolean.class.isPrimitive(); } + static boolean testByte() { return byte.class.isPrimitive(); } + static boolean testShort() { return short.class.isPrimitive(); } + static boolean testChar() { return char.class.isPrimitive(); } + static boolean testInt() { return int.class.isPrimitive(); } + static boolean testFloat() { return float.class.isPrimitive(); } + static boolean testLong() { return long.class.isPrimitive(); } + static boolean testDouble() { return double.class.isPrimitive(); } + static boolean testObject() { return Object.class.isPrimitive(); } + static boolean testArray() { return Object[].class.isPrimitive(); } + } + + static class StaticConstants { + static boolean testBoolean() { return staticClassBoolean.isPrimitive(); } + static boolean testByte() { return staticClassByte.isPrimitive(); } + static boolean testShort() { return staticClassShort.isPrimitive(); } + static boolean testChar() { return staticClassChar.isPrimitive(); } + static boolean testInt() { return staticClassInt.isPrimitive(); } + static boolean testFloat() { return staticClassFloat.isPrimitive(); } + static boolean testLong() { return staticClassLong.isPrimitive(); } + static boolean testDouble() { return staticClassDouble.isPrimitive(); } + static boolean testObject() { return staticClassObject.isPrimitive(); } + static boolean testArray() { return staticClassArray.isPrimitive(); } + static boolean testNull() { return staticClassNull.isPrimitive(); } + } + + static class NoConstants { + static boolean testBoolean() { return classBoolean.isPrimitive(); } + static boolean testByte() { return classByte.isPrimitive(); } + static boolean testShort() { return classShort.isPrimitive(); } + static boolean testChar() { return classChar.isPrimitive(); } + static boolean testInt() { return classInt.isPrimitive(); } + static boolean testFloat() { return classFloat.isPrimitive(); } + static boolean testLong() { return classLong.isPrimitive(); } + static boolean testDouble() { return classDouble.isPrimitive(); } + static boolean testObject() { return classObject.isPrimitive(); } + static boolean testArray() { return classArray.isPrimitive(); } + static boolean testNull() { return classNull.isPrimitive(); } + } + +} + From 548530cf084b5756200def41f52e03df55cb51e7 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 3 Mar 2016 23:57:29 +0300 Subject: [PATCH 054/311] 8150465: Unsafe methods to produce uninitialized arrays Reviewed-by: jrose, kvn, psandoz, aph, twisti, flar --- hotspot/src/share/vm/classfile/vmSymbols.hpp | 2 + hotspot/src/share/vm/opto/c2compiler.cpp | 1 + hotspot/src/share/vm/opto/library_call.cpp | 27 ++- .../unsafe/AllocateUninitializedArray.java | 213 ++++++++++++++++++ 4 files changed, 237 insertions(+), 6 deletions(-) create mode 100644 hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index fcc4ad8be25..6dd88c2d2e7 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -1040,6 +1040,8 @@ do_intrinsic(_allocateInstance, jdk_internal_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \ do_name( allocateInstance_name, "allocateInstance") \ do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \ + do_intrinsic(_allocateUninitializedArray, jdk_internal_misc_Unsafe, allocateUninitializedArray_name, newArray_signature, F_R) \ + do_name( allocateUninitializedArray_name, "allocateUninitializedArray0") \ do_intrinsic(_copyMemory, jdk_internal_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \ do_name( copyMemory_name, "copyMemory0") \ do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \ diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index aeea26748fe..5d61042af32 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -500,6 +500,7 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt case vmIntrinsics::_currentTimeMillis: case vmIntrinsics::_nanoTime: case vmIntrinsics::_allocateInstance: + case vmIntrinsics::_allocateUninitializedArray: case vmIntrinsics::_newArray: case vmIntrinsics::_getLength: case vmIntrinsics::_copyOf: diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 4ecca52fb3d..40d82895cf4 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -247,6 +247,7 @@ class LibraryCallKit : public GraphKit { bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, AccessKind kind, bool is_unaligned); static bool klass_needs_init_guard(Node* kls); bool inline_unsafe_allocate(); + bool inline_unsafe_newArray(bool uninitialized); bool inline_unsafe_copyMemory(); bool inline_native_currentThread(); #ifdef TRACE_HAVE_INTRINSICS @@ -257,8 +258,6 @@ class LibraryCallKit : public GraphKit { bool inline_native_isInterrupted(); bool inline_native_Class_query(vmIntrinsics::ID id); bool inline_native_subtype_check(); - - bool inline_native_newArray(); bool inline_native_getLength(); bool inline_array_copyOf(bool is_copyOfRange); bool inline_array_equals(StrIntrinsicNode::ArgEnc ae); @@ -715,7 +714,6 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_nanoTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime"); case vmIntrinsics::_allocateInstance: return inline_unsafe_allocate(); case vmIntrinsics::_copyMemory: return inline_unsafe_copyMemory(); - case vmIntrinsics::_newArray: return inline_native_newArray(); case vmIntrinsics::_getLength: return inline_native_getLength(); case vmIntrinsics::_copyOf: return inline_array_copyOf(false); case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true); @@ -724,6 +722,9 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_Objects_checkIndex: return inline_objects_checkIndex(); case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual()); + case vmIntrinsics::_allocateUninitializedArray: return inline_unsafe_newArray(true); + case vmIntrinsics::_newArray: return inline_unsafe_newArray(false); + case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check(); case vmIntrinsics::_isInstance: @@ -3829,9 +3830,17 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, //-----------------------inline_native_newArray-------------------------- // private static native Object java.lang.reflect.newArray(Class componentType, int length); -bool LibraryCallKit::inline_native_newArray() { - Node* mirror = argument(0); - Node* count_val = argument(1); +// private native Object Unsafe.allocateUninitializedArray0(Class cls, int size); +bool LibraryCallKit::inline_unsafe_newArray(bool uninitialized) { + Node* mirror; + Node* count_val; + if (uninitialized) { + mirror = argument(1); + count_val = argument(2); + } else { + mirror = argument(0); + count_val = argument(1); + } mirror = null_check(mirror); // If mirror or obj is dead, only null-path is taken. @@ -3876,6 +3885,12 @@ bool LibraryCallKit::inline_native_newArray() { result_val->init_req(_normal_path, obj); result_io ->init_req(_normal_path, i_o()); result_mem->init_req(_normal_path, reset_memory()); + + if (uninitialized) { + // Mark the allocation so that zeroing is skipped + AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(obj, &_gvn); + alloc->maybe_set_complete(&_gvn); + } } // Return the combined state. diff --git a/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java b/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java new file mode 100644 index 00000000000..404ccc6c60d --- /dev/null +++ b/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2016, 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 8150465 + * @summary Unsafe methods to produce uninitialized arrays + * @modules java.base/jdk.internal.misc + * @run main/othervm -ea -Diters=200 -Xint AllocateUninitializedArray + * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1 AllocateUninitializedArray + * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4 AllocateUninitializedArray + */ +import java.lang.reflect.Field; +import java.lang.reflect.Array; +import java.util.concurrent.Callable; + +public class AllocateUninitializedArray { + static final int ITERS = Integer.getInteger("iters", 1); + static final jdk.internal.misc.Unsafe UNSAFE; + + static { + try { + Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + UNSAFE = (jdk.internal.misc.Unsafe) f.get(null); + } catch (Exception e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + + public static void main(String... args) throws Exception { + testIAE(AllConstants::testObject); + testIAE(LengthIsConstant::testObject); + testIAE(ClassIsConstant::testObject); + testIAE(NothingIsConstant::testObject); + + testIAE(AllConstants::testArray); + testIAE(LengthIsConstant::testArray); + testIAE(ClassIsConstant::testArray); + testIAE(NothingIsConstant::testArray); + + testIAE(AllConstants::testNull); + testIAE(LengthIsConstant::testNull); + testIAE(ClassIsConstant::testNull); + testIAE(NothingIsConstant::testNull); + + testOK(boolean[].class, 10, AllConstants::testBoolean); + testOK(byte[].class, 10, AllConstants::testByte); + testOK(short[].class, 10, AllConstants::testShort); + testOK(char[].class, 10, AllConstants::testChar); + testOK(int[].class, 10, AllConstants::testInt); + testOK(float[].class, 10, AllConstants::testFloat); + testOK(long[].class, 10, AllConstants::testLong); + testOK(double[].class, 10, AllConstants::testDouble); + + testOK(boolean[].class, 10, LengthIsConstant::testBoolean); + testOK(byte[].class, 10, LengthIsConstant::testByte); + testOK(short[].class, 10, LengthIsConstant::testShort); + testOK(char[].class, 10, LengthIsConstant::testChar); + testOK(int[].class, 10, LengthIsConstant::testInt); + testOK(float[].class, 10, LengthIsConstant::testFloat); + testOK(long[].class, 10, LengthIsConstant::testLong); + testOK(double[].class, 10, LengthIsConstant::testDouble); + + testOK(boolean[].class, 10, ClassIsConstant::testBoolean); + testOK(byte[].class, 10, ClassIsConstant::testByte); + testOK(short[].class, 10, ClassIsConstant::testShort); + testOK(char[].class, 10, ClassIsConstant::testChar); + testOK(int[].class, 10, ClassIsConstant::testInt); + testOK(float[].class, 10, ClassIsConstant::testFloat); + testOK(long[].class, 10, ClassIsConstant::testLong); + testOK(double[].class, 10, ClassIsConstant::testDouble); + + testOK(boolean[].class, 10, NothingIsConstant::testBoolean); + testOK(byte[].class, 10, NothingIsConstant::testByte); + testOK(short[].class, 10, NothingIsConstant::testShort); + testOK(char[].class, 10, NothingIsConstant::testChar); + testOK(int[].class, 10, NothingIsConstant::testInt); + testOK(float[].class, 10, NothingIsConstant::testFloat); + testOK(long[].class, 10, NothingIsConstant::testLong); + testOK(double[].class, 10, NothingIsConstant::testDouble); + } + + public static void testOK(Class expectClass, int expectLen, Callable test) throws Exception { + for (int c = 0; c < ITERS; c++) { + Object res = test.call(); + Class actualClass = res.getClass(); + if (!actualClass.equals(expectClass)) { + throw new IllegalStateException("Wrong class: expected = " + expectClass + ", but got " + actualClass); + } + int actualLen = Array.getLength(res); + if (actualLen != expectLen) { + throw new IllegalStateException("Wrong length: expected = " + expectLen + ", but got " + actualLen); + } + } + } + + static volatile Object sink; + + public static void testIAE(Callable test) throws Exception { + for (int c = 0; c < ITERS; c++) { + try { + sink = test.call(); + throw new IllegalStateException("Expected IAE"); + } catch (IllegalArgumentException iae) { + // expected + } + } + } + + static volatile int sampleLenNeg = -1; + static volatile int sampleLenZero = 0; + static volatile int sampleLen = 10; + + + static volatile Class classBoolean = boolean.class; + static volatile Class classByte = byte.class; + static volatile Class classShort = short.class; + static volatile Class classChar = char.class; + static volatile Class classInt = int.class; + static volatile Class classFloat = float.class; + static volatile Class classLong = long.class; + static volatile Class classDouble = double.class; + static volatile Class classObject = Object.class; + static volatile Class classArray = Object[].class; + static volatile Class classNull = null; + + static class AllConstants { + static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class, 10); } + static Object testByte() { return UNSAFE.allocateUninitializedArray(byte.class, 10); } + static Object testShort() { return UNSAFE.allocateUninitializedArray(short.class, 10); } + static Object testChar() { return UNSAFE.allocateUninitializedArray(char.class, 10); } + static Object testInt() { return UNSAFE.allocateUninitializedArray(int.class, 10); } + static Object testFloat() { return UNSAFE.allocateUninitializedArray(float.class, 10); } + static Object testLong() { return UNSAFE.allocateUninitializedArray(long.class, 10); } + static Object testDouble() { return UNSAFE.allocateUninitializedArray(double.class, 10); } + static Object testObject() { return UNSAFE.allocateUninitializedArray(Object.class, 10); } + static Object testArray() { return UNSAFE.allocateUninitializedArray(Object[].class, 10); } + static Object testNull() { return UNSAFE.allocateUninitializedArray(null, 10); } + static Object testZero() { return UNSAFE.allocateUninitializedArray(int.class, 0); } + static Object testNeg() { return UNSAFE.allocateUninitializedArray(int.class, -1); } + } + + static class ClassIsConstant { + static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class, sampleLen); } + static Object testByte() { return UNSAFE.allocateUninitializedArray(byte.class, sampleLen); } + static Object testShort() { return UNSAFE.allocateUninitializedArray(short.class, sampleLen); } + static Object testChar() { return UNSAFE.allocateUninitializedArray(char.class, sampleLen); } + static Object testInt() { return UNSAFE.allocateUninitializedArray(int.class, sampleLen); } + static Object testFloat() { return UNSAFE.allocateUninitializedArray(float.class, sampleLen); } + static Object testLong() { return UNSAFE.allocateUninitializedArray(long.class, sampleLen); } + static Object testDouble() { return UNSAFE.allocateUninitializedArray(double.class, sampleLen); } + static Object testObject() { return UNSAFE.allocateUninitializedArray(Object.class, sampleLen); } + static Object testArray() { return UNSAFE.allocateUninitializedArray(Object[].class, sampleLen); } + static Object testNull() { return UNSAFE.allocateUninitializedArray(null, sampleLen); } + static Object testZero() { return UNSAFE.allocateUninitializedArray(int.class, sampleLenZero); } + static Object testNeg() { return UNSAFE.allocateUninitializedArray(int.class, sampleLenNeg); } + } + + static class LengthIsConstant { + static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, 10); } + static Object testByte() { return UNSAFE.allocateUninitializedArray(classByte, 10); } + static Object testShort() { return UNSAFE.allocateUninitializedArray(classShort, 10); } + static Object testChar() { return UNSAFE.allocateUninitializedArray(classChar, 10); } + static Object testInt() { return UNSAFE.allocateUninitializedArray(classInt, 10); } + static Object testFloat() { return UNSAFE.allocateUninitializedArray(classFloat, 10); } + static Object testLong() { return UNSAFE.allocateUninitializedArray(classLong, 10); } + static Object testDouble() { return UNSAFE.allocateUninitializedArray(classDouble, 10); } + static Object testObject() { return UNSAFE.allocateUninitializedArray(classObject, 10); } + static Object testArray() { return UNSAFE.allocateUninitializedArray(classArray, 10); } + static Object testNull() { return UNSAFE.allocateUninitializedArray(classNull, 10); } + static Object testZero() { return UNSAFE.allocateUninitializedArray(classInt, 0); } + static Object testNeg() { return UNSAFE.allocateUninitializedArray(classInt, -1); } + } + + static class NothingIsConstant { + static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, sampleLen); } + static Object testByte() { return UNSAFE.allocateUninitializedArray(classByte, sampleLen); } + static Object testShort() { return UNSAFE.allocateUninitializedArray(classShort, sampleLen); } + static Object testChar() { return UNSAFE.allocateUninitializedArray(classChar, sampleLen); } + static Object testInt() { return UNSAFE.allocateUninitializedArray(classInt, sampleLen); } + static Object testFloat() { return UNSAFE.allocateUninitializedArray(classFloat, sampleLen); } + static Object testLong() { return UNSAFE.allocateUninitializedArray(classLong, sampleLen); } + static Object testDouble() { return UNSAFE.allocateUninitializedArray(classDouble, sampleLen); } + static Object testObject() { return UNSAFE.allocateUninitializedArray(classObject, sampleLen); } + static Object testArray() { return UNSAFE.allocateUninitializedArray(classArray, sampleLen); } + static Object testNull() { return UNSAFE.allocateUninitializedArray(classNull, sampleLen); } + static Object testZero() { return UNSAFE.allocateUninitializedArray(classInt, sampleLenZero); } + static Object testNeg() { return UNSAFE.allocateUninitializedArray(classInt, sampleLenNeg); } + } +} + From 103aff334f61fdb654453a0f6a6d58a5ded6ac7c Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 4 Mar 2016 01:30:11 +0300 Subject: [PATCH 055/311] 8146801: Allocating short arrays of non-constant size is slow Reviewed-by: kvn, twisti, vlivanov --- hotspot/src/cpu/aarch64/vm/aarch64.ad | 3 -- .../src/cpu/aarch64/vm/globals_aarch64.hpp | 2 + hotspot/src/cpu/ppc/vm/globals_ppc.hpp | 2 + hotspot/src/cpu/ppc/vm/ppc.ad | 2 - hotspot/src/cpu/sparc/vm/globals_sparc.hpp | 2 + hotspot/src/cpu/sparc/vm/sparc.ad | 3 -- hotspot/src/cpu/x86/vm/globals_x86.hpp | 2 + hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 35 ++++++++++-- hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 5 +- hotspot/src/cpu/x86/vm/x86_32.ad | 52 +++++++++++++----- hotspot/src/cpu/x86/vm/x86_64.ad | 53 +++++++++++++------ hotspot/src/share/vm/opto/matcher.hpp | 4 -- hotspot/src/share/vm/opto/memnode.cpp | 14 +++-- hotspot/src/share/vm/opto/memnode.hpp | 7 ++- .../commandLineFlagConstraintsCompiler.cpp | 8 +++ .../commandLineFlagConstraintsCompiler.hpp | 2 + hotspot/src/share/vm/runtime/globals.hpp | 7 +++ 17 files changed, 150 insertions(+), 53 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index acc65080e2f..832c9e765ba 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -3425,9 +3425,6 @@ const bool Matcher::misaligned_vectors_ok() { // false => size gets scaled to BytesPerLong, ok. const bool Matcher::init_array_count_is_in_bytes = false; -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 18 * BytesPerLong; - // Use conditional move (CMOVL) const int Matcher::long_cmove_cost() { // long cmoves are no more expensive than int cmoves diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp index 86d2c14ce54..9380d429878 100644 --- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp @@ -76,6 +76,8 @@ define_pd_global(bool, CompactStrings, false); // avoid biased locking while we are bootstrapping the aarch64 build define_pd_global(bool, UseBiasedLocking, false); +define_pd_global(intx, InitArrayShortSize, 18*BytesPerLong); + #if defined(COMPILER1) || defined(COMPILER2) define_pd_global(intx, InlineSmallCode, 1000); #endif diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index 4afb89e1ffb..77f7a491b02 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -76,6 +76,8 @@ define_pd_global(uintx, TypeProfileLevel, 111); define_pd_global(bool, CompactStrings, true); +define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); + // Platform dependent flag handling: flags only defined on this platform. #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ \ diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index df119f8bdf1..20521eb8e18 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -2137,8 +2137,6 @@ MachTypeNode *Matcher::make_decode_node() { return decode; } */ -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 8 * BytesPerLong; // false => size gets scaled to BytesPerLong, ok. const bool Matcher::init_array_count_is_in_bytes = false; diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp index 3b813df0254..66889ae73b3 100644 --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp @@ -90,6 +90,8 @@ define_pd_global(uintx, TypeProfileLevel, 111); define_pd_global(bool, CompactStrings, true); +define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); + #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ \ product(intx, UseVIS, 99, \ diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 5cf884a5501..f24c1f9b384 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -1980,9 +1980,6 @@ const bool Matcher::isSimpleConstant64(jlong value) { // No scaling for the parameter the ClearArray node. const bool Matcher::init_array_count_is_in_bytes = true; -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 8 * BytesPerLong; - // No additional cost for CMOVL. const int Matcher::long_cmove_cost() { return 0; } diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index 7a34048248e..a8d36092b58 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -97,6 +97,8 @@ define_pd_global(bool, CompactStrings, true); define_pd_global(bool, PreserveFramePointer, false); +define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); + #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ \ develop(bool, IEEEPrecision, true, \ diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index e1c73024118..4bca248d815 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -7198,21 +7198,50 @@ void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_ } -void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp) { +void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp, bool is_large) { // cnt - number of qwords (8-byte words). // base - start address, qword aligned. + // is_large - if optimizers know cnt is larger than InitArrayShortSize assert(base==rdi, "base register must be edi for rep stos"); assert(tmp==rax, "tmp register must be eax for rep stos"); assert(cnt==rcx, "cnt register must be ecx for rep stos"); + assert(InitArrayShortSize % BytesPerLong == 0, + "InitArrayShortSize should be the multiple of BytesPerLong"); + + Label DONE; xorptr(tmp, tmp); + + if (!is_large) { + Label LOOP, LONG; + cmpptr(cnt, InitArrayShortSize/BytesPerLong); + jccb(Assembler::greater, LONG); + + NOT_LP64(shlptr(cnt, 1);) // convert to number of 32-bit words for 32-bit VM + + decrement(cnt); + jccb(Assembler::negative, DONE); // Zero length + + // Use individual pointer-sized stores for small counts: + BIND(LOOP); + movptr(Address(base, cnt, Address::times_ptr), tmp); + decrement(cnt); + jccb(Assembler::greaterEqual, LOOP); + jmpb(DONE); + + BIND(LONG); + } + + // Use longer rep-prefixed ops for non-small counts: if (UseFastStosb) { - shlptr(cnt,3); // convert to number of bytes + shlptr(cnt, 3); // convert to number of bytes rep_stosb(); } else { - NOT_LP64(shlptr(cnt,1);) // convert to number of dwords for 32-bit VM + NOT_LP64(shlptr(cnt, 1);) // convert to number of 32-bit words for 32-bit VM rep_stos(); } + + BIND(DONE); } #ifdef COMPILER2 diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index 95931ad2b24..84d9df6cfb4 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -1284,8 +1284,9 @@ public: // C2 compiled method's prolog code. void verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b); - // clear memory of size 'cnt' qwords, starting at 'base'. - void clear_mem(Register base, Register cnt, Register rtmp); + // clear memory of size 'cnt' qwords, starting at 'base'; + // if 'is_large' is set, do not try to produce short loop + void clear_mem(Register base, Register cnt, Register rtmp, bool is_large); #ifdef COMPILER2 void string_indexof_char(Register str1, Register cnt1, Register ch, Register result, diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index b09ca8e36ab..c9583ba13e0 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -1420,9 +1420,6 @@ const bool Matcher::isSimpleConstant64(jlong value) { // The ecx parameter to rep stos for the ClearArray node is in dwords. const bool Matcher::init_array_count_is_in_bytes = false; -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 8 * BytesPerLong; - // Needs 2 CMOV's for longs. const int Matcher::long_cmove_cost() { return 1; } @@ -11369,27 +11366,54 @@ instruct MoveL2D_reg_reg_sse(regD dst, eRegL src, regD tmp) %{ // ======================================================================= // fast clearing of an array instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ - predicate(!UseFastStosb); + predicate(!((ClearArrayNode*)n)->is_large()); match(Set dummy (ClearArray cnt base)); effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); - format %{ "XOR EAX,EAX\t# ClearArray:\n\t" - "SHL ECX,1\t# Convert doublewords to words\n\t" - "REP STOS\t# store EAX into [EDI++] while ECX--" %} + + format %{ $$template + $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t" + $$emit$$"CMP InitArrayShortSize,rcx\n\t" + $$emit$$"JG LARGE\n\t" + $$emit$$"SHL ECX, 1\n\t" + $$emit$$"DEC ECX\n\t" + $$emit$$"JS DONE\t# Zero length\n\t" + $$emit$$"MOV EAX,(EDI,ECX,4)\t# LOOP\n\t" + $$emit$$"DEC ECX\n\t" + $$emit$$"JGE LOOP\n\t" + $$emit$$"JMP DONE\n\t" + $$emit$$"# LARGE:\n\t" + if (UseFastStosb) { + $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t" + $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t" + } else { + $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t" + $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t" + } + $$emit$$"# DONE" + %} ins_encode %{ - __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register); + __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, false); %} ins_pipe( pipe_slow ); %} -instruct rep_fast_stosb(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ - predicate(UseFastStosb); +instruct rep_stos_large(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ + predicate(((ClearArrayNode*)n)->is_large()); match(Set dummy (ClearArray cnt base)); effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); - format %{ "XOR EAX,EAX\t# ClearArray:\n\t" - "SHL ECX,3\t# Convert doublewords to bytes\n\t" - "REP STOSB\t# store EAX into [EDI++] while ECX--" %} + format %{ $$template + $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t" + if (UseFastStosb) { + $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t" + $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t" + } else { + $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t" + $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t" + } + $$emit$$"# DONE" + %} ins_encode %{ - __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register); + __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, true); %} ins_pipe( pipe_slow ); %} diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 6f32ace2f18..9579436fb20 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -1637,9 +1637,6 @@ const bool Matcher::isSimpleConstant64(jlong value) { // The ecx parameter to rep stosq for the ClearArray node is in words. const bool Matcher::init_array_count_is_in_bytes = false; -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 8 * BytesPerLong; - // No additional cost for CMOVL. const int Matcher::long_cmove_cost() { return 0; } @@ -10460,31 +10457,55 @@ instruct MoveL2D_reg_reg(regD dst, rRegL src) %{ instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, rFlagsReg cr) %{ - predicate(!UseFastStosb); + predicate(!((ClearArrayNode*)n)->is_large()); match(Set dummy (ClearArray cnt base)); effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); - format %{ "xorq rax, rax\t# ClearArray:\n\t" - "rep stosq\t# Store rax to *rdi++ while rcx--" %} + format %{ $$template + $$emit$$"xorq rax, rax\t# ClearArray:\n\t" + $$emit$$"cmp InitArrayShortSize,rcx\n\t" + $$emit$$"jg LARGE\n\t" + $$emit$$"dec rcx\n\t" + $$emit$$"js DONE\t# Zero length\n\t" + $$emit$$"mov rax,(rdi,rcx,8)\t# LOOP\n\t" + $$emit$$"dec rcx\n\t" + $$emit$$"jge LOOP\n\t" + $$emit$$"jmp DONE\n\t" + $$emit$$"# LARGE:\n\t" + if (UseFastStosb) { + $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t" + $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--\n\t" + } else { + $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--\n\t" + } + $$emit$$"# DONE" + %} ins_encode %{ - __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register); + __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, false); %} ins_pipe(pipe_slow); %} -instruct rep_fast_stosb(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, - rFlagsReg cr) +instruct rep_stos_large(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, + rFlagsReg cr) %{ - predicate(UseFastStosb); + predicate(((ClearArrayNode*)n)->is_large()); match(Set dummy (ClearArray cnt base)); effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); - format %{ "xorq rax, rax\t# ClearArray:\n\t" - "shlq rcx,3\t# Convert doublewords to bytes\n\t" - "rep stosb\t# Store rax to *rdi++ while rcx--" %} - ins_encode %{ - __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register); + + format %{ $$template + $$emit$$"xorq rax, rax\t# ClearArray:\n\t" + if (UseFastStosb) { + $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t" + $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--" + } else { + $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--" + } %} - ins_pipe( pipe_slow ); + ins_encode %{ + __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, true); + %} + ins_pipe(pipe_slow); %} instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, diff --git a/hotspot/src/share/vm/opto/matcher.hpp b/hotspot/src/share/vm/opto/matcher.hpp index 64cc48c65ec..dad3854e3f2 100644 --- a/hotspot/src/share/vm/opto/matcher.hpp +++ b/hotspot/src/share/vm/opto/matcher.hpp @@ -399,10 +399,6 @@ public: // Optional scaling for the parameter to the ClearArray/CopyArray node. static const bool init_array_count_is_in_bytes; - // Threshold small size (in bytes) for a ClearArray/CopyArray node. - // Anything this size or smaller may get converted to discrete scalar stores. - static const int init_array_short_size; - // Some hardware needs 2 CMOV's for longs. static const int long_cmove_cost(); diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 51733c8fa65..a09caf81bb7 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -2741,6 +2741,9 @@ Node* ClearArrayNode::Identity(PhaseGVN* phase) { //------------------------------Idealize--------------------------------------- // Clearing a short array is faster with stores Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape){ + // Already know this is a large node, do not try to ideal it + if (_is_large) return NULL; + const int unit = BytesPerLong; const TypeX* t = phase->type(in(2))->isa_intptr_t(); if (!t) return NULL; @@ -2753,8 +2756,11 @@ Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape){ // (see jck test stmt114.stmt11402.val). if (size <= 0 || size % unit != 0) return NULL; intptr_t count = size / unit; - // Length too long; use fast hardware clear - if (size > Matcher::init_array_short_size) return NULL; + // Length too long; communicate this to matchers and assemblers. + // Assemblers are responsible to produce fast hardware clears for it. + if (size > InitArrayShortSize) { + return new ClearArrayNode(in(0), in(1), in(2), in(3), true); + } Node *mem = in(1); if( phase->type(mem)==Type::TOP ) return NULL; Node *adr = in(3); @@ -2852,7 +2858,7 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, // Bulk clear double-words Node* zsize = phase->transform(new SubXNode(zend, zbase) ); Node* adr = phase->transform(new AddPNode(dest, dest, start_offset) ); - mem = new ClearArrayNode(ctl, mem, zsize, adr); + mem = new ClearArrayNode(ctl, mem, zsize, adr, false); return phase->transform(mem); } @@ -3901,7 +3907,7 @@ Node* InitializeNode::complete_stores(Node* rawctl, Node* rawmem, Node* rawptr, zeroes_done, zeroes_needed, phase); zeroes_done = zeroes_needed; - if (zsize > Matcher::init_array_short_size && ++big_init_gaps > 2) + if (zsize > InitArrayShortSize && ++big_init_gaps > 2) do_zeroing = false; // leave the hole, next time } } diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 8d9cd71bc0a..c1477bb2e4c 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -1013,9 +1013,11 @@ public: //------------------------------ClearArray------------------------------------- class ClearArrayNode: public Node { +private: + bool _is_large; public: - ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base ) - : Node(ctrl,arymem,word_cnt,base) { + ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base, bool is_large) + : Node(ctrl,arymem,word_cnt,base), _is_large(is_large) { init_class_id(Class_ClearArray); } virtual int Opcode() const; @@ -1026,6 +1028,7 @@ public: virtual Node* Identity(PhaseGVN* phase); virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual uint match_edge(uint idx) const; + bool is_large() const { return _is_large; } // Clear the given area of an object or array. // The start offset must always be aligned mod BytesPerInt. diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp index 1484cba01c8..bfadc319516 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp @@ -354,6 +354,14 @@ Flag::Error TypeProfileLevelConstraintFunc(uintx value, bool verbose) { return Flag::SUCCESS; } +Flag::Error InitArrayShortSizeConstraintFunc(intx value, bool verbose) { + if (value % BytesPerLong != 0) { + return Flag::VIOLATES_CONSTRAINT; + } else { + return Flag::SUCCESS; + } +} + #ifdef COMPILER2 Flag::Error InteriorEntryAlignmentConstraintFunc(intx value, bool verbose) { if (InteriorEntryAlignment > CodeEntryAlignment) { diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp index f9d07848960..0038d52eac8 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp @@ -62,6 +62,8 @@ Flag::Error ArraycopySrcPrefetchDistanceConstraintFunc(uintx value, bool verbose Flag::Error TypeProfileLevelConstraintFunc(uintx value, bool verbose); +Flag::Error InitArrayShortSizeConstraintFunc(intx value, bool verbose); + #ifdef COMPILER2 Flag::Error InteriorEntryAlignmentConstraintFunc(intx value, bool verbose); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index ce36ff1db49..113a9f71ab6 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -4162,6 +4162,13 @@ public: "in the loaded class C. " \ "Check (3) is available only in debug builds.") \ \ + develop_pd(intx, InitArrayShortSize, \ + "Threshold small size (in bytes) for clearing arrays. " \ + "Anything this size or smaller may get converted to discrete " \ + "scalar stores.") \ + range(0, max_intx) \ + constraint(InitArrayShortSizeConstraintFunc, AfterErgo) \ + \ diagnostic(bool, CompilerDirectivesIgnoreCompileCommands, false, \ "Disable backwards compatibility for compile commands.") \ \ From 40fe96de0de8f604ba19055650aa2657f000d1fa Mon Sep 17 00:00:00 2001 From: Vivek Deshpande Date: Thu, 3 Mar 2016 22:02:13 -0800 Subject: [PATCH 056/311] 8150767: Enables SHA Extensions on x86 Add x86 intrinsics for SHA-1 and SHA-256. Co-authored-by: Shravya Rukmannagari Reviewed-by: kvn, twisti --- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 88 ++++ hotspot/src/cpu/x86/vm/assembler_x86.hpp | 13 + hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 52 +- .../src/cpu/x86/vm/macroAssembler_x86_sha.cpp | 495 ++++++++++++++++++ .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 143 +++++ .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 140 +++++ hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp | 30 ++ hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp | 15 + hotspot/src/cpu/x86/vm/vmStructs_x86.hpp | 7 +- hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 27 +- hotspot/src/cpu/x86/vm/vm_version_x86.hpp | 13 +- .../src/jdk/vm/ci/amd64/AMD64.java | 3 +- .../AMD64HotSpotJVMCIBackendFactory.java | 3 + .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 1 + .../src/share/vm/jvmci/vmStructs_jvmci.cpp | 7 +- hotspot/src/share/vm/runtime/globals.hpp | 2 +- 16 files changed, 1011 insertions(+), 28 deletions(-) create mode 100644 hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 00ce5c3560c..65f2da7ecd0 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -777,6 +777,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) { case 0x6E: // movd case 0x7E: // movd case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush + case 0xFE: // paddd debug_only(has_disp32 = true); break; @@ -926,6 +927,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) { ip++; // skip P2, move to opcode // To find the end of instruction (which == end_pc_operand). switch (0xFF & *ip) { + case 0x22: // pinsrd r, r/a, #8 case 0x61: // pcmpestri r, r/a, #8 case 0x70: // pshufd r, r/a, #8 case 0x73: // psrldq r, #8 @@ -3953,6 +3955,83 @@ void Assembler::setb(Condition cc, Register dst) { emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::palignr(XMMRegister dst, XMMRegister src, int imm8) { + assert(VM_Version::supports_ssse3(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8((unsigned char)0x0F); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8(imm8); +} + +void Assembler::pblendw(XMMRegister dst, XMMRegister src, int imm8) { + assert(VM_Version::supports_sse4_1(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8((unsigned char)0x0E); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8(imm8); +} + +void Assembler::sha1rnds4(XMMRegister dst, XMMRegister src, int imm8) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes); + emit_int8((unsigned char)0xCC); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8((unsigned char)imm8); +} + +void Assembler::sha1nexte(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xC8); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::sha1msg1(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xC9); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::sha1msg2(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xCA); + emit_int8((unsigned char)(0xC0 | encode)); +} + +// xmm0 is implicit additional source to this instruction. +void Assembler::sha256rnds2(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xCB); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::sha256msg1(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xCC); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::sha256msg2(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xCD); + emit_int8((unsigned char)(0xC0 | encode)); +} + + void Assembler::shll(Register dst, int imm8) { assert(isShiftCount(imm8), "illegal shift count"); int encode = prefix_and_encode(dst->encoding()); @@ -4931,6 +5010,15 @@ void Assembler::paddd(XMMRegister dst, XMMRegister src) { emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::paddd(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + simd_prefix(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0xFE); + emit_operand(dst, src); +} + void Assembler::paddq(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index 7712ce02cab..3026afda174 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1672,6 +1672,18 @@ private: void setb(Condition cc, Register dst); + void palignr(XMMRegister dst, XMMRegister src, int imm8); + void pblendw(XMMRegister dst, XMMRegister src, int imm8); + + void sha1rnds4(XMMRegister dst, XMMRegister src, int imm8); + void sha1nexte(XMMRegister dst, XMMRegister src); + void sha1msg1(XMMRegister dst, XMMRegister src); + void sha1msg2(XMMRegister dst, XMMRegister src); + // xmm0 is implicit additional source to the following instruction. + void sha256rnds2(XMMRegister dst, XMMRegister src); + void sha256msg1(XMMRegister dst, XMMRegister src); + void sha256msg2(XMMRegister dst, XMMRegister src); + void shldl(Register dst, Register src); void shldl(Register dst, Register src, int8_t imm8); @@ -1868,6 +1880,7 @@ private: void paddb(XMMRegister dst, XMMRegister src); void paddw(XMMRegister dst, XMMRegister src); void paddd(XMMRegister dst, XMMRegister src); + void paddd(XMMRegister dst, Address src); void paddq(XMMRegister dst, XMMRegister src); void vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index 84d9df6cfb4..d33473606aa 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -48,7 +48,6 @@ class MacroAssembler: public Assembler { // This is the base routine called by the different versions of call_VM_leaf. The interpreter // may customize this version by overriding it for its purposes (e.g., to save/restore // additional registers when doing a VM call). -#define COMMA , virtual void call_VM_leaf_base( address entry_point, // the entry point @@ -903,35 +902,66 @@ class MacroAssembler: public Assembler { void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } void ldmxcsr(AddressLiteral src); + void fast_sha1(XMMRegister abcd, XMMRegister e0, XMMRegister e1, XMMRegister msg0, + XMMRegister msg1, XMMRegister msg2, XMMRegister msg3, XMMRegister shuf_mask, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block); + +#ifdef _LP64 + void fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, + XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block, XMMRegister shuf_mask); +#else + void fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, + XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block); +#endif + void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx, Register rdx, Register tmp); +#ifdef _LP64 void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rcx, Register rdx, Register tmp1 LP64_ONLY(COMMA Register tmp2)); + Register rax, Register rcx, Register rdx, Register tmp1, Register tmp2); void fast_pow(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx, - Register rdx NOT_LP64(COMMA Register tmp) LP64_ONLY(COMMA Register tmp1) - LP64_ONLY(COMMA Register tmp2) LP64_ONLY(COMMA Register tmp3) LP64_ONLY(COMMA Register tmp4)); + Register rdx, Register tmp1, Register tmp2, Register tmp3, Register tmp4); void fast_sin(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rbx LP64_ONLY(COMMA Register rcx), Register rdx - LP64_ONLY(COMMA Register tmp1) LP64_ONLY(COMMA Register tmp2) - LP64_ONLY(COMMA Register tmp3) LP64_ONLY(COMMA Register tmp4)); + Register rax, Register rbx, Register rcx, Register rdx, Register tmp1, Register tmp2, + Register tmp3, Register tmp4); void fast_cos(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rcx, Register rdx NOT_LP64(COMMA Register tmp) - LP64_ONLY(COMMA Register r8) LP64_ONLY(COMMA Register r9) - LP64_ONLY(COMMA Register r10) LP64_ONLY(COMMA Register r11)); + Register rax, Register rcx, Register rdx, Register tmp1, + Register tmp2, Register tmp3, Register tmp4); +#else + void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, + XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, + Register rax, Register rcx, Register rdx, Register tmp1); + + void fast_pow(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, + XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx, + Register rdx, Register tmp); + + void fast_sin(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, + XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, + Register rax, Register rbx, Register rdx); + + void fast_cos(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, + XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, + Register rax, Register rcx, Register rdx, Register tmp); -#ifndef _LP64 void libm_sincos_huge(XMMRegister xmm0, XMMRegister xmm1, Register eax, Register ecx, Register edx, Register ebx, Register esi, Register edi, Register ebp, Register esp); + void libm_reduce_pi04l(Register eax, Register ecx, Register edx, Register ebx, Register esi, Register edi, Register ebp, Register esp); #endif diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp new file mode 100644 index 00000000000..bbc96156fe5 --- /dev/null +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp @@ -0,0 +1,495 @@ +/* +* Copyright (c) 2016, Intel Corporation. +* +* 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. +* +*/ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "runtime/stubRoutines.hpp" +#include "macroAssembler_x86.hpp" + +// ofs and limit are used for multi-block byte array. +// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) +void MacroAssembler::fast_sha1(XMMRegister abcd, XMMRegister e0, XMMRegister e1, XMMRegister msg0, + XMMRegister msg1, XMMRegister msg2, XMMRegister msg3, XMMRegister shuf_mask, + Register buf, Register state, Register ofs, Register limit, Register rsp, bool multi_block) { + + Label start, done_hash, loop0; + + address upper_word_mask = StubRoutines::x86::upper_word_mask_addr(); + address shuffle_byte_flip_mask = StubRoutines::x86::shuffle_byte_flip_mask_addr(); + + bind(start); + movdqu(abcd, Address(state, 0)); + pinsrd(e0, Address(state, 16), 3); + movdqu(shuf_mask, ExternalAddress(upper_word_mask)); // 0xFFFFFFFF000000000000000000000000 + pand(e0, shuf_mask); + pshufd(abcd, abcd, 0x1B); + movdqu(shuf_mask, ExternalAddress(shuffle_byte_flip_mask)); //0x000102030405060708090a0b0c0d0e0f + + bind(loop0); + // Save hash values for addition after rounds + movdqu(Address(rsp, 0), e0); + movdqu(Address(rsp, 16), abcd); + + + // Rounds 0 - 3 + movdqu(msg0, Address(buf, 0)); + pshufb(msg0, shuf_mask); + paddd(e0, msg0); + movdqa(e1, abcd); + sha1rnds4(abcd, e0, 0); + + // Rounds 4 - 7 + movdqu(msg1, Address(buf, 16)); + pshufb(msg1, shuf_mask); + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1rnds4(abcd, e1, 0); + sha1msg1(msg0, msg1); + + // Rounds 8 - 11 + movdqu(msg2, Address(buf, 32)); + pshufb(msg2, shuf_mask); + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1rnds4(abcd, e0, 0); + sha1msg1(msg1, msg2); + pxor(msg0, msg2); + + // Rounds 12 - 15 + movdqu(msg3, Address(buf, 48)); + pshufb(msg3, shuf_mask); + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1msg2(msg0, msg3); + sha1rnds4(abcd, e1, 0); + sha1msg1(msg2, msg3); + pxor(msg1, msg3); + + // Rounds 16 - 19 + sha1nexte(e0, msg0); + movdqa(e1, abcd); + sha1msg2(msg1, msg0); + sha1rnds4(abcd, e0, 0); + sha1msg1(msg3, msg0); + pxor(msg2, msg0); + + // Rounds 20 - 23 + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1msg2(msg2, msg1); + sha1rnds4(abcd, e1, 1); + sha1msg1(msg0, msg1); + pxor(msg3, msg1); + + // Rounds 24 - 27 + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1msg2(msg3, msg2); + sha1rnds4(abcd, e0, 1); + sha1msg1(msg1, msg2); + pxor(msg0, msg2); + + // Rounds 28 - 31 + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1msg2(msg0, msg3); + sha1rnds4(abcd, e1, 1); + sha1msg1(msg2, msg3); + pxor(msg1, msg3); + + // Rounds 32 - 35 + sha1nexte(e0, msg0); + movdqa(e1, abcd); + sha1msg2(msg1, msg0); + sha1rnds4(abcd, e0, 1); + sha1msg1(msg3, msg0); + pxor(msg2, msg0); + + // Rounds 36 - 39 + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1msg2(msg2, msg1); + sha1rnds4(abcd, e1, 1); + sha1msg1(msg0, msg1); + pxor(msg3, msg1); + + // Rounds 40 - 43 + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1msg2(msg3, msg2); + sha1rnds4(abcd, e0, 2); + sha1msg1(msg1, msg2); + pxor(msg0, msg2); + + // Rounds 44 - 47 + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1msg2(msg0, msg3); + sha1rnds4(abcd, e1, 2); + sha1msg1(msg2, msg3); + pxor(msg1, msg3); + + // Rounds 48 - 51 + sha1nexte(e0, msg0); + movdqa(e1, abcd); + sha1msg2(msg1, msg0); + sha1rnds4(abcd, e0, 2); + sha1msg1(msg3, msg0); + pxor(msg2, msg0); + + // Rounds 52 - 55 + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1msg2(msg2, msg1); + sha1rnds4(abcd, e1, 2); + sha1msg1(msg0, msg1); + pxor(msg3, msg1); + + // Rounds 56 - 59 + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1msg2(msg3, msg2); + sha1rnds4(abcd, e0, 2); + sha1msg1(msg1, msg2); + pxor(msg0, msg2); + + // Rounds 60 - 63 + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1msg2(msg0, msg3); + sha1rnds4(abcd, e1, 3); + sha1msg1(msg2, msg3); + pxor(msg1, msg3); + + // Rounds 64 - 67 + sha1nexte(e0, msg0); + movdqa(e1, abcd); + sha1msg2(msg1, msg0); + sha1rnds4(abcd, e0, 3); + sha1msg1(msg3, msg0); + pxor(msg2, msg0); + + // Rounds 68 - 71 + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1msg2(msg2, msg1); + sha1rnds4(abcd, e1, 3); + pxor(msg3, msg1); + + // Rounds 72 - 75 + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1msg2(msg3, msg2); + sha1rnds4(abcd, e0, 3); + + // Rounds 76 - 79 + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1rnds4(abcd, e1, 3); + + // add current hash values with previously saved + movdqu(msg0, Address(rsp, 0)); + sha1nexte(e0, msg0); + movdqu(msg0, Address(rsp, 16)); + paddd(abcd, msg0); + + if (multi_block) { + // increment data pointer and loop if more to process + addptr(buf, 64); + addptr(ofs, 64); + cmpptr(ofs, limit); + jcc(Assembler::belowEqual, loop0); + movptr(rax, ofs); //return ofs + } + // write hash values back in the correct order + pshufd(abcd, abcd, 0x1b); + movdqu(Address(state, 0), abcd); + pextrd(Address(state, 16), e0, 3); + + bind(done_hash); + +} + +// xmm0 (msg) is used as an implicit argument to sh256rnds2 +// and state0 and state1 can never use xmm0 register. +// ofs and limit are used for multi-block byte array. +// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) +#ifdef _LP64 +void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, + XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block, XMMRegister shuf_mask) { +#else +void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, + XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block) { +#endif + Label start, done_hash, loop0; + + address K256 = StubRoutines::x86::k256_addr(); + address pshuffle_byte_flip_mask = StubRoutines::x86::pshuffle_byte_flip_mask_addr(); + + bind(start); + movdqu(state0, Address(state, 0)); + movdqu(state1, Address(state, 16)); + + pshufd(state0, state0, 0xB1); + pshufd(state1, state1, 0x1B); + movdqa(msgtmp4, state0); + palignr(state0, state1, 8); + pblendw(state1, msgtmp4, 0xF0); + +#ifdef _LP64 + movdqu(shuf_mask, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + lea(rax, ExternalAddress(K256)); + + bind(loop0); + movdqu(Address(rsp, 0), state0); + movdqu(Address(rsp, 16), state1); + + // Rounds 0-3 + movdqu(msg, Address(buf, 0)); +#ifdef _LP64 + pshufb(msg, shuf_mask); +#else + pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + movdqa(msgtmp0, msg); + paddd(msg, Address(rax, 0)); + sha256rnds2(state1, state0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + + // Rounds 4-7 + movdqu(msg, Address(buf, 16)); +#ifdef _LP64 + pshufb(msg, shuf_mask); +#else + pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + movdqa(msgtmp1, msg); + paddd(msg, Address(rax, 16)); + sha256rnds2(state1, state0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp0, msgtmp1); + + // Rounds 8-11 + movdqu(msg, Address(buf, 32)); +#ifdef _LP64 + pshufb(msg, shuf_mask); +#else + pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + movdqa(msgtmp2, msg); + paddd(msg, Address(rax, 32)); + sha256rnds2(state1, state0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp1, msgtmp2); + + // Rounds 12-15 + movdqu(msg, Address(buf, 48)); +#ifdef _LP64 + pshufb(msg, shuf_mask); +#else + pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + movdqa(msgtmp3, msg); + paddd(msg, Address(rax, 48)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp3); + palignr(msgtmp4, msgtmp2, 4); + paddd(msgtmp0, msgtmp4); + sha256msg2(msgtmp0, msgtmp3); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp2, msgtmp3); + + // Rounds 16-19 + movdqa(msg, msgtmp0); + paddd(msg, Address(rax, 64)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp0); + palignr(msgtmp4, msgtmp3, 4); + paddd(msgtmp1, msgtmp4); + sha256msg2(msgtmp1, msgtmp0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp3, msgtmp0); + + // Rounds 20-23 + movdqa(msg, msgtmp1); + paddd(msg, Address(rax, 80)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp1); + palignr(msgtmp4, msgtmp0, 4); + paddd(msgtmp2, msgtmp4); + sha256msg2(msgtmp2, msgtmp1); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp0, msgtmp1); + + // Rounds 24-27 + movdqa(msg, msgtmp2); + paddd(msg, Address(rax, 96)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp2); + palignr(msgtmp4, msgtmp1, 4); + paddd(msgtmp3, msgtmp4); + sha256msg2(msgtmp3, msgtmp2); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp1, msgtmp2); + + // Rounds 28-31 + movdqa(msg, msgtmp3); + paddd(msg, Address(rax, 112)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp3); + palignr(msgtmp4, msgtmp2, 4); + paddd(msgtmp0, msgtmp4); + sha256msg2(msgtmp0, msgtmp3); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp2, msgtmp3); + + // Rounds 32-35 + movdqa(msg, msgtmp0); + paddd(msg, Address(rax, 128)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp0); + palignr(msgtmp4, msgtmp3, 4); + paddd(msgtmp1, msgtmp4); + sha256msg2(msgtmp1, msgtmp0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp3, msgtmp0); + + // Rounds 36-39 + movdqa(msg, msgtmp1); + paddd(msg, Address(rax, 144)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp1); + palignr(msgtmp4, msgtmp0, 4); + paddd(msgtmp2, msgtmp4); + sha256msg2(msgtmp2, msgtmp1); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp0, msgtmp1); + + // Rounds 40-43 + movdqa(msg, msgtmp2); + paddd(msg, Address(rax, 160)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp2); + palignr(msgtmp4, msgtmp1, 4); + paddd(msgtmp3, msgtmp4); + sha256msg2(msgtmp3, msgtmp2); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp1, msgtmp2); + + // Rounds 44-47 + movdqa(msg, msgtmp3); + paddd(msg, Address(rax, 176)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp3); + palignr(msgtmp4, msgtmp2, 4); + paddd(msgtmp0, msgtmp4); + sha256msg2(msgtmp0, msgtmp3); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp2, msgtmp3); + + // Rounds 48-51 + movdqa(msg, msgtmp0); + paddd(msg, Address(rax, 192)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp0); + palignr(msgtmp4, msgtmp3, 4); + paddd(msgtmp1, msgtmp4); + sha256msg2(msgtmp1, msgtmp0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp3, msgtmp0); + + // Rounds 52-55 + movdqa(msg, msgtmp1); + paddd(msg, Address(rax, 208)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp1); + palignr(msgtmp4, msgtmp0, 4); + paddd(msgtmp2, msgtmp4); + sha256msg2(msgtmp2, msgtmp1); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + + // Rounds 56-59 + movdqa(msg, msgtmp2); + paddd(msg, Address(rax, 224)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp2); + palignr(msgtmp4, msgtmp1, 4); + paddd(msgtmp3, msgtmp4); + sha256msg2(msgtmp3, msgtmp2); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + + // Rounds 60-63 + movdqa(msg, msgtmp3); + paddd(msg, Address(rax, 240)); + sha256rnds2(state1, state0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + movdqu(msg, Address(rsp, 0)); + paddd(state0, msg); + movdqu(msg, Address(rsp, 16)); + paddd(state1, msg); + + if (multi_block) { + // increment data pointer and loop if more to process + addptr(buf, 64); + addptr(ofs, 64); + cmpptr(ofs, limit); + jcc(Assembler::belowEqual, loop0); + movptr(rax, ofs); //return ofs + } + + pshufd(state0, state0, 0x1B); + pshufd(state1, state1, 0xB1); + movdqa(msgtmp4, state0); + pblendw(state0, state1, 0xF0); + palignr(state1, msgtmp4, 8); + + movdqu(Address(state, 0), state0); + movdqu(Address(state, 16), state1); + + bind(done_hash); + +} diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 894e4cb3319..f5652df8b31 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -3068,6 +3068,136 @@ class StubGenerator: public StubCodeGenerator { return start; } + address generate_upper_word_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "upper_word_mask"); + address start = __ pc(); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0xFFFFFFFF, relocInfo::none, 0); + return start; + } + + address generate_shuffle_byte_flip_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "shuffle_byte_flip_mask"); + address start = __ pc(); + __ emit_data(0x0c0d0e0f, relocInfo::none, 0); + __ emit_data(0x08090a0b, relocInfo::none, 0); + __ emit_data(0x04050607, relocInfo::none, 0); + __ emit_data(0x00010203, relocInfo::none, 0); + return start; + } + + // ofs and limit are use for multi-block byte array. + // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) + address generate_sha1_implCompress(bool multi_block, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + Register buf = rax; + Register state = rdx; + Register ofs = rcx; + Register limit = rdi; + + const Address buf_param(rbp, 8 + 0); + const Address state_param(rbp, 8 + 4); + const Address ofs_param(rbp, 8 + 8); + const Address limit_param(rbp, 8 + 12); + + const XMMRegister abcd = xmm0; + const XMMRegister e0 = xmm1; + const XMMRegister e1 = xmm2; + const XMMRegister msg0 = xmm3; + + const XMMRegister msg1 = xmm4; + const XMMRegister msg2 = xmm5; + const XMMRegister msg3 = xmm6; + const XMMRegister shuf_mask = xmm7; + + __ enter(); + __ subptr(rsp, 8 * wordSize); + if (multi_block) { + __ push(limit); + } + __ movptr(buf, buf_param); + __ movptr(state, state_param); + if (multi_block) { + __ movptr(ofs, ofs_param); + __ movptr(limit, limit_param); + } + + __ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask, + buf, state, ofs, limit, rsp, multi_block); + + if (multi_block) { + __ pop(limit); + } + __ addptr(rsp, 8 * wordSize); + __ leave(); + __ ret(0); + return start; + } + + address generate_pshuffle_byte_flip_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "pshuffle_byte_flip_mask"); + address start = __ pc(); + __ emit_data(0x00010203, relocInfo::none, 0); + __ emit_data(0x04050607, relocInfo::none, 0); + __ emit_data(0x08090a0b, relocInfo::none, 0); + __ emit_data(0x0c0d0e0f, relocInfo::none, 0); + return start; + } + + // ofs and limit are use for multi-block byte array. + // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) + address generate_sha256_implCompress(bool multi_block, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + Register buf = rbx; + Register state = rsi; + Register ofs = rdx; + Register limit = rcx; + + const Address buf_param(rbp, 8 + 0); + const Address state_param(rbp, 8 + 4); + const Address ofs_param(rbp, 8 + 8); + const Address limit_param(rbp, 8 + 12); + + const XMMRegister msg = xmm0; + const XMMRegister state0 = xmm1; + const XMMRegister state1 = xmm2; + const XMMRegister msgtmp0 = xmm3; + + const XMMRegister msgtmp1 = xmm4; + const XMMRegister msgtmp2 = xmm5; + const XMMRegister msgtmp3 = xmm6; + const XMMRegister msgtmp4 = xmm7; + + __ enter(); + __ subptr(rsp, 8 * wordSize); + handleSOERegisters(true /*saving*/); + __ movptr(buf, buf_param); + __ movptr(state, state_param); + if (multi_block) { + __ movptr(ofs, ofs_param); + __ movptr(limit, limit_param); + } + + __ fast_sha256(msg, state0, state1, msgtmp0, msgtmp1, msgtmp2, msgtmp3, msgtmp4, + buf, state, ofs, limit, rsp, multi_block); + + handleSOERegisters(false); + __ addptr(rsp, 8 * wordSize); + __ leave(); + __ ret(0); + return start; + } // byte swap x86 long address generate_ghash_long_swap_mask() { @@ -3772,6 +3902,19 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_counterMode_AESCrypt = generate_counterMode_AESCrypt_Parallel(); } + if (UseSHA1Intrinsics) { + StubRoutines::x86::_upper_word_mask_addr = generate_upper_word_mask(); + StubRoutines::x86::_shuffle_byte_flip_mask_addr = generate_shuffle_byte_flip_mask(); + StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress"); + StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB"); + } + if (UseSHA256Intrinsics) { + StubRoutines::x86::_k256_adr = (address)StubRoutines::x86::_k256; + StubRoutines::x86::_pshuffle_byte_flip_mask_addr = generate_pshuffle_byte_flip_mask(); + StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress"); + StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB"); + } + // Generate GHASH intrinsics code if (UseGHASHIntrinsics) { StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask(); diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index db518d804db..2f4adc88506 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -3695,6 +3695,133 @@ class StubGenerator: public StubCodeGenerator { return start; } + address generate_upper_word_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "upper_word_mask"); + address start = __ pc(); + __ emit_data64(0x0000000000000000, relocInfo::none); + __ emit_data64(0xFFFFFFFF00000000, relocInfo::none); + return start; + } + + address generate_shuffle_byte_flip_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "shuffle_byte_flip_mask"); + address start = __ pc(); + __ emit_data64(0x08090a0b0c0d0e0f, relocInfo::none); + __ emit_data64(0x0001020304050607, relocInfo::none); + return start; + } + + // ofs and limit are use for multi-block byte array. + // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) + address generate_sha1_implCompress(bool multi_block, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + Register buf = c_rarg0; + Register state = c_rarg1; + Register ofs = c_rarg2; + Register limit = c_rarg3; + + const XMMRegister abcd = xmm0; + const XMMRegister e0 = xmm1; + const XMMRegister e1 = xmm2; + const XMMRegister msg0 = xmm3; + + const XMMRegister msg1 = xmm4; + const XMMRegister msg2 = xmm5; + const XMMRegister msg3 = xmm6; + const XMMRegister shuf_mask = xmm7; + + __ enter(); + +#ifdef _WIN64 + // save the xmm registers which must be preserved 6-7 + __ subptr(rsp, 4 * wordSize); + __ movdqu(Address(rsp, 0), xmm6); + __ movdqu(Address(rsp, 2 * wordSize), xmm7); +#endif + + __ subptr(rsp, 4 * wordSize); + + __ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask, + buf, state, ofs, limit, rsp, multi_block); + + __ addptr(rsp, 4 * wordSize); +#ifdef _WIN64 + // restore xmm regs belonging to calling function + __ movdqu(xmm6, Address(rsp, 0)); + __ movdqu(xmm7, Address(rsp, 2 * wordSize)); + __ addptr(rsp, 4 * wordSize); +#endif + + __ leave(); + __ ret(0); + return start; + } + + address generate_pshuffle_byte_flip_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "pshuffle_byte_flip_mask"); + address start = __ pc(); + __ emit_data64(0x0405060700010203, relocInfo::none); + __ emit_data64(0x0c0d0e0f08090a0b, relocInfo::none); + return start; + } + +// ofs and limit are use for multi-block byte array. +// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) + address generate_sha256_implCompress(bool multi_block, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + Register buf = c_rarg0; + Register state = c_rarg1; + Register ofs = c_rarg2; + Register limit = c_rarg3; + + const XMMRegister msg = xmm0; + const XMMRegister state0 = xmm1; + const XMMRegister state1 = xmm2; + const XMMRegister msgtmp0 = xmm3; + + const XMMRegister msgtmp1 = xmm4; + const XMMRegister msgtmp2 = xmm5; + const XMMRegister msgtmp3 = xmm6; + const XMMRegister msgtmp4 = xmm7; + + const XMMRegister shuf_mask = xmm8; + + __ enter(); +#ifdef _WIN64 + // save the xmm registers which must be preserved 6-7 + __ subptr(rsp, 6 * wordSize); + __ movdqu(Address(rsp, 0), xmm6); + __ movdqu(Address(rsp, 2 * wordSize), xmm7); + __ movdqu(Address(rsp, 4 * wordSize), xmm8); +#endif + + __ subptr(rsp, 4 * wordSize); + + __ fast_sha256(msg, state0, state1, msgtmp0, msgtmp1, msgtmp2, msgtmp3, msgtmp4, + buf, state, ofs, limit, rsp, multi_block, shuf_mask); + + __ addptr(rsp, 4 * wordSize); +#ifdef _WIN64 + // restore xmm regs belonging to calling function + __ movdqu(xmm6, Address(rsp, 0)); + __ movdqu(xmm7, Address(rsp, 2 * wordSize)); + __ movdqu(xmm8, Address(rsp, 4 * wordSize)); + __ addptr(rsp, 6 * wordSize); +#endif + __ leave(); + __ ret(0); + return start; + } + // This is a version of CTR/AES crypt which does 6 blocks in a loop at a time // to hide instruction latency // @@ -4974,6 +5101,19 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_counterMode_AESCrypt = generate_counterMode_AESCrypt_Parallel(); } + if (UseSHA1Intrinsics) { + StubRoutines::x86::_upper_word_mask_addr = generate_upper_word_mask(); + StubRoutines::x86::_shuffle_byte_flip_mask_addr = generate_shuffle_byte_flip_mask(); + StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress"); + StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB"); + } + if (UseSHA256Intrinsics) { + StubRoutines::x86::_k256_adr = (address)StubRoutines::x86::_k256; + StubRoutines::x86::_pshuffle_byte_flip_mask_addr = generate_pshuffle_byte_flip_mask(); + StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress"); + StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB"); + } + // Generate GHASH intrinsics code if (UseGHASHIntrinsics) { StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask(); diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp index 3bc199b1db5..141fbf048eb 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp @@ -29,6 +29,12 @@ #include "runtime/thread.inline.hpp" #include "crc32c.h" +#ifdef _MSC_VER +#define ALIGNED_(x) __declspec(align(x)) +#else +#define ALIGNED_(x) __attribute__ ((aligned(x))) +#endif + // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. @@ -37,6 +43,10 @@ address StubRoutines::x86::_key_shuffle_mask_addr = NULL; address StubRoutines::x86::_counter_shuffle_mask_addr = NULL; address StubRoutines::x86::_ghash_long_swap_mask_addr = NULL; address StubRoutines::x86::_ghash_byte_swap_mask_addr = NULL; +address StubRoutines::x86::_upper_word_mask_addr = NULL; +address StubRoutines::x86::_shuffle_byte_flip_mask_addr = NULL; +address StubRoutines::x86::_k256_adr = NULL; +address StubRoutines::x86::_pshuffle_byte_flip_mask_addr = NULL; uint64_t StubRoutines::x86::_crc_by128_masks[] = { @@ -236,3 +246,23 @@ void StubRoutines::x86::generate_CRC32C_table(bool is_pclmulqdq_table_supported) _crc32c_table = (juint*)pclmulqdq_table; } } + +ALIGNED_(64) juint StubRoutines::x86::_k256[] = +{ + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp index 5b2bf4bdf91..4c9ce0153fd 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp @@ -46,6 +46,17 @@ static address _ghash_long_swap_mask_addr; static address _ghash_byte_swap_mask_addr; + // upper word mask for sha1 + static address _upper_word_mask_addr; + // byte flip mask for sha1 + static address _shuffle_byte_flip_mask_addr; + + //k256 table for sha256 + static juint _k256[]; + static address _k256_adr; + // byte flip mask for sha256 + static address _pshuffle_byte_flip_mask_addr; + public: static address verify_mxcsr_entry() { return _verify_mxcsr_entry; } static address key_shuffle_mask_addr() { return _key_shuffle_mask_addr; } @@ -53,5 +64,9 @@ static address crc_by128_masks_addr() { return (address)_crc_by128_masks; } static address ghash_long_swap_mask_addr() { return _ghash_long_swap_mask_addr; } static address ghash_byte_swap_mask_addr() { return _ghash_byte_swap_mask_addr; } + static address upper_word_mask_addr() { return _upper_word_mask_addr; } + static address shuffle_byte_flip_mask_addr() { return _shuffle_byte_flip_mask_addr; } + static address k256_addr() { return _k256_adr; } + static address pshuffle_byte_flip_mask_addr() { return _pshuffle_byte_flip_mask_addr; } static void generate_CRC32C_table(bool is_pclmulqdq_supported); #endif // CPU_X86_VM_STUBROUTINES_X86_32_HPP diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp index 40e6e431882..713ee14472d 100644 --- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp @@ -68,10 +68,11 @@ declare_constant(VM_Version::CPU_AVX512DQ) \ declare_constant(VM_Version::CPU_AVX512PF) \ declare_constant(VM_Version::CPU_AVX512ER) \ - declare_constant(VM_Version::CPU_AVX512CD) \ - declare_constant(VM_Version::CPU_AVX512BW) + declare_constant(VM_Version::CPU_AVX512CD) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ - declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) + declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \ + declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \ + declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) #endif // CPU_X86_VM_VMSTRUCTS_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 0bfd8e8f3e0..7472ad4def1 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -577,7 +577,7 @@ void VM_Version::get_processor_features() { } char buf[256]; - jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, (supports_cmov() ? ", cmov" : ""), @@ -608,7 +608,8 @@ void VM_Version::get_processor_features() { (supports_bmi1() ? ", bmi1" : ""), (supports_bmi2() ? ", bmi2" : ""), (supports_adx() ? ", adx" : ""), - (supports_evex() ? ", evex" : "")); + (supports_evex() ? ", evex" : ""), + (supports_sha() ? ", sha" : "")); _features_string = os::strdup(buf); // UseSSE is set to the smaller of what hardware supports and what @@ -730,17 +731,29 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } - if (UseSHA) { + if (supports_sha()) { + if (FLAG_IS_DEFAULT(UseSHA)) { + UseSHA = true; + } + } else if (UseSHA) { warning("SHA instructions are not available on this CPU"); FLAG_SET_DEFAULT(UseSHA, false); } - if (UseSHA1Intrinsics) { + if (UseSHA) { + if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); + } + } else if (UseSHA1Intrinsics) { warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); } - if (UseSHA256Intrinsics) { + if (UseSHA) { + if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); + } + } else if (UseSHA256Intrinsics) { warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); } @@ -750,6 +763,10 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } + if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA, false); + } + if (UseAdler32Intrinsics) { warning("Adler32Intrinsics not available on this CPU."); FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp index 77550a96a4c..8dca27b546b 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp @@ -221,7 +221,7 @@ class VM_Version : public Abstract_VM_Version { avx512pf : 1, avx512er : 1, avx512cd : 1, - : 1, + sha : 1, avx512bw : 1, avx512vl : 1; } bits; @@ -282,11 +282,13 @@ protected: CPU_AVX512DQ = (1 << 27), CPU_AVX512PF = (1 << 28), CPU_AVX512ER = (1 << 29), - CPU_AVX512CD = (1 << 30), - CPU_AVX512BW = (1 << 31) + CPU_AVX512CD = (1 << 30) + // Keeping sign bit 31 unassigned. }; -#define CPU_AVX512VL UCONST64(0x100000000) // EVEX instructions with smaller vector length : enums are limited to 32bit +#define CPU_AVX512BW ((uint64_t)UCONST64(0x100000000)) // enums are limited to 31 bit +#define CPU_AVX512VL ((uint64_t)UCONST64(0x200000000)) // EVEX instructions with smaller vector length +#define CPU_SHA ((uint64_t)UCONST64(0x400000000)) // SHA instructions enum Extended_Family { // AMD @@ -516,6 +518,8 @@ protected: result |= CPU_ADX; if(_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0) result |= CPU_BMI2; + if (_cpuid_info.sef_cpuid7_ebx.bits.sha != 0) + result |= CPU_SHA; if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0) result |= CPU_LZCNT; // for Intel, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw @@ -721,6 +725,7 @@ public: static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); } static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } + static bool supports_sha() { return (_features & CPU_SHA) != 0; } // Intel features static bool is_intel_family_core() { return is_intel() && extended_cpu_family() == CPU_FAMILY_INTEL_CORE; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java index 972aea94231..3fb9046711b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java @@ -203,7 +203,8 @@ public class AMD64 extends Architecture { AVX512ER, AVX512CD, AVX512BW, - AVX512VL + AVX512VL, + SHA } private final EnumSet features; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index 69a31604560..b2fec728519 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -122,6 +122,9 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto if ((config.vmVersionFeatures & config.amd64AVX512VL) != 0) { features.add(AMD64.CPUFeature.AVX512VL); } + if ((config.vmVersionFeatures & config.amd64SHA) != 0) { + features.add(AMD64.CPUFeature.SHA); + } return features; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 88da9e5b32a..744ec27c044 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -945,6 +945,7 @@ public class HotSpotVMConfig { @HotSpotVMConstant(name = "VM_Version::CPU_AVX512CD", archs = {"amd64"}) @Stable public long amd64AVX512CD; @HotSpotVMConstant(name = "VM_Version::CPU_AVX512BW", archs = {"amd64"}) @Stable public long amd64AVX512BW; @HotSpotVMConstant(name = "VM_Version::CPU_AVX512VL", archs = {"amd64"}) @Stable public long amd64AVX512VL; + @HotSpotVMConstant(name = "VM_Version::CPU_SHA", archs = {"amd64"}) @Stable public long amd64SHA; // SPARC specific values @HotSpotVMConstant(name = "VM_Version::vis3_instructions_m", archs = {"sparc"}) @Stable public int sparcVis3Instructions; diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp index 99a7fbd3ac9..9c754133a40 100644 --- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp +++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp @@ -639,11 +639,12 @@ declare_constant(VM_Version::CPU_AVX512DQ) \ declare_constant(VM_Version::CPU_AVX512PF) \ declare_constant(VM_Version::CPU_AVX512ER) \ - declare_constant(VM_Version::CPU_AVX512CD) \ - declare_constant(VM_Version::CPU_AVX512BW) + declare_constant(VM_Version::CPU_AVX512CD) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ - declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) + declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \ + declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \ + declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) #endif // TARGET_ARCH_x86 diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 113a9f71ab6..d1a72e7027a 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -725,7 +725,7 @@ public: \ product(bool, UseSHA, false, \ "Control whether SHA instructions can be used " \ - "on SPARC and on ARM") \ + "on SPARC, on ARM and on x86") \ \ product(bool, UseGHASHIntrinsics, false, \ "Use intrinsics for GHASH versions of crypto") \ From d30d68717818485dad96159ebd2c313e3071839f Mon Sep 17 00:00:00 2001 From: Zoltan Majo Date: Fri, 4 Mar 2016 08:53:59 +0100 Subject: [PATCH 057/311] 8150839: Adjust the number of compiler threads for 32-bit platforms Set the number of compiler threads to 3 on 32-bit platforms. Reviewed-by: iveresov --- .../share/vm/runtime/advancedThresholdPolicy.cpp | 15 ++++++++++++++- hotspot/src/share/vm/runtime/arguments.cpp | 2 ++ .../share/vm/runtime/simpleThresholdPolicy.cpp | 6 ++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp index 1d046e6abe0..4ecfa0e913c 100644 --- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp @@ -42,17 +42,30 @@ void AdvancedThresholdPolicy::print_specific(EventType type, methodHandle mh, me } void AdvancedThresholdPolicy::initialize() { + int count = CICompilerCount; +#ifdef _LP64 // Turn on ergonomic compiler count selection if (FLAG_IS_DEFAULT(CICompilerCountPerCPU) && FLAG_IS_DEFAULT(CICompilerCount)) { FLAG_SET_DEFAULT(CICompilerCountPerCPU, true); } - int count = CICompilerCount; if (CICompilerCountPerCPU) { // Simple log n seems to grow too slowly for tiered, try something faster: log n * log log n int log_cpu = log2_intptr(os::active_processor_count()); int loglog_cpu = log2_intptr(MAX2(log_cpu, 1)); count = MAX2(log_cpu * loglog_cpu, 1) * 3 / 2; } +#else + // On 32-bit systems, the number of compiler threads is limited to 3. + // On these systems, the virtual address space available to the JVM + // is usually limited to 2-4 GB (the exact value depends on the platform). + // As the compilers (especially C2) can consume a large amount of + // memory, scaling the number of compiler threads with the number of + // available cores can result in the exhaustion of the address space + /// available to the VM and thus cause the VM to crash. + if (FLAG_IS_DEFAULT(CICompilerCount)) { + count = 3; + } +#endif set_c1_count(MAX2(count / 3, 1)); set_c2_count(MAX2(count - c1_count(), 1)); diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 006e3c94739..88fe092af1c 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2472,9 +2472,11 @@ bool Arguments::check_vm_args_consistency() { status = false; } +#ifdef _LP64 if (!FLAG_IS_DEFAULT(CICompilerCount) && !FLAG_IS_DEFAULT(CICompilerCountPerCPU) && CICompilerCountPerCPU) { warning("The VM option CICompilerCountPerCPU overrides CICompilerCount."); } +#endif #ifndef SUPPORT_RESERVED_STACK_AREA if (StackReservedPages != 0) { diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp index 187d3b1e208..3f8b76c9327 100644 --- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp @@ -138,9 +138,15 @@ void SimpleThresholdPolicy::initialize() { FLAG_SET_DEFAULT(CICompilerCount, 3); } int count = CICompilerCount; +#ifdef _LP64 + // On 64-bit systems, scale the number of compiler threads with + // the number of cores available on the system. Scaling is not + // performed on 32-bit systems because it can lead to exhaustion + // of the virtual memory address space available to the JVM. if (CICompilerCountPerCPU) { count = MAX2(log2_intptr(os::active_processor_count()), 1) * 3 / 2; } +#endif set_c1_count(MAX2(count / 3, 1)); set_c2_count(MAX2(count - c1_count(), 1)); FLAG_SET_ERGO(intx, CICompilerCount, c1_count() + c2_count()); From 29b4b2182cb6944beda92b121f5006bb718230df Mon Sep 17 00:00:00 2001 From: Rahul Raghavan Date: Fri, 4 Mar 2016 01:18:08 -0800 Subject: [PATCH 058/311] 8140721: ProfilerNumberOf*Methods flags should be diagnostic Converted four ProfilerNumberOf*Methods flags from develop to diagnostic. Reviewed-by: twisti --- hotspot/src/share/vm/runtime/globals.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index ce36ff1db49..ffff2be7ff0 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3092,16 +3092,16 @@ public: develop(intx, MethodHistogramCutoff, 100, \ "The cutoff value for method invocation histogram (+CountCalls)") \ \ - develop(intx, ProfilerNumberOfInterpretedMethods, 25, \ + diagnostic(intx, ProfilerNumberOfInterpretedMethods, 25, \ "Number of interpreted methods to show in profile") \ \ - develop(intx, ProfilerNumberOfCompiledMethods, 25, \ + diagnostic(intx, ProfilerNumberOfCompiledMethods, 25, \ "Number of compiled methods to show in profile") \ \ - develop(intx, ProfilerNumberOfStubMethods, 25, \ + diagnostic(intx, ProfilerNumberOfStubMethods, 25, \ "Number of stub methods to show in profile") \ \ - develop(intx, ProfilerNumberOfRuntimeStubNodes, 25, \ + diagnostic(intx, ProfilerNumberOfRuntimeStubNodes, 25, \ "Number of runtime stub nodes to show in profile") \ \ product(intx, ProfileIntervalsTicks, 100, \ From 1c2427a1827c7d21af03082041612d4f454be25b Mon Sep 17 00:00:00 2001 From: Gustavo Romero Date: Mon, 7 Mar 2016 10:03:06 -0300 Subject: [PATCH 059/311] 8150353: PPC64LE: Support RTM on linux Reviewed-by: mdoerr, kvn --- .../src/cpu/ppc/vm/globalDefinitions_ppc.hpp | 2 +- hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp | 11 ++++- hotspot/src/os/linux/vm/os_linux.cpp | 45 +++++++++++++++++++ hotspot/src/os/linux/vm/os_linux.hpp | 13 ++++++ hotspot/src/share/vm/opto/compile.hpp | 4 ++ 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp index ba981816f4a..f8fe437547d 100644 --- a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp @@ -47,7 +47,7 @@ const bool CCallingConventionRequiresIntsAsLongs = true; // The expected size in bytes of a cache line, used to pad data structures. #define DEFAULT_CACHE_LINE_SIZE 128 -#if defined(COMPILER2) && defined(AIX) +#if defined(COMPILER2) && (defined(AIX) || defined(linux)) // Include Transactional Memory lock eliding optimization #define INCLUDE_RTM_OPT 1 #endif diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp index 63c0e30a913..6743b2967f9 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp @@ -255,7 +255,16 @@ void VM_Version::initialize() { } #endif #ifdef linux - // TODO: check kernel version (we currently have too old versions only) + // At least Linux kernel 4.2, as the problematic behavior of syscalls + // being called in the middle of a transaction has been addressed. + // Please, refer to commit b4b56f9ecab40f3b4ef53e130c9f6663be491894 + // in Linux kernel source tree: https://goo.gl/Kc5i7A + if (os::Linux::os_version_is_known()) { + if (os::Linux::os_version() >= 0x040200) + os_too_old = false; + } else { + vm_exit_during_initialization("RTM can not be enabled: kernel version is unknown."); + } #endif if (os_too_old) { vm_exit_during_initialization("RTM is not supported on this OS version."); diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index d46a1146dd7..f3896ed96a0 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -144,6 +144,7 @@ pthread_t os::Linux::_main_thread; int os::Linux::_page_size = -1; const int os::Linux::_vm_default_page_size = (8 * K); bool os::Linux::_supports_fast_thread_cpu_time = false; +uint32_t os::Linux::_os_version = 0; const char * os::Linux::_glibc_version = NULL; const char * os::Linux::_libpthread_version = NULL; pthread_condattr_t os::Linux::_condattr[1]; @@ -4356,6 +4357,48 @@ jlong os::Linux::fast_thread_cpu_time(clockid_t clockid) { return (tp.tv_sec * NANOSECS_PER_SEC) + tp.tv_nsec; } +void os::Linux::initialize_os_info() { + assert(_os_version == 0, "OS info already initialized"); + + struct utsname _uname; + + uint32_t major; + uint32_t minor; + uint32_t fix; + + int rc; + + // Kernel version is unknown if + // verification below fails. + _os_version = 0x01000000; + + rc = uname(&_uname); + if (rc != -1) { + + rc = sscanf(_uname.release,"%d.%d.%d", &major, &minor, &fix); + if (rc == 3) { + + if (major < 256 && minor < 256 && fix < 256) { + // Kernel version format is as expected, + // set it overriding unknown state. + _os_version = (major << 16) | + (minor << 8 ) | + (fix << 0 ) ; + } + } + } +} + +uint32_t os::Linux::os_version() { + assert(_os_version != 0, "not initialized"); + return _os_version & 0x00FFFFFF; +} + +bool os::Linux::os_version_is_known() { + assert(_os_version != 0, "not initialized"); + return _os_version & 0x01000000 ? false : true; +} + ///// // glibc on Linux platform uses non-documented flag // to indicate, that some special sort of signal @@ -4578,6 +4621,8 @@ void os::init(void) { Linux::initialize_system_info(); + Linux::initialize_os_info(); + // main_thread points to the aboriginal thread Linux::_main_thread = pthread_self(); diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp index 1dcaafefd11..68e1968d2a1 100644 --- a/hotspot/src/os/linux/vm/os_linux.hpp +++ b/hotspot/src/os/linux/vm/os_linux.hpp @@ -56,6 +56,15 @@ class Linux { static GrowableArray* _cpu_to_node; + // 0x00000000 = uninitialized, + // 0x01000000 = kernel version unknown, + // otherwise a 32-bit number: + // Ox00AABBCC + // AA, Major Version + // BB, Minor Version + // CC, Fix Version + static uint32_t _os_version; + protected: static julong _physical_memory; @@ -198,6 +207,10 @@ class Linux { static jlong fast_thread_cpu_time(clockid_t clockid); + static void initialize_os_info(); + static bool os_version_is_known(); + static uint32_t os_version(); + // pthread_cond clock suppport private: static pthread_condattr_t _condattr[1]; diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 40724fbd6b7..343574e68f3 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -1118,7 +1118,11 @@ class Compile : public Phase { bool in_scratch_emit_size() const { return _in_scratch_emit_size; } enum ScratchBufferBlob { +#if defined(PPC64) + MAX_inst_size = 2048, +#else MAX_inst_size = 1024, +#endif MAX_locs_size = 128, // number of relocInfo elements MAX_const_size = 128, MAX_stubs_size = 128 From d4b4dca194fbe01fec2c8576ea93f8129e0e4023 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Mon, 7 Mar 2016 15:03:48 -0800 Subject: [PATCH 060/311] 8151002: Make Assembler methods vextract and vinsert match actual instructions Reviewed-by: kvn, vlivanov, mcberg --- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 130 ++++++++----- hotspot/src/cpu/x86/vm/assembler_x86.hpp | 50 +++-- hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 20 +- hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 131 ++++++++++++- .../src/cpu/x86/vm/sharedRuntime_x86_32.cpp | 8 +- .../src/cpu/x86/vm/sharedRuntime_x86_64.cpp | 8 +- .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 4 +- hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 4 +- hotspot/src/cpu/x86/vm/x86.ad | 184 +++++++++--------- 9 files changed, 342 insertions(+), 197 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 65f2da7ecd0..ffdd9fe2338 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -5699,8 +5699,9 @@ void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_ } -void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { +void Assembler::vinsertf128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; @@ -5709,11 +5710,12 @@ void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 128 bits // 0x01 - insert into upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) { +void Assembler::vinsertf64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); @@ -5721,26 +5723,29 @@ void Assembler::vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 256 bits // 0x01 - insert into upper 256 bits - emit_int8(value & 0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinsertf64x4h(XMMRegister dst, Address src, int value) { +void Assembler::vinsertf64x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); assert(dst != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionMark im(this); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + int nds_enc = nds->is_valid() ? nds->encoding() : 0; attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_64bit); // swap src<->dst for encoding - vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x1A); emit_operand(dst, src); // 0x00 - insert into lower 256 bits - // 0x01 - insert into upper 128 bits - emit_int8(value & 0x01); + // 0x01 - insert into upper 256 bits + emit_int8(imm8 & 0x01); } -void Assembler::vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) { +void Assembler::vinsertf32x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x03, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); @@ -5750,57 +5755,64 @@ void Assembler::vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, // 0x01 - insert into q1 128 bits (128..255) // 0x02 - insert into q2 128 bits (256..383) // 0x03 - insert into q3 128 bits (384..511) - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vinsertf32x4h(XMMRegister dst, Address src, int value) { +void Assembler::vinsertf32x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); assert(dst != xnoreg, "sanity"); + assert(imm8 <= 0x03, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; + int nds_enc = nds->is_valid() ? nds->encoding() : 0; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); // swap src<->dst for encoding - vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x18); emit_operand(dst, src); // 0x00 - insert into q0 128 bits (0..127) // 0x01 - insert into q1 128 bits (128..255) // 0x02 - insert into q2 128 bits (256..383) // 0x03 - insert into q3 128 bits (384..511) - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vinsertf128h(XMMRegister dst, Address src) { +void Assembler::vinsertf128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); assert(dst != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; + int nds_enc = nds->is_valid() ? nds->encoding() : 0; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); // swap src<->dst for encoding - vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x18); emit_operand(dst, src); + // 0x00 - insert into lower 128 bits // 0x01 - insert into upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextractf128h(XMMRegister dst, XMMRegister src) { +void Assembler::vextractf128(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x19); emit_int8((unsigned char)(0xC0 | encode)); - // 0x00 - insert into lower 128 bits - // 0x01 - insert into upper 128 bits - emit_int8(0x01); + // 0x00 - extract from lower 128 bits + // 0x01 - extract from upper 128 bits + emit_int8(imm8 & 0x01); } -void Assembler::vextractf128h(Address dst, XMMRegister src) { +void Assembler::vextractf128(Address dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); assert(src != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); @@ -5808,12 +5820,14 @@ void Assembler::vextractf128h(Address dst, XMMRegister src) { vex_prefix(dst, 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x19); emit_operand(src, dst); + // 0x00 - extract from lower 128 bits // 0x01 - extract from upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { +void Assembler::vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx2(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; @@ -5822,11 +5836,12 @@ void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 128 bits // 0x01 - insert into upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) { +void Assembler::vinserti64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); @@ -5834,39 +5849,44 @@ void Assembler::vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 256 bits // 0x01 - insert into upper 256 bits - emit_int8(value & 0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinserti128h(XMMRegister dst, Address src) { +void Assembler::vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { assert(VM_Version::supports_avx2(), ""); assert(dst != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; + int nds_enc = nds->is_valid() ? nds->encoding() : 0; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); // swap src<->dst for encoding - vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x38); emit_operand(dst, src); + // 0x00 - insert into lower 128 bits // 0x01 - insert into upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextracti128h(XMMRegister dst, XMMRegister src) { +void Assembler::vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x39); emit_int8((unsigned char)(0xC0 | encode)); - // 0x00 - insert into lower 128 bits - // 0x01 - insert into upper 128 bits - emit_int8(0x01); + // 0x00 - extract from lower 128 bits + // 0x01 - extract from upper 128 bits + emit_int8(imm8 & 0x01); } -void Assembler::vextracti128h(Address dst, XMMRegister src) { +void Assembler::vextracti128(Address dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx2(), ""); assert(src != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); @@ -5874,47 +5894,53 @@ void Assembler::vextracti128h(Address dst, XMMRegister src) { vex_prefix(dst, 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x39); emit_operand(src, dst); + // 0x00 - extract from lower 128 bits // 0x01 - extract from upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextracti64x4h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextracti64x4(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x3B); emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - extract from lower 256 bits // 0x01 - extract from upper 256 bits - emit_int8(value & 0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextracti64x2h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextracti64x2(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x03, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ !_legacy_mode_dq, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x39); emit_int8((unsigned char)(0xC0 | encode)); + // 0x00 - extract from bits 127:0 // 0x01 - extract from bits 255:128 // 0x02 - extract from bits 383:256 // 0x03 - extract from bits 511:384 - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vextractf64x4h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextractf64x4(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x1B); emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - extract from lower 256 bits // 0x01 - extract from upper 256 bits - emit_int8(value & 0x1); + emit_int8(imm8 & 0x01); } -void Assembler::vextractf64x4h(Address dst, XMMRegister src, int value) { +void Assembler::vextractf64x4(Address dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); assert(src != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionMark im(this); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4,/* input_size_in_bits */ EVEX_64bit); @@ -5923,11 +5949,12 @@ void Assembler::vextractf64x4h(Address dst, XMMRegister src, int value) { emit_operand(src, dst); // 0x00 - extract from lower 256 bits // 0x01 - extract from upper 256 bits - emit_int8(value & 0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextractf32x4h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextractf32x4(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); + assert(imm8 <= 0x03, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); @@ -5937,12 +5964,13 @@ void Assembler::vextractf32x4h(XMMRegister dst, XMMRegister src, int value) { // 0x01 - extract from bits 255:128 // 0x02 - extract from bits 383:256 // 0x03 - extract from bits 511:384 - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vextractf32x4h(Address dst, XMMRegister src, int value) { +void Assembler::vextractf32x4(Address dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); assert(src != xnoreg, "sanity"); + assert(imm8 <= 0x03, "imm8: %u", imm8); InstructionMark im(this); InstructionAttr attributes(AVX_512bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); @@ -5953,19 +5981,21 @@ void Assembler::vextractf32x4h(Address dst, XMMRegister src, int value) { // 0x01 - extract from bits 255:128 // 0x02 - extract from bits 383:256 // 0x03 - extract from bits 511:384 - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vextractf64x2h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextractf64x2(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x03, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ !_legacy_mode_dq, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x19); emit_int8((unsigned char)(0xC0 | encode)); + // 0x00 - extract from bits 127:0 // 0x01 - extract from bits 255:128 // 0x02 - extract from bits 383:256 // 0x03 - extract from bits 511:384 - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } // duplicate 4-bytes integer data from src into 8 locations in dest diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index 3026afda174..561278599b7 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -1971,33 +1971,31 @@ private: void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_len); - // Copy low 128bit into high 128bit of YMM registers. - void vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vextractf128h(XMMRegister dst, XMMRegister src); - void vextracti128h(XMMRegister dst, XMMRegister src); + // 128bit copy from/to 256bit (YMM) vector registers + void vinsertf128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vextractf128(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vinsertf128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8); + void vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8); + void vextractf128(Address dst, XMMRegister src, uint8_t imm8); + void vextracti128(Address dst, XMMRegister src, uint8_t imm8); - // Load/store high 128bit of YMM registers which does not destroy other half. - void vinsertf128h(XMMRegister dst, Address src); - void vinserti128h(XMMRegister dst, Address src); - void vextractf128h(Address dst, XMMRegister src); - void vextracti128h(Address dst, XMMRegister src); + // 256bit copy from/to 512bit (ZMM) vector registers + void vinserti64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vinsertf64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vextracti64x4(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf64x4(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf64x4(Address dst, XMMRegister src, uint8_t imm8); + void vinsertf64x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8); - // Copy low 256bit into high 256bit of ZMM registers. - void vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value); - void vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value); - void vextracti64x4h(XMMRegister dst, XMMRegister src, int value); - void vextractf64x4h(XMMRegister dst, XMMRegister src, int value); - void vextractf64x4h(Address dst, XMMRegister src, int value); - void vinsertf64x4h(XMMRegister dst, Address src, int value); - - // Copy targeted 128bit segments of the ZMM registers - void vextracti64x2h(XMMRegister dst, XMMRegister src, int value); - void vextractf64x2h(XMMRegister dst, XMMRegister src, int value); - void vextractf32x4h(XMMRegister dst, XMMRegister src, int value); - void vextractf32x4h(Address dst, XMMRegister src, int value); - void vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value); - void vinsertf32x4h(XMMRegister dst, Address src, int value); + // 128bit copy from/to 256bit (YMM) or 512bit (ZMM) vector registers + void vextracti64x2(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf64x2(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf32x4(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf32x4(Address dst, XMMRegister src, uint8_t imm8); + void vinsertf32x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vinsertf32x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8); // duplicate 4-bytes integer data from src into 8 locations in dest void vpbroadcastd(XMMRegister dst, XMMRegister src); diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index 4bca248d815..8eb6764770f 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -3445,7 +3445,7 @@ void MacroAssembler::movptr(Address dst, Register src) { void MacroAssembler::movdqu(Address dst, XMMRegister src) { if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (src->encoding() > 15)) { - Assembler::vextractf32x4h(dst, src, 0); + Assembler::vextractf32x4(dst, src, 0); } else { Assembler::movdqu(dst, src); } @@ -3453,7 +3453,7 @@ void MacroAssembler::movdqu(Address dst, XMMRegister src) { void MacroAssembler::movdqu(XMMRegister dst, Address src) { if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (dst->encoding() > 15)) { - Assembler::vinsertf32x4h(dst, src, 0); + Assembler::vinsertf32x4(dst, dst, src, 0); } else { Assembler::movdqu(dst, src); } @@ -3478,7 +3478,7 @@ void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src) { void MacroAssembler::vmovdqu(Address dst, XMMRegister src) { if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (src->encoding() > 15)) { - Assembler::vextractf64x4h(dst, src, 0); + vextractf64x4_low(dst, src); } else { Assembler::vmovdqu(dst, src); } @@ -3486,7 +3486,7 @@ void MacroAssembler::vmovdqu(Address dst, XMMRegister src) { void MacroAssembler::vmovdqu(XMMRegister dst, Address src) { if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (dst->encoding() > 15)) { - Assembler::vinsertf64x4h(dst, src, 0); + vinsertf64x4_low(dst, src); } else { Assembler::vmovdqu(dst, src); } @@ -5649,14 +5649,14 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int // Save upper half of ZMM registers subptr(rsp, 32*num_xmm_regs); for (int n = 0; n < num_xmm_regs; n++) { - vextractf64x4h(Address(rsp, n*32), as_XMMRegister(n), 1); + vextractf64x4_high(Address(rsp, n*32), as_XMMRegister(n)); } } assert(UseAVX > 0, "256 bit vectors are supported only with AVX"); // Save upper half of YMM registers subptr(rsp, 16*num_xmm_regs); for (int n = 0; n < num_xmm_regs; n++) { - vextractf128h(Address(rsp, n*16), as_XMMRegister(n)); + vextractf128_high(Address(rsp, n*16), as_XMMRegister(n)); } } #endif @@ -5665,7 +5665,7 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int #ifdef _LP64 if (VM_Version::supports_evex()) { for (int n = 0; n < num_xmm_regs; n++) { - vextractf32x4h(Address(rsp, n*16), as_XMMRegister(n), 0); + vextractf32x4(Address(rsp, n*16), as_XMMRegister(n), 0); } } else { for (int n = 0; n < num_xmm_regs; n++) { @@ -5753,7 +5753,7 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int #ifdef _LP64 if (VM_Version::supports_evex()) { for (int n = 0; n < num_xmm_regs; n++) { - vinsertf32x4h(as_XMMRegister(n), Address(rsp, n*16), 0); + vinsertf32x4(as_XMMRegister(n), as_XMMRegister(n), Address(rsp, n*16), 0); } } else { for (int n = 0; n < num_xmm_regs; n++) { @@ -5771,12 +5771,12 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int if (MaxVectorSize > 16) { // Restore upper half of YMM registers. for (int n = 0; n < num_xmm_regs; n++) { - vinsertf128h(as_XMMRegister(n), Address(rsp, n*16)); + vinsertf128_high(as_XMMRegister(n), Address(rsp, n*16)); } addptr(rsp, 16*num_xmm_regs); if(UseAVX > 2) { for (int n = 0; n < num_xmm_regs; n++) { - vinsertf64x4h(as_XMMRegister(n), Address(rsp, n*32), 1); + vinsertf64x4_high(as_XMMRegister(n), Address(rsp, n*32)); } addptr(rsp, 32*num_xmm_regs); } diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index d33473606aa..e325bbcdb2d 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -1215,14 +1215,131 @@ public: void vpxor(XMMRegister dst, XMMRegister src) { Assembler::vpxor(dst, dst, src, true); } void vpxor(XMMRegister dst, Address src) { Assembler::vpxor(dst, dst, src, true); } - // Move packed integer values from low 128 bit to hign 128 bit in 256 bit vector. - void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { - if (UseAVX > 1) // vinserti128h is available only in AVX2 - Assembler::vinserti128h(dst, nds, src); - else - Assembler::vinsertf128h(dst, nds, src); + void vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { + if (UseAVX > 1) { // vinserti128 is available only in AVX2 + Assembler::vinserti128(dst, nds, src, imm8); + } else { + Assembler::vinsertf128(dst, nds, src, imm8); + } } + void vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { + if (UseAVX > 1) { // vinserti128 is available only in AVX2 + Assembler::vinserti128(dst, nds, src, imm8); + } else { + Assembler::vinsertf128(dst, nds, src, imm8); + } + } + + void vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8) { + if (UseAVX > 1) { // vextracti128 is available only in AVX2 + Assembler::vextracti128(dst, src, imm8); + } else { + Assembler::vextractf128(dst, src, imm8); + } + } + + void vextracti128(Address dst, XMMRegister src, uint8_t imm8) { + if (UseAVX > 1) { // vextracti128 is available only in AVX2 + Assembler::vextracti128(dst, src, imm8); + } else { + Assembler::vextractf128(dst, src, imm8); + } + } + + // 128bit copy to/from high 128 bits of 256bit (YMM) vector registers + void vinserti128_high(XMMRegister dst, XMMRegister src) { + vinserti128(dst, dst, src, 1); + } + void vinserti128_high(XMMRegister dst, Address src) { + vinserti128(dst, dst, src, 1); + } + void vextracti128_high(XMMRegister dst, XMMRegister src) { + vextracti128(dst, src, 1); + } + void vextracti128_high(Address dst, XMMRegister src) { + vextracti128(dst, src, 1); + } + void vinsertf128_high(XMMRegister dst, XMMRegister src) { + vinsertf128(dst, dst, src, 1); + } + void vinsertf128_high(XMMRegister dst, Address src) { + vinsertf128(dst, dst, src, 1); + } + void vextractf128_high(XMMRegister dst, XMMRegister src) { + vextractf128(dst, src, 1); + } + void vextractf128_high(Address dst, XMMRegister src) { + vextractf128(dst, src, 1); + } + + // 256bit copy to/from high 256 bits of 512bit (ZMM) vector registers + void vinserti64x4_high(XMMRegister dst, XMMRegister src) { + vinserti64x4(dst, dst, src, 1); + } + void vinsertf64x4_high(XMMRegister dst, XMMRegister src) { + vinsertf64x4(dst, dst, src, 1); + } + void vextracti64x4_high(XMMRegister dst, XMMRegister src) { + vextracti64x4(dst, src, 1); + } + void vextractf64x4_high(XMMRegister dst, XMMRegister src) { + vextractf64x4(dst, src, 1); + } + void vextractf64x4_high(Address dst, XMMRegister src) { + vextractf64x4(dst, src, 1); + } + void vinsertf64x4_high(XMMRegister dst, Address src) { + vinsertf64x4(dst, dst, src, 1); + } + + // 128bit copy to/from low 128 bits of 256bit (YMM) vector registers + void vinserti128_low(XMMRegister dst, XMMRegister src) { + vinserti128(dst, dst, src, 0); + } + void vinserti128_low(XMMRegister dst, Address src) { + vinserti128(dst, dst, src, 0); + } + void vextracti128_low(XMMRegister dst, XMMRegister src) { + vextracti128(dst, src, 0); + } + void vextracti128_low(Address dst, XMMRegister src) { + vextracti128(dst, src, 0); + } + void vinsertf128_low(XMMRegister dst, XMMRegister src) { + vinsertf128(dst, dst, src, 0); + } + void vinsertf128_low(XMMRegister dst, Address src) { + vinsertf128(dst, dst, src, 0); + } + void vextractf128_low(XMMRegister dst, XMMRegister src) { + vextractf128(dst, src, 0); + } + void vextractf128_low(Address dst, XMMRegister src) { + vextractf128(dst, src, 0); + } + + // 256bit copy to/from low 256 bits of 512bit (ZMM) vector registers + void vinserti64x4_low(XMMRegister dst, XMMRegister src) { + vinserti64x4(dst, dst, src, 0); + } + void vinsertf64x4_low(XMMRegister dst, XMMRegister src) { + vinsertf64x4(dst, dst, src, 0); + } + void vextracti64x4_low(XMMRegister dst, XMMRegister src) { + vextracti64x4(dst, src, 0); + } + void vextractf64x4_low(XMMRegister dst, XMMRegister src) { + vextractf64x4(dst, src, 0); + } + void vextractf64x4_low(Address dst, XMMRegister src) { + vextractf64x4(dst, src, 0); + } + void vinsertf64x4_low(XMMRegister dst, Address src) { + vinsertf64x4(dst, dst, src, 0); + } + + // Carry-Less Multiplication Quadword void vpclmulldq(XMMRegister dst, XMMRegister nds, XMMRegister src) { // 0x00 - multiply lower 64 bits [0:63] diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index af6797ef95a..b2bc4fce1aa 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -208,13 +208,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ __ subptr(rsp, ymm_bytes); // Save upper half of YMM registers for (int n = 0; n < num_xmm_regs; n++) { - __ vextractf128h(Address(rsp, n*16), as_XMMRegister(n)); + __ vextractf128_high(Address(rsp, n*16), as_XMMRegister(n)); } if (UseAVX > 2) { __ subptr(rsp, zmm_bytes); // Save upper half of ZMM registers for (int n = 0; n < num_xmm_regs; n++) { - __ vextractf64x4h(Address(rsp, n*32), as_XMMRegister(n), 1); + __ vextractf64x4_high(Address(rsp, n*32), as_XMMRegister(n)); } } } @@ -304,13 +304,13 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve if (UseAVX > 2) { // Restore upper half of ZMM registers. for (int n = 0; n < num_xmm_regs; n++) { - __ vinsertf64x4h(as_XMMRegister(n), Address(rsp, n*32), 1); + __ vinsertf64x4_high(as_XMMRegister(n), Address(rsp, n*32)); } __ addptr(rsp, zmm_bytes); } // Restore upper half of YMM registers. for (int n = 0; n < num_xmm_regs; n++) { - __ vinsertf128h(as_XMMRegister(n), Address(rsp, n*16)); + __ vinsertf128_high(as_XMMRegister(n), Address(rsp, n*16)); } __ addptr(rsp, ymm_bytes); } diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index 686530b7e09..75f248fb1a3 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -179,13 +179,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // Save upper half of YMM registers(0..15) int base_addr = XSAVE_AREA_YMM_BEGIN; for (int n = 0; n < 16; n++) { - __ vextractf128h(Address(rsp, base_addr+n*16), as_XMMRegister(n)); + __ vextractf128_high(Address(rsp, base_addr+n*16), as_XMMRegister(n)); } if (VM_Version::supports_evex()) { // Save upper half of ZMM registers(0..15) base_addr = XSAVE_AREA_ZMM_BEGIN; for (int n = 0; n < 16; n++) { - __ vextractf64x4h(Address(rsp, base_addr+n*32), as_XMMRegister(n), 1); + __ vextractf64x4_high(Address(rsp, base_addr+n*32), as_XMMRegister(n)); } // Save full ZMM registers(16..num_xmm_regs) base_addr = XSAVE_AREA_UPPERBANK; @@ -333,13 +333,13 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve // Restore upper half of YMM registers (0..15) int base_addr = XSAVE_AREA_YMM_BEGIN; for (int n = 0; n < 16; n++) { - __ vinsertf128h(as_XMMRegister(n), Address(rsp, base_addr+n*16)); + __ vinsertf128_high(as_XMMRegister(n), Address(rsp, base_addr+n*16)); } if (VM_Version::supports_evex()) { // Restore upper half of ZMM registers (0..15) base_addr = XSAVE_AREA_ZMM_BEGIN; for (int n = 0; n < 16; n++) { - __ vinsertf64x4h(as_XMMRegister(n), Address(rsp, base_addr+n*32), 1); + __ vinsertf64x4_high(as_XMMRegister(n), Address(rsp, base_addr+n*32)); } // Restore full ZMM registers(16..num_xmm_regs) base_addr = XSAVE_AREA_UPPERBANK; diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 2f4adc88506..d1df1eac653 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -275,7 +275,7 @@ class StubGenerator: public StubCodeGenerator { } if (VM_Version::supports_evex()) { for (int i = xmm_save_first; i <= last_reg; i++) { - __ vextractf32x4h(xmm_save(i), as_XMMRegister(i), 0); + __ vextractf32x4(xmm_save(i), as_XMMRegister(i), 0); } } else { for (int i = xmm_save_first; i <= last_reg; i++) { @@ -393,7 +393,7 @@ class StubGenerator: public StubCodeGenerator { // emit the restores for xmm regs if (VM_Version::supports_evex()) { for (int i = xmm_save_first; i <= last_reg; i++) { - __ vinsertf32x4h(as_XMMRegister(i), xmm_save(i), 0); + __ vinsertf32x4(as_XMMRegister(i), as_XMMRegister(i), xmm_save(i), 0); } } else { for (int i = xmm_save_first; i <= last_reg; i++) { diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 7472ad4def1..94c7e156d7e 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -385,7 +385,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movdl(xmm0, rcx); __ pshufd(xmm0, xmm0, 0x00); - __ vinsertf128h(xmm0, xmm0, xmm0); + __ vinsertf128_high(xmm0, xmm0); __ vmovdqu(xmm7, xmm0); #ifdef _LP64 __ vmovdqu(xmm8, xmm0); diff --git a/hotspot/src/cpu/x86/vm/x86.ad b/hotspot/src/cpu/x86/vm/x86.ad index a316b914a52..603e00beef4 100644 --- a/hotspot/src/cpu/x86/vm/x86.ad +++ b/hotspot/src/cpu/x86/vm/x86.ad @@ -3179,13 +3179,13 @@ instruct Repl32B(vecY dst, rRegI src) %{ "punpcklbw $dst,$dst\n\t" "pshuflw $dst,$dst,0x00\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate32B" %} + "vinserti128_high $dst,$dst\t! replicate32B" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3196,12 +3196,12 @@ instruct Repl32B_mem(vecY dst, memory mem) %{ format %{ "punpcklbw $dst,$mem\n\t" "pshuflw $dst,$dst,0x00\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate32B" %} + "vinserti128_high $dst,$dst\t! replicate32B" %} ins_encode %{ __ punpcklbw($dst$$XMMRegister, $mem$$Address); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3223,11 +3223,11 @@ instruct Repl32B_imm(vecY dst, immI con) %{ match(Set dst (ReplicateB con)); format %{ "movq $dst,[$constantaddress]\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! lreplicate32B($con)" %} + "vinserti128_high $dst,$dst\t! lreplicate32B($con)" %} ins_encode %{ __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 1))); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3298,12 +3298,12 @@ instruct Repl16S(vecY dst, rRegI src) %{ format %{ "movd $dst,$src\n\t" "pshuflw $dst,$dst,0x00\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate16S" %} + "vinserti128_high $dst,$dst\t! replicate16S" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3313,11 +3313,11 @@ instruct Repl16S_mem(vecY dst, memory mem) %{ match(Set dst (ReplicateS (LoadS mem))); format %{ "pshuflw $dst,$mem,0x00\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate16S" %} + "vinserti128_high $dst,$dst\t! replicate16S" %} ins_encode %{ __ pshuflw($dst$$XMMRegister, $mem$$Address, 0x00); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3327,11 +3327,11 @@ instruct Repl16S_imm(vecY dst, immI con) %{ match(Set dst (ReplicateS con)); format %{ "movq $dst,[$constantaddress]\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate16S($con)" %} + "vinserti128_high $dst,$dst\t! replicate16S($con)" %} ins_encode %{ __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 2))); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3363,11 +3363,11 @@ instruct Repl8I(vecY dst, rRegI src) %{ match(Set dst (ReplicateI src)); format %{ "movd $dst,$src\n\t" "pshufd $dst,$dst,0x00\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate8I" %} + "vinserti128_high $dst,$dst\t! replicate8I" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3376,10 +3376,10 @@ instruct Repl8I_mem(vecY dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI (LoadI mem))); format %{ "pshufd $dst,$mem,0x00\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate8I" %} + "vinserti128_high $dst,$dst\t! replicate8I" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3401,11 +3401,11 @@ instruct Repl8I_imm(vecY dst, immI con) %{ match(Set dst (ReplicateI con)); format %{ "movq $dst,[$constantaddress]\t! replicate8I($con)\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst" %} + "vinserti128_high $dst,$dst" %} ins_encode %{ __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4))); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3430,11 +3430,11 @@ instruct Repl4L(vecY dst, rRegL src) %{ match(Set dst (ReplicateL src)); format %{ "movdq $dst,$src\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate4L" %} + "vinserti128_high $dst,$dst\t! replicate4L" %} ins_encode %{ __ movdq($dst$$XMMRegister, $src$$Register); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3447,13 +3447,13 @@ instruct Repl4L(vecY dst, eRegL src, regD tmp) %{ "movdl $tmp,$src.hi\n\t" "punpckldq $dst,$tmp\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate4L" %} + "vinserti128_high $dst,$dst\t! replicate4L" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3464,11 +3464,11 @@ instruct Repl4L_imm(vecY dst, immL con) %{ match(Set dst (ReplicateL con)); format %{ "movq $dst,[$constantaddress]\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate4L($con)" %} + "vinserti128_high $dst,$dst\t! replicate4L($con)" %} ins_encode %{ __ movq($dst$$XMMRegister, $constantaddress($con)); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3478,11 +3478,11 @@ instruct Repl4L_mem(vecY dst, memory mem) %{ match(Set dst (ReplicateL (LoadL mem))); format %{ "movq $dst,$mem\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate4L" %} + "vinserti128_high $dst,$dst\t! replicate4L" %} ins_encode %{ __ movq($dst$$XMMRegister, $mem$$Address); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3511,10 +3511,10 @@ instruct Repl8F(vecY dst, regF src) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF src)); format %{ "pshufd $dst,$src,0x00\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate8F" %} + "vinsertf128_high $dst,$dst\t! replicate8F" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x00); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3523,10 +3523,10 @@ instruct Repl8F_mem(vecY dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF (LoadF mem))); format %{ "pshufd $dst,$mem,0x00\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate8F" %} + "vinsertf128_high $dst,$dst\t! replicate8F" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3576,10 +3576,10 @@ instruct Repl4D(vecY dst, regD src) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateD src)); format %{ "pshufd $dst,$src,0x44\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate4D" %} + "vinsertf128_high $dst,$dst\t! replicate4D" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x44); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3588,10 +3588,10 @@ instruct Repl4D_mem(vecY dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateD (LoadD mem))); format %{ "pshufd $dst,$mem,0x44\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate4D" %} + "vinsertf128_high $dst,$dst\t! replicate4D" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $mem$$Address, 0x44); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -4791,7 +4791,7 @@ instruct rvadd8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF effect(TEMP tmp, TEMP tmp2); format %{ "vphaddd $tmp,$src2,$src2\n\t" "vphaddd $tmp,$tmp,$tmp2\n\t" - "vextracti128 $tmp2,$tmp\n\t" + "vextracti128_high $tmp2,$tmp\n\t" "vpaddd $tmp,$tmp,$tmp2\n\t" "movd $tmp2,$src1\n\t" "vpaddd $tmp2,$tmp2,$tmp\n\t" @@ -4800,7 +4800,7 @@ instruct rvadd8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF int vector_len = 1; __ vphaddd($tmp$$XMMRegister, $src2$$XMMRegister, $src2$$XMMRegister, vector_len); __ vphaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, vector_len); - __ vextracti128h($tmp2$$XMMRegister, $tmp$$XMMRegister); + __ vextracti128_high($tmp2$$XMMRegister, $tmp$$XMMRegister); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, 0); __ movdl($tmp2$$XMMRegister, $src1$$Register); __ vpaddd($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -4813,7 +4813,7 @@ instruct rvadd8I_reduction_reg_evex(rRegI dst, rRegI src1, vecY src2, regF tmp, predicate(UseAVX > 2); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti128 $tmp,$src2\n\t" + format %{ "vextracti128_high $tmp,$src2\n\t" "vpaddd $tmp,$tmp,$src2\n\t" "pshufd $tmp2,$tmp,0xE\n\t" "vpaddd $tmp,$tmp,$tmp2\n\t" @@ -4824,7 +4824,7 @@ instruct rvadd8I_reduction_reg_evex(rRegI dst, rRegI src1, vecY src2, regF tmp, "movd $dst,$tmp2\t! add reduction8I" %} ins_encode %{ int vector_len = 0; - __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, vector_len); __ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, vector_len); @@ -4841,9 +4841,9 @@ instruct rvadd16I_reduction_reg_evex(rRegI dst, rRegI src1, vecZ src2, regF tmp, predicate(UseAVX > 2); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2, TEMP tmp3); - format %{ "vextracti64x4 $tmp3,$src2,0x1\n\t" + format %{ "vextracti64x4_high $tmp3,$src2\n\t" "vpaddd $tmp3,$tmp3,$src2\n\t" - "vextracti128 $tmp,$tmp3\n\t" + "vextracti128_high $tmp,$tmp3\n\t" "vpaddd $tmp,$tmp,$tmp3\n\t" "pshufd $tmp2,$tmp,0xE\n\t" "vpaddd $tmp,$tmp,$tmp2\n\t" @@ -4853,9 +4853,9 @@ instruct rvadd16I_reduction_reg_evex(rRegI dst, rRegI src1, vecZ src2, regF tmp, "vpaddd $tmp2,$tmp,$tmp2\n\t" "movd $dst,$tmp2\t! mul reduction16I" %} ins_encode %{ - __ vextracti64x4h($tmp3$$XMMRegister, $src2$$XMMRegister, 1); + __ vextracti64x4_high($tmp3$$XMMRegister, $src2$$XMMRegister); __ vpaddd($tmp3$$XMMRegister, $tmp3$$XMMRegister, $src2$$XMMRegister, 1); - __ vextracti128h($tmp$$XMMRegister, $tmp3$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $tmp3$$XMMRegister); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp3$$XMMRegister, 0); __ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, 0); @@ -4892,7 +4892,7 @@ instruct rvadd4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF predicate(UseAVX > 2); match(Set dst (AddReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti128 $tmp,$src2\n\t" + format %{ "vextracti128_high $tmp,$src2\n\t" "vpaddq $tmp2,$tmp,$src2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vpaddq $tmp2,$tmp2,$tmp\n\t" @@ -4900,7 +4900,7 @@ instruct rvadd4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF "vpaddq $tmp2,$tmp2,$tmp\n\t" "movdq $dst,$tmp2\t! add reduction4L" %} ins_encode %{ - __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister); __ vpaddq($tmp2$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, 0); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -4915,9 +4915,9 @@ instruct rvadd8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF predicate(UseAVX > 2); match(Set dst (AddReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti64x4 $tmp2,$src2,0x1\n\t" + format %{ "vextracti64x4_high $tmp2,$src2\n\t" "vpaddq $tmp2,$tmp2,$src2\n\t" - "vextracti128 $tmp,$tmp2\n\t" + "vextracti128_high $tmp,$tmp2\n\t" "vpaddq $tmp2,$tmp2,$tmp\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vpaddq $tmp2,$tmp2,$tmp\n\t" @@ -4925,9 +4925,9 @@ instruct rvadd8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF "vpaddq $tmp2,$tmp2,$tmp\n\t" "movdq $dst,$tmp2\t! add reduction8L" %} ins_encode %{ - __ vextracti64x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 1); + __ vextracti64x4_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $src2$$XMMRegister, 1); - __ vextracti128h($tmp$$XMMRegister, $tmp2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $tmp2$$XMMRegister); __ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -5026,7 +5026,7 @@ instruct radd8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{ "vaddss $dst,$dst,$tmp\n\t" "pshufd $tmp,$src2,0x03\n\t" "vaddss $dst,$dst,$tmp\n\t" - "vextractf128 $tmp2,$src2\n\t" + "vextractf128_high $tmp2,$src2\n\t" "vaddss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vaddss $dst,$dst,$tmp\n\t" @@ -5042,7 +5042,7 @@ instruct radd8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{ __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf128h($tmp2$$XMMRegister, $src2$$XMMRegister); + __ vextractf128_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5065,7 +5065,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vaddss $dst,$dst,$tmp\n\t" "pshufd $tmp,$src2,0x03\n\t" "vaddss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vaddss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vaddss $dst,$dst,$tmp\n\t" @@ -5073,7 +5073,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vaddss $dst,$dst,$tmp\n\t" "pshufd $tmp,$tmp2,0x03\n\t" "vaddss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x2\n\t" + "vextractf32x4 $tmp2,$src2,0x2\n\t" "vaddss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vaddss $dst,$dst,$tmp\n\t" @@ -5081,7 +5081,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vaddss $dst,$dst,$tmp\n\t" "pshufd $tmp,$tmp2,0x03\n\t" "vaddss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x3\n\t" + "vextractf32x4 $tmp2,$src2,0x3\n\t" "vaddss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vaddss $dst,$dst,$tmp\n\t" @@ -5097,7 +5097,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5105,7 +5105,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5113,7 +5113,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5162,7 +5162,7 @@ instruct rvadd4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{ format %{ "vaddsd $dst,$dst,$src2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vaddsd $dst,$dst,$tmp\n\t" - "vextractf32x4h $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vaddsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vaddsd $dst,$dst,$tmp\t! add reduction4D" %} @@ -5170,7 +5170,7 @@ instruct rvadd4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{ __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5185,15 +5185,15 @@ instruct rvadd8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{ format %{ "vaddsd $dst,$dst,$src2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vaddsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vaddsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vaddsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x2\n\t" + "vextractf32x4 $tmp2,$src2,0x2\n\t" "vaddsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vaddsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x3\n\t" + "vextractf32x4 $tmp2,$src2,0x3\n\t" "vaddsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vaddsd $dst,$dst,$tmp\t! add reduction8D" %} @@ -5201,15 +5201,15 @@ instruct rvadd8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{ __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5307,7 +5307,7 @@ instruct rvmul8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF predicate(UseAVX > 0); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti128 $tmp,$src2\n\t" + format %{ "vextracti128_high $tmp,$src2\n\t" "vpmulld $tmp,$tmp,$src2\n\t" "pshufd $tmp2,$tmp,0xE\n\t" "vpmulld $tmp,$tmp,$tmp2\n\t" @@ -5318,7 +5318,7 @@ instruct rvmul8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF "movd $dst,$tmp2\t! mul reduction8I" %} ins_encode %{ int vector_len = 0; - __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister); __ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, vector_len); __ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE); __ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, vector_len); @@ -5335,9 +5335,9 @@ instruct rvmul16I_reduction_reg(rRegI dst, rRegI src1, vecZ src2, regF tmp, regF predicate(UseAVX > 2); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2, TEMP tmp3); - format %{ "vextracti64x4 $tmp3,$src2,0x1\n\t" + format %{ "vextracti64x4_high $tmp3,$src2\n\t" "vpmulld $tmp3,$tmp3,$src2\n\t" - "vextracti128 $tmp,$tmp3\n\t" + "vextracti128_high $tmp,$tmp3\n\t" "vpmulld $tmp,$tmp,$src2\n\t" "pshufd $tmp2,$tmp,0xE\n\t" "vpmulld $tmp,$tmp,$tmp2\n\t" @@ -5347,9 +5347,9 @@ instruct rvmul16I_reduction_reg(rRegI dst, rRegI src1, vecZ src2, regF tmp, regF "vpmulld $tmp2,$tmp,$tmp2\n\t" "movd $dst,$tmp2\t! mul reduction16I" %} ins_encode %{ - __ vextracti64x4h($tmp3$$XMMRegister, $src2$$XMMRegister, 1); + __ vextracti64x4_high($tmp3$$XMMRegister, $src2$$XMMRegister); __ vpmulld($tmp3$$XMMRegister, $tmp3$$XMMRegister, $src2$$XMMRegister, 1); - __ vextracti128h($tmp$$XMMRegister, $tmp3$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $tmp3$$XMMRegister); __ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp3$$XMMRegister, 0); __ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE); __ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, 0); @@ -5386,7 +5386,7 @@ instruct rvmul4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF predicate(UseAVX > 2 && VM_Version::supports_avx512dq()); match(Set dst (MulReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti128 $tmp,$src2\n\t" + format %{ "vextracti128_high $tmp,$src2\n\t" "vpmullq $tmp2,$tmp,$src2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vpmullq $tmp2,$tmp2,$tmp\n\t" @@ -5394,7 +5394,7 @@ instruct rvmul4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF "vpmullq $tmp2,$tmp2,$tmp\n\t" "movdq $dst,$tmp2\t! mul reduction4L" %} ins_encode %{ - __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister); __ vpmullq($tmp2$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, 0); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -5409,9 +5409,9 @@ instruct rvmul8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF predicate(UseAVX > 2 && VM_Version::supports_avx512dq()); match(Set dst (MulReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti64x4 $tmp2,$src2,0x1\n\t" + format %{ "vextracti64x4_high $tmp2,$src2\n\t" "vpmullq $tmp2,$tmp2,$src2\n\t" - "vextracti128 $tmp,$tmp2\n\t" + "vextracti128_high $tmp,$tmp2\n\t" "vpmullq $tmp2,$tmp2,$tmp\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vpmullq $tmp2,$tmp2,$tmp\n\t" @@ -5419,9 +5419,9 @@ instruct rvmul8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF "vpmullq $tmp2,$tmp2,$tmp\n\t" "movdq $dst,$tmp2\t! mul reduction8L" %} ins_encode %{ - __ vextracti64x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 1); + __ vextracti64x4_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $src2$$XMMRegister, 1); - __ vextracti128h($tmp$$XMMRegister, $tmp2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $tmp2$$XMMRegister); __ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -5520,7 +5520,7 @@ instruct rvmul8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{ "vmulss $dst,$dst,$tmp\n\t" "pshufd $tmp,$src2,0x03\n\t" "vmulss $dst,$dst,$tmp\n\t" - "vextractf128 $tmp2,$src2\n\t" + "vextractf128_high $tmp2,$src2\n\t" "vmulss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vmulss $dst,$dst,$tmp\n\t" @@ -5536,7 +5536,7 @@ instruct rvmul8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{ __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf128h($tmp2$$XMMRegister, $src2$$XMMRegister); + __ vextractf128_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5559,7 +5559,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vmulss $dst,$dst,$tmp\n\t" "pshufd $tmp,$src2,0x03\n\t" "vmulss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vmulss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vmulss $dst,$dst,$tmp\n\t" @@ -5567,7 +5567,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vmulss $dst,$dst,$tmp\n\t" "pshufd $tmp,$tmp2,0x03\n\t" "vmulss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x2\n\t" + "vextractf32x4 $tmp2,$src2,0x2\n\t" "vmulss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vmulss $dst,$dst,$tmp\n\t" @@ -5575,7 +5575,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vmulss $dst,$dst,$tmp\n\t" "pshufd $tmp,$tmp2,0x03\n\t" "vmulss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x3\n\t" + "vextractf32x4 $tmp2,$src2,0x3\n\t" "vmulss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vmulss $dst,$dst,$tmp\n\t" @@ -5591,7 +5591,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5599,7 +5599,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5607,7 +5607,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5656,7 +5656,7 @@ instruct rvmul4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{ format %{ "vmulsd $dst,$dst,$src2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vmulsd $dst,$dst,$tmp\n\t" - "vextractf128 $tmp2,$src2\n\t" + "vextractf128_high $tmp2,$src2\n\t" "vmulsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vmulsd $dst,$dst,$tmp\t! mul reduction4D" %} @@ -5664,7 +5664,7 @@ instruct rvmul4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{ __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf128h($tmp2$$XMMRegister, $src2$$XMMRegister); + __ vextractf128_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5679,15 +5679,15 @@ instruct rvmul8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{ format %{ "vmulsd $dst,$dst,$src2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vmulsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vmulsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vmulsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x2\n\t" + "vextractf32x4 $tmp2,$src2,0x2\n\t" "vmulsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vmulsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x3\n\t" + "vextractf32x4 $tmp2,$src2,0x3\n\t" "vmulsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vmulsd $dst,$dst,$tmp\t! mul reduction8D" %} @@ -5695,15 +5695,15 @@ instruct rvmul8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{ __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); From f4b4c5d7b0e312183ce7d69437868ee5520a6ee4 Mon Sep 17 00:00:00 2001 From: Ed Nevill Date: Tue, 8 Mar 2016 14:39:50 +0000 Subject: [PATCH 061/311] 8150394: aarch64: add support for 8.1 LSE CAS instructions Co-authored-by: Ananth Jasty Reviewed-by: aph --- hotspot/src/cpu/aarch64/vm/aarch64.ad | 27 +++-- .../src/cpu/aarch64/vm/assembler_aarch64.hpp | 66 +++++++++-- .../aarch64/vm/c1_LIRAssembler_aarch64.cpp | 70 ++++++----- .../src/cpu/aarch64/vm/globals_aarch64.hpp | 5 + .../cpu/aarch64/vm/macroAssembler_aarch64.cpp | 112 ++++++++++++------ .../cpu/aarch64/vm/macroAssembler_aarch64.hpp | 17 +-- .../src/cpu/aarch64/vm/register_aarch64.hpp | 3 + .../src/cpu/aarch64/vm/vm_version_aarch64.cpp | 14 +++ 8 files changed, 223 insertions(+), 91 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index 832c9e765ba..7689614b710 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -4132,14 +4132,14 @@ encode %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register, - &Assembler::ldxr, &MacroAssembler::cmp, &Assembler::stlxr); + Assembler::xword, /*acquire*/ false, /*release*/ true); %} enc_class aarch64_enc_cmpxchgw(memory mem, iRegINoSp oldval, iRegINoSp newval) %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register, - &Assembler::ldxrw, &MacroAssembler::cmpw, &Assembler::stlxrw); + Assembler::word, /*acquire*/ false, /*release*/ true); %} @@ -4151,14 +4151,14 @@ encode %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register, - &Assembler::ldaxr, &MacroAssembler::cmp, &Assembler::stlxr); + Assembler::xword, /*acquire*/ true, /*release*/ true); %} enc_class aarch64_enc_cmpxchgw_acq(memory mem, iRegINoSp oldval, iRegINoSp newval) %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register, - &Assembler::ldaxrw, &MacroAssembler::cmpw, &Assembler::stlxrw); + Assembler::word, /*acquire*/ true, /*release*/ true); %} @@ -4676,7 +4676,12 @@ encode %{ // Compare object markOop with mark and if equal exchange scratch1 // with object markOop. - { + if (UseLSE) { + __ mov(tmp, disp_hdr); + __ casal(Assembler::xword, tmp, box, oop); + __ cmp(tmp, disp_hdr); + __ br(Assembler::EQ, cont); + } else { Label retry_load; __ bind(retry_load); __ ldaxr(tmp, oop); @@ -4726,7 +4731,11 @@ encode %{ __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes()-markOopDesc::monitor_value)); __ mov(disp_hdr, zr); - { + if (UseLSE) { + __ mov(rscratch1, disp_hdr); + __ casal(Assembler::xword, rscratch1, rthread, tmp); + __ cmp(rscratch1, disp_hdr); + } else { Label retry_load, fail; __ bind(retry_load); __ ldaxr(rscratch1, tmp); @@ -4815,7 +4824,11 @@ encode %{ // see the stack address of the basicLock in the markOop of the // object. - { + if (UseLSE) { + __ mov(tmp, box); + __ casl(Assembler::xword, tmp, disp_hdr, oop); + __ cmp(tmp, box); + } else { Label retry_load; __ bind(retry_load); __ ldxr(tmp, oop); diff --git a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp index ca617716562..85e0f2e4eca 100644 --- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp @@ -972,7 +972,7 @@ public: // System void system(int op0, int op1, int CRn, int CRm, int op2, - Register rt = (Register)0b11111) + Register rt = dummy_reg) { starti; f(0b11010101000, 31, 21); @@ -1082,7 +1082,7 @@ public: #define INSN(NAME, opc) \ void NAME() { \ - branch_reg((Register)0b11111, opc); \ + branch_reg(dummy_reg, opc); \ } INSN(eret, 0b0100); @@ -1094,10 +1094,22 @@ public: enum operand_size { byte, halfword, word, xword }; void load_store_exclusive(Register Rs, Register Rt1, Register Rt2, - Register Rn, enum operand_size sz, int op, int o0) { + Register Rn, enum operand_size sz, int op, bool ordered) { starti; f(sz, 31, 30), f(0b001000, 29, 24), f(op, 23, 21); - rf(Rs, 16), f(o0, 15), rf(Rt2, 10), rf(Rn, 5), rf(Rt1, 0); + rf(Rs, 16), f(ordered, 15), rf(Rt2, 10), rf(Rn, 5), rf(Rt1, 0); + } + + void load_exclusive(Register dst, Register addr, + enum operand_size sz, bool ordered) { + load_store_exclusive(dummy_reg, dst, dummy_reg, addr, + sz, 0b010, ordered); + } + + void store_exclusive(Register status, Register new_val, Register addr, + enum operand_size sz, bool ordered) { + load_store_exclusive(status, new_val, dummy_reg, addr, + sz, 0b000, ordered); } #define INSN4(NAME, sz, op, o0) /* Four registers */ \ @@ -1109,19 +1121,19 @@ public: #define INSN3(NAME, sz, op, o0) /* Three registers */ \ void NAME(Register Rs, Register Rt, Register Rn) { \ guarantee(Rs != Rn && Rs != Rt, "unpredictable instruction"); \ - load_store_exclusive(Rs, Rt, (Register)0b11111, Rn, sz, op, o0); \ + load_store_exclusive(Rs, Rt, dummy_reg, Rn, sz, op, o0); \ } #define INSN2(NAME, sz, op, o0) /* Two registers */ \ void NAME(Register Rt, Register Rn) { \ - load_store_exclusive((Register)0b11111, Rt, (Register)0b11111, \ + load_store_exclusive(dummy_reg, Rt, dummy_reg, \ Rn, sz, op, o0); \ } #define INSN_FOO(NAME, sz, op, o0) /* Three registers, encoded differently */ \ void NAME(Register Rt1, Register Rt2, Register Rn) { \ guarantee(Rt1 != Rt2, "unpredictable instruction"); \ - load_store_exclusive((Register)0b11111, Rt1, Rt2, Rn, sz, op, o0); \ + load_store_exclusive(dummy_reg, Rt1, Rt2, Rn, sz, op, o0); \ } // bytes @@ -1169,6 +1181,46 @@ public: #undef INSN4 #undef INSN_FOO + // 8.1 Compare and swap extensions + void lse_cas(Register Rs, Register Rt, Register Rn, + enum operand_size sz, bool a, bool r, bool not_pair) { + starti; + if (! not_pair) { // Pair + assert(sz == word || sz == xword, "invalid size"); + /* The size bit is in bit 30, not 31 */ + sz = (operand_size)(sz == word ? 0b00:0b01); + } + f(sz, 31, 30), f(0b001000, 29, 24), f(1, 23), f(a, 22), f(1, 21); + rf(Rs, 16), f(r, 15), f(0b11111, 14, 10), rf(Rn, 5), rf(Rt, 0); + } + + // CAS +#define INSN(NAME, a, r) \ + void NAME(operand_size sz, Register Rs, Register Rt, Register Rn) { \ + assert(Rs != Rn && Rs != Rt, "unpredictable instruction"); \ + lse_cas(Rs, Rt, Rn, sz, a, r, true); \ + } + INSN(cas, false, false) + INSN(casa, true, false) + INSN(casl, false, true) + INSN(casal, true, true) +#undef INSN + + // CASP +#define INSN(NAME, a, r) \ + void NAME(operand_size sz, Register Rs, Register Rs1, \ + Register Rt, Register Rt1, Register Rn) { \ + assert((Rs->encoding() & 1) == 0 && (Rt->encoding() & 1) == 0 && \ + Rs->successor() == Rs1 && Rt->successor() == Rt1 && \ + Rs != Rn && Rs1 != Rn && Rs != Rt, "invalid registers"); \ + lse_cas(Rs, Rt, Rn, sz, a, r, false); \ + } + INSN(casp, false, false) + INSN(caspa, true, false) + INSN(caspl, false, true) + INSN(caspal, true, true) +#undef INSN + // Load register (literal) #define INSN(NAME, opc, V) \ void NAME(Register Rt, address dest) { \ diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp index e32a3c76b79..a42f0a127b0 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp @@ -1556,38 +1556,52 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { } void LIR_Assembler::casw(Register addr, Register newval, Register cmpval) { - Label retry_load, nope; - // flush and load exclusive from the memory location - // and fail if it is not what we expect - __ bind(retry_load); - __ ldaxrw(rscratch1, addr); - __ cmpw(rscratch1, cmpval); - __ cset(rscratch1, Assembler::NE); - __ br(Assembler::NE, nope); - // if we store+flush with no intervening write rscratch1 wil be zero - __ stlxrw(rscratch1, newval, addr); - // retry so we only ever return after a load fails to compare - // ensures we don't return a stale value after a failed write. - __ cbnzw(rscratch1, retry_load); - __ bind(nope); + if (UseLSE) { + __ mov(rscratch1, cmpval); + __ casal(Assembler::word, rscratch1, newval, addr); + __ cmpw(rscratch1, cmpval); + __ cset(rscratch1, Assembler::NE); + } else { + Label retry_load, nope; + // flush and load exclusive from the memory location + // and fail if it is not what we expect + __ bind(retry_load); + __ ldaxrw(rscratch1, addr); + __ cmpw(rscratch1, cmpval); + __ cset(rscratch1, Assembler::NE); + __ br(Assembler::NE, nope); + // if we store+flush with no intervening write rscratch1 wil be zero + __ stlxrw(rscratch1, newval, addr); + // retry so we only ever return after a load fails to compare + // ensures we don't return a stale value after a failed write. + __ cbnzw(rscratch1, retry_load); + __ bind(nope); + } __ membar(__ AnyAny); } void LIR_Assembler::casl(Register addr, Register newval, Register cmpval) { - Label retry_load, nope; - // flush and load exclusive from the memory location - // and fail if it is not what we expect - __ bind(retry_load); - __ ldaxr(rscratch1, addr); - __ cmp(rscratch1, cmpval); - __ cset(rscratch1, Assembler::NE); - __ br(Assembler::NE, nope); - // if we store+flush with no intervening write rscratch1 wil be zero - __ stlxr(rscratch1, newval, addr); - // retry so we only ever return after a load fails to compare - // ensures we don't return a stale value after a failed write. - __ cbnz(rscratch1, retry_load); - __ bind(nope); + if (UseLSE) { + __ mov(rscratch1, cmpval); + __ casal(Assembler::xword, rscratch1, newval, addr); + __ cmp(rscratch1, cmpval); + __ cset(rscratch1, Assembler::NE); + } else { + Label retry_load, nope; + // flush and load exclusive from the memory location + // and fail if it is not what we expect + __ bind(retry_load); + __ ldaxr(rscratch1, addr); + __ cmp(rscratch1, cmpval); + __ cset(rscratch1, Assembler::NE); + __ br(Assembler::NE, nope); + // if we store+flush with no intervening write rscratch1 wil be zero + __ stlxr(rscratch1, newval, addr); + // retry so we only ever return after a load fails to compare + // ensures we don't return a stale value after a failed write. + __ cbnz(rscratch1, retry_load); + __ bind(nope); + } __ membar(__ AnyAny); } diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp index 9380d429878..bb9dd4d2dc8 100644 --- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp @@ -103,6 +103,9 @@ define_pd_global(intx, InlineSmallCode, 1000); \ product(bool, UseCRC32, false, \ "Use CRC32 instructions for CRC32 computation") \ + \ + product(bool, UseLSE, false, \ + "Use LSE instructions") \ // Don't attempt to use Neon on builtin sim until builtin sim supports it #define UseCRC32 false @@ -123,6 +126,8 @@ define_pd_global(intx, InlineSmallCode, 1000); "Use Neon for CRC32 computation") \ product(bool, UseCRC32, false, \ "Use CRC32 instructions for CRC32 computation") \ + product(bool, UseLSE, false, \ + "Use LSE instructions") \ product(bool, TraceTraps, false, "Trace all traps the signal handler") #endif diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index 942518b116b..bfa9c8fba5b 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -2070,25 +2070,32 @@ void MacroAssembler::cmpxchgptr(Register oldv, Register newv, Register addr, Reg // oldv holds comparison value // newv holds value to write in exchange // addr identifies memory word to compare against/update - // tmp returns 0/1 for success/failure - Label retry_load, nope; + if (UseLSE) { + mov(tmp, oldv); + casal(Assembler::xword, oldv, newv, addr); + cmp(tmp, oldv); + br(Assembler::EQ, succeed); + membar(AnyAny); + } else { + Label retry_load, nope; - bind(retry_load); - // flush and load exclusive from the memory location - // and fail if it is not what we expect - ldaxr(tmp, addr); - cmp(tmp, oldv); - br(Assembler::NE, nope); - // if we store+flush with no intervening write tmp wil be zero - stlxr(tmp, newv, addr); - cbzw(tmp, succeed); - // retry so we only ever return after a load fails to compare - // ensures we don't return a stale value after a failed write. - b(retry_load); - // if the memory word differs we return it in oldv and signal a fail - bind(nope); - membar(AnyAny); - mov(oldv, tmp); + bind(retry_load); + // flush and load exclusive from the memory location + // and fail if it is not what we expect + ldaxr(tmp, addr); + cmp(tmp, oldv); + br(Assembler::NE, nope); + // if we store+flush with no intervening write tmp wil be zero + stlxr(tmp, newv, addr); + cbzw(tmp, succeed); + // retry so we only ever return after a load fails to compare + // ensures we don't return a stale value after a failed write. + b(retry_load); + // if the memory word differs we return it in oldv and signal a fail + bind(nope); + membar(AnyAny); + mov(oldv, tmp); + } if (fail) b(*fail); } @@ -2099,28 +2106,63 @@ void MacroAssembler::cmpxchgw(Register oldv, Register newv, Register addr, Regis // newv holds value to write in exchange // addr identifies memory word to compare against/update // tmp returns 0/1 for success/failure - Label retry_load, nope; + if (UseLSE) { + mov(tmp, oldv); + casal(Assembler::word, oldv, newv, addr); + cmp(tmp, oldv); + br(Assembler::EQ, succeed); + membar(AnyAny); + } else { + Label retry_load, nope; - bind(retry_load); - // flush and load exclusive from the memory location - // and fail if it is not what we expect - ldaxrw(tmp, addr); - cmp(tmp, oldv); - br(Assembler::NE, nope); - // if we store+flush with no intervening write tmp wil be zero - stlxrw(tmp, newv, addr); - cbzw(tmp, succeed); - // retry so we only ever return after a load fails to compare - // ensures we don't return a stale value after a failed write. - b(retry_load); - // if the memory word differs we return it in oldv and signal a fail - bind(nope); - membar(AnyAny); - mov(oldv, tmp); + bind(retry_load); + // flush and load exclusive from the memory location + // and fail if it is not what we expect + ldaxrw(tmp, addr); + cmp(tmp, oldv); + br(Assembler::NE, nope); + // if we store+flush with no intervening write tmp wil be zero + stlxrw(tmp, newv, addr); + cbzw(tmp, succeed); + // retry so we only ever return after a load fails to compare + // ensures we don't return a stale value after a failed write. + b(retry_load); + // if the memory word differs we return it in oldv and signal a fail + bind(nope); + membar(AnyAny); + mov(oldv, tmp); + } if (fail) b(*fail); } +// A generic CAS; success or failure is in the EQ flag. +void MacroAssembler::cmpxchg(Register addr, Register expected, + Register new_val, + enum operand_size size, + bool acquire, bool release, + Register tmp) { + if (UseLSE) { + mov(tmp, expected); + lse_cas(tmp, new_val, addr, size, acquire, release, /*not_pair*/ true); + cmp(tmp, expected); + } else { + BLOCK_COMMENT("cmpxchg {"); + Label retry_load, done; + bind(retry_load); + load_exclusive(tmp, addr, size, acquire); + if (size == xword) + cmp(tmp, expected); + else + cmpw(tmp, expected); + br(Assembler::NE, done); + store_exclusive(tmp, new_val, addr, size, release); + cbnzw(tmp, retry_load); + bind(done); + BLOCK_COMMENT("} cmpxchg"); + } +} + static bool different(Register a, RegisterOrConstant b, Register c) { if (b.is_constant()) return a != c; diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp index e042b5055eb..64ef4f65eca 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -971,21 +971,10 @@ public: } // A generic CAS; success or failure is in the EQ flag. - template void cmpxchg(Register addr, Register expected, Register new_val, - T1 load_insn, - void (MacroAssembler::*cmp_insn)(Register, Register), - T2 store_insn, - Register tmp = rscratch1) { - Label retry_load, done; - bind(retry_load); - (this->*load_insn)(tmp, addr); - (this->*cmp_insn)(tmp, expected); - br(Assembler::NE, done); - (this->*store_insn)(tmp, new_val, addr); - cbnzw(tmp, retry_load); - bind(done); - } + enum operand_size size, + bool acquire, bool release, + Register tmp = rscratch1); // Calls diff --git a/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp index 762b8b0f1ce..6e935f687b1 100644 --- a/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp @@ -107,6 +107,9 @@ CONSTANT_REGISTER_DECLARATION(Register, r31_sp, (31)); CONSTANT_REGISTER_DECLARATION(Register, zr, (32)); CONSTANT_REGISTER_DECLARATION(Register, sp, (33)); +// Used as a filler in instructions where a register field is unused. +const Register dummy_reg = r31_sp; + // Use FloatRegister as shortcut class FloatRegisterImpl; typedef FloatRegisterImpl* FloatRegister; diff --git a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp index 21859656b52..40275cabfa0 100644 --- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp @@ -61,6 +61,10 @@ #define HWCAP_CRC32 (1<<7) #endif +#ifndef HWCAP_ATOMICS +#define HWCAP_ATOMICS (1<<8) +#endif + int VM_Version::_cpu; int VM_Version::_model; int VM_Version::_model2; @@ -172,6 +176,7 @@ void VM_Version::get_processor_features() { if (auxv & HWCAP_AES) strcat(buf, ", aes"); if (auxv & HWCAP_SHA1) strcat(buf, ", sha1"); if (auxv & HWCAP_SHA2) strcat(buf, ", sha256"); + if (auxv & HWCAP_ATOMICS) strcat(buf, ", lse"); _features_string = os::strdup(buf); @@ -191,6 +196,15 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false); } + if (auxv & HWCAP_ATOMICS) { + if (FLAG_IS_DEFAULT(UseLSE)) + FLAG_SET_DEFAULT(UseLSE, true); + } else { + if (UseLSE) { + warning("UseLSE specified, but not supported on this CPU"); + } + } + if (auxv & HWCAP_AES) { UseAES = UseAES || FLAG_IS_DEFAULT(UseAES); UseAESIntrinsics = From af0f23a6173cf2936a7ce1dcf236ef4bab44abc3 Mon Sep 17 00:00:00 2001 From: Ed Nevill Date: Sat, 20 Feb 2016 15:11:42 +0000 Subject: [PATCH 062/311] 8150082: aarch64: optimise small array copy Reviewed-by: aph --- .../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 175 +++++++++++++----- 1 file changed, 126 insertions(+), 49 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index 942d7bc5cb7..b50ad0b1181 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -729,7 +729,7 @@ class StubGenerator: public StubCodeGenerator { // // count is a count of words. // - // Precondition: count >= 2 + // Precondition: count >= 8 // // Postconditions: // @@ -750,7 +750,7 @@ class StubGenerator: public StubCodeGenerator { assert_different_registers(rscratch1, t0, t1, t2, t3, t4, t5, t6, t7); assert_different_registers(s, d, count, rscratch1); - Label again, large, small; + Label again, drain; const char *stub_name; if (direction == copy_forwards) stub_name = "foward_copy_longs"; @@ -759,51 +759,21 @@ class StubGenerator: public StubCodeGenerator { StubCodeMark mark(this, "StubRoutines", stub_name); __ align(CodeEntryAlignment); __ bind(start); - __ cmp(count, 8); - __ br(Assembler::LO, small); if (direction == copy_forwards) { __ sub(s, s, 2 * wordSize); __ sub(d, d, 2 * wordSize); } - __ subs(count, count, 16); - __ br(Assembler::GE, large); - - // 8 <= count < 16 words. Copy 8. - __ ldp(t0, t1, Address(s, 2 * unit)); - __ ldp(t2, t3, Address(s, 4 * unit)); - __ ldp(t4, t5, Address(s, 6 * unit)); - __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); - - __ stp(t0, t1, Address(d, 2 * unit)); - __ stp(t2, t3, Address(d, 4 * unit)); - __ stp(t4, t5, Address(d, 6 * unit)); - __ stp(t6, t7, Address(__ pre(d, 8 * unit))); - - if (direction == copy_forwards) { - __ add(s, s, 2 * wordSize); - __ add(d, d, 2 * wordSize); - } +#ifdef ASSERT + // Make sure we are never given < 8 words { - Label L1, L2; - __ bind(small); - __ tbz(count, exact_log2(4), L1); - __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ ldp(t2, t3, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); - __ stp(t2, t3, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); - __ bind(L1); - - __ tbz(count, 1, L2); - __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); - __ bind(L2); + Label L; + __ cmp(count, 8); + __ br(Assembler::GE, L); + __ stop("genrate_copy_longs called with < 8 words"); + __ bind(L); } - - __ ret(lr); - - __ align(CodeEntryAlignment); - __ bind(large); +#endif // Fill 8 registers __ ldp(t0, t1, Address(s, 2 * unit)); @@ -811,6 +781,9 @@ class StubGenerator: public StubCodeGenerator { __ ldp(t4, t5, Address(s, 6 * unit)); __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + __ subs(count, count, 16); + __ br(Assembler::LO, drain); + int prefetch = PrefetchCopyIntervalInBytes; bool use_stride = false; if (direction == copy_backwards) { @@ -837,6 +810,7 @@ class StubGenerator: public StubCodeGenerator { __ br(Assembler::HS, again); // Drain + __ bind(drain); __ stp(t0, t1, Address(d, 2 * unit)); __ stp(t2, t3, Address(d, 4 * unit)); __ stp(t4, t5, Address(d, 6 * unit)); @@ -931,16 +905,119 @@ class StubGenerator: public StubCodeGenerator { int granularity = uabs(step); const Register t0 = r3, t1 = r4; + // <= 96 bytes do inline. Direction doesn't matter because we always + // load all the data before writing anything + Label copy4, copy8, copy16, copy32, copy80, copy128, copy_big, finish; + const Register t2 = r5, t3 = r6, t4 = r7, t5 = r8; + const Register t6 = r9, t7 = r10, t8 = r11, t9 = r12; + const Register send = r17, dend = r18; + + if (PrefetchCopyIntervalInBytes > 0) + __ prfm(Address(s, 0), PLDL1KEEP); + + __ cmp(count, 80/granularity); + __ br(Assembler::HI, copy_big); + + __ lea(send, Address(s, count, Address::lsl(exact_log2(granularity)))); + __ lea(dend, Address(d, count, Address::lsl(exact_log2(granularity)))); + + __ cmp(count, 16/granularity); + __ br(Assembler::LS, copy16); + + __ cmp(count, 64/granularity); + __ br(Assembler::HI, copy80); + + __ cmp(count, 32/granularity); + __ br(Assembler::LS, copy32); + + // 33..64 bytes + __ ldp(t0, t1, Address(s, 0)); + __ ldp(t2, t3, Address(s, 16)); + __ ldp(t4, t5, Address(send, -32)); + __ ldp(t6, t7, Address(send, -16)); + + __ stp(t0, t1, Address(d, 0)); + __ stp(t2, t3, Address(d, 16)); + __ stp(t4, t5, Address(dend, -32)); + __ stp(t6, t7, Address(dend, -16)); + __ b(finish); + + // 17..32 bytes + __ bind(copy32); + __ ldp(t0, t1, Address(s, 0)); + __ ldp(t2, t3, Address(send, -16)); + __ stp(t0, t1, Address(d, 0)); + __ stp(t2, t3, Address(dend, -16)); + __ b(finish); + + // 65..80 bytes + __ bind(copy80); + __ ldp(t0, t1, Address(s, 0)); + __ ldp(t2, t3, Address(s, 16)); + __ ldp(t4, t5, Address(s, 32)); + __ ldp(t6, t7, Address(s, 48)); + __ ldp(t8, t9, Address(send, -16)); + + __ stp(t0, t1, Address(d, 0)); + __ stp(t2, t3, Address(d, 16)); + __ stp(t4, t5, Address(d, 32)); + __ stp(t6, t7, Address(d, 48)); + __ stp(t8, t9, Address(dend, -16)); + __ b(finish); + + // 0..16 bytes + __ bind(copy16); + __ cmp(count, 8/granularity); + __ br(Assembler::LO, copy8); + + // 8..16 bytes + __ ldr(t0, Address(s, 0)); + __ ldr(t1, Address(send, -8)); + __ str(t0, Address(d, 0)); + __ str(t1, Address(dend, -8)); + __ b(finish); + + if (granularity < 8) { + // 4..7 bytes + __ bind(copy8); + __ tbz(count, 2 - exact_log2(granularity), copy4); + __ ldrw(t0, Address(s, 0)); + __ ldrw(t1, Address(send, -4)); + __ strw(t0, Address(d, 0)); + __ strw(t1, Address(dend, -4)); + __ b(finish); + if (granularity < 4) { + // 0..3 bytes + __ bind(copy4); + __ cbz(count, finish); // get rid of 0 case + if (granularity == 2) { + __ ldrh(t0, Address(s, 0)); + __ strh(t0, Address(d, 0)); + } else { // granularity == 1 + // Now 1..3 bytes. Handle the 1 and 2 byte case by copying + // the first and last byte. + // Handle the 3 byte case by loading and storing base + count/2 + // (count == 1 (s+0)->(d+0), count == 2,3 (s+1) -> (d+1)) + // This does means in the 1 byte case we load/store the same + // byte 3 times. + __ lsr(count, count, 1); + __ ldrb(t0, Address(s, 0)); + __ ldrb(t1, Address(send, -1)); + __ ldrb(t2, Address(s, count)); + __ strb(t0, Address(d, 0)); + __ strb(t1, Address(dend, -1)); + __ strb(t2, Address(d, count)); + } + __ b(finish); + } + } + + __ bind(copy_big); if (is_backwards) { __ lea(s, Address(s, count, Address::lsl(exact_log2(-step)))); __ lea(d, Address(d, count, Address::lsl(exact_log2(-step)))); } - Label tail; - - __ cmp(count, 16/granularity); - __ br(Assembler::LO, tail); - // Now we've got the small case out of the way we can align the // source address on a 2-word boundary. @@ -986,8 +1063,6 @@ class StubGenerator: public StubCodeGenerator { #endif } - __ cmp(count, 16/granularity); - __ br(Assembler::LT, tail); __ bind(aligned); // s is now 2-word-aligned. @@ -1001,9 +1076,11 @@ class StubGenerator: public StubCodeGenerator { __ bl(copy_b); // And the tail. - - __ bind(tail); copy_memory_small(s, d, count, tmp, step); + + if (granularity >= 8) __ bind(copy8); + if (granularity >= 4) __ bind(copy4); + __ bind(finish); } From 5f3739f293a12342e4bdde33719451d51972ef60 Mon Sep 17 00:00:00 2001 From: Ed Nevill Date: Sat, 20 Feb 2016 15:15:35 +0000 Subject: [PATCH 063/311] 8150313: aarch64: optimise array copy using SIMD instructions Reviewed-by: aph --- .../src/cpu/aarch64/vm/globals_aarch64.hpp | 3 + .../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 133 +++++++++++------- 2 files changed, 89 insertions(+), 47 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp index bb9dd4d2dc8..60edc02fc2a 100644 --- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp @@ -109,6 +109,7 @@ define_pd_global(intx, InlineSmallCode, 1000); // Don't attempt to use Neon on builtin sim until builtin sim supports it #define UseCRC32 false +#define UseSIMDForMemoryOps false #else #define UseBuiltinSim false @@ -126,6 +127,8 @@ define_pd_global(intx, InlineSmallCode, 1000); "Use Neon for CRC32 computation") \ product(bool, UseCRC32, false, \ "Use CRC32 instructions for CRC32 computation") \ + product(bool, UseSIMDForMemoryOps, false, \ + "Use SIMD instructions in generated memory move code") \ product(bool, UseLSE, false, \ "Use LSE instructions") \ product(bool, TraceTraps, false, "Trace all traps the signal handler") diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index b50ad0b1181..6ac553302c3 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -741,6 +741,7 @@ class StubGenerator: public StubCodeGenerator { void generate_copy_longs(Label &start, Register s, Register d, Register count, copy_direction direction) { int unit = wordSize * direction; + int bias = (UseSIMDForMemoryOps ? 4:2) * wordSize; int offset; const Register t0 = r3, t1 = r4, t2 = r5, t3 = r6, @@ -760,8 +761,8 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); __ bind(start); if (direction == copy_forwards) { - __ sub(s, s, 2 * wordSize); - __ sub(d, d, 2 * wordSize); + __ sub(s, s, bias); + __ sub(d, d, bias); } #ifdef ASSERT @@ -776,10 +777,15 @@ class StubGenerator: public StubCodeGenerator { #endif // Fill 8 registers - __ ldp(t0, t1, Address(s, 2 * unit)); - __ ldp(t2, t3, Address(s, 4 * unit)); - __ ldp(t4, t5, Address(s, 6 * unit)); - __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + if (UseSIMDForMemoryOps) { + __ ldpq(v0, v1, Address(s, 4 * unit)); + __ ldpq(v2, v3, Address(__ pre(s, 8 * unit))); + } else { + __ ldp(t0, t1, Address(s, 2 * unit)); + __ ldp(t2, t3, Address(s, 4 * unit)); + __ ldp(t4, t5, Address(s, 6 * unit)); + __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + } __ subs(count, count, 16); __ br(Assembler::LO, drain); @@ -797,39 +803,56 @@ class StubGenerator: public StubCodeGenerator { if (PrefetchCopyIntervalInBytes > 0) __ prfm(use_stride ? Address(s, stride) : Address(s, prefetch), PLDL1KEEP); - __ stp(t0, t1, Address(d, 2 * unit)); - __ ldp(t0, t1, Address(s, 2 * unit)); - __ stp(t2, t3, Address(d, 4 * unit)); - __ ldp(t2, t3, Address(s, 4 * unit)); - __ stp(t4, t5, Address(d, 6 * unit)); - __ ldp(t4, t5, Address(s, 6 * unit)); - __ stp(t6, t7, Address(__ pre(d, 8 * unit))); - __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + if (UseSIMDForMemoryOps) { + __ stpq(v0, v1, Address(d, 4 * unit)); + __ ldpq(v0, v1, Address(s, 4 * unit)); + __ stpq(v2, v3, Address(__ pre(d, 8 * unit))); + __ ldpq(v2, v3, Address(__ pre(s, 8 * unit))); + } else { + __ stp(t0, t1, Address(d, 2 * unit)); + __ ldp(t0, t1, Address(s, 2 * unit)); + __ stp(t2, t3, Address(d, 4 * unit)); + __ ldp(t2, t3, Address(s, 4 * unit)); + __ stp(t4, t5, Address(d, 6 * unit)); + __ ldp(t4, t5, Address(s, 6 * unit)); + __ stp(t6, t7, Address(__ pre(d, 8 * unit))); + __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + } __ subs(count, count, 8); __ br(Assembler::HS, again); // Drain __ bind(drain); - __ stp(t0, t1, Address(d, 2 * unit)); - __ stp(t2, t3, Address(d, 4 * unit)); - __ stp(t4, t5, Address(d, 6 * unit)); - __ stp(t6, t7, Address(__ pre(d, 8 * unit))); - - if (direction == copy_forwards) { - __ add(s, s, 2 * wordSize); - __ add(d, d, 2 * wordSize); + if (UseSIMDForMemoryOps) { + __ stpq(v0, v1, Address(d, 4 * unit)); + __ stpq(v2, v3, Address(__ pre(d, 8 * unit))); + } else { + __ stp(t0, t1, Address(d, 2 * unit)); + __ stp(t2, t3, Address(d, 4 * unit)); + __ stp(t4, t5, Address(d, 6 * unit)); + __ stp(t6, t7, Address(__ pre(d, 8 * unit))); } { Label L1, L2; __ tbz(count, exact_log2(4), L1); - __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ ldp(t2, t3, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); - __ stp(t2, t3, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); + if (UseSIMDForMemoryOps) { + __ ldpq(v0, v1, Address(__ pre(s, 4 * unit))); + __ stpq(v0, v1, Address(__ pre(d, 4 * unit))); + } else { + __ ldp(t0, t1, Address(s, 2 * unit)); + __ ldp(t2, t3, Address(__ pre(s, 4 * unit))); + __ stp(t0, t1, Address(d, 2 * unit)); + __ stp(t2, t3, Address(__ pre(d, 4 * unit))); + } __ bind(L1); + if (direction == copy_forwards) { + __ add(s, s, 2 * wordSize); + __ add(d, d, 2 * wordSize); + } + __ tbz(count, 1, L2); __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); @@ -914,8 +937,7 @@ class StubGenerator: public StubCodeGenerator { if (PrefetchCopyIntervalInBytes > 0) __ prfm(Address(s, 0), PLDL1KEEP); - - __ cmp(count, 80/granularity); + __ cmp(count, (UseSIMDForMemoryOps ? 96:80)/granularity); __ br(Assembler::HI, copy_big); __ lea(send, Address(s, count, Address::lsl(exact_log2(granularity)))); @@ -931,15 +953,22 @@ class StubGenerator: public StubCodeGenerator { __ br(Assembler::LS, copy32); // 33..64 bytes - __ ldp(t0, t1, Address(s, 0)); - __ ldp(t2, t3, Address(s, 16)); - __ ldp(t4, t5, Address(send, -32)); - __ ldp(t6, t7, Address(send, -16)); + if (UseSIMDForMemoryOps) { + __ ldpq(v0, v1, Address(s, 0)); + __ ldpq(v2, v3, Address(send, -32)); + __ stpq(v0, v1, Address(d, 0)); + __ stpq(v2, v3, Address(dend, -32)); + } else { + __ ldp(t0, t1, Address(s, 0)); + __ ldp(t2, t3, Address(s, 16)); + __ ldp(t4, t5, Address(send, -32)); + __ ldp(t6, t7, Address(send, -16)); - __ stp(t0, t1, Address(d, 0)); - __ stp(t2, t3, Address(d, 16)); - __ stp(t4, t5, Address(dend, -32)); - __ stp(t6, t7, Address(dend, -16)); + __ stp(t0, t1, Address(d, 0)); + __ stp(t2, t3, Address(d, 16)); + __ stp(t4, t5, Address(dend, -32)); + __ stp(t6, t7, Address(dend, -16)); + } __ b(finish); // 17..32 bytes @@ -950,19 +979,29 @@ class StubGenerator: public StubCodeGenerator { __ stp(t2, t3, Address(dend, -16)); __ b(finish); - // 65..80 bytes + // 65..80/96 bytes + // (96 bytes if SIMD because we do 32 byes per instruction) __ bind(copy80); - __ ldp(t0, t1, Address(s, 0)); - __ ldp(t2, t3, Address(s, 16)); - __ ldp(t4, t5, Address(s, 32)); - __ ldp(t6, t7, Address(s, 48)); - __ ldp(t8, t9, Address(send, -16)); + if (UseSIMDForMemoryOps) { + __ ldpq(v0, v1, Address(s, 0)); + __ ldpq(v2, v3, Address(s, 32)); + __ ldpq(v4, v5, Address(send, -32)); + __ stpq(v0, v1, Address(d, 0)); + __ stpq(v2, v3, Address(d, 32)); + __ stpq(v4, v5, Address(dend, -32)); + } else { + __ ldp(t0, t1, Address(s, 0)); + __ ldp(t2, t3, Address(s, 16)); + __ ldp(t4, t5, Address(s, 32)); + __ ldp(t6, t7, Address(s, 48)); + __ ldp(t8, t9, Address(send, -16)); - __ stp(t0, t1, Address(d, 0)); - __ stp(t2, t3, Address(d, 16)); - __ stp(t4, t5, Address(d, 32)); - __ stp(t6, t7, Address(d, 48)); - __ stp(t8, t9, Address(dend, -16)); + __ stp(t0, t1, Address(d, 0)); + __ stp(t2, t3, Address(d, 16)); + __ stp(t4, t5, Address(d, 32)); + __ stp(t6, t7, Address(d, 48)); + __ stp(t8, t9, Address(dend, -16)); + } __ b(finish); // 0..16 bytes From 2011115a3ec220b69d4cfc715869dff26d4e350a Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Mon, 22 Feb 2016 11:22:55 +0100 Subject: [PATCH 064/311] 8150203: Incremental update from build-infra project Reviewed-by: erikj --- common/autoconf/flags.m4 | 1 + common/autoconf/generated-configure.sh | 16 +++++++++++----- common/autoconf/libraries.m4 | 14 +++++++++----- common/autoconf/spec.gmk.in | 2 ++ make/Init.gmk | 3 +++ make/common/NativeCompilation.gmk | 9 ++++++--- 6 files changed, 32 insertions(+), 13 deletions(-) diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index c949c93c5cf..1cc71d47058 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -891,6 +891,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], AC_SUBST(JDKLIB_LIBS) AC_SUBST(JDKEXE_LIBS) AC_SUBST(LDFLAGS_CXX_JDK) + AC_SUBST(LDFLAGS_HASH_STYLE) LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 20d766e7d4e..839422ccb9c 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -701,6 +701,7 @@ COMPILER_SUPPORTS_TARGET_BITS_FLAG ZERO_ARCHFLAG LDFLAGS_TESTEXE LDFLAGS_TESTLIB +LDFLAGS_HASH_STYLE LDFLAGS_CXX_JDK JDKEXE_LIBS JDKLIB_LIBS @@ -4230,7 +4231,7 @@ pkgadd_help() { # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, 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 @@ -4860,7 +4861,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1455271513 +DATE_WHEN_GENERATED=1456136545 ############################################################################### # @@ -46881,6 +46882,7 @@ $as_echo "$supports" >&6; } + LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" @@ -58630,7 +58632,8 @@ fi # Setup libm (the maths library) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 + if test "x$OPENJDK_TARGET_OS" != "xwindows"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 $as_echo_n "checking for cos in -lm... " >&6; } if ${ac_cv_lib_m_cos+:} false; then : $as_echo_n "(cached) " >&6 @@ -58675,12 +58678,15 @@ _ACEOF else - { $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5 $as_echo "$as_me: Maths library was not found" >&6;} fi - LIBM=-lm + LIBM="-lm" + else + LIBM="" + fi # Setup libdl (for dynamic library loading) diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index 7bae405555e..a6a8bd4f19b 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, 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 @@ -160,10 +160,14 @@ AC_DEFUN_ONCE([LIB_SETUP_LLVM], AC_DEFUN_ONCE([LIB_SETUP_MISC_LIBS], [ # Setup libm (the maths library) - AC_CHECK_LIB(m, cos, [], [ - AC_MSG_NOTICE([Maths library was not found]) - ]) - LIBM=-lm + if test "x$OPENJDK_TARGET_OS" != "xwindows"; then + AC_CHECK_LIB(m, cos, [], [ + AC_MSG_NOTICE([Maths library was not found]) + ]) + LIBM="-lm" + else + LIBM="" + fi AC_SUBST(LIBM) # Setup libdl (for dynamic library loading) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 2a6c872cf27..1b178681404 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -351,6 +351,8 @@ CXXFLAGS_JDKLIB:=@CXXFLAGS_JDKLIB@ CFLAGS_JDKEXE:=@CFLAGS_JDKEXE@ CXXFLAGS_JDKEXE:=@CXXFLAGS_JDKEXE@ +LDFLAGS_HASH_STYLE := @LDFLAGS_HASH_STYLE@ + CXX:=@FIXPATH@ @CCACHE@ @ICECC@ @CXX@ CPP:=@FIXPATH@ @CPP@ diff --git a/make/Init.gmk b/make/Init.gmk index 4ed492c68fc..ee67aeaa65f 100644 --- a/make/Init.gmk +++ b/make/Init.gmk @@ -154,6 +154,9 @@ ifeq ($(HAS_SPEC),) # Do nothing endif + # Do not let make delete spec files even if aborted while doing a reconfigure + .PRECIOUS: $(SPECS) + # Unless reconfigure is explicitely called, let all main targets depend on # the spec files to be up to date. ifeq ($(findstring reconfigure, $(INIT_TARGETS)), ) diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 53637fcb953..f16a85182c8 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -651,12 +651,15 @@ define SetupNativeCompilationBody $$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE) $$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$(notdir $$($1_TARGET)))) + $$(call MakeDir, $$(@D) $$($1_OBJECT_DIR)) $$(call ExecuteWithLog, $$@, \ $$($1_RC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \ $$($1_VERSIONINFO_RESOURCE)) # Windows RC compiler does not support -showIncludes, so we mis-use CL for this. - $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \ - $(CC_OUT_OPTION)$$($1_RES_DEP).obj $$($1_VERSIONINFO_RESOURCE) > $$($1_RES_DEP).raw 2>&1 || true ; \ + $$(call ExecuteWithLog, $$($1_RES_DEP).obj, \ + $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \ + $(CC_OUT_OPTION)$$($1_RES_DEP).obj -P -Fi$$($1_RES_DEP).pp \ + $$($1_VERSIONINFO_RESOURCE)) > $$($1_RES_DEP).raw 2>&1 || true ; \ $(ECHO) $$($1_RES): \\ > $$($1_RES_DEP) ; \ $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEP).raw >> $$($1_RES_DEP) ; \ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEP) > $$($1_RES_DEP_TARGETS) @@ -670,7 +673,7 @@ define SetupNativeCompilationBody $1_REAL_MAPFILE := $$($1_OBJECT_DIR)/mapfile $$($1_REAL_MAPFILE) : $$($1_MAPFILE) $$($1_REORDER) - $$(MKDIR) -p $$(@D) + $$(call MakeDir, $$(@D)) $$(CP) $$($1_MAPFILE) $$@.tmp $$(SED) -e 's=OUTPUTDIR=$$($1_OBJECT_DIR)=' $$($1_REORDER) >> $$@.tmp $$(MV) $$@.tmp $$@ From 589abd0822a17c5ba206eff93bd4e49bc4c83e92 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Mon, 22 Feb 2016 11:23:03 +0100 Subject: [PATCH 065/311] 8150203: Incremental update from build-infra project Reviewed-by: erikj --- jdk/make/gensrc/GensrcMisc.gmk | 16 +++++++++------- jdk/make/lib/Awt2dLibraries.gmk | 6 +++--- jdk/make/lib/CoreLibraries.gmk | 6 +++--- jdk/make/lib/Lib-java.instrument.gmk | 3 +-- jdk/make/lib/Lib-jdk.jdi.gmk | 3 +-- jdk/make/lib/Lib-jdk.jdwp.agent.gmk | 3 +-- .../build/tools/dtdbuilder/DTDParser.java | 6 +----- 7 files changed, 19 insertions(+), 24 deletions(-) diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk index bc70e0e01f0..ffefb50a5b0 100644 --- a/jdk/make/gensrc/GensrcMisc.gmk +++ b/jdk/make/gensrc/GensrcMisc.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, 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 @@ -53,6 +53,8 @@ SOR_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSRC_SOR_SRC)/$(GENSRC_SOR_SRC_FILE) | $(eval $(call SetupNativeCompilation, BUILD_GENSRC_SOR_EXE, \ SRC := $(GENSRC_SOR_SRC), \ INCLUDE_FILES := $(GENSRC_SOR_SRC_FILE), \ + CFLAGS_windows := -nologo, \ + LDFLAGS_windows := -nologo, \ TOOLCHAIN := TOOLCHAIN_BUILD, \ OBJECT_DIR := $(GENSRC_SOR_BIN), \ OUTPUT_DIR := $(GENSRC_SOR_BIN), \ @@ -61,12 +63,12 @@ $(eval $(call SetupNativeCompilation, BUILD_GENSRC_SOR_EXE, \ SOR_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/ch/SocketOptionRegistry-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template ifeq ($(wildcard $(SOR_PREGEN_FILE)), ) - $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE) + $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE_TARGET) $(MKDIR) -p $(@D) $(RM) $@ $@.tmp NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \ $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOR_COPYRIGHT_YEARS)" > $@.tmp - $(BUILD_GENSRC_SOR_EXE) >> $@.tmp + $(BUILD_GENSRC_SOR_EXE_TARGET) >> $@.tmp $(MV) $@.tmp $@ else $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(SOR_PREGEN_FILE) @@ -97,12 +99,12 @@ ifneq ($(OPENJDK_TARGET_OS), windows) UC_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/fs/UnixConstants-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template ifeq ($(wildcard $(UC_PREGEN_FILE)), ) - $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE) + $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE_TARGET) $(MKDIR) -p $(@D) $(RM) $@ $@.tmp NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \ $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(UC_COPYRIGHT_YEARS)" > $@.tmp - $(BUILD_GENSRC_UC_EXE) >> $@.tmp + $(BUILD_GENSRC_UC_EXE_TARGET) >> $@.tmp $(MV) $@.tmp $@ else $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(UC_PREGEN_FILE) @@ -132,12 +134,12 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) OUTPUT_DIR := $(GENSRC_SOL_BIN), \ PROGRAM := genSolarisConstants)) - $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE) + $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE_TARGET) $(MKDIR) -p $(@D) $(RM) $@ $@.tmp NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \ $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOL_COPYRIGHT_YEARS)" > $@.tmp - $(BUILD_GENSRC_SOL_EXE) >> $@.tmp + $(BUILD_GENSRC_SOL_EXE_TARGET) >> $@.tmp $(MV) $@.tmp $@ diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index ad58edb2823..d6ba6443bf2 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, 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 @@ -593,8 +593,8 @@ ifeq ($(BUILD_HEADLESS), true) LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \ REORDER := $(LIBAWT_HEADLESS_REORDER), \ LIBS_unix := -lawt -ljvm -ljava, \ - LIBS_linux := -lm $(LIBDL), \ - LIBS_solaris := -lm $(LIBDL) $(LIBCXX) -lc, \ + LIBS_linux := $(LIBM) $(LIBDL), \ + LIBS_solaris := $(LIBM) $(LIBDL) $(LIBCXX) -lc, \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \ )) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index ea7c7f3c991..bd707071427 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, 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 @@ -163,7 +163,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \ LIBS_unix := -ljvm -lverify, \ LIBS_linux := $(LIBDL) $(BUILD_LIBFDLIBM), \ LIBS_solaris := -lsocket -lnsl -lscf $(LIBDL) $(BUILD_LIBFDLIBM) -lc, \ - LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) -lm,\ + LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) $(LIBM),\ LIBS_macosx := -lfdlibm \ -framework CoreFoundation \ -framework Foundation \ @@ -225,7 +225,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBZIP, \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_windows := -export:ZIP_Open -export:ZIP_Close -export:ZIP_FindEntry \ -export:ZIP_ReadEntry -export:ZIP_GetNextEntry \ - -export:ZIP_InflateFully -export:ZIP_CRC32, \ + -export:ZIP_InflateFully, \ LIBS_unix := -ljvm -ljava $(LIBZ), \ LIBS_solaris := -lc, \ LIBS_windows := jvm.lib $(WIN_JAVA_LIB), \ diff --git a/jdk/make/lib/Lib-java.instrument.gmk b/jdk/make/lib/Lib-java.instrument.gmk index 02df76073af..44ba88dad40 100644 --- a/jdk/make/lib/Lib-java.instrument.gmk +++ b/jdk/make/lib/Lib-java.instrument.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, 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 @@ -67,7 +67,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBINSTRUMENT, \ -L$(call FindLibDirForModule, java.base)/jli, \ LDFLAGS_macosx := -Wl$(COMMA)-all_load, \ LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \ - LDFLAGS_windows := -export:Agent_OnAttach, \ LIBS := $(JDKLIB_LIBS), \ LIBS_unix := -ljava $(LIBZ), \ LIBS_linux := -ljli $(LIBDL), \ diff --git a/jdk/make/lib/Lib-jdk.jdi.gmk b/jdk/make/lib/Lib-jdk.jdi.gmk index 8bed1f9abd1..bb1edfd1c23 100644 --- a/jdk/make/lib/Lib-jdk.jdi.gmk +++ b/jdk/make/lib/Lib-jdk.jdi.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, 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 @@ -47,7 +47,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows) CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ $(LIBDT_SHMEM_CPPFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ - LDFLAGS_windows := -export:jdwpTransport_OnLoad, \ LIBS := $(JDKLIB_LIBS), \ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ RC_FLAGS := $(RC_FLAGS) \ diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk index 198dc2c2433..84c05ba6368 100644 --- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, 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 @@ -46,7 +46,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBDT_SOCKET, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdt_socket/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ - LDFLAGS_windows := -export:jdwpTransport_OnLoad, \ LIBS_linux := -lpthread, \ LIBS_solaris := -lnsl -lsocket -lc, \ LIBS_windows := $(JDKLIB_LIBS) ws2_32.lib, \ diff --git a/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java b/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java index 0dee68e367f..8ef7cfe13b0 100644 --- a/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java +++ b/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -908,16 +908,12 @@ class DTDParser implements DTDConstants { this.dtd = dtd; this.in = new DTDInputStream(in, dtd); - long tm = System.currentTimeMillis(); ch = this.in.read(); parseSection(); if (ch != -1) { error("premature"); } - - tm = System.currentTimeMillis() - tm; - System.err.println("[Parsed DTD " + dtd + " in " + tm + "ms]"); } catch (IOException e) { error("ioexception"); } catch (Exception e) { From 4b8c19d6b707315811bd697f2221dccb6c494d63 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Mon, 22 Feb 2016 11:27:09 +0100 Subject: [PATCH 066/311] 8150197: Integrate AIX fixes from build-infra Reviewed-by: erikj --- common/autoconf/flags.m4 | 24 ++++++++++++++++++++--- common/autoconf/generated-configure.sh | 27 ++++++++++++++++++++++---- common/autoconf/spec.gmk.in | 4 ++++ make/common/NativeCompilation.gmk | 5 +++++ 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index 1cc71d47058..6b08cbb0a4f 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -123,12 +123,16 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], [ # COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output # COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler + # COMPILER_BINDCMD_FILE_FLAG : option for specifying a file which saves the binder + # commands produced by the link step (currently AIX only) if test "x$TOOLCHAIN_TYPE" = xxlc; then COMPILER_TARGET_BITS_FLAG="-q" COMPILER_COMMAND_FILE_FLAG="-f" + COMPILER_BINDCMD_FILE_FLAG="-bloadmap:" else COMPILER_TARGET_BITS_FLAG="-m" COMPILER_COMMAND_FILE_FLAG="@" + COMPILER_BINDCMD_FILE_FLAG="" # The solstudio linker does not support @-files. if test "x$TOOLCHAIN_TYPE" = xsolstudio; then @@ -152,6 +156,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], fi AC_SUBST(COMPILER_TARGET_BITS_FLAG) AC_SUBST(COMPILER_COMMAND_FILE_FLAG) + AC_SUBST(COMPILER_BINDCMD_FILE_FLAG) # FIXME: figure out if we should select AR flags depending on OS or toolchain. if test "x$OPENJDK_TARGET_OS" = xmacosx; then @@ -294,10 +299,23 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], SET_SHARED_LIBRARY_NAME='-h [$]1' SET_SHARED_LIBRARY_MAPFILE='-M[$]1' elif test "x$TOOLCHAIN_TYPE" = xxlc; then - PICFLAG="-qpic=large" + # '-qpic' defaults to 'qpic=small'. This means that the compiler generates only + # one instruction for accessing the TOC. If the TOC grows larger than 64K, the linker + # will have to patch this single instruction with a call to some out-of-order code which + # does the load from the TOC. This is of course slow. But in that case we also would have + # to use '-bbigtoc' for linking anyway so we could also change the PICFLAG to 'qpic=large'. + # With 'qpic=large' the compiler will by default generate a two-instruction sequence which + # can be patched directly by the linker and does not require a jump to out-of-order code. + # Another alternative instead of using 'qpic=large -bbigtoc' may be to use '-qminimaltoc' + # instead. This creates a distinct TOC for every compilation unit (and thus requires two + # loads for accessing a global variable). But there are rumors that this may be seen as a + # 'performance feature' because of improved code locality of the symbols used in a + # compilation unit. + PICFLAG="-qpic" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" C_FLAG_REORDER='' CXX_FLAG_REORDER='' - SHARED_LIBRARY_FLAGS="-qmkshrobj" + SHARED_LIBRARY_FLAGS="-qmkshrobj -bM:SRE -bnoentry" SET_EXECUTABLE_ORIGIN="" SET_SHARED_LIBRARY_ORIGIN='' SET_SHARED_LIBRARY_NAME='' @@ -835,7 +853,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], LDFLAGS_CXX_SOLSTUDIO="-norunpath" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - LDFLAGS_XLC="-brtl -bnolibpath -bexpall -bernotok" + LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" fi diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 839422ccb9c..7a9d7900667 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -744,6 +744,7 @@ EXE_OUT_OPTION CC_OUT_OPTION STRIPFLAGS ARFLAGS +COMPILER_BINDCMD_FILE_FLAG COMPILER_COMMAND_FILE_FLAG COMPILER_TARGET_BITS_FLAG JT_HOME @@ -4861,7 +4862,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1456136545 +DATE_WHEN_GENERATED=1456136781 ############################################################################### # @@ -45392,12 +45393,16 @@ $as_echo "$tool_specified" >&6; } # COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output # COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler + # COMPILER_BINDCMD_FILE_FLAG : option for specifying a file which saves the binder + # commands produced by the link step (currently AIX only) if test "x$TOOLCHAIN_TYPE" = xxlc; then COMPILER_TARGET_BITS_FLAG="-q" COMPILER_COMMAND_FILE_FLAG="-f" + COMPILER_BINDCMD_FILE_FLAG="-bloadmap:" else COMPILER_TARGET_BITS_FLAG="-m" COMPILER_COMMAND_FILE_FLAG="@" + COMPILER_BINDCMD_FILE_FLAG="" # The solstudio linker does not support @-files. if test "x$TOOLCHAIN_TYPE" = xsolstudio; then @@ -45425,6 +45430,7 @@ $as_echo "no" >&6; } + # FIXME: figure out if we should select AR flags depending on OS or toolchain. if test "x$OPENJDK_TARGET_OS" = xmacosx; then ARFLAGS="-r" @@ -46199,10 +46205,23 @@ $as_echo "$ac_cv_c_bigendian" >&6; } SET_SHARED_LIBRARY_NAME='-h $1' SET_SHARED_LIBRARY_MAPFILE='-M$1' elif test "x$TOOLCHAIN_TYPE" = xxlc; then - PICFLAG="-qpic=large" + # '-qpic' defaults to 'qpic=small'. This means that the compiler generates only + # one instruction for accessing the TOC. If the TOC grows larger than 64K, the linker + # will have to patch this single instruction with a call to some out-of-order code which + # does the load from the TOC. This is of course slow. But in that case we also would have + # to use '-bbigtoc' for linking anyway so we could also change the PICFLAG to 'qpic=large'. + # With 'qpic=large' the compiler will by default generate a two-instruction sequence which + # can be patched directly by the linker and does not require a jump to out-of-order code. + # Another alternative instead of using 'qpic=large -bbigtoc' may be to use '-qminimaltoc' + # instead. This creates a distinct TOC for every compilation unit (and thus requires two + # loads for accessing a global variable). But there are rumors that this may be seen as a + # 'performance feature' because of improved code locality of the symbols used in a + # compilation unit. + PICFLAG="-qpic" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" C_FLAG_REORDER='' CXX_FLAG_REORDER='' - SHARED_LIBRARY_FLAGS="-qmkshrobj" + SHARED_LIBRARY_FLAGS="-qmkshrobj -bM:SRE -bnoentry" SET_EXECUTABLE_ORIGIN="" SET_SHARED_LIBRARY_ORIGIN='' SET_SHARED_LIBRARY_NAME='' @@ -46825,7 +46844,7 @@ $as_echo "$supports" >&6; } LDFLAGS_CXX_SOLSTUDIO="-norunpath" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - LDFLAGS_XLC="-brtl -bnolibpath -bexpall -bernotok" + LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" fi diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 1b178681404..d8322ebce9c 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -314,6 +314,10 @@ COMPILER_SUPPORTS_TARGET_BITS_FLAG=@COMPILER_SUPPORTS_TARGET_BITS_FLAG@ # Option used to pass a command file to the compiler COMPILER_COMMAND_FILE_FLAG:=@COMPILER_COMMAND_FILE_FLAG@ +# Option for specifying a file which saves the binder commands +# produced by the link step (for debugging, currently AIX only) +COMPILER_BINDCMD_FILE_FLAG:=@COMPILER_BINDCMD_FILE_FLAG@ + CC_OUT_OPTION:=@CC_OUT_OPTION@ EXE_OUT_OPTION:=@EXE_OUT_OPTION@ LD_OUT_OPTION:=@LD_OUT_OPTION@ diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index f16a85182c8..ffae49df541 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -771,6 +771,11 @@ define SetupNativeCompilationBody $1_EXTRA_LDFLAGS += "-implib:$$($1_OBJECT_DIR)/$$($1_LIBRARY).lib" endif + # Create loadmap on AIX. Helps in diagnosing some problems. + ifneq ($(COMPILER_BINDCMD_FILE_FLAG),) + $1_EXTRA_LDFLAGS += $(COMPILER_BINDCMD_FILE_FLAG)$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).loadmap + endif + $1_EXTRA_LIBS += $(GLOBAL_LIBS) $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ From 0c28c2ee37928055b5aaafd7ec3e0e5ca46c5025 Mon Sep 17 00:00:00 2001 From: Jon Masamitsu Date: Mon, 22 Feb 2016 09:41:56 -0800 Subject: [PATCH 067/311] 8150302: Reference processing logging prints the "from list" incorrectly Reviewed-by: tamao, brutisso --- hotspot/src/share/vm/gc/shared/referenceProcessor.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp index 544cf81001d..7b3616ff168 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp @@ -339,7 +339,7 @@ void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, // all linked Reference objects. Note that it is important to not dirty any // cards during reference processing since this will cause card table // verification to fail for G1. - log_develop_trace(gc, ref)("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, p2i(refs_list.head())); + log_develop_trace(gc, ref)("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, p2i(&refs_list)); oop obj = NULL; oop next_d = refs_list.head(); @@ -502,7 +502,7 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list, // Close the reachable set complete_gc->do_void(); log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " dead Refs out of " SIZE_FORMAT " discovered Refs by policy, from list " INTPTR_FORMAT, - iter.removed(), iter.processed(), p2i(refs_list.head())); + iter.removed(), iter.processed(), p2i(&refs_list)); } // Traverse the list and remove any Refs that are not active, or @@ -536,7 +536,7 @@ ReferenceProcessor::pp2_work(DiscoveredList& refs_list, if (iter.processed() > 0) { log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " active Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT, - iter.removed(), iter.processed(), p2i(refs_list.head())); + iter.removed(), iter.processed(), p2i(&refs_list)); } ) } @@ -575,7 +575,7 @@ ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list, if (iter.processed() > 0) { log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " active Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT, - iter.removed(), iter.processed(), p2i(refs_list.head())); + iter.removed(), iter.processed(), p2i(&refs_list)); } ) } @@ -1198,7 +1198,7 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, NOT_PRODUCT( if (iter.processed() > 0) { log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT, - iter.removed(), iter.processed(), p2i(refs_list.head())); + iter.removed(), iter.processed(), p2i(&refs_list)); } ) } From 5b5e0a63e76a979ee2e3db3adf3c76151320406a Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Mon, 22 Feb 2016 11:00:06 -0800 Subject: [PATCH 068/311] 8149915: enabling validate-annotations feature for xsd schema with annotation causes NPE Reviewed-by: joehw --- .../internal/impl/XML11DTDScannerImpl.java | 10 - .../internal/impl/XMLDTDScannerImpl.java | 3 +- .../impl/XMLDocumentFragmentScannerImpl.java | 19 +- .../internal/impl/XMLDocumentScannerImpl.java | 6 +- .../internal/impl/XMLEntityManager.java | 21 +- .../impl/XMLNSDocumentScannerImpl.java | 8 +- .../xerces/internal/impl/XMLScanner.java | 9 +- .../xs/traversers/XSAttributeChecker.java | 8 +- .../impl/xs/traversers/XSDHandler.java | 224 +++++++++--------- .../internal/parsers/XML11Configuration.java | 159 ++++++------- .../xerces/internal/util/HTTPInputSource.java | 6 +- .../jaxp/unittest/validation/Bug8149915.xsd | 7 + .../jaxp/unittest/validation/SchemaTest.java | 50 ++++ 13 files changed, 270 insertions(+), 260 deletions(-) create mode 100644 jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd create mode 100644 jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java index e3336e3bee4..d6648b75bcb 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java @@ -97,19 +97,9 @@ import com.sun.org.apache.xerces.internal.xni.XNIException; public class XML11DTDScannerImpl extends XMLDTDScannerImpl { - /** Array of 3 strings. */ - private String[] fStrings = new String[3]; - - /** String. */ - private XMLString fString = new XMLString(); - /** String buffer. */ private XMLStringBuffer fStringBuffer = new XMLStringBuffer(); - /** String buffer. */ - private XMLStringBuffer fStringBuffer2 = new XMLStringBuffer(); - private XMLStringBuffer fStringBuffer3 = new XMLStringBuffer(); - // // Constructors // diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java index 591e4601efe..4daa5f0e333 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -46,7 +46,6 @@ import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; -import com.sun.xml.internal.stream.Entity; /** * This class is responsible for scanning the declarations found diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java index 1ea57877573..e31e838c8e8 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -23,7 +23,6 @@ package com.sun.org.apache.xerces.internal.impl; import com.sun.xml.internal.stream.XMLBufferListener; import com.sun.xml.internal.stream.XMLEntityStorage; -import com.sun.xml.internal.stream.XMLInputFactoryImpl; import com.sun.xml.internal.stream.dtd.DTDGrammarUtil; import java.io.EOFException; @@ -50,17 +49,11 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; -import com.sun.org.apache.xerces.internal.util.NamespaceSupport; import com.sun.org.apache.xerces.internal.utils.SecuritySupport; -import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.State; import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; -import com.sun.org.apache.xerces.internal.xni.NamespaceContext; -import javax.xml.XMLConstants; import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.events.XMLEvent; /** * @@ -210,12 +203,12 @@ public class XMLDocumentFragmentScannerImpl null, null, null, - EXTERNAL_ACCESS_DEFAULT + null }; private static final char [] cdata = {'[','C','D','A','T','A','['}; static final char [] xmlDecl = {'<','?','x','m','l'}; - private static final char [] endTag = {'<','/'}; + // private static final char [] endTag = {'<','/'}; // debugging /** Debug scanner state. */ @@ -2066,7 +2059,7 @@ public class XMLDocumentFragmentScannerImpl */ String checkAccess(String systemId, String allowedProtocols) throws IOException { String baseSystemId = fEntityScanner.getBaseSystemId(); - String expandedSystemId = fEntityManager.expandSystemId(systemId, baseSystemId,fStrictURI); + String expandedSystemId = XMLEntityManager.expandSystemId(systemId, baseSystemId, fStrictURI); return SecuritySupport.checkAccess(expandedSystemId, allowedProtocols, Constants.ACCESS_EXTERNAL_ALL); } @@ -2602,8 +2595,6 @@ public class XMLDocumentFragmentScannerImpl // // Driver methods // - private boolean fContinueDispatching = true; - private boolean fScanningForMarkup = true; /** * decides the appropriate state of the parser @@ -3266,7 +3257,7 @@ public class XMLDocumentFragmentScannerImpl protected XMLString getString(){ if(fAttributeCacheUsedCount < initialCacheCount || fAttributeCacheUsedCount < attributeValueCache.size()){ - return (XMLString)attributeValueCache.get(fAttributeCacheUsedCount++); + return attributeValueCache.get(fAttributeCacheUsedCount++); } else{ XMLString str = new XMLString(); fAttributeCacheUsedCount++; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java index 5a48b73aa52..7f1bbf10226 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -31,7 +31,6 @@ import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.xni.NamespaceContext; import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; -import com.sun.org.apache.xerces.internal.xni.XMLString; import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; @@ -224,9 +223,6 @@ public class XMLDocumentScannerImpl /** A DTD Description. */ private final XMLDTDDescription fDTDDescription = new XMLDTDDescription(null, null, null, null, null); - /** String. */ - private XMLString fString = new XMLString(); - private static final char [] DOCTYPE = {'D','O','C','T','Y','P','E'}; private static final char [] COMMENTSTRING = {'-','-'}; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java index ff96275c433..f08a1275dfa 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -370,7 +370,7 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { protected Map fEntities = new HashMap<>(); /** Entity stack. */ - protected Stack fEntityStack = new Stack(); + protected Stack fEntityStack = new Stack<>(); /** Current entity. */ protected Entity.ScannedEntity fCurrentEntity = null; @@ -633,10 +633,10 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { final HTTPInputSource httpInputSource = (HTTPInputSource) xmlInputSource; // set request properties - Iterator propIter = httpInputSource.getHTTPRequestProperties(); + Iterator> propIter = httpInputSource.getHTTPRequestProperties(); while (propIter.hasNext()) { - Map.Entry entry = (Map.Entry) propIter.next(); - urlConnection.setRequestProperty((String) entry.getKey(), (String) entry.getValue()); + Map.Entry entry = propIter.next(); + urlConnection.setRequestProperty(entry.getKey(), entry.getValue()); } // set preference for redirection @@ -1057,7 +1057,6 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { String literalSystemId = resourceIdentifier.getLiteralSystemId(); String baseSystemId = resourceIdentifier.getBaseSystemId(); String expandedSystemId = resourceIdentifier.getExpandedSystemId(); - String namespace = resourceIdentifier.getNamespace(); // if no base systemId given, assume that it's relative // to the systemId of the current scanned entity @@ -2067,14 +2066,6 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { // system id has to be a valid URI if (strict) { - - - // check if there is a system id before - // trying to expand it. - if (systemId == null) { - return null; - } - try { // if it's already an absolute one, return it new URI(systemId); @@ -2968,7 +2959,7 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { if (!fCurrentEntity.xmlDeclChunkRead) { fCurrentEntity.xmlDeclChunkRead = true; - len = fCurrentEntity.DEFAULT_XMLDECL_BUFFER_SIZE; + len = DEFAULT_XMLDECL_BUFFER_SIZE; } return fInputStream.read(b, off, len); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java index 8badd36d876..2cdb0001322 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -25,8 +25,6 @@ import com.sun.org.apache.xerces.internal.xni.XMLString; import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidatorFilter; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; -import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl; -import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; import com.sun.org.apache.xerces.internal.util.XMLSymbols; import com.sun.org.apache.xerces.internal.xni.NamespaceContext; import com.sun.org.apache.xerces.internal.xni.QName; @@ -34,13 +32,9 @@ import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; -import com.sun.org.apache.xerces.internal.xni.XMLAttributes; import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; -import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.events.XMLEvent; /** diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java index 10c484ac3a3..5ead2dd1fc6 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -25,7 +25,6 @@ import com.sun.org.apache.xerces.internal.util.Status; import com.sun.xml.internal.stream.XMLEntityStorage; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import javax.xml.stream.events.XMLEvent; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.SymbolTable; @@ -120,8 +119,8 @@ public abstract class XMLScanner //we should have a feature when set to true computes this value private boolean fNeedNonNormalizedValue = false; - protected ArrayList attributeValueCache = new ArrayList(); - protected ArrayList stringBufferCache = new ArrayList(); + protected ArrayList attributeValueCache = new ArrayList<>(); + protected ArrayList stringBufferCache = new ArrayList<>(); protected int fStringBufferIndex = 0; protected boolean fAttributeCacheInitDone = false; protected int fAttributeCacheUsedCount = 0; @@ -1470,7 +1469,7 @@ public abstract class XMLScanner XMLStringBuffer getStringBuffer(){ if((fStringBufferIndex < initialCacheCount )|| (fStringBufferIndex < stringBufferCache.size())){ - return (XMLStringBuffer)stringBufferCache.get(fStringBufferIndex++); + return stringBufferCache.get(fStringBufferIndex++); }else{ XMLStringBuffer tmpObj = new XMLStringBuffer(); fStringBufferIndex++; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java index f9a9fe309ac..816cdaa4757 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -1172,7 +1172,7 @@ public class XSAttributeChecker { if (max != SchemaSymbols.OCCURRENCE_UNBOUNDED) { // maxOccurLimit is only check in secure mode - if (fSchemaHandler.fSecureProcessing != null) { + if (fSchemaHandler.fSecurityManager != null) { String localName = element.getLocalName(); // The maxOccurs restriction no longer applies to elements @@ -1191,8 +1191,8 @@ public class XSAttributeChecker { if (!optimize) { //Revisit :: IMO this is not right place to check // maxOccurNodeLimit. - int maxOccurNodeLimit = fSchemaHandler.fSecureProcessing.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT); - if (max > maxOccurNodeLimit && !fSchemaHandler.fSecureProcessing.isNoLimit(maxOccurNodeLimit)) { + int maxOccurNodeLimit = fSchemaHandler.fSecurityManager.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT); + if (max > maxOccurNodeLimit && !fSchemaHandler.fSecurityManager.isNoLimit(maxOccurNodeLimit)) { reportSchemaFatalError("MaxOccurLimit", new Object[] {new Integer(maxOccurNodeLimit)}, element); // reset max values in case processing continues on error diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java index 852a09fb87f..d1671179b00 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -194,6 +194,7 @@ public class XSDHandler { /** Property identifier: entity resolver. */ public static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; + /** Property identifier: entity manager. */ protected static final String ENTITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; @@ -214,16 +215,13 @@ public class XSDHandler { protected static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; - private static final String SECURE_PROCESSING = - Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; - /** Property identifier: locale. */ protected static final String LOCALE = Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; - /** Property identifier: Security property manager. */ + /** Property identifier: Security property manager. */ private static final String XML_SECURITY_PROPERTY_MANAGER = - Constants.XML_SECURITY_PROPERTY_MANAGER; + Constants.XML_SECURITY_PROPERTY_MANAGER; protected static final boolean DEBUG_NODE_POOL = false; @@ -243,17 +241,12 @@ public class XSDHandler { // as unlikely as possible to cause collisions. public final static String REDEF_IDENTIFIER = "_fn3dktizrknc9pi"; - // - //protected data that can be accessable by any traverser + //protected data that can be accessible by any traverser protected XSDeclarationPool fDeclPool = null; - /** - *

Security manager in effect.

- * - *

Protected to allow access by any traverser.

- */ - protected XMLSecurityManager fSecureProcessing = null; + // the Security manager in effect. + protected XMLSecurityManager fSecurityManager = null; private String fAccessExternalSchema; private String fAccessExternalDTD; @@ -266,27 +259,28 @@ public class XSDHandler { // XSDocumentInfoRegistry we can easily get the corresponding // XSDocumentInfo object. private boolean registryEmpty = true; - private Map fUnparsedAttributeRegistry = new HashMap(); - private Map fUnparsedAttributeGroupRegistry = new HashMap(); - private Map fUnparsedElementRegistry = new HashMap(); - private Map fUnparsedGroupRegistry = new HashMap(); - private Map fUnparsedIdentityConstraintRegistry = new HashMap(); - private Map fUnparsedNotationRegistry = new HashMap(); - private Map fUnparsedTypeRegistry = new HashMap(); + private Map fUnparsedAttributeRegistry = new HashMap<>(); + private Map fUnparsedAttributeGroupRegistry = new HashMap<>(); + private Map fUnparsedElementRegistry = new HashMap<>(); + private Map fUnparsedGroupRegistry = new HashMap<>(); + private Map fUnparsedIdentityConstraintRegistry = new HashMap<>(); + private Map fUnparsedNotationRegistry = new HashMap<>(); + private Map fUnparsedTypeRegistry = new HashMap<>(); // Compensation for the above maps to locate XSDocumentInfo, // Since we may take Schema Element directly, so can not get the // corresponding XSDocumentInfo object just using above maps. - private Map fUnparsedAttributeRegistrySub = new HashMap(); - private Map fUnparsedAttributeGroupRegistrySub = new HashMap(); - private Map fUnparsedElementRegistrySub = new HashMap(); - private Map fUnparsedGroupRegistrySub = new HashMap(); - private Map fUnparsedIdentityConstraintRegistrySub = new HashMap(); - private Map fUnparsedNotationRegistrySub = new HashMap(); - private Map fUnparsedTypeRegistrySub = new HashMap(); + private Map fUnparsedAttributeRegistrySub = new HashMap<>(); + private Map fUnparsedAttributeGroupRegistrySub = new HashMap<>(); + private Map fUnparsedElementRegistrySub = new HashMap<>(); + private Map fUnparsedGroupRegistrySub = new HashMap<>(); + private Map fUnparsedIdentityConstraintRegistrySub = new HashMap<>(); + private Map fUnparsedNotationRegistrySub = new HashMap<>(); + private Map fUnparsedTypeRegistrySub = new HashMap<>(); // Stores XSDocumentInfo (keyed by component name), to check for duplicate // components declared within the same xsd document - private Map fUnparsedRegistriesExt[] = new HashMap[] { + @SuppressWarnings("unchecked") + private Map fUnparsedRegistriesExt[] = new HashMap[] { null, null, // ATTRIBUTE_TYPE null, // ATTRIBUTEGROUP_TYPE @@ -300,17 +294,19 @@ public class XSDHandler { // this map is keyed on by XSDocumentInfo objects. Its values // are Vectors containing the XSDocumentInfo objects d, // ed or d by the key XSDocumentInfo. - private Map fDependencyMap = new HashMap(); + private Map> fDependencyMap = new HashMap<>(); // this map is keyed on by a target namespace. Its values // are Vectors containing namespaces imported by schema documents // with the key target namespace. - // if an imprted schema has absent namespace, the value "null" is stored. - private Map fImportMap = new HashMap(); + // if an imported schema has absent namespace, the value "null" is stored. + private Map fImportMap = new HashMap<> (); + // all namespaces that imports other namespaces // if the importing schema has absent namespace, empty string is stored. // (because the key of a map can't be null.) - private Vector fAllTNSs = new Vector(); + private Vector fAllTNSs = new Vector<>(); + // stores instance document mappings between namespaces and schema hints private Map fLocationPairs = null; @@ -333,7 +329,7 @@ public class XSDHandler { if(ele.getOwnerDocument() instanceof com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM){ documentURI = ((com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI(); } - return documentURI != null ? documentURI : (String) fDoc2SystemId.get(ele); + return documentURI != null ? documentURI : fDoc2SystemId.get(ele); } // This vector stores strings which are combinations of the @@ -341,11 +337,11 @@ public class XSDHandler { // schema document. This combination is used so that the user's // EntityResolver can provide a consistent way of identifying a // schema document that is included in multiple other schemas. - private Map fTraversed = new HashMap(); + private Map fTraversed = new HashMap<>(); // this map contains a mapping from Schema Element to its systemId // this is useful to resolve a uri relative to the referring document - private Map fDoc2SystemId = new HashMap(); + private Map fDoc2SystemId = new HashMap<>(); // the primary XSDocumentInfo we were called to parse private XSDocumentInfo fRoot = null; @@ -387,7 +383,15 @@ public class XSDHandler { // the XMLErrorReporter private XMLErrorReporter fErrorReporter; - private XMLEntityResolver fEntityResolver; + + // the XMLErrorHandler + private XMLErrorHandler fErrorHandler; + + // the Locale + private Locale fLocale; + + // the XMLEntityManager + private XMLEntityResolver fEntityManager; // the XSAttributeChecker private XSAttributeChecker fAttributeChecker; @@ -404,6 +408,9 @@ public class XSDHandler { // the Grammar Pool private XMLGrammarPool fGrammarPool; + // the security property manager + private XMLSecurityPropertyManager fSecurityPropertyMgr = null; + //************ Traversers ********** XSDAttributeGroupTraverser fAttributeGroupTraverser; XSDAttributeTraverser fAttributeTraverser; @@ -638,7 +645,7 @@ public class XSDHandler { // for all grammars with s for (int i = fAllTNSs.size() - 1; i >= 0; i--) { // get its target namespace - String tns = (String)fAllTNSs.elementAt(i); + String tns = fAllTNSs.elementAt(i); // get all namespaces it imports Vector ins = (Vector)fImportMap.get(tns); // get the grammar @@ -696,12 +703,13 @@ public class XSDHandler { fAnnotationValidator.setFeature(VALIDATION, true); fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true); fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter); + /** set security manager and XML Security Property Manager **/ + fAnnotationValidator.setProperty(SECURITY_MANAGER, (fSecurityManager != null) ? fSecurityManager : new XMLSecurityManager(true)); + fAnnotationValidator.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); /** Set error handler. **/ - XMLErrorHandler errorHandler = fErrorReporter.getErrorHandler(); - fAnnotationValidator.setProperty(ERROR_HANDLER, (errorHandler != null) ? errorHandler : new DefaultErrorHandler()); + fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler()); /** Set locale. **/ - Locale locale = fErrorReporter.getLocale(); - fAnnotationValidator.setProperty(LOCALE, locale); + fAnnotationValidator.setProperty(LOCALE, fLocale); } /** @@ -880,10 +888,10 @@ public class XSDHandler { // store the document and its location // REVISIT: don't expose the DOM tree - sg.addDocument(null, (String)fDoc2SystemId.get(currSchemaInfo.fSchemaElement)); + sg.addDocument(null, fDoc2SystemId.get(currSchemaInfo.fSchemaElement)); fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo); - Vector dependencies = new Vector(); + Vector dependencies = new Vector<>(); Element rootNode = schemaRoot; Element newSchemaRoot = null; @@ -1334,9 +1342,9 @@ public class XSDHandler { } // end for // now we're done with this one! - DOMUtil.setHidden(currDoc, fHiddenNodes); + DOMUtil.setHidden(currDoc, fHiddenNodes); // now add the schemas this guy depends on - Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc); + Vector currSchemaDepends = fDependencyMap.get(currSchemaDoc); for (int i = 0; i < currSchemaDepends.size(); i++) { schemasToProcess.push(currSchemaDepends.elementAt(i)); } @@ -1466,7 +1474,7 @@ public class XSDHandler { DOMUtil.setHidden(currDoc, fHiddenNodes); // now add the schemas this guy depends on - Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc); + Vector currSchemaDepends = fDependencyMap.get(currSchemaDoc); for (int i = 0; i < currSchemaDepends.size(); i++) { schemasToProcess.push(currSchemaDepends.elementAt(i)); } @@ -1915,7 +1923,7 @@ public class XSDHandler { } public String schemaDocument2SystemId(XSDocumentInfo schemaDoc) { - return (String)fDoc2SystemId.get(schemaDoc.fSchemaElement); + return fDoc2SystemId.get(schemaDoc.fSchemaElement); } // This method determines whether there is a group @@ -2044,7 +2052,7 @@ public class XSDHandler { XMLInputSource schemaSource = null; try { Map pairs = usePairs ? fLocationPairs : Collections.emptyMap(); - schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver); + schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager); } catch (IOException ex) { if (mustResolve) { @@ -2097,7 +2105,7 @@ public class XSDHandler { XMLInputSource schemaSource = null; try { Map pairs = usePairs ? fLocationPairs : Collections.emptyMap(); - schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver); + schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager); } catch (IOException ex) { if (mustResolve) { @@ -2152,7 +2160,7 @@ public class XSDHandler { if (referType != XSDDescription.CONTEXT_PREPARSE){ schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); key = new XSDKey(schemaId, referType, schemaNamespace); - if((schemaElement = (Element)fTraversed.get(key)) != null) { + if((schemaElement = fTraversed.get(key)) != null) { fLastSchemaWasDuplicate = true; return schemaElement; } @@ -2211,7 +2219,7 @@ public class XSDHandler { if (referType != XSDDescription.CONTEXT_PREPARSE) { schemaId = XMLEntityManager.expandSystemId(inputSource.getSystemId(), schemaSource.getBaseSystemId(), false); key = new XSDKey(schemaId, referType, schemaNamespace); - if ((schemaElement = (Element) fTraversed.get(key)) != null) { + if ((schemaElement = fTraversed.get(key)) != null) { fLastSchemaWasDuplicate = true; return schemaElement; } @@ -2238,9 +2246,8 @@ public class XSDHandler { namespacePrefixes = true; // If this is a Xerces SAX parser set the security manager if there is one if (parser instanceof SAXParser) { - Object securityManager = fSchemaParser.getProperty(SECURITY_MANAGER); - if (securityManager != null) { - parser.setProperty(SECURITY_MANAGER, securityManager); + if (fSecurityManager != null) { + parser.setProperty(SECURITY_MANAGER, fSecurityManager); } } } @@ -2347,7 +2354,7 @@ public class XSDHandler { } if (isDocument) { key = new XSDKey(schemaId, referType, schemaNamespace); - if ((schemaElement = (Element) fTraversed.get(key)) != null) { + if ((schemaElement = fTraversed.get(key)) != null) { fLastSchemaWasDuplicate = true; return schemaElement; } @@ -2402,7 +2409,7 @@ public class XSDHandler { } if (isDocument) { key = new XSDKey(schemaId, referType, schemaNamespace); - if ((schemaElement = (Element) fTraversed.get(key)) != null) { + if ((schemaElement = fTraversed.get(key)) != null) { fLastSchemaWasDuplicate = true; return schemaElement; } @@ -3502,40 +3509,21 @@ public class XSDHandler { // set symbol table fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE); - fSecureProcessing = null; - if( componentManager!=null ) { - fSecureProcessing = (XMLSecurityManager) componentManager.getProperty(SECURE_PROCESSING, null); - } + // set security manager + fSecurityManager = (XMLSecurityManager) componentManager.getProperty(SECURITY_MANAGER, null); + + //set entity manager + fEntityManager = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER); //set entity resolver - fEntityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER); XMLEntityResolver er = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER); if (er != null) fSchemaParser.setEntityResolver(er); // set error reporter - fErrorReporter = - (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); - try { - XMLErrorHandler currErrorHandler = fErrorReporter.getErrorHandler(); - // Setting a parser property can be much more expensive - // than checking its value. Don't set the ERROR_HANDLER - // or LOCALE properties unless they've actually changed. - if (currErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) { - fSchemaParser.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler()); - if (fAnnotationValidator != null) { - fAnnotationValidator.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler()); - } - } - Locale currentLocale = fErrorReporter.getLocale(); - if (currentLocale != fSchemaParser.getProperty(LOCALE)) { - fSchemaParser.setProperty(LOCALE, currentLocale); - if (fAnnotationValidator != null) { - fAnnotationValidator.setProperty(LOCALE, currentLocale); - } - } - } - catch (XMLConfigurationException e) {} + fErrorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); + fErrorHandler = fErrorReporter.getErrorHandler(); + fLocale = fErrorReporter.getLocale(); fValidateAnnotations = componentManager.getFeature(VALIDATE_ANNOTATIONS, false); fHonourAllSchemaLocations = componentManager.getFeature(HONOUR_ALL_SCHEMALOCATIONS, false); @@ -3543,56 +3531,66 @@ public class XSDHandler { fTolerateDuplicates = componentManager.getFeature(TOLERATE_DUPLICATES, false); try { - fSchemaParser.setFeature( - CONTINUE_AFTER_FATAL_ERROR, - fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR)); - } catch (XMLConfigurationException e) { + // Setting a parser property can be much more expensive + // than checking its value. Don't set the ERROR_HANDLER + // or LOCALE properties unless they've actually changed. + if (fErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) { + fSchemaParser.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler()); + if (fAnnotationValidator != null) { + fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler()); + } + } + if (fLocale != fSchemaParser.getProperty(LOCALE)) { + fSchemaParser.setProperty(LOCALE, fLocale); + if (fAnnotationValidator != null) { + fAnnotationValidator.setProperty(LOCALE, fLocale); + } + } } + catch (XMLConfigurationException e) {} + + try { + fSchemaParser.setFeature(CONTINUE_AFTER_FATAL_ERROR, fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR)); + } catch (XMLConfigurationException e) {} try { if (componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false)) { fSchemaParser.setFeature(ALLOW_JAVA_ENCODINGS, true); } - } catch (XMLConfigurationException e) { - } + } catch (XMLConfigurationException e) {} + try { if (componentManager.getFeature(STANDARD_URI_CONFORMANT_FEATURE, false)) { fSchemaParser.setFeature(STANDARD_URI_CONFORMANT_FEATURE, true); } - } catch (XMLConfigurationException e) { - } + } catch (XMLConfigurationException e) {} try { - fGrammarPool = - (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL); + fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL); } catch (XMLConfigurationException e) { fGrammarPool = null; } + // security features try { if (componentManager.getFeature(DISALLOW_DOCTYPE, false)) { fSchemaParser.setFeature(DISALLOW_DOCTYPE, true); } - } catch (XMLConfigurationException e) { - } + } catch (XMLConfigurationException e) {} + try { - Object security = componentManager.getProperty(SECURITY_MANAGER, null); - if (security != null){ - fSchemaParser.setProperty(SECURITY_MANAGER, security); + if (fSecurityManager != null) { + fSchemaParser.setProperty(SECURITY_MANAGER, fSecurityManager); } - } catch (XMLConfigurationException e) { - } + } catch (XMLConfigurationException e) {} + + fSecurityPropertyMgr = (XMLSecurityPropertyManager) componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER); - XMLSecurityPropertyManager securityPropertyMgr = (XMLSecurityPropertyManager) - componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER); //Passing on the setting to the parser - fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, securityPropertyMgr); + fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); - fAccessExternalDTD = securityPropertyMgr.getValue( - XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD); - - fAccessExternalSchema = securityPropertyMgr.getValue( - XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA); + fAccessExternalDTD = fSecurityPropertyMgr.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD); + fAccessExternalSchema = fSecurityPropertyMgr.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA); } // reset(XMLComponentManager) @@ -4051,7 +4049,7 @@ public class XSDHandler { so long as there's some include/import/redefine path amongst them. If they rver reverse this decision the code's right here though... - neilg // now look in fDependencyMap to see if this is reachable - if(((Vector)fDependencyMap.get(currSchema)).contains(declDocInfo)) { + if((fDependencyMap.get(currSchema)).contains(declDocInfo)) { return declDocInfo; } // obviously the requesting doc didn't include, redefine or @@ -4072,9 +4070,9 @@ public class XSDHandler { if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) { // make it visible DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes); - Vector dependingSchemas = (Vector)fDependencyMap.get(startSchema); + Vector dependingSchemas = fDependencyMap.get(startSchema); for (int i = 0; i < dependingSchemas.size(); i++) { - setSchemasVisible((XSDocumentInfo)dependingSchemas.elementAt(i)); + setSchemasVisible(dependingSchemas.elementAt(i)); } } // if it's visible already than so must be its children @@ -4107,7 +4105,7 @@ public class XSDHandler { ElementImpl ele = (ElementImpl)e; // get system id from document object Document doc = ele.getOwnerDocument(); - String sid = (String)fDoc2SystemId.get(DOMUtil.getRoot(doc)); + String sid = fDoc2SystemId.get(DOMUtil.getRoot(doc)); // line/column numbers are stored in the element node int line = ele.getLineNumber(); int column = ele.getColumnNumber(); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java index 459067067a1..3c4dd4f810e 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -52,7 +52,6 @@ import com.sun.org.apache.xerces.internal.util.FeatureState; import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings; import com.sun.org.apache.xerces.internal.util.PropertyState; import com.sun.org.apache.xerces.internal.util.SymbolTable; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; @@ -166,59 +165,57 @@ public class XML11Configuration extends ParserConfigurationSettings protected static final String USE_GRAMMAR_POOL_ONLY = Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; - // feature identifiers + // feature identifiers - /** Feature identifier: validation. */ - protected static final String VALIDATION = - Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; + /** Feature identifier: validation. */ + protected static final String VALIDATION = + Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; - /** Feature identifier: namespaces. */ - protected static final String NAMESPACES = - Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE; + /** Feature identifier: namespaces. */ + protected static final String NAMESPACES = + Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE; - /** Feature identifier: external general entities. */ - protected static final String EXTERNAL_GENERAL_ENTITIES = - Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE; + /** Feature identifier: external general entities. */ + protected static final String EXTERNAL_GENERAL_ENTITIES = + Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE; - /** Feature identifier: external parameter entities. */ - protected static final String EXTERNAL_PARAMETER_ENTITIES = - Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE; + /** Feature identifier: external parameter entities. */ + protected static final String EXTERNAL_PARAMETER_ENTITIES = + Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE; - /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ - protected static final String IGNORE_XSI_TYPE = - Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; - /** Feature identifier: whether to ignore ID/IDREF errors */ - protected static final String ID_IDREF_CHECKING = - Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; - /** Feature identifier: whether to ignore unparsed entity errors */ - protected static final String UNPARSED_ENTITY_CHECKING = - Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; - /** Feature identifier: whether to ignore identity constraint errors */ - protected static final String IDENTITY_CONSTRAINT_CHECKING = - Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; // property identifiers + /** Property identifier: xml string. */ + protected static final String XML_STRING = + Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY; - /** Property identifier: xml string. */ - protected static final String XML_STRING = - Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY; + /** Property identifier: symbol table. */ + protected static final String SYMBOL_TABLE = + Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; - /** Property identifier: symbol table. */ - protected static final String SYMBOL_TABLE = - Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; - - /** Property identifier: error handler. */ - protected static final String ERROR_HANDLER = - Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; - - /** Property identifier: entity resolver. */ - protected static final String ENTITY_RESOLVER = - Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; + /** Property identifier: error handler. */ + protected static final String ERROR_HANDLER = + Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; + /** Property identifier: entity resolver. */ + protected static final String ENTITY_RESOLVER = + Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; /** Property identifier: XML Schema validator. */ protected static final String SCHEMA_VALIDATOR = @@ -232,8 +229,6 @@ public class XML11Configuration extends ParserConfigurationSettings protected static final String SCHEMA_NONS_LOCATION = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION; - // property identifiers - /** Property identifier: error reporter. */ protected static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; @@ -313,33 +308,33 @@ public class XML11Configuration extends ParserConfigurationSettings // Data // - protected SymbolTable fSymbolTable; + protected SymbolTable fSymbolTable; protected XMLInputSource fInputSource; protected ValidationManager fValidationManager; - protected XMLVersionDetector fVersionDetector; + protected XMLVersionDetector fVersionDetector; protected XMLLocator fLocator; - protected Locale fLocale; + protected Locale fLocale; - /** XML 1.0 Components. */ - protected ArrayList fComponents; + /** XML 1.0 Components. */ + protected ArrayList fComponents; - /** XML 1.1. Components. */ - protected ArrayList fXML11Components = null; + /** XML 1.1. Components. */ + protected ArrayList fXML11Components = null; - /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */ - protected ArrayList fCommonComponents = null; + /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */ + protected ArrayList fCommonComponents = null; - /** The document handler. */ - protected XMLDocumentHandler fDocumentHandler; + /** The document handler. */ + protected XMLDocumentHandler fDocumentHandler; - /** The DTD handler. */ - protected XMLDTDHandler fDTDHandler; + /** The DTD handler. */ + protected XMLDTDHandler fDTDHandler; - /** The DTD content model handler. */ - protected XMLDTDContentModelHandler fDTDContentModelHandler; + /** The DTD content model handler. */ + protected XMLDTDContentModelHandler fDTDContentModelHandler; - /** Last component in the document pipeline */ - protected XMLDocumentSource fLastComponent; + /** Last component in the document pipeline */ + protected XMLDocumentSource fLastComponent; /** * True if a parse is in progress. This state is needed because @@ -477,15 +472,15 @@ public class XML11Configuration extends ParserConfigurationSettings // create a vector to hold all the components in use // XML 1.0 specialized components - fComponents = new ArrayList(); + fComponents = new ArrayList<>(); // XML 1.1 specialized components - fXML11Components = new ArrayList(); + fXML11Components = new ArrayList<>(); // Common components for XML 1.1. and XML 1.0 - fCommonComponents = new ArrayList(); + fCommonComponents = new ArrayList<>(); // create table for features and properties - fFeatures = new HashMap(); - fProperties = new HashMap(); + fFeatures = new HashMap<>(); + fProperties = new HashMap<>(); // add default recognized features final String[] recognizedFeatures = @@ -580,35 +575,35 @@ public class XML11Configuration extends ParserConfigurationSettings } fEntityManager = new XMLEntityManager(); - fProperties.put(ENTITY_MANAGER, fEntityManager); + fProperties.put(ENTITY_MANAGER, fEntityManager); addCommonComponent(fEntityManager); fErrorReporter = new XMLErrorReporter(); fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner()); - fProperties.put(ERROR_REPORTER, fErrorReporter); + fProperties.put(ERROR_REPORTER, fErrorReporter); addCommonComponent(fErrorReporter); fNamespaceScanner = new XMLNSDocumentScannerImpl(); - fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner); + fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner); addComponent((XMLComponent) fNamespaceScanner); fDTDScanner = new XMLDTDScannerImpl(); - fProperties.put(DTD_SCANNER, fDTDScanner); + fProperties.put(DTD_SCANNER, fDTDScanner); addComponent((XMLComponent) fDTDScanner); fDTDProcessor = new XMLDTDProcessor(); - fProperties.put(DTD_PROCESSOR, fDTDProcessor); + fProperties.put(DTD_PROCESSOR, fDTDProcessor); addComponent((XMLComponent) fDTDProcessor); fDTDValidator = new XMLNSDTDValidator(); - fProperties.put(DTD_VALIDATOR, fDTDValidator); + fProperties.put(DTD_VALIDATOR, fDTDValidator); addComponent(fDTDValidator); fDatatypeValidatorFactory = DTDDVFactory.getInstance(); - fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory); + fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory); fValidationManager = new ValidationManager(); - fProperties.put(VALIDATION_MANAGER, fValidationManager); + fProperties.put(VALIDATION_MANAGER, fValidationManager); fVersionDetector = new XMLVersionDetector(); @@ -935,20 +930,20 @@ public class XML11Configuration extends ParserConfigurationSettings // forward to every XML 1.0 component int count = fComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fComponents.get(i); + XMLComponent c = fComponents.get(i); c.setFeature(featureId, state); } // forward it to common components count = fCommonComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fCommonComponents.get(i); + XMLComponent c = fCommonComponents.get(i); c.setFeature(featureId, state); } // forward to every XML 1.1 component count = fXML11Components.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fXML11Components.get(i); + XMLComponent c = fXML11Components.get(i); try{ c.setFeature(featureId, state); } @@ -996,19 +991,19 @@ public class XML11Configuration extends ParserConfigurationSettings // forward to every XML 1.0 component int count = fComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fComponents.get(i); + XMLComponent c = fComponents.get(i); c.setProperty(propertyId, value); } // forward it to every common Component count = fCommonComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fCommonComponents.get(i); + XMLComponent c = fCommonComponents.get(i); c.setProperty(propertyId, value); } // forward it to every XML 1.1 component count = fXML11Components.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fXML11Components.get(i); + XMLComponent c = fXML11Components.get(i); try{ c.setProperty(propertyId, value); } @@ -1034,7 +1029,7 @@ public class XML11Configuration extends ParserConfigurationSettings protected void reset() throws XNIException { int count = fComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fComponents.get(i); + XMLComponent c = fComponents.get(i); c.reset(this); } @@ -1047,7 +1042,7 @@ public class XML11Configuration extends ParserConfigurationSettings // reset common components int count = fCommonComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fCommonComponents.get(i); + XMLComponent c = fCommonComponents.get(i); c.reset(this); } @@ -1061,7 +1056,7 @@ public class XML11Configuration extends ParserConfigurationSettings // reset every component int count = fXML11Components.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fXML11Components.get(i); + XMLComponent c = fXML11Components.get(i); c.reset(this); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java index f4e29a3a856..bdd0750d0fa 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java @@ -51,7 +51,7 @@ public final class HTTPInputSource extends XMLInputSource { protected boolean fFollowRedirects = true; /** HTTP request properties. **/ - protected Map fHTTPRequestProperties = new HashMap(); + protected Map fHTTPRequestProperties = new HashMap<>(); // // Constructors @@ -159,7 +159,7 @@ public final class HTTPInputSource extends XMLInputSource { * been set */ public String getHTTPRequestProperty(String key) { - return (String) fHTTPRequestProperties.get(key); + return fHTTPRequestProperties.get(key); } // getHTTPRequestProperty(String):String /** @@ -172,7 +172,7 @@ public final class HTTPInputSource extends XMLInputSource { * @return an iterator for the request properties this * input source contains */ - public Iterator getHTTPRequestProperties() { + public Iterator> getHTTPRequestProperties() { return fHTTPRequestProperties.entrySet().iterator(); } // getHTTPRequestProperties():Iterator diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd b/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd new file mode 100644 index 00000000000..872033f5d1a --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd @@ -0,0 +1,7 @@ + + + + Testapp for XSD annotation issue + This is an XSD annotation, just for the sake of it. + + diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java b/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java new file mode 100644 index 00000000000..f8a5e62ac55 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 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 validation; + +import java.io.File; + +import javax.xml.XMLConstants; +import javax.xml.validation.SchemaFactory; + +import org.testng.annotations.Test; + +/* + * @summary Test Schema creation + * @bug 8149915 + */ +public class SchemaTest { + + /* + * @bug 8149915 + * Verifies that the annotation validator is initialized with the security manager for schema + * creation with http://apache.org/xml/features/validate-annotations=true. + */ + @Test + public void testValidation() throws Exception { + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + factory.setFeature("http://apache.org/xml/features/validate-annotations", true); + factory.newSchema(new File(getClass().getResource("Bug8149915.xsd").getFile())); + } +} From 0698afcea9e69524f7169f56686ab68662042d1b Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Mon, 22 Feb 2016 16:17:25 -0800 Subject: [PATCH 069/311] 8149600: javac, remove unused options, step 2 Reviewed-by: jjg, mcimadamore --- .../com/sun/tools/javac/comp/Attr.java | 14 +- .../com/sun/tools/javac/comp/Check.java | 14 +- .../com/sun/tools/javac/jvm/ClassWriter.java | 44 +----- .../classes/com/sun/tools/javac/jvm/Gen.java | 140 +----------------- .../sun/tools/javac/main/JavaCompiler.java | 105 ++++--------- .../com/sun/tools/javac/main/Option.java | 2 +- .../tools/javac/resources/compiler.properties | 14 -- .../tools/javac/resources/javac.properties | 8 - .../com/sun/tools/javah/JavahTask.java | 10 +- .../test/tools/javac/6257443/T6257443.java | 10 +- .../test/tools/javac/6521805/T6521805a.java | 22 --- .../test/tools/javac/6521805/T6521805a_1.out | 2 - .../test/tools/javac/6521805/T6521805a_2.out | 2 - .../api/taskListeners/EventsBalancedTest.java | 4 +- .../tools/javac/diags/CheckResourceKeys.java | 9 +- .../tools/javac/diags/examples.not-yet.txt | 3 - .../examples/WarnSyntheticNameConflict.java | 34 ----- 17 files changed, 53 insertions(+), 384 deletions(-) delete mode 100644 langtools/test/tools/javac/6521805/T6521805a.java delete mode 100644 langtools/test/tools/javac/6521805/T6521805a_1.out delete mode 100644 langtools/test/tools/javac/6521805/T6521805a_2.out delete mode 100644 langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index f62d866bacb..efa57d8b854 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -155,8 +155,6 @@ public class Attr extends JCTree.Visitor { allowDefaultMethods = source.allowDefaultMethods(); allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); sourceName = source.name; - relax = (options.isSet("-retrofit") || - options.isSet("-relax")); useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning"); statInfo = new ResultInfo(KindSelector.NIL, Type.noType); @@ -168,10 +166,6 @@ public class Attr extends JCTree.Visitor { recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext); } - /** Switch: relax some constraints for retrofit mode. - */ - boolean relax; - /** Switch: support target-typing inference */ boolean allowPoly; @@ -1025,8 +1019,7 @@ public class Attr extends JCTree.Visitor { log.error(tree.pos(), "default.allowed.in.intf.annotation.member"); } - if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 && - !relax) + if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0) log.error(tree.pos(), "missing.meth.body.or.decl.abstract"); } else if ((tree.sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) { if ((owner.flags() & INTERFACE) != 0) { @@ -4384,8 +4377,7 @@ public class Attr extends JCTree.Visitor { // If this is a non-abstract class, check that it has no abstract // methods or unimplemented methods of an implemented interface. if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) { - if (!relax) - chk.checkAllDefined(tree.pos(), c); + chk.checkAllDefined(tree.pos(), c); } if ((c.flags() & ANNOTATION) != 0) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index a130f220926..357e44b1913 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -81,8 +81,6 @@ public class Check { private final Types types; private final TypeAnnotations typeAnnotations; private final JCDiagnostic.Factory diags; - private boolean warnOnSyntheticConflicts; - private boolean suppressAbortOnBadClassFile; private final JavaFileManager fileManager; private final Source source; private final Profile profile; @@ -130,8 +128,6 @@ public class Check { allowStrictMethodClashCheck = source.allowStrictMethodClashCheck(); allowPrivateSafeVarargs = source.allowPrivateSafeVarargs(); allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation(); - warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts"); - suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile"); warnOnAccessToSensitiveMembers = options.isSet("warnOnAccessToSensitiveMembers"); Target target = Target.instance(context); @@ -269,8 +265,7 @@ public class Check { */ public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, "cant.access", ex.sym, ex.getDetailValue()); - if (ex instanceof ClassFinder.BadClassFile - && !suppressAbortOnBadClassFile) throw new Abort(); + if (ex instanceof ClassFinder.BadClassFile) throw new Abort(); else return syms.errType; } @@ -2632,12 +2627,7 @@ public class Check { */ private void syntheticError(DiagnosticPosition pos, Symbol sym) { if (!sym.type.isErroneous()) { - if (warnOnSyntheticConflicts) { - log.warning(pos, "synthetic.name.conflict", sym, sym.location()); - } - else { - log.error(pos, "synthetic.name.conflict", sym, sym.location()); - } + log.error(pos, "synthetic.name.conflict", sym, sym.location()); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 1b1f8a15457..aa161b5ec76 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -72,18 +72,6 @@ public class ClassWriter extends ClassFile { */ private boolean verbose; - /** Switch: scramble private field names. - */ - private boolean scramble; - - /** Switch: scramble all field names. - */ - private boolean scrambleAll; - - /** Switch: retrofit mode. - */ - private boolean retrofit; - /** Switch: emit source file attribute. */ private boolean emitSourceFile; @@ -184,9 +172,6 @@ public class ClassWriter extends ClassFile { signatureGen = new CWSignatureGenerator(types); verbose = options.isSet(VERBOSE); - scramble = options.isSet("-scramble"); - scrambleAll = options.isSet("-scrambleAll"); - retrofit = options.isSet("-retrofit"); genCrt = options.isSet(XJCOV); debugstackmap = options.isSet("debugstackmap"); @@ -491,26 +476,11 @@ public class ClassWriter extends ClassFile { putChar(poolbuf, poolCountIdx, pool.pp); } - /** Given a field, return its name. - */ - Name fieldName(Symbol sym) { - if (scramble && (sym.flags() & PRIVATE) != 0 || - scrambleAll && (sym.flags() & (PROTECTED | PUBLIC)) == 0) - return names.fromString("_$" + sym.name.getIndex()); - else - return sym.name; - } - /** Given a symbol, return its name-and-type. */ NameAndType nameType(Symbol sym) { - return new NameAndType(fieldName(sym), - retrofit - ? sym.erasure(types) - : sym.externalType(types), types); - // if we retrofit, then the NameAndType has been read in as is - // and no change is necessary. If we compile normally, the - // NameAndType is generated from a symbol reference, and the + return new NameAndType(sym.name, sym.externalType(types), types); + // the NameAndType is generated from a symbol reference, and the // adjustment of adding an additional this$n parameter needs to be made. } @@ -1055,10 +1025,10 @@ public class ClassWriter extends ClassFile { databuf.appendChar(flags); if (dumpFieldModifiers) { PrintWriter pw = log.getWriter(Log.WriterKind.ERROR); - pw.println("FIELD " + fieldName(v)); + pw.println("FIELD " + v.name); pw.println("---" + flagNames(v.flags())); } - databuf.appendChar(pool.put(fieldName(v))); + databuf.appendChar(pool.put(v.name)); databuf.appendChar(pool.put(typeSig(v.erasure(types)))); int acountIdx = beginAttrs(); int acount = 0; @@ -1079,10 +1049,10 @@ public class ClassWriter extends ClassFile { databuf.appendChar(flags); if (dumpMethodModifiers) { PrintWriter pw = log.getWriter(Log.WriterKind.ERROR); - pw.println("METHOD " + fieldName(m)); + pw.println("METHOD " + m.name); pw.println("---" + flagNames(m.flags())); } - databuf.appendChar(pool.put(fieldName(m))); + databuf.appendChar(pool.put(m.name)); databuf.appendChar(pool.put(typeSig(m.externalType(types)))); int acountIdx = beginAttrs(); int acount = 0; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index 83ed8adbef5..6280b8d5cf4 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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,25 +120,11 @@ public class Gen extends JCTree.Visitor { : options.isSet(G_CUSTOM, "vars"); genCrt = options.isSet(XJCOV); debugCode = options.isSet("debugcode"); - allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic"); allowBetterNullChecks = target.hasObjects(); pool = new Pool(types); // ignore cldc because we cannot have both stackmap formats this.stackMap = StackMapFormat.JSR202; - - // by default, avoid jsr's for simple finalizers - int setjsrlimit = 50; - String jsrlimitString = options.get("jsrlimit"); - if (jsrlimitString != null) { - try { - setjsrlimit = Integer.parseInt(jsrlimitString); - } catch (NumberFormatException ex) { - // ignore ill-formed numbers for jsrlimit - } - } - this.jsrlimit = setjsrlimit; - this.useJsrLocally = false; // reset in visitTry annotate = Annotate.instance(context); } @@ -148,19 +134,8 @@ public class Gen extends JCTree.Visitor { private final boolean varDebugInfo; private final boolean genCrt; private final boolean debugCode; - private final boolean allowInvokedynamic; private final boolean allowBetterNullChecks; - /** Default limit of (approximate) size of finalizer to inline. - * Zero means always use jsr. 100 or greater means never use - * jsr. - */ - private final int jsrlimit; - - /** True if jsr is used. - */ - private boolean useJsrLocally; - /** Code buffer, set by genMethod. */ private Code code; @@ -1339,31 +1314,11 @@ public class Gen extends JCTree.Visitor { // in a new environment which calls the finally block if there is one. final Env tryEnv = env.dup(tree, new GenContext()); final Env oldEnv = env; - if (!useJsrLocally) { - useJsrLocally = - (stackMap == StackMapFormat.NONE) && - (jsrlimit <= 0 || - jsrlimit < 100 && - estimateCodeComplexity(tree.finalizer)>jsrlimit); - } tryEnv.info.finalize = new GenFinalizer() { void gen() { - if (useJsrLocally) { - if (tree.finalizer != null) { - Code.State jsrState = code.state.dup(); - jsrState.push(Code.jsrReturnValue); - tryEnv.info.cont = - new Chain(code.emitJump(jsr), - tryEnv.info.cont, - jsrState); - } - Assert.check(tryEnv.info.gaps.length() % 2 == 0); - tryEnv.info.gaps.append(code.curCP()); - } else { - Assert.check(tryEnv.info.gaps.length() % 2 == 0); - tryEnv.info.gaps.append(code.curCP()); - genLast(); - } + Assert.check(tryEnv.info.gaps.length() % 2 == 0); + tryEnv.info.gaps.append(code.curCP()); + genLast(); } void genLast() { if (tree.finalizer != null) @@ -1568,93 +1523,6 @@ public class Gen extends JCTree.Visitor { } } - /** Very roughly estimate the number of instructions needed for - * the given tree. - */ - int estimateCodeComplexity(JCTree tree) { - if (tree == null) return 0; - class ComplexityScanner extends TreeScanner { - int complexity = 0; - public void scan(JCTree tree) { - if (complexity > jsrlimit) return; - super.scan(tree); - } - public void visitClassDef(JCClassDecl tree) {} - public void visitDoLoop(JCDoWhileLoop tree) - { super.visitDoLoop(tree); complexity++; } - public void visitWhileLoop(JCWhileLoop tree) - { super.visitWhileLoop(tree); complexity++; } - public void visitForLoop(JCForLoop tree) - { super.visitForLoop(tree); complexity++; } - public void visitSwitch(JCSwitch tree) - { super.visitSwitch(tree); complexity+=5; } - public void visitCase(JCCase tree) - { super.visitCase(tree); complexity++; } - public void visitSynchronized(JCSynchronized tree) - { super.visitSynchronized(tree); complexity+=6; } - public void visitTry(JCTry tree) - { super.visitTry(tree); - if (tree.finalizer != null) complexity+=6; } - public void visitCatch(JCCatch tree) - { super.visitCatch(tree); complexity+=2; } - public void visitConditional(JCConditional tree) - { super.visitConditional(tree); complexity+=2; } - public void visitIf(JCIf tree) - { super.visitIf(tree); complexity+=2; } - // note: for break, continue, and return we don't take unwind() into account. - public void visitBreak(JCBreak tree) - { super.visitBreak(tree); complexity+=1; } - public void visitContinue(JCContinue tree) - { super.visitContinue(tree); complexity+=1; } - public void visitReturn(JCReturn tree) - { super.visitReturn(tree); complexity+=1; } - public void visitThrow(JCThrow tree) - { super.visitThrow(tree); complexity+=1; } - public void visitAssert(JCAssert tree) - { super.visitAssert(tree); complexity+=5; } - public void visitApply(JCMethodInvocation tree) - { super.visitApply(tree); complexity+=2; } - public void visitNewClass(JCNewClass tree) - { scan(tree.encl); scan(tree.args); complexity+=2; } - public void visitNewArray(JCNewArray tree) - { super.visitNewArray(tree); complexity+=5; } - public void visitAssign(JCAssign tree) - { super.visitAssign(tree); complexity+=1; } - public void visitAssignop(JCAssignOp tree) - { super.visitAssignop(tree); complexity+=2; } - public void visitUnary(JCUnary tree) - { complexity+=1; - if (tree.type.constValue() == null) super.visitUnary(tree); } - public void visitBinary(JCBinary tree) - { complexity+=1; - if (tree.type.constValue() == null) super.visitBinary(tree); } - public void visitTypeTest(JCInstanceOf tree) - { super.visitTypeTest(tree); complexity+=1; } - public void visitIndexed(JCArrayAccess tree) - { super.visitIndexed(tree); complexity+=1; } - public void visitSelect(JCFieldAccess tree) - { super.visitSelect(tree); - if (tree.sym.kind == VAR) complexity+=1; } - public void visitIdent(JCIdent tree) { - if (tree.sym.kind == VAR) { - complexity+=1; - if (tree.type.constValue() == null && - tree.sym.owner.kind == TYP) - complexity+=1; - } - } - public void visitLiteral(JCLiteral tree) - { complexity+=1; } - public void visitTree(JCTree tree) {} - public void visitWildcard(JCWildcard tree) { - throw new AssertionError(this.getClass().getName()); - } - } - ComplexityScanner scanner = new ComplexityScanner(); - tree.accept(scanner); - return scanner.complexity; - } - public void visitIf(JCIf tree) { int limit = code.nextreg; Chain thenExit = null; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 40ca702ba82..4f72befa543 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -389,9 +389,6 @@ public class JavaCompiler { verbose = options.isSet(VERBOSE); sourceOutput = options.isSet(PRINTSOURCE); // used to be -s - stubOutput = options.isSet("-stubs"); - relax = options.isSet("-relax"); - printFlat = options.isSet("-printflat"); encoding = options.get(ENCODING); lineDebugInfo = options.isUnset(G_CUSTOM) || options.isSet(G_CUSTOM, "lines"); @@ -447,18 +444,6 @@ public class JavaCompiler { */ public boolean sourceOutput; - /** Emit stub source files rather than class files. - */ - public boolean stubOutput; - - /** Switch: relax some constraints for producing the jsr14 prototype. - */ - boolean relax; - - /** Debug switch: Emit Java sources after inner class flattening. - */ - public boolean printFlat; - /** The encoding to be used for source input. */ public String encoding; @@ -611,7 +596,7 @@ public class JavaCompiler { // where public boolean keepComments = false; protected boolean keepComments() { - return keepComments || sourceOutput || stubOutput; + return keepComments || sourceOutput; } @@ -676,30 +661,6 @@ public class JavaCompiler { } } - /** Emit plain Java source for a class. - * @param env The attribution environment of the outermost class - * containing this class. - * @param cdef The class definition to be printed. - */ - JavaFileObject printSource(Env env, JCClassDecl cdef) throws IOException { - JavaFileObject outFile - = fileManager.getJavaFileForOutput(CLASS_OUTPUT, - cdef.sym.flatname.toString(), - JavaFileObject.Kind.SOURCE, - null); - if (inputFiles.contains(outFile)) { - log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); - return null; - } else { - try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) { - new Pretty(out, true).printUnit(env.toplevel, cdef); - if (verbose) - log.printVerbose("wrote.file", outFile); - } - return outFile; - } - } - /** Generate code and emit a class file for a given class * @param env The attribution environment of the outermost class * containing this class. @@ -720,6 +681,30 @@ public class JavaCompiler { return null; } + /** Emit plain Java source for a class. + * @param env The attribution environment of the outermost class + * containing this class. + * @param cdef The class definition to be printed. + */ + JavaFileObject printSource(Env env, JCClassDecl cdef) throws IOException { + JavaFileObject outFile + = fileManager.getJavaFileForOutput(CLASS_OUTPUT, + cdef.sym.flatname.toString(), + JavaFileObject.Kind.SOURCE, + null); + if (inputFiles.contains(outFile)) { + log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); + return null; + } else { + try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) { + new Pretty(out, true).printUnit(env.toplevel, cdef); + if (verbose) + log.printVerbose("wrote.file", outFile); + } + return outFile; + } + } + /** Compile a source file that has been accessed by the class finder. * @param c The class the source file of which needs to be compiled. */ @@ -897,12 +882,6 @@ public class JavaCompiler { throw new AssertionError("attempt to reuse JavaCompiler"); } - /** - * Set needRootClasses to true, in JavaCompiler subclass constructor - * that want to collect public apis of classes supplied on the command line. - */ - protected boolean needRootClasses = false; - /** * The list of classes explicitly supplied on the command line for compilation. * Not always populated. @@ -966,7 +945,7 @@ public class JavaCompiler { // If generating source, or if tracking public apis, // then remember the classes declared in // the original compilation units listed on the command line. - if (needRootClasses || sourceOutput || stubOutput) { + if (sourceOutput) { ListBuffer cdefs = new ListBuffer<>(); for (JCCompilationUnit unit : roots) { for (List defs = unit.defs; @@ -1275,11 +1254,6 @@ public class JavaCompiler { if (shouldStop(CompileState.FLOW)) return; - if (relax) { - results.add(env); - return; - } - if (verboseCompilePolicy) printNote("[flow " + env.enclClass.sym + "]"); JavaFileObject prev = log.useSource( @@ -1419,9 +1393,9 @@ public class JavaCompiler { TreeMaker localMake = make.forToplevel(env.toplevel); if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF)) { - if (!(stubOutput || sourceOutput || printFlat)) { + if (!(sourceOutput)) { if (shouldStop(CompileState.LOWER)) - return; + return; List pdef = lower.translateTopLevelClass(env, env.tree, localMake); if (pdef.head != null) { Assert.check(pdef.tail.isEmpty()); @@ -1431,19 +1405,6 @@ public class JavaCompiler { return; } - if (stubOutput) { - //emit stub Java source file, only for compilation - //units enumerated explicitly on the command line - JCClassDecl cdef = (JCClassDecl)env.tree; - if (untranslated instanceof JCClassDecl && - rootClasses.contains((JCClassDecl)untranslated) && - ((cdef.mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || - cdef.sym.packge().getQualifiedName() == names.java_lang)) { - results.add(new Pair<>(env, removeMethodBodies(cdef))); - } - return; - } - if (shouldStop(CompileState.TRANSTYPES)) return; @@ -1504,16 +1465,12 @@ public class JavaCompiler { if (shouldStop(CompileState.GENERATE)) return; - boolean usePrintSource = (stubOutput || sourceOutput || printFlat); - for (Pair, JCClassDecl> x: queue) { Env env = x.fst; JCClassDecl cdef = x.snd; if (verboseCompilePolicy) { - printNote("[generate " - + (usePrintSource ? " source" : "code") - + " " + cdef.sym + "]"); + printNote("[generate " + (sourceOutput ? " source" : "code") + " " + cdef.sym + "]"); } if (!taskListener.isEmpty()) { @@ -1526,9 +1483,9 @@ public class JavaCompiler { env.toplevel.sourcefile); try { JavaFileObject file; - if (usePrintSource) + if (sourceOutput) { file = printSource(env, cdef); - else { + } else { if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT) && jniWriter.needsHeader(cdef.sym)) { jniWriter.write(cdef.sym); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index 0a291db707f..4867bdad290 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, 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 diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 795f38032f7..281d8e82656 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -981,10 +981,6 @@ compiler.err.string.const.req=\ compiler.err.synthetic.name.conflict=\ the symbol {0} conflicts with a compiler-synthesized symbol in {1} -# 0: symbol, 1: symbol -compiler.warn.synthetic.name.conflict=\ - the symbol {0} conflicts with a compiler-synthesized symbol in {1} - compiler.err.throws.not.allowed.in.intf.annotation=\ throws clause not allowed in @interface members @@ -1334,16 +1330,6 @@ compiler.misc.verbose.total=\ compiler.misc.verbose.wrote.file=\ [wrote {0}] -## extra output when using -verbose (Retro) -compiler.misc.verbose.retro=\ - [retrofitting {0}] - -compiler.misc.verbose.retro.with=\ - \tretrofitting {0} with {1} - -compiler.misc.verbose.retro.with.list=\ - \tretrofitting {0} with type parameters {1}, supertype {2}, interfaces {3} - ## extra output when using -verbose (code/ClassReader) # 0: string compiler.misc.verbose.loading=\ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties index d64280ab946..7246acf194f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties @@ -124,20 +124,12 @@ javac.opt.nogj=\ Don't accept generics in the language javac.opt.moreinfo=\ Print extended information for type variables -javac.opt.printflat=\ - Print abstract syntax tree after inner class conversion javac.opt.printsearch=\ Print information where classfiles are searched javac.opt.prompt=\ Stop after each error -javac.opt.retrofit=\ - Retrofit existing classfiles with generic types javac.opt.s=\ Emit java sources instead of classfiles -javac.opt.scramble=\ - Scramble private identifiers in bytecode -javac.opt.scrambleall=\ - Scramble package visible identifiers in bytecode javac.opt.version=\ Version information javac.opt.arg.pathname=\ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java index 56b369c8082..789069b49ed 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, 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 @@ -170,12 +170,6 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { } }, - new HiddenOption(false, "-stubs") { - void process(JavahTask task, String opt, String arg) { - // ignored; for backwards compatibility - } - }, - new Option(false, "-v", "-verbose") { void process(JavahTask task, String opt, String arg) { task.verbose = true; @@ -454,8 +448,6 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { if (llni) g = new LLNI(doubleAlign, util); else { -// if (stubs) -// throw new BadArgs("jni.no.stubs"); g = new JNI(util); } diff --git a/langtools/test/tools/javac/6257443/T6257443.java b/langtools/test/tools/javac/6257443/T6257443.java index 5d81ed5d12f..91d3120908f 100644 --- a/langtools/test/tools/javac/6257443/T6257443.java +++ b/langtools/test/tools/javac/6257443/T6257443.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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,13 +31,7 @@ * * @clean foo.package-info * - * @compile -XD-printflat package-info.java - * @run main/othervm T6257443 -no foo/package-info.class - * - * @compile -XD-stubs package-info.java - * @run main/othervm T6257443 -no foo/package-info.class - * - * @compile -XD-printsource package-info.java + * @compile -printsource package-info.java * @run main/othervm T6257443 -no foo/package-info.class */ diff --git a/langtools/test/tools/javac/6521805/T6521805a.java b/langtools/test/tools/javac/6521805/T6521805a.java deleted file mode 100644 index d81fab6ddc5..00000000000 --- a/langtools/test/tools/javac/6521805/T6521805a.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * @test /nodynamiccopyright/ - * @bug 6521805 - * @summary Regression: JDK5/JDK6 javac allows write access to outer class reference - * @author mcimadamore - * - * @compile/fail/ref=T6521805a_1.out T6521805a.java -XDrawDiagnostics - * @compile/ref=T6521805a_2.out T6521805a.java -XDwarnOnSyntheticConflicts -XDrawDiagnostics - */ - -class T6521805a { - - static class Outer { - T6521805a this$0 = null; - } - - public class Inner extends Outer { - public void foo() { - this$0 = new T6521805a(); - } - } -} diff --git a/langtools/test/tools/javac/6521805/T6521805a_1.out b/langtools/test/tools/javac/6521805/T6521805a_1.out deleted file mode 100644 index 3c069c0a793..00000000000 --- a/langtools/test/tools/javac/6521805/T6521805a_1.out +++ /dev/null @@ -1,2 +0,0 @@ -T6521805a.java:17:12: compiler.err.synthetic.name.conflict: this$0, T6521805a.Outer -1 error diff --git a/langtools/test/tools/javac/6521805/T6521805a_2.out b/langtools/test/tools/javac/6521805/T6521805a_2.out deleted file mode 100644 index 98d97813f36..00000000000 --- a/langtools/test/tools/javac/6521805/T6521805a_2.out +++ /dev/null @@ -1,2 +0,0 @@ -T6521805a.java:17:12: compiler.warn.synthetic.name.conflict: this$0, T6521805a.Outer -1 warning diff --git a/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java b/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java index b9be7190088..62b92bcc15a 100644 --- a/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java +++ b/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -61,8 +61,6 @@ public class EventsBalancedTest { test(null, Arrays.asList(a, b)); test(null, Arrays.asList(b, a)); - test(Arrays.asList("-XD-relax"), Arrays.asList(a, b)); - test(Arrays.asList("-XD-relax"), Arrays.asList(b, a)); for (CompileState stop : CompileState.values()) { test(Arrays.asList("-XDshouldStopPolicyIfNoError=" + stop, diff --git a/langtools/test/tools/javac/diags/CheckResourceKeys.java b/langtools/test/tools/javac/diags/CheckResourceKeys.java index 1c29a7240e0..9c1c0380fad 100644 --- a/langtools/test/tools/javac/diags/CheckResourceKeys.java +++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java @@ -231,22 +231,15 @@ public class CheckResourceKeys { "compiler.err.type.var.more.than.once.in.result", // UNUSED "compiler.misc.non.denotable.type", // UNUSED "compiler.misc.unnamed.package", // should be required, CR 6964147 - "compiler.misc.verbose.retro", // UNUSED - "compiler.misc.verbose.retro.with", // UNUSED - "compiler.misc.verbose.retro.with.list", // UNUSED "compiler.warn.proc.type.already.exists", // TODO in JavacFiler "javac.err.invalid.arg", // UNUSED ?? "javac.opt.arg.class", // UNUSED ?? "javac.opt.arg.pathname", // UNUSED ?? "javac.opt.moreinfo", // option commented out "javac.opt.nogj", // UNUSED - "javac.opt.printflat", // option commented out "javac.opt.printsearch", // option commented out "javac.opt.prompt", // option commented out - "javac.opt.retrofit", // UNUSED - "javac.opt.s", // option commented out - "javac.opt.scramble", // option commented out - "javac.opt.scrambleall" // option commented out + "javac.opt.s" // option commented out )); /** diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index bd79b7940d0..806d471ea99 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -86,9 +86,6 @@ compiler.misc.unable.to.access.file # ClassFile compiler.misc.undecl.type.var # ClassReader compiler.misc.unicode.str.not.supported # ClassReader compiler.misc.malformed.vararg.method # ClassReader -compiler.misc.verbose.retro # UNUSED -compiler.misc.verbose.retro.with # UNUSED -compiler.misc.verbose.retro.with.list # UNUSED compiler.misc.version.not.available # JavaCompiler; implies build error compiler.misc.where.description.captured compiler.misc.where.typevar.1 diff --git a/langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java b/langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java deleted file mode 100644 index 508cfb4ceca..00000000000 --- a/langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2010, 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. - */ - -// key: compiler.warn.synthetic.name.conflict -// options: -XDwarnOnSyntheticConflicts - -class WarnSyntheticNameConflict { - - static class Outer { - WarnSyntheticNameConflict this$0 = null; - } - - public class Inner extends Outer { } -} From 0934254e0397496f7e271bea6fb803e96e529e11 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Tue, 23 Feb 2016 09:52:56 +0800 Subject: [PATCH 070/311] 8149154: tools/pack200/Pack200Test.java failed with NullPointerException Reviewed-by: ksrini --- jdk/test/tools/pack200/Pack200Test.java | 2 ++ jdk/test/tools/pack200/Utils.java | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/jdk/test/tools/pack200/Pack200Test.java b/jdk/test/tools/pack200/Pack200Test.java index 9298e9723a8..fb6d9b1f83d 100644 --- a/jdk/test/tools/pack200/Pack200Test.java +++ b/jdk/test/tools/pack200/Pack200Test.java @@ -81,7 +81,9 @@ public class Pack200Test { System.out.println("Packing [" + in.toString() + "]"); // Call the packer Utils.pack(jarFile, packFile); + System.out.println("Done Packing [" + in.toString() + "]"); jarFile.close(); + System.out.println("Start leak check"); leakCheck(); System.out.println(" Unpacking using java unpacker"); diff --git a/jdk/test/tools/pack200/Utils.java b/jdk/test/tools/pack200/Utils.java index f0c29a597b5..60f2d0c50bc 100644 --- a/jdk/test/tools/pack200/Utils.java +++ b/jdk/test/tools/pack200/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -324,6 +324,9 @@ class Utils { private static void findFiles0(File startDir, List list, FileFilter filter) throws IOException { File[] foundFiles = startDir.listFiles(filter); + if (foundFiles == null) { + return; + } list.addAll(Arrays.asList(foundFiles)); File[] dirs = startDir.listFiles(DIR_FILTER); for (File dir : dirs) { From a06164b8d9ce74075aa0a1b6c460e502f472ab97 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 23 Feb 2016 10:22:40 +0530 Subject: [PATCH 071/311] 8150233: Missing copyright headers in XSurfaceData/ExtendedKeyCodes Reviewed-by: prr --- .../classes/sun/awt/ExtendedKeyCodes.java | 24 +++++++++++++++++++ .../classes/sun/java2d/x11/XSurfaceData.java | 24 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java b/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java index 1e054b9de81..c034dbebd44 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2009, 2016, 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. + */ package sun.awt; import java.util.Collections; diff --git a/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java b/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java index 8e71a80a0e9..dbae176dd7e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java +++ b/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2010, 2016, 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. + */ package sun.java2d.x11; import java.awt.image.*; From 43cef7fa52bf08269e2dbd60408f4b0f6d6547b1 Mon Sep 17 00:00:00 2001 From: Manajit Halder Date: Tue, 23 Feb 2016 10:24:29 +0530 Subject: [PATCH 072/311] 8147834: [macosx] KeyEvents for function keys F17, F18, F19 return keyCode 0 Reviewed-by: serb, aniyogi --- .../macosx/native/libawt_lwawt/awt/AWTEvent.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m index 07bb7fab938..9b8e370a938 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m @@ -134,7 +134,7 @@ const keyTable[] = {0x3D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x3E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x3F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, // the 'fn' key on PowerBooks - {0x40, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, + {0x40, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F17}, {0x41, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DECIMAL}, {0x42, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x43, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_MULTIPLY}, @@ -149,8 +149,8 @@ const keyTable[] = {0x4C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER}, {0x4D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x4E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_SUBTRACT}, - {0x4F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, - {0x50, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, + {0x4F, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F18}, + {0x50, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F19}, {0x51, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_EQUALS}, {0x52, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD0}, {0x53, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD1}, @@ -160,7 +160,7 @@ const keyTable[] = {0x57, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD5}, {0x58, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD6}, {0x59, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD7}, - {0x5A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, + {0x5A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F20}, {0x5B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD8}, {0x5C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD9}, {0x5D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH}, // This is a combo yen/backslash on JIS keyboards. From 5baf4fccc46aa4ebc274f85accdb3da5757603cb Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Tue, 23 Feb 2016 07:17:54 +0100 Subject: [PATCH 073/311] 8150360: augment/correct MethodHandle API documentation Reviewed-by: psandoz --- .../java/lang/invoke/MethodHandle.java | 15 ++++++++-- .../java/lang/invoke/MethodHandles.java | 28 +++++++++++++++++-- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index a3f6f47b00f..235ffe60f57 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -1026,6 +1026,9 @@ MethodHandle longsToString = publicLookup() .asCollector(long[].class, 1); assertEquals("[123]", (String) longsToString.invokeExact((long)123)); * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments * @param arrayLength the number of arguments to collect into a new array argument * @return a new method handle which collects some trailing argument @@ -1067,6 +1070,9 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1); assertEquals("BCPQRSZ", swr.toString()); * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param collectArgPos the zero-based position in the parameter list at which to start collecting. * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments * @param arrayLength the number of arguments to collect into a new array argument @@ -1356,8 +1362,11 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); * The reference {@code x} must be convertible to the first parameter * type of the target. *

- * (Note: Because method handles are immutable, the target method handle - * retains its original type and behavior.) + * Note: Because method handles are immutable, the target method handle + * retains its original type and behavior. + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param x the value to bind to the first argument of the target * @return a new method handle which prepends the given value to the incoming * argument list, before calling the original method handle diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index fc9ac8e1518..c7389b63b05 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -2139,7 +2139,7 @@ return invoker; * if its index does not appear in the array. * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments}, * incoming arguments which are not mentioned in the reordering array - * are may be any type, as determined only by {@code newType}. + * may be of any type, as determined only by {@code newType}. *

{@code
 import static java.lang.invoke.MethodHandles.*;
 import static java.lang.invoke.MethodType.*;
@@ -2157,6 +2157,9 @@ MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
 assert(twice.type().equals(intfn1));
 assert((int)twice.invokeExact(21) == 42);
      * }
+ *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke after arguments are reordered * @param newType the expected type of the new method handle * @param reorder an index array which controls the reordering @@ -2421,6 +2424,9 @@ assert((int)twice.invokeExact(21) == 42); * It may range between zero and N-L (inclusively), * where N is the arity of the target method handle * and L is the length of the values array. + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke after the argument is inserted * @param pos where to insert the argument (zero for the first) * @param values the series of arguments to insert @@ -2647,6 +2653,9 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY * return target(p..., f[i](v[i])..., b...); * } * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * * @param target the method handle to invoke after arguments are filtered * @param pos the position of the first argument to filter @@ -2791,6 +2800,9 @@ assertEquals("[top, [[up, down, strange], charm], bottom]", * a non-void result, then {@code collectArguments(mh, N, coll)} * is equivalent to {@code filterArguments(mh, N, coll)}. * Other equivalences are possible but would require argument permutation. + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * * @param target the method handle to invoke after filtering the subsequence of arguments * @param pos the position of the first adapter argument to pass to the filter, @@ -2887,6 +2899,9 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 * filter3(v); * } * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke before filtering the return value * @param filter method handle to call on the return value * @return method handle which incorporates the specified return value filtering logic @@ -2981,6 +2996,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * return target2(a..., b...); * } * } + *

+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke after arguments are combined * @param combiner method handle to call initially on the incoming arguments * @return method handle which incorporates the specified argument folding logic @@ -3828,8 +3846,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * (Note that, except for argument type conversions, combinators represent {@code void} values in parameter lists * by omitting the corresponding paradoxical arguments, not by inserting {@code null} or zero values.) *

- * The {@code target} and {@code cleanup} handles' return types must be the same. Their parameter type lists also - * must be the same, but the {@code cleanup} handle must accept one or two more leading parameters:

    + * The {@code target} and {@code cleanup} handles must have the same corresponding argument and return types, except + * that the {@code cleanup} handle may omit trailing arguments. Also, the {@code cleanup} handle must have one or + * two extra leading parameters:
      *
    • a {@code Throwable}, which will carry the exception thrown by the {@code target} handle (if any); and *
    • a parameter of the same type as the return type of both {@code target} and {@code cleanup}, which will carry * the result from the execution of the {@code target} handle. @@ -3949,6 +3968,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * return target2(z..., a..., b...); * } * } + *

      + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * * @param target the method handle to invoke after arguments are combined * @param pos the position at which to start folding and at which to insert the folding result; if this is {@code From 28d990ee6fae99f1e35fca94fcb6d4a894efae64 Mon Sep 17 00:00:00 2001 From: Nishit Jain Date: Tue, 23 Feb 2016 17:09:46 +0900 Subject: [PATCH 074/311] 8074411: Describe "minor unit" and/or "default fraction digits" in Currency class' javadoc clearly Reviewed-by: naoto, okutsu, peytoia --- .../share/classes/java/util/Currency.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/Currency.java b/jdk/src/java.base/share/classes/java/util/Currency.java index 74c7b4bb3fc..8648147bcfe 100644 --- a/jdk/src/java.base/share/classes/java/util/Currency.java +++ b/jdk/src/java.base/share/classes/java/util/Currency.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -92,7 +92,12 @@ import sun.util.logging.PlatformLogger; * and the remainder of entries in file are processed. For instances where duplicate * country code entries exist, the behavior of the Currency information for that * {@code Currency} is undefined and the remainder of entries in file are processed. + *

      + * It is recommended to use {@link java.math.BigDecimal} class while dealing + * with {@code Currency} or monetary values as it provides better handling of floating + * point numbers and their operations. * + * @see java.math.BigDecimal * @since 1.4 */ public final class Currency implements Serializable { @@ -516,14 +521,16 @@ public final class Currency implements Serializable { } /** - * Gets the default number of fraction digits used with this currency. - * For example, the default number of fraction digits for the Euro is 2, - * while for the Japanese Yen it's 0. - * In the case of pseudo-currencies, such as IMF Special Drawing Rights, - * -1 is returned. - * - * @return the default number of fraction digits used with this currency - */ + * Gets the default number of fraction digits used with this currency. + * Note that the number of fraction digits is the same as ISO 4217's + * minor unit for the currency. + * For example, the default number of fraction digits for the Euro is 2, + * while for the Japanese Yen it's 0. + * In the case of pseudo-currencies, such as IMF Special Drawing Rights, + * -1 is returned. + * + * @return the default number of fraction digits used with this currency + */ public int getDefaultFractionDigits() { return defaultFractionDigits; } From 19a07cb7dbe771af578160533c7bd6ffca49b28a Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Tue, 23 Feb 2016 09:49:04 +0100 Subject: [PATCH 075/311] 8143410: augment pseudo-code descriptions in MethodHandles API Reviewed-by: psandoz --- .../java/lang/invoke/MethodHandles.java | 91 +++++++++++++++---- 1 file changed, 71 insertions(+), 20 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index c7389b63b05..befe2520ec7 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -2645,12 +2645,20 @@ assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY MethodHandle f2 = filterArguments(cat, 0, upcase, upcase); assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY * } - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, {@code T} + * denotes the return type of both the {@code target} and resulting adapter. + * {@code P}/{@code p} and {@code B}/{@code b} represent the types and values + * of the parameters and arguments that precede and follow the filter position + * {@code pos}, respectively. {@code A[i]}/{@code a[i]} stand for the types and + * values of the filtered parameters and arguments; they also represent the + * return types of the {@code filter[i]} handles. The latter accept arguments + * {@code v[i]} of type {@code V[i]}, which also appear in the signature of + * the resulting adapter. *

      {@code
      -     * V target(P... p, A[i]... a[i], B... b);
      +     * T target(P... p, A[i]... a[i], B... b);
            * A[i] filter[i](V[i]);
            * T adapter(P... p, V[i]... v[i], B... b) {
      -     *   return target(p..., f[i](v[i])..., b...);
      +     *   return target(p..., filter[i](v[i])..., b...);
            * }
            * }
      *

      @@ -2762,7 +2770,17 @@ MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3); assertEquals("[top, [[up, down, strange], charm], bottom]", (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom")); * } - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the return type of the {@code target} and resulting adapter. + * {@code V}/{@code v} stand for the return type and value of the + * {@code filter}, which are also found in the signature and arguments of + * the {@code target}, respectively, unless {@code V} is {@code void}. + * {@code A}/{@code a} and {@code C}/{@code c} represent the parameter types + * and values preceding and following the collection position, {@code pos}, + * in the {@code target}'s signature. They also turn up in the resulting + * adapter's signature and arguments, where they surround + * {@code B}/{@code b}, which represent the parameter types and arguments + * to the {@code filter} (if any). *

      {@code
            * T target(A...,V,C...);
            * V filter(B...);
      @@ -2780,7 +2798,7 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
            * // and if the filter has a void return:
            * T target3(A...,C...);
            * void filter3(B...);
      -     * void adapter3(A... a,B... b,C... c) {
      +     * T adapter3(A... a,B... b,C... c) {
            *   filter3(b...);
            *   return target3(a...,c...);
            * }
      @@ -2876,27 +2894,31 @@ System.out.println((String) cat.invokeExact("x", "y")); // xy
       MethodHandle f0 = filterReturnValue(cat, length);
       System.out.println((int) f0.invokeExact("x", "y")); // 2
            * }
      - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, + * {@code T}/{@code t} represent the result type and value of the + * {@code target}; {@code V}, the result type of the {@code filter}; and + * {@code A}/{@code a}, the types and values of the parameters and arguments + * of the {@code target} as well as the resulting adapter. *

      {@code
      -     * V target(A...);
      -     * T filter(V);
      -     * T adapter(A... a) {
      -     *   V v = target(a...);
      -     *   return filter(v);
      +     * T target(A...);
      +     * V filter(T);
      +     * V adapter(A... a) {
      +     *   T t = target(a...);
      +     *   return filter(t);
            * }
            * // and if the target has a void return:
            * void target2(A...);
      -     * T filter2();
      -     * T adapter2(A... a) {
      +     * V filter2();
      +     * V adapter2(A... a) {
            *   target2(a...);
            *   return filter2();
            * }
            * // and if the filter has a void return:
      -     * V target3(A...);
      +     * T target3(A...);
            * void filter3(V);
            * void adapter3(A... a) {
      -     *   V v = target3(a...);
      -     *   filter3(v);
      +     *   T t = target3(a...);
      +     *   filter3(t);
            * }
            * }
      *

      @@ -2979,7 +3001,15 @@ MethodHandle catTrace = foldArguments(cat, trace); // also prints "boo": assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * } - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the result type of the {@code target} and resulting adapter. + * {@code V}/{@code v} represent the type and value of the parameter and argument + * of {@code target} that precedes the folding position; {@code V} also is + * the result type of the {@code combiner}. {@code A}/{@code a} denote the + * types and values of the {@code N} parameters and arguments at the folding + * position. {@code B}/{@code b} represent the types and values of the + * {@code target} parameters and arguments that follow the folded parameters + * and arguments. *

      {@code
            * // there are N arguments in A...
            * T target(V, A[N]..., B...);
      @@ -3040,7 +3070,13 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
            * argument and return types, except that the return type
            * of the test must be boolean, and the test is allowed
            * to have fewer arguments than the other two method handles.
      -     * 

      Here is pseudocode for the resulting adapter: + *

      + * Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the uniform result type of the three involved handles; + * {@code A}/{@code a}, the types and values of the {@code target} + * parameters and arguments that are consumed by the {@code test}; and + * {@code B}/{@code b}, those types and values of the {@code target} + * parameters and arguments that are not consumed by the {@code test}. *

      {@code
            * boolean test(A...);
            * T target(A...,B...);
      @@ -3102,7 +3138,13 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
            * argument and return types, except that handler may omit trailing arguments
            * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
            * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
      -     * 

      Here is pseudocode for the resulting adapter: + *

      + * Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the return type of the {@code target} and {@code handler}, + * and correspondingly that of the resulting adapter; {@code A}/{@code a}, + * the types and values of arguments to the resulting handle consumed by + * {@code handler}; and {@code B}/{@code b}, those of arguments to the + * resulting handle discarded by {@code handler}. *

      {@code
            * T target(A..., B...);
            * T handler(ExType, A...);
      @@ -3951,7 +3993,16 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
           // also prints "jum":
           assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
            * }
      - *

      Here is pseudocode for the resulting adapter: + *

      Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the result type of the {@code target} and resulting adapter. + * {@code V}/{@code v} represent the type and value of the parameter and argument + * of {@code target} that precedes the folding position; {@code V} also is + * the result type of the {@code combiner}. {@code A}/{@code a} denote the + * types and values of the {@code N} parameters and arguments at the folding + * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types + * and values of the {@code target} parameters and arguments that precede and + * follow the folded parameters and arguments starting at {@code pos}, + * respectively. *

      {@code
            * // there are N arguments in A...
            * T target(Z..., V, A[N]..., B...);
      
      From e020d2f477f39ef03d161f0f0123df315a3c5b40 Mon Sep 17 00:00:00 2001
      From: Bengt Rutisson 
      Date: Tue, 23 Feb 2016 09:52:46 +0100
      Subject: [PATCH 076/311] 8150367: Add back information about the number of GC
       workers
      
      Reviewed-by: sjohanss, tschatzl
      ---
       hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 9 +++++----
       hotspot/src/share/vm/gc/shared/workgroup.hpp   | 2 ++
       2 files changed, 7 insertions(+), 4 deletions(-)
      
      diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
      index d7546a121ff..f241d749045 100644
      --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
      +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
      @@ -3235,10 +3235,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
       
           GCTraceCPUTime tcpu;
       
      -    uint active_workers = AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(),
      -                                                                  workers()->active_workers(),
      -                                                                  Threads::number_of_non_daemon_threads());
      -    workers()->set_active_workers(active_workers);
           FormatBuffer<> gc_string("Pause ");
           if (collector_state()->during_initial_mark_pause()) {
             gc_string.append("Initial Mark");
      @@ -3249,6 +3245,11 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
           }
           GCTraceTime(Info, gc) tm(gc_string, NULL, gc_cause(), true);
       
      +    uint active_workers = AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(),
      +                                                                  workers()->active_workers(),
      +                                                                  Threads::number_of_non_daemon_threads());
      +    workers()->set_active_workers(active_workers);
      +
           g1_policy()->note_gc_start(active_workers);
       
           TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
      diff --git a/hotspot/src/share/vm/gc/shared/workgroup.hpp b/hotspot/src/share/vm/gc/shared/workgroup.hpp
      index b2a48647cab..c28579ef471 100644
      --- a/hotspot/src/share/vm/gc/shared/workgroup.hpp
      +++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp
      @@ -29,6 +29,7 @@
       #include "runtime/globals.hpp"
       #include "runtime/thread.hpp"
       #include "gc/shared/gcId.hpp"
      +#include "logging/log.hpp"
       #include "utilities/debug.hpp"
       #include "utilities/globalDefinitions.hpp"
       
      @@ -151,6 +152,7 @@ class AbstractWorkGang : public CHeapObj {
           _active_workers = MAX2(1U, _active_workers);
           assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
                  "Unless dynamic should use total workers");
      +    log_info(gc, task)("GC Workers: %d", _active_workers);
         }
       
         // Return the Ith worker.
      
      From 861dc1364556f2b7f6c7d9e57ea16e588e76888e Mon Sep 17 00:00:00 2001
      From: Antonios Printezis 
      Date: Tue, 23 Feb 2016 10:44:05 +0100
      Subject: [PATCH 077/311] 8146989: Introduce per-worker preserved mark stacks
       in ParNew
      
      Unify and provide per-worker preserved mark stack handling in ParNew
      
      Reviewed-by: tschatzl, ysr
      ---
       .../src/share/vm/gc/cms/parNewGeneration.cpp  |  26 ++--
       .../src/share/vm/gc/cms/parNewGeneration.hpp  |   9 +-
       hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp  |  15 +--
       .../share/vm/gc/serial/defNewGeneration.cpp   |  40 ++-----
       .../share/vm/gc/serial/defNewGeneration.hpp   |  12 +-
       .../src/share/vm/gc/shared/preservedMarks.cpp |  93 +++++++++++++++
       .../src/share/vm/gc/shared/preservedMarks.hpp | 111 ++++++++++++++++++
       .../vm/gc/shared/preservedMarks.inline.hpp    |  48 ++++++++
       8 files changed, 284 insertions(+), 70 deletions(-)
       create mode 100644 hotspot/src/share/vm/gc/shared/preservedMarks.cpp
       create mode 100644 hotspot/src/share/vm/gc/shared/preservedMarks.hpp
       create mode 100644 hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp
      
      diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp
      index 0f2f019e9d8..6962f158e5c 100644
      --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp
      +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp
      @@ -39,6 +39,7 @@
       #include "gc/shared/genOopClosures.inline.hpp"
       #include "gc/shared/generation.hpp"
       #include "gc/shared/plab.inline.hpp"
      +#include "gc/shared/preservedMarks.inline.hpp"
       #include "gc/shared/referencePolicy.hpp"
       #include "gc/shared/space.hpp"
       #include "gc/shared/spaceDecorator.hpp"
      @@ -64,6 +65,7 @@ ParScanThreadState::ParScanThreadState(Space* to_space_,
                                              int thread_num_,
                                              ObjToScanQueueSet* work_queue_set_,
                                              Stack* overflow_stacks_,
      +                                       PreservedMarks* preserved_marks_,
                                              size_t desired_plab_sz_,
                                              ParallelTaskTerminator& term_) :
         _to_space(to_space_),
      @@ -73,6 +75,7 @@ ParScanThreadState::ParScanThreadState(Space* to_space_,
         _work_queue(work_queue_set_->queue(thread_num_)),
         _to_space_full(false),
         _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL),
      +  _preserved_marks(preserved_marks_),
         _ageTable(false), // false ==> not the global age table, no perf data.
         _to_space_alloc_buffer(desired_plab_sz_),
         _to_space_closure(young_gen_, this),
      @@ -286,6 +289,7 @@ public:
                               Generation&             old_gen,
                               ObjToScanQueueSet&      queue_set,
                               Stack*       overflow_stacks_,
      +                        PreservedMarksSet&      preserved_marks_set,
                               size_t                  desired_plab_sz,
                               ParallelTaskTerminator& term);
       
      @@ -322,6 +326,7 @@ ParScanThreadStateSet::ParScanThreadStateSet(int num_threads,
                                                    Generation& old_gen,
                                                    ObjToScanQueueSet& queue_set,
                                                    Stack* overflow_stacks,
      +                                             PreservedMarksSet& preserved_marks_set,
                                                    size_t desired_plab_sz,
                                                    ParallelTaskTerminator& term)
         : ResourceArray(sizeof(ParScanThreadState), num_threads),
      @@ -336,7 +341,8 @@ ParScanThreadStateSet::ParScanThreadStateSet(int num_threads,
         for (int i = 0; i < num_threads; ++i) {
           new ((ParScanThreadState*)_data + i)
               ParScanThreadState(&to_space, &young_gen, &old_gen, i, &queue_set,
      -                           overflow_stacks, desired_plab_sz, term);
      +                           overflow_stacks, preserved_marks_set.get(i),
      +                           desired_plab_sz, term);
         }
       }
       
      @@ -905,12 +911,16 @@ void ParNewGeneration::collect(bool   full,
         // Set the correct parallelism (number of queues) in the reference processor
         ref_processor()->set_active_mt_degree(active_workers);
       
      +  // Need to initialize the preserved marks before the ThreadStateSet c'tor.
      +  _preserved_marks_set.init(active_workers);
      +
         // Always set the terminator for the active number of workers
         // because only those workers go through the termination protocol.
         ParallelTaskTerminator _term(active_workers, task_queues());
         ParScanThreadStateSet thread_state_set(active_workers,
                                                *to(), *this, *_old_gen, *task_queues(),
      -                                         _overflow_stacks, desired_plab_sz(), _term);
      +                                         _overflow_stacks, _preserved_marks_set,
      +                                         desired_plab_sz(), _term);
       
         thread_state_set.reset(active_workers, promotion_failed());
       
      @@ -993,6 +1003,7 @@ void ParNewGeneration::collect(bool   full,
         } else {
           handle_promotion_failed(gch, thread_state_set);
         }
      +  _preserved_marks_set.reclaim();
         // set new iteration safe limit for the survivor spaces
         from()->set_concurrent_iteration_safe_limit(from()->top());
         to()->set_concurrent_iteration_safe_limit(to()->top());
      @@ -1070,15 +1081,6 @@ oop ParNewGeneration::real_forwardee_slow(oop obj) {
         return forward_ptr;
       }
       
      -void ParNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) {
      -  if (m->must_be_preserved_for_promotion_failure(obj)) {
      -    // We should really have separate per-worker stacks, rather
      -    // than use locking of a common pair of stacks.
      -    MutexLocker ml(ParGCRareEvent_lock);
      -    preserve_mark(obj, m);
      -  }
      -}
      -
       // Multiple GC threads may try to promote an object.  If the object
       // is successfully promoted, a forwarding pointer will be installed in
       // the object in the young generation.  This method claims the right
      @@ -1136,7 +1138,7 @@ oop ParNewGeneration::copy_to_survivor_space(ParScanThreadState* par_scan_state,
             _promotion_failed = true;
             new_obj = old;
       
      -      preserve_mark_if_necessary(old, m);
      +      par_scan_state->preserved_marks()->push_if_necessary(old, m);
             par_scan_state->register_promotion_failure(sz);
           }
       
      diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp
      index 765ea72962e..94ec916357c 100644
      --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp
      +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp
      @@ -30,6 +30,7 @@
       #include "gc/shared/copyFailedInfo.hpp"
       #include "gc/shared/gcTrace.hpp"
       #include "gc/shared/plab.hpp"
      +#include "gc/shared/preservedMarks.hpp"
       #include "gc/shared/taskqueue.hpp"
       #include "memory/padded.hpp"
       
      @@ -65,6 +66,7 @@ class ParScanThreadState {
        private:
         ObjToScanQueue *_work_queue;
         Stack* const _overflow_stack;
      +  PreservedMarks* const _preserved_marks;
       
         PLAB _to_space_alloc_buffer;
       
      @@ -128,6 +130,7 @@ class ParScanThreadState {
                            Generation* old_gen_, int thread_num_,
                            ObjToScanQueueSet* work_queue_set_,
                            Stack* overflow_stacks_,
      +                     PreservedMarks* preserved_marks_,
                            size_t desired_plab_sz_,
                            ParallelTaskTerminator& term_);
       
      @@ -136,6 +139,8 @@ class ParScanThreadState {
       
         ObjToScanQueue* work_queue() { return _work_queue; }
       
      +  PreservedMarks* preserved_marks() const { return _preserved_marks; }
      +
         PLAB* to_space_alloc_buffer() {
           return &_to_space_alloc_buffer;
         }
      @@ -331,10 +336,6 @@ class ParNewGeneration: public DefNewGeneration {
         static oop real_forwardee_slow(oop obj);
         static void waste_some_time();
       
      -  // Preserve the mark of "obj", if necessary, in preparation for its mark
      -  // word being overwritten with a self-forwarding-pointer.
      -  void preserve_mark_if_necessary(oop obj, markOop m);
      -
         void handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set);
       
        protected:
      diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp
      index ca7643f59a8..eff37e8ae44 100644
      --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp
      +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp
      @@ -27,25 +27,12 @@
       
       #include "gc/g1/g1OopClosures.hpp"
       #include "gc/g1/heapRegionManager.hpp"
      + #include "gc/shared/preservedMarks.hpp"
       #include "gc/shared/workgroup.hpp"
       #include "utilities/globalDefinitions.hpp"
       
       class G1CollectedHeap;
       
      -class OopAndMarkOop {
      -  oop _o;
      -  markOop _m;
      - public:
      -  OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) {
      -  }
      -
      -  void set_mark() {
      -    _o->set_mark(_m);
      -  }
      -};
      -
      -typedef Stack OopAndMarkOopStack;
      -
       // Task to fixup self-forwarding pointers
       // installed as a result of an evacuation failure.
       class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask {
      diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
      index 9c00cd90383..08a21b2634f 100644
      --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
      +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
      @@ -36,6 +36,7 @@
       #include "gc/shared/genCollectedHeap.hpp"
       #include "gc/shared/genOopClosures.inline.hpp"
       #include "gc/shared/generationSpec.hpp"
      +#include "gc/shared/preservedMarks.inline.hpp"
       #include "gc/shared/referencePolicy.hpp"
       #include "gc/shared/space.inline.hpp"
       #include "gc/shared/spaceDecorator.hpp"
      @@ -184,6 +185,7 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs,
                                          size_t initial_size,
                                          const char* policy)
         : Generation(rs, initial_size),
      +    _preserved_marks_set(false /* in_c_heap */),
           _promo_failure_drain_in_progress(false),
           _should_allocate_from_space(false)
       {
      @@ -602,6 +604,8 @@ void DefNewGeneration::collect(bool   full,
       
         age_table()->clear();
         to()->clear(SpaceDecorator::Mangle);
      +  // The preserved marks should be empty at the start of the GC.
      +  _preserved_marks_set.init(1);
       
         gch->rem_set()->prepare_for_younger_refs_iterate(false);
       
      @@ -704,6 +708,8 @@ void DefNewGeneration::collect(bool   full,
           // Reset the PromotionFailureALot counters.
           NOT_PRODUCT(gch->reset_promotion_should_fail();)
         }
      +  // We should have processed and cleared all the preserved marks.
      +  _preserved_marks_set.reclaim();
         // set new iteration safe limit for the survivor spaces
         from()->set_concurrent_iteration_safe_limit(from()->top());
         to()->set_concurrent_iteration_safe_limit(to()->top());
      @@ -721,13 +727,6 @@ void DefNewGeneration::collect(bool   full,
         gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
       }
       
      -class RemoveForwardPointerClosure: public ObjectClosure {
      -public:
      -  void do_object(oop obj) {
      -    obj->init_mark();
      -  }
      -};
      -
       void DefNewGeneration::init_assuming_no_promotion_failure() {
         _promotion_failed = false;
         _promotion_failed_info.reset();
      @@ -735,33 +734,12 @@ void DefNewGeneration::init_assuming_no_promotion_failure() {
       }
       
       void DefNewGeneration::remove_forwarding_pointers() {
      -  RemoveForwardPointerClosure rspc;
      +  RemoveForwardedPointerClosure rspc;
         eden()->object_iterate(&rspc);
         from()->object_iterate(&rspc);
       
         // Now restore saved marks, if any.
      -  assert(_objs_with_preserved_marks.size() == _preserved_marks_of_objs.size(),
      -         "should be the same");
      -  while (!_objs_with_preserved_marks.is_empty()) {
      -    oop obj   = _objs_with_preserved_marks.pop();
      -    markOop m = _preserved_marks_of_objs.pop();
      -    obj->set_mark(m);
      -  }
      -  _objs_with_preserved_marks.clear(true);
      -  _preserved_marks_of_objs.clear(true);
      -}
      -
      -void DefNewGeneration::preserve_mark(oop obj, markOop m) {
      -  assert(_promotion_failed && m->must_be_preserved_for_promotion_failure(obj),
      -         "Oversaving!");
      -  _objs_with_preserved_marks.push(obj);
      -  _preserved_marks_of_objs.push(m);
      -}
      -
      -void DefNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) {
      -  if (m->must_be_preserved_for_promotion_failure(obj)) {
      -    preserve_mark(obj, m);
      -  }
      +  _preserved_marks_set.restore();
       }
       
       void DefNewGeneration::handle_promotion_failure(oop old) {
      @@ -769,7 +747,7 @@ void DefNewGeneration::handle_promotion_failure(oop old) {
       
         _promotion_failed = true;
         _promotion_failed_info.register_copy_failure(old->size());
      -  preserve_mark_if_necessary(old, old->mark());
      +  _preserved_marks_set.get()->push_if_necessary(old, old->mark());
         // forward to self
         old->forward_to(old);
       
      diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp
      index 484a6b6aa52..f258491ae32 100644
      --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp
      +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp
      @@ -30,6 +30,7 @@
       #include "gc/shared/copyFailedInfo.hpp"
       #include "gc/shared/generation.hpp"
       #include "gc/shared/generationCounters.hpp"
      +#include "gc/shared/preservedMarks.hpp"
       #include "utilities/stack.hpp"
       
       class ContiguousSpace;
      @@ -87,15 +88,8 @@ protected:
         // therefore we must remove their forwarding pointers.
         void remove_forwarding_pointers();
       
      -  // Preserve the mark of "obj", if necessary, in preparation for its mark
      -  // word being overwritten with a self-forwarding-pointer.
      -  void   preserve_mark_if_necessary(oop obj, markOop m);
      -  void   preserve_mark(oop obj, markOop m);    // work routine used by the above
      -
      -  // Together, these keep  pairs.
      -  // They should always contain the same number of elements.
      -  Stack     _objs_with_preserved_marks;
      -  Stack _preserved_marks_of_objs;
      +  // Preserved marks
      +  PreservedMarksSet _preserved_marks_set;
       
         // Promotion failure handling
         ExtendedOopClosure *_promo_failure_scan_stack_closure;
      diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp
      new file mode 100644
      index 00000000000..a82c8dd7bd4
      --- /dev/null
      +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp
      @@ -0,0 +1,93 @@
      +/*
      + * Copyright (c) 2016, 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.
      + *
      + */
      +
      +#include "precompiled.hpp"
      +#include "gc/shared/preservedMarks.inline.hpp"
      +#include "memory/allocation.inline.hpp"
      +#include "oops/oop.inline.hpp"
      +
      +void PreservedMarks::restore() {
      +  // First, iterate over the stack and restore all marks.
      +  StackIterator iter(_stack);
      +  while (!iter.is_empty()) {
      +    OopAndMarkOop elem = iter.next();
      +    elem.set_mark();
      +  }
      +
      +  // Second, reclaim all the stack memory
      +  _stack.clear(true /* clear_cache */);
      +}
      +
      +void RemoveForwardedPointerClosure::do_object(oop obj) {
      +  if (obj->is_forwarded()) {
      +    obj->init_mark();
      +  }
      +}
      +
      +void PreservedMarksSet::init(uint num) {
      +  assert(_stacks == NULL && _num == 0, "do not re-initialize");
      +  assert(num > 0, "pre-condition");
      +  if (_in_c_heap) {
      +    _stacks = NEW_C_HEAP_ARRAY(Padded, num, mtGC);
      +  } else {
      +    _stacks = NEW_RESOURCE_ARRAY(Padded, num);
      +  }
      +  for (uint i = 0; i < num; i += 1) {
      +    ::new (_stacks + i) PreservedMarks();
      +  }
      +  _num = num;
      +
      +  assert_empty();
      +}
      +
      +void PreservedMarksSet::restore() {
      +  for (uint i = 0; i < _num; i += 1) {
      +    get(i)->restore();
      +  }
      +}
      +
      +void PreservedMarksSet::reclaim() {
      +  assert_empty();
      +
      +  for (uint i = 0; i < _num; i += 1) {
      +    _stacks[i].~Padded();
      +  }
      +
      +  if (_in_c_heap) {
      +    FREE_C_HEAP_ARRAY(Padded, _stacks);
      +  } else {
      +    // the array was resource-allocated, so nothing to do
      +  }
      +  _stacks = NULL;
      +  _num = 0;
      +}
      +
      +#ifndef PRODUCT
      +void PreservedMarksSet::assert_empty() {
      +  assert(_stacks != NULL && _num > 0, "should have been initialized");
      +  for (uint i = 0; i < _num; i += 1) {
      +    assert(get(i)->is_empty(), "stack should be empty");
      +  }
      +}
      +#endif // ndef PRODUCT
      diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp
      new file mode 100644
      index 00000000000..42576d18f38
      --- /dev/null
      +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp
      @@ -0,0 +1,111 @@
      +/*
      + * Copyright (c) 2016, 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.
      + *
      + */
      +
      +#ifndef SHARE_VM_GC_SHARED_PRESERVEDMARKS_HPP
      +#define SHARE_VM_GC_SHARED_PRESERVEDMARKS_HPP
      +
      +#include "memory/allocation.hpp"
      +#include "memory/padded.hpp"
      +#include "oops/oop.hpp"
      +#include "utilities/stack.hpp"
      +
      +class OopAndMarkOop {
      +private:
      +  oop _o;
      +  markOop _m;
      +
      +public:
      +  OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) { }
      +
      +  void set_mark() const {
      +    _o->set_mark(_m);
      +  }
      +};
      +typedef Stack OopAndMarkOopStack;
      +
      +class PreservedMarks VALUE_OBJ_CLASS_SPEC {
      +private:
      +  OopAndMarkOopStack _stack;
      +
      +  inline bool should_preserve_mark(oop obj, markOop m) const;
      +  inline void push(oop obj, markOop m);
      +
      +public:
      +  bool is_empty() const { return _stack.is_empty(); }
      +  inline void push_if_necessary(oop obj, markOop m);
      +  // Iterate over the stack, restore the preserved marks, then reclaim
      +  // the memory taken up by stack chunks.
      +  void restore();
      +  ~PreservedMarks() { assert(is_empty(), "should have been cleared"); }
      +};
      +
      +class RemoveForwardedPointerClosure: public ObjectClosure {
      +public:
      +  virtual void do_object(oop obj);
      +};
      +
      +class PreservedMarksSet VALUE_OBJ_CLASS_SPEC {
      +private:
      +  // true -> _stacks will be allocated in the C heap
      +  // false -> _stacks will be allocated in the resource arena
      +  const bool _in_c_heap;
      +
      +  // Number of stacks we have allocated (typically, one stack per GC worker).
      +  // This should be >= 1 if the stacks have been initialized,
      +  // or == 0 if they have not.
      +  uint _num;
      +
      +  // Stack array (typically, one stack per GC worker) of length _num.
      +  // This should be != NULL if the stacks have been initialized,
      +  // or == NULL if they have not.
      +  Padded* _stacks;
      +
      +public:
      +  // Return the i'th stack.
      +  PreservedMarks* get(uint i = 0) const {
      +    assert(_num > 0 && _stacks != NULL, "stacks should have been initialized");
      +    assert(i < _num, "pre-condition");
      +    return (_stacks + i);
      +  }
      +
      +  // Allocate stack array.
      +  void init(uint num);
      +  // Iterate over all stacks, restore all preserved marks, then
      +  // reclaim the memory taken up by stack chunks.
      +  void restore();
      +  // Reclaim stack array.
      +  void reclaim();
      +
      +  // Assert all the stacks are empty.
      +  void assert_empty() PRODUCT_RETURN;
      +
      +  PreservedMarksSet(bool in_c_heap)
      +      : _in_c_heap(in_c_heap), _num(0), _stacks(NULL) { }
      +
      +  ~PreservedMarksSet() {
      +    assert(_stacks == NULL && _num == 0, "stacks should have been reclaimed");
      +  }
      +};
      +
      +#endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_HPP
      diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp
      new file mode 100644
      index 00000000000..32c83115a69
      --- /dev/null
      +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp
      @@ -0,0 +1,48 @@
      +/*
      + * Copyright (c) 2016, 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.
      + *
      + */
      +
      +#include "gc/shared/preservedMarks.hpp"
      +#include "oops/markOop.inline.hpp"
      +#include "utilities/stack.inline.hpp"
      +
      +#ifndef SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP
      +#define SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP
      +
      +inline bool PreservedMarks::should_preserve_mark(oop obj, markOop m) const {
      +  return m->must_be_preserved_for_promotion_failure(obj);
      +}
      +
      +inline void PreservedMarks::push(oop obj, markOop m) {
      +  assert(should_preserve_mark(obj, m), "pre-condition");
      +  OopAndMarkOop elem(obj, m);
      +  _stack.push(elem);
      +}
      +
      +inline void PreservedMarks::push_if_necessary(oop obj, markOop m) {
      +  if (should_preserve_mark(obj, m)) {
      +    push(obj, m);
      +  }
      +}
      +
      +#endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP
      
      From ef5eb42e40bfd979df5b4acd6a77e71134f71a15 Mon Sep 17 00:00:00 2001
      From: Aleksey Shipilev 
      Date: Tue, 23 Feb 2016 17:55:28 +0300
      Subject: [PATCH 078/311] 8150180: String.value contents should be trusted
      
      Reviewed-by: vlivanov, redestad, jrose, twisti
      ---
       .../share/classes/java/lang/String.java         | 17 ++++++++++++++++-
       1 file changed, 16 insertions(+), 1 deletion(-)
      
      diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java
      index 86ec043d5b1..85d22cbc1ec 100644
      --- a/jdk/src/java.base/share/classes/java/lang/String.java
      +++ b/jdk/src/java.base/share/classes/java/lang/String.java
      @@ -42,6 +42,7 @@ import java.util.regex.PatternSyntaxException;
       import java.util.stream.IntStream;
       import java.util.stream.StreamSupport;
       import jdk.internal.HotSpotIntrinsicCandidate;
      +import jdk.internal.vm.annotation.Stable;
       
       /**
        * The {@code String} class represents character strings. All
      @@ -119,7 +120,18 @@ import jdk.internal.HotSpotIntrinsicCandidate;
       public final class String
           implements java.io.Serializable, Comparable, CharSequence {
       
      -    /** The value is used for character storage. */
      +    /**
      +     * The value is used for character storage.
      +     *
      +     * @implNote This field is trusted by the VM, and is a subject to
      +     * constant folding if String instance is constant. Overwriting this
      +     * field after construction will cause problems.
      +     *
      +     * Additionally, it is marked with {@link Stable} to trust the contents
      +     * of the array. No other facility in JDK provides this functionality (yet).
      +     * {@link Stable} is safe here, because value is never null.
      +     */
      +    @Stable
           private final byte[] value;
       
           /**
      @@ -129,6 +141,9 @@ public final class String
            * LATIN1
            * UTF16
            *
      +     * @implNote This field is trusted by the VM, and is a subject to
      +     * constant folding if String instance is constant. Overwriting this
      +     * field after construction will cause problems.
            */
           private final byte coder;
       
      
      From 4dfed6652630593769bf049be7ac2213ca47b69f Mon Sep 17 00:00:00 2001
      From: Yingqi Lu 
      Date: Tue, 23 Feb 2016 17:41:00 +0000
      Subject: [PATCH 079/311] 6432031: Add support for SO_REUSEPORT
      
      Reviewed-by: alanb, simonis, chegar
      ---
       jdk/make/mapfiles/libnet/mapfile-vers         |  6 +-
       jdk/make/mapfiles/libnio/mapfile-linux        |  3 +-
       jdk/make/mapfiles/libnio/mapfile-macosx       |  3 +-
       jdk/make/mapfiles/libnio/mapfile-solaris      |  3 +-
       .../genconstants/ch/genSocketOptionRegistry.c | 18 ++++-
       .../net/AbstractPlainDatagramSocketImpl.java  | 60 +++++++++++++-
       .../java/net/AbstractPlainSocketImpl.java     | 59 +++++++++++++-
       .../classes/java/net/DatagramSocketImpl.java  |  8 +-
       .../classes/java/net/MulticastSocket.java     | 14 +++-
       .../share/classes/java/net/SocketImpl.java    |  8 +-
       .../share/classes/java/net/SocketOptions.java | 13 +++-
       .../java/net/StandardSocketOptions.java       | 25 +++++-
       .../share/classes/jdk/net/Sockets.java        | 32 +++++++-
       .../AsynchronousServerSocketChannelImpl.java  |  5 +-
       .../nio/ch/AsynchronousSocketChannelImpl.java |  5 +-
       .../sun/nio/ch/DatagramChannelImpl.java       |  5 +-
       .../share/classes/sun/nio/ch/Net.java         | 17 +++-
       .../sun/nio/ch/ServerSocketChannelImpl.java   |  6 +-
       .../classes/sun/nio/ch/SocketChannelImpl.java |  5 +-
       .../java.base/share/native/libnet/net_util.c  | 13 +++-
       .../java.base/share/native/libnet/net_util.h  |  4 +-
       .../java/net/PlainDatagramSocketImpl.java     | 25 +++++-
       .../classes/java/net/PlainSocketImpl.java     | 25 +++++-
       .../native/libnet/PlainDatagramSocketImpl.c   |  6 +-
       .../java.base/unix/native/libnet/SdpSupport.c |  7 +-
       .../java.base/unix/native/libnet/SocketImpl.c | 47 +++++++++++
       .../unix/native/libnet/net_util_md.c          | 22 +++++-
       .../unix/native/libnet/net_util_md.h          | 15 +++-
       jdk/src/java.base/unix/native/libnio/ch/Net.c |  8 +-
       .../unix/native/libnio/ch/nio_util.h          | 14 +++-
       .../net/DualStackPlainDatagramSocketImpl.java | 10 ++-
       .../java/net/DualStackPlainSocketImpl.java    | 10 ++-
       .../classes/java/net/PlainSocketImpl.java     | 23 +++++-
       .../net/TwoStacksPlainDatagramSocketImpl.java |  8 +-
       .../java/net/TwoStacksPlainSocketImpl.java    |  9 ++-
       .../windows/native/libnet/SocketImpl.c        | 47 +++++++++++
       .../windows/native/libnet/net_util_md.c       |  7 +-
       .../windows/native/libnet/net_util_md.h       |  4 +
       .../java.base/windows/native/libnio/ch/Net.c  |  9 ++-
       .../java/net/SocketOption/OptionsTest.java    | 78 +++++++++++++------
       .../Basic.java                                | 12 ++-
       .../AsynchronousSocketChannel/Basic.java      | 12 ++-
       .../DatagramChannel/SocketOptionTests.java    | 23 ++++--
       .../SocketOptionTests.java                    | 11 ++-
       44 files changed, 669 insertions(+), 75 deletions(-)
       create mode 100644 jdk/src/java.base/unix/native/libnet/SocketImpl.c
       create mode 100644 jdk/src/java.base/windows/native/libnet/SocketImpl.c
      
      diff --git a/jdk/make/mapfiles/libnet/mapfile-vers b/jdk/make/mapfiles/libnet/mapfile-vers
      index a37668a8418..82247780181 100644
      --- a/jdk/make/mapfiles/libnet/mapfile-vers
      +++ b/jdk/make/mapfiles/libnet/mapfile-vers
      @@ -1,5 +1,5 @@
       #
      -# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
      +# Copyright (c) 1997, 2016, 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
      @@ -87,6 +87,9 @@ SUNWprivate_1.1 {
       		Java_java_net_PlainSocketImpl_socketConnect;
       		Java_java_net_PlainDatagramSocketImpl_getTimeToLive;
       		Java_java_net_PlainDatagramSocketImpl_setTimeToLive;
      +                Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0;
      +                Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0;
      +                Java_jdk_net_Sockets_isReusePortAvailable0;
       		Java_sun_net_PortConfig_getUpper0;
       		Java_sun_net_PortConfig_getLower0;
       		Java_sun_net_dns_ResolverConfigurationImpl_localDomain0;
      @@ -112,6 +115,7 @@ SUNWprivate_1.1 {
       		NET_EnableFastTcpLoopback;
       		NET_ThrowNew;
                       ipv6_available;
      +                reuseport_available;
                       initInetAddressIDs;
       
       	local:
      diff --git a/jdk/make/mapfiles/libnio/mapfile-linux b/jdk/make/mapfiles/libnio/mapfile-linux
      index b9b059a80c2..e4563b10c12 100644
      --- a/jdk/make/mapfiles/libnio/mapfile-linux
      +++ b/jdk/make/mapfiles/libnio/mapfile-linux
      @@ -1,5 +1,5 @@
       #
      -# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
      +# Copyright (c) 2001, 2016, 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
      @@ -109,6 +109,7 @@ SUNWprivate_1.1 {
       		Java_sun_nio_ch_Net_setIntOption0;
                       Java_sun_nio_ch_Net_initIDs;
       		Java_sun_nio_ch_Net_isIPv6Available0;
      +                Java_sun_nio_ch_Net_isReusePortAvailable0;
       		Java_sun_nio_ch_Net_joinOrDrop4;
       		Java_sun_nio_ch_Net_blockOrUnblock4;
       		Java_sun_nio_ch_Net_joinOrDrop6;
      diff --git a/jdk/make/mapfiles/libnio/mapfile-macosx b/jdk/make/mapfiles/libnio/mapfile-macosx
      index 6e4a7fb594c..daee0371e3c 100644
      --- a/jdk/make/mapfiles/libnio/mapfile-macosx
      +++ b/jdk/make/mapfiles/libnio/mapfile-macosx
      @@ -1,5 +1,5 @@
       #
      -# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
      +# Copyright (c) 2001, 2016, 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
      @@ -102,6 +102,7 @@ SUNWprivate_1.1 {
       		Java_sun_nio_ch_Net_setIntOption0;
                       Java_sun_nio_ch_Net_initIDs;
       		Java_sun_nio_ch_Net_isIPv6Available0;
      +                Java_sun_nio_ch_Net_isReusePortAvailable0;
       		Java_sun_nio_ch_Net_joinOrDrop4;
       		Java_sun_nio_ch_Net_blockOrUnblock4;
       		Java_sun_nio_ch_Net_joinOrDrop6;
      diff --git a/jdk/make/mapfiles/libnio/mapfile-solaris b/jdk/make/mapfiles/libnio/mapfile-solaris
      index 6834bd221d4..a1e0d99b0e6 100644
      --- a/jdk/make/mapfiles/libnio/mapfile-solaris
      +++ b/jdk/make/mapfiles/libnio/mapfile-solaris
      @@ -1,5 +1,5 @@
       #
      -# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
      +# Copyright (c) 2001, 2016, 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
      @@ -97,6 +97,7 @@ SUNWprivate_1.1 {
       		Java_sun_nio_ch_Net_setIntOption0;
                       Java_sun_nio_ch_Net_initIDs;
       		Java_sun_nio_ch_Net_isIPv6Available0;
      +                Java_sun_nio_ch_Net_isReusePortAvailable0;
       		Java_sun_nio_ch_Net_joinOrDrop4;
       		Java_sun_nio_ch_Net_blockOrUnblock4;
       		Java_sun_nio_ch_Net_joinOrDrop6;
      diff --git a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
      index 41bd5484ab7..aab692f1f19 100644
      --- a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
      +++ b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 2008, 2016, 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
      @@ -34,6 +34,21 @@
       #include 
       #endif
       
      +/* Defines SO_REUSEPORT */
      +#if !defined(SO_REUSEPORT)
      +#ifdef _WIN32
      +#define SO_REUSEPORT 0
      +#elif __linux__
      +#define SO_REUSEPORT 15
      +#elif __solaris__
      +#define SO_REUSEPORT 0x100e
      +#elif defined(AIX) || defined(MACOSX)
      +#define SO_REUSEPORT 0x0200
      +#else
      +#define SO_REUSEPORT 0
      +#endif
      +#endif
      +
       /**
        * Generates sun.nio.ch.SocketOptionRegistry, a class that maps Java-level
        * socket options to the platform specific level and option.
      @@ -102,6 +117,7 @@ int main(int argc, const char* argv[]) {
           emit_unspec("StandardSocketOptions.SO_SNDBUF",    SOL_SOCKET, SO_SNDBUF);
           emit_unspec("StandardSocketOptions.SO_RCVBUF",    SOL_SOCKET, SO_RCVBUF);
           emit_unspec("StandardSocketOptions.SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR);
      +    emit_unspec("StandardSocketOptions.SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT);
           emit_unspec("StandardSocketOptions.TCP_NODELAY",  IPPROTO_TCP, TCP_NODELAY);
       
           emit_inet("StandardSocketOptions.IP_TOS",            IPPROTO_IP,     IP_TOS);
      diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
      index 1f9eba1300e..7a9b7fc17ed 100644
      --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
      +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 1996, 2016, 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
      @@ -28,6 +28,9 @@ import java.io.FileDescriptor;
       import java.io.IOException;
       import java.security.AccessController;
       import sun.net.ResourceManager;
      +import java.util.Set;
      +import java.util.HashSet;
      +import java.util.Collections;
       
       /**
        * Abstract datagram and multicast socket implementation base class.
      @@ -70,6 +73,45 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
                   });
           }
       
      +    private static volatile boolean checkedReusePort;
      +    private static volatile boolean isReusePortAvailable;
      +
      +    /**
      +     * Tells whether SO_REUSEPORT is supported.
      +     */
      +    static boolean isReusePortAvailable() {
      +        if (!checkedReusePort) {
      +            isReusePortAvailable = isReusePortAvailable0();
      +            checkedReusePort = true;
      +        }
      +        return isReusePortAvailable;
      +    }
      +
      +    private static volatile Set> socketOptions;
      +
      +    /**
      +     * Returns a set of SocketOptions supported by this impl
      +     * and by this impl's socket (Socket or ServerSocket)
      +     *
      +     * @return a Set of SocketOptions
      +     */
      +    @Override
      +    protected Set> supportedOptions() {
      +        Set> options = socketOptions;
      +        if (options == null) {
      +            if (isReusePortAvailable()) {
      +                options = new HashSet<>();
      +                options.addAll(super.supportedOptions());
      +                options.add(StandardSocketOptions.SO_REUSEPORT);
      +                options = Collections.unmodifiableSet(options);
      +            } else {
      +                options = super.supportedOptions();
      +            }
      +            socketOptions = options;
      +        }
      +        return options;
      +    }
      +
           /**
            * Creates a datagram socket
            */
      @@ -303,6 +345,14 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
                    if (o == null || !(o instanceof Boolean))
                        throw new SocketException("bad argument for IP_MULTICAST_LOOP");
                    break;
      +         case SO_REUSEPORT:
      +             if (o == null || !(o instanceof Boolean)) {
      +                 throw new SocketException("bad argument for SO_REUSEPORT");
      +             }
      +             if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
      +                 throw new UnsupportedOperationException("unsupported option");
      +             }
      +             break;
                default:
                    throw new SocketException("invalid option: " + optID);
                }
      @@ -343,6 +393,13 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
                       result = socketGetOption(optID);
                       break;
       
      +            case SO_REUSEPORT:
      +                if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
      +                    throw new UnsupportedOperationException("unsupported option");
      +                }
      +                result = socketGetOption(optID);
      +                break;
      +
                   default:
                       throw new SocketException("invalid option: " + optID);
               }
      @@ -364,4 +421,5 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
           }
       
           abstract int dataAvailable();
      +    private static native boolean isReusePortAvailable0();
       }
      diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
      index 8841e4fe724..c9afa2657a2 100644
      --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
      +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 1995, 2016, 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
      @@ -33,6 +33,9 @@ import java.io.FileDescriptor;
       import sun.net.ConnectionResetException;
       import sun.net.NetHooks;
       import sun.net.ResourceManager;
      +import java.util.Set;
      +import java.util.HashSet;
      +import java.util.Collections;
       
       /**
        * Default Socket Implementation. This implementation does
      @@ -87,6 +90,45 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
                   });
           }
       
      +    private static volatile boolean checkedReusePort;
      +    private static volatile boolean isReusePortAvailable;
      +
      +    /**
      +     * Tells whether SO_REUSEPORT is supported.
      +     */
      +    static boolean isReusePortAvailable() {
      +        if (!checkedReusePort) {
      +            isReusePortAvailable = isReusePortAvailable0();
      +            checkedReusePort = true;
      +        }
      +        return isReusePortAvailable;
      +    }
      +
      +    private static volatile Set> socketOptions;
      +
      +   /**
      +    * Returns a set of SocketOptions supported by this impl
      +    * and by this impl's socket (Socket or ServerSocket)
      +    *
      +    * @return a Set of SocketOptions
      +    */
      +    @Override
      +    protected Set> supportedOptions() {
      +        Set> options = socketOptions;
      +        if (options == null) {
      +            if (isReusePortAvailable()) {
      +                options = new HashSet<>();
      +                options.addAll(super.supportedOptions());
      +                options.add(StandardSocketOptions.SO_REUSEPORT);
      +                options = Collections.unmodifiableSet(options);
      +            } else {
      +                options = super.supportedOptions();
      +            }
      +            socketOptions = options;
      +        }
      +        return options;
      +    }
      +
           /**
            * Creates a socket with a boolean that specifies whether this
            * is a stream socket (true) or an unconnected UDP socket (false).
      @@ -269,6 +311,13 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
                       throw new SocketException("bad parameter for SO_REUSEADDR");
                   on = ((Boolean)val).booleanValue();
                   break;
      +        case SO_REUSEPORT:
      +            if (val == null || !(val instanceof Boolean))
      +                throw new SocketException("bad parameter for SO_REUSEPORT");
      +            if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT))
      +                throw new UnsupportedOperationException("unsupported option");
      +            on = ((Boolean)val).booleanValue();
      +            break;
               default:
                   throw new SocketException("unrecognized TCP option: " + opt);
               }
      @@ -326,6 +375,12 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
               case SO_KEEPALIVE:
                   ret = socketGetOption(opt, null);
                   return Boolean.valueOf(ret != -1);
      +        case SO_REUSEPORT:
      +            if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
      +                throw new UnsupportedOperationException("unsupported option");
      +            }
      +            ret = socketGetOption(opt, null);
      +            return Boolean.valueOf(ret != -1);
               // should never get here
               default:
                   return null;
      @@ -723,4 +778,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
       
           public static final int SHUT_RD = 0;
           public static final int SHUT_WR = 1;
      +
      +    private static native boolean isReusePortAvailable0();
       }
      diff --git a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java
      index 97526bc3712..5621ea3a608 100644
      --- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java
      +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 1996, 2016, 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
      @@ -287,6 +287,9 @@ public abstract class DatagramSocketImpl implements SocketOptions {
                   setOption(SocketOptions.SO_RCVBUF, value);
               } else if (name == StandardSocketOptions.SO_REUSEADDR) {
                   setOption(SocketOptions.SO_REUSEADDR, value);
      +        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
      +            supportedOptions().contains(name)) {
      +            setOption(SocketOptions.SO_REUSEPORT, value);
               } else if (name == StandardSocketOptions.IP_TOS) {
                   setOption(SocketOptions.IP_TOS, value);
               } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
      @@ -329,6 +332,9 @@ public abstract class DatagramSocketImpl implements SocketOptions {
                   return (T) getOption(SocketOptions.SO_RCVBUF);
               } else if (name == StandardSocketOptions.SO_REUSEADDR) {
                   return (T) getOption(SocketOptions.SO_REUSEADDR);
      +        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
      +            supportedOptions().contains(name)) {
      +            return (T) getOption(SocketOptions.SO_REUSEPORT);
               } else if (name == StandardSocketOptions.IP_TOS) {
                   return (T) getOption(SocketOptions.IP_TOS);
               } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
      diff --git a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java
      index 77c6e198ab0..365092b1e07 100644
      --- a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java
      +++ b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
      + * Copyright (c) 1995, 2016, 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
      @@ -98,7 +98,11 @@ class MulticastSocket extends DatagramSocket {
            * 

      * When the socket is created the * {@link DatagramSocket#setReuseAddress(boolean)} method is - * called to enable the SO_REUSEADDR socket option. + * called to enable the SO_REUSEADDR socket option. When + * {@link StandardSocketOptions#SO_REUSEPORT SO_REUSEPORT} is + * supported then + * {@link DatagramSocketImpl#setOption(SocketOption, Object)} + * is called to enable the socket option. * * @exception IOException if an I/O exception occurs * while creating the MulticastSocket @@ -106,6 +110,7 @@ class MulticastSocket extends DatagramSocket { * {@code checkListen} method doesn't allow the operation. * @see SecurityManager#checkListen * @see java.net.DatagramSocket#setReuseAddress(boolean) + * @see java.net.DatagramSocketImpl#setOption(SocketOption, Object) */ public MulticastSocket() throws IOException { this(new InetSocketAddress(0)); @@ -167,6 +172,11 @@ class MulticastSocket extends DatagramSocket { // Enable SO_REUSEADDR before binding setReuseAddress(true); + // Enable SO_REUSEPORT if supported before binding + if (supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + this.setOption(StandardSocketOptions.SO_REUSEPORT, true); + } + if (bindaddr != null) { try { bind(bindaddr); diff --git a/jdk/src/java.base/share/classes/java/net/SocketImpl.java b/jdk/src/java.base/share/classes/java/net/SocketImpl.java index eef92f30b6e..7a30173a597 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, 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 @@ -386,6 +386,9 @@ public abstract class SocketImpl implements SocketOptions { setOption(SocketOptions.SO_RCVBUF, value); } else if (name == StandardSocketOptions.SO_REUSEADDR) { setOption(SocketOptions.SO_REUSEADDR, value); + } else if (name == StandardSocketOptions.SO_REUSEPORT && + supportedOptions().contains(name)) { + setOption(SocketOptions.SO_REUSEPORT, value); } else if (name == StandardSocketOptions.SO_LINGER && (getSocket() != null)) { setOption(SocketOptions.SO_LINGER, value); @@ -426,6 +429,9 @@ public abstract class SocketImpl implements SocketOptions { return (T)getOption(SocketOptions.SO_RCVBUF); } else if (name == StandardSocketOptions.SO_REUSEADDR) { return (T)getOption(SocketOptions.SO_REUSEADDR); + } else if (name == StandardSocketOptions.SO_REUSEPORT && + supportedOptions().contains(name)) { + return (T)getOption(SocketOptions.SO_REUSEPORT); } else if (name == StandardSocketOptions.SO_LINGER && (getSocket() != null)) { return (T)getOption(SocketOptions.SO_LINGER); diff --git a/jdk/src/java.base/share/classes/java/net/SocketOptions.java b/jdk/src/java.base/share/classes/java/net/SocketOptions.java index c846bbb9b12..fbfb81eca1a 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketOptions.java +++ b/jdk/src/java.base/share/classes/java/net/SocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -170,6 +170,17 @@ public interface SocketOptions { @Native public static final int SO_REUSEADDR = 0x04; + /** Sets SO_REUSEPORT for a socket. This option enables and disables + * the ability to have multiple sockets listen to the same address + * and port. + *

      + * Valid for: SocketImpl, DatagramSocketImpl + * + * @since 9 + * @see StandardSocketOptions#SO_REUSEPORT + */ + @Native public static final int SO_REUSEPORT = 0x0E; + /** * Sets SO_BROADCAST for a socket. This option enables and disables * the ability of the process to send broadcast messages. It is supported diff --git a/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java b/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java index 7fdd5f075d6..ae47845fae3 100644 --- a/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java +++ b/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -186,6 +186,29 @@ public final class StandardSocketOptions { public static final SocketOption SO_REUSEADDR = new StdSocketOption("SO_REUSEADDR", Boolean.class); + /** + * Re-use port. + * + *

      The value of this socket option is a {@code Boolean} that represents + * whether the option is enabled or disabled. The exact semantics of this + * socket option are socket type and system dependent. + * + *

      In the case of stream-oriented sockets, this socket option usually allows + * multiple listening sockets to be bound to both same address + * and same port. + * + *

      For datagram-oriented sockets the socket option usually allows + * multiple UDP sockets to be bound to the same address and port. + * + *

      An implementation allows this socket option to be set before the + * socket is bound or connected. Changing the value of this socket option + * after the socket is bound has no effect. + * + * @since 9 + */ + public static final SocketOption SO_REUSEPORT = + new StdSocketOption("SO_REUSEPORT", Boolean.class); + /** * Linger on close if data is present. * diff --git a/jdk/src/java.base/share/classes/jdk/net/Sockets.java b/jdk/src/java.base/share/classes/jdk/net/Sockets.java index 1ba53f29a15..a8b78b044d8 100644 --- a/jdk/src/java.base/share/classes/jdk/net/Sockets.java +++ b/jdk/src/java.base/share/classes/jdk/net/Sockets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -251,9 +251,23 @@ public class Sockets { } } + private static volatile boolean checkedReusePort; + private static volatile boolean isReusePortAvailable; + + /** + * Tells whether SO_REUSEPORT is supported. + */ + static boolean isReusePortAvailable() { + if (!checkedReusePort) { + isReusePortAvailable = isReusePortAvailable0(); + checkedReusePort = true; + } + return isReusePortAvailable; + } + private static void initOptionSets() { boolean flowsupported = ExtendedOptionsImpl.flowSupported(); - + boolean reuseportsupported = isReusePortAvailable(); // Socket Set> set = new HashSet<>(); @@ -261,6 +275,9 @@ public class Sockets { set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.SO_LINGER); set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.TCP_NODELAY); @@ -275,6 +292,9 @@ public class Sockets { set = new HashSet<>(); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); set = Collections.unmodifiableSet(set); options.put(ServerSocket.class, set); @@ -285,6 +305,9 @@ public class Sockets { set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); if (flowsupported) { set.add(ExtendedSocketOptions.SO_FLOW_SLA); @@ -298,6 +321,9 @@ public class Sockets { set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); @@ -308,4 +334,6 @@ public class Sockets { set = Collections.unmodifiableSet(set); options.put(MulticastSocket.class, set); } + + private static native boolean isReusePortAvailable0(); } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java index 8ed2c9f1317..39b19b42204 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -231,6 +231,9 @@ abstract class AsynchronousServerSocketChannelImpl HashSet> set = new HashSet<>(2); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } return Collections.unmodifiableSet(set); } } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index 3122b96a29f..36b3c1b7ab9 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -508,6 +508,9 @@ abstract class AsynchronousSocketChannelImpl set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_KEEPALIVE); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.TCP_NODELAY); if (ExtendedOptionsImpl.flowSupported()) { set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 7eb987991c9..77d14619222 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -298,6 +298,9 @@ class DatagramChannelImpl set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.SO_BROADCAST); set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.IP_MULTICAST_IF); diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java index 27c46a9ca2c..062ce35468e 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -56,6 +56,8 @@ public class Net { private static volatile boolean checkedIPv6; private static volatile boolean isIPv6Available; + private static volatile boolean checkedReusePort; + private static volatile boolean isReusePortAvailable; /** * Tells whether dual-IPv4/IPv6 sockets should be used. @@ -68,6 +70,17 @@ public class Net { return isIPv6Available; } + /** + * Tells whether SO_REUSEPORT is supported. + */ + static boolean isReusePortAvailable() { + if (!checkedReusePort) { + isReusePortAvailable = isReusePortAvailable0(); + checkedReusePort = true; + } + return isReusePortAvailable; + } + /** * Returns true if exclusive binding is on */ @@ -389,6 +402,8 @@ public class Net { private static native boolean isIPv6Available0(); + private static native boolean isReusePortAvailable0(); + /* * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS */ diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 2a427f1a352..9cfe7c43c4d 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -33,7 +33,6 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; - /** * An implementation of ServerSocketChannels */ @@ -185,6 +184,9 @@ class ServerSocketChannelImpl HashSet> set = new HashSet<>(2); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); return Collections.unmodifiableSet(set); } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index c4965e1111b..c4644920c3e 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -234,6 +234,9 @@ class SocketChannelImpl set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_KEEPALIVE); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.SO_LINGER); set.add(StandardSocketOptions.TCP_NODELAY); // additional options required by socket adaptor diff --git a/jdk/src/java.base/share/native/libnet/net_util.c b/jdk/src/java.base/share/native/libnet/net_util.c index e94903fd720..c2d4b002b04 100644 --- a/jdk/src/java.base/share/native/libnet/net_util.c +++ b/jdk/src/java.base/share/native/libnet/net_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -29,14 +29,21 @@ #include "net_util.h" int IPv6_supported() ; +int reuseport_supported() ; static int IPv6_available; +static int REUSEPORT_available; JNIEXPORT jint JNICALL ipv6_available() { return IPv6_available ; } +JNIEXPORT jint JNICALL reuseport_available() +{ + return REUSEPORT_available; +} + JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { @@ -45,7 +52,6 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) jmethodID mid; jstring s; jint preferIPv4Stack; - if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) { return JNI_EVERSION; /* JNI version not supported */ } @@ -64,6 +70,9 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) supporting socket APIs are available */ IPv6_available = IPv6_supported() & (!preferIPv4Stack); + + /* check if SO_REUSEPORT is supported on this platform */ + REUSEPORT_available = reuseport_supported(); platformInit(); parseExclusiveBindProperty(env); diff --git a/jdk/src/java.base/share/native/libnet/net_util.h b/jdk/src/java.base/share/native/libnet/net_util.h index f6b29297ecf..1d7b2a2c51e 100644 --- a/jdk/src/java.base/share/native/libnet/net_util.h +++ b/jdk/src/java.base/share/native/libnet/net_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -131,6 +131,8 @@ jfieldID NET_GetFileDescriptorID(JNIEnv *env); JNIEXPORT jint JNICALL ipv6_available() ; +JNIEXPORT jint JNICALL reuseport_available() ; + void NET_AllocSockaddr(struct sockaddr **him, int *len); diff --git a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java index 31715d40c82..f7c65931613 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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,7 +45,15 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl protected void setOption(SocketOption name, T value) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - super.setOption(name, value); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + super.setOption(name, value); + } else { + if (supportedOptions().contains(name)) { + super.setOption(name, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } else { if (!flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -62,7 +70,15 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - return super.getOption(name); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + return super.getOption(name); + } else { + if (supportedOptions().contains(name)) { + return super.getOption(name); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } if (!flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -87,6 +103,9 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl } protected void socketSetOption(int opt, Object val) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + throw new UnsupportedOperationException("unsupported option"); + } try { socketSetOption0(opt, val); } catch (SocketException se) { diff --git a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java index 272130bd6b9..2ec573ea5a9 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -59,7 +59,15 @@ class PlainSocketImpl extends AbstractPlainSocketImpl protected void setOption(SocketOption name, T value) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - super.setOption(name, value); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + super.setOption(name, value); + } else { + if (supportedOptions().contains(name)) { + super.setOption(name, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } else { if (getSocket() == null || !flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -76,7 +84,15 @@ class PlainSocketImpl extends AbstractPlainSocketImpl @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - return super.getOption(name); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + return super.getOption(name); + } else { + if (supportedOptions().contains(name)) { + return super.getOption(name); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } if (getSocket() == null || !flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -101,6 +117,9 @@ class PlainSocketImpl extends AbstractPlainSocketImpl } protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + throw new UnsupportedOperationException("unsupported option"); + } try { socketSetOption0(opt, b, val); } catch (SocketException se) { diff --git a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c index e6f18428769..034040baf83 100644 --- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c +++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -1392,6 +1392,7 @@ Java_java_net_PlainDatagramSocketImpl_socketSetOption0(JNIEnv *env, } case java_net_SocketOptions_SO_REUSEADDR: + case java_net_SocketOptions_SO_REUSEPORT: case java_net_SocketOptions_SO_BROADCAST: { jclass cls; @@ -1769,6 +1770,9 @@ Java_java_net_PlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this, case java_net_SocketOptions_SO_REUSEADDR: return createBoolean(env, optval.i); + case java_net_SocketOptions_SO_REUSEPORT: + return createBoolean(env, optval.i); + case java_net_SocketOptions_SO_SNDBUF: case java_net_SocketOptions_SO_RCVBUF: case java_net_SocketOptions_IP_TOS: diff --git a/jdk/src/java.base/unix/native/libnet/SdpSupport.c b/jdk/src/java.base/unix/native/libnet/SdpSupport.c index be8c46464fa..1fe5353fcd6 100644 --- a/jdk/src/java.base/unix/native/libnet/SdpSupport.c +++ b/jdk/src/java.base/unix/native/libnet/SdpSupport.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, 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 @@ -108,6 +108,11 @@ Java_sun_net_sdp_SdpSupport_convert0(JNIEnv *env, jclass cls, int fd) len = sizeof(arg); if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, &len) == 0) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, len); +#ifdef SO_REUSEPORT + len = sizeof(arg); + if (getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char*)&arg, &len) == 0) + setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (char*)&arg, len); +#endif len = sizeof(arg); if (getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, &len) == 0) setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, len); diff --git a/jdk/src/java.base/unix/native/libnet/SocketImpl.c b/jdk/src/java.base/unix/native/libnet/SocketImpl.c new file mode 100644 index 00000000000..3427b0ef405 --- /dev/null +++ b/jdk/src/java.base/unix/native/libnet/SocketImpl.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, 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 +#include + +#include "net_util.h" + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.c b/jdk/src/java.base/unix/native/libnet/net_util_md.c index f5645699d29..abad413e39c 100644 --- a/jdk/src/java.base/unix/native/libnet/net_util_md.c +++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -439,6 +439,25 @@ jint IPv6_supported() } #endif /* DONT_ENABLE_IPV6 */ +jint reuseport_supported() +{ + /* Do a simple dummy call, and try to figure out from that */ + int one = 1; + int rv, s; + s = socket(PF_INET, SOCK_STREAM, 0); + if (s < 0) { + return JNI_FALSE; + } + rv = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void *)&one, sizeof(one)); + if (rv != 0) { + rv = JNI_FALSE; + } else { + rv = JNI_TRUE; + } + close(s); + return rv; +} + void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, const char* hostname, int gai_error) @@ -1014,6 +1033,7 @@ NET_MapSocketOption(jint cmd, int *level, int *optname) { { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF }, { java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE }, { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR }, + { java_net_SocketOptions_SO_REUSEPORT, SOL_SOCKET, SO_REUSEPORT }, { java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST }, { java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS }, { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF }, diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.h b/jdk/src/java.base/unix/native/libnet/net_util_md.h index 31ed3f808eb..f440bd8ae6a 100644 --- a/jdk/src/java.base/unix/native/libnet/net_util_md.h +++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -60,6 +60,19 @@ void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, #define NET_WAIT_WRITE 0x02 #define NET_WAIT_CONNECT 0x04 +/* Defines SO_REUSEPORT */ +#ifndef SO_REUSEPORT +#ifdef __linux__ +#define SO_REUSEPORT 15 +#elif __solaris__ +#define SO_REUSEPORT 0x100e +#elif defined(AIX) || defined(MACOSX) +#define SO_REUSEPORT 0x0200 +#else +#define SO_REUSEPORT 0 +#endif +#endif + jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout); /************************************************************************ diff --git a/jdk/src/java.base/unix/native/libnio/ch/Net.c b/jdk/src/java.base/unix/native/libnio/ch/Net.c index 1010355bb76..a4032d69652 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/Net.c +++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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,12 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) return (ipv6_available()) ? JNI_TRUE : JNI_FALSE; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) { return -1; diff --git a/jdk/src/java.base/unix/native/libnio/ch/nio_util.h b/jdk/src/java.base/unix/native/libnio/ch/nio_util.h index 441ea20cc7c..c769dfbd49c 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/nio_util.h +++ b/jdk/src/java.base/unix/native/libnio/ch/nio_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -36,6 +36,18 @@ } while((_result == -1) && (errno == EINTR)); \ } while(0) +/* Defines SO_REUSEPORT */ +#ifndef SO_REUSEPORT +#ifdef __linux__ +#define SO_REUSEPORT 15 +#elif __solaris__ +#define SO_REUSEPORT 0x100e +#elif defined(AIX) || defined(MACOSX) +#define SO_REUSEPORT 0x0200 +#else +#define SO_REUSEPORT 0 +#endif +#endif /* NIO utility procedures */ diff --git a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java index 88a7ddcfdb0..8f464ddfd07 100644 --- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -167,6 +167,11 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl int optionValue = 0; + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } + switch(opt) { case IP_TOS : case SO_RCVBUF : @@ -200,6 +205,9 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl } if (opt == SO_REUSEADDR && reuseAddressEmulated) return isReuseAddress; + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) + throw new UnsupportedOperationException("unsupported option"); int value = socketGetIntOption(nativefd, opt); Object returnValue = null; diff --git a/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java index 6792a411842..3d681db1dd6 100644 --- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -181,6 +181,10 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl if (opt == SO_TIMEOUT) { // timeout implemented through select. return; } + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } int optionValue = 0; @@ -224,6 +228,10 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl localAddress(nativefd, (InetAddressContainer)iaContainerObj); return 0; // return value doesn't matter. } + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } // SO_REUSEADDR emulated when using exclusive bind if (opt == SO_REUSEADDR && exclusiveBind) diff --git a/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java index 938d995593b..259a39ac195 100644 --- a/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -173,10 +173,18 @@ class PlainSocketImpl extends AbstractPlainSocketImpl } public void setOption(int opt, Object val) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } impl.setOption(opt, val); } public Object getOption(int opt) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } return impl.getOption(opt); } @@ -332,14 +340,27 @@ class PlainSocketImpl extends AbstractPlainSocketImpl void socketSetOption(int cmd, boolean on, Object value) throws SocketException { + if (cmd == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } impl.socketSetOption(cmd, on, value); } int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } return impl.socketGetOption(opt, iaContainerObj); } void socketSendUrgentData(int data) throws IOException { impl.socketSendUrgentData(data); } + + static boolean isReusePortAvailable() { + // SO_REUSEPORT is not supported on Windows. + return false; + } } diff --git a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java index 9bdb8d5c6e1..7198b49671e 100644 --- a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -130,6 +130,9 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl return socketLocalAddress(family); } else if (optID == SO_REUSEADDR && reuseAddressEmulated) { return isReuseAddress; + } else if (optID == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); } else { return super.getOption(optID); } @@ -142,6 +145,9 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl // socket already bound, emulate reuseAddressEmulated = true; isReuseAddress = (Boolean)val; + } else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); } else { socketNativeSetOption(opt, val); } diff --git a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java index a8be4000d93..4f0b132520e 100644 --- a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -128,6 +128,9 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl } else if (opt == SO_REUSEADDR && exclusiveBind) { // SO_REUSEADDR emulated when using exclusive bind return isReuseAddress; + } else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); } else return super.getOption(opt); } @@ -144,6 +147,10 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl // SO_REUSEADDR emulated when using exclusive bind if (opt == SO_REUSEADDR && exclusiveBind) isReuseAddress = on; + else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } else socketNativeSetOption(opt, on, value); } diff --git a/jdk/src/java.base/windows/native/libnet/SocketImpl.c b/jdk/src/java.base/windows/native/libnet/SocketImpl.c new file mode 100644 index 00000000000..8e5745de8d3 --- /dev/null +++ b/jdk/src/java.base/windows/native/libnet/SocketImpl.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, 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 + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.c b/jdk/src/java.base/windows/native/libnet/net_util_md.c index 8a0f5c15275..4868201c1f3 100644 --- a/jdk/src/java.base/windows/native/libnet/net_util_md.c +++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -242,6 +242,11 @@ jint IPv6_supported() return JNI_TRUE; } +jint reuseport_supported() +{ + /* SO_REUSEPORT is not supported onn Windows */ + return JNI_FALSE; +} /* * Return the default TOS value */ diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.h b/jdk/src/java.base/windows/native/libnet/net_util_md.h index db6971616bf..5ac48046f3b 100644 --- a/jdk/src/java.base/windows/native/libnet/net_util_md.h +++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h @@ -54,6 +54,9 @@ #else +/*SO_REUSEPORT is not supported on Windows, define it to 0*/ +#define SO_REUSEPORT 0 + /* Retain this code a little longer to support building in * old environments. _MSC_VER is defined as: * 1200 for MSVC++ 6.0 @@ -353,3 +356,4 @@ JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0_XP JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP (JNIEnv *env, jclass cls, jstring name, jint index); + diff --git a/jdk/src/java.base/windows/native/libnio/ch/Net.c b/jdk/src/java.base/windows/native/libnio/ch/Net.c index 12f3c190c49..c7702006d27 100644 --- a/jdk/src/java.base/windows/native/libnio/ch/Net.c +++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -93,6 +93,13 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) return ipv6_available() ? JNI_TRUE : JNI_FALSE; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) { return 1; diff --git a/jdk/test/java/net/SocketOption/OptionsTest.java b/jdk/test/java/net/SocketOption/OptionsTest.java index 947d784aa9d..5b109d533ac 100644 --- a/jdk/test/java/net/SocketOption/OptionsTest.java +++ b/jdk/test/java/net/SocketOption/OptionsTest.java @@ -54,6 +54,7 @@ public class OptionsTest { Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) }; @@ -61,6 +62,7 @@ public class OptionsTest { static Test[] serverSocketTests = new Test[] { Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) }; @@ -68,6 +70,7 @@ public class OptionsTest { Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) }; @@ -97,15 +100,19 @@ public class OptionsTest { Socket c = new Socket("127.0.0.1", srv.getLocalPort()); Socket s = srv.accept(); ) { + Set> options = c.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); for (int i=0; i> options = c.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); for (int i=0; i> options = c.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); for (int i=0; i> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) { return Boolean.valueOf(socket.getKeepAlive()); @@ -183,6 +200,8 @@ public class OptionsTest { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.SO_LINGER)) { return Integer.valueOf(socket.getSoLinger()); } else if (option.equals(StandardSocketOptions.IP_TOS)) { @@ -194,10 +213,15 @@ public class OptionsTest { } } else if (type.equals(ServerSocket.class)) { ServerSocket socket = (ServerSocket)s; + Set> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); + if (option.equals(StandardSocketOptions.SO_RCVBUF)) { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(jdk.net.Sockets.getOption( socket, StandardSocketOptions.IP_TOS)); @@ -206,6 +230,8 @@ public class OptionsTest { } } else if (type.equals(DatagramSocket.class)) { DatagramSocket socket = (DatagramSocket)s; + Set> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); if (option.equals(StandardSocketOptions.SO_SNDBUF)) { return Integer.valueOf(socket.getSendBufferSize()); @@ -213,6 +239,8 @@ public class OptionsTest { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(socket.getTrafficClass()); } else { @@ -221,6 +249,8 @@ public class OptionsTest { } else if (type.equals(MulticastSocket.class)) { MulticastSocket socket = (MulticastSocket)s; + Set> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); if (option.equals(StandardSocketOptions.SO_SNDBUF)) { return Integer.valueOf(socket.getSendBufferSize()); @@ -228,6 +258,8 @@ public class OptionsTest { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(socket.getTrafficClass()); } else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) { diff --git a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java index 753629f8e1b..c3450df7d23 100644 --- a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -141,8 +141,11 @@ public class Basic { try { // check supported options Set> options = ch.supportedOptions(); + boolean reuseport = options.contains(SO_REUSEPORT); if (!options.contains(SO_REUSEADDR)) throw new RuntimeException("SO_REUSEADDR should be supported"); + if (!options.contains(SO_REUSEPORT) && reuseport) + throw new RuntimeException("SO_REUSEPORT should be supported"); if (!options.contains(SO_RCVBUF)) throw new RuntimeException("SO_RCVBUF should be supported"); @@ -156,6 +159,13 @@ public class Basic { checkOption(ch, SO_REUSEADDR, true); ch.setOption(SO_REUSEADDR, false); checkOption(ch, SO_REUSEADDR, false); + + if (reuseport) { + ch.setOption(SO_REUSEPORT, true); + checkOption(ch, SO_REUSEPORT, true); + ch.setOption(SO_REUSEPORT, false); + checkOption(ch, SO_REUSEPORT, false); + } } finally { ch.close(); } diff --git a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java index 23d9eb36e4e..c833735eb0f 100644 --- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -37,6 +37,7 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.io.Closeable; import java.io.IOException; +import java.util.Set; public class Basic { static final Random rand = new Random(); @@ -165,6 +166,15 @@ public class Basic { // read others (can't check as actual value is implementation dependent) ch.getOption(SO_RCVBUF); ch.getOption(SO_SNDBUF); + + Set> options = ch.supportedOptions(); + boolean reuseport = options.contains(SO_REUSEPORT); + if (reuseport) { + if (ch.getOption(SO_REUSEPORT)) + throw new RuntimeException("Default of SO_REUSEPORT should be 'false'"); + if (!ch.setOption(SO_REUSEPORT, true).getOption(SO_REUSEPORT)) + throw new RuntimeException("SO_REUSEPORT did not change"); + } } } diff --git a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java index bc7146cc982..40aef3282ac 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -50,9 +50,17 @@ public class SocketOptionTests { // check supported options Set> options = dc.supportedOptions(); - List> expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, - SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL, - IP_MULTICAST_LOOP); + boolean reuseport = options.contains(SO_REUSEPORT); + List> expected; + if (reuseport) { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, + SO_REUSEADDR, SO_REUSEPORT, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, + IP_MULTICAST_TTL, IP_MULTICAST_LOOP); + } else { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, + SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL, + IP_MULTICAST_LOOP); + } for (SocketOption opt: expected) { if (!options.contains(opt)) throw new RuntimeException(opt.name() + " should be supported"); @@ -83,7 +91,12 @@ public class SocketOptionTests { checkOption(dc, SO_REUSEADDR, true); dc.setOption(SO_REUSEADDR, false); checkOption(dc, SO_REUSEADDR, false); - + if (reuseport) { + dc.setOption(SO_REUSEPORT, true); + checkOption(dc, SO_REUSEPORT, true); + dc.setOption(SO_REUSEPORT, false); + checkOption(dc, SO_REUSEPORT, false); + } // bind socket dc.bind(new InetSocketAddress(0)); diff --git a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java index a7756989290..0a3aa9dee32 100644 --- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -49,8 +49,11 @@ public class SocketOptionTests { // check supported options Set> options = ssc.supportedOptions(); + boolean reuseport = options.contains(SO_REUSEPORT); if (!options.contains(SO_REUSEADDR)) throw new RuntimeException("SO_REUSEADDR should be supported"); + if (!options.contains(SO_REUSEPORT) && reuseport) + throw new RuntimeException("SO_REUSEPORT should be supported"); if (!options.contains(SO_RCVBUF)) throw new RuntimeException("SO_RCVBUF should be supported"); @@ -64,6 +67,12 @@ public class SocketOptionTests { checkOption(ssc, SO_REUSEADDR, true); ssc.setOption(SO_REUSEADDR, false); checkOption(ssc, SO_REUSEADDR, false); + if (reuseport) { + ssc.setOption(SO_REUSEPORT, true); + checkOption(ssc, SO_REUSEPORT, true); + ssc.setOption(SO_REUSEPORT, false); + checkOption(ssc, SO_REUSEPORT, false); + } // NullPointerException try { From e9d44ad2ca2a253a7784c01c1931474e5649e065 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 23 Feb 2016 10:51:37 -0800 Subject: [PATCH 080/311] 8150434: Remove redundant "jdk_localedata" from the CLDR locale data meta info class name Reviewed-by: mchung --- .../build/tools/cldrconverter/ResourceBundleGenerator.java | 5 +---- .../services/sun.util.locale.provider.LocaleDataMetaInfo | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java index c2f16e823cf..500cf2b10e4 100644 --- a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java @@ -248,10 +248,7 @@ class ResourceBundleGenerator implements BundleGenerator { dir.mkdirs(); } String className = - (CLDRConverter.isBaseModule ? "CLDRBaseLocaleDataMetaInfo" : - "CLDRLocaleDataMetaInfo_" + - CLDRConverter.DESTINATION_DIR.substring(CLDRConverter.DESTINATION_DIR.lastIndexOf('/')+1) - .replaceAll("\\.", "_")); + (CLDRConverter.isBaseModule ? "CLDRBaseLocaleDataMetaInfo" : "CLDRLocaleDataMetaInfo"); File file = new File(dir, className + ".java"); if (!file.exists()) { file.createNewFile(); diff --git a/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo b/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo index b2a0b3ad6c7..076f3b15265 100644 --- a/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo +++ b/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo @@ -1,2 +1,2 @@ sun.util.resources.provider.NonBaseLocaleDataMetaInfo -sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo_jdk_localedata +sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo From 7386fd03857982ae1ab216e8c093a5e17ae7229f Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 23 Feb 2016 22:10:02 +0300 Subject: [PATCH 081/311] 8148146: Integrate new internal Unsafe entry points, and basic intrinsic support for VarHandles Reviewed-by: psandoz, kvn, jrose, adinn, simonis, coleenp --- .../classes/jdk/internal/misc/Unsafe.java | 355 ++++++++++++++++++ 1 file changed, 355 insertions(+) diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index 5818d4835a1..8905977111b 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -782,6 +782,46 @@ public final class Unsafe { Object expected, Object x); + @HotSpotIntrinsicCandidate + public final native Object compareAndExchangeObjectVolatile(Object o, long offset, + Object expected, + Object x); + + @HotSpotIntrinsicCandidate + public final Object compareAndExchangeObjectAcquire(Object o, long offset, + Object expected, + Object x) { + return compareAndExchangeObjectVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final Object compareAndExchangeObjectRelease(Object o, long offset, + Object expected, + Object x) { + return compareAndExchangeObjectVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapObject(Object o, long offset, + Object expected, + Object x) { + return compareAndSwapObject(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapObjectAcquire(Object o, long offset, + Object expected, + Object x) { + return compareAndSwapObject(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapObjectRelease(Object o, long offset, + Object expected, + Object x) { + return compareAndSwapObject(o, offset, expected, x); + } + /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. @@ -796,6 +836,46 @@ public final class Unsafe { int expected, int x); + @HotSpotIntrinsicCandidate + public final native int compareAndExchangeIntVolatile(Object o, long offset, + int expected, + int x); + + @HotSpotIntrinsicCandidate + public final int compareAndExchangeIntAcquire(Object o, long offset, + int expected, + int x) { + return compareAndExchangeIntVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final int compareAndExchangeIntRelease(Object o, long offset, + int expected, + int x) { + return compareAndExchangeIntVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapInt(Object o, long offset, + int expected, + int x) { + return compareAndSwapInt(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapIntAcquire(Object o, long offset, + int expected, + int x) { + return compareAndSwapInt(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapIntRelease(Object o, long offset, + int expected, + int x) { + return compareAndSwapInt(o, offset, expected, x); + } + /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. @@ -810,6 +890,46 @@ public final class Unsafe { long expected, long x); + @HotSpotIntrinsicCandidate + public final native long compareAndExchangeLongVolatile(Object o, long offset, + long expected, + long x); + + @HotSpotIntrinsicCandidate + public final long compareAndExchangeLongAcquire(Object o, long offset, + long expected, + long x) { + return compareAndExchangeLongVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final long compareAndExchangeLongRelease(Object o, long offset, + long expected, + long x) { + return compareAndExchangeLongVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapLong(Object o, long offset, + long expected, + long x) { + return compareAndSwapLong(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapLongAcquire(Object o, long offset, + long expected, + long x) { + return compareAndSwapLong(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapLongRelease(Object o, long offset, + long expected, + long x) { + return compareAndSwapLong(o, offset, expected, x); + } + /** * Fetches a reference value from a given Java variable, with volatile * load semantics. Otherwise identical to {@link #getObject(Object, long)} @@ -908,6 +1028,224 @@ public final class Unsafe { @HotSpotIntrinsicCandidate public native void putOrderedLong(Object o, long offset, long x); + /** Acquire version of {@link #getObjectVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final Object getObjectAcquire(Object o, long offset) { + return getObjectVolatile(o, offset); + } + + /** Acquire version of {@link #getBooleanVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final boolean getBooleanAcquire(Object o, long offset) { + return getBooleanVolatile(o, offset); + } + + /** Acquire version of {@link #getByteVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final byte getByteAcquire(Object o, long offset) { + return getByteVolatile(o, offset); + } + + /** Acquire version of {@link #getShortVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final short getShortAcquire(Object o, long offset) { + return getShortVolatile(o, offset); + } + + /** Acquire version of {@link #getCharVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final char getCharAcquire(Object o, long offset) { + return getCharVolatile(o, offset); + } + + /** Acquire version of {@link #getIntVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final int getIntAcquire(Object o, long offset) { + return getIntVolatile(o, offset); + } + + /** Acquire version of {@link #getFloatVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final float getFloatAcquire(Object o, long offset) { + return getFloatVolatile(o, offset); + } + + /** Acquire version of {@link #getLongVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final long getLongAcquire(Object o, long offset) { + return getLongVolatile(o, offset); + } + + /** Acquire version of {@link #getDoubleVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final double getDoubleAcquire(Object o, long offset) { + return getDoubleVolatile(o, offset); + } + + /** Release version of {@link #putObjectVolatile(Object, long, Object)} */ + @HotSpotIntrinsicCandidate + public final void putObjectRelease(Object o, long offset, Object x) { + putObjectVolatile(o, offset, x); + } + + /** Release version of {@link #putBooleanVolatile(Object, long, boolean)} */ + @HotSpotIntrinsicCandidate + public final void putBooleanRelease(Object o, long offset, boolean x) { + putBooleanVolatile(o, offset, x); + } + + /** Release version of {@link #putByteVolatile(Object, long, byte)} */ + @HotSpotIntrinsicCandidate + public final void putByteRelease(Object o, long offset, byte x) { + putByteVolatile(o, offset, x); + } + + /** Release version of {@link #putShortVolatile(Object, long, short)} */ + @HotSpotIntrinsicCandidate + public final void putShortRelease(Object o, long offset, short x) { + putShortVolatile(o, offset, x); + } + + /** Release version of {@link #putCharVolatile(Object, long, char)} */ + @HotSpotIntrinsicCandidate + public final void putCharRelease(Object o, long offset, char x) { + putCharVolatile(o, offset, x); + } + + /** Release version of {@link #putIntVolatile(Object, long, int)} */ + @HotSpotIntrinsicCandidate + public final void putIntRelease(Object o, long offset, int x) { + putIntVolatile(o, offset, x); + } + + /** Release version of {@link #putFloatVolatile(Object, long, float)} */ + @HotSpotIntrinsicCandidate + public final void putFloatRelease(Object o, long offset, float x) { + putFloatVolatile(o, offset, x); + } + + /** Release version of {@link #putLongVolatile(Object, long, long)} */ + @HotSpotIntrinsicCandidate + public final void putLongRelease(Object o, long offset, long x) { + putLongVolatile(o, offset, x); + } + + /** Release version of {@link #putDoubleVolatile(Object, long, double)} */ + @HotSpotIntrinsicCandidate + public final void putDoubleRelease(Object o, long offset, double x) { + putDoubleVolatile(o, offset, x); + } + + // ------------------------------ Opaque -------------------------------------- + + /** Opaque version of {@link #getObjectVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final Object getObjectOpaque(Object o, long offset) { + return getObjectVolatile(o, offset); + } + + /** Opaque version of {@link #getBooleanVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final boolean getBooleanOpaque(Object o, long offset) { + return getBooleanVolatile(o, offset); + } + + /** Opaque version of {@link #getByteVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final byte getByteOpaque(Object o, long offset) { + return getByteVolatile(o, offset); + } + + /** Opaque version of {@link #getShortVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final short getShortOpaque(Object o, long offset) { + return getShortVolatile(o, offset); + } + + /** Opaque version of {@link #getCharVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final char getCharOpaque(Object o, long offset) { + return getCharVolatile(o, offset); + } + + /** Opaque version of {@link #getIntVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final int getIntOpaque(Object o, long offset) { + return getIntVolatile(o, offset); + } + + /** Opaque version of {@link #getFloatVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final float getFloatOpaque(Object o, long offset) { + return getFloatVolatile(o, offset); + } + + /** Opaque version of {@link #getLongVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final long getLongOpaque(Object o, long offset) { + return getLongVolatile(o, offset); + } + + /** Opaque version of {@link #getDoubleVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final double getDoubleOpaque(Object o, long offset) { + return getDoubleVolatile(o, offset); + } + + /** Opaque version of {@link #putObjectVolatile(Object, long, Object)} */ + @HotSpotIntrinsicCandidate + public final void putObjectOpaque(Object o, long offset, Object x) { + putObjectVolatile(o, offset, x); + } + + /** Opaque version of {@link #putBooleanVolatile(Object, long, boolean)} */ + @HotSpotIntrinsicCandidate + public final void putBooleanOpaque(Object o, long offset, boolean x) { + putBooleanVolatile(o, offset, x); + } + + /** Opaque version of {@link #putByteVolatile(Object, long, byte)} */ + @HotSpotIntrinsicCandidate + public final void putByteOpaque(Object o, long offset, byte x) { + putByteVolatile(o, offset, x); + } + + /** Opaque version of {@link #putShortVolatile(Object, long, short)} */ + @HotSpotIntrinsicCandidate + public final void putShortOpaque(Object o, long offset, short x) { + putShortVolatile(o, offset, x); + } + + /** Opaque version of {@link #putCharVolatile(Object, long, char)} */ + @HotSpotIntrinsicCandidate + public final void putCharOpaque(Object o, long offset, char x) { + putCharVolatile(o, offset, x); + } + + /** Opaque version of {@link #putIntVolatile(Object, long, int)} */ + @HotSpotIntrinsicCandidate + public final void putIntOpaque(Object o, long offset, int x) { + putIntVolatile(o, offset, x); + } + + /** Opaque version of {@link #putFloatVolatile(Object, long, float)} */ + @HotSpotIntrinsicCandidate + public final void putFloatOpaque(Object o, long offset, float x) { + putFloatVolatile(o, offset, x); + } + + /** Opaque version of {@link #putLongVolatile(Object, long, long)} */ + @HotSpotIntrinsicCandidate + public final void putLongOpaque(Object o, long offset, long x) { + putLongVolatile(o, offset, x); + } + + /** Opaque version of {@link #putDoubleVolatile(Object, long, double)} */ + @HotSpotIntrinsicCandidate + public final void putDoubleOpaque(Object o, long offset, double x) { + putDoubleVolatile(o, offset, x); + } + /** * Unblocks the given thread blocked on {@code park}, or, if it is * not blocked, causes the subsequent call to {@code park} not to @@ -1100,6 +1438,23 @@ public final class Unsafe { @HotSpotIntrinsicCandidate public native void fullFence(); + /** + * Ensures that loads before the fence will not be reordered with + * loads after the fence. + */ + public final void loadLoadFence() { + loadFence(); + } + + /** + * Ensures that stores before the fence will not be reordered with + * stores after the fence. + */ + public final void storeStoreFence() { + storeFence(); + } + + /** * Throws IllegalAccessError; for use by the VM for access control * error support. From 68832ef0f69365ad4a6a783cc8c8a2a17d2496e4 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 23 Feb 2016 11:17:02 -0800 Subject: [PATCH 082/311] 8150427: Demote ToolReloadTest.java and mark as intermittently failing Reviewed-by: jjg --- langtools/test/TEST.groups | 10 ++++++---- langtools/test/jdk/jshell/ToolReloadTest.java | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/langtools/test/TEST.groups b/langtools/test/TEST.groups index 0065d8ec397..8a77c0804f1 100644 --- a/langtools/test/TEST.groups +++ b/langtools/test/TEST.groups @@ -22,15 +22,17 @@ # Tiered testing definitions -# All langtools tests are tier 1. +# (Nearly) all langtools tests are tier 1. tier1 = \ com \ jdk \ lib \ - tools + tools \ + -jdk/jshell/ToolReloadTest.java -# No langtools tests are tier 2. -tier2 = +# (Almost) no langtools tests are tier 2. +tier2 = \ + jdk/jshell/ToolReloadTest.java # No langtools tests are tier 3 either. tier3 = diff --git a/langtools/test/jdk/jshell/ToolReloadTest.java b/langtools/test/jdk/jshell/ToolReloadTest.java index 44578dec261..4871fccd946 100644 --- a/langtools/test/jdk/jshell/ToolReloadTest.java +++ b/langtools/test/jdk/jshell/ToolReloadTest.java @@ -23,6 +23,7 @@ /* * @test + * @key intermittent * @bug 8081845 8147898 * @summary Tests for /reload in JShell tool * @modules jdk.compiler/com.sun.tools.javac.api From 4513cbc5745bde2e7bef4a68bf22c3e8f872365d Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 23 Feb 2016 21:43:59 +0100 Subject: [PATCH 083/311] 8150257: Remove softfloat lib support Reviewed-by: dholmes, erikj --- make/common/NativeCompilation.gmk | 4 ---- 1 file changed, 4 deletions(-) diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index ffae49df541..f675790efc6 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -776,8 +776,6 @@ define SetupNativeCompilationBody $1_EXTRA_LDFLAGS += $(COMPILER_BINDCMD_FILE_FLAG)$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).loadmap endif - $1_EXTRA_LIBS += $(GLOBAL_LIBS) - $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_CREATE_DEBUGINFO_CMDS) \ $$($1_STRIP_CMD) @@ -854,8 +852,6 @@ define SetupNativeCompilationBody ifneq (,$$($1_PROGRAM)) # A executable binary has been specified, setup the target for it. - $1_EXTRA_LIBS += $(GLOBAL_LIBS) - $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \ $$($1_CODESIGN) $$($1_CREATE_DEBUGINFO_CMDS) $$($1_MANIFEST_VERSION) \ From 4e4d31d0a9bd54f2251f10ae956bd7579a390ab4 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Tue, 23 Feb 2016 21:44:05 +0100 Subject: [PATCH 084/311] 8150257: Remove softfloat lib support Reviewed-by: dholmes, erikj --- hotspot/make/bsd/makefiles/arm.make | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hotspot/make/bsd/makefiles/arm.make b/hotspot/make/bsd/makefiles/arm.make index f35f70a579b..9e6fdd5abae 100644 --- a/hotspot/make/bsd/makefiles/arm.make +++ b/hotspot/make/bsd/makefiles/arm.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2008, 2016, 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 @@ -24,8 +24,4 @@ Obj_Files += bsd_arm.o -ifneq ($(EXT_LIBS_PATH),) - LIBS += $(EXT_LIBS_PATH)/sflt_glibc.a -endif - CFLAGS += -DVM_LITTLE_ENDIAN From 1036ce73ea11c37337c2d84c9fd6ae60e07df021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Bourg=C3=A8s?= Date: Tue, 23 Feb 2016 22:07:27 +0100 Subject: [PATCH 085/311] 8148886: SEGV in sun.java2d.marlin.Renderer._endRendering Handle reentrancy in both AAShapePipe and MarlinRenderingEngine using new sun.java2d.ReentrantContextProvider implementations Reviewed-by: flar, prr --- .../classes/sun/java2d/ReentrantContext.java | 43 ++++ .../sun/java2d/ReentrantContextProvider.java | 169 +++++++++++++++ .../java2d/ReentrantContextProviderCLQ.java | 89 ++++++++ .../java2d/ReentrantContextProviderTL.java | 123 +++++++++++ .../sun/java2d/marlin/ByteArrayCache.java | 9 +- .../sun/java2d/marlin/FloatArrayCache.java | 9 +- .../sun/java2d/marlin/IntArrayCache.java | 9 +- .../sun/java2d/marlin/MarlinCache.java | 6 +- .../java2d/marlin/MarlinRenderingEngine.java | 76 +++---- .../sun/java2d/marlin/RendererContext.java | 31 +-- .../classes/sun/java2d/marlin/Version.java | 4 +- .../classes/sun/java2d/pipe/AAShapePipe.java | 141 ++++++------ .../sun/java2d/marlin/CrashPaintTest.java | 205 ++++++++++++++++++ 13 files changed, 767 insertions(+), 147 deletions(-) create mode 100644 jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContext.java create mode 100644 jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProvider.java create mode 100644 jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderCLQ.java create mode 100644 jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java create mode 100644 jdk/test/sun/java2d/marlin/CrashPaintTest.java diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContext.java b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContext.java new file mode 100644 index 00000000000..fc067b0070d --- /dev/null +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContext.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 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. + */ +package sun.java2d; + +import java.lang.ref.Reference; + +/** + * ReentrantContext is a base class to hold thread-local data supporting + * reentrancy in either a ThreadLocal or a ConcurrentLinkedQueue + * + * @see ReentrantContextProvider + */ +public class ReentrantContext { + // usage stored as a byte + byte usage = ReentrantContextProvider.USAGE_TL_INACTIVE; + /* + * Reference to this instance (hard, soft or weak). + * @see ReentrantContextProvider#refType + */ + Reference reference = null; +} diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProvider.java b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProvider.java new file mode 100644 index 00000000000..92132aabcc4 --- /dev/null +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProvider.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2016, 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. + */ +package sun.java2d; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; + +/** + * This abstract ReentrantContextProvider helper class manages the creation, + * storage, and retrieval of concrete ReentrantContext instances which can be + * subclassed to hold cached contextual data. + * + * It supports reentrancy as every call to acquire() provides a new unique context + * instance that must later be returned for reuse by a call to release(ctx) + * (typically in a try/finally block). + * + * It has a couple of abstract implementations which store references in a queue + * and/or thread-local storage. + * The Providers can be configured to hold ReentrantContext instances in memory + * using hard, soft or weak references. + * + * The acquire() and release() methods are used to retrieve and return the contexts. + * + * The {@code newContext()} method remains abstract in all implementations and + * must be provided by the module to create a new subclass of ReentrantContext + * with the appropriate contextual data in it. + * + * Sample Usage: + * - create a subclass ReentrantContextImpl to hold the thread state: + * + * static final class ReentrantContextImpl extends ReentrantContext { + * // specific cached data + * } + * + * - create the appropriate ReentrantContextProvider: + * + * private static final ReentrantContextProvider contextProvider = + * new ReentrantContextProviderTL(ReentrantContextProvider.REF_WEAK) + * { + * @Override + * protected ReentrantContextImpl newContext() { + * return new ReentrantContextImpl(); + * } + * }; + * ... + * void someMethod() { + * ReentrantContextImpl ctx = contextProvider.acquire(); + * try { + * // use the context + * } finally { + * contextProvider.release(ctx); + * } + * } + * + * @param ReentrantContext subclass + * + * @see ReentrantContext + */ +public abstract class ReentrantContextProvider +{ + // thread-local storage: inactive + static final byte USAGE_TL_INACTIVE = 0; + // thread-local storage: in use + static final byte USAGE_TL_IN_USE = 1; + // CLQ storage + static final byte USAGE_CLQ = 2; + + // hard reference + public static final int REF_HARD = 0; + // soft reference + public static final int REF_SOFT = 1; + // weak reference + public static final int REF_WEAK = 2; + + /* members */ + // internal reference type + private final int refType; + + /** + * Create a new ReentrantContext provider using the given reference type + * among hard, soft or weak + * + * @param refType reference type + */ + protected ReentrantContextProvider(final int refType) { + this.refType = refType; + } + + /** + * Create a new ReentrantContext instance + * + * @return new ReentrantContext instance + */ + protected abstract K newContext(); + + /** + * Give a ReentrantContext instance for the current thread + * + * @return ReentrantContext instance + */ + public abstract K acquire(); + + /** + * Restore the given ReentrantContext instance for reuse + * + * @param ctx ReentrantContext instance + */ + public abstract void release(K ctx); + + @SuppressWarnings("unchecked") + protected final Reference getOrCreateReference(final K ctx) { + if (ctx.reference == null) { + // Create the reference: + switch (refType) { + case REF_HARD: + ctx.reference = new HardReference(ctx); + break; + case REF_SOFT: + ctx.reference = new SoftReference(ctx); + break; + default: + case REF_WEAK: + ctx.reference = new WeakReference(ctx); + break; + } + } + return (Reference) ctx.reference; + } + + /* Missing HardReference implementation */ + static final class HardReference extends WeakReference { + // kept strong reference: + private final V strongRef; + + HardReference(final V referent) { + // no referent needed for the parent WeakReference: + super(null); + this.strongRef = referent; + } + + @Override + public V get() { + return strongRef; + } + } +} diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderCLQ.java b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderCLQ.java new file mode 100644 index 00000000000..22978cef888 --- /dev/null +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderCLQ.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016, 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. + */ +package sun.java2d; + +import java.lang.ref.Reference; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * This ReentrantContextProvider implementation uses one ConcurrentLinkedQueue + * to store all ReentrantContext instances (thread and its child contexts) + * + * Note: this implementation keeps less contexts in memory depending on the + * concurrent active threads in contrary to a ThreadLocal provider. However, + * it is slower in highly concurrent workloads. + * + * @param ReentrantContext subclass + */ +public abstract class ReentrantContextProviderCLQ + extends ReentrantContextProvider +{ + // ReentrantContext queue to store all contexts + private final ConcurrentLinkedQueue> ctxQueue + = new ConcurrentLinkedQueue>(); + + /** + * Create a new ReentrantContext provider using the given reference type + * among hard, soft or weak based using a ConcurrentLinkedQueue storage + * + * @param refType reference type + */ + public ReentrantContextProviderCLQ(final int refType) { + super(refType); + } + + /** + * Give a ReentrantContext instance for the current thread + * + * @return ReentrantContext instance + */ + @Override + public final K acquire() { + K ctx = null; + // Drain queue if all referent are null: + Reference ref = null; + while ((ctx == null) && ((ref = ctxQueue.poll()) != null)) { + ctx = ref.get(); + } + if (ctx == null) { + // create a new ReentrantContext if none is available + ctx = newContext(); + ctx.usage = USAGE_CLQ; + } + return ctx; + } + + /** + * Restore the given ReentrantContext instance for reuse + * + * @param ctx ReentrantContext instance + */ + @Override + public final void release(final K ctx) { + if (ctx.usage == USAGE_CLQ) { + ctxQueue.offer(getOrCreateReference(ctx)); + } + } +} diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java new file mode 100644 index 00000000000..14dcb84d6d5 --- /dev/null +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016, 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. + */ +package sun.java2d; + +import java.lang.ref.Reference; + +/** +* This ReentrantContextProvider implementation uses a ThreadLocal to hold + * the first ReentrantContext per thread and a ReentrantContextProviderCLQ to + * store child ReentrantContext instances needed during recursion. + * + * Note: this implementation may keep up to one context in memory per thread. + * Child contexts for recursive uses are stored in the queue using a WEAK + * reference by default unless specified in the 2 argument constructor. + * + * @param ReentrantContext subclass + */ +public abstract class ReentrantContextProviderTL + extends ReentrantContextProvider +{ + // Thread-local storage: + private final ThreadLocal> ctxTL + = new ThreadLocal>(); + + // ReentrantContext CLQ provider for child contexts: + private final ReentrantContextProviderCLQ ctxProviderCLQ; + + /** + * Create a new ReentrantContext provider using the given reference type + * among hard, soft or weak. + * It uses weak reference for the child contexts. + * + * @param refType reference type + */ + public ReentrantContextProviderTL(final int refType) { + this(refType, REF_WEAK); + } + + /** + * Create a new ReentrantContext provider using the given reference types + * among hard, soft or weak + * + * @param refTypeTL reference type used by ThreadLocal + * @param refTypeCLQ reference type used by ReentrantContextProviderCLQ + */ + public ReentrantContextProviderTL(final int refTypeTL, final int refTypeCLQ) + { + super(refTypeTL); + + final ReentrantContextProviderTL parent = this; + + this.ctxProviderCLQ = new ReentrantContextProviderCLQ(refTypeCLQ) { + @Override + protected K newContext() { + return parent.newContext(); + } + }; + } + + /** + * Give a ReentrantContext instance for the current thread + * + * @return ReentrantContext instance + */ + @Override + public final K acquire() { + K ctx = null; + final Reference ref = ctxTL.get(); + if (ref != null) { + ctx = ref.get(); + } + if (ctx == null) { + // create a new ReentrantContext if none is available + ctx = newContext(); + // update thread local reference: + ctxTL.set(getOrCreateReference(ctx)); + } + // Check reentrance: + if (ctx.usage == USAGE_TL_INACTIVE) { + ctx.usage = USAGE_TL_IN_USE; + } else { + // get or create another ReentrantContext from CLQ provider: + ctx = ctxProviderCLQ.acquire(); + } + return ctx; + } + + /** + * Restore the given ReentrantContext instance for reuse + * + * @param ctx ReentrantContext instance + */ + @Override + public final void release(final K ctx) { + if (ctx.usage == USAGE_TL_IN_USE) { + ctx.usage = USAGE_TL_INACTIVE; + } else { + ctxProviderCLQ.release(ctx); + } + } +} diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java index 226a3d2e30d..6e8da24453e 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -126,7 +126,7 @@ final class ByteArrayCache implements MarlinConst { } if (doChecks) { - check(array, 0, array.length, value); + check(array, fromIndex, toIndex, value); } } @@ -135,9 +135,10 @@ final class ByteArrayCache implements MarlinConst { { if (doChecks) { // check zero on full array: - for (int i = fromIndex; i < toIndex; i++) { + for (int i = 0; i < array.length; i++) { if (array[i] != value) { - logException("Invalid array value at " + i + "\n" + logException("Invalid value at: " + i + " = " + array[i] + + " from: " + fromIndex + " to: " + toIndex + "\n" + Arrays.toString(array), new Throwable()); // ensure array is correctly filled: diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java index 06d7f351e28..681c75d4ceb 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -127,7 +127,7 @@ final class FloatArrayCache implements MarlinConst { } if (doChecks) { - check(array, 0, array.length, value); + check(array, fromIndex, toIndex, value); } } @@ -136,9 +136,10 @@ final class FloatArrayCache implements MarlinConst { { if (doChecks) { // check zero on full array: - for (int i = fromIndex; i < toIndex; i++) { + for (int i = 0; i < array.length; i++) { if (array[i] != value) { - logException("Invalid array value at " + i + "\n" + logException("Invalid value at: " + i + " = " + array[i] + + " from: " + fromIndex + " to: " + toIndex + "\n" + Arrays.toString(array), new Throwable()); // ensure array is correctly filled: diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java index 11c5aae84f6..af4d0b69529 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -126,7 +126,7 @@ final class IntArrayCache implements MarlinConst { } if (doChecks) { - check(array, 0, array.length, value); + check(array, fromIndex, toIndex, value); } } @@ -135,9 +135,10 @@ final class IntArrayCache implements MarlinConst { { if (doChecks) { // check zero on full array: - for (int i = fromIndex; i < toIndex; i++) { + for (int i = 0; i < array.length; i++) { if (array[i] != value) { - logException("Invalid array value at " + i + "\n" + logException("Invalid value at: " + i + " = " + array[i] + + " from: " + fromIndex + " to: " + toIndex + "\n" + Arrays.toString(array), new Throwable()); // ensure array is correctly filled: diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java index 18cb441c571..40afc7fe9a6 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -590,8 +590,8 @@ public final class MarlinCache implements MarlinConst { alphaRow[to + 1] = 0; } if (doChecks) { - IntArrayCache.check(blkFlags, 0, blkFlags.length, 0); - IntArrayCache.check(alphaRow, 0, alphaRow.length, 0); + IntArrayCache.check(blkFlags, blkW, blkE, 0); + IntArrayCache.check(alphaRow, from, px1 - bboxX0, 0); } if (doMonitors) { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java index f7b5f7c43a8..e01a5e77f9c 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -30,11 +30,12 @@ import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Path2D; import java.awt.geom.PathIterator; -import java.lang.ref.Reference; import java.security.AccessController; -import java.util.concurrent.ConcurrentLinkedQueue; import static sun.java2d.marlin.MarlinUtils.logInfo; import sun.awt.geom.PathConsumer2D; +import sun.java2d.ReentrantContextProvider; +import sun.java2d.ReentrantContextProviderCLQ; +import sun.java2d.ReentrantContextProviderTL; import sun.java2d.pipe.AATileGenerator; import sun.java2d.pipe.Region; import sun.java2d.pipe.RenderingEngine; @@ -882,46 +883,50 @@ public class MarlinRenderingEngine extends RenderingEngine // use ThreadLocal or ConcurrentLinkedQueue to get one RendererContext private static final boolean useThreadLocal; - // hard reference - static final int REF_HARD = 0; - // soft reference - static final int REF_SOFT = 1; - // weak reference - static final int REF_WEAK = 2; - // reference type stored in either TL or CLQ static final int REF_TYPE; // Per-thread RendererContext - private static final ThreadLocal rdrCtxThreadLocal; - // RendererContext queue when ThreadLocal is disabled - private static final ConcurrentLinkedQueue rdrCtxQueue; + private static final ReentrantContextProvider rdrCtxProvider; // Static initializer to use TL or CLQ mode static { - // CLQ mode by default: useThreadLocal = MarlinProperties.isUseThreadLocal(); - rdrCtxThreadLocal = (useThreadLocal) ? new ThreadLocal() - : null; - rdrCtxQueue = (!useThreadLocal) ? new ConcurrentLinkedQueue() - : null; // Soft reference by default: - String refType = AccessController.doPrivileged( + final String refType = AccessController.doPrivileged( new GetPropertyAction("sun.java2d.renderer.useRef", "soft")); switch (refType) { default: case "soft": - REF_TYPE = REF_SOFT; + REF_TYPE = ReentrantContextProvider.REF_SOFT; break; case "weak": - REF_TYPE = REF_WEAK; + REF_TYPE = ReentrantContextProvider.REF_WEAK; break; case "hard": - REF_TYPE = REF_HARD; + REF_TYPE = ReentrantContextProvider.REF_HARD; break; } + + if (useThreadLocal) { + rdrCtxProvider = new ReentrantContextProviderTL(REF_TYPE) + { + @Override + protected RendererContext newContext() { + return RendererContext.createContext(); + } + }; + } else { + rdrCtxProvider = new ReentrantContextProviderCLQ(REF_TYPE) + { + @Override + protected RendererContext newContext() { + return RendererContext.createContext(); + } + }; + } } private static boolean settingsLogged = !enableLogs; @@ -936,13 +941,13 @@ public class MarlinRenderingEngine extends RenderingEngine String refType; switch (REF_TYPE) { default: - case REF_HARD: + case ReentrantContextProvider.REF_HARD: refType = "hard"; break; - case REF_SOFT: + case ReentrantContextProvider.REF_SOFT: refType = "soft"; break; - case REF_WEAK: + case ReentrantContextProvider.REF_WEAK: refType = "weak"; break; } @@ -1025,22 +1030,7 @@ public class MarlinRenderingEngine extends RenderingEngine */ @SuppressWarnings({"unchecked"}) static RendererContext getRendererContext() { - RendererContext rdrCtx = null; - final Object ref = (useThreadLocal) ? rdrCtxThreadLocal.get() - : rdrCtxQueue.poll(); - if (ref != null) { - // resolve reference: - rdrCtx = (REF_TYPE == REF_HARD) ? ((RendererContext) ref) - : ((Reference) ref).get(); - } - // create a new RendererContext if none is available - if (rdrCtx == null) { - rdrCtx = RendererContext.createContext(); - if (useThreadLocal) { - // update thread local reference: - rdrCtxThreadLocal.set(rdrCtx.reference); - } - } + final RendererContext rdrCtx = rdrCtxProvider.acquire(); if (doMonitors) { RendererContext.stats.mon_pre_getAATileGenerator.start(); } @@ -1057,8 +1047,6 @@ public class MarlinRenderingEngine extends RenderingEngine if (doMonitors) { RendererContext.stats.mon_pre_getAATileGenerator.stop(); } - if (!useThreadLocal) { - rdrCtxQueue.offer(rdrCtx.reference); - } + rdrCtxProvider.release(rdrCtx); } } diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java index f9524c88870..60de2c31570 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -26,9 +26,10 @@ package sun.java2d.marlin; import java.awt.geom.Path2D; -import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicInteger; +import sun.java2d.ReentrantContext; +import sun.java2d.ReentrantContextProvider; import static sun.java2d.marlin.ArrayCache.*; import sun.java2d.marlin.MarlinRenderingEngine.NormalizingPathIterator; import static sun.java2d.marlin.MarlinUtils.logInfo; @@ -36,7 +37,7 @@ import static sun.java2d.marlin.MarlinUtils.logInfo; /** * This class is a renderer context dedicated to a single thread */ -final class RendererContext implements MarlinConst { +final class RendererContext extends ReentrantContext implements MarlinConst { // RendererContext creation counter private static final AtomicInteger contextCount = new AtomicInteger(1); @@ -45,7 +46,7 @@ final class RendererContext implements MarlinConst { ? RendererStats.getInstance(): null; private static final boolean USE_CACHE_HARD_REF = doStats - || (MarlinRenderingEngine.REF_TYPE == MarlinRenderingEngine.REF_WEAK); + || (MarlinRenderingEngine.REF_TYPE == ReentrantContextProvider.REF_WEAK); /** * Create a new renderer context @@ -55,6 +56,7 @@ final class RendererContext implements MarlinConst { static RendererContext createContext() { final RendererContext newCtx = new RendererContext("ctx" + Integer.toString(contextCount.getAndIncrement())); + if (RendererContext.stats != null) { RendererContext.stats.allContexts.add(newCtx); } @@ -63,11 +65,6 @@ final class RendererContext implements MarlinConst { // context name (debugging purposes) final String name; - /* - * Reference to this instance (hard, soft or weak). - * @see MarlinRenderingEngine#REF_TYPE - */ - final Object reference; // Smallest object used as Cleaner's parent reference final Object cleanerObj = new Object(); // dirty flag indicating an exception occured during pipeline in pathTo() @@ -101,7 +98,7 @@ final class RendererContext implements MarlinConst { /** * Constructor * - * @param name + * @param name context name (debugging) */ RendererContext(final String name) { if (logCreateContext) { @@ -124,20 +121,6 @@ final class RendererContext implements MarlinConst { stroker = new Stroker(this); dasher = new Dasher(this); - - // Create the reference to this instance (hard, soft or weak): - switch (MarlinRenderingEngine.REF_TYPE) { - default: - case MarlinRenderingEngine.REF_HARD: - reference = this; - break; - case MarlinRenderingEngine.REF_SOFT: - reference = new SoftReference(this); - break; - case MarlinRenderingEngine.REF_WEAK: - reference = new WeakReference(this); - break; - } } /** diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java index 94b0e2f1e59..1d144169376 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -27,7 +27,7 @@ package sun.java2d.marlin; public final class Version { - private static final String version = "marlin-0.7.3-Unsafe-OpenJDK"; + private static final String version = "marlin-0.7.3.2-Unsafe-OpenJDK"; public static String getVersion() { return version; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java index e071b967a02..3046ff69c60 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -28,7 +28,11 @@ import java.awt.BasicStroke; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.Rectangle2D; +import java.util.concurrent.ConcurrentLinkedQueue; import sun.awt.SunHints; +import sun.java2d.ReentrantContext; +import sun.java2d.ReentrantContextProvider; +import sun.java2d.ReentrantContextProviderTL; import sun.java2d.SunGraphics2D; /** @@ -38,28 +42,31 @@ import sun.java2d.SunGraphics2D; * This class sets up the Generator and computes the alpha tiles * and then passes them on to a CompositePipe object for painting. */ -public class AAShapePipe +public final class AAShapePipe implements ShapeDrawPipe, ParallelogramPipe { - static RenderingEngine renderengine = RenderingEngine.getInstance(); + static final RenderingEngine renderengine = RenderingEngine.getInstance(); // Per-thread TileState (~1K very small so do not use any Weak Reference) - private static final ThreadLocal tileStateThreadLocal = - new ThreadLocal() { - @Override - protected TileState initialValue() { - return new TileState(); - } - }; + private static final ReentrantContextProvider tileStateProvider = + new ReentrantContextProviderTL( + ReentrantContextProvider.REF_HARD) + { + @Override + protected TileState newContext() { + return new TileState(); + } + }; - CompositePipe outpipe; + final CompositePipe outpipe; public AAShapePipe(CompositePipe pipe) { outpipe = pipe; } + @Override public void draw(SunGraphics2D sg, Shape s) { - BasicStroke bs; + final BasicStroke bs; if (sg.stroke instanceof BasicStroke) { bs = (BasicStroke) sg.stroke; @@ -71,10 +78,12 @@ public class AAShapePipe renderPath(sg, s, bs); } + @Override public void fill(SunGraphics2D sg, Shape s) { renderPath(sg, s, null); } + @Override public void fillParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2, @@ -82,21 +91,23 @@ public class AAShapePipe double dx1, double dy1, double dx2, double dy2) { - Region clip = sg.getCompClip(); - final TileState ts = tileStateThreadLocal.get(); - final int[] abox = ts.abox; + final TileState ts = tileStateProvider.acquire(); + try { + final int[] abox = ts.abox; - AATileGenerator aatg = - renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, - clip, abox); - if (aatg == null) { - // Nothing to render - return; + final AATileGenerator aatg = + renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, + sg.getCompClip(), abox); + if (aatg != null) { + renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), + aatg, abox, ts); + } + } finally { + tileStateProvider.release(ts); } - - renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); } + @Override public void drawParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2, @@ -105,52 +116,61 @@ public class AAShapePipe double dx2, double dy2, double lw1, double lw2) { - Region clip = sg.getCompClip(); - final TileState ts = tileStateThreadLocal.get(); - final int[] abox = ts.abox; + final TileState ts = tileStateProvider.acquire(); + try { + final int[] abox = ts.abox; - AATileGenerator aatg = - renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2, - clip, abox); - if (aatg == null) { - // Nothing to render - return; + final AATileGenerator aatg = + renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, + lw2, sg.getCompClip(), abox); + if (aatg != null) { + // Note that bbox is of the original shape, not the wide path. + // This is appropriate for handing to Paint methods... + renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), + aatg, abox, ts); + } + } finally { + tileStateProvider.release(ts); } - - // Note that bbox is of the original shape, not the wide path. - // This is appropriate for handing to Paint methods... - renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); } public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) { - boolean adjust = (bs != null && + final boolean adjust = (bs != null && sg.strokeHint != SunHints.INTVAL_STROKE_PURE); - boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); + final boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); - Region clip = sg.getCompClip(); - final TileState ts = tileStateThreadLocal.get(); - final int[] abox = ts.abox; + final TileState ts = tileStateProvider.acquire(); + try { + final int[] abox = ts.abox; - AATileGenerator aatg = - renderengine.getAATileGenerator(s, sg.transform, clip, - bs, thin, adjust, abox); - if (aatg == null) { - // Nothing to render - return; + final AATileGenerator aatg = + renderengine.getAATileGenerator(s, sg.transform, sg.getCompClip(), + bs, thin, adjust, abox); + if (aatg != null) { + renderTiles(sg, s, aatg, abox, ts); + } + } finally { + tileStateProvider.release(ts); } - - renderTiles(sg, s, aatg, abox, ts); } public void renderTiles(SunGraphics2D sg, Shape s, - AATileGenerator aatg, int abox[], TileState ts) + final AATileGenerator aatg, + final int[] abox, final TileState ts) { Object context = null; try { + // reentrance: outpipe may also use AAShapePipe: context = outpipe.startSequence(sg, s, ts.computeDevBox(abox), abox); + // copy of int[] abox as local variables for performance: + final int x0 = abox[0]; + final int y0 = abox[1]; + final int x1 = abox[2]; + final int y1 = abox[3]; + final int tw = aatg.getTileWidth(); final int th = aatg.getTileHeight(); @@ -158,16 +178,15 @@ public class AAShapePipe final byte[] alpha = ts.getAlphaTile(tw * th); byte[] atile; - for (int y = abox[1]; y < abox[3]; y += th) { - int h = Math.min(th, abox[3] - y); + for (int y = y0; y < y1; y += th) { + final int h = Math.min(th, y1 - y); - for (int x = abox[0]; x < abox[2]; x += tw) { - int w = Math.min(tw, abox[2] - x); + for (int x = x0; x < x1; x += tw) { + final int w = Math.min(tw, x1 - x); - int a = aatg.getTypicalAlpha(); - if (a == 0x00 || - outpipe.needTile(context, x, y, w, h) == false) - { + final int a = aatg.getTypicalAlpha(); + + if (a == 0x00 || !outpipe.needTile(context, x, y, w, h)) { aatg.nextTile(); outpipe.skipTile(context, x, y); continue; @@ -180,8 +199,7 @@ public class AAShapePipe aatg.getAlpha(alpha, 0, tw); } - outpipe.renderPathTile(context, atile, 0, tw, - x, y, w, h); + outpipe.renderPathTile(context, atile, 0, tw, x, y, w, h); } } } finally { @@ -193,7 +211,7 @@ public class AAShapePipe } // Tile state used by AAShapePipe - static final class TileState { + static final class TileState extends ReentrantContext { // cached tile (32 x 32 tile by default) private byte[] theTile = new byte[32 * 32]; // dirty aabox array @@ -240,5 +258,4 @@ public class AAShapePipe return box; } } - } diff --git a/jdk/test/sun/java2d/marlin/CrashPaintTest.java b/jdk/test/sun/java2d/marlin/CrashPaintTest.java new file mode 100644 index 00000000000..cf710bc83a5 --- /dev/null +++ b/jdk/test/sun/java2d/marlin/CrashPaintTest.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2016, 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.awt.Color; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.PaintContext; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.TexturePaint; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8148886 + * @summary Verifies that Marlin supports reentrant operations (ThreadLocal) + * like in custom Paint or custom Composite + * @run main CrashPaintTest + */ +public class CrashPaintTest { + + static final boolean SAVE_IMAGE = false; + + public static void main(String argv[]) { + Locale.setDefault(Locale.US); + + // initialize j.u.l Looger: + final Logger log = Logger.getLogger("sun.java2d.marlin"); + log.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + Throwable th = record.getThrown(); + // detect any Throwable: + if (th != null) { + System.out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(System.out); + + throw new RuntimeException("Test failed: ", th); + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }); + + // enable Marlin logging & internal checks: + System.setProperty("sun.java2d.renderer.log", "true"); + System.setProperty("sun.java2d.renderer.useLogger", "true"); + System.setProperty("sun.java2d.renderer.doChecks", "true"); + + // Force using thread-local storage: + System.setProperty("sun.java2d.renderer.useThreadLocal", "true"); + // Force smaller pixelsize to force using array caches: + System.setProperty("sun.java2d.renderer.pixelsize", "256"); + + final int width = 300; + final int height = 300; + + final BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setBackground(Color.WHITE); + g2d.clearRect(0, 0, width, height); + + final Ellipse2D.Double ellipse + = new Ellipse2D.Double(0, 0, width, height); + + final Paint paint = new CustomPaint(100); + + for (int i = 0; i < 20; i++) { + final long start = System.nanoTime(); + g2d.setPaint(paint); + g2d.fill(ellipse); + + g2d.setColor(Color.GREEN); + g2d.draw(ellipse); + + final long time = System.nanoTime() - start; + System.out.println("paint: duration= " + (1e-6 * time) + " ms."); + } + + if (SAVE_IMAGE) { + try { + final File file = new File("CrashPaintTest.png"); + System.out.println("Writing file: " + + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } catch (IOException ex) { + System.out.println("Writing file failure:"); + ex.printStackTrace(); + } + } + + // Check image on few pixels: + final Raster raster = image.getData(); + + // 170, 175 = blue + checkPixel(raster, 170, 175, Color.BLUE.getRGB()); + // 50, 50 = blue + checkPixel(raster, 50, 50, Color.BLUE.getRGB()); + + // 190, 110 = pink + checkPixel(raster, 190, 110, Color.PINK.getRGB()); + // 280, 210 = pink + checkPixel(raster, 280, 210, Color.PINK.getRGB()); + + } finally { + g2d.dispose(); + } + } + + private static void checkPixel(final Raster raster, + final int x, final int y, + final int expected) { + + final int[] rgb = (int[]) raster.getDataElements(x, y, null); + + if (rgb[0] != expected) { + throw new IllegalStateException("bad pixel at (" + x + ", " + y + + ") = " + rgb[0] + " expected: " + expected); + } + } + + private static class CustomPaint extends TexturePaint { + private int size; + + CustomPaint(final int size) { + super(new BufferedImage(size, size, + BufferedImage.TYPE_INT_ARGB), + new Rectangle2D.Double(0, 0, size, size) + ); + this.size = size; + } + + @Override + public PaintContext createContext(ColorModel cm, + Rectangle deviceBounds, + Rectangle2D userBounds, + AffineTransform at, + RenderingHints hints) { + + // Fill bufferedImage using + final Graphics2D g2d = (Graphics2D) getImage().getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setBackground(Color.PINK); + g2d.clearRect(0, 0, size, size); + + g2d.setColor(Color.BLUE); + g2d.drawRect(0, 0, size, size); + + g2d.fillOval(size / 10, size / 10, + size * 8 / 10, size * 8 / 10); + + } finally { + g2d.dispose(); + } + + return super.createContext(cm, deviceBounds, userBounds, at, hints); + } + } +} From aa585fa3cf5db420e14588d8c58730dab1e16bf0 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 23 Feb 2016 17:19:28 -0500 Subject: [PATCH 086/311] 8150337: sun/misc/SunMiscSignalTest.java failed intermittently Correct test to allow for signals to be ignored Reviewed-by: bpb --- .../classes/jdk/internal/misc/Signal.java | 5 ++ jdk/test/sun/misc/SunMiscSignalTest.java | 46 ++++++++++++++++--- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java index 92adbbe295e..0002fdcde93 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java @@ -279,6 +279,11 @@ public final class Signal { public void handle(Signal sig) { throw new UnsupportedOperationException("invoking native signal handle not supported"); } + + public String toString() { + return this == SIG_DFL ? "SIG_DFL" : + (this == SIG_IGN ? "SIG_IGN" : super.toString()); + } } } diff --git a/jdk/test/sun/misc/SunMiscSignalTest.java b/jdk/test/sun/misc/SunMiscSignalTest.java index 4179b000b85..3dbab4f6cc0 100644 --- a/jdk/test/sun/misc/SunMiscSignalTest.java +++ b/jdk/test/sun/misc/SunMiscSignalTest.java @@ -180,6 +180,12 @@ public class SunMiscSignalTest { return newArray; } + // Return true if the signal is one of the shutdown signals known to the VM + private static boolean isShutdownSignal(Signal signal) { + String name = signal.getName(); + return name.equals("INT") || name.equals("HUP") || name.equals("TERM"); + } + /** * Quick verification of supported signals using sun.misc.Signal. * @@ -201,14 +207,24 @@ public class SunMiscSignalTest { Assert.assertEquals(signal.toString(), "SIG" + name, "toString() mismatch, "); try { - SignalHandler old = Signal.handle(signal, h); + orig = Signal.handle(signal, h); + printf("oldHandler: %s%n", orig); Assert.assertEquals(CanRegister.YES, register, "Unexpected handle succeeded " + name); try { Signal.raise(signal); Assert.assertEquals(CanRaise.YES, raise, "Unexpected raise success for " + name); Invoked inv = h.semaphore().tryAcquire(Utils.adjustTimeout(100L), TimeUnit.MILLISECONDS) ? Invoked.YES : Invoked.NO; - Assert.assertEquals(inv, invoked, "handler not invoked;"); + if (!isShutdownSignal(signal)) { + // Normal case + Assert.assertEquals(inv, invoked, "handler not invoked;"); + } else { + if (orig == SignalHandler.SIG_IGN) { + Assert.assertEquals(inv, Invoked.NO, "handler should not be invoked"); + } else { + Assert.assertEquals(inv, invoked, "handler not invoked;"); + } + } } catch (IllegalArgumentException uoe3) { Assert.assertNotEquals(CanRaise.YES, raise, "raise failed for " + name + ": " + uoe3.getMessage()); @@ -270,14 +286,22 @@ public class SunMiscSignalTest { } // Test expected exception when raising a signal when no handler defined - @Test(expectedExceptions = IllegalArgumentException.class) + @Test static void testRaiseNoConsumer() { Signal signal = new Signal("INT"); SignalHandler orig = null; try { - Signal.handle(signal, SignalHandler.SIG_DFL); + orig = Signal.handle(signal, SignalHandler.SIG_DFL); + printf("oldHandler: %s%n", orig); + if (orig == SignalHandler.SIG_IGN) { + // SIG_IGN for TERM means it cannot be handled + return; + } Signal.raise(signal); - } finally { + Assert.fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException iae) { + printf("IAE message: %s%n", iae.getMessage()); + } finally { // Restore original signal handler if (orig != null && signal != null) { Signal.handle(signal, orig); @@ -296,7 +320,13 @@ public class SunMiscSignalTest { } Handler handler = new Handler(); Signal signal = new Signal("INT"); - Signal.handle(signal, handler); + SignalHandler orig = Signal.handle(signal, handler); + printf("oldHandler: %s%n", orig); + if (orig == SignalHandler.SIG_IGN) { + // SIG_IGN for INT means it cannot be handled + return; + } + Signal.raise(signal); boolean handled = handler.semaphore() .tryAcquire(Utils.adjustTimeout(100L), TimeUnit.MILLISECONDS); @@ -332,6 +362,10 @@ public class SunMiscSignalTest { Handler h1 = new Handler(); Handler h2 = new Handler(); SignalHandler orig = Signal.handle(signal, h1); + if (orig == SignalHandler.SIG_IGN) { + // SIG_IGN for TERM means it cannot be handled + return; + } try { SignalHandler prev = Signal.handle(signal, h2); From c542850197c0325cbe02a71b37c1161637673690 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 24 Feb 2016 00:14:23 +0100 Subject: [PATCH 087/311] 8150456: jdk 9 nightly build fails on Windows 32 bit Reviewed-by: tbell, ihse --- jdk/make/lib/CoreLibraries.gmk | 2 +- jdk/src/java.base/share/native/libzip/CRC32.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index bd707071427..ea2934245df 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -225,7 +225,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBZIP, \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_windows := -export:ZIP_Open -export:ZIP_Close -export:ZIP_FindEntry \ -export:ZIP_ReadEntry -export:ZIP_GetNextEntry \ - -export:ZIP_InflateFully, \ + -export:ZIP_InflateFully -export:ZIP_CRC32, \ LIBS_unix := -ljvm -ljava $(LIBZ), \ LIBS_solaris := -lc, \ LIBS_windows := jvm.lib $(WIN_JAVA_LIB), \ diff --git a/jdk/src/java.base/share/native/libzip/CRC32.c b/jdk/src/java.base/share/native/libzip/CRC32.c index 5d1a5c34d95..e29207b7764 100644 --- a/jdk/src/java.base/share/native/libzip/CRC32.c +++ b/jdk/src/java.base/share/native/libzip/CRC32.c @@ -54,7 +54,7 @@ Java_java_util_zip_CRC32_updateBytes0(JNIEnv *env, jclass cls, jint crc, return crc; } -JNIEXPORT jint JNICALL +jint JNICALL ZIP_CRC32(jint crc, const jbyte *buf, jint len) { return crc32(crc, (Bytef*)buf, len); From 44c03b15e225c4817560ed09e497cc7c3166b49f Mon Sep 17 00:00:00 2001 From: Timo Kinnunen Date: Tue, 23 Feb 2016 18:58:36 -0500 Subject: [PATCH 088/311] 8150426: Wrong cast in metadata_at_put Fix cast. Reviewed-by: dholmes, coleenp, jprovino --- hotspot/src/share/vm/oops/typeArrayOop.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp index e4670a8949b..8ab2f4d1f74 100644 --- a/hotspot/src/share/vm/oops/typeArrayOop.hpp +++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp @@ -129,7 +129,7 @@ class typeArrayOopDesc : public arrayOopDesc { Metadata* metadata_at(int which) const { return (Metadata*)*long_at_addr(which); } void metadata_at_put(int which, Metadata* contents) { - *long_at_addr(which) = (long)contents; + *long_at_addr(which) = (jlong)contents; } #else Metadata* metadata_at(int which) const { From ad6d8685e40569e82d266e293ddca5069c0a9569 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Tue, 23 Feb 2016 19:10:01 -0500 Subject: [PATCH 089/311] 8150379: [windows] Fix Leaks in perfMemory_windows.cpp Reviewed-by: clanger, dholmes, gthornbr --- hotspot/src/os/windows/vm/perfMemory_windows.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hotspot/src/os/windows/vm/perfMemory_windows.cpp b/hotspot/src/os/windows/vm/perfMemory_windows.cpp index 8987ef1fb5b..7748b653c1d 100644 --- a/hotspot/src/os/windows/vm/perfMemory_windows.cpp +++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp @@ -628,6 +628,7 @@ static void cleanup_sharedmem_resources(const char* dirname) { if (!is_directory_secure(dirname)) { // the directory is not secure, don't attempt any cleanup + os::closedir(dirp); return; } @@ -1445,6 +1446,8 @@ static char* mapping_create_shared(size_t size) { // check that the file system is secure - i.e. it supports ACLs. if (!is_filesystem_secure(dirname)) { + FREE_C_HEAP_ARRAY(char, dirname); + FREE_C_HEAP_ARRAY(char, user); return NULL; } @@ -1624,6 +1627,7 @@ static void open_file_mapping(const char* user, int vmid, // if (!is_directory_secure(dirname)) { FREE_C_HEAP_ARRAY(char, dirname); + if (luser != user) FREE_C_HEAP_ARRAY(char, luser); THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Process not found"); } From bf5a0964407b3a644ef23ac7361b1819b0fb3cd0 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 23 Feb 2016 16:13:48 -0800 Subject: [PATCH 090/311] 8149772: cleanup handling of -encoding in JavacFileManager Reviewed-by: jlahoda --- .../sun/tools/javac/file/BaseFileManager.java | 16 ++++++++++------ .../com/sun/tools/javac/main/JavaCompiler.java | 4 ---- .../classes/com/sun/tools/javac/main/Option.java | 8 +------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java index 42603b462ca..caf3dc32546 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java @@ -267,7 +267,14 @@ public abstract class BaseFileManager implements JavaFileManager { * @return true if successful, and false otherwise */ public boolean handleOption(Option option, String value) { - return locations.handleOption(option, value); + switch (option) { + case ENCODING: + encodingName = value; + return true; + + default: + return locations.handleOption(option, value); + } } /** @@ -285,6 +292,7 @@ public abstract class BaseFileManager implements JavaFileManager { // // + private String encodingName; private String defaultEncodingName; private String getDefaultEncodingName() { if (defaultEncodingName == null) { @@ -295,11 +303,7 @@ public abstract class BaseFileManager implements JavaFileManager { } public String getEncodingName() { - String encName = options.get(Option.ENCODING); - if (encName == null) - return getDefaultEncodingName(); - else - return encName; + return (encodingName != null) ? encodingName : getDefaultEncodingName(); } @SuppressWarnings("cast") diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 4f72befa543..4d3bc8bb8ff 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -389,7 +389,6 @@ public class JavaCompiler { verbose = options.isSet(VERBOSE); sourceOutput = options.isSet(PRINTSOURCE); // used to be -s - encoding = options.get(ENCODING); lineDebugInfo = options.isUnset(G_CUSTOM) || options.isSet(G_CUSTOM, "lines"); genEndPos = options.isSet(XJCOV) || @@ -444,9 +443,6 @@ public class JavaCompiler { */ public boolean sourceOutput; - /** The encoding to be used for source input. - */ - public String encoding; /** Generate code with the LineNumberTable attribute for debugging */ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index 4867bdad290..6a0aebc7bd1 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -238,13 +238,7 @@ public enum Option { IMPLICIT("-implicit:", "opt.implicit", STANDARD, BASIC, ONEOF, "none", "class"), - ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) { - @Override - public boolean process(OptionHelper helper, String option, String operand) { - return super.process(helper, option, operand); - } - - }, + ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER), SOURCE("-source", "opt.arg.release", "opt.source", STANDARD, BASIC) { @Override From 2cdc922f31ea56ab753fa3de632ba375a13c2ecc Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Tue, 23 Feb 2016 16:25:01 -0800 Subject: [PATCH 091/311] 8149328: remove the dependency on java.logging from java.compiler Reviewed-by: jjg --- .../classes/javax/tools/ToolProvider.java | 52 ++----------------- 1 file changed, 3 insertions(+), 49 deletions(-) diff --git a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java index 950daf73328..447c9647b1a 100644 --- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java +++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -28,12 +28,7 @@ package javax.tools; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.HashMap; -import java.util.Locale; import java.util.Map; -import java.util.logging.Logger; -import java.util.logging.Level; - -import static java.util.logging.Level.*; /** * Provides methods for locating tool providers, for example, @@ -45,47 +40,6 @@ import static java.util.logging.Level.*; */ public class ToolProvider { - private static final String propertyName = "sun.tools.ToolProvider"; - private static final String loggerName = "javax.tools"; - - /* - * Define the system property "sun.tools.ToolProvider" to enable - * debugging: - * - * java ... -Dsun.tools.ToolProvider ... - */ - static T trace(Level level, Object reason) { - // NOTE: do not make this method private as it affects stack traces - try { - if (System.getProperty(propertyName) != null) { - StackTraceElement[] st = Thread.currentThread().getStackTrace(); - String method = "???"; - String cls = ToolProvider.class.getName(); - if (st.length > 2) { - StackTraceElement frame = st[2]; - method = String.format((Locale)null, "%s(%s:%s)", - frame.getMethodName(), - frame.getFileName(), - frame.getLineNumber()); - cls = frame.getClassName(); - } - Logger logger = Logger.getLogger(loggerName); - if (reason instanceof Throwable) { - logger.logp(level, cls, method, - reason.getClass().getName(), (Throwable)reason); - } else { - logger.logp(level, cls, method, String.valueOf(reason)); - } - } - } catch (SecurityException ex) { - System.err.format((Locale)null, "%s: %s; %s%n", - ToolProvider.class.getName(), - reason, - ex.getLocalizedMessage()); - } - return null; - } - private static final String systemJavaCompilerName = "com.sun.tools.javac.api.JavacTool"; @@ -153,7 +107,7 @@ public class ToolProvider { try { return c.asSubclass(clazz).newInstance(); } catch (InstantiationException | IllegalAccessException | RuntimeException | Error e) { - return trace(WARNING, e); + throw new Error(e); } } @@ -164,7 +118,7 @@ public class ToolProvider { try { c = Class.forName(name, false, ClassLoader.getSystemClassLoader()); } catch (ClassNotFoundException | RuntimeException | Error e) { - return trace(WARNING, e); + throw new Error(e); } toolClasses.put(name, new WeakReference<>(c)); } From 659fb4ecb35ed7bb34b1f5d1dc946055d69b0566 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 23 Feb 2016 16:38:04 -0800 Subject: [PATCH 092/311] 8145472: replace remaining java.io.File with java.nio.file.Path Reviewed-by: vromero --- .../classes/com/sun/tools/javac/comp/Infer.java | 14 ++++++++------ .../com/sun/tools/javac/main/Arguments.java | 17 +++++++++-------- .../com/sun/tools/javac/main/CommandLine.java | 9 +++++---- .../com/sun/tools/javac/main/Option.java | 16 +++++++++------- .../com/sun/tools/javac/main/OptionHelper.java | 11 ++++++----- 5 files changed, 37 insertions(+), 30 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java index 9f30e750db3..190c0e6e623 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -44,9 +44,11 @@ import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node; import com.sun.tools.javac.comp.Resolve.InapplicableMethodException; import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; -import java.io.File; -import java.io.FileWriter; import java.io.IOException; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -353,9 +355,9 @@ public class Infer { rsContext.attrMode(), rsContext.step, round); - File dotFile = new File(dependenciesFolder, filename); - try (FileWriter fw = new FileWriter(dotFile)) { - fw.append(graph); + Path dotFile = Paths.get(dependenciesFolder, filename); + try (Writer w = Files.newBufferedWriter(dotFile)) { + w.append(graph); } round++; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java index af02f2261d0..5d79556b3b9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -25,9 +25,10 @@ package com.sun.tools.javac.main; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -73,7 +74,7 @@ public class Arguments { private String ownName; private Set classNames; - private Set files; + private Set files; private Map deferredFileManagerOptions; private Set fileObjects; private final Options options; @@ -153,8 +154,8 @@ public class Arguments { } @Override - public void addFile(File f) { - files.add(f); + public void addFile(Path p) { + files.add(p); } @Override @@ -252,7 +253,7 @@ public class Arguments { } else { fileObjects = new LinkedHashSet<>(); JavacFileManager jfm = (JavacFileManager) getFileManager(); - for (JavaFileObject fo: jfm.getJavaFileObjectsFromFiles(files)) + for (JavaFileObject fo: jfm.getJavaFileObjectsFromPaths(files)) fileObjects.add(fo); } } @@ -583,8 +584,8 @@ public class Arguments { if (value == null) { return true; } - File file = new File(value); - if (file.exists() && !file.isDirectory()) { + Path file = Paths.get(value); + if (Files.exists(file) && !Files.isDirectory(file)) { error("err.file.not.directory", value); return false; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java index d770176e797..546f64d6a86 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -27,9 +27,10 @@ package com.sun.tools.javac.main; import java.io.IOException; import java.io.Reader; -import java.io.FileReader; -import java.io.BufferedReader; import java.io.StreamTokenizer; +import java.nio.file.Files; +import java.nio.file.Paths; + import com.sun.tools.javac.util.ListBuffer; /** @@ -73,7 +74,7 @@ public class CommandLine { private static void loadCmdFile(String name, ListBuffer args) throws IOException { - try (Reader r = new BufferedReader(new FileReader(name))) { + try (Reader r = Files.newBufferedReader(Paths.get(name))) { StreamTokenizer st = new StreamTokenizer(r); st.resetSyntax(); st.wordChars(' ', 255); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index 6a0aebc7bd1..b48f51632f2 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -25,9 +25,11 @@ package com.sun.tools.javac.main; -import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collections; import java.util.EnumSet; import java.util.LinkedHashMap; @@ -531,16 +533,16 @@ public enum Option { @Override public boolean process(OptionHelper helper, String option) { if (option.endsWith(".java") ) { - File f = new File(option); - if (!f.exists()) { - helper.error("err.file.not.found", f); + Path p = Paths.get(option); + if (!Files.exists(p)) { + helper.error("err.file.not.found", p); return true; } - if (!f.isFile()) { - helper.error("err.file.not.file", f); + if (!Files.isRegularFile(p)) { + helper.error("err.file.not.file", p); return true; } - helper.addFile(f); + helper.addFile(p); } else { helper.addClassName(option); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java index cf6479238d1..149576f0029 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, 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 @@ -25,9 +25,10 @@ package com.sun.tools.javac.main; +import java.nio.file.Path; + import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Log.PrefixKind; -import java.io.File; /** * Helper object to be used by {@link Option#process}, providing access to @@ -63,7 +64,7 @@ public abstract class OptionHelper { abstract void error(String key, Object... args); /** Record a file to be compiled. */ - abstract void addFile(File f); + abstract void addFile(Path p); /** Record the name of a class for annotation processing. */ abstract void addClassName(String s); @@ -112,8 +113,8 @@ public abstract class OptionHelper { } @Override - public void addFile(File f) { - throw new IllegalArgumentException(f.getPath()); + public void addFile(Path p) { + throw new IllegalArgumentException(p.toString()); } @Override From 7c15525950e393fafdb66656c1dce51100b1f316 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Wed, 24 Feb 2016 02:50:14 +0000 Subject: [PATCH 093/311] 8149417: Use final restricted flag Reviewed-by: mullan, weijun, coffeys --- .../classes/javax/crypto/JceSecurity.java | 5 +-- .../crypto/JceSecurity/FinalRestricted.java | 45 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 jdk/test/javax/crypto/JceSecurity/FinalRestricted.java diff --git a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java index fa674888824..338aa12eafc 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java +++ b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -64,8 +64,7 @@ final class JceSecurity { private static final Map verifyingProviders = new IdentityHashMap<>(); - // Set the default value. May be changed in the static initializer. - private static boolean isRestricted = true; + private static final boolean isRestricted; /* * Don't let anyone instantiate this. diff --git a/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java b/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java new file mode 100644 index 00000000000..fdfa76de068 --- /dev/null +++ b/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, 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 8149417 + * @summary Use final restricted flag + */ + +import java.security.*; +import java.lang.reflect.*; + +public class FinalRestricted { + + public static void main(String[] args) throws Exception { + + int modifiers = Class.forName("javax.crypto.JceSecurity") + .getDeclaredField("isRestricted").getModifiers(); + if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers) && + Modifier.isPrivate(modifiers))) { + throw new Exception("JceSecurity.isRestricted is not " + + "a private static final field!"); + } + } +} From be76f3e83be580787a751244ede0fedf63049f85 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 23 Feb 2016 19:17:54 -0800 Subject: [PATCH 094/311] 8150475: -sourcepath / crashes javac Reviewed-by: darcy, vromero --- .../tools/javac/file/JavacFileManager.java | 2 +- langtools/test/tools/javac/file/T8150475.java | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/file/T8150475.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java index 091ef22661c..1fc2fa1ac6d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -425,7 +425,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil if (container.endsWith("bootmodules.jimage")) { System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:"); container = Locations.JRT_MARKER_FILE; - } else if (container.getFileName().toString().endsWith(".jimage")) { + } else if (container.getNameCount() > 0 && container.getFileName().toString().endsWith(".jimage")) { System.err.println("Warning: reference to " + container + " ignored"); return; } diff --git a/langtools/test/tools/javac/file/T8150475.java b/langtools/test/tools/javac/file/T8150475.java new file mode 100644 index 00000000000..790b944cbf8 --- /dev/null +++ b/langtools/test/tools/javac/file/T8150475.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, 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 + * @compile -sourcepath / T8150475.java + */ + +class T8150475 { } + From 3634fb9df2a8f1b117ecce947f14a3079e1cd783 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 24 Feb 2016 18:06:34 +0100 Subject: [PATCH 095/311] 8149036: Add tracing for thread related events at os level Reviewed-by: coleenp, mlarsson, dholmes --- hotspot/src/os/aix/vm/os_aix.cpp | 49 ++++++++++-------------- hotspot/src/os/bsd/vm/os_bsd.cpp | 22 +++++++++-- hotspot/src/os/linux/vm/os_linux.cpp | 21 ++++++++-- hotspot/src/os/posix/vm/os_posix.cpp | 13 +++++++ hotspot/src/os/posix/vm/os_posix.hpp | 5 +++ hotspot/src/os/solaris/vm/os_solaris.cpp | 42 ++++++++++++++++++-- hotspot/src/os/windows/vm/os_windows.cpp | 44 ++++++++++++++++++++- hotspot/src/share/vm/logging/logTag.hpp | 1 + hotspot/src/share/vm/runtime/thread.cpp | 34 +++++++++++++--- 9 files changed, 187 insertions(+), 44 deletions(-) diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index f63a789b89c..c38d2a3fbd0 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -36,6 +36,7 @@ #include "compiler/compileBroker.hpp" #include "interpreter/interpreter.hpp" #include "jvm_aix.h" +#include "logging/log.hpp" #include "libo4.hpp" #include "libperfstat_aix.hpp" #include "libodm_aix.hpp" @@ -791,13 +792,8 @@ static void *java_start(Thread *thread) { const pthread_t pthread_id = ::pthread_self(); const tid_t kernel_thread_id = ::thread_self(); - trcVerbose("newborn Thread : pthread-id %u, ktid " UINT64_FORMAT - ", stack %p ... %p, stacksize 0x%IX (%IB)", - pthread_id, kernel_thread_id, - thread->stack_end(), - thread->stack_base(), - thread->stack_size(), - thread->stack_size()); + log_info(os, thread)("Thread is alive (pthread id " UINTX_FORMAT ", tid " UINTX_FORMAT ")", + (uintx) pthread_id, (uintx) kernel_thread_id); // Normally, pthread stacks on AIX live in the data segment (are allocated with malloc() // by the pthread library). In rare cases, this may not be the case, e.g. when third-party @@ -805,7 +801,7 @@ static void *java_start(Thread *thread) { // guard pages on those stacks, because the stacks may reside in memory which is not // protectable (shmated). if (thread->stack_base() > ::sbrk(0)) { - trcVerbose("Thread " UINT64_FORMAT ": stack not in data segment.", (uint64_t) pthread_id); + log_warning(os, thread)("Thread " UINTX_FORMAT ": stack not in data segment.", (uintx)pthread_id); } // Try to randomize the cache line index of hot stack frames. @@ -839,8 +835,8 @@ static void *java_start(Thread *thread) { // Call one more level start routine. thread->run(); - trcVerbose("Thread finished : pthread-id %u, ktid " UINT64_FORMAT ".", - pthread_id, kernel_thread_id); + log_info(os, thread)("Thread finished (pthread id " UINTX_FORMAT ", tid " UINTX_FORMAT ").", + (uintx) pthread_id, (uintx) kernel_thread_id); return 0; } @@ -908,20 +904,19 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + + char buf[64]; + if (ret == 0) { + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } else { + log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", + strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } + pthread_attr_destroy(&attr); - if (ret == 0) { - trcVerbose("Created New Thread : pthread-id %u", tid); - } else { - if (os::Aix::on_pase()) { - // QIBM_MULTI_THREADED=Y is needed when the launcher is started on iSeries - // using QSH. Otherwise pthread_create fails with errno=11. - trcVerbose("(Please make sure you set the environment variable " - "QIBM_MULTI_THREADED=Y before running this program.)"); - } - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("pthread_create()"); - } + if (ret != 0) { // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; @@ -958,13 +953,6 @@ bool os::create_attached_thread(JavaThread* thread) { const pthread_t pthread_id = ::pthread_self(); const tid_t kernel_thread_id = ::thread_self(); - trcVerbose("attaching Thread : pthread-id %u, ktid " UINT64_FORMAT ", stack %p ... %p, stacksize 0x%IX (%IB)", - pthread_id, kernel_thread_id, - thread->stack_end(), - thread->stack_base(), - thread->stack_size(), - thread->stack_size()); - // OSThread::thread_id is the pthread id. osthread->set_thread_id(pthread_id); @@ -990,6 +978,9 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Aix::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (pthread id " UINTX_FORMAT ", tid " UINTX_FORMAT ")", + (uintx) pthread_id, (uintx) kernel_thread_id); + return true; } diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 8fdc6bc63b7..51fce416eda 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -32,6 +32,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_bsd.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_bsd.inline.hpp" @@ -681,6 +682,9 @@ static void *java_start(Thread *thread) { osthread->set_thread_id(os::Bsd::gettid()); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ".", + os::current_thread_id(), (uintx) pthread_self()); + #ifdef __APPLE__ uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id()); guarantee(unique_thread_id != 0, "unique thread id was not found"); @@ -716,6 +720,9 @@ static void *java_start(Thread *thread) { // call one more level start routine thread->run(); + log_info(os, thread)("Thread finished (tid " UINTX_FORMAT ", pthread id " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return 0; } @@ -776,12 +783,18 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + char buf[64]; + if (ret == 0) { + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } else { + log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", + strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } + pthread_attr_destroy(&attr); if (ret != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("pthread_create()"); - } // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; @@ -858,6 +871,9 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Bsd::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ".", + os::current_thread_id(), (uintx) pthread_self()); + return true; } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 3783351c345..5bf366d3997 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -662,6 +662,9 @@ static void *java_start(Thread *thread) { osthread->set_thread_id(os::current_thread_id()); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + if (UseNUMA) { int lgrp_id = os::numa_get_group_id(); if (lgrp_id != -1) { @@ -691,6 +694,9 @@ static void *java_start(Thread *thread) { // call one more level start routine thread->run(); + log_info(os, thread)("Thread finished (tid " UINTX_FORMAT ", pthread id " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return 0; } @@ -756,12 +762,18 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + char buf[64]; + if (ret == 0) { + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } else { + log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", + strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } + pthread_attr_destroy(&attr); if (ret != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("pthread_create()"); - } // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; @@ -858,6 +870,9 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Linux::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return true; } diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index 8cccda34d21..85407bd3cad 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -1071,6 +1071,19 @@ void os::Posix::ucontext_set_pc(ucontext_t* ctx, address pc) { #endif } +char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr) { + size_t stack_size = 0; + size_t guard_size = 0; + int detachstate = 0; + pthread_attr_getstacksize(attr, &stack_size); + pthread_attr_getguardsize(attr, &guard_size); + pthread_attr_getdetachstate(attr, &detachstate); + jio_snprintf(buf, buflen, "stacksize: " SIZE_FORMAT "k, guardsize: " SIZE_FORMAT "k, %s", + stack_size / 1024, guard_size / 1024, + (detachstate == PTHREAD_CREATE_DETACHED ? "detached" : "joinable")); + return buf; +} + os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); diff --git a/hotspot/src/os/posix/vm/os_posix.hpp b/hotspot/src/os/posix/vm/os_posix.hpp index be464ea8fa1..0196e989456 100644 --- a/hotspot/src/os/posix/vm/os_posix.hpp +++ b/hotspot/src/os/posix/vm/os_posix.hpp @@ -76,6 +76,11 @@ public: static address ucontext_get_pc(const ucontext_t* ctx); // Set PC into context. Needed for continuation after signal. static void ucontext_set_pc(ucontext_t* ctx, address pc); + + // Helper function; describes pthread attributes as short string. String is written + // to buf with len buflen; buf is returned. + static char* describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr); + }; /* diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index ae008b6dbe9..e454ed165c7 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -32,6 +32,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_solaris.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_solaris.inline.hpp" @@ -68,6 +69,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" #include "utilities/vmError.hpp" // put OS-includes here @@ -736,6 +738,9 @@ extern "C" void* java_start(void* thread_addr) { osthr->set_lwp_id(_lwp_self()); // Store lwp in case we are bound thread->_schedctl = (void *) schedctl_init(); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").", + os::current_thread_id()); + if (UseNUMA) { int lgrp_id = os::numa_get_group_id(); if (lgrp_id != -1) { @@ -781,6 +786,8 @@ extern "C" void* java_start(void* thread_addr) { Atomic::dec(&os::Solaris::_os_thread_count); } + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id()); + if (UseDetachedThreads) { thr_exit(NULL); ShouldNotReachHere(); @@ -853,6 +860,9 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Solaris::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").", + os::current_thread_id()); + return true; } @@ -879,6 +889,25 @@ bool os::create_main_thread(JavaThread* thread) { return true; } +// Helper function to trace thread attributes, similar to os::Posix::describe_pthread_attr() +static char* describe_thr_create_attributes(char* buf, size_t buflen, + size_t stacksize, long flags) +{ + stringStream ss(buf, buflen); + ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024); + ss.print("flags: "); + #define PRINT_FLAG(f) if (flags & f) ss.print( XSTR(f) " "); + #define ALL(X) \ + X(THR_SUSPENDED) \ + X(THR_DETACHED) \ + X(THR_BOUND) \ + X(THR_NEW_LWP) \ + X(THR_DAEMON) + ALL(PRINT_FLAG) + #undef ALL + #undef PRINT_FLAG + return buf; +} bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { @@ -974,10 +1003,17 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, osthread->set_thread_id(-1); status = thr_create(NULL, stack_size, java_start, thread, flags, &tid); + + char buf[64]; + if (status == 0) { + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); + } else { + log_warning(os, thread)("Failed to start thread - thr_create failed (%s) for attributes: %s.", + strerror(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); + } + if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::create_thread"); - } thread->set_osthread(NULL); // Need to clean up stuff we've allocated so far delete osthread; diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 19d7319e7e1..cc15183b186 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -35,6 +35,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_windows.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_windows.inline.hpp" @@ -71,6 +72,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" #include "utilities/vmError.hpp" #ifdef _DEBUG @@ -436,6 +438,8 @@ static unsigned __stdcall java_start(Thread* thread) { res = 20115; // java thread } + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").", os::current_thread_id()); + // Install a win32 structured exception handler around every thread created // by VM, so VM can generate error dump when an exception occurred in non- // Java thread (e.g. VM thread). @@ -446,6 +450,8 @@ static unsigned __stdcall java_start(Thread* thread) { // Nothing to do. } + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id()); + // One less thread is executing // When the VMThread gets here, the main thread may have already exited // which frees the CodeHeap containing the Atomic::add code @@ -509,6 +515,10 @@ bool os::create_attached_thread(JavaThread* thread) { osthread->set_state(RUNNABLE); thread->set_osthread(osthread); + + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").", + os::current_thread_id()); + return true; } @@ -530,6 +540,28 @@ bool os::create_main_thread(JavaThread* thread) { return true; } +// Helper function to trace _beginthreadex attributes, +// similar to os::Posix::describe_pthread_attr() +static char* describe_beginthreadex_attributes(char* buf, size_t buflen, + size_t stacksize, unsigned initflag) +{ + stringStream ss(buf, buflen); + if (stacksize == 0) { + ss.print("stacksize: default, "); + } else { + ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024); + } + ss.print("flags: "); + #define PRINT_FLAG(f) if (initflag & f) ss.print( XSTR(f) " "); + #define ALL(X) \ + X(CREATE_SUSPENDED) \ + X(STACK_SIZE_PARAM_IS_A_RESERVATION) + ALL(PRINT_FLAG) + #undef ALL + #undef PRINT_FLAG + return buf; +} + // Allocate and initialize a new OSThread bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { @@ -596,14 +628,24 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, // document because JVM uses C runtime library. The good news is that the // flag appears to work with _beginthredex() as well. + const unsigned initflag = CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION; HANDLE thread_handle = (HANDLE)_beginthreadex(NULL, (unsigned)stack_size, (unsigned (__stdcall *)(void*)) java_start, thread, - CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, + initflag, &thread_id); + char buf[64]; + if (thread_handle != NULL) { + log_info(os, thread)("Thread started (tid: %u, attributes: %s)", + thread_id, describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); + } else { + log_warning(os, thread)("Failed to start thread - _beginthreadex failed (%s) for attributes: %s.", + strerror(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); + } + if (thread_handle == NULL) { // Need to clean up stuff we've allocated so far CloseHandle(osthread->interrupt_event()); diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 60e39f710f5..16a91cfbddf 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -81,6 +81,7 @@ LOG_TAG(survivor) \ LOG_TAG(sweep) \ LOG_TAG(task) \ + LOG_TAG(thread) \ LOG_TAG(tlab) \ LOG_TAG(time) \ LOG_TAG(verify) \ diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 267c6584c37..654aebd9e70 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -324,6 +324,10 @@ void Thread::record_stack_base_and_size() { // record thread's native stack, stack grows downward MemTracker::record_thread_stack(stack_end(), stack_size()); #endif // INCLUDE_NMT + log_debug(os, thread)("Thread " UINTX_FORMAT " stack dimensions: " + PTR_FORMAT "-" PTR_FORMAT " (" SIZE_FORMAT "k).", + os::current_thread_id(), p2i(stack_base() - stack_size()), + p2i(stack_base()), stack_size()/1024); } @@ -1802,6 +1806,10 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { // Call after last event on thread EVENT_THREAD_EXIT(this); + log_info(os, thread)("Thread " UINTX_FORMAT " %s.", + os::current_thread_id(), + exit_type == JavaThread::normal_exit ? "exiting" : "detaching"); + // Call Thread.exit(). We try 3 times in case we got another Thread.stop during // the execution of the method. If that is not enough, then we don't really care. Thread.stop // is deprecated anyhow. @@ -2491,18 +2499,25 @@ void JavaThread::create_stack_guard_pages() { // warning("Guarding at " PTR_FORMAT " for len " SIZE_FORMAT "\n", low_addr, len); if (allocate && !os::create_stack_guard_pages((char *) low_addr, len)) { - warning("Attempt to allocate stack guard pages failed."); + log_warning(os, thread)("Attempt to allocate stack guard pages failed."); return; } if (os::guard_memory((char *) low_addr, len)) { _stack_guard_state = stack_guard_enabled; } else { - warning("Attempt to protect stack guard pages failed."); + log_warning(os, thread)("Attempt to protect stack guard pages failed (" + PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); if (os::uncommit_memory((char *) low_addr, len)) { - warning("Attempt to deallocate stack guard pages failed."); + log_warning(os, thread)("Attempt to deallocate stack guard pages failed."); } + return; } + + log_debug(os, thread)("Thread " UINTX_FORMAT " stack guard pages activated: " + PTR_FORMAT "-" PTR_FORMAT ".", + os::current_thread_id(), p2i(low_addr), p2i(low_addr + len)); + } void JavaThread::remove_stack_guard_pages() { @@ -2515,16 +2530,25 @@ void JavaThread::remove_stack_guard_pages() { if (os::remove_stack_guard_pages((char *) low_addr, len)) { _stack_guard_state = stack_guard_unused; } else { - warning("Attempt to deallocate stack guard pages failed."); + log_warning(os, thread)("Attempt to deallocate stack guard pages failed (" + PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); + return; } } else { if (_stack_guard_state == stack_guard_unused) return; if (os::unguard_memory((char *) low_addr, len)) { _stack_guard_state = stack_guard_unused; } else { - warning("Attempt to unprotect stack guard pages failed."); + log_warning(os, thread)("Attempt to unprotect stack guard pages failed (" + PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); + return; } } + + log_debug(os, thread)("Thread " UINTX_FORMAT " stack guard pages removed: " + PTR_FORMAT "-" PTR_FORMAT ".", + os::current_thread_id(), p2i(low_addr), p2i(low_addr + len)); + } void JavaThread::enable_stack_reserved_zone() { From 5d5113046a2273da15da3eb65e5dd6a7e5478393 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 24 Feb 2016 13:18:54 -0500 Subject: [PATCH 096/311] 8150419: Cleanup BufferNode API Fewer public functions, cleanup allocation. Reviewed-by: tschatzl, drwhite --- hotspot/src/share/vm/gc/g1/ptrQueue.cpp | 60 +++++++++++++++++-------- hotspot/src/share/vm/gc/g1/ptrQueue.hpp | 55 ++++++++++------------- 2 files changed, 65 insertions(+), 50 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp index 756b9599fb8..55b41a0b605 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -30,6 +30,8 @@ #include "runtime/mutexLocker.hpp" #include "runtime/thread.inline.hpp" +#include + PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) : _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active), _permanent(permanent), _lock(NULL) @@ -87,6 +89,19 @@ void PtrQueue::locking_enqueue_completed_buffer(void** buf) { } +BufferNode* BufferNode::allocate(size_t byte_size) { + assert(byte_size > 0, "precondition"); + assert(is_size_aligned(byte_size, sizeof(void**)), + "Invalid buffer size " SIZE_FORMAT, byte_size); + void* data = NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC); + return new (data) BufferNode; +} + +void BufferNode::deallocate(BufferNode* node) { + node->~BufferNode(); + FREE_C_HEAP_ARRAY(char, node); +} + PtrQueueSet::PtrQueueSet(bool notify_when_complete) : _max_completed_queue(0), _cbl_mon(NULL), _fl_lock(NULL), @@ -123,17 +138,23 @@ void PtrQueueSet::initialize(Monitor* cbl_mon, void** PtrQueueSet::allocate_buffer() { assert(_sz > 0, "Didn't set a buffer size."); - MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); - if (_fl_owner->_buf_free_list != NULL) { - void** res = BufferNode::make_buffer_from_node(_fl_owner->_buf_free_list); - _fl_owner->_buf_free_list = _fl_owner->_buf_free_list->next(); - _fl_owner->_buf_free_list_sz--; - return res; - } else { - // Allocate space for the BufferNode in front of the buffer. - char *b = NEW_C_HEAP_ARRAY(char, _sz + BufferNode::aligned_size(), mtGC); - return BufferNode::make_buffer_from_block(b); + BufferNode* node = NULL; + { + MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); + node = _fl_owner->_buf_free_list; + if (node != NULL) { + _fl_owner->_buf_free_list = node->next(); + _fl_owner->_buf_free_list_sz--; + } } + if (node == NULL) { + node = BufferNode::allocate(_sz); + } else { + // Reinitialize buffer obtained from free list. + node->set_index(0); + node->set_next(NULL); + } + return BufferNode::make_buffer_from_node(node); } void PtrQueueSet::deallocate_buffer(void** buf) { @@ -150,13 +171,13 @@ void PtrQueueSet::reduce_free_list() { // For now we'll adopt the strategy of deleting half. MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag); size_t n = _buf_free_list_sz / 2; - while (n > 0) { - assert(_buf_free_list != NULL, "_buf_free_list_sz must be wrong."); - void* b = BufferNode::make_block_from_node(_buf_free_list); - _buf_free_list = _buf_free_list->next(); - FREE_C_HEAP_ARRAY(char, b); - _buf_free_list_sz --; - n--; + for (size_t i = 0; i < n; ++i) { + assert(_buf_free_list != NULL, + "_buf_free_list_sz is wrong: " SIZE_FORMAT, _buf_free_list_sz); + BufferNode* node = _buf_free_list; + _buf_free_list = node->next(); + _buf_free_list_sz--; + BufferNode::deallocate(node); } } @@ -236,8 +257,9 @@ bool PtrQueueSet::process_or_enqueue_complete_buffer(void** buf) { void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - BufferNode* cbn = BufferNode::new_from_buffer(buf); + BufferNode* cbn = BufferNode::make_node_from_buffer(buf); cbn->set_index(index); + cbn->set_next(NULL); if (_completed_buffers_tail == NULL) { assert(_completed_buffers_head == NULL, "Well-formedness"); _completed_buffers_head = cbn; diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp index 707d591c0c0..a2207641238 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -33,9 +33,6 @@ // the addresses of modified old-generation objects. This type supports // this operation. -// The definition of placement operator new(size_t, void*) in the . -#include - class PtrQueueSet; class PtrQueue VALUE_OBJ_CLASS_SPEC { friend class VMStructs; @@ -168,42 +165,38 @@ protected: class BufferNode { size_t _index; BufferNode* _next; -public: + void* _buffer[1]; // Pseudo flexible array member. + BufferNode() : _index(0), _next(NULL) { } + ~BufferNode() { } + + static size_t buffer_offset() { + return offset_of(BufferNode, _buffer); + } + +public: BufferNode* next() const { return _next; } void set_next(BufferNode* n) { _next = n; } size_t index() const { return _index; } void set_index(size_t i) { _index = i; } - // Align the size of the structure to the size of the pointer - static size_t aligned_size() { - static const size_t alignment = round_to(sizeof(BufferNode), sizeof(void*)); - return alignment; + // Allocate a new BufferNode with the "buffer" having size bytes. + static BufferNode* allocate(size_t byte_size); + + // Free a BufferNode. + static void deallocate(BufferNode* node); + + // Return the BufferNode containing the buffer. + static BufferNode* make_node_from_buffer(void** buffer) { + return reinterpret_cast( + reinterpret_cast(buffer) - buffer_offset()); } - // BufferNode is allocated before the buffer. - // The chunk of memory that holds both of them is a block. - - // Produce a new BufferNode given a buffer. - static BufferNode* new_from_buffer(void** buf) { - return new (make_block_from_buffer(buf)) BufferNode; - } - - // The following are the required conversion routines: - static BufferNode* make_node_from_buffer(void** buf) { - return (BufferNode*)make_block_from_buffer(buf); - } + // Return the buffer for node. static void** make_buffer_from_node(BufferNode *node) { - return make_buffer_from_block(node); - } - static void* make_block_from_node(BufferNode *node) { - return (void*)node; - } - static void** make_buffer_from_block(void* p) { - return (void**)((char*)p + aligned_size()); - } - static void* make_block_from_buffer(void** p) { - return (void*)((char*)p - aligned_size()); + // &_buffer[0] might lead to index out of bounds warnings. + return reinterpret_cast( + reinterpret_cast(node) + buffer_offset()); } }; From 453c5ef3758028d9c4cf4707e2487e5266352e69 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Wed, 24 Feb 2016 16:04:51 -0500 Subject: [PATCH 097/311] 8150506: Remove unused locks Reviewed-by: mgronlun, tschatzl, mgerdin, coleenp --- hotspot/src/share/vm/runtime/fprofiler.cpp | 5 ++--- hotspot/src/share/vm/runtime/mutex.cpp | 5 +---- hotspot/src/share/vm/runtime/mutexLocker.cpp | 14 +------------- hotspot/src/share/vm/runtime/mutexLocker.hpp | 7 +------ 4 files changed, 5 insertions(+), 26 deletions(-) diff --git a/hotspot/src/share/vm/runtime/fprofiler.cpp b/hotspot/src/share/vm/runtime/fprofiler.cpp index fbc51b4047d..fc687618e03 100644 --- a/hotspot/src/share/vm/runtime/fprofiler.cpp +++ b/hotspot/src/share/vm/runtime/fprofiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -836,8 +836,7 @@ void FlatProfiler::record_vm_tick() { vm_thread_profiler->inc_thread_ticks(); // Get a snapshot of a current VMThread pc (and leave it running!) - // The call may fail if, for instance the VM thread is interrupted while - // holding the Interrupt_lock or for other reasons. + // The call may fail in some circumstances epc = os::get_thread_pc(VMThread::vm_thread()); if(epc.pc() != NULL) { if (os::dll_address_to_function_name(epc.pc(), buf, sizeof(buf), NULL)) { diff --git a/hotspot/src/share/vm/runtime/mutex.cpp b/hotspot/src/share/vm/runtime/mutex.cpp index 81fa378d05c..ef6ac43b5d6 100644 --- a/hotspot/src/share/vm/runtime/mutex.cpp +++ b/hotspot/src/share/vm/runtime/mutex.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -1320,15 +1320,12 @@ void Monitor::set_owner_implementation(Thread *new_owner) { // The rank Mutex::native is an exception in that it is not subject // to the verification rules. // Here are some further notes relating to mutex acquisition anomalies: - // . under Solaris, the interrupt lock gets acquired when doing - // profiling, so any lock could be held. // . it is also ok to acquire Safepoint_lock at the very end while we // already hold Terminator_lock - may happen because of periodic safepoints if (this->rank() != Mutex::native && this->rank() != Mutex::suspend_resume && locks != NULL && locks->rank() <= this->rank() && !SafepointSynchronize::is_at_safepoint() && - this != Interrupt_lock && this != ProfileVM_lock && !(this == Safepoint_lock && contains(locks, Terminator_lock) && SafepointSynchronize::is_synchronizing())) { new_owner->print_owned_locks(); diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp index ae1d213b6e5..fa1aea26a55 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -50,7 +50,6 @@ Mutex* JmethodIdCreation_lock = NULL; Mutex* JfieldIdCreation_lock = NULL; Monitor* JNICritical_lock = NULL; Mutex* JvmtiThreadState_lock = NULL; -Monitor* JvmtiPendingEvent_lock = NULL; Monitor* Heap_lock = NULL; Mutex* ExpandHeap_lock = NULL; Mutex* AdapterHandlerLibrary_lock = NULL; @@ -73,8 +72,6 @@ Monitor* CGC_lock = NULL; Monitor* STS_lock = NULL; Monitor* SLT_lock = NULL; Monitor* FullGCCount_lock = NULL; -Monitor* CMark_lock = NULL; -Mutex* CMRegionStack_lock = NULL; Mutex* SATB_Q_FL_lock = NULL; Monitor* SATB_Q_CBL_mon = NULL; Mutex* Shared_SATB_Q_lock = NULL; @@ -94,11 +91,8 @@ Mutex* MultiArray_lock = NULL; Monitor* Terminator_lock = NULL; Monitor* BeforeExit_lock = NULL; Monitor* Notify_lock = NULL; -Monitor* Interrupt_lock = NULL; -Monitor* ProfileVM_lock = NULL; Mutex* ProfilePrint_lock = NULL; Mutex* ExceptionCache_lock = NULL; -Monitor* ObjAllocPost_lock = NULL; Mutex* OsrList_lock = NULL; #ifndef PRODUCT @@ -184,8 +178,6 @@ void mutex_init() { } if (UseG1GC) { - def(CMark_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_never); // coordinate concurrent mark thread - def(CMRegionStack_lock , Mutex, leaf, true, Monitor::_safepoint_check_never); def(SATB_Q_FL_lock , Mutex , special, true, Monitor::_safepoint_check_never); def(SATB_Q_CBL_mon , Monitor, nonleaf, true, Monitor::_safepoint_check_never); def(Shared_SATB_Q_lock , Mutex, nonleaf, true, Monitor::_safepoint_check_never); @@ -206,12 +198,10 @@ void mutex_init() { def(ParGCRareEvent_lock , Mutex , leaf , true, Monitor::_safepoint_check_sometimes); def(DerivedPointerTableGC_lock , Mutex, leaf, true, Monitor::_safepoint_check_never); def(CodeCache_lock , Mutex , special, true, Monitor::_safepoint_check_never); - def(Interrupt_lock , Monitor, special, true, Monitor::_safepoint_check_never); // used for interrupt processing def(RawMonitor_lock , Mutex, special, true, Monitor::_safepoint_check_never); def(OopMapCacheAlloc_lock , Mutex, leaf, true, Monitor::_safepoint_check_always); // used for oop_map_cache allocation. def(Patching_lock , Mutex , special, true, Monitor::_safepoint_check_never); // used for safepointing and code patching. - def(ObjAllocPost_lock , Monitor, special, false, Monitor::_safepoint_check_never); def(Service_lock , Monitor, special, true, Monitor::_safepoint_check_never); // used for service thread operations def(JmethodIdCreation_lock , Mutex , leaf, true, Monitor::_safepoint_check_always); // used for creating jmethodIDs. @@ -267,7 +257,6 @@ void mutex_init() { def(MultiArray_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks SymbolTable_lock def(JvmtiThreadState_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController - def(JvmtiPendingEvent_lock , Monitor, nonleaf, false, Monitor::_safepoint_check_never); // Used by JvmtiCodeBlobEvents def(Management_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // used for JVM management def(Compile_lock , Mutex , nonleaf+3, true, Monitor::_safepoint_check_sometimes); @@ -277,7 +266,6 @@ void mutex_init() { def(MethodCompileQueue_lock , Monitor, nonleaf+4, true, Monitor::_safepoint_check_always); def(Debug2_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never); def(Debug3_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never); - def(ProfileVM_lock , Monitor, special, false, Monitor::_safepoint_check_never); // used for profiling of the VMThread def(CompileThread_lock , Monitor, nonleaf+5, false, Monitor::_safepoint_check_always); def(PeriodicTask_lock , Monitor, nonleaf+5, true, Monitor::_safepoint_check_sometimes); if (WhiteBoxAPI) { diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp index bbf6f143312..eccd3ca7314 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -43,7 +43,6 @@ extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI metho extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in extern Mutex* JvmtiThreadState_lock; // a lock on modification of JVMTI thread data -extern Monitor* JvmtiPendingEvent_lock; // a lock on the JVMTI pending events list extern Monitor* Heap_lock; // a lock on the heap extern Mutex* ExpandHeap_lock; // a lock on expanding the heap extern Mutex* AdapterHandlerLibrary_lock; // a lock on the AdapterHandlerLibrary @@ -68,8 +67,6 @@ extern Monitor* CGC_lock; // used for coordination betwee extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet. extern Monitor* SLT_lock; // used in CMS GC for acquiring PLL extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc -extern Monitor* CMark_lock; // used for concurrent mark thread coordination -extern Mutex* CMRegionStack_lock; // used for protecting accesses to the CM region stack extern Mutex* SATB_Q_FL_lock; // Protects SATB Q // buffer free list. extern Monitor* SATB_Q_CBL_mon; // Protects SATB Q @@ -98,8 +95,6 @@ extern Mutex* MultiArray_lock; // a lock used to guard allocat extern Monitor* Terminator_lock; // a lock used to guard termination of the vm extern Monitor* BeforeExit_lock; // a lock used to guard cleanups and shutdown hooks extern Monitor* Notify_lock; // a lock used to synchronize the start-up of the vm -extern Monitor* Interrupt_lock; // a lock used for condition variable mediated interrupt processing -extern Monitor* ProfileVM_lock; // a lock used for profiling the VMThread extern Mutex* ProfilePrint_lock; // a lock used to serialize the printing of profiles extern Mutex* ExceptionCache_lock; // a lock used to synchronize exception cache updates extern Mutex* OsrList_lock; // a lock used to serialize access to OSR queues From c25e32cc70d50a0a9938f75b664ffb3eb887e5e0 Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Wed, 24 Feb 2016 16:34:25 -0500 Subject: [PATCH 098/311] 8150490: Update OS detection code to recognize Windows Server 2016 Reviewed-by: mgronlun, alanb, dholmes --- hotspot/src/os/windows/vm/os_windows.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 19d7319e7e1..72faa4b63a6 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1668,8 +1668,7 @@ void os::win32::print_windows_version(outputStream* st) { if (is_workstation) { st->print("10"); } else { - // The server version name of Windows 10 is not known at this time - st->print("%d.%d", major_version, minor_version); + st->print("Server 2016"); } break; From 8961912c749a2542a391c7e0946dbb74de7f7b01 Mon Sep 17 00:00:00 2001 From: Derek White Date: Wed, 24 Feb 2016 09:25:39 +0100 Subject: [PATCH 099/311] 8134992: vm/gc/compact/Compact_InternedStrings_Strings failed due to a malloc() failure Reviewed-by: mgerdin, brutisso --- hotspot/src/share/vm/gc/shared/collectedHeap.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp index 9bba8daf55e..f132d75e860 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp @@ -405,7 +405,9 @@ size_t CollectedHeap::max_tlab_size() const { oop CollectedHeap::new_store_pre_barrier(JavaThread* thread, oop new_obj) { // If a previous card-mark was deferred, flush it now. flush_deferred_store_barrier(thread); - if (can_elide_initializing_store_barrier(new_obj)) { + if (can_elide_initializing_store_barrier(new_obj) || + new_obj->is_typeArray()) { + // Arrays of non-references don't need a pre-barrier. // The deferred_card_mark region should be empty // following the flush above. assert(thread->deferred_card_mark().is_empty(), "Error"); From 7234547f04c3496a8985281b538e069eb780b50c Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Wed, 24 Feb 2016 14:36:53 +0300 Subject: [PATCH 100/311] 8081722: Provide public access to sun.awt.shell.ShellFolder methods which are required for implementing javax.swing.JFileChooser Reviewed-by: prr, serb, alexsch --- .../swing/filechooser/FileSystemView.java | 65 +++++++++- .../ShellFolderQueriesTest.java | 122 ++++++++++++++++++ 2 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java b/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java index bbc35bf9c1d..e573cf6f6af 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -583,6 +583,69 @@ public abstract class FileSystemView { } } + /** + * Returns an array of files representing the values to show by default in + * the file chooser selector. + * + * @return an array of {@code File} objects. + * @throws SecurityException if the caller does not have necessary + * permissions + * @since 9 + */ + public File[] getChooserComboBoxFiles() { + return (File[]) ShellFolder.get("fileChooserComboBoxFolders"); + } + + /** + * Returns whether the specified file denotes a shell interpreted link which + * can be obtained by the {@link #getLinkLocation(File)}. + * + * @param file a file + * @return whether this is a link + * @throws NullPointerException if {@code file} equals {@code null} + * @throws SecurityException if the caller does not have necessary + * permissions + * @see #getLinkLocation(File) + * @since 9 + */ + public boolean isLink(File file) { + if (file == null) { + throw new NullPointerException("file is null"); + } + try { + return ShellFolder.getShellFolder(file).isLink(); + } catch (FileNotFoundException e) { + return false; + } + } + + /** + * Returns the regular file referenced by the specified link file if + * the specified file is a shell interpreted link. + * Returns {@code null} if the specified file is not + * a shell interpreted link. + * + * @param file a file + * @return the linked file or {@code null}. + * @throws FileNotFoundException if the linked file does not exist + * @throws NullPointerException if {@code file} equals {@code null} + * @throws SecurityException if the caller does not have necessary + * permissions + * @since 9 + */ + public File getLinkLocation(File file) throws FileNotFoundException { + if (file == null) { + throw new NullPointerException("file is null"); + } + ShellFolder shellFolder; + try { + shellFolder = ShellFolder.getShellFolder(file); + } catch (FileNotFoundException e) { + return null; + } + return shellFolder.isLink() ? shellFolder.getLinkLocation() : null; + } + /** * Throws {@code FileNotFoundException} if file not found or current thread was interrupted */ diff --git a/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java b/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java new file mode 100644 index 00000000000..0892b5e2090 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016, 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 8081722 + * @summary Provide public API for file hierarchy provided by + * sun.awt.shell.ShellFolder + * @author Semyon Sadetsky + * @run main ShellFolderQueriesTest + */ + +import sun.awt.OSInfo; + +import javax.swing.filechooser.FileSystemView; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +public class ShellFolderQueriesTest { + static final String HOME = System.getProperty("user.home"); + static final FileSystemView fsv = FileSystemView.getFileSystemView(); + + + static String scriptBeg = + "set WshShell = WScript.CreateObject(\"WScript.Shell\")\n" + + "set oShellLink = WshShell.CreateShortcut(\"shortcut.lnk\")\n" + + "oShellLink.TargetPath = \""; + static String scriptEnd = "\"\noShellLink.WindowStyle = 1\noShellLink.Save"; + + public static void main(String[] args) throws Exception { + if(OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { + testGet(); + testLink(); + } else { + testGet(); + } + System.out.println("ok"); + } + + private static void testLink() throws IOException, InterruptedException { + // Create and execute VBS script to create a link + File file = createVbsScript(scriptBeg + HOME + scriptEnd); + Runtime.getRuntime().exec("cscript " + file.getName(), null, + file.getParentFile()).waitFor(); + file.delete(); + + File link = new File(file.getParentFile(), "shortcut.lnk"); + if (!fsv.isLink(link)) { + link.delete(); + throw new RuntimeException("Link is not detected"); + } + + File location = fsv.getLinkLocation(link); + if (!location.getAbsolutePath().equals(HOME)) { + link.delete(); + throw new RuntimeException("Link location " + location + + " is wrong"); + } + link.delete(); + + + link = File.createTempFile("test", ".tst"); + + if (fsv.isLink(link)) { + link.delete(); + throw new RuntimeException("File is not a link"); + } + + try { + location = fsv.getLinkLocation(link); + if (location != null) { + link.delete(); + throw new RuntimeException("Not a link, should return null"); + } + } + catch (FileNotFoundException e) { + } + link.delete(); + } + + private static File createVbsScript(String script) throws IOException { + File file = File.createTempFile("test", ".vbs"); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(script.getBytes()); + fos.close(); + return file; + } + + private static void testGet() { + File[] files = fsv.getChooserComboBoxFiles(); + for (File file : files) { + if (fsv.isLink(file)) { + throw new RuntimeException( + "Link shouldn't be in FileChooser combobox, " + + file.getPath()); + } + } + } +} From 4087262c5886bc9170b6de029af1ad0ae89532be Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Wed, 24 Feb 2016 19:25:16 +0300 Subject: [PATCH 101/311] 8150470: JCK: api/xsl/conf/copy/copy19 test failure Reviewed-by: joehw, aefimov --- .../sun/org/apache/xerces/internal/impl/XMLEntityManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java index f08a1275dfa..d405a33cdcd 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java @@ -2959,7 +2959,7 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { if (!fCurrentEntity.xmlDeclChunkRead) { fCurrentEntity.xmlDeclChunkRead = true; - len = DEFAULT_XMLDECL_BUFFER_SIZE; + len = Entity.ScannedEntity.DEFAULT_XMLDECL_BUFFER_SIZE; } return fInputStream.read(b, off, len); } From fb338bec25d6a355f2baabff7dff7e220947d73a Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Wed, 24 Feb 2016 16:33:19 -0500 Subject: [PATCH 102/311] 8150490: Update OS detection code to recognize Windows Server 2016 Reviewed-by: mgronlun, alanb, dholmes --- jdk/src/java.base/windows/native/libjava/java_props_md.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/windows/native/libjava/java_props_md.c b/jdk/src/java.base/windows/native/libjava/java_props_md.c index 135976483b6..382a35a571e 100644 --- a/jdk/src/java.base/windows/native/libjava/java_props_md.c +++ b/jdk/src/java.base/windows/native/libjava/java_props_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -469,7 +469,9 @@ GetJavaProperties(JNIEnv* env) * Windows Server 2008 R2 6 1 (!VER_NT_WORKSTATION) * Windows 8 6 2 (VER_NT_WORKSTATION) * Windows Server 2012 6 2 (!VER_NT_WORKSTATION) + * Windows Server 2012 R2 6 3 (!VER_NT_WORKSTATION) * Windows 10 10 0 (VER_NT_WORKSTATION) + * Windows Server 2016 10 0 (!VER_NT_WORKSTATION) * * This mapping will presumably be augmented as new Windows * versions are released. @@ -543,6 +545,7 @@ GetJavaProperties(JNIEnv* env) } } else { switch (minorVersion) { + case 0: sprops.os_name = "Windows Server 2016"; break; default: sprops.os_name = "Windows NT (unknown)"; } } From 306361b2920760ba73a4075836b30be8b54066e6 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Mon, 7 Mar 2016 13:45:38 -0500 Subject: [PATCH 103/311] 8139474: -release 7 -verbose causes Javac exception Reviewed-by: jjg --- .../com/sun/tools/javac/code/ClassFinder.java | 27 ++++++++-------- .../sun/tools/javac/file/RelativePath.java | 3 +- .../JavacProcessingEnvironment.java | 15 +++++---- .../T8139474/DashRelease7DashVerboseTest.java | 31 +++++++++++++++++++ 4 files changed, 54 insertions(+), 22 deletions(-) create mode 100644 langtools/test/tools/javac/T8139474/DashRelease7DashVerboseTest.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java index 0c602c4c16a..466a41d7635 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -26,7 +26,7 @@ package com.sun.tools.javac.code; import java.io.IOException; -import java.io.File; +import java.nio.file.Path; import java.util.EnumSet; import java.util.HashMap; import java.util.Map; @@ -45,7 +45,6 @@ import com.sun.tools.javac.code.Symbol.CompletionFailure; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.comp.Annotate; -import com.sun.tools.javac.comp.Enter; import com.sun.tools.javac.file.JRTIndex; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.jvm.ClassReader; @@ -535,25 +534,25 @@ public class ClassFinder { if (fileManager instanceof StandardJavaFileManager) { StandardJavaFileManager fm = (StandardJavaFileManager)fileManager; if (haveSourcePath && wantSourceFiles) { - List path = List.nil(); - for (File file : fm.getLocation(SOURCE_PATH)) { - path = path.prepend(file); + List path = List.nil(); + for (Path sourcePath : fm.getLocationAsPaths(SOURCE_PATH)) { + path = path.prepend(sourcePath); } log.printVerbose("sourcepath", path.reverse().toString()); } else if (wantSourceFiles) { - List path = List.nil(); - for (File file : fm.getLocation(CLASS_PATH)) { - path = path.prepend(file); + List path = List.nil(); + for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { + path = path.prepend(classPath); } log.printVerbose("sourcepath", path.reverse().toString()); } if (wantClassFiles) { - List path = List.nil(); - for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) { - path = path.prepend(file); + List path = List.nil(); + for (Path platformPath : fm.getLocationAsPaths(PLATFORM_CLASS_PATH)) { + path = path.prepend(platformPath); } - for (File file : fm.getLocation(CLASS_PATH)) { - path = path.prepend(file); + for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { + path = path.prepend(classPath); } log.printVerbose("classpath", path.reverse().toString()); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java index 59d79df9ac1..3e541b884f1 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, 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 @@ -25,7 +25,6 @@ package com.sun.tools.javac.file; -import java.io.File; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.InvalidPathException; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 94ed6da8d11..9165f9b2cb9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -31,6 +31,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.Path; import java.util.*; import java.util.regex.*; import java.util.stream.Collectors; @@ -42,6 +43,7 @@ import javax.lang.model.util.*; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; + import static javax.tools.StandardLocation.*; import com.sun.source.util.TaskEvent; @@ -79,6 +81,7 @@ import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Options; import com.sun.tools.javac.util.ServiceLoader; + import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.main.Option.*; @@ -317,9 +320,9 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea if (fileManager instanceof JavacFileManager) { StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager; - Iterable workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH) - ? standardFileManager.getLocation(ANNOTATION_PROCESSOR_PATH) - : standardFileManager.getLocation(CLASS_PATH); + Iterable workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH) + ? standardFileManager.getLocationAsPaths(ANNOTATION_PROCESSOR_PATH) + : standardFileManager.getLocationAsPaths(CLASS_PATH); if (needClassLoader(options.get(PROCESSOR), workingPath) ) handleException(key, e); @@ -1298,14 +1301,14 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea * Called retroactively to determine if a class loader was required, * after we have failed to create one. */ - private boolean needClassLoader(String procNames, Iterable workingpath) { + private boolean needClassLoader(String procNames, Iterable workingpath) { if (procNames != null) return true; URL[] urls = new URL[1]; - for(File pathElement : workingpath) { + for(Path pathElement : workingpath) { try { - urls[0] = pathElement.toURI().toURL(); + urls[0] = pathElement.toUri().toURL(); if (ServiceProxy.hasService(Processor.class, urls)) return true; } catch (MalformedURLException ex) { diff --git a/langtools/test/tools/javac/T8139474/DashRelease7DashVerboseTest.java b/langtools/test/tools/javac/T8139474/DashRelease7DashVerboseTest.java new file mode 100644 index 00000000000..5e0c19cddb3 --- /dev/null +++ b/langtools/test/tools/javac/T8139474/DashRelease7DashVerboseTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 8139474 + * @summary -release 7 -verbose causes Javac exception + * @compile -release 7 -verbose DashRelease7DashVerboseTest.java +*/ + +public class DashRelease7DashVerboseTest {} From 528c1dfc4ee4a8b2d98395949ccddf0b35d72f87 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Tue, 8 Mar 2016 11:37:00 -0800 Subject: [PATCH 104/311] 8148187: Remove OS X-specific com.apple.concurrent package Removed jdk.deploy.osx module (including com.apple.concurrent) Reviewed-by: alanb, erikj, mchung --- .../share/classes/com/sun/tools/javac/resources/ct.properties | 1 - .../jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties index 135646a3fdb..b94ead7665b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties @@ -1,6 +1,5 @@ apple.laf.*: hidden apple.security.*: hidden -com.apple.concurrent.*: hidden com.apple.eawt.*: hidden com.apple.eawt.event.*: hidden com.apple.eio.*: hidden diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java index bd70ec841b1..1c45a2fd54f 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java @@ -38,7 +38,7 @@ enum Profile { "jdk.httpserver", "jdk.security.auth", "jdk.naming.dns", "jdk.naming.rmi", "jdk.management"), - FULL_JRE("Full JRE", 4, "java.se", "jdk.deploy.osx", "jdk.charsets", + FULL_JRE("Full JRE", 4, "java.se", "jdk.charsets", "jdk.crypto.ec", "jdk.crypto.pkcs11", "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat", "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs"); From 51ea08084f757c2f33b9815a97b4328a3b64b1dc Mon Sep 17 00:00:00 2001 From: Robert Field Date: Tue, 8 Mar 2016 11:53:35 -0800 Subject: [PATCH 105/311] 8148316: jshell tool: Configurable output format 8148317: jshell tool: unify commands into /set 8149524: JShell: CompletenessAnalysis fails on class Case, E2 extends Enum, E3 extends Enum> {} Reviewed-by: jlahoda --- .../internal/jshell/tool/ArgTokenizer.java | 271 +++++ .../jdk/internal/jshell/tool/Feedback.java | 1049 +++++++++++++++++ .../jdk/internal/jshell/tool/JShellTool.java | 778 ++++++------ .../jdk/jshell/CompletenessAnalyzer.java | 4 +- .../jdk/jshell/CommandCompletionTest.java | 8 +- .../test/jdk/jshell/CompletenessTest.java | 4 +- .../test/jdk/jshell/ExternalEditorTest.java | 8 +- .../test/jdk/jshell/ReplToolTesting.java | 43 +- langtools/test/jdk/jshell/ToolBasicTest.java | 97 +- langtools/test/jdk/jshell/ToolFormatTest.java | 159 +++ 10 files changed, 1996 insertions(+), 425 deletions(-) create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java create mode 100644 langtools/test/jdk/jshell/ToolFormatTest.java diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java new file mode 100644 index 00000000000..2e86d9de290 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 1995, 2016, 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. + */ + +package jdk.internal.jshell.tool; + +import java.util.Arrays; +import java.util.stream.Stream; + +/** + * Parse command arguments, derived from StreamTokenizer by + * @author James Gosling + */ +class ArgTokenizer { + + private final String str; + private final int length; + private int next = 0; + private char buf[] = new char[20]; + private int mark; + + private final byte ctype[] = new byte[256]; + private static final byte CT_ALPHA = 0; + private static final byte CT_WHITESPACE = 1; + private static final byte CT_QUOTE = 8; + + private String sval; + private boolean isQuoted = false; + + ArgTokenizer(String arg) { + this.str = arg; + this.length = arg.length(); + quoteChar('"'); + quoteChar('\''); + whitespaceChars(0x09, 0x0D); + whitespaceChars(0x1C, 0x20); + whitespaceChars(0x85, 0x85); + whitespaceChars(0xA0, 0xA0); + } + + String next() { + nextToken(); + return sval; + } + + String[] next(String... strings) { + return next(Arrays.stream(strings)); + } + + String[] next(Stream stream) { + nextToken(); + if (sval == null) { + return null; + } + String[] matches = stream + .filter(s -> s.startsWith(sval)) + .toArray(size -> new String[size]); + return matches; + } + + String val() { + return sval; + } + + boolean isQuoted() { + return isQuoted; + } + + String whole() { + return str; + } + + void mark() { + mark = next; + } + + void rewind() { + next = mark; + } + + /** + * Reads a single character. + * + * @return The character read, or -1 if the end of the stream has been + * reached + */ + private int read() { + if (next >= length) { + return -1; + } + return str.charAt(next++); + } + + /** + * Specifies that all characters c in the range + * low <= c <= high + * are white space characters. White space characters serve only to + * separate tokens in the input stream. + * + *

      Any other attribute settings for the characters in the specified + * range are cleared. + * + * @param low the low end of the range. + * @param hi the high end of the range. + */ + private void whitespaceChars(int low, int hi) { + if (low < 0) + low = 0; + if (hi >= ctype.length) + hi = ctype.length - 1; + while (low <= hi) + ctype[low++] = CT_WHITESPACE; + } + + /** + * Specifies that matching pairs of this character delimit string + * constants in this tokenizer. + *

      + * If a string quote character is encountered, then a string is + * recognized, consisting of all characters after (but not including) + * the string quote character, up to (but not including) the next + * occurrence of that same string quote character, or a line + * terminator, or end of file. The usual escape sequences such as + * {@code "\u005Cn"} and {@code "\u005Ct"} are recognized and + * converted to single characters as the string is parsed. + * + *

      Any other attribute settings for the specified character are cleared. + * + * @param ch the character. + */ + private void quoteChar(int ch) { + if (ch >= 0 && ch < ctype.length) + ctype[ch] = CT_QUOTE; + } + + private int unicode2ctype(int c) { + switch (c) { + case 0x1680: + case 0x180E: + case 0x200A: + case 0x202F: + case 0x205F: + case 0x3000: + return CT_WHITESPACE; + default: + return CT_ALPHA; + } + } + + /** + * Parses the next token of this tokenizer. + */ + public void nextToken() { + byte ct[] = ctype; + int c; + int lctype; + sval = null; + isQuoted = false; + + do { + c = read(); + if (c < 0) { + return; + } + lctype = (c < 256) ? ct[c] : unicode2ctype(c); + } while (lctype == CT_WHITESPACE); + + if (lctype == CT_ALPHA) { + int i = 0; + do { + if (i >= buf.length) { + buf = Arrays.copyOf(buf, buf.length * 2); + } + buf[i++] = (char) c; + c = read(); + lctype = c < 0 ? CT_WHITESPACE : (c < 256)? ct[c] : unicode2ctype(c); + } while (lctype == CT_ALPHA); + if (c >= 0) --next; // push last back + sval = String.copyValueOf(buf, 0, i); + return; + } + + if (lctype == CT_QUOTE) { + int quote = c; + int i = 0; + /* Invariants (because \Octal needs a lookahead): + * (i) c contains char value + * (ii) d contains the lookahead + */ + int d = read(); + while (d >= 0 && d != quote) { + if (d == '\\') { + c = read(); + int first = c; /* To allow \377, but not \477 */ + if (c >= '0' && c <= '7') { + c = c - '0'; + int c2 = read(); + if ('0' <= c2 && c2 <= '7') { + c = (c << 3) + (c2 - '0'); + c2 = read(); + if ('0' <= c2 && c2 <= '7' && first <= '3') { + c = (c << 3) + (c2 - '0'); + d = read(); + } else + d = c2; + } else + d = c2; + } else { + switch (c) { + case 'a': + c = 0x7; + break; + case 'b': + c = '\b'; + break; + case 'f': + c = 0xC; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = 0xB; + break; + } + d = read(); + } + } else { + c = d; + d = read(); + } + if (i >= buf.length) { + buf = Arrays.copyOf(buf, buf.length * 2); + } + buf[i++] = (char)c; + } + + if (d == quote) { + isQuoted = true; + } + sval = String.copyValueOf(buf, 0, i); + } + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java new file mode 100644 index 00000000000..9089dfc86aa --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java @@ -0,0 +1,1049 @@ +/* + * Copyright (c) 2016, 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. + */ + +package jdk.internal.jshell.tool; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Feedback customization support + * + * @author Robert Field + */ +class Feedback { + + // Patern for substituted fields within a customized format string + private static final Pattern FIELD_PATTERN = Pattern.compile("\\{(.*?)\\}"); + + // Current mode + private Mode mode = new Mode("", false); // initial value placeholder during start-up + + // Mapping of mode names to mode modes + private final Map modeMap = new HashMap<>(); + + public boolean shouldDisplayCommandFluff() { + return mode.commandFluff; + } + + public String getPre() { + return mode.pre; + } + + public String getPost() { + return mode.post; + } + + public String getErrorPre() { + return mode.errorPre; + } + + public String getErrorPost() { + return mode.errorPost; + } + + public String getFormat(FormatCase fc, FormatWhen fw, FormatAction fa, FormatResolve fr, + boolean hasName, boolean hasType, boolean hasResult) { + return mode.getFormat(fc, fw, fa, fr, hasName, hasType, hasResult); + } + + public String getPrompt(String nextId) { + return mode.getPrompt(nextId); + } + + public String getContinuationPrompt(String nextId) { + return mode.getContinuationPrompt(nextId); + } + + public boolean setFeedback(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setFeedback(); + } + + public boolean setField(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setField(); + } + + public boolean setFormat(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setFormat(); + } + + public boolean setNewMode(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setNewMode(); + } + + public boolean setPrompt(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setPrompt(); + } + + public void printFeedbackHelp(JShellTool tool) { + new FormatSetter(tool, null).printFeedbackHelp(); + } + + public void printFieldHelp(JShellTool tool) { + new FormatSetter(tool, null).printFieldHelp(); + } + + public void printFormatHelp(JShellTool tool) { + new FormatSetter(tool, null).printFormatHelp(); + } + + public void printNewModeHelp(JShellTool tool) { + new FormatSetter(tool, null).printNewModeHelp(); + } + + public void printPromptHelp(JShellTool tool) { + new FormatSetter(tool, null).printPromptHelp(); + } + + /** + * Holds all the context of a mode mode + */ + private class Mode { + + // Use name of mode mode + + final String name; + + // Display command verification/information + final boolean commandFluff; + + // event cases: class, method + final EnumMap>> cases; + + // action names: add. modified, replaced, ... + final EnumMap> actions; + + // resolution status description format with %s for unresolved + final EnumMap> resolves; + + // primary snippet vs update + final EnumMap whens; + + // fixed map of how to get format string for a field, given a specific formatting contet + final EnumMap> fields; + + // format wrappers for name, type, and result + String fname = "%s"; + String ftype = "%s"; + String fresult = "%s"; + + // start and end, also used by hard-coded output + String pre = "| "; + String post = "\n"; + String errorPre = "| Error: "; + String errorPost = "\n"; + + String prompt = "\n-> "; + String continuationPrompt = ">> "; + + /** + * The context of a specific mode to potentially display. + */ + class Context { + + final FormatCase fc; + final FormatAction fa; + final FormatResolve fr; + final FormatWhen fw; + final boolean hasName; + final boolean hasType; + final boolean hasResult; + + Context(FormatCase fc, FormatWhen fw, FormatAction fa, FormatResolve fr, + boolean hasName, boolean hasType, boolean hasResult) { + this.fc = fc; + this.fa = fa; + this.fr = fr; + this.fw = fw; + this.hasName = hasName; + this.hasType = hasType; + this.hasResult = hasResult; + } + + String when() { + return whens.get(fw); + } + + String action() { + return actions.get(fa).get(fw); + } + + String resolve() { + return String.format(resolves.get(fr).get(fw), FormatField.RESOLVE.form); + } + + String name() { + return hasName + ? String.format(fname, FormatField.NAME.form) + : ""; + } + + String type() { + return hasType + ? String.format(ftype, FormatField.TYPE.form) + : ""; + } + + String result() { + return hasResult + ? String.format(fresult, FormatField.RESULT.form) + : ""; + } + + /** + * Lookup format based on case, action, and whether it update. + * Replace fields with context specific formats. + * + * @return format string + */ + String format() { + String format = cases.get(fc).get(fa).get(fw); + if (format == null) { + return ""; + } + Matcher m = FIELD_PATTERN.matcher(format); + StringBuffer sb = new StringBuffer(format.length()); + while (m.find()) { + String fieldName = m.group(1).toUpperCase(Locale.US); + String sub = null; + for (FormatField f : FormatField.values()) { + if (f.name().startsWith(fieldName)) { + sub = fields.get(f).apply(this); + break; + } + } + if (sub != null) { + m.appendReplacement(sb, Matcher.quoteReplacement(sub)); + } + } + m.appendTail(sb); + return sb.toString(); + } + } + + { + // set fixed mappings of fields + fields = new EnumMap<>(FormatField.class); + fields.put(FormatField.WHEN, c -> c.when()); + fields.put(FormatField.ACTION, c -> c.action()); + fields.put(FormatField.RESOLVE, c -> c.resolve()); + fields.put(FormatField.NAME, c -> c.name()); + fields.put(FormatField.TYPE, c -> c.type()); + fields.put(FormatField.RESULT, c -> c.result()); + fields.put(FormatField.PRE, c -> pre); + fields.put(FormatField.POST, c -> post); + fields.put(FormatField.ERRORPRE, c -> errorPre); + fields.put(FormatField.ERRORPOST, c -> errorPost); + } + + /** + * Set up an empty mode. + * + * @param name + * @param commandFluff True if should display command fluff messages + */ + Mode(String name, boolean commandFluff) { + this.name = name; + this.commandFluff = commandFluff; + cases = new EnumMap<>(FormatCase.class); + for (FormatCase fc : FormatCase.values()) { + EnumMap> ac = new EnumMap<>(FormatAction.class); + cases.put(fc, ac); + for (FormatAction fa : FormatAction.values()) { + EnumMap aw = new EnumMap<>(FormatWhen.class); + ac.put(fa, aw); + for (FormatWhen fw : FormatWhen.values()) { + aw.put(fw, ""); + } + } + } + + actions = new EnumMap<>(FormatAction.class); + for (FormatAction fa : FormatAction.values()) { + EnumMap afw = new EnumMap<>(FormatWhen.class); + actions.put(fa, afw); + for (FormatWhen fw : FormatWhen.values()) { + afw.put(fw, fa.name() + "-" + fw.name()); + } + } + + resolves = new EnumMap<>(FormatResolve.class); + for (FormatResolve fr : FormatResolve.values()) { + EnumMap arw = new EnumMap<>(FormatWhen.class); + resolves.put(fr, arw); + for (FormatWhen fw : FormatWhen.values()) { + arw.put(fw, fr.name() + "-" + fw.name() + ": %s"); + } + } + + whens = new EnumMap<>(FormatWhen.class); + for (FormatWhen fw : FormatWhen.values()) { + whens.put(fw, fw.name()); + } + } + + /** + * Set up a copied mode. + * + * @param name + * @param commandFluff True if should display command fluff messages + * @param m Mode to copy + */ + Mode(String name, boolean commandFluff, Mode m) { + this.name = name; + this.commandFluff = commandFluff; + cases = new EnumMap<>(FormatCase.class); + for (FormatCase fc : FormatCase.values()) { + EnumMap> ac = new EnumMap<>(FormatAction.class); + EnumMap> mc = m.cases.get(fc); + cases.put(fc, ac); + for (FormatAction fa : FormatAction.values()) { + EnumMap aw = new EnumMap<>(mc.get(fa)); + ac.put(fa, aw); + } + } + + actions = new EnumMap<>(FormatAction.class); + for (FormatAction fa : FormatAction.values()) { + EnumMap afw = new EnumMap<>(m.actions.get(fa)); + actions.put(fa, afw); + } + + resolves = new EnumMap<>(FormatResolve.class); + for (FormatResolve fr : FormatResolve.values()) { + EnumMap arw = new EnumMap<>(m.resolves.get(fr)); + resolves.put(fr, arw); + } + + whens = new EnumMap<>(m.whens); + + this.fname = m.fname; + this.ftype = m.ftype; + this.fresult = m.fresult; + this.pre = m.pre; + this.post = m.post; + this.errorPre = m.errorPre; + this.errorPost = m.errorPost; + this.prompt = m.prompt; + this.continuationPrompt = m.continuationPrompt; + } + + String getFormat(FormatCase fc, FormatWhen fw, FormatAction fa, FormatResolve fr, + boolean hasName, boolean hasType, boolean hasResult) { + Context context = new Context(fc, fw, fa, fr, + hasName, hasType, hasResult); + return context.format(); + } + + void setCases(String format, Collection cc, Collection ca, Collection cw) { + for (FormatCase fc : cc) { + EnumMap> ma = cases.get(fc); + for (FormatAction fa : ca) { + EnumMap mw = ma.get(fa); + for (FormatWhen fw : cw) { + mw.put(fw, format); + } + } + } + } + + void setActions(String format, Collection ca, Collection cw) { + for (FormatAction fa : ca) { + EnumMap mw = actions.get(fa); + for (FormatWhen fw : cw) { + mw.put(fw, format); + } + } + } + + void setResolves(String format, Collection cr, Collection cw) { + for (FormatResolve fr : cr) { + EnumMap mw = resolves.get(fr); + for (FormatWhen fw : cw) { + mw.put(fw, format); + } + } + } + + void setWhens(String format, Collection cw) { + for (FormatWhen fw : cw) { + whens.put(fw, format); + } + } + + void setName(String s) { + fname = s; + } + + void setType(String s) { + ftype = s; + } + + void setResult(String s) { + fresult = s; + } + + void setPre(String s) { + pre = s; + } + + void setPost(String s) { + post = s; + } + + void setErrorPre(String s) { + errorPre = s; + } + + void setErrorPost(String s) { + errorPost = s; + } + + String getPre() { + return pre; + } + + String getPost() { + return post; + } + + String getErrorPre() { + return errorPre; + } + + String getErrorPost() { + return errorPost; + } + + void setPrompts(String prompt, String continuationPrompt) { + this.prompt = prompt; + this.continuationPrompt = continuationPrompt; + } + + String getPrompt(String nextId) { + return String.format(prompt, nextId); + } + + String getContinuationPrompt(String nextId) { + return String.format(continuationPrompt, nextId); + } + } + + /** + * The brace delimited substitutions + */ + public enum FormatField { + WHEN, + ACTION, + RESOLVE("%1$s"), + NAME("%2$s"), + TYPE("%3$s"), + RESULT("%4$s"), + PRE, + POST, + ERRORPRE, + ERRORPOST; + String form; + + FormatField(String s) { + this.form = s; + } + + FormatField() { + this.form = null; + } + } + + /** + * The event cases + */ + public enum FormatCase { + IMPORT("import declaration: {action} {name}"), + CLASS("class, interface, enum, or annotation declaration: {action} {name} {resolve}"), + INTERFACE("class, interface, enum, or annotation declaration: {action} {name} {resolve}"), + ENUM("class, interface, enum, or annotation declaration: {action} {name} {resolve}"), + ANNOTATION("annotation interface declaration: {action} {name} {resolve}"), + METHOD("method declaration: {action} {name} {type}==parameter-types {resolve}"), + VARDECL("variable declaration: {action} {name} {type} {resolve}"), + VARDECLRECOVERABLE("recoverably failed variable declaration: {action} {name} {resolve}"), + VARINIT("variable declaration with init: {action} {name} {type} {resolve} {result}"), + VARRESET("variable reset on update: {action} {name}"), + EXPRESSION("expression: {action}=='Saved to scratch variable' {name} {type} {result}"), + VARVALUE("variable value expression: {action} {name} {type} {result}"), + ASSIGNMENT("assign variable: {action} {name} {type} {result}"), + STATEMENT("statement: {action}"); + String doc; + + private FormatCase(String doc) { + this.doc = doc; + } + } + + /** + * The event actions + */ + public enum FormatAction { + ADDED("snippet has been added"), + MODIFIED("an existing snippet has been modified"), + REPLACED("an existing snippet has been replaced with a new snippet"), + OVERWROTE("an existing snippet has been overwritten"), + DROPPED("snippet has been dropped"), + REJECTED("snippet has failed and been rejected"); + String doc; + + private FormatAction(String doc) { + this.doc = doc; + } + } + + /** + * When the event occurs: primary or update + */ + public enum FormatWhen { + PRIMARY("the entered snippet"), + UPDATE("an update to a dependent snippet"); + String doc; + + private FormatWhen(String doc) { + this.doc = doc; + } + } + + /** + * Resolution problems with event + */ + public enum FormatResolve { + OK("resolved correctly"), + DEFINED("defined despite recoverably unresolved references"), + NOTDEFINED("not defined because of recoverably unresolved references"); + String doc; + + private FormatResolve(String doc) { + this.doc = doc; + } + } + + // Class used to set custom eval output formats + // For both /set format and /set field -- Parse arguments, setting custom format, or printing error + private class FormatSetter { + + private final ArgTokenizer at; + private final JShellTool tool; + boolean valid = true; + + class Case, E2 extends Enum, E3 extends Enum> { + + Set e1; + Set e2; + Set e3; + + Case(Set e1, Set e2, Set e3) { + this.e1 = e1; + this.e2 = e2; + this.e3 = e3; + } + + Case(Set e1, Set e2) { + this.e1 = e1; + this.e2 = e2; + } + } + + FormatSetter(JShellTool tool, ArgTokenizer at) { + this.tool = tool; + this.at = at; + } + + void hard(String format, Object... args) { + tool.hard(format, args); + } + + > void hardEnums(EnumSet es, Function e2s) { + hardPairs(es.stream(), ev -> ev.name().toLowerCase(Locale.US), e2s); + } + + void hardPairs(Stream stream, Function a, Function b) { + tool.hardPairs(stream, a, b); + } + + void fluff(String format, Object... args) { + tool.fluff(format, args); + } + + void error(String format, Object... args) { + tool.error(format, args); + } + + void errorat(String format, Object... args) { + Object[] a2 = Arrays.copyOf(args, args.length + 1); + a2[args.length] = at.whole(); + tool.error(format + " -- /set %s", a2); + } + + void fluffRaw(String format, Object... args) { + tool.fluffRaw(format, args); + } + + // For /set prompt "" "" + boolean setPrompt() { + Mode m = nextMode(); + String prompt = nextFormat(); + String continuationPrompt = nextFormat(); + if (valid) { + m.setPrompts(prompt, continuationPrompt); + } else { + fluff("See '/help /set prompt' for help"); + } + return valid; + } + + // For /set newmode [command|quiet []] + boolean setNewMode() { + String umode = at.next(); + if (umode == null) { + errorat("Expected new feedback mode"); + valid = false; + } + if (modeMap.containsKey(umode)) { + errorat("Expected a new feedback mode name. %s is a known feedback mode", umode); + valid = false; + } + String[] fluffOpt = at.next("command", "quiet"); + boolean fluff = fluffOpt == null || fluffOpt.length != 1 || "command".equals(fluffOpt[0]); + if (fluffOpt != null && fluffOpt.length != 1) { + errorat("Specify either 'command' or 'quiet'"); + valid = false; + } + Mode om = null; + String omode = at.next(); + if (omode != null) { + om = toMode(omode); + } + if (valid) { + Mode nm = (om != null) + ? new Mode(umode, fluff, om) + : new Mode(umode, fluff); + modeMap.put(umode, nm); + fluff("Created new feedback mode: %s", nm.name); + } else { + fluff("See '/help /set newmode' for help"); + } + return valid; + } + + // For /set feedback + boolean setFeedback() { + Mode m = nextMode(); + if (valid && m != null) { + mode = m; + fluff("Feedback mode: %s", mode.name); + } else { + fluff("See '/help /set feedback' for help"); + } + return valid; + } + + // For /set format "" ... + boolean setFormat() { + Mode m = nextMode(); + String format = nextFormat(); + if (valid) { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatCase(d, 0), + parseFormatAction(d, 1), + parseFormatWhen(d, 2) + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format in the specified cases + specs.stream() + .forEach(c -> m.setCases(format, c.e1, c.e2, c.e3)); + } + } + if (!valid) { + fluff("See '/help /set format' for help"); + } + return valid; + } + + // For /set field mode "" ... + boolean setField() { + Mode m = nextMode(); + String fieldName = at.next(); + FormatField field = parseFormatSelector(fieldName, EnumSet.allOf(FormatField.class), "field"); + String format = nextFormat(); + if (valid) { + switch (field) { + case ACTION: { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatAction(d, 0), + parseFormatWhen(d, 1) + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format of the specified actions + specs.stream() + .forEach(c -> m.setActions(format, c.e1, c.e2)); + } + break; + } + case RESOLVE: { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatResolve(d, 0), + parseFormatWhen(d, 1) + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format of the specified resolves + specs.stream() + .forEach(c -> m.setResolves(format, c.e1, c.e2)); + } + break; + } + case WHEN: { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatWhen(d, 1), + null + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format of the specified whens + specs.stream() + .forEach(c -> m.setWhens(format, c.e1)); + } + break; + } + case NAME: { + m.setName(format); + break; + } + case TYPE: { + m.setType(format); + break; + } + case RESULT: { + m.setResult(format); + break; + } + case PRE: { + m.setPre(format); + break; + } + case POST: { + m.setPost(format); + break; + } + case ERRORPRE: { + m.setErrorPre(format); + break; + } + case ERRORPOST: { + m.setErrorPost(format); + break; + } + } + } + if (!valid) { + fluff("See '/help /set field' for help"); + } + return valid; + } + + Mode nextMode() { + String umode = at.next(); + return toMode(umode); + } + + Mode toMode(String umode) { + if (umode == null) { + errorat("Expected a feedback mode"); + valid = false; + return null; + } + Mode m = modeMap.get(umode); + if (m != null) { + return m; + } + // Failing an exact match, go searching + Mode[] matches = modeMap.entrySet().stream() + .filter(e -> e.getKey().startsWith(umode)) + .map(e -> e.getValue()) + .toArray(size -> new Mode[size]); + if (matches.length == 1) { + return matches[0]; + } else { + valid = false; + if (matches.length == 0) { + errorat("Does not match any current feedback mode: %s", umode); + } else { + errorat("Matchs more then one current feedback mode: %s", umode); + } + fluff("The feedback mode should be one of the following:"); + modeMap.keySet().stream() + .forEach(mk -> fluff(" %s", mk)); + fluff("You may also use just enough letters to make it unique."); + return null; + } + } + + // Test if the format string is correctly + final String nextFormat() { + String format = at.next(); + if (format == null) { + errorat("Expected format missing"); + valid = false; + return null; + } + if (!at.isQuoted()) { + errorat("Format '%s' must be quoted", format); + valid = false; + return null; + } + return format; + } + + final Set parseFormatCase(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatCase.class, EnumSet.allOf(FormatCase.class), "case"); + } + + final Set parseFormatAction(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatAction.class, + EnumSet.of(FormatAction.ADDED, FormatAction.MODIFIED, FormatAction.REPLACED), "action"); + } + + final Set parseFormatResolve(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatResolve.class, + EnumSet.of(FormatResolve.DEFINED, FormatResolve.NOTDEFINED), "resolve"); + } + + final Set parseFormatWhen(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatWhen.class, EnumSet.of(FormatWhen.PRIMARY), "when"); + } + + /** + * In a selector x-y-z , parse x, y, or z -- whether they are missing, + * or a comma separated list of identifiers and stars. + * + * @param The enum this selector should belong to + * @param sa The array of selector strings + * @param i The index of which selector string to use + * @param klass The class of the enum that should be used + * @param defaults The set of enum values to use if the selector is + * missing + * @return The set of enum values specified by this selector + */ + final > Set parseFormatSelectorStar(String[] sa, int i, Class klass, EnumSet defaults, String label) { + String s = sa.length > i + ? sa[i] + : null; + if (s == null || s.isEmpty()) { + return defaults; + } + Set set = EnumSet.noneOf(klass); + EnumSet values = EnumSet.allOf(klass); + for (String as : s.split(",")) { + if (as.equals("*")) { + set.addAll(values); + } else if (!as.isEmpty()) { + set.add(parseFormatSelector(as, values, label)); + } + } + return set; + } + + /** + * In a x-y-a,b selector, parse an x, y, a, or b -- that is an + * identifier + * + * @param The enum this selector should belong to + * @param s The string to parse: x, y, or z + * @param values The allowed of this enum + * @return The enum value + */ + final > E parseFormatSelector(String s, EnumSet values, String label) { + if (s == null) { + valid = false; + return null; + } + String u = s.toUpperCase(Locale.US); + for (E c : values) { + if (c.name().startsWith(u)) { + return c; + } + } + + errorat("Not a valid %s: %s, must be one of: %s", label, s, + values.stream().map(v -> v.name().toLowerCase(Locale.US)).collect(Collectors.joining(" "))); + valid = false; + return values.iterator().next(); + } + + final void printFormatHelp() { + hard("Set the format for reporting a snippet event."); + hard(""); + hard("/set format \"\" ..."); + hard(""); + hard("Where is the name of a previously defined feedback mode -- see '/help /set newmode'."); + hard("Where is a quoted string which will have these field substitutions:"); + hard(" {action} == The action, e.g.: Added, Modified, Assigned, ..."); + hard(" {name} == The name, e.g.: the variable name, ..."); + hard(" {type} == The type name"); + hard(" {resolve} == Unresolved info, e.g.: ', however, it cannot be invoked until'"); + hard(" {result} == The result value"); + hard(" {when} == The entered snippet or a resultant update"); + hard(" {pre} == The feedback prefix"); + hard(" {post} == The feedback postfix"); + hard(" {errorpre} == The error prefix"); + hard(" {errorpost} == The error postfix"); + hard("Use '/set field' to set the format of these substitutions."); + hard("Where is the context in which the format is applied."); + hard("The structure of selector is: [-[-]]"); + hard("Where each field component may be missing (indicating defaults),"); + hard("star (indicating all), or a comma separated list of field values."); + hard("For case, the field values are:"); + hardEnums(EnumSet.allOf(FormatCase.class), ev -> ev.doc); + hard("For action, the field values are:"); + hardEnums(EnumSet.allOf(FormatAction.class), ev -> ev.doc); + hard("For when, the field values are:"); + hardEnums(EnumSet.allOf(FormatWhen.class), ev -> ev.doc); + hard(""); + hard("Example:"); + hard(" /set format example '{pre}{action} variable {name}, reset to null{post}' varreset-*-update"); + } + + final void printFieldHelp() { + hard("Set the format of a field substitution as used in '/set format'."); + hard(""); + hard("/set field \"\" ..."); + hard(""); + hard("Where is the name of a previously defined feedback mode -- see '/set newmode'."); + hard("Where is context-specific format to set, each with its own selector structure:"); + hard(" action == The action. The selector: -."); + hard(" name == The name. '%%s' is the name. No selectors."); + hard(" type == The type name. '%%s' is the type. No selectors."); + hard(" resolve == Unresolved info. '%%s' is the unresolved list. The selector: -."); + hard(" result == The result value. '%%s' is the result value. No selectors."); + hard(" when == The entered snippet or a resultant update. The selector: "); + hard(" pre == The feedback prefix. No selectors."); + hard(" post == The feedback postfix. No selectors."); + hard(" errorpre == The error prefix. No selectors."); + hard(" errorpost == The error postfix. No selectors."); + hard("Where is a quoted string -- see the description specific to the field (above)."); + hard("Where is the context in which the format is applied (see above)."); + hard("For action, the field values are:"); + hardEnums(EnumSet.allOf(FormatAction.class), ev -> ev.doc); + hard("For when, the field values are:"); + hardEnums(EnumSet.allOf(FormatWhen.class), ev -> ev.doc); + hard("For resolve, the field values are:"); + hardEnums(EnumSet.allOf(FormatResolve.class), ev -> ev.doc); + hard(""); + hard("Example:"); + hard(" /set field example resolve ' which cannot be invoked until%%s is declared' defined-update"); + } + + final void printFeedbackHelp() { + hard("Set the feedback mode describing displayed feedback for entered snippets and commands."); + hard(""); + hard("/set feedback "); + hard(""); + hard("Where is the name of a previously defined feedback mode."); + hard("Currently defined feedback modes:"); + modeMap.keySet().stream() + .forEach(m -> hard(" %s", m)); + hard("User-defined modes can be added, see '/help /set newmode'"); + } + + final void printNewModeHelp() { + hard("Create a user-defined feedback mode, optionally copying from an existing mode."); + hard(""); + hard("/set newmode [command|quiet []]"); + hard(""); + hard("Where is the name of a mode you wish to create."); + hard("Where is the name of a previously defined feedback mode."); + hard("If is present, its settings are copied to the new mode."); + hard("'command' vs 'quiet' determines if informative/verifying command feedback is displayed."); + hard(""); + hard("Once the new mode is created, use '/set format', '/set field', and '/set prompt' to configure it."); + hard("Use '/set feedback' to use the new mode."); + } + + final void printPromptHelp() { + hard("Set the prompts. Both the normal prompt and the continuation-prompt must be set."); + hard(""); + hard("/set prompt \"\" \"\""); + hard(""); + hard("Where is the name of a previously defined feedback mode."); + hard("Where and are quoted strings printed as input promptds;"); + hard("Both may optionally contain '%%s' which will be substituted with the next snippet id --"); + hard("note that what is entered may not be assigned that id, for example it may be an error or command."); + hard("The continuation-prompt is used on the second and subsequent lines of a multi-line snippet."); + } + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index fd14be2a612..10b121b4062 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -35,7 +34,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.io.Reader; -import java.io.StreamTokenizer; import java.io.StringReader; import java.nio.charset.Charset; import java.nio.file.AccessDeniedException; @@ -66,24 +64,25 @@ import java.util.stream.StreamSupport; import jdk.internal.jshell.debug.InternalDebugControl; import jdk.internal.jshell.tool.IOContext.InputInterruptedException; +import jdk.jshell.DeclarationSnippet; import jdk.jshell.Diag; import jdk.jshell.EvalException; +import jdk.jshell.ExpressionSnippet; +import jdk.jshell.ImportSnippet; import jdk.jshell.JShell; -import jdk.jshell.Snippet; -import jdk.jshell.DeclarationSnippet; -import jdk.jshell.TypeDeclSnippet; +import jdk.jshell.JShell.Subscription; import jdk.jshell.MethodSnippet; import jdk.jshell.PersistentSnippet; -import jdk.jshell.VarSnippet; -import jdk.jshell.ExpressionSnippet; +import jdk.jshell.Snippet; import jdk.jshell.Snippet.Status; +import jdk.jshell.Snippet.SubKind; +import jdk.jshell.SnippetEvent; import jdk.jshell.SourceCodeAnalysis; import jdk.jshell.SourceCodeAnalysis.CompletionInfo; import jdk.jshell.SourceCodeAnalysis.Suggestion; -import jdk.jshell.SnippetEvent; +import jdk.jshell.TypeDeclSnippet; import jdk.jshell.UnresolvedReferenceException; -import jdk.jshell.Snippet.SubKind; -import jdk.jshell.JShell.Subscription; +import jdk.jshell.VarSnippet; import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; @@ -94,7 +93,12 @@ import java.util.ResourceBundle; import java.util.Spliterators; import java.util.function.Function; import java.util.function.Supplier; +import jdk.internal.jshell.tool.Feedback.FormatAction; +import jdk.internal.jshell.tool.Feedback.FormatCase; +import jdk.internal.jshell.tool.Feedback.FormatResolve; +import jdk.internal.jshell.tool.Feedback.FormatWhen; import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND; /** @@ -103,6 +107,7 @@ import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND; */ public class JShellTool { + private static final String LINE_SEP = System.getProperty("line.separator"); private static final Pattern LINEBREAK = Pattern.compile("\\R"); private static final Pattern HISTORY_ALL_START_FILENAME = Pattern.compile( "((?(all|history|start))(\\z|\\p{javaWhitespace}+))?(?.*)"); @@ -116,6 +121,8 @@ public class JShellTool { final PrintStream userout; final PrintStream usererr; + final Feedback feedback = new Feedback(); + /** * The constructor for the tool (used by tool launch via main and by test * harnesses to capture ins and outs. @@ -137,6 +144,70 @@ public class JShellTool { this.userin = userin; this.userout = userout; this.usererr = usererr; + initializeFeedbackModes(); + } + + /** + * Create the default set of feedback modes + */ + final void initializeFeedbackModes() { + // Initialize normal feedback mode + cmdSet("newmode normal command"); + cmdSet("prompt normal '\n-> ' '>> '"); + cmdSet("field normal pre '| '"); + cmdSet("field normal post '%n'"); + cmdSet("field normal errorpre '| '"); + cmdSet("field normal errorpost '%n'"); + cmdSet("field normal action 'Added' added-primary"); + cmdSet("field normal action 'Modified' modified-primary"); + cmdSet("field normal action 'Replaced' replaced-primary"); + cmdSet("field normal action 'Overwrote' overwrote-primary"); + cmdSet("field normal action 'Dropped' dropped-primary"); + cmdSet("field normal action 'Rejected' rejected-primary"); + cmdSet("field normal action ' Update added' added-update"); + cmdSet("field normal action ' Update modified' modified-update"); + cmdSet("field normal action ' Update replaced' replaced-update"); + cmdSet("field normal action ' Update overwrote' overwrote-update"); + cmdSet("field normal action ' Update dropped' dropped-update"); + cmdSet("field normal action ' Update rejected' rejected-update"); + cmdSet("field normal resolve '' ok-*"); + cmdSet("field normal resolve ', however, it cannot be invoked until%s is declared' defined-primary"); + cmdSet("field normal resolve ', however, it cannot be referenced until%s is declared' notdefined-primary"); + cmdSet("field normal resolve ' which cannot be invoked until%s is declared' defined-update"); + cmdSet("field normal resolve ' which cannot be referenced until%s is declared' notdefined-update"); + cmdSet("field normal name '%s'"); + cmdSet("field normal type '%s'"); + cmdSet("field normal result '%s'"); + + cmdSet("format normal '' *-*-*"); + + cmdSet("format normal '{pre}{action} class {name}{resolve}{post}' class"); + cmdSet("format normal '{pre}{action} interface {name}{resolve}{post}' interface"); + cmdSet("format normal '{pre}{action} enum {name}{resolve}{post}' enum"); + cmdSet("format normal '{pre}{action} annotation interface {name}{resolve}{post}' annotation"); + + cmdSet("format normal '{pre}{action} method {name}({type}){resolve}{post}' method"); + + cmdSet("format normal '{pre}{action} variable {name} of type {type}{resolve}{post}' vardecl"); + cmdSet("format normal '{pre}{action} variable {name} of type {type} with initial value {result}{resolve}{post}' varinit"); + cmdSet("format normal '{pre}{action} variable {name}{resolve}{post}' vardeclrecoverable"); + cmdSet("format normal '{pre}{action} variable {name}, reset to null{post}' varreset-*-update"); + + cmdSet("format normal '{pre}Expression value is: {result}{post}" + + "{pre} assigned to temporary variable {name} of type {type}{post}' expression"); + cmdSet("format normal '{pre}Variable {name} of type {type} has value {result}{post}' varvalue"); + cmdSet("format normal '{pre}Variable {name} has been assigned the value {result}{post}' assignment"); + + cmdSet("feedback normal"); + + // Initialize off feedback mode + cmdSet("newmode off quiet"); + cmdSet("prompt off '-> ' '>> '"); + cmdSet("field off pre '| '"); + cmdSet("field off post '%n'"); + cmdSet("field off errorpre '| '"); + cmdSet("field off errorpost '%n'"); + cmdSet("format off '' *-*-*"); } private IOContext input = null; @@ -150,7 +221,6 @@ public class JShellTool { private boolean debug = false; private boolean displayPrompt = true; public boolean testPrompt = false; - private Feedback feedback = Feedback.Default; private String cmdlineClasspath = null; private String cmdlineStartup = null; private String[] editor = null; @@ -185,6 +255,15 @@ public class JShellTool { Map mapSnippet; + /** + * Is the input/output currently interactive + * + * @return true if console + */ + boolean interactive() { + return input != null && input.interactiveOutput(); + } + void debug(String format, Object... args) { if (debug) { cmderr.printf(format + "\n", args); @@ -192,38 +271,98 @@ public class JShellTool { } /** - * For more verbose feedback modes - * @param format printf format - * @param args printf args + * Base output for command output -- no pre- or post-fix + * + * @param printf format + * @param printf args */ - void fluff(String format, Object... args) { - if (feedback() != Feedback.Off && feedback() != Feedback.Concise) { - hard(format, args); - } + void rawout(String format, Object... args) { + cmdout.printf(format, args); } /** - * For concise feedback mode only - * @param format printf format - * @param args printf args - */ - void concise(String format, Object... args) { - if (feedback() == Feedback.Concise) { - hard(format, args); - } - } - - /** - * For all feedback modes -- must show + * Must show command output + * * @param format printf format * @param args printf args */ void hard(String format, Object... args) { - cmdout.printf("| " + format + "\n", args); + rawout(feedback.getPre() + format + feedback.getPost(), args); + } + + /** + * Error command output + * + * @param format printf format + * @param args printf args + */ + void error(String format, Object... args) { + rawout(feedback.getErrorPre() + format + feedback.getErrorPost(), args); + } + + /** + * Optional output + * + * @param format printf format + * @param args printf args + */ + void fluff(String format, Object... args) { + if (feedback.shouldDisplayCommandFluff() && interactive()) { + hard(format, args); + } + } + + /** + * Optional output -- with embedded per- and post-fix + * + * @param format printf format + * @param args printf args + */ + void fluffRaw(String format, Object... args) { + if (feedback.shouldDisplayCommandFluff() && interactive()) { + rawout(format, args); + } + } + + void hardPairs(Stream stream, Function a, Function b) { + Map a2b = stream.collect(toMap(a, b, + (m1, m2) -> m1, + () -> new LinkedHashMap<>())); + int aLen = 0; + for (String av : a2b.keySet()) { + aLen = Math.max(aLen, av.length()); + } + String format = " %-" + aLen + "s -- %s"; + String indentedNewLine = LINE_SEP + feedback.getPre() + + String.format(" %-" + (aLen + 4) + "s", ""); + for (Entry e : a2b.entrySet()) { + hard(format, e.getKey(), e.getValue().replaceAll("\n", indentedNewLine)); + } + } + + /** + * User custom feedback mode only + * + * @param fcase Event to report + * @param update Is this an update (rather than primary) + * @param fa Action + * @param fr Resolution status + * @param name Name string + * @param type Type string or null + * @param result Result value or null + * @param unresolved The unresolved symbols + */ + void custom(FormatCase fcase, boolean update, FormatAction fa, FormatResolve fr, + String name, String type, String unresolved, String result) { + String format = feedback.getFormat(fcase, + (update ? FormatWhen.UPDATE : FormatWhen.PRIMARY), fa, fr, + name != null, type != null, result != null); + fluffRaw(format, unresolved, name, type, result); } /** * Trim whitespace off end of string + * * @param s * @return */ @@ -276,8 +415,8 @@ public class JShellTool { } if (regenerateOnDeath) { - fluff("Welcome to JShell -- Version %s", version()); - fluff("Type /help for help"); + hard("Welcome to JShell -- Version %s", version()); + hard("Type /help for help"); } try { @@ -369,14 +508,14 @@ public class JShellTool { } private void printUsage() { - cmdout.printf("Usage: jshell \n"); - cmdout.printf("where possible options include:\n"); - cmdout.printf(" -classpath Specify where to find user class files\n"); - cmdout.printf(" -cp Specify where to find user class files\n"); - cmdout.printf(" -startup One run replacement for the start-up definitions\n"); - cmdout.printf(" -nostartup Do not run the start-up definitions\n"); - cmdout.printf(" -help Print a synopsis of standard options\n"); - cmdout.printf(" -version Version information\n"); + rawout("Usage: jshell \n"); + rawout("where possible options include:\n"); + rawout(" -classpath Specify where to find user class files\n"); + rawout(" -cp Specify where to find user class files\n"); + rawout(" -startup One run replacement for the start-up definitions\n"); + rawout(" -nostartup Do not run the start-up definitions\n"); + rawout(" -help Print a synopsis of standard options\n"); + rawout(" -version Version information\n"); } private void resetState() { @@ -460,10 +599,8 @@ public class JShellTool { ? "\u0005" //ENQ : "\u0006" //ACK : incomplete.isEmpty() - ? feedback() == Feedback.Concise - ? "-> " - : "\n-> " - : ">> " + ? feedback.getPrompt(currentNameSpace.tidNext()) + : feedback.getContinuationPrompt(currentNameSpace.tidNext()) ; } else { prompt = ""; @@ -541,7 +678,7 @@ public class JShellTool { Command[] candidates = findCommand(cmd, c -> c.kind.isRealCommand); if (candidates.length == 0) { if (!rerunHistoryEntryById(cmd.substring(1))) { - hard("No such command or snippet id: %s", cmd); + error("No such command or snippet id: %s", cmd); fluff("Type /help for help."); } } else if (candidates.length == 1) { @@ -552,7 +689,7 @@ public class JShellTool { addToReplayHistory((command.command + " " + arg).trim()); } } else { - hard("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", "))); + error("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", "))); fluff("Type /help for help."); } } @@ -635,45 +772,6 @@ public class JShellTool { } } - class ArgTokenizer extends StreamTokenizer { - - ArgTokenizer(String arg) { - super(new StringReader(arg)); - resetSyntax(); - wordChars(0x00, 0xFF); - quoteChar('"'); - quoteChar('\''); - - whitespaceChars(0x09, 0x0D); - whitespaceChars(0x1C, 0x20); - whitespaceChars(0x85, 0x85); - whitespaceChars(0xA0, 0xA0); - whitespaceChars(0x1680, 0x1680); - whitespaceChars(0x180E, 0x180E); - whitespaceChars(0x2000, 0x200A); - whitespaceChars(0x202F, 0x202F); - whitespaceChars(0x205F, 0x205F); - whitespaceChars(0x3000, 0x3000); - } - - String next() { - try { - nextToken(); - } catch (Throwable t) { - return null; - } - return sval; - } - - String val() { - return sval; - } - - boolean isQuoted() { - return ttype == '\'' || ttype == '"'; - } - } - static final class FixedCompletionProvider implements CompletionProvider { private final String[] alternatives; @@ -801,16 +899,9 @@ public class JShellTool { " -- List the snippet with the specified snippet id\n", arg -> cmdList(arg), editKeywordCompletion())); - registerCommand(new Command("/seteditor", "", "set the external editor command to use", - "Specify the command to launch for the /edit command.\n" + - "The command is an operating system dependent string.\n" + - "The command may include space-separated arguments (such as flags).\n" + - "When /edit is used, temporary file to edit will be appended as the last argument.\n", - arg -> cmdSetEditor(arg), - EMPTY_COMPLETION_PROVIDER)); registerCommand(new Command("/edit", "", "edit a source entry referenced by name or id", "Edit a snippet or snippets of source in an external editor.\n" + - "The editor to use is set with /seteditor.\n" + + "The editor to use is set with /set editor.\n" + "If no editor has been set, a simple editor will be launched.\n\n" + "/edit \n" + " -- Edit the snippet or snippets with the specified name (preference for active snippets)\n" + @@ -875,7 +966,7 @@ public class JShellTool { " * Start-up code is re-executed.\n" + " * The execution state is restarted.\n" + " * The classpath is cleared.\n" + - "Tool settings are maintained: /feedback, /prompt, and /seteditor\n" + + "Tool settings are maintained, as set with: /set ...\n" + "Save any work before using this command\n", arg -> cmdReset(), EMPTY_COMPLETION_PROVIDER)); @@ -895,25 +986,6 @@ public class JShellTool { " -- With the 'quiet' argument the replay is not shown. Errors will display.\n", arg -> cmdReload(arg), reloadCompletion())); - registerCommand(new Command("/feedback", "", "feedback information: off, concise, normal, verbose, default, or ?", - "Set the level of feedback describing the effect of commands and snippets.\n\n" + - "/feedback off\n" + - " -- Give no feedback\n" + - "/feedback concise\n" + - " -- Brief and generally symbolic feedback\n" + - "/feedback normal\n" + - " -- Give a natural language description of the actions\n" + - "/feedback verbose\n" + - " -- Like normal but with side-effects described\n" + - "/feedback default\n" + - " -- Same as normal for user input, off for input from a file\n", - arg -> cmdFeedback(arg), - new FixedCompletionProvider("off", "concise", "normal", "verbose", "default", "?"))); - registerCommand(new Command("/prompt", null, "toggle display of a prompt", - "Toggle between displaying an input prompt and not displaying a prompt.\n" + - "Particularly useful when pasting large amounts of text.\n", - arg -> cmdPrompt(), - EMPTY_COMPLETION_PROVIDER)); registerCommand(new Command("/classpath", "", "add a path to the classpath", "Append a additional path to the classpath.\n", arg -> cmdClasspath(arg), @@ -923,10 +995,6 @@ public class JShellTool { "Display the history of snippet and command input since this jshell was launched.\n", arg -> cmdHistory(), EMPTY_COMPLETION_PROVIDER)); - registerCommand(new Command("/setstart", "", "read file and set as the new start-up definitions", - "The contents of the specified file become the default start-up snippets and commands.\n", - arg -> cmdSetStart(arg), - FILE_COMPLETION_PROVIDER)); registerCommand(new Command("/debug", null, "toggle debugging of the jshell", "Display debugging information for the jshelll implementation.\n" + "0: Debugging off\n" + @@ -951,6 +1019,37 @@ public class JShellTool { " -- Display information about the specified help subject. Example: /help intro\n", arg -> cmdHelp(arg), EMPTY_COMPLETION_PROVIDER)); + registerCommand(new Command("/set", "editor|start|feedback|newmode|prompt|format|field ...", "set jshell configuration information", + "Set jshell configuration information, including:\n" + + "the external editor to use, the start-up definitions to use, a new feedback mode,\n" + + "the command prompt, the feedback mode to use, or the format of output.\n" + + "\n" + + "/set editor ...\n" + + " -- Specify the command to launch for the /edit command.\n" + + " The is an operating system dependent string.\n" + + "\n" + + "/set start \n" + + " -- The contents of the specified become the default start-up snippets and commands.\n" + + "\n" + + "/set feedback \n" + + " -- Set the feedback mode describing displayed feedback for entered snippets and commands.\n" + + "\n" + + "/set newmode [command|quiet []]\n" + + " -- Create a user-defined feedback mode, optionally copying from an existing mode.\n" + + "\n" + + "/set prompt \"\" \"\"\n" + + " -- Set the displayed prompts for a given feedback mode.\n" + + "\n" + + "/set format \"\" ...\n" + + " -- Configure a feedback mode by setting the format to use in a specified set of cases.\n" + + "\n" + + "/set field name|type|result|when|action|resolve|pre|post|errorpre|errorpost \"\" ...\n" + + " -- Set the format of a field within the of a \"/set format\" command\n" + + "\n" + + "To get more information about one of these forms, use /help with the form specified.\n" + + "For example: /help /set format\n", + arg -> cmdSet(arg), + new FixedCompletionProvider("format", "field", "feedback", "prompt", "newmode", "start", "editor"))); registerCommand(new Command("/?", "", "get information about jshell", "Display information about jshell (abbreviation for /help).\n" + "/?\n" + @@ -1051,19 +1150,136 @@ public class JShellTool { // --- Command implementations --- - boolean cmdSetEditor(String arg) { - if (arg.isEmpty()) { - hard("/seteditor requires a path argument"); + private static final String[] setSub = new String[]{ + "format", "field", "feedback", "newmode", "prompt", "editor", "start"}; + + // The /set command. Currently /set format, /set field and /set feedback. + // Other commands will fold here, see: 8148317 + final boolean cmdSet(String arg) { + ArgTokenizer at = new ArgTokenizer(arg.trim()); + String which = setSubCommand(at); + if (which == null) { return false; - } else { - List ed = new ArrayList<>(); - ArgTokenizer at = new ArgTokenizer(arg); - String n; - while ((n = at.next()) != null) ed.add(n); - editor = ed.toArray(new String[ed.size()]); - fluff("Editor set to: %s", arg); - return true; } + switch (which) { + case "format": + return feedback.setFormat(this, at); + case "field": + return feedback.setField(this, at); + case "feedback": + return feedback.setFeedback(this, at); + case "newmode": + return feedback.setNewMode(this, at); + case "prompt": + return feedback.setPrompt(this, at); + case "editor": { + String prog = at.next(); + if (prog == null) { + hard("The '/set editor' command requires a path argument"); + return false; + } else { + List ed = new ArrayList<>(); + ed.add(prog); + String n; + while ((n = at.next()) != null) { + ed.add(n); + } + editor = ed.toArray(new String[ed.size()]); + fluff("Editor set to: %s", arg); + return true; + } + } + case "start": { + String filename = at.next(); + if (filename == null) { + hard("The '/set start' command requires a filename argument."); + } else { + try { + byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename)); + String init = new String(encoded); + PREFS.put(STARTUP_KEY, init); + } catch (AccessDeniedException e) { + hard("File '%s' for /set start is not accessible.", filename); + return false; + } catch (NoSuchFileException e) { + hard("File '%s' for /set start is not found.", filename); + return false; + } catch (Exception e) { + hard("Exception while reading start set file: %s", e); + return false; + } + } + return true; + } + default: + hard("Error: Invalid /set argument: %s", which); + return false; + } + } + + boolean printSetHelp(ArgTokenizer at) { + String which = setSubCommand(at); + if (which == null) { + return false; + } + switch (which) { + case "format": + feedback.printFormatHelp(this); + return true; + case "field": + feedback.printFieldHelp(this); + return true; + case "feedback": + feedback.printFeedbackHelp(this); + return true; + case "newmode": + feedback.printNewModeHelp(this); + return true; + case "prompt": + feedback.printPromptHelp(this); + return true; + case "editor": + hard("Specify the command to launch for the /edit command."); + hard(""); + hard("/set editor ..."); + hard(""); + hard("The is an operating system dependent string."); + hard("The may include space-separated arguments (such as flags) -- ...."); + hard("When /edit is used, the temporary file to edit will be appended as the last argument."); + return true; + case "start": + hard("Set the start-up configuration -- a sequence of snippets and commands read at start-up."); + hard(""); + hard("/set start "); + hard(""); + hard("The contents of the specified become the default start-up snippets and commands --"); + hard("which are run when the jshell tool is started or reset."); + return true; + default: + hard("Error: Invalid /set argument: %s", which); + return false; + } + } + + String setSubCommand(ArgTokenizer at) { + String[] matches = at.next(setSub); + if (matches == null) { + error("The /set command requires arguments. See: /help /set"); + return null; + } else if (matches.length == 0) { + error("Not a valid argument to /set: %s", at.val()); + fluff("/set is followed by one of: %s", Arrays.stream(setSub) + .collect(Collectors.joining(", ")) + ); + return null; + } else if (matches.length > 1) { + error("Ambiguous argument to /set: %s", at.val()); + fluff("Use one of: %s", Arrays.stream(matches) + .collect(Collectors.joining(", ")) + ); + return null; + } + return matches[0]; } boolean cmdClasspath(String arg) { @@ -1137,91 +1353,50 @@ public class JShellTool { return true; } - private boolean cmdFeedback(String arg) { - switch (arg) { - case "": - case "d": - case "default": - feedback = Feedback.Default; - break; - case "o": - case "off": - feedback = Feedback.Off; - break; - case "c": - case "concise": - feedback = Feedback.Concise; - break; - case "n": - case "normal": - feedback = Feedback.Normal; - break; - case "v": - case "verbose": - feedback = Feedback.Verbose; - break; - default: - hard("Follow /feedback with of the following:"); - hard(" off (errors and critical output only)"); - hard(" concise"); - hard(" normal"); - hard(" verbose"); - hard(" default"); - hard("You may also use just the first letter, for example: /f c"); - hard("In interactive mode 'default' is the same as 'normal', from a file it is the same as 'off'"); - return false; - } - fluff("Feedback mode: %s", feedback.name().toLowerCase()); - return true; - } - boolean cmdHelp(String arg) { - if (!arg.isEmpty()) { - StringBuilder sb = new StringBuilder(); - commands.values().stream() - .filter(c -> c.command.startsWith(arg)) - .forEach(c -> { - sb.append("\n"); - sb.append(c.command); - sb.append("\n\n"); - sb.append(c.help); - sb.append("\n"); - }); - if (sb.length() > 0) { - cmdout.print(sb); - return true; + ArgTokenizer at = new ArgTokenizer(arg); + String subject = at.next(); + if (subject != null) { + Command[] matches = commands.values().stream() + .filter(c -> c.command.startsWith(subject)) + .toArray(size -> new Command[size]); + at.mark(); + String sub = at.next(); + if (sub != null && matches.length == 1 && matches[0].command.equals("/set")) { + at.rewind(); + return printSetHelp(at); + } + if (matches.length > 0) { + for (Command c : matches) { + hard(""); + hard("%s", c.command); + hard(""); + hard("%s", c.help.replaceAll("\n", LINE_SEP + feedback.getPre())); + } + return true; + } else { + error("No commands or subjects start with the provided argument: %s\n\n", arg); } - cmdout.printf("No commands or subjects start with the provided argument: %s\n\n", arg); } - int synopsisLen = 0; - Map synopsis2Description = new LinkedHashMap<>(); - for (Command cmd : new LinkedHashSet<>(commands.values())) { - if (!cmd.kind.showInHelp) - continue; - StringBuilder synopsis = new StringBuilder(); - synopsis.append(cmd.command); - if (cmd.params != null) - synopsis.append(" ").append(cmd.params); - synopsis2Description.put(synopsis.toString(), cmd.description); - synopsisLen = Math.max(synopsisLen, synopsis.length()); - } - cmdout.println("Type a Java language expression, statement, or declaration."); - cmdout.println("Or type one of the following commands:\n"); - for (Entry e : synopsis2Description.entrySet()) { - cmdout.print(String.format("%-" + synopsisLen + "s", e.getKey())); - cmdout.print(" -- "); - String indentedNewLine = System.getProperty("line.separator") + - String.format("%-" + (synopsisLen + 4) + "s", ""); - cmdout.println(e.getValue().replace("\n", indentedNewLine)); - } - cmdout.println(); - cmdout.println("For more information type '/help' followed by the name of command or a subject."); - cmdout.println("For example '/help /list' or '/help intro'. Subjects:\n"); - commands.values().stream() - .filter(c -> c.kind == CommandKind.HELP_SUBJECT) - .forEach(c -> { - cmdout.printf("%-12s -- %s\n", c.command, c.description); - }); + hard("Type a Java language expression, statement, or declaration."); + hard("Or type one of the following commands:"); + hard(""); + hardPairs(commands.values().stream() + .filter(cmd -> cmd.kind.showInHelp), + cmd -> (cmd.params != null) + ? cmd.command + " " + cmd.params + : cmd.command, + cmd -> cmd.description + ); + hard(""); + hard("For more information type '/help' followed by the name of command or a subject."); + hard("For example '/help /list' or '/help intro'. Subjects:"); + hard(""); + hardPairs(commands.values().stream() + .filter(cmd -> cmd.kind == CommandKind.HELP_SUBJECT), + cmd -> cmd.command, + cmd -> cmd.description + ); return true; } @@ -1482,13 +1657,6 @@ public class JShellTool { return true; } - private boolean cmdPrompt() { - displayPrompt = !displayPrompt; - fluff("Prompt will %sdisplay. Use /prompt to toggle.", displayPrompt ? "" : "NOT "); - concise("Prompt: %s", displayPrompt ? "on" : "off"); - return true; - } - private boolean cmdReset() { live = false; fluff("Resetting state."); @@ -1577,28 +1745,6 @@ public class JShellTool { return true; } - private boolean cmdSetStart(String filename) { - if (filename.isEmpty()) { - hard("The /setstart command requires a filename argument."); - } else { - try { - byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename)); - String init = new String(encoded); - PREFS.put(STARTUP_KEY, init); - } catch (AccessDeniedException e) { - hard("File '%s' for /setstart is not accessible.", filename); - return false; - } catch (NoSuchFileException e) { - hard("File '%s' for /setstart is not found.", filename); - return false; - } catch (Exception e) { - hard("Exception while reading start set file: %s", e); - return false; - } - } - return true; - } - private boolean cmdVars() { for (VarSnippet vk : state.variables()) { String val = state.status(vk) == Status.VALID @@ -1831,14 +1977,10 @@ public class JShellTool { printDiagnostics(source, diagnostics, true); } else { // Update - SubKind subkind = sn.subKind(); - if (sn instanceof DeclarationSnippet - && (feedback() == Feedback.Verbose - || ste.status() == Status.OVERWRITTEN - || subkind == SubKind.VAR_DECLARATION_SUBKIND - || subkind == SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND)) { - // Under the conditions, display update information - displayDeclarationAndValue(ste, true, null); + if (sn instanceof DeclarationSnippet) { + // display update information + displayDeclarationAndValue(ste, true, ste.value()); + List other = errorsOnly(diagnostics); if (other.size() > 0) { printDiagnostics(source, other, true); @@ -1851,118 +1993,117 @@ public class JShellTool { @SuppressWarnings("fallthrough") private void displayDeclarationAndValue(SnippetEvent ste, boolean update, String value) { Snippet key = ste.snippet(); - String declared; + FormatAction action; Status status = ste.status(); switch (status) { case VALID: case RECOVERABLE_DEFINED: case RECOVERABLE_NOT_DEFINED: if (ste.previousStatus().isActive) { - declared = ste.isSignatureChange() - ? "Replaced" - : "Modified"; + action = ste.isSignatureChange() + ? FormatAction.REPLACED + : FormatAction.MODIFIED; } else { - declared = "Added"; + action = FormatAction.ADDED; } break; case OVERWRITTEN: - declared = "Overwrote"; + action = FormatAction.OVERWROTE; break; case DROPPED: - declared = "Dropped"; + action = FormatAction.DROPPED; break; case REJECTED: - declared = "Rejected"; + action = FormatAction.REJECTED; break; case NONEXISTENT: default: // Should not occur - declared = ste.previousStatus().toString() + "=>" + status.toString(); + error("Unexpected status: " + ste.previousStatus().toString() + "=>" + status.toString()); + return; } - if (update) { - declared = " Update " + declared.toLowerCase(); - } - String however; + FormatResolve resolution; + String unresolved; if (key instanceof DeclarationSnippet && (status == Status.RECOVERABLE_DEFINED || status == Status.RECOVERABLE_NOT_DEFINED)) { - String cannotUntil = (status == Status.RECOVERABLE_NOT_DEFINED) - ? " cannot be referenced until" - : " cannot be invoked until"; - however = (update? " which" : ", however, it") + cannotUntil + unresolved((DeclarationSnippet) key); + resolution = (status == Status.RECOVERABLE_NOT_DEFINED) + ? FormatResolve.NOTDEFINED + : FormatResolve.DEFINED; + unresolved = unresolved((DeclarationSnippet) key); } else { - however = ""; + resolution = FormatResolve.OK; + unresolved = ""; } switch (key.subKind()) { case CLASS_SUBKIND: - fluff("%s class %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.CLASS, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case INTERFACE_SUBKIND: - fluff("%s interface %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.INTERFACE, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case ENUM_SUBKIND: - fluff("%s enum %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.ENUM, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case ANNOTATION_TYPE_SUBKIND: - fluff("%s annotation interface %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.ANNOTATION, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case METHOD_SUBKIND: - fluff("%s method %s(%s)%s", declared, ((MethodSnippet) key).name(), - ((MethodSnippet) key).parameterTypes(), however); + custom(FormatCase.METHOD, update, action, resolution, + ((MethodSnippet) key).name(), ((MethodSnippet) key).parameterTypes(), unresolved, null); break; case VAR_DECLARATION_SUBKIND: - if (!update) { - VarSnippet vk = (VarSnippet) key; - if (status == Status.RECOVERABLE_NOT_DEFINED) { - fluff("%s variable %s%s", declared, vk.name(), however); - } else { - fluff("%s variable %s of type %s%s", declared, vk.name(), vk.typeName(), however); - } - break; - } - // Fall through case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND: { VarSnippet vk = (VarSnippet) key; if (status == Status.RECOVERABLE_NOT_DEFINED) { - if (!update) { - fluff("%s variable %s%s", declared, vk.name(), however); - break; - } - } else if (update) { - if (ste.isSignatureChange()) { - hard("%s variable %s, reset to null", declared, vk.name()); - } + custom(FormatCase.VARDECLRECOVERABLE, update, action, resolution, + vk.name(), null, unresolved, null); + } else if (update && ste.isSignatureChange()) { + custom(FormatCase.VARRESET, update, action, resolution, + vk.name(), null, unresolved, value); + } else if (key.subKind() == SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND) { + custom(FormatCase.VARINIT, update, action, resolution, + vk.name(), vk.typeName(), unresolved, value); } else { - fluff("%s variable %s of type %s with initial value %s", - declared, vk.name(), vk.typeName(), value); - concise("%s : %s", vk.name(), value); + custom(FormatCase.VARDECL, update, action, resolution, + vk.name(), vk.typeName(), unresolved, value); } break; } case TEMP_VAR_EXPRESSION_SUBKIND: { VarSnippet vk = (VarSnippet) key; - if (update) { - hard("%s temporary variable %s, reset to null", declared, vk.name()); - } else { - fluff("Expression value is: %s", (value)); - fluff(" assigned to temporary variable %s of type %s", vk.name(), vk.typeName()); - concise("%s : %s", vk.name(), value); - } + custom(FormatCase.EXPRESSION, update, action, resolution, + vk.name(), vk.typeName(), null, value); break; } case OTHER_EXPRESSION_SUBKIND: - fluff("Expression value is: %s", (value)); + error("Unexpected expression form -- value is: %s", (value)); break; case VAR_VALUE_SUBKIND: { ExpressionSnippet ek = (ExpressionSnippet) key; - fluff("Variable %s of type %s has value %s", ek.name(), ek.typeName(), (value)); - concise("%s : %s", ek.name(), value); + custom(FormatCase.VARVALUE, update, action, resolution, + ek.name(), ek.typeName(), null, value); break; } case ASSIGNMENT_SUBKIND: { ExpressionSnippet ek = (ExpressionSnippet) key; - fluff("Variable %s has been assigned the value %s", ek.name(), (value)); - concise("%s : %s", ek.name(), value); + custom(FormatCase.ASSIGNMENT, update, action, resolution, + ek.name(), ek.typeName(), null, value); break; } + case SINGLE_TYPE_IMPORT_SUBKIND: + case TYPE_IMPORT_ON_DEMAND_SUBKIND: + case SINGLE_STATIC_IMPORT_SUBKIND: + case STATIC_IMPORT_ON_DEMAND_SUBKIND: + custom(FormatCase.IMPORT, update, action, resolution, + ((ImportSnippet) key).name(), null, null, null); + break; + case STATEMENT_SUBKIND: + custom(FormatCase.STATEMENT, update, action, resolution, + null, null, null, null); + break; } } //where @@ -2048,34 +2189,9 @@ public class JShellTool { sb.append(", "); } } - switch (unr.size()) { - case 0: - break; - case 1: - sb.append(" is declared"); - break; - default: - sb.append(" are declared"); - break; - } return sb.toString(); } - enum Feedback { - Default, - Off, - Concise, - Normal, - Verbose - } - - Feedback feedback() { - if (feedback == Feedback.Default) { - return input == null || input.interactiveOutput() ? Feedback.Normal : Feedback.Off; - } - return feedback; - } - /** The current version number as a string. */ static String version() { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java index 462d61e87de..2ae696a026f 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -231,7 +231,7 @@ class CompletenessAnalyzer { // Declarations and type parameters (thus expressions) EXTENDS(TokenKind.EXTENDS, XEXPR|XDECL), // extends - COMMA(TokenKind.COMMA, XEXPR|XDECL|XSTART), // , + COMMA(TokenKind.COMMA, XEXPR|XDECL), // , AMP(TokenKind.AMP, XEXPR|XDECL), // & GT(TokenKind.GT, XEXPR|XDECL), // > LT(TokenKind.LT, XEXPR|XDECL1), // < diff --git a/langtools/test/jdk/jshell/CommandCompletionTest.java b/langtools/test/jdk/jshell/CommandCompletionTest.java index 1ca831f0c13..07f7fc3e397 100644 --- a/langtools/test/jdk/jshell/CommandCompletionTest.java +++ b/langtools/test/jdk/jshell/CommandCompletionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -50,13 +50,9 @@ import org.testng.annotations.Test; public class CommandCompletionTest extends ReplToolTesting { public void testCommand() { - assertCompletion("/f|", false, "/feedback "); assertCompletion("/deb|", false); - assertCompletion("/feedback v|", false, "verbose"); assertCompletion("/c|", false, "/classes ", "/classpath "); assertCompletion("/h|", false, "/help ", "/history "); - assertCompletion("/feedback |", false, - "?", "concise", "default", "normal", "off", "verbose"); } public void testList() { @@ -108,7 +104,7 @@ public class CommandCompletionTest extends ReplToolTesting { public void testSave() throws IOException { Compiler compiler = new Compiler(); - assertCompletion("/s|", false, "/save ", "/seteditor ", "/setstart "); + assertCompletion("/s|", false, "/save ", "/set "); List p1 = listFiles(Paths.get("")); Collections.addAll(p1, "all ", "history ", "start "); FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString())); diff --git a/langtools/test/jdk/jshell/CompletenessTest.java b/langtools/test/jdk/jshell/CompletenessTest.java index 893baeee6ed..bbf10d2b28b 100644 --- a/langtools/test/jdk/jshell/CompletenessTest.java +++ b/langtools/test/jdk/jshell/CompletenessTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ /* * @test + * @bug 8149524 * @summary Test SourceCodeAnalysis * @build KullaTesting TestingInputStream * @run testng CompletenessTest @@ -60,6 +61,7 @@ public class CompletenessTest extends KullaTesting { "try { } finally { }", "try (java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName)) { }", "foo: while (true) { printf(\"Innn\"); break foo; }", + "class Case, E2 extends Enum, E3 extends Enum> {}", ";", }; diff --git a/langtools/test/jdk/jshell/ExternalEditorTest.java b/langtools/test/jdk/jshell/ExternalEditorTest.java index b337c3d6d27..a794c7e57af 100644 --- a/langtools/test/jdk/jshell/ExternalEditorTest.java +++ b/langtools/test/jdk/jshell/ExternalEditorTest.java @@ -113,7 +113,7 @@ public class ExternalEditorTest extends EditorTestBase { @Override public void testEditor(boolean defaultStartup, String[] args, ReplTest... tests) { ReplTest[] t = new ReplTest[tests.length + 1]; - t[0] = a -> assertCommandCheckOutput(a, "/seteditor " + executionScript, + t[0] = a -> assertCommandCheckOutput(a, "/set editor " + executionScript, assertStartsWith("| Editor set to: " + executionScript)); System.arraycopy(tests, 0, t, 1, tests.length); super.testEditor(defaultStartup, args, t); @@ -193,8 +193,8 @@ public class ExternalEditorTest extends EditorTestBase { @Test public void setUnknownEditor() { test( - a -> assertCommand(a, "/seteditor", "| /seteditor requires a path argument\n"), - a -> assertCommand(a, "/seteditor UNKNOWN", "| Editor set to: UNKNOWN\n"), + a -> assertCommand(a, "/set editor", "| /set editor requires a path argument\n"), + a -> assertCommand(a, "/set editor UNKNOWN", "| Editor set to: UNKNOWN\n"), a -> assertCommand(a, "int a;", null), a -> assertCommand(a, "/e 1", "| Edit Error: process IO failure: Cannot run program \"UNKNOWN\": error=2, No such file or directory\n") @@ -204,7 +204,7 @@ public class ExternalEditorTest extends EditorTestBase { @Test(enabled = false) public void testRemoveTempFile() { test(new String[]{"-nostartup"}, - a -> assertCommandCheckOutput(a, "/seteditor " + executionScript, + a -> assertCommandCheckOutput(a, "/set editor " + executionScript, assertStartsWith("| Editor set to: " + executionScript)), a -> assertVariable(a, "int", "a", "0", "0"), a -> assertEditOutput(a, "/e 1", assertStartsWith("| Edit Error: Failure read edit file:"), () -> { diff --git a/langtools/test/jdk/jshell/ReplToolTesting.java b/langtools/test/jdk/jshell/ReplToolTesting.java index 05dd5389e0b..d4f697d3613 100644 --- a/langtools/test/jdk/jshell/ReplToolTesting.java +++ b/langtools/test/jdk/jshell/ReplToolTesting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -397,6 +397,15 @@ public class ReplToolTesting { assertCommand(after, cmd, out, "", null, "", ""); } + public void assertCommandOutputContains(boolean after, String cmd, String has) { + assertCommandCheckOutput(after, cmd, (s) -> + assertTrue(s.contains(has), "Output: \'" + s + "' does not contain: " + has)); + } + + public void assertCommandOutputStartsWith(boolean after, String cmd, String starts) { + assertCommandCheckOutput(after, cmd, assertStartsWith(starts)); + } + public void assertCommandCheckOutput(boolean after, String cmd, Consumer check) { if (!after) { assertCommand(false, cmd, null); @@ -437,13 +446,13 @@ public class ReplToolTesting { } private List computeCompletions(String code, boolean isSmart) { - JShellTool repl = this.repl != null ? this.repl + JShellTool js = this.repl != null ? this.repl : new JShellTool(null, null, null, null, null, null, null); int cursor = code.indexOf('|'); code = code.replace("|", ""); assertTrue(cursor > -1, "'|' not found: " + code); List completions = - repl.commandCompletionSuggestions(code, cursor, new int[1]); //XXX: ignoring anchor for now + js.commandCompletionSuggestions(code, cursor, new int[1]); //XXX: ignoring anchor for now return completions.stream() .filter(s -> isSmart == s.isSmart) .map(s -> s.continuation) @@ -481,6 +490,15 @@ public class ReplToolTesting { return name.hashCode(); } + @Override + public boolean equals(Object o) { + if (o instanceof MemberInfo) { + MemberInfo mi = (MemberInfo) o; + return name.equals(mi.name); + } + return false; + } + public abstract Consumer checkOutput(); public String getSource() { @@ -536,6 +554,11 @@ public class ReplToolTesting { "Output: " + output + " does not fit pattern: " + finalPattern); } + @Override + public int hashCode() { + return name.hashCode(); + } + @Override public boolean equals(Object o) { if (o instanceof VariableInfo) { @@ -585,6 +608,10 @@ public class ReplToolTesting { return s -> assertTrue(checkOutput.test(s), "Expected: '" + expectedOutput + "', actual: " + s); } + @Override + public int hashCode() { + return (name.hashCode() << 2) ^ type.hashCode() ; + } @Override public boolean equals(Object o) { @@ -615,6 +642,11 @@ public class ReplToolTesting { return s -> assertTrue(checkOutput.test(s), "Expected: '" + expectedOutput + "', actual: " + s); } + @Override + public int hashCode() { + return name.hashCode() ; + } + @Override public boolean equals(Object o) { if (o instanceof ClassInfo) { @@ -640,6 +672,11 @@ public class ReplToolTesting { return s -> assertTrue("".equals(s), "Expected: '', actual: " + s); } + @Override + public int hashCode() { + return (name.hashCode() << 2) ^ type.hashCode() ; + } + @Override public boolean equals(Object o) { if (o instanceof ImportInfo) { diff --git a/langtools/test/jdk/jshell/ToolBasicTest.java b/langtools/test/jdk/jshell/ToolBasicTest.java index f4501c84d32..e38ff644e77 100644 --- a/langtools/test/jdk/jshell/ToolBasicTest.java +++ b/langtools/test/jdk/jshell/ToolBasicTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 + * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 * @requires os.family != "solaris" * @summary Tests for Basic tests for REPL tool * @library /tools/lib @@ -90,8 +90,7 @@ public class ToolBasicTest extends ReplToolTesting { public void elideStartUpFromList() { test( - (a) -> assertCommandCheckOutput(a, "123", (s) -> - assertTrue(s.contains("type int"), s)), + (a) -> assertCommandOutputContains(a, "123", "type int"), (a) -> assertCommandCheckOutput(a, "/list", (s) -> { int cnt; try (Scanner scanner = new Scanner(s)) { @@ -112,8 +111,7 @@ public class ToolBasicTest extends ReplToolTesting { Compiler compiler = new Compiler(); Path path = compiler.getPath("myfile"); test( - (a) -> assertCommandCheckOutput(a, "123", - (s) -> assertTrue(s.contains("type int"), s)), + (a) -> assertCommandOutputContains(a, "123", "type int"), (a) -> assertCommand(a, "/save " + path.toString(), "") ); try (Stream lines = Files.lines(path)) { @@ -594,12 +592,12 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertMethod(a, "void f() {}", "()V", "f"), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertCommand(a, "/save " + startUpFile.toString(), null), - (a) -> assertCommand(a, "/setstart " + startUpFile.toString(), null) + (a) -> assertCommand(a, "/set start " + startUpFile.toString(), null) ); Path unknown = compiler.getPath("UNKNOWN"); test( - (a) -> assertCommand(a, "/setstart " + unknown.toString(), - "| File '" + unknown + "' for /setstart is not found.\n") + (a) -> assertCommand(a, "/set start " + unknown.toString(), + "| File '" + unknown + "' for /set start is not found.\n") ); test(false, new String[0], (a) -> { @@ -619,7 +617,7 @@ public class ToolBasicTest extends ReplToolTesting { } private void removeStartup() { - Preferences preferences = Preferences.userRoot().node("tool/REPL"); + Preferences preferences = Preferences.userRoot().node("tool/JShell"); if (preferences != null) { preferences.remove("STARTUP"); } @@ -636,7 +634,7 @@ public class ToolBasicTest extends ReplToolTesting { } public void testNoArgument() { - String[] commands = {"/save", "/open", "/setstart"}; + String[] commands = {"/save", "/open", "/set start"}; test(Stream.of(commands) .map(cmd -> { String c = cmd; @@ -670,8 +668,7 @@ public class ToolBasicTest extends ReplToolTesting { test( a -> assertVariable(a, "int", "x"), a -> assertCommandCheckOutput(a, "/vars", assertVariables()), - a -> assertCommandCheckOutput(a, "System.exit(5);", s -> - assertTrue(s.contains("terminated"), s)), + a -> assertCommandOutputContains(a, "System.exit(5);", "terminated"), a -> assertCommandCheckOutput(a, "/vars", s -> assertTrue(s.trim().isEmpty(), s)), a -> assertMethod(a, "void f() { }", "()void", "f"), @@ -699,8 +696,7 @@ public class ToolBasicTest extends ReplToolTesting { s -> assertEquals(s, "| No definition or id named " + arg + " found. There are no active definitions.\n")), a -> assertVariable(a, "int", "aardvark"), - a -> assertCommandCheckOutput(a, "/list aardvark", - s -> assertTrue(s.contains("aardvark"))), + a -> assertCommandOutputContains(a, "/list aardvark", "aardvark"), a -> assertCommandCheckOutput(a, "/list start", s -> checkLineToList(s, START_UP)), a -> assertCommandCheckOutput(a, "/list all", @@ -714,14 +710,14 @@ public class ToolBasicTest extends ReplToolTesting { } public void testFeedbackNegative() { - test(a -> assertCommandCheckOutput(a, "/feedback aaaa", - assertStartsWith("| Follow /feedback with of the following"))); + test(a -> assertCommandCheckOutput(a, "/set feedback aaaa", + assertStartsWith("| Does not match any current feedback mode"))); } public void testFeedbackOff() { for (String off : new String[]{"o", "off"}) { test( - a -> assertCommand(a, "/feedback " + off, ""), + a -> assertCommand(a, "/set feedback " + off, ""), a -> assertCommand(a, "int a", ""), a -> assertCommand(a, "void f() {}", ""), a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("| Error:")), @@ -730,23 +726,6 @@ public class ToolBasicTest extends ReplToolTesting { } } - public void testFeedbackConcise() { - Compiler compiler = new Compiler(); - Path testConciseFile = compiler.getPath("testConciseFeedback"); - String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"}; - compiler.writeToFile(testConciseFile, sources); - for (String concise : new String[]{"c", "concise"}) { - test( - a -> assertCommand(a, "/feedback " + concise, ""), - a -> assertCommand(a, sources[0], ""), - a -> assertCommand(a, sources[1], ""), - a -> assertCommand(a, sources[2], ""), - a -> assertCommand(a, sources[3], "| a : 10\n"), - a -> assertCommand(a, "/o " + testConciseFile.toString(), "| a : 10\n") - ); - } - } - public void testFeedbackNormal() { Compiler compiler = new Compiler(); Path testNormalFile = compiler.getPath("testConciseNormal"); @@ -759,58 +738,20 @@ public class ToolBasicTest extends ReplToolTesting { "| Variable a has been assigned the value 10\n" }; compiler.writeToFile(testNormalFile, sources2); - for (String feedback : new String[]{"/f", "/feedback"}) { - for (String feedbackState : new String[]{"n", "normal", "v", "verbose"}) { - String f = null; - if (feedbackState.startsWith("n")) { - f = "normal"; - } else if (feedbackState.startsWith("v")) { - f = "verbose"; - } - final String finalF = f; + for (String feedback : new String[]{"/set f", "/set feedback"}) { + for (String feedbackState : new String[]{"n", "normal", "o", "off"}) { test( - a -> assertCommand(a, feedback + " " + feedbackState, "| Feedback mode: " + finalF +"\n"), + a -> assertCommand(a, feedback + " " + feedbackState, "| Feedback mode: normal\n"), a -> assertCommand(a, sources[0], output[0]), a -> assertCommand(a, sources[1], output[1]), a -> assertCommand(a, sources[2], output[2]), a -> assertCommand(a, sources[3], output[3]), - a -> assertCommand(a, "/o " + testNormalFile.toString(), - "| Modified variable a of type int\n" + - "| Modified method f()\n" + - "| Update overwrote method f()\n" + - "| Modified class A\n" + - "| Update overwrote class A\n" + - "| Variable a has been assigned the value 10\n") + a -> assertCommand(a, "/o " + testNormalFile.toString(), "") ); } } } - public void testFeedbackDefault() { - Compiler compiler = new Compiler(); - Path testDefaultFile = compiler.getPath("testDefaultFeedback"); - String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"}; - String[] output = new String[] { - "| Added variable a of type int\n", - "| Added method f()\n", - "| Added class A\n", - "| Variable a has been assigned the value 10\n" - }; - compiler.writeToFile(testDefaultFile, sources); - for (String defaultFeedback : new String[]{"", "d", "default"}) { - test( - a -> assertCommand(a, "/feedback o", ""), - a -> assertCommand(a, "int x", ""), - a -> assertCommand(a, "/feedback " + defaultFeedback, "| Feedback mode: default\n"), - a -> assertCommand(a, sources[0], output[0]), - a -> assertCommand(a, sources[1], output[1]), - a -> assertCommand(a, sources[2], output[2]), - a -> assertCommand(a, sources[3], output[3]), - a -> assertCommand(a, "/o " + testDefaultFile.toString(), "") - ); - } - } - public void testDrop() { test(false, new String[]{"-nostartup"}, a -> assertVariable(a, "int", "a"), @@ -906,7 +847,7 @@ public class ToolBasicTest extends ReplToolTesting { public void testCommandPrefix() { test(a -> assertCommandCheckOutput(a, "/s", - assertStartsWith("| Command: /s is ambiguous: /seteditor, /save, /setstart")), + assertStartsWith("| Command: /s is ambiguous: /save, /set")), a -> assertCommand(a, "int var", "| Added variable var of type int\n"), a -> assertCommandCheckOutput(a, "/va", assertStartsWith("| int var = 0")), diff --git a/langtools/test/jdk/jshell/ToolFormatTest.java b/langtools/test/jdk/jshell/ToolFormatTest.java new file mode 100644 index 00000000000..cc3aa0273af --- /dev/null +++ b/langtools/test/jdk/jshell/ToolFormatTest.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2016, 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 8148316 8148317 + * @summary Tests for output customization + * @library /tools/lib + * @build KullaTesting TestingInputStream ToolBox Compiler + * @run testng ToolFormatTest + */ +import org.testng.annotations.Test; + +@Test +public class ToolFormatTest extends ReplToolTesting { + + public void testSetFormat() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode test command", "| Created new feedback mode: test"), + (a) -> assertCommand(a, "/set field test pre '$ '", ""), + (a) -> assertCommand(a, "/set field test post ''", ""), + (a) -> assertCommand(a, "/set field test action 'ADD ' added-primary", ""), + (a) -> assertCommand(a, "/set field test action 'MOD ' modified-primary", ""), + (a) -> assertCommand(a, "/set field test action 'REP ' replaced-primary", ""), + (a) -> assertCommand(a, "/set field test action 'UP-ADD ' added-update", ""), + (a) -> assertCommand(a, "/set field test action 'UP-MOD ' modified-update", ""), + (a) -> assertCommand(a, "/set field test action 'UP-REP ' replaced-update", ""), + (a) -> assertCommand(a, "/set field test resolve 'OK' ok-*", ""), + (a) -> assertCommand(a, "/set field test resolve 'DEF' defined-*", ""), + (a) -> assertCommand(a, "/set field test resolve 'NODEF' notdefined-*", ""), + (a) -> assertCommand(a, "/set field test name ':%s ' ", ""), + (a) -> assertCommand(a, "/set field test type '[%s]' ", ""), + (a) -> assertCommand(a, "/set field test result '=%s ' ", ""), + (a) -> assertCommand(a, "/set format test '{pre}{action}{type}{name}{result}{resolve}' *-*-*", ""), + (a) -> assertCommand(a, "/set format test '{pre}HI this is enum' enum", ""), + (a) -> assertCommand(a, "/set feedback test", "$ Feedback mode: test"), + (a) -> assertCommand(a, "class D {}", "$ ADD :D OK"), + (a) -> assertCommand(a, "void m() {}", "$ ADD []:m OK"), + (a) -> assertCommand(a, "interface EX extends EEX {}", "$ ADD :EX NODEF"), + (a) -> assertCommand(a, "56", "$ ADD [int]:$4 =56 OK"), + (a) -> assertCommand(a, "class D { int hh; }", "$ REP :D OK$ OVERWROTE-UPDATE:D OK"), + (a) -> assertCommandOutputStartsWith(a, "/set feedback normal", "| Feedback mode: normal") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testNewModeQuiet() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode nmq quiet normal", "| Created new feedback mode: nmq"), + (a) -> assertCommand(a, "/set feedback nmq", ""), + (a) -> assertCommand(a, "/se ne nmq2 q nor", ""), + (a) -> assertCommand(a, "/se fee nmq2", ""), + (a) -> assertCommand(a, "/set newmode nmc command normal", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback nmc", "| Feedback mode: nmc"), + (a) -> assertCommandOutputStartsWith(a, "/set newmode nm", "| Created new feedback mode: nm"), + (a) -> assertCommandOutputStartsWith(a, "/set feedback nm", "| Feedback mode: nm") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testSetError() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal", "| Created new feedback mode: te"), + (a) -> assertCommand(a, "/set field te errorpre 'ERROR: '", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback te", ""), + (a) -> assertCommandCheckOutput(a, "/set ", assertStartsWith("ERROR: The /set command requires arguments")), + (a) -> assertCommandCheckOutput(a, "/set xyz", assertStartsWith("ERROR: Not a valid argument to /set")), + (a) -> assertCommandCheckOutput(a, "/set f", assertStartsWith("ERROR: Ambiguous argument to /set")), + (a) -> assertCommandCheckOutput(a, "/set feedback", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set feedback xyz", assertStartsWith("ERROR: Does not match any current feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set format", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set format xyz", assertStartsWith("ERROR: Does not match any current feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set format te", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set format te aaa", assertStartsWith("ERROR: Format 'aaa' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set format te 'aaa'", assertStartsWith("ERROR: At least one selector required")), + (a) -> assertCommandCheckOutput(a, "/set format te 'aaa' frog", assertStartsWith("ERROR: Not a valid case")), + (a) -> assertCommandCheckOutput(a, "/set format te 'aaa' import-frog", assertStartsWith("ERROR: Not a valid action")), + (a) -> assertCommandCheckOutput(a, "/set newmode", assertStartsWith("ERROR: Expected new feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set newmode te", assertStartsWith("ERROR: Expected a new feedback mode name")), + (a) -> assertCommandCheckOutput(a, "/set newmode x xyz", assertStartsWith("ERROR: Specify either 'command' or 'quiet'")), + (a) -> assertCommandCheckOutput(a, "/set newmode x quiet y", assertStartsWith("ERROR: Does not match any current feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set prompt", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set prompt te", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set prompt te aaa xyz", assertStartsWith("ERROR: Format 'aaa' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set prompt te 'aaa' xyz", assertStartsWith("ERROR: Format 'xyz' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set prompt", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set prompt te", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set prompt te aaa", assertStartsWith("ERROR: Format 'aaa' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set prompt te 'aaa'", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set field", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set field xyz", assertStartsWith("ERROR: Does not match any current feedback mode: xyz")), + (a) -> assertCommandCheckOutput(a, "/set field te xyz", assertStartsWith("ERROR: Not a valid field: xyz, must be one of: when")), + (a) -> assertCommandCheckOutput(a, "/set field te action", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set field te action 'act'", assertStartsWith("ERROR: At least one selector required")) + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testSetHelp() { + try { + test( + (a) -> assertCommandOutputContains(a, "/help /set", "command to launch"), + (a) -> assertCommandOutputContains(a, "/help /set format", "vardecl"), + (a) -> assertCommandOutputContains(a, "/hel /se for", "vardecl"), + (a) -> assertCommandOutputContains(a, "/help /set editor", "temporary file") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testSetHelpError() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal", "| Created new feedback mode: te"), + (a) -> assertCommand(a, "/set field te errorpre 'ERROR: '", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback te", "| Feedback mode: te"), + (a) -> assertCommandOutputContains(a, "/help /set xyz", "ERROR: Not a valid argument to /set: xyz"), + (a) -> assertCommandOutputContains(a, "/help /set f", "ERROR: Ambiguous argument to /set: f") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } +} From a0224437fcc150c04c75de8ca162d91324e3296d Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 9 Mar 2016 12:52:14 +0300 Subject: [PATCH 106/311] 8151223: String concatenation fails with implicit toString() on package-private class Reviewed-by: mcimadamore, forax --- .../com/sun/tools/javac/jvm/StringConcat.java | 26 ++- .../javac/StringConcat/access/Holder.java | 98 +++++++++ .../StringConcat/access/PublicClass.java | 27 +++ .../StringConcat/access/PublicInterface.java | 27 +++ .../access/Public_PrivateInterface1.java | 30 +++ .../access/Public_PrivateInterface2.java | 30 +++ .../access/Public_PublicClass.java | 30 +++ .../access/Public_PublicInterface.java | 30 +++ .../tools/javac/StringConcat/access/Test.java | 192 ++++++++++++++++++ 9 files changed, 486 insertions(+), 4 deletions(-) create mode 100644 langtools/test/tools/javac/StringConcat/access/Holder.java create mode 100644 langtools/test/tools/javac/StringConcat/access/PublicClass.java create mode 100644 langtools/test/tools/javac/StringConcat/access/PublicInterface.java create mode 100644 langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface1.java create mode 100644 langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface2.java create mode 100644 langtools/test/tools/javac/StringConcat/access/Public_PublicClass.java create mode 100644 langtools/test/tools/javac/StringConcat/access/Public_PublicInterface.java create mode 100644 langtools/test/tools/javac/StringConcat/access/Test.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java index bb5436bd96c..80cee302dec 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java @@ -33,8 +33,7 @@ import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.*; import static com.sun.tools.javac.code.Kinds.Kind.MTH; -import static com.sun.tools.javac.code.TypeTag.DOUBLE; -import static com.sun.tools.javac.code.TypeTag.LONG; +import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.jvm.ByteCodes.*; import static com.sun.tools.javac.tree.JCTree.Tag.PLUS; import com.sun.tools.javac.jvm.Items.*; @@ -142,6 +141,25 @@ public abstract class StringConcat { return res.append(tree); } + /** + * If the type is not accessible from current context, try to figure out the + * sharpest accessible supertype. + * + * @param originalType type to sharpen + * @return sharped type + */ + Type sharpestAccessible(Type originalType) { + if (originalType.hasTag(ARRAY)) { + return types.makeArrayType(sharpestAccessible(types.elemtype(originalType))); + } + + Type type = originalType; + while (!rs.isAccessible(gen.getAttrEnv(), type.asElement())) { + type = types.supertype(type); + } + return type; + } + /** * "Legacy" bytecode flavor: emit the StringBuilder.append chains for string * concatenation. @@ -314,7 +332,7 @@ public abstract class StringConcat { if (arg.type == syms.botType) { dynamicArgs.add(types.boxedClass(syms.voidType).type); } else { - dynamicArgs.add(arg.type); + dynamicArgs.add(sharpestAccessible(arg.type)); } gen.genExpr(arg, arg.type).load(); } @@ -415,7 +433,7 @@ public abstract class StringConcat { } else { // Ordinary arguments come through the dynamic arguments. recipe.append(TAG_ARG); - dynamicArgs.add(arg.type); + dynamicArgs.add(sharpestAccessible(arg.type)); gen.genExpr(arg, arg.type).load(); } } diff --git a/langtools/test/tools/javac/StringConcat/access/Holder.java b/langtools/test/tools/javac/StringConcat/access/Holder.java new file mode 100644 index 00000000000..6b4cb37e688 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Holder.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, 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 p1; + +public class Holder { + public Private_PublicClass c1 = new Private_PublicClass(); + public Private_PublicInterface c2 = new Private_PublicInterface(); + public Private_PrivateInterface1 c3 = new Private_PrivateInterface1(); + public Private_PrivateInterface2 c4 = new Private_PrivateInterface2(); + + public Public_PublicClass c5 = new Public_PublicClass(); + public Public_PublicInterface c6 = new Public_PublicInterface(); + public Public_PrivateInterface1 c7 = new Public_PrivateInterface1(); + public Public_PrivateInterface2 c8 = new Public_PrivateInterface2(); + + public Private_PublicClass[] ac1 = new Private_PublicClass[0]; + public Private_PublicInterface[] ac2 = new Private_PublicInterface[0]; + public Private_PrivateInterface1[] ac3 = new Private_PrivateInterface1[0]; + public Private_PrivateInterface2[] ac4 = new Private_PrivateInterface2[0]; + + public Public_PublicClass[] ac5 = new Public_PublicClass[0]; + public Public_PublicInterface[] ac6 = new Public_PublicInterface[0]; + public Public_PrivateInterface1[] ac7 = new Public_PrivateInterface1[0]; + public Public_PrivateInterface2[] ac8 = new Public_PrivateInterface2[0]; + + public Private_PublicClass[][] aac1 = new Private_PublicClass[0][]; + public Private_PublicInterface[][] aac2 = new Private_PublicInterface[0][]; + public Private_PrivateInterface1[][] aac3 = new Private_PrivateInterface1[0][]; + public Private_PrivateInterface2[][] aac4 = new Private_PrivateInterface2[0][]; + + public Public_PublicClass[][] aac5 = new Public_PublicClass[0][]; + public Public_PublicInterface[][] aac6 = new Public_PublicInterface[0][]; + public Public_PrivateInterface1[][] aac7 = new Public_PrivateInterface1[0][]; + public Public_PrivateInterface2[][] aac8 = new Public_PrivateInterface2[0][]; + + public PublicInterface i1 = new Private_PublicInterface(); + public PrivateInterface1 i2 = new Private_PrivateInterface1(); + public PrivateInterface2 i3 = new Private_PrivateInterface2(); + + public PublicInterface[] ai1 = new Private_PublicInterface[0]; + public PrivateInterface1[] ai2 = new Private_PrivateInterface1[0]; + public PrivateInterface2[] ai3 = new Private_PrivateInterface2[0]; + + public PublicInterface[][] aai1 = new Private_PublicInterface[0][]; + public PrivateInterface1[][] aai2 = new Private_PrivateInterface1[0][]; + public PrivateInterface2[][] aai3 = new Private_PrivateInterface2[0][]; +} + +interface PrivateInterface1 { +} + +interface PrivateInterface2 extends PublicInterface { +} + +class Private_PublicClass extends PublicClass { + public String toString() { + return "passed"; + } +} + +class Private_PublicInterface implements PublicInterface { + public String toString() { + return "passed"; + } +} + +class Private_PrivateInterface1 implements PrivateInterface1 { + public String toString() { + return "passed"; + } +} + +class Private_PrivateInterface2 implements PrivateInterface2 { + public String toString() { + return "passed"; + } +} diff --git a/langtools/test/tools/javac/StringConcat/access/PublicClass.java b/langtools/test/tools/javac/StringConcat/access/PublicClass.java new file mode 100644 index 00000000000..d4ae6bfc36e --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/PublicClass.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, 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 p1; + +public class PublicClass { +} diff --git a/langtools/test/tools/javac/StringConcat/access/PublicInterface.java b/langtools/test/tools/javac/StringConcat/access/PublicInterface.java new file mode 100644 index 00000000000..ba26be94955 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/PublicInterface.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, 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 p1; + +public interface PublicInterface { +} diff --git a/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface1.java b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface1.java new file mode 100644 index 00000000000..301f90ec798 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface1.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, 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 p1; + +public class Public_PrivateInterface1 implements PrivateInterface1 { + public String toString() { + return "passed"; + } +} diff --git a/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface2.java b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface2.java new file mode 100644 index 00000000000..dcfcea14ad4 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface2.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, 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 p1; + +public class Public_PrivateInterface2 implements PrivateInterface2 { + public String toString() { + return "passed"; + } +} diff --git a/langtools/test/tools/javac/StringConcat/access/Public_PublicClass.java b/langtools/test/tools/javac/StringConcat/access/Public_PublicClass.java new file mode 100644 index 00000000000..20d28acf0d3 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Public_PublicClass.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, 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 p1; + +public class Public_PublicClass { + public String toString() { + return "passed"; + } +} diff --git a/langtools/test/tools/javac/StringConcat/access/Public_PublicInterface.java b/langtools/test/tools/javac/StringConcat/access/Public_PublicInterface.java new file mode 100644 index 00000000000..1c8ae4b60bd --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Public_PublicInterface.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, 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 p1; + +public class Public_PublicInterface implements PublicInterface { + public String toString() { + return "passed"; + } +} diff --git a/langtools/test/tools/javac/StringConcat/access/Test.java b/langtools/test/tools/javac/StringConcat/access/Test.java new file mode 100644 index 00000000000..fc9e78c0e31 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Test.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2016, 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 8151223 + * @summary String concatenation fails with implicit toString() on package-private class + * @modules jdk.jdeps/com.sun.tools.classfile + * @compile -XDstringConcat=indy Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java + * @run main Test + * @compile -XDstringConcat=indyWithConstants Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java + * @run main Test + */ + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.ConstantPool.*; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class Test { + static List actualTypes; + + public static void main(String[] argv) throws Exception { + readIndyTypes(); + + p1.Holder holder = new p1.Holder(); + + int idx = 0; + + // ---------------------------------------------------------------------------- + + // public Private_PublicClass c1 = new Private_PublicClass(); + test("" + holder.c1, idx++, "(Lp1/PublicClass;)Ljava/lang/String;"); + + // public Private_PublicInterface c2 = new Private_PublicInterface(); + test("" + holder.c2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface1 c3 = new Private_PrivateInterface1(); + test("" + holder.c3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface2 c4 = new Private_PrivateInterface2(); + test("" + holder.c4, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public Public_PublicClass c5 = new Public_PublicClass(); + test("" + holder.c5, idx++, "(Lp1/Public_PublicClass;)Ljava/lang/String;"); + + // public Public_PublicInterface c6 = new Public_PublicInterface(); + test("" + holder.c6, idx++, "(Lp1/Public_PublicInterface;)Ljava/lang/String;"); + + // public Public_PrivateInterface1 c7 = new Public_PrivateInterface1(); + test("" + holder.c7, idx++, "(Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + + // public Public_PrivateInterface2 c8 = new Public_PrivateInterface2(); + test("" + holder.c8, idx++, "(Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public Private_PublicClass[] ac1 = new Private_PublicClass[0]; + test("" + holder.ac1, idx++, "([Lp1/PublicClass;)Ljava/lang/String;"); + + // public Private_PublicInterface[] ac2 = new Private_PublicInterface[0]; + test("" + holder.ac2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface1[] ac3 = new Private_PrivateInterface1[0]; + test("" + holder.ac3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface2[] ac4 = new Private_PrivateInterface2[0]; + test("" + holder.ac4, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public Public_PublicClass[] ac5 = new Public_PublicClass[0]; + test("" + holder.ac5, idx++, "([Lp1/Public_PublicClass;)Ljava/lang/String;"); + + // public Public_PublicInterface[] ac6 = new Public_PublicInterface[0]; + test("" + holder.ac6, idx++, "([Lp1/Public_PublicInterface;)Ljava/lang/String;"); + + // public Public_PrivateInterface1[] ac7 = new Public_PrivateInterface1[0]; + test("" + holder.ac7, idx++, "([Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + + // public Public_PrivateInterface2[] ac8 = new Public_PrivateInterface2[0]; + test("" + holder.ac8, idx++, "([Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public Private_PublicClass[][] aac1 = new Private_PublicClass[0][]; + test("" + holder.aac1, idx++, "([[Lp1/PublicClass;)Ljava/lang/String;"); + + // public Private_PublicInterface[][] aac2 = new Private_PublicInterface[0][]; + test("" + holder.aac2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface1[][] aac3 = new Private_PrivateInterface1[0][]; + test("" + holder.aac3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface2[][] aac4 = new Private_PrivateInterface2[0][]; + test("" + holder.aac4, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public Public_PublicClass[][] aac5 = new Public_PublicClass[0][]; + test("" + holder.aac5, idx++, "([[Lp1/Public_PublicClass;)Ljava/lang/String;"); + + // public Public_PublicInterface[][] aac6 = new Public_PublicInterface[0][]; + test("" + holder.aac6, idx++, "([[Lp1/Public_PublicInterface;)Ljava/lang/String;"); + + // public Public_PrivateInterface1[][] aac7 = new Public_PrivateInterface1[0][]; + test("" + holder.aac7, idx++, "([[Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + + // public Public_PrivateInterface2[][] aac8 = new Public_PrivateInterface2[0][]; + test("" + holder.aac8, idx++, "([[Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public PublicInterface i1 = new Private_PublicInterface(); + test("" + holder.i1, idx++, "(Lp1/PublicInterface;)Ljava/lang/String;"); + + // public PrivateInterface1 i2 = new Private_PrivateInterface1(); + test("" + holder.i2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public PrivateInterface2 i3 = new Private_PrivateInterface2(); + test("" + holder.i3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public PublicInterface[] ai1 = new Private_PublicInterface[0]; + test("" + holder.ai1, idx++, "([Lp1/PublicInterface;)Ljava/lang/String;"); + + // public PrivateInterface1[] ai2 = new Private_PrivateInterface1[0]; + test("" + holder.ai2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public PrivateInterface2[] ai3 = new Private_PrivateInterface2[0]; + test("" + holder.ai3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public PublicInterface[][] aai1 = new Private_PublicInterface[0][]; + test("" + holder.aai1, idx++, "([[Lp1/PublicInterface;)Ljava/lang/String;"); + + // public PrivateInterface1[][] aai2 = new Private_PrivateInterface1[0][]; + test("" + holder.aai2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public PrivateInterface2[][] aai3 = new Private_PrivateInterface2[0][]; + test("" + holder.aai3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + } + + public static void test(String actual, int index, String expectedType) { + if (!"passed".equals(actual) && !actual.startsWith("[")) { + throw new IllegalStateException("Unexpected result: " + actual); + } + String actualType = actualTypes.get(index); + if (!actualType.equals(expectedType)) { + throw new IllegalStateException("Unexpected type: expected = " + expectedType + ", actual = " + actualType); + } + } + + public static void readIndyTypes() throws Exception { + actualTypes = new ArrayList(); + + ClassFile classFile = ClassFile.read(new File(System.getProperty("test.classes", "."), + Test.class.getName() + ".class")); + ConstantPool constantPool = classFile.constant_pool; + + for (Method method : classFile.methods) { + if (method.getName(constantPool).equals("main")) { + Code_attribute code = (Code_attribute) method.attributes + .get(Attribute.Code); + for (Instruction i : code.getInstructions()) { + if (i.getOpcode() == Opcode.INVOKEDYNAMIC) { + CONSTANT_InvokeDynamic_info indyInfo = (CONSTANT_InvokeDynamic_info) constantPool.get(i.getUnsignedShort(1)); + CONSTANT_NameAndType_info natInfo = indyInfo.getNameAndTypeInfo(); + actualTypes.add(natInfo.getType()); + } + } + } + } + } +} From 0a352526f390f8d204ccdeace3b3fdddcd47b017 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 9 Mar 2016 18:31:49 +0300 Subject: [PATCH 107/311] 8151516: test/tools/javac/TestIndyStringConcat depends on runtime JDK details Reviewed-by: mcimadamore --- .../StringConcat/TestIndyStringConcat.java | 111 ++++++++++++++++++ .../tools/javac/StringConcat/access/Test.java | 26 ++-- .../tools/javac/TestIndyStringConcat.java | 74 ------------ 3 files changed, 126 insertions(+), 85 deletions(-) create mode 100644 langtools/test/tools/javac/StringConcat/TestIndyStringConcat.java delete mode 100644 langtools/test/tools/javac/TestIndyStringConcat.java diff --git a/langtools/test/tools/javac/StringConcat/TestIndyStringConcat.java b/langtools/test/tools/javac/StringConcat/TestIndyStringConcat.java new file mode 100644 index 00000000000..4c8917bbbf9 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/TestIndyStringConcat.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, 2016, 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 com.sun.tools.classfile.*; +import com.sun.tools.classfile.BootstrapMethods_attribute.BootstrapMethodSpecifier; +import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info; +import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info; + +import java.io.File; + +/* + * @test + * @bug 8148483 8151516 8151223 + * @summary Test that StringConcat is working for JDK >= 9 + * @modules jdk.jdeps/com.sun.tools.classfile + * + * @clean TestIndyStringConcat* + * @compile -source 6 -target 6 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -source 7 -target 7 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -source 8 -target 8 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -XDstringConcat=inline -source 9 -target 9 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -XDstringConcat=indy -source 9 -target 9 TestIndyStringConcat.java + * @run main TestIndyStringConcat true + * + * @clean TestIndyStringConcat* + * @compile -XDstringConcat=indyWithConstants -source 9 -target 9 TestIndyStringConcat.java + * @run main TestIndyStringConcat true + */ +public class TestIndyStringConcat { + + static String other; + + public static String test() { + return "Foo" + other; + } + + public static void main(String[] args) throws Exception { + boolean expected = Boolean.valueOf(args[0]); + boolean actual = hasStringConcatFactoryCall("test"); + if (expected != actual) { + throw new AssertionError("expected = " + expected + ", actual = " + actual); + } + } + + public static boolean hasStringConcatFactoryCall(String methodName) throws Exception { + ClassFile classFile = ClassFile.read(new File(System.getProperty("test.classes", "."), + TestIndyStringConcat.class.getName() + ".class")); + ConstantPool constantPool = classFile.constant_pool; + + BootstrapMethods_attribute bsm_attr = + (BootstrapMethods_attribute)classFile + .getAttribute(Attribute.BootstrapMethods); + + for (Method method : classFile.methods) { + if (method.getName(constantPool).equals(methodName)) { + Code_attribute code = (Code_attribute) method.attributes + .get(Attribute.Code); + for (Instruction i : code.getInstructions()) { + if (i.getOpcode() == Opcode.INVOKEDYNAMIC) { + CONSTANT_InvokeDynamic_info indyInfo = + (CONSTANT_InvokeDynamic_info) constantPool.get(i.getUnsignedShort(1)); + + BootstrapMethodSpecifier bsmSpec = + bsm_attr.bootstrap_method_specifiers[indyInfo.bootstrap_method_attr_index]; + + CONSTANT_MethodHandle_info bsmInfo = + (CONSTANT_MethodHandle_info) constantPool.get(bsmSpec.bootstrap_method_ref); + + if (bsmInfo.getCPRefInfo().getClassName().equals("java/lang/invoke/StringConcatFactory")) { + return true; + } + } + } + } + } + return false; + } + +} diff --git a/langtools/test/tools/javac/StringConcat/access/Test.java b/langtools/test/tools/javac/StringConcat/access/Test.java index fc9e78c0e31..72237e8b4ef 100644 --- a/langtools/test/tools/javac/StringConcat/access/Test.java +++ b/langtools/test/tools/javac/StringConcat/access/Test.java @@ -21,17 +21,6 @@ * questions. */ -/* - * @test - * @bug 8151223 - * @summary String concatenation fails with implicit toString() on package-private class - * @modules jdk.jdeps/com.sun.tools.classfile - * @compile -XDstringConcat=indy Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java - * @run main Test - * @compile -XDstringConcat=indyWithConstants Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java - * @run main Test - */ - import com.sun.tools.classfile.*; import com.sun.tools.classfile.ConstantPool.*; @@ -39,6 +28,21 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +/* + * @test + * @bug 8151223 + * @summary String concatenation fails with implicit toString() on package-private class + * @modules jdk.jdeps/com.sun.tools.classfile + * + * @clean * + * @compile -XDstringConcat=indy Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java + * @run main Test + * + * @clean * + * @compile -XDstringConcat=indyWithConstants Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java + * @run main Test + */ + public class Test { static List actualTypes; diff --git a/langtools/test/tools/javac/TestIndyStringConcat.java b/langtools/test/tools/javac/TestIndyStringConcat.java deleted file mode 100644 index b799f70015b..00000000000 --- a/langtools/test/tools/javac/TestIndyStringConcat.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 - * @summary Test that StringConcat is working for JDK >= 9 - * @compile -source 6 -target 6 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -source 7 -target 7 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -source 8 -target 8 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -XDstringConcat=inline -source 9 -target 9 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -XDstringConcat=indy -source 9 -target 9 TestIndyStringConcat.java - * @run main TestIndyStringConcat true - * @clean TestIndyStringConcat* - * @compile -XDstringConcat=indyWithConstants -source 9 -target 9 TestIndyStringConcat.java - * @run main TestIndyStringConcat true - */ -public class TestIndyStringConcat { - - private static class MyObject { - public String toString() { - throw new RuntimeException("Boyyaa"); - } - } - - class Inner { } - - public static void main(String[] args) { - boolean useIndyConcat = Boolean.valueOf(args[0]); - try { - String s = "Foo" + new MyObject(); - } catch (RuntimeException ex) { - boolean indifiedStringConcat = false; - ex.printStackTrace(); - for (StackTraceElement e : ex.getStackTrace()) { - if (e.getClassName().contains("$$StringConcat") && - e.getMethodName().equals("concat")) { - indifiedStringConcat = true; - break; - } - } - if (indifiedStringConcat != useIndyConcat) { - throw new AssertionError(); - } - } - } -} From eb9a8ddcc4d2f3bcad1acb33198cfe53ba8aa18c Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Thu, 10 Mar 2016 08:54:29 +0100 Subject: [PATCH 108/311] 8150632: jdk.jshell.TaskFactory should use jdk.Version to check for java.specification.version Reviewed-by: rfield --- .../src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java index 0582fd66cae..f27b0c770be 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java @@ -61,6 +61,7 @@ import javax.lang.model.util.Elements; import javax.tools.FileObject; import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject; import jdk.jshell.ClassTracker.ClassInfo; +import jdk.Version; /** * The primary interface to the compiler API. Parsing, analysis, and @@ -73,6 +74,7 @@ class TaskFactory { private final MemoryFileManager fileManager; private final JShell state; private String classpath = System.getProperty("java.class.path"); + private final static Version INITIAL_SUPPORTED_VER = Version.parse("9"); TaskFactory(JShell state) { this.state = state; @@ -80,7 +82,8 @@ class TaskFactory { if (compiler == null) { throw new UnsupportedOperationException("Compiler not available, must be run with full JDK 9."); } - if (!System.getProperty("java.specification.version").equals("9")) { + Version current = Version.parse(System.getProperty("java.specification.version")); + if (INITIAL_SUPPORTED_VER.compareToIgnoreOpt(current) > 0) { throw new UnsupportedOperationException("Wrong compiler, must be run with full JDK 9."); } this.fileManager = new MemoryFileManager( From c66a688da238dca67f2c8981ad701de8cf4af382 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 10 Mar 2016 09:28:19 -0800 Subject: [PATCH 109/311] Added tag jdk-9+109 for changeset f74f056dc069 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 08776ccc375..5fb34d8884a 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -351,3 +351,4 @@ cb73b474703e2de266542b505cffd658bcc052da jdk-9+99 dd05d3761a341143ef4a6b1a245e0960cc125b76 jdk-9+106 7a0c343551497bd0e38ad69a77cc57d9f396615a jdk-9+107 fd18a155ad22f62e06a9b74850ab8609d415c752 jdk-9+108 +f5991c73ed73b9a355a090b65c8d7fb9a1901f89 jdk-9+109 From 19e4c511578a846d781ed5cbaf947165409b138d Mon Sep 17 00:00:00 2001 From: Robert Field Date: Thu, 10 Mar 2016 14:47:14 -0800 Subject: [PATCH 110/311] 8080069: JShell: Support for corralled classes Reviewed-by: jlahoda --- .../jdk/internal/jshell/tool/JShellTool.java | 8 +- .../share/classes/jdk/jshell/Corraller.java | 148 ++++++++++++ .../share/classes/jdk/jshell/Eval.java | 11 +- .../classes/jdk/jshell/ExecutionControl.java | 2 +- .../jshell/UnresolvedReferenceException.java | 24 +- .../share/classes/jdk/jshell/Wrap.java | 92 +++++++- langtools/test/jdk/jshell/ClassesTest.java | 9 +- langtools/test/jdk/jshell/DropTest.java | 36 +-- langtools/test/jdk/jshell/KullaTesting.java | 12 +- langtools/test/jdk/jshell/ReplaceTest.java | 215 +++++++++++++----- 10 files changed, 439 insertions(+), 118 deletions(-) create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 10b121b4062..55eb01bb908 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -98,6 +98,7 @@ import jdk.internal.jshell.tool.Feedback.FormatCase; import jdk.internal.jshell.tool.Feedback.FormatResolve; import jdk.internal.jshell.tool.Feedback.FormatWhen; import static java.util.stream.Collectors.toList; +import static jdk.jshell.Snippet.Kind.METHOD; import static java.util.stream.Collectors.toMap; import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND; @@ -2139,7 +2140,7 @@ public class JShellTool { } //where void printUnresolved(UnresolvedReferenceException ex) { - MethodSnippet corralled = ex.getMethodSnippet(); + DeclarationSnippet corralled = ex.getSnippet(); List otherErrors = errorsOnly(state.diagnostics(corralled)); StringBuilder sb = new StringBuilder(); if (otherErrors.size() > 0) { @@ -2155,7 +2156,10 @@ public class JShellTool { sb.append("."); } - hard("Attempted to call %s which cannot be invoked until%s", corralled.name(), + String format = corralled.kind() == METHOD + ? "Attempted to call %s which cannot be invoked until%s" + : "Attempted to use %s which cannot be accessed until%s"; + hard(format, corralled.name(), unresolved(corralled), sb.toString()); if (otherErrors.size() > 0) { printDiagnostics(corralled.source(), otherErrors, true); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java new file mode 100644 index 00000000000..349e393caa0 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016, 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. + */ + +package jdk.jshell; + +import java.util.List; +import com.sun.source.tree.ArrayTypeTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import jdk.jshell.Wrap.Range; +import static java.util.stream.Collectors.toList; + +/** + * Produce a corralled version of the Wrap for a snippet. + * + * @author Robert Field + */ +class Corraller { + + private final int index; + private final String compileSource; + private final TreeDissector dis; + + Corraller(int index, String compileSource, TreeDissector dis) { + this.index = index; + this.compileSource = compileSource; + this.dis = dis; + } + + Wrap corralTree(Tree tree, String enclosingType, int indent) { + switch (tree.getKind()) { + case VARIABLE: + return corralVariable((VariableTree) tree, indent); + case CLASS: + case ENUM: + case ANNOTATION_TYPE: + case INTERFACE: + return corralType((ClassTree) tree, indent); + case METHOD: + return corralMethod((MethodTree) tree, enclosingType, indent); + default: + return null; + } + } + + Wrap corralMethod(MethodTree mt) { + return corralMethod(mt, null, 1); + } + + Wrap corralMethod(MethodTree mt, String enclosingType, int indent) { + Range modRange = dis.treeToRange(mt.getModifiers()); + Range tpRange = dis.treeListToRange(mt.getTypeParameters()); + Range typeRange = dis.treeToRange(mt.getReturnType()); + String name = mt.getName().toString(); + if ("".equals(name)) { + name = enclosingType; + } + Range paramRange = dis.treeListToRange(mt.getParameters()); + Range throwsRange = dis.treeListToRange(mt.getThrows()); + return Wrap.corralledMethod(compileSource, + modRange, tpRange, typeRange, name, paramRange, throwsRange, index, indent); + } + + Wrap corralVariable(VariableTree vt, int indent) { + String name = vt.getName().toString(); + Range modRange = dis.treeToRange(vt.getModifiers()); + Tree baseType = vt.getType(); + StringBuilder sbBrackets = new StringBuilder(); + while (baseType instanceof ArrayTypeTree) { + //TODO handle annotations too + baseType = ((ArrayTypeTree) baseType).getType(); + sbBrackets.append("[]"); + } + Range rtype = dis.treeToRange(baseType); + Range runit = dis.treeToRange(vt); + runit = new Range(runit.begin, runit.end - 1); + ExpressionTree it = vt.getInitializer(); + int nameMax; + if (it != null) { + Range rinit = dis.treeToRange(it); + nameMax = rinit.begin - 1; + } else { + nameMax = runit.end - 1; + } + int nameStart = compileSource.lastIndexOf(name, nameMax); + if (nameStart < 0) { + throw new AssertionError("Name '" + name + "' not found"); + } + int nameEnd = nameStart + name.length(); + Range rname = new Range(nameStart, nameEnd); + return Wrap.corralledVar(compileSource, modRange, rtype, sbBrackets.toString(), rname, indent); + } + + Wrap corralType(ClassTree ct, int indent) { + boolean isClass; + switch (ct.getKind()) { + case CLASS: + isClass = true; + break; + case INTERFACE: + isClass = false; + break; + default: + return null; + } + Range modRange = dis.treeToRange(ct.getModifiers()); + String name = ct.getSimpleName().toString(); + Range tpRange = dis.treeListToRange(ct.getTypeParameters()); + Range extendsRange = dis.treeToRange(ct.getExtendsClause()); + List implementsRanges = ct.getImplementsClause().stream() + .map(ic -> dis.treeToRange(ic)) + .collect(toList()); + List members = ct.getMembers().stream() + .map(t -> corralTree(t, name, indent + 1)) + .filter(w -> w != null) + .collect(toList()); + boolean hasConstructor = ct.getMembers().stream() + .anyMatch(t -> t.getKind() == Tree.Kind.METHOD && ((MethodTree) t).getName().toString().equals("")); + Wrap wrap = Wrap.corralledType(compileSource, modRange, ct.getKind(), name, tpRange, + extendsRange, implementsRanges, members, isClass && !hasConstructor, index, indent); + return wrap; + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java index 3f01908b782..610840353ec 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java @@ -53,6 +53,7 @@ import java.util.Set; import jdk.jshell.ClassTracker.ClassInfo; import jdk.jshell.Key.ErroneousKey; import jdk.jshell.Key.MethodKey; +import jdk.jshell.Key.TypeDeclKey; import jdk.jshell.Snippet.SubKind; import jdk.jshell.TaskFactory.AnalyzeTask; import jdk.jshell.TaskFactory.BaseTask; @@ -300,7 +301,8 @@ class Eval { ClassTree klassTree = (ClassTree) unitTree; String name = klassTree.getSimpleName().toString(); Wrap guts = Wrap.classMemberWrap(compileSource); - Wrap corralled = null; //TODO + TypeDeclKey key = state.keyMap.keyForClass(name); + Wrap corralled = new Corraller(key.index(), compileSource, dis).corralType(klassTree, 1); Snippet snip = new TypeDeclSnippet(state.keyMap.keyForClass(name), userSource, guts, name, snippetKind, corralled, tds.declareReferences(), tds.bodyReferences()); @@ -362,12 +364,8 @@ class Eval { String unitName = mt.getName().toString(); Wrap guts = Wrap.classMemberWrap(compileSource); - Range modRange = dis.treeToRange(mt.getModifiers()); - Range tpRange = dis.treeListToRange(mt.getTypeParameters()); Range typeRange = dis.treeToRange(mt.getReturnType()); String name = mt.getName().toString(); - Range paramRange = dis.treeListToRange(mt.getParameters()); - Range throwsRange = dis.treeListToRange(mt.getThrows()); String parameterTypes = mt.getParameters() @@ -378,8 +376,7 @@ class Eval { MethodKey key = state.keyMap.keyForMethod(name, parameterTypes); // rewrap with correct Key index - Wrap corralled = Wrap.corralledMethod(compileSource, - modRange, tpRange, typeRange, name, paramRange, throwsRange, key.index()); + Wrap corralled = new Corraller(key.index(), compileSource, dis).corralMethod(mt); Snippet snip = new MethodSnippet(key, userSource, guts, unitName, signature, corralled, tds.declareReferences(), tds.bodyReferences()); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java index ad115656661..8f629fd75c8 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java @@ -225,7 +225,7 @@ class ExecutionControl { int id = in.readInt(); StackTraceElement[] elems = readStackTrace(); Snippet si = maps.getSnippet(id); - throw new UnresolvedReferenceException((MethodSnippet) si, elems); + throw new UnresolvedReferenceException((DeclarationSnippet) si, elems); } case RESULT_KILLED: { proc.out.println("Killed."); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java index eaf240d47b2..3e3de8fd943 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -28,33 +28,33 @@ package jdk.jshell; /** * Exception reported on attempting to execute a * {@link jdk.jshell.Snippet.Status#RECOVERABLE_DEFINED RECOVERABLE_DEFINED} - * method. + * snippet. *

      * The stack can be queried by methods on Exception. * Note that in stack trace frames representing JShell Snippets, * StackTraceElement.getFileName() will return "#" followed by * the Snippet id and for snippets without a method name (for example an - * expression) StackTraceElement.getMethodName() will be the + * expression) StackTraceElement.getName() will be the * empty string. */ @SuppressWarnings("serial") // serialVersionUID intentionally omitted public class UnresolvedReferenceException extends Exception { - final MethodSnippet methodSnippet; + final DeclarationSnippet snippet; - UnresolvedReferenceException(MethodSnippet methodSnippet, StackTraceElement[] stackElements) { - super("Attempt to invoke method with unresolved references"); - this.methodSnippet = methodSnippet; + UnresolvedReferenceException(DeclarationSnippet snippet, StackTraceElement[] stackElements) { + super("Attempt to use definition snippet with unresolved references"); + this.snippet = snippet; this.setStackTrace(stackElements); } /** - * Return the method Snippet which has the unresolved reference(s). - * @return the MethodSnippet of the + * Return the Snippet which has the unresolved reference(s). + * @return the Snippet of the * {@link jdk.jshell.Snippet.Status#RECOVERABLE_DEFINED RECOVERABLE_DEFINED} - * method. + * definition snippet. */ - public MethodSnippet getMethodSnippet() { - return methodSnippet; + public DeclarationSnippet getSnippet() { + return snippet; } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java index 1b380444936..62759319a9b 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -27,6 +27,7 @@ package jdk.jshell; import java.util.ArrayList; import java.util.List; +import com.sun.source.tree.Tree; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; /** @@ -58,9 +59,18 @@ abstract class Wrap implements GeneralWrap { return methodWrap("", source, ""); } - public static Wrap corralledMethod(String source, Range modRange, Range tpRange, Range typeRange, String name, Range paramRange, Range throwsRange, int id) { + private static String indent(int n) { + return " ".substring(0, n * 4); + } + + private static String nlindent(int n) { + return "\n" + indent(n); + } + + public static Wrap corralledMethod(String source, Range modRange, Range tpRange, + Range typeRange, String name, Range paramRange, Range throwsRange, int id, int indent) { List l = new ArrayList<>(); - l.add(" public static\n "); + l.add(indent(indent) + ((indent == 1) ? "public static" + nlindent(indent) : "")); if (!modRange.isEmpty()) { l.add(new RangeWrap(source, modRange)); l.add(" "); @@ -70,17 +80,81 @@ abstract class Wrap implements GeneralWrap { l.add(new RangeWrap(source, tpRange)); l.add("> "); } - l.add(new RangeWrap(source, typeRange)); - l.add(" " + name + "(\n "); - if (paramRange != null) { + if (!typeRange.isEmpty()) { + l.add(new RangeWrap(source, typeRange)); + l.add(" "); + } + l.add(name + "("); + if (paramRange != null && !paramRange.isEmpty()) { + l.add(nlindent(indent + 1)); l.add(new RangeWrap(source, paramRange)); } - l.add(") "); + l.add(")"); if (throwsRange != null) { - l.add("throws "); + l.add(" throws "); l.add(new RangeWrap(source, throwsRange)); } - l.add(" {\n throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");\n}\n"); + l.add(" {" + + nlindent(indent+1) + + "throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");" + + nlindent(indent) + + "}\n"); + return new CompoundWrap(l.toArray()); + } + + public static Wrap corralledType(String source, Range modRange, Tree.Kind kind, String name, Range tpRange, + Range extendsRange, List implementsRanges, List members, + boolean defaultConstructor, int id, int indent) { + boolean isInterface = kind == Tree.Kind.INTERFACE; + List l = new ArrayList<>(); + l.add(indent(indent) + ((indent == 1) ? "public static" + nlindent(indent) : "")); + if (!modRange.isEmpty()) { + l.add(new RangeWrap(source, modRange)); + l.add(" "); + } + l.add((isInterface ? "interface " : "class ") + name); + if (tpRange != null) { + l.add("<"); + l.add(new RangeWrap(source, tpRange)); + l.add("> "); + } + if (extendsRange != null && !extendsRange.isEmpty()) { + l.add(" extends "); + l.add(new RangeWrap(source, extendsRange)); + } + for (int i = 0; i < implementsRanges.size(); ++i) { + Range ir = implementsRanges.get(i); + l.add(i == 0 ? " implements " : ", "); + l.add(new RangeWrap(source, ir)); + } + if (defaultConstructor) { + l.add(" {" + + nlindent(indent+1) + + ((indent == 1)? "public " : "") + name + "() {" + + nlindent(indent+2) + + "throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");" + + nlindent(indent+1) + + "}\n"); + } else { + l.add(" {\n"); + } + l.addAll(members); + l.add(indent(indent) + "}\n"); + return new CompoundWrap(l.toArray()); + } + + public static Wrap corralledVar(String source, Range modRange, Range typeRange, String brackets, Range nameRange, int indent) { + RangeWrap wname = new RangeWrap(source, nameRange); + List l = new ArrayList<>(); + l.add(indent(indent) + ((indent == 1) ? "public static" + nlindent(indent) : "")); + if (!modRange.isEmpty()) { + l.add(new RangeWrap(source, modRange)); + l.add(" "); + } + l.add(new RangeWrap(source, typeRange)); + l.add(" "); + l.add(wname); + l.add(semi(wname)); return new CompoundWrap(l.toArray()); } diff --git a/langtools/test/jdk/jshell/ClassesTest.java b/langtools/test/jdk/jshell/ClassesTest.java index 394d88b3c0e..058714fe438 100644 --- a/langtools/test/jdk/jshell/ClassesTest.java +++ b/langtools/test/jdk/jshell/ClassesTest.java @@ -43,12 +43,13 @@ import org.testng.annotations.Test; import jdk.jshell.Diag; import static jdk.jshell.Snippet.Status.VALID; import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED; +import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED; import static jdk.jshell.Snippet.Status.DROPPED; import static jdk.jshell.Snippet.Status.REJECTED; +import static jdk.jshell.Snippet.Status.OVERWRITTEN; import static jdk.jshell.Snippet.SubKind.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; -import static jdk.jshell.Snippet.Status.OVERWRITTEN; @Test public class ClassesTest extends KullaTesting { @@ -82,10 +83,10 @@ public class ClassesTest extends KullaTesting { TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareFail("class A { void f() { return g(); } }", "compiler.err.prob.found.req"); assertTypeDeclSnippet(c1, "A", REJECTED, CLASS_SUBKIND, 0, 2); TypeDeclSnippet c2 = classKey(assertEval("class A { int f() { return g(); } }", - ste(c1, REJECTED, RECOVERABLE_NOT_DEFINED, false, null))); - assertTypeDeclSnippet(c2, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0); + ste(c1, REJECTED, RECOVERABLE_DEFINED, true, null))); + assertTypeDeclSnippet(c2, "A", RECOVERABLE_DEFINED, CLASS_SUBKIND, 1, 0); assertDrop(c2, - ste(c2, RECOVERABLE_NOT_DEFINED, DROPPED, false, null)); + ste(c2, RECOVERABLE_DEFINED, DROPPED, true, null)); } public void classDeclaration() { diff --git a/langtools/test/jdk/jshell/DropTest.java b/langtools/test/jdk/jshell/DropTest.java index 0e61ebad700..04e9fb2a4e5 100644 --- a/langtools/test/jdk/jshell/DropTest.java +++ b/langtools/test/jdk/jshell/DropTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 8081431 + * @bug 8081431 8080069 * @summary Test of JShell#drop(). * @build KullaTesting TestingInputStream * @run testng DropTest @@ -31,6 +31,7 @@ import jdk.jshell.DeclarationSnippet; import jdk.jshell.PersistentSnippet; +import jdk.jshell.VarSnippet; import org.testng.annotations.Test; import static jdk.jshell.Snippet.Status.*; @@ -45,21 +46,27 @@ public class DropTest extends KullaTesting { assertDrop(var, ste(var, VALID, DROPPED, true, null), ste(method, VALID, RECOVERABLE_DEFINED, false, var)); - //assertDrop(method, - // ste(method, RECOVERABLE_DEFINED, DROPPED, false, null), - // ste(clazz, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, method)); - //assertDeclareFail("new C();", "compiler.err.cant.resolve.location"); + assertDrop(method, + ste(method, RECOVERABLE_DEFINED, DROPPED, true, null), + ste(clazz, VALID, RECOVERABLE_DEFINED, false, method)); + VarSnippet cc = varKey(assertEval("C c;")); + assertEvalUnresolvedException("new C();", "C", 1, 0); assertVariables(); assertMethods(); assertClasses(); assertActiveKeys(); + method = methodKey(assertEval("int mu() { return x * 4; }", + ste(MAIN_SNIPPET, DROPPED, RECOVERABLE_DEFINED, true, null), + ste(clazz, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); assertEval("int x = 10;", "10", - ste(var, DROPPED, VALID, true, null), + ste(MAIN_SNIPPET, DROPPED, VALID, true, null), ste(method, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)); PersistentSnippet c0 = varKey(assertEval("C c0 = new C();")); assertEval("c0.v();", "\"#40\""); - assertEval("C c = new C();"); + assertEval("C c = new C();", + ste(MAIN_SNIPPET, VALID, VALID, false, null), + ste(cc, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("c.v();", "\"#40\""); assertEval("int mu() { return x * 3; }", ste(MAIN_SNIPPET, VALID, VALID, false, null), @@ -144,9 +151,10 @@ public class DropTest extends KullaTesting { DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(x, VALID, DROPPED, true, null), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, x)); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "variable x"); - assertDeclareFail("new A().a;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, x)); + assertEval("A foo() { return null; }"); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable x"); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertVariables(); assertActiveKeys(); } @@ -158,9 +166,9 @@ public class DropTest extends KullaTesting { DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(x, VALID, DROPPED, true, null), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, x)); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "method x()"); - assertDeclareFail("new A().a;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, x)); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "method x()"); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertMethods(); assertActiveKeys(); } diff --git a/langtools/test/jdk/jshell/KullaTesting.java b/langtools/test/jdk/jshell/KullaTesting.java index c2ceeea1e06..0ea4a622499 100644 --- a/langtools/test/jdk/jshell/KullaTesting.java +++ b/langtools/test/jdk/jshell/KullaTesting.java @@ -191,14 +191,14 @@ public class KullaTesting { return key; } - public MethodSnippet assertEvalUnresolvedException(String input, String name, int unresolvedSize, int diagnosticsSize) { + public DeclarationSnippet assertEvalUnresolvedException(String input, String name, int unresolvedSize, int diagnosticsSize) { List events = assertEval(input, null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null); SnippetEvent ste = events.get(0); - MethodSnippet methodKey = ((UnresolvedReferenceException) ste.exception()).getMethodSnippet(); - assertEquals(methodKey.name(), name, "Given input: " + input + ", checking name"); - assertEquals(getState().unresolvedDependencies(methodKey).size(), unresolvedSize, "Given input: " + input + ", checking unresolved"); - assertEquals(getState().diagnostics(methodKey).size(), diagnosticsSize, "Given input: " + input + ", checking diagnostics"); - return methodKey; + DeclarationSnippet sn = ((UnresolvedReferenceException) ste.exception()).getSnippet(); + assertEquals(sn.name(), name, "Given input: " + input + ", checking name"); + assertEquals(getState().unresolvedDependencies(sn).size(), unresolvedSize, "Given input: " + input + ", checking unresolved"); + assertEquals(getState().diagnostics(sn).size(), diagnosticsSize, "Given input: " + input + ", checking diagnostics"); + return sn; } public Snippet assertKeyMatch(String input, boolean isExecutable, SubKind expectedSubKind, STEInfo mainInfo, STEInfo... updates) { diff --git a/langtools/test/jdk/jshell/ReplaceTest.java b/langtools/test/jdk/jshell/ReplaceTest.java index a26545da577..36b1c505cd4 100644 --- a/langtools/test/jdk/jshell/ReplaceTest.java +++ b/langtools/test/jdk/jshell/ReplaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -22,7 +22,7 @@ */ /* - * @test + * @test 8080069 * @summary Test of Snippet redefinition and replacement. * @build KullaTesting TestingInputStream * @run testng ReplaceTest @@ -30,6 +30,7 @@ import java.util.Collection; +import java.util.List; import jdk.jshell.Snippet; import jdk.jshell.MethodSnippet; import jdk.jshell.PersistentSnippet; @@ -38,9 +39,11 @@ import jdk.jshell.VarSnippet; import jdk.jshell.DeclarationSnippet; import org.testng.annotations.Test; +import jdk.jshell.SnippetEvent; +import jdk.jshell.UnresolvedReferenceException; +import static org.testng.Assert.assertEquals; import static jdk.jshell.Snippet.Status.*; import static jdk.jshell.Snippet.SubKind.*; -import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @Test @@ -259,7 +262,7 @@ public class ReplaceTest extends KullaTesting { ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET), ste(f, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)); - MethodSnippet exsn = assertEvalUnresolvedException("t();", "f", 0, 1); + DeclarationSnippet exsn = assertEvalUnresolvedException("t();", "f", 0, 1); assertTrue(exsn == f, "Identity must not change"); assertActiveKeys(); } @@ -289,13 +292,95 @@ public class ReplaceTest extends KullaTesting { } public void testForwardVarToClass() { - DeclarationSnippet a = classKey(assertEval("class A { int f() { return g; } }", added(RECOVERABLE_NOT_DEFINED))); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "variable g"); + DeclarationSnippet a = classKey(assertEval("class A { int f() { return g; } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g"); Snippet g = varKey(assertEval("int g = 10;", "10", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null))); + ste(a, RECOVERABLE_DEFINED, VALID, false, null))); assertEval("new A().f();", "10"); assertEval("double g = 10;", "10.0", null, + DiagCheck.DIAG_OK, + DiagCheck.DIAG_ERROR, + ste(MAIN_SNIPPET, VALID, VALID, true, null), + ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET), + ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)); + assertUnresolvedDependencies(a, 0); + assertActiveKeys(); + } + + public void testForwardVarToClassGeneric() { + DeclarationSnippet a = classKey(assertEval("class A { final T x; A(T v) { this.x = v; } ; T get() { return x; } int core() { return g; } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g"); + + List events = assertEval("A as = new A<>(\"hi\");", null, + UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null); + SnippetEvent ste = events.get(0); + Snippet assn = ste.snippet(); + DeclarationSnippet unsn = ((UnresolvedReferenceException) ste.exception()).getSnippet(); + assertEquals(unsn.name(), "A", "Wrong with unresolved"); + assertEquals(getState().unresolvedDependencies(unsn).size(), 1, "Wrong size unresolved"); + assertEquals(getState().diagnostics(unsn).size(), 0, "Expected no diagnostics"); + + Snippet g = varKey(assertEval("int g = 10;", "10", + added(VALID), + ste(a, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); + assertEval("A as = new A<>(\"low\");", + ste(MAIN_SNIPPET, VALID, VALID, false, null), + ste(assn, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); + assertEval("as.get();", "\"low\""); + assertUnresolvedDependencies(a, 0); + assertActiveKeys(); + } + + public void testForwardVarToClassExtendsImplements() { + DeclarationSnippet ik = classKey(assertEval("interface I { default int ii() { return 1; } }", added(VALID))); + DeclarationSnippet jk = classKey(assertEval("interface J { default int jj() { return 2; } }", added(VALID))); + DeclarationSnippet ck = classKey(assertEval("class C { int cc() { return 3; } }", added(VALID))); + DeclarationSnippet dk = classKey(assertEval("class D extends C implements I,J { int dd() { return g; } }", added(RECOVERABLE_DEFINED))); + DeclarationSnippet ek = classKey(assertEval("class E extends D { int ee() { return 5; } }", added(VALID))); + assertUnresolvedDependencies1(dk, RECOVERABLE_DEFINED, "variable g"); + assertEvalUnresolvedException("new D();", "D", 1, 0); + assertEvalUnresolvedException("new E();", "D", 1, 0); + VarSnippet g = varKey(assertEval("int g = 10;", "10", + added(VALID), + ste(dk, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); + assertEval("E e = new E();"); + assertDrop(g, + ste(g, VALID, DROPPED, true, null), + ste(dk, VALID, RECOVERABLE_DEFINED, false, g)); + assertEvalUnresolvedException("new D();", "D", 1, 0); + assertEvalUnresolvedException("new E();", "D", 1, 0); + assertEval("e.ee();", "5"); + assertEvalUnresolvedException("e.dd();", "D", 1, 0); + assertEval("e.cc();", "3"); + assertEval("e.jj();", "2"); + assertEval("e.ii();", "1"); + assertActiveKeys(); + } + + public void testForwardVarToInterface() { + DeclarationSnippet i = classKey(assertEval("interface I { default int f() { return x; } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(i, RECOVERABLE_DEFINED, "variable x"); + DeclarationSnippet c = classKey(assertEval("class C implements I { int z() { return 2; } }", added(VALID))); + assertEval("C c = new C();"); + assertEval("c.z();", "2"); + assertEvalUnresolvedException("c.f()", "I", 1, 0); + Snippet g = varKey(assertEval("int x = 55;", "55", + added(VALID), + ste(i, RECOVERABLE_DEFINED, VALID, false, null))); + assertEval("c.f();", "55"); + assertUnresolvedDependencies(i, 0); + assertActiveKeys(); + } + + public void testForwardVarToEnum() { + DeclarationSnippet a = classKey(assertEval("enum E { Q, W, E; float ff() { return fff; } }", added(RECOVERABLE_NOT_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "variable fff"); + Snippet g = varKey(assertEval("float fff = 4.5f;", "4.5", + added(VALID), + ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null))); + assertEval("E.Q.ff();", "4.5"); + assertEval("double fff = 3.3;", "3.3", null, DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(MAIN_SNIPPET, VALID, VALID, true, null), @@ -305,20 +390,21 @@ public class ReplaceTest extends KullaTesting { assertActiveKeys(); } - public void testForwardMethodToClass() { - DeclarationSnippet a = classKey(assertEval("class A { int f() { return g(); } }", added(RECOVERABLE_NOT_DEFINED))); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "method g()"); + DeclarationSnippet a = classKey(assertEval("class A { int f() { return g(); } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "method g()"); + assertEval("A foo() { return null; }"); + assertEvalUnresolvedException("new A();", "A", 1, 0); Snippet g = methodKey(assertEval("int g() { return 10; }", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null))); + ste(a, RECOVERABLE_DEFINED, VALID, false, null))); assertEval("new A().f();", "10"); assertEval("double g() { return 10; }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET)); + ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)); assertUnresolvedDependencies(a, 0); assertActiveKeys(); } @@ -336,8 +422,8 @@ public class ReplaceTest extends KullaTesting { DiagCheck.DIAG_ERROR, ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET)); - assertDeclareFail("new A().b;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, true, MAIN_SNIPPET)); + assertEvalUnresolvedException("new A().b;", "A", 0, 1); assertActiveKeys(); } @@ -503,42 +589,42 @@ public class ReplaceTest extends KullaTesting { public void testForwardSingleImportMethodToClass1() { PersistentSnippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.format;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("new A().s;", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET))); - assertDeclareFail("new A().s;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); } public void testForwardSingleImportMethodToClass2() { PersistentSnippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.format;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("new A().s();", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A().s();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); } public void testForwardSingleImportClassToClass1() { @@ -589,42 +675,44 @@ public class ReplaceTest extends KullaTesting { public void testForwardImportOnDemandMethodToClass1() { PersistentSnippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); - assertEval("new A().s;", "\"10\""); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); + assertEval("A x = new A();"); + assertEval("x.s;", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A().s;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); + assertEval("x.s;", "\"10\""); } public void testForwardImportOnDemandMethodToClass2() { PersistentSnippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("new A().s();", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A().s();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); } public void testForwardImportOnDemandClassToClass1() { @@ -673,86 +761,87 @@ public class ReplaceTest extends KullaTesting { public void testForwardSingleImportFieldToClass1() { PersistentSnippet a = classKey(assertEval("class A { static double pi() { return PI; } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.PI;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, false, list)); } public void testForwardSingleImportFieldToClass2() { PersistentSnippet a = classKey(assertEval("class A { static double pi = PI; }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.PI;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, true, null)); assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, true, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, true, list)); } public void testForwardImportOnDemandFieldToClass1() { PersistentSnippet a = classKey(assertEval("class A { static double pi() { return PI; } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, false, list)); } public void testForwardImportOnDemandFieldToClass2() { PersistentSnippet a = classKey(assertEval("class A { static double pi = PI; }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, true, null)); assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, true, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, true, list)); + assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true"); } public void testReplaceCausesMethodReferenceError() { From 0bca52a90883fa850b5e0018471ef317d3df387b Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Wed, 24 Feb 2016 15:31:36 -0800 Subject: [PATCH 111/311] 8149139: [javadoc] Modify Content to accept CharSequence Reviewed-by: jjg --- .../html/AbstractExecutableMemberWriter.java | 10 ++-- .../formats/html/AbstractMemberWriter.java | 24 +------- .../doclets/formats/html/ClassWriterImpl.java | 7 +-- .../html/ConstantsSummaryWriterImpl.java | 4 +- .../formats/html/HtmlDocletWriter.java | 60 +++++++++---------- .../doclets/formats/html/LinkInfoImpl.java | 2 +- .../formats/html/MethodWriterImpl.java | 5 +- .../formats/html/PackageIndexFrameWriter.java | 2 +- .../formats/html/PropertyWriterImpl.java | 2 +- .../formats/html/TagletWriterImpl.java | 3 +- .../doclets/formats/html/markup/Comment.java | 5 +- .../formats/html/markup/ContentBuilder.java | 6 +- .../doclets/formats/html/markup/DocType.java | 5 +- .../formats/html/markup/HtmlDocument.java | 5 +- .../doclets/formats/html/markup/HtmlTree.java | 3 +- .../formats/html/markup/HtmlWriter.java | 2 +- .../doclets/formats/html/markup/RawHtml.java | 11 ++-- .../formats/html/markup/StringContent.java | 8 +-- .../internal/doclets/toolkit/Content.java | 4 +- .../internal/doclets/toolkit/util/Utils.java | 6 +- 20 files changed, 79 insertions(+), 95 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java index d82da4653cd..44977bfb71a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java @@ -104,11 +104,11 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite sb.append(utils.getFullyQualifiedName(member)); if (!utils.isConstructor(member)) { sb.append("."); - sb.append(member.getSimpleName().toString()); + sb.append(member.getSimpleName()); } sb.append(utils.flatSignature((ExecutableElement) member)); - return writer.getDocLink(MEMBER, member, sb.toString()); + return writer.getDocLink(MEMBER, member, sb); } /** @@ -204,7 +204,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite htmltree.addContent("("); String sep = ""; List parameters = member.getParameters(); - String indent = makeSpace(indentSize + 1); + CharSequence indent = makeSpace(indentSize + 1); TypeMirror rcvrType = member.getReceiverType(); if (includeAnnotations && rcvrType != null && utils.isAnnotated(rcvrType)) { List annotationMirrors = rcvrType.getAnnotationMirrors(); @@ -260,7 +260,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite protected void addExceptions(ExecutableElement member, Content htmltree, int indentSize) { List exceptions = member.getThrownTypes(); if (!exceptions.isEmpty()) { - String indent = makeSpace(indentSize + 1 - 7); + CharSequence indent = makeSpace(indentSize + 1 - 7); htmltree.addContent(DocletConstants.NL); htmltree.addContent(indent); htmltree.addContent("throws "); @@ -336,7 +336,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite @Override @DefinedBy(Api.LANGUAGE_MODEL) protected Boolean defaultAction(TypeMirror e, Void p) { - buf.append(e.toString()); + buf.append(e); return foundTypeVariable; } }; diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java index aa04f515ea1..50f4c099807 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java @@ -223,26 +223,6 @@ public abstract class AbstractMemberWriter { htmltree.addContent(name); } - protected String typeString(Element member) { - return new SimpleElementVisitor9() { - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - public String visitExecutable(ExecutableElement e, Void p) { - return utils.isMethod(e) ? e.getReturnType().toString() : ""; - } - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - public String visitVariable(VariableElement e, Void p) { - return e.toString(); - } - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - protected String defaultAction(Element e, Void p) { - return ""; - } - }.visit(member); - } - /** * Add the modifier for the member. The modifiers are ordered as specified * by The Java Language Specification. @@ -282,7 +262,7 @@ public abstract class AbstractMemberWriter { } } - protected String makeSpace(int len) { + protected CharSequence makeSpace(int len) { if (len <= 0) { return ""; } @@ -290,7 +270,7 @@ public abstract class AbstractMemberWriter { for (int i = 0; i < len; i++) { sb.append(' '); } - return sb.toString(); + return sb; } /** diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java index 9356fb7f3c2..17efe9c9c52 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java @@ -199,8 +199,7 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, packageLabel); Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel); pkgNameDiv.addContent(getSpace()); - Content pkgNameContent = getPackageLink(pkg, - new StringContent(pkg.getQualifiedName().toString())); + Content pkgNameContent = getPackageLink(pkg, new StringContent(pkg.getQualifiedName())); pkgNameDiv.addContent(pkgNameContent); div.addContent(pkgNameDiv); } @@ -395,10 +394,10 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE, typeElement)); if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) { - li.addContent(utils.asTypeElement(type).getSimpleName().toString()); + li.addContent(utils.asTypeElement(type).getSimpleName()); li.addContent(typeParameters); } else { - li.addContent(utils.asTypeElement(type).getQualifiedName().toString()); + li.addContent(utils.asTypeElement(type).getQualifiedName()); li.addContent(typeParameters); } } else { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java index 2b993595998..70f4a0fdd5a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java @@ -244,7 +244,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons PackageElement enclosingPackage = utils.containingPackage(typeElement); if (!enclosingPackage.isUnnamed()) { Content cb = new ContentBuilder(); - cb.addContent(enclosingPackage.getQualifiedName().toString()); + cb.addContent(enclosingPackage.getQualifiedName()); cb.addContent("."); cb.addContent(classlink); return getClassName(cb); @@ -332,7 +332,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons */ private Content getNameColumn(VariableElement member) { Content nameContent = getDocLink(LinkInfoImpl.Kind.CONSTANT_SUMMARY, - member, member.getSimpleName().toString(), false); + member, member.getSimpleName(), false); Content code = HtmlTree.CODE(nameContent); return HtmlTree.TD(code); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index c5daf0fa50b..294bc605891 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -166,6 +166,8 @@ public class HtmlDocletWriter extends HtmlDocWriter { HtmlTree fixedNavDiv = new HtmlTree(HtmlTag.DIV); + final static Pattern IMPROPER_HTML_CHARS = Pattern.compile(".*[&<>].*"); + /** * Constructor to construct the HtmlStandardWriter object. * @@ -945,7 +947,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { public Content getPackageName(PackageElement packageElement) { return packageElement == null || packageElement.isUnnamed() ? defaultPackageLabel - : getPackageLabel(packageElement.getQualifiedName().toString()); + : getPackageLabel(packageElement.getQualifiedName()); } /** @@ -954,7 +956,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param packageName the package name * @return the package name content */ - public Content getPackageLabel(String packageName) { + public Content getPackageLabel(CharSequence packageName) { return new StringContent(packageName); } @@ -1038,7 +1040,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param label the label for the link. * @return a content tree for the package link. */ - public Content getPackageLink(PackageElement packageElement, String label) { + public Content getPackageLink(PackageElement packageElement, CharSequence label) { return getPackageLink(packageElement, new StringContent(label)); } @@ -1081,7 +1083,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { public Content interfaceName(TypeElement typeElement, boolean qual) { Content name = new StringContent((qual) - ? typeElement.getQualifiedName().toString() + ? typeElement.getQualifiedName() : utils.getSimpleName(typeElement)); return (utils.isInterface(typeElement)) ? HtmlTree.SPAN(HtmlStyle.interfaceName, name) : name; } @@ -1279,7 +1281,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param label the label for the link * @return a content tree for the element link */ - public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label) { + public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label) { return getDocLink(context, utils.getEnclosingTypeElement(element), element, new StringContent(label)); } @@ -1293,7 +1295,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param strong true if the link should be strong. * @return the link for the given member. */ - public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label, + public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label, boolean strong) { return getDocLink(context, utils.getEnclosingTypeElement(element), element, label, strong); } @@ -1311,7 +1313,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @return the link for the given member. */ public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, - String label, boolean strong) { + CharSequence label, boolean strong) { return getDocLink(context, typeElement, element, label, strong, false); } @@ -1334,13 +1336,14 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @return the link for the given member. */ public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, - String label, boolean strong, boolean isProperty) { + CharSequence label, boolean strong, boolean isProperty) { return getDocLink(context, typeElement, element, new StringContent(check(label)), strong, isProperty); } - String check(String s) { - if (s.matches(".*[&<>].*")) { - throw new IllegalArgumentException(s); + CharSequence check(CharSequence s) { + Matcher m = IMPROPER_HTML_CHARS.matcher(s); + if (m.matches()) { + throw new IllegalArgumentException(s.toString()); } return s; } @@ -1426,7 +1429,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { CommentHelper ch = utils.getCommentHelper(element); String tagName = ch.getTagName(see); - String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see))); + String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see)).toString()); // Check if @see is an href or "string" if (seetext.startsWith("<") || seetext.startsWith("\"")) { return new RawHtml(seetext); @@ -1452,7 +1455,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { //@see is referencing an included package if (label.isEmpty()) label = plainOrCode(isLinkPlain, - new StringContent(refPackage.getQualifiedName().toString())); + new StringContent(refPackage.getQualifiedName())); return getPackageLink(refPackage, label); } else { // @see is not referencing an included class or package. Check for cross links. @@ -1695,7 +1698,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { final Content result = new ContentBuilder() { @Override - public void addContent(String text) { + public void addContent(CharSequence text) { super.addContent(utils.normalizeNewlines(text)); } }; @@ -1741,7 +1744,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { public Boolean visitAttribute(AttributeTree node, Content c) { StringBuilder sb = new StringBuilder(SPACER).append(node.getName()); if (node.getValueKind() == ValueKind.EMPTY) { - result.addContent(sb.toString()); + result.addContent(sb); return false; } sb.append("="); @@ -1758,7 +1761,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { break; } sb.append(quote); - result.addContent(sb.toString()); + result.addContent(sb); Content docRootContent = new ContentBuilder(); for (DocTree dt : node.getValue()) { @@ -1767,16 +1770,15 @@ public class HtmlDocletWriter extends HtmlDocWriter { if (text.startsWith("/..") && !configuration.docrootparent.isEmpty()) { result.addContent(configuration.docrootparent); docRootContent = new ContentBuilder(); - text = textCleanup(text.substring(3), isLast(node)); + result.addContent(textCleanup(text.substring(3), isLast(node))); } else { if (!docRootContent.isEmpty()) { docRootContent = copyDocRootContent(docRootContent); } else { text = redirectRelativeLinks(element, (TextTree) dt); } - text = textCleanup(text, isLast(node)); + result.addContent(textCleanup(text, isLast(node))); } - result.addContent(text); } else { docRootContent = copyDocRootContent(docRootContent); dt.accept(this, docRootContent); @@ -1889,8 +1891,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { @Override @DefinedBy(Api.COMPILER_TREE) public Boolean visitStartElement(StartElementTree node, Content c) { String text = "<" + node.getName(); - text = utils.normalizeNewlines(text); - RawHtml rawHtml = new RawHtml(text); + RawHtml rawHtml = new RawHtml(utils.normalizeNewlines(text)); result.addContent(rawHtml); for (DocTree dt : node.getAttributes()) { @@ -1900,11 +1901,11 @@ public class HtmlDocletWriter extends HtmlDocWriter { return false; } - private String textCleanup(String text, boolean isLast) { + private CharSequence textCleanup(String text, boolean isLast) { return textCleanup(text, isLast, false); } - private String textCleanup(String text, boolean isLast, boolean trimLeader) { + private CharSequence textCleanup(String text, boolean isLast, boolean trimLeader) { if (trimLeader) { text = removeLeadingWhitespace(text); } @@ -1912,16 +1913,14 @@ public class HtmlDocletWriter extends HtmlDocWriter { text = removeTrailingWhitespace(text); } text = utils.replaceTabs(text); - text = utils.normalizeNewlines(text); - return text; + return utils.normalizeNewlines(text); } @Override @DefinedBy(Api.COMPILER_TREE) public Boolean visitText(TextTree node, Content c) { String text = node.getBody(); - text = textCleanup(text, isLast(node), commentRemoved); + result.addContent(new RawHtml(textCleanup(text, isLast(node), commentRemoved))); commentRemoved = false; - result.addContent(new RawHtml(text)); return false; } @@ -2358,7 +2357,8 @@ public class HtmlDocletWriter extends HtmlDocWriter { private void addAnnotations(TypeElement annotationDoc, LinkInfoImpl linkInfo, ContentBuilder annotation, Mapmap, int indent, boolean linkBreak) { - linkInfo.label = new StringContent("@" + annotationDoc.getSimpleName().toString()); + linkInfo.label = new StringContent("@"); + linkInfo.label.addContent(annotationDoc.getSimpleName()); annotation.addContent(getLink(linkInfo)); if (!map.isEmpty()) { annotation.addContent("("); @@ -2372,7 +2372,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { annotation.addContent(","); if (linkBreak) { annotation.addContent(DocletConstants.NL); - int spaces = annotationDoc.getSimpleName().toString().length() + 2; + int spaces = annotationDoc.getSimpleName().length() + 2; for (int k = 0; k < (spaces + indent); k++) { annotation.addContent(" "); } @@ -2496,7 +2496,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { @Override @DefinedBy(Api.LANGUAGE_MODEL) public Content visitEnumConstant(VariableElement c, Void p) { return getDocLink(LinkInfoImpl.Kind.ANNOTATION, - c, c.getSimpleName().toString(), false); + c, c.getSimpleName(), false); } @Override @DefinedBy(Api.LANGUAGE_MODEL) public Content visitArray(List vals, Void p) { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java index 01cd9508a1a..30801a6bbc9 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java @@ -294,7 +294,7 @@ public class LinkInfoImpl extends LinkInfo { * Set the label for the link. * @param label plain-text label for the link */ - public LinkInfoImpl label(String label) { + public LinkInfoImpl label(CharSequence label) { this.label = new StringContent(label); return this; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java index 40b00cdd1fd..68648d4aaaa 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java @@ -356,11 +356,10 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter Content overriddenTypeLink = writer.getLink(new LinkInfoImpl(writer.configuration, context, overriddenType)); Content codeOverridenTypeLink = HtmlTree.CODE(overriddenTypeLink); - String name = method.getSimpleName().toString(); Content methlink = writer.getLink( new LinkInfoImpl(writer.configuration, LinkInfoImpl.Kind.MEMBER, holder) - .where(writer.getName(writer.getAnchor(method))).label(name)); + .where(writer.getName(writer.getAnchor(method))).label(method.getSimpleName())); Content codeMethLink = HtmlTree.CODE(methlink); Content dd = HtmlTree.DD(codeMethLink); dd.addContent(writer.getSpace()); @@ -395,7 +394,7 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter dl.addContent(dt); Content methlink = writer.getDocLink( LinkInfoImpl.Kind.MEMBER, implementedMeth, - implementedMeth.getSimpleName().toString(), false); + implementedMeth.getSimpleName(), false); Content codeMethLink = HtmlTree.CODE(methlink); Content dd = HtmlTree.DD(codeMethLink); dd.addContent(writer.getSpace()); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java index 064a93ce9d2..94170a334fb 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java @@ -123,7 +123,7 @@ public class PackageIndexFrameWriter extends AbstractPackageIndexWriter { packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME, packageLabel, "", "packageFrame"); } else { - packageLabel = getPackageLabel(pe.getQualifiedName().toString()); + packageLabel = getPackageLabel(pe.getQualifiedName()); packageLinkContent = getHyperLink(pathString(pe, DocPaths.PACKAGE_FRAME), packageLabel, "", "packageFrame"); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java index 3a1eebc23cf..9b7ca5da8ed 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java @@ -158,7 +158,7 @@ public class PropertyWriterImpl extends AbstractMemberWriter writer.getDocLink(LinkInfoImpl.Kind.PROPERTY_COPY, holder, property, utils.isIncluded(holder) - ? holder.toString() : utils.getFullyQualifiedName(holder), + ? holder.getSimpleName() : holder.getQualifiedName(), false); Content codeLink = HtmlTree.CODE(link); Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel, diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java index 1ae644233b2..80a4cccf532 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java @@ -91,8 +91,7 @@ public class TagletWriterImpl extends TagletWriter { */ protected Content codeTagOutput(Element element, DocTree tag) { CommentHelper ch = utils.getCommentHelper(element); - String str = utils.normalizeNewlines(ch.getText(tag)); - StringContent content = new StringContent(str); + StringContent content = new StringContent(utils.normalizeNewlines(ch.getText(tag))); Content result = HtmlTree.CODE(content); return result; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java index 0adfc088106..32c5cc6c5b3 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -75,7 +75,8 @@ public class Comment extends Content { * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java index 64ceef82473..e4a9265cbbd 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -50,8 +50,8 @@ public class ContentBuilder extends Content { } @Override - public void addContent(String text) { - if (text.isEmpty()) + public void addContent(CharSequence text) { + if (text.length() == 0) return; ensureMutableContents(); Content c = contents.isEmpty() ? null : contents.get(contents.size() - 1); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java index 469ee40743f..cd6739d3f1f 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -89,7 +89,8 @@ public class DocType extends Content { * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java index 8f995c7c772..73da0086ab1 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -90,7 +90,8 @@ public class HtmlDocument extends Content { * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java index 93b9071dcf7..a3a40f4391e 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java @@ -132,7 +132,8 @@ public class HtmlTree extends Content { * * @param stringContent string content that needs to be added */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { if (!content.isEmpty()) { Content lastContent = content.get(content.size() - 1); if (lastContent instanceof StringContent) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java index 88c93108672..dce9fd720a7 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java @@ -475,7 +475,7 @@ public class HtmlWriter { addStyles(HtmlStyle.rowColor, vars); addStyles(HtmlStyle.tableTab, vars); addStyles(HtmlStyle.activeTableTab, vars); - script.addContent(new RawHtml(vars.toString())); + script.addContent(new RawHtml(vars)); } /** diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java index fe425dd743a..ca621a4c75a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -53,8 +53,8 @@ public class RawHtml extends Content { * * @param rawHtml raw HTML text to be added */ - public RawHtml(String rawHtml) { - rawHtmlContent = nullCheck(rawHtml); + public RawHtml(CharSequence rawHtml) { + rawHtmlContent = rawHtml.toString(); } /** @@ -77,7 +77,8 @@ public class RawHtml extends Content { * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } @@ -103,7 +104,7 @@ public class RawHtml extends Content { return charCount(rawHtmlContent); } - static int charCount(String htmlText) { + static int charCount(CharSequence htmlText) { State state = State.TEXT; int count = 0; for (int i = 0; i < htmlText.length(); i++) { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java index 6b7c7dde2ed..cececf6b991 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -58,7 +58,7 @@ public class StringContent extends Content { * * @param initialContent initial content for the object */ - public StringContent(String initialContent) { + public StringContent(CharSequence initialContent) { stringContent = new StringBuilder(); appendChars(initialContent); } @@ -83,7 +83,7 @@ public class StringContent extends Content { * @param strContent string content to be added */ @Override - public void addContent(String strContent) { + public void addContent(CharSequence strContent) { appendChars(strContent); } @@ -118,7 +118,7 @@ public class StringContent extends Content { return s.endsWith(DocletConstants.NL); } - private void appendChars(String s) { + private void appendChars(CharSequence s) { for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); switch (ch) { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java index 3d2e664a3e0..7efd4250504 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -74,7 +74,7 @@ public abstract class Content { * * @param stringContent the string content to be added */ - public abstract void addContent(String stringContent); + public abstract void addContent(CharSequence stringContent); /** * Writes content to a writer. diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index 5914a2e6013..fa2c90f1efe 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1356,7 +1356,7 @@ public class Utils { return result.toString(); } - public String normalizeNewlines(String text) { + public CharSequence normalizeNewlines(CharSequence text) { StringBuilder sb = new StringBuilder(); final int textLength = text.length(); final String NL = DocletConstants.NL; @@ -1379,7 +1379,7 @@ public class Utils { } } sb.append(text, pos, textLength); - return sb.toString(); + return sb; } /** @@ -1746,6 +1746,8 @@ public class Utils { * A generic utility which returns the fully qualified names of an entity, * if the entity is not qualifiable then its enclosing entity, it is upto * the caller to add the elements name as required. + * @param e the element to get FQN for. + * @return the name */ public String getFullyQualifiedName(Element e) { return getFullyQualifiedName(e, true); From 42867443a4bd204e6adb92ddea0fb62a795d3ee7 Mon Sep 17 00:00:00 2001 From: Ajit Ghaisas Date: Thu, 25 Feb 2016 10:22:22 +0530 Subject: [PATCH 112/311] 8020039: SynthTableHeaderUI refers to possibly null parameter in cell renderer Reviewed-by: rchamyal, serb --- .../com/apple/laf/AquaTableHeaderUI.java | 15 +++--- .../swing/plaf/synth/SynthTableHeaderUI.java | 3 +- .../TableHeaderRendererExceptionTest.java | 53 +++++++++++++++++++ 3 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 jdk/test/javax/swing/JTableHeader/8020039/TableHeaderRendererExceptionTest.java diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java index 2dec5c895eb..35b87aac27e 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java @@ -128,14 +128,17 @@ public class AquaTableHeaderUI extends BasicTableHeaderUI { // Modify the table "border" to draw smaller, and with the titles in the right position // and sort indicators, just like an NSSave/Open panel. final AquaTableHeaderBorder cellBorder = AquaTableHeaderBorder.getListHeaderBorder(); - final boolean thisColumnSelected = localTable.getColumnModel().getColumn(column).getModelIndex() == sortColumn; + cellBorder.setSortOrder(AquaTableHeaderBorder.SORT_NONE); - cellBorder.setSelected(thisColumnSelected); - if (thisColumnSelected) { - cellBorder.setSortOrder(sortOrder); - } else { - cellBorder.setSortOrder(AquaTableHeaderBorder.SORT_NONE); + if (localTable != null) { + final boolean thisColumnSelected = localTable.getColumnModel().getColumn(column).getModelIndex() == sortColumn; + + cellBorder.setSelected(thisColumnSelected); + if (thisColumnSelected) { + cellBorder.setSortOrder(sortOrder); + } } + setBorder(cellBorder); return this; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java index 904172fa049..16272ffa819 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java @@ -230,9 +230,10 @@ public class SynthTableHeaderUI extends BasicTableHeaderUI boolean hasRollover = (column == getRolloverColumn()); if (isSelected || hasRollover || hasFocus) { + boolean enabled = (table == null)? true : table.isEnabled(); SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel. getUIOfType(getUI(), SynthLabelUI.class), - isSelected, hasFocus, table.isEnabled(), + isSelected, hasFocus, enabled, hasRollover); } else { SynthLookAndFeel.resetSelectedUI(); diff --git a/jdk/test/javax/swing/JTableHeader/8020039/TableHeaderRendererExceptionTest.java b/jdk/test/javax/swing/JTableHeader/8020039/TableHeaderRendererExceptionTest.java new file mode 100644 index 00000000000..54ac5fd2619 --- /dev/null +++ b/jdk/test/javax/swing/JTableHeader/8020039/TableHeaderRendererExceptionTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, 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 javax.swing.UIManager; +import javax.swing.table.JTableHeader; + +/** + * @test + * @summary Tests whether getTableCellRendererComponent() method handles + * null table parameter + * @bug 8020039 + * @run main TableHeaderRendererExceptionTest + */ +public class TableHeaderRendererExceptionTest { + + public static void main(String[] args) throws Throwable { + //Execute test for all supported look and feels + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + String lookAndFeelString = lookAndFeelItem.getClassName(); + + UIManager.setLookAndFeel(lookAndFeelString); + + // Test getTableCellRendererComponent method by passing null table + JTableHeader header = new JTableHeader(); + + header.getDefaultRenderer().getTableCellRendererComponent(null, + " test ", true, true, -1, 0); + } + } +} From a9a432a1a1774056ff85e01d34fd1e4c398a5ce2 Mon Sep 17 00:00:00 2001 From: Shafi Ahmad Date: Thu, 25 Feb 2016 11:27:13 +0530 Subject: [PATCH 113/311] 8150002: Check for the validity of oop before printing it in verify_remembered_set Adding missing check for valid oop. Reviewed-by: dcubed --- hotspot/src/share/vm/gc/g1/heapRegion.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.cpp b/hotspot/src/share/vm/gc/g1/heapRegion.cpp index 1c332adcdf1..42cb7d5928a 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp @@ -781,7 +781,9 @@ public: ResourceMark rm; _containing_obj->print_on(log.error_stream()); log.error("points to obj " PTR_FORMAT " in region " HR_FORMAT, p2i(obj), HR_FORMAT_PARAMS(to)); - obj->print_on(log.error_stream()); + if (obj->is_oop()) { + obj->print_on(log.error_stream()); + } log.error("Obj head CTE = %d, field CTE = %d.", cv_obj, cv_field); log.error("----------"); _failures = true; From 451cd91ea9c7aedacf58eb8eaee19d138cb1a4b0 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Thu, 25 Feb 2016 13:56:23 +0530 Subject: [PATCH 114/311] 8148379: jdk.nashorn.api.scripting spec. adjustments, clarifications Reviewed-by: hannesw, mhaupt --- nashorn/make/build.xml | 4 + nashorn/make/project.properties | 2 + .../api/scripting/AbstractJSObject.java | 100 +++++------------- .../jdk/nashorn/api/scripting/JSObject.java | 7 +- .../api/scripting/NashornException.java | 8 +- .../scripting/NashornScriptEngineFactory.java | 10 +- .../api/scripting/ScriptObjectMirror.java | 27 +++-- .../nashorn/api/scripting/ScriptUtils.java | 27 ++++- nashorn/test/script/basic/JDK-8026367.js | 2 + 9 files changed, 85 insertions(+), 102 deletions(-) diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index 5092b958692..dff7478f6f1 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -242,6 +242,7 @@ + @@ -261,6 +262,7 @@ + @@ -276,6 +278,7 @@ + @@ -289,6 +292,7 @@ + diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties index 6b3551065bc..fbaca210b7e 100644 --- a/nashorn/make/project.properties +++ b/nashorn/make/project.properties @@ -34,6 +34,8 @@ build.compiler=modern javac.source=1.8 javac.target=1.8 +javadoc.option=-tag "implSpec:a:Implementation Requirements:" + # nashorn version information nashorn.version=0.1 nashorn.fullversion=0.1 diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java index ce2c18811ca..0d5bf7157ee 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java @@ -27,6 +27,7 @@ package jdk.nashorn.api.scripting; import java.util.Collection; import java.util.Collections; +import java.util.Objects; import java.util.Set; /** @@ -34,19 +35,19 @@ import java.util.Set; * * This class can also be subclassed by an arbitrary Java class. Nashorn will * treat objects of such classes just like nashorn script objects. Usual nashorn - * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued + * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be delegated * to appropriate method call of this class. * * @since 1.8u40 */ public abstract class AbstractJSObject implements JSObject { /** - * Call this object as a JavaScript function. This is equivalent to - * 'func.apply(thiz, args)' in JavaScript. - * - * @param thiz 'this' object to be passed to the function - * @param args arguments to method - * @return result of call + * The default constructor. + */ + public AbstractJSObject() {} + + /** + * @implSpec This implementation always throws UnsupportedOperationException */ @Override public Object call(final Object thiz, final Object... args) { @@ -54,11 +55,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Call this 'constructor' JavaScript function to create a new object. - * This is equivalent to 'new func(arg1, arg2...)' in JavaScript. - * - * @param args arguments to method - * @return result of constructor call + * @implSpec This implementation always throws UnsupportedOperationException */ @Override public Object newObject(final Object... args) { @@ -66,10 +63,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Evaluate a JavaScript expression. - * - * @param s JavaScript expression to evaluate - * @return evaluation result + * @implSpec This imlementation always throws UnsupportedOperationException */ @Override public Object eval(final String s) { @@ -77,21 +71,16 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Retrieves a named member of this JavaScript object. - * - * @param name of member - * @return member + * @implSpec This implementation always returns null */ @Override public Object getMember(final String name) { + Objects.requireNonNull(name); return null; } /** - * Retrieves an indexed member of this JavaScript object. - * - * @param index index slot to retrieve - * @return member + * @implSpec This implementation always returns null */ @Override public Object getSlot(final int index) { @@ -99,21 +88,16 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Does this object have a named member? - * - * @param name name of member - * @return true if this object has a member of the given name + * @implSpec This implementation always returns false */ @Override public boolean hasMember(final String name) { + Objects.requireNonNull(name); return false; } /** - * Does this object have a indexed property? - * - * @param slot index to check - * @return true if this object has a slot + * @implSpec This implementation always returns false */ @Override public boolean hasSlot(final int slot) { @@ -121,31 +105,25 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Remove a named member from this JavaScript object - * - * @param name name of the member + * @implSpec This implementation is a no-op */ @Override public void removeMember(final String name) { + Objects.requireNonNull(name); //empty } /** - * Set a named member in this JavaScript object - * - * @param name name of the member - * @param value value of the member + * @implSpec This implementation is a no-op */ @Override public void setMember(final String name, final Object value) { + Objects.requireNonNull(name); //empty } /** - * Set an indexed member in this JavaScript object - * - * @param index index of the member slot - * @param value value of the member + * @implSpec This implementation is a no-op */ @Override public void setSlot(final int index, final Object value) { @@ -155,9 +133,7 @@ public abstract class AbstractJSObject implements JSObject { // property and value iteration /** - * Returns the set of all property names of this object. - * - * @return set of property names + * @implSpec This implementation returns empty set */ @Override public Set keySet() { @@ -165,9 +141,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Returns the set of all property values of this object. - * - * @return set of property values. + * @implSpec This implementation returns empty set */ @Override public Collection values() { @@ -177,22 +151,13 @@ public abstract class AbstractJSObject implements JSObject { // JavaScript instanceof check /** - * Checking whether the given object is an instance of 'this' object. - * - * @param instance instance to check - * @return true if the given 'instance' is an instance of this 'function' object + * @implSpec This implementation always returns false */ @Override public boolean isInstance(final Object instance) { return false; } - /** - * Checking whether this object is an instance of the given 'clazz' object. - * - * @param clazz clazz to check - * @return true if this object is an instance of the given 'clazz' - */ @Override public boolean isInstanceOf(final Object clazz) { if (clazz instanceof JSObject) { @@ -202,20 +167,13 @@ public abstract class AbstractJSObject implements JSObject { return false; } - /** - * ECMA [[Class]] property - * - * @return ECMA [[Class]] property value of this object - */ @Override public String getClassName() { return getClass().getName(); } /** - * Is this a function object? - * - * @return if this mirror wraps a ECMAScript function instance + * @implSpec This implementation always returns false */ @Override public boolean isFunction() { @@ -223,9 +181,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Is this a 'use strict' function object? - * - * @return true if this mirror represents a ECMAScript 'use strict' function + * @implSpec This implementation always returns false */ @Override public boolean isStrictFunction() { @@ -233,9 +189,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Is this an array object? - * - * @return if this mirror wraps a ECMAScript array object + * @implSpec This implementation always returns false */ @Override public boolean isArray() { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java index 8545bf79665..afbb0a21363 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java @@ -32,7 +32,7 @@ import jdk.nashorn.internal.runtime.JSType; /** * This interface can be implemented by an arbitrary Java class. Nashorn will * treat objects of such classes just like nashorn script objects. Usual nashorn - * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued + * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be delegated * to appropriate method call of this interface. * * @since 1.8u40 @@ -42,7 +42,7 @@ public interface JSObject { * Call this object as a JavaScript function. This is equivalent to * 'func.apply(thiz, args)' in JavaScript. * - * @param thiz 'this' object to be passed to the function + * @param thiz 'this' object to be passed to the function. This may be null. * @param args arguments to method * @return result of call */ @@ -70,6 +70,7 @@ public interface JSObject { * * @param name of member * @return member + * @throws NullPointerException if name is null */ public Object getMember(final String name); @@ -101,6 +102,7 @@ public interface JSObject { * Remove a named member from this JavaScript object * * @param name name of the member + * @throws NullPointerException if name is null */ public void removeMember(final String name); @@ -109,6 +111,7 @@ public interface JSObject { * * @param name name of the member * @param value value of the member + * @throws NullPointerException if name is null */ public void setMember(final String name, final Object value); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java index 1f7631d332d..fc1a7464df0 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java @@ -46,6 +46,8 @@ import jdk.nashorn.internal.runtime.ScriptObject; */ @SuppressWarnings("serial") public abstract class NashornException extends RuntimeException { + private static final long serialVersionUID = 1L; + // script file name private String fileName; // script line number @@ -58,7 +60,7 @@ public abstract class NashornException extends RuntimeException { private Object ecmaError; /** - * Constructor + * Constructor to initialize error message, file name, line and column numbers. * * @param msg exception message * @param fileName file name @@ -70,7 +72,7 @@ public abstract class NashornException extends RuntimeException { } /** - * Constructor + * Constructor to initialize error message, cause exception, file name, line and column numbers. * * @param msg exception message * @param cause exception cause @@ -86,7 +88,7 @@ public abstract class NashornException extends RuntimeException { } /** - * Constructor + * Constructor to initialize error message and cause exception. * * @param msg exception message * @param cause exception cause diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java index f05b7070471..2012bf12600 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java @@ -154,7 +154,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given class loader. + * Create a new Script engine initialized with the given class loader. * * @param appLoader class loader to be used as script "app" class loader. * @return newly created script engine. @@ -167,7 +167,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given class filter. + * Create a new Script engine initialized with the given class filter. * * @param classFilter class filter to use. * @return newly created script engine. @@ -181,7 +181,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given arguments. + * Create a new Script engine initialized with the given arguments. * * @param args arguments array passed to script engine. * @return newly created script engine. @@ -195,7 +195,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given arguments. + * Create a new Script engine initialized with the given arguments and the given class loader. * * @param args arguments array passed to script engine. * @param appLoader class loader to be used as script "app" class loader. @@ -210,7 +210,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given arguments. + * Create a new Script engine initialized with the given arguments, class loader and class filter. * * @param args arguments array passed to script engine. * @param appLoader class loader to be used as script "app" class loader. diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java index ea2f51f1e7c..8d7fe11bea6 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java @@ -287,22 +287,21 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin }); } - @Override - public boolean isInstance(final Object obj) { - if (! (obj instanceof ScriptObjectMirror)) { + public boolean isInstance(final Object instance) { + if (! (instance instanceof ScriptObjectMirror)) { return false; } - final ScriptObjectMirror instance = (ScriptObjectMirror)obj; + final ScriptObjectMirror mirror = (ScriptObjectMirror)instance; // if not belongs to my global scope, return false - if (global != instance.global) { + if (global != mirror.global) { return false; } return inGlobal(new Callable() { @Override public Boolean call() { - return sobj.isInstance(instance.sobj); + return sobj.isInstance(mirror.sobj); } }); } @@ -653,10 +652,10 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin } /** - * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. + * Make a script object mirror on given object if needed. * * @param obj object to be wrapped/converted - * @param homeGlobal global to which this object belongs. Not used for ConsStrings. + * @param homeGlobal global to which this object belongs. * @return wrapped/converted object */ public static Object wrap(final Object obj, final Object homeGlobal) { @@ -664,13 +663,13 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin } /** - * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. The - * created wrapper will implement the Java {@code List} interface if {@code obj} is a JavaScript - * {@code Array} object; this is compatible with Java JSON libraries expectations. Arrays retrieved through its + * Make a script object mirror on given object if needed. The created wrapper will implement + * the Java {@code List} interface if {@code obj} is a JavaScript {@code Array} object; + * this is compatible with Java JSON libraries expectations. Arrays retrieved through its * properties (transitively) will also implement the list interface. * * @param obj object to be wrapped/converted - * @param homeGlobal global to which this object belongs. Not used for ConsStrings. + * @param homeGlobal global to which this object belongs. * @return wrapped/converted object */ public static Object wrapAsJSONCompatible(final Object obj, final Object homeGlobal) { @@ -678,10 +677,10 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin } /** - * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. + * Make a script object mirror on given object if needed. * * @param obj object to be wrapped/converted - * @param homeGlobal global to which this object belongs. Not used for ConsStrings. + * @param homeGlobal global to which this object belongs. * @param jsonCompatible if true, the created wrapper will implement the Java {@code List} interface if * {@code obj} is a JavaScript {@code Array} object. Arrays retrieved through its properties (transitively) * will also implement the list interface. diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java index 367efa56591..e824cceb1c5 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java @@ -74,9 +74,15 @@ public final class ScriptUtils { * @param func the function to wrap * @param sync the object to synchronize on * @return a synchronizing wrapper function + * @throws IllegalArgumentException if func does not represent a script function */ - public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) { - return func.createSynchronized(unwrap(sync)); + public static Object makeSynchronizedFunction(final Object func, final Object sync) { + final Object unwrapped = unwrap(func); + if (unwrapped instanceof ScriptFunction) { + return ((ScriptFunction)unwrapped).createSynchronized(unwrap(sync)); + } + + throw new IllegalArgumentException(); } /** @@ -84,9 +90,19 @@ public final class ScriptUtils { * * @param obj object to be wrapped * @return wrapped object + * @throws IllegalArgumentException if obj cannot be wrapped */ - public static ScriptObjectMirror wrap(final ScriptObject obj) { - return (ScriptObjectMirror) ScriptObjectMirror.wrap(obj, Context.getGlobal()); + public static ScriptObjectMirror wrap(final Object obj) { + if (obj instanceof ScriptObjectMirror) { + return (ScriptObjectMirror)obj; + } + + if (obj instanceof ScriptObject) { + final ScriptObject sobj = (ScriptObject)obj; + return (ScriptObjectMirror) ScriptObjectMirror.wrap(sobj, Context.getGlobal()); + } + + throw new IllegalArgumentException(); } /** @@ -135,7 +151,8 @@ public final class ScriptUtils { * Convert the given object to the given type. * * @param obj object to be converted - * @param type destination type to convert to + * @param type destination type to convert to. type is either a Class + * or nashorn representation of a Java type returned by Java.type() call in script. * @return converted object */ public static Object convert(final Object obj, final Object type) { diff --git a/nashorn/test/script/basic/JDK-8026367.js b/nashorn/test/script/basic/JDK-8026367.js index 0b14ecfe481..6d498c1fe7c 100644 --- a/nashorn/test/script/basic/JDK-8026367.js +++ b/nashorn/test/script/basic/JDK-8026367.js @@ -37,10 +37,12 @@ var obj = { // Sync called with one argument will synchronize on this-object of invocation inc: sync(function(d) { this.count += d; + Assert.assertTrue(java.lang.Thread.holdsLock(this)); }), // Pass explicit object to synchronize on as second argument dec: sync(function(d) { this.count -= d; + Assert.assertTrue(java.lang.Thread.holdsLock(obj)); }, obj) }; From be1f49a6fdc3252f91763eb701b64d4c4b457ca5 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Thu, 25 Feb 2016 10:43:04 +0100 Subject: [PATCH 115/311] 8148159: [TESTBUG] TestCompilerDirectivesCompatibility tests fails on non-tiered server VMs Add whitebox for checking available compilers Reviewed-by: kvn --- test/lib/sun/hotspot/WhiteBox.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index 9964831c3c9..668d2f00c1a 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -207,7 +207,7 @@ public class WhiteBox { // Compiler public native int matchesMethod(Executable method, String pattern); public native int matchesInline(Executable method, String pattern); - public native boolean shouldPrintAssembly(Executable method); + public native boolean shouldPrintAssembly(Executable method, int comp_level); public native int deoptimizeFrames(boolean makeNotEntrant); public native void deoptimizeAll(); From 167ce92545929e1afd69eb29306cbbf40d04ecb5 Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Thu, 25 Feb 2016 11:20:03 +0100 Subject: [PATCH 116/311] 8150390: Move rs length sampling data to the sampling thread Reviewed-by: drwhite, jwilhelm --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 7 +-- .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 3 +- .../src/share/vm/gc/g1/g1CollectorPolicy.cpp | 3 +- .../src/share/vm/gc/g1/g1CollectorPolicy.hpp | 2 +- .../vm/gc/g1/g1YoungRemSetSamplingThread.cpp | 29 +++++++++--- hotspot/src/share/vm/gc/g1/youngList.cpp | 46 ++----------------- hotspot/src/share/vm/gc/g1/youngList.hpp | 16 +------ 7 files changed, 32 insertions(+), 74 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index f241d749045..be30e88c541 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1400,7 +1400,6 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, JavaThread::dirty_card_queue_set().abandon_logs(); assert(dirty_card_queue_set().completed_buffers_num() == 0, "DCQS should be empty"); - _young_list->reset_sampled_info(); // At this point there should be no regions in the // entire heap tagged as young. assert(check_young_list_empty(true /* check_heap */), @@ -3390,8 +3389,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { clear_cset_fast_test(); - _young_list->reset_sampled_info(); - // Don't check the whole heap at this point as the // GC alloc regions from this pause have been tagged // as survivors and moved on to the survivor list. @@ -5188,8 +5185,8 @@ public: bool success() { return _success; } }; -bool G1CollectedHeap::check_young_list_empty(bool check_heap, bool check_sample) { - bool ret = _young_list->check_list_empty(check_sample); +bool G1CollectedHeap::check_young_list_empty(bool check_heap) { + bool ret = _young_list->check_list_empty(); if (check_heap) { NoYoungRegionsClosure closure; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 3d8badc27bb..a62d1c6a8ed 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -1333,8 +1333,7 @@ public: return _young_list->check_list_well_formed(); } - bool check_young_list_empty(bool check_heap, - bool check_sample = true); + bool check_young_list_empty(bool check_heap); // *** Stuff related to concurrent marking. It's not clear to me that so // many of these need to be public. diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index 93b2cce3dd1..f14e360ce44 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -787,10 +787,9 @@ double G1CollectorPolicy::predict_survivor_regions_evac_time() const { return survivor_regions_evac_time; } -void G1CollectorPolicy::revise_young_list_target_length_if_necessary() { +void G1CollectorPolicy::revise_young_list_target_length_if_necessary(size_t rs_lengths) { guarantee( adaptive_young_list_length(), "should not call this otherwise" ); - size_t rs_lengths = _g1->young_list()->sampled_rs_lengths(); if (rs_lengths > _rs_lengths_prediction) { // add 10% to avoid having to recalculate often size_t rs_lengths_prediction = rs_lengths * 1100 / 1000; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp index fbdc47742cf..6db53e64119 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp @@ -471,7 +471,7 @@ public: // Check the current value of the young list RSet lengths and // compare it against the last prediction. If the current value is // higher, recalculate the young list target length prediction. - void revise_young_list_target_length_if_necessary(); + void revise_young_list_target_length_if_necessary(size_t rs_lengths); // This should be called after the heap is resized. void record_new_heap_size(uint new_number_of_regions); diff --git a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp index b511b04617f..8c8d216478c 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp @@ -26,6 +26,8 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1YoungRemSetSamplingThread.hpp" +#include "gc/g1/heapRegion.inline.hpp" +#include "gc/g1/heapRegionRemSet.hpp" #include "gc/g1/suspendibleThreadSet.hpp" #include "runtime/mutexLocker.hpp" @@ -100,22 +102,35 @@ void G1YoungRemSetSamplingThread::sample_young_list_rs_lengths() { G1CollectorPolicy* g1p = g1h->g1_policy(); if (g1p->adaptive_young_list_length()) { int regions_visited = 0; - g1h->young_list()->rs_length_sampling_init(); - while (g1h->young_list()->rs_length_sampling_more()) { - g1h->young_list()->rs_length_sampling_next(); + HeapRegion* hr = g1h->young_list()->first_region(); + size_t sampled_rs_lengths = 0; + + while (hr != NULL) { + size_t rs_length = hr->rem_set()->occupied(); + sampled_rs_lengths += rs_length; + + // The current region may not yet have been added to the + // incremental collection set (it gets added when it is + // retired as the current allocation region). + if (hr->in_collection_set()) { + // Update the collection set policy information for this region + g1p->update_incremental_cset_info(hr, rs_length); + } + ++regions_visited; // we try to yield every time we visit 10 regions if (regions_visited == 10) { if (sts.should_yield()) { sts.yield(); - // we just abandon the iteration - break; + // A gc may have occurred and our sampling data is stale and further + // traversal of the young list is unsafe + return; } regions_visited = 0; } + hr = hr->get_next_young_region(); } - - g1p->revise_young_list_target_length_if_necessary(); + g1p->revise_young_list_target_length_if_necessary(sampled_rs_lengths); } } diff --git a/hotspot/src/share/vm/gc/g1/youngList.cpp b/hotspot/src/share/vm/gc/g1/youngList.cpp index 3d95e8ff93a..25b9d21d4fa 100644 --- a/hotspot/src/share/vm/gc/g1/youngList.cpp +++ b/hotspot/src/share/vm/gc/g1/youngList.cpp @@ -33,9 +33,9 @@ #include "utilities/ostream.hpp" YoungList::YoungList(G1CollectedHeap* g1h) : - _g1h(g1h), _head(NULL), _length(0), _last_sampled_rs_lengths(0), + _g1h(g1h), _head(NULL), _length(0), _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) { - guarantee(check_list_empty(false), "just making sure..."); + guarantee(check_list_empty(), "just making sure..."); } void YoungList::push_region(HeapRegion *hr) { @@ -86,9 +86,7 @@ void YoungList::empty_list() { _survivor_tail = NULL; _survivor_length = 0; - _last_sampled_rs_lengths = 0; - - assert(check_list_empty(false), "just making sure..."); + assert(check_list_empty(), "just making sure..."); } bool YoungList::check_list_well_formed() { @@ -119,17 +117,13 @@ bool YoungList::check_list_well_formed() { return ret; } -bool YoungList::check_list_empty(bool check_sample) { +bool YoungList::check_list_empty() { bool ret = true; if (_length != 0) { log_error(gc, verify)("### YOUNG LIST should have 0 length, not %u", _length); ret = false; } - if (check_sample && _last_sampled_rs_lengths != 0) { - log_error(gc, verify)("### YOUNG LIST has non-zero last sampled RS lengths"); - ret = false; - } if (_head != NULL) { log_error(gc, verify)("### YOUNG LIST does not have a NULL head"); ret = false; @@ -141,38 +135,6 @@ bool YoungList::check_list_empty(bool check_sample) { return ret; } -void -YoungList::rs_length_sampling_init() { - _sampled_rs_lengths = 0; - _curr = _head; -} - -bool -YoungList::rs_length_sampling_more() { - return _curr != NULL; -} - -void -YoungList::rs_length_sampling_next() { - assert( _curr != NULL, "invariant" ); - size_t rs_length = _curr->rem_set()->occupied(); - - _sampled_rs_lengths += rs_length; - - // The current region may not yet have been added to the - // incremental collection set (it gets added when it is - // retired as the current allocation region). - if (_curr->in_collection_set()) { - // Update the collection set policy information for this region - _g1h->g1_policy()->update_incremental_cset_info(_curr, rs_length); - } - - _curr = _curr->get_next_young_region(); - if (_curr == NULL) { - _last_sampled_rs_lengths = _sampled_rs_lengths; - } -} - void YoungList::reset_auxilary_lists() { guarantee( is_empty(), "young list should be empty" ); diff --git a/hotspot/src/share/vm/gc/g1/youngList.hpp b/hotspot/src/share/vm/gc/g1/youngList.hpp index 36108b807db..1030b3f9c1c 100644 --- a/hotspot/src/share/vm/gc/g1/youngList.hpp +++ b/hotspot/src/share/vm/gc/g1/youngList.hpp @@ -37,14 +37,9 @@ private: HeapRegion* _survivor_head; HeapRegion* _survivor_tail; - HeapRegion* _curr; - uint _length; uint _survivor_length; - size_t _last_sampled_rs_lengths; - size_t _sampled_rs_lengths; - void empty_list(HeapRegion* list); public: @@ -72,15 +67,6 @@ public: return (size_t) survivor_length() * HeapRegion::GrainBytes; } - void rs_length_sampling_init(); - bool rs_length_sampling_more(); - void rs_length_sampling_next(); - - void reset_sampled_info() { - _last_sampled_rs_lengths = 0; - } - size_t sampled_rs_lengths() { return _last_sampled_rs_lengths; } - // for development purposes void reset_auxilary_lists(); void clear() { _head = NULL; _length = 0; } @@ -97,7 +83,7 @@ public: // debugging bool check_list_well_formed(); - bool check_list_empty(bool check_sample = true); + bool check_list_empty(); void print(); }; From bf7f1925fd61b796eff185f07b017ce38278367b Mon Sep 17 00:00:00 2001 From: Jesper Wilhelmsson Date: Thu, 25 Feb 2016 17:26:49 +0100 Subject: [PATCH 117/311] 8150647: Quarantine TestPLABResize.java until JDK-8150183 is fixed 8150562: Quarantine LoadAgentDcmdTest.java due to JDK-8150318 Reviewed-by: iklam, tschatzl --- hotspot/test/gc/g1/plab/TestPLABResize.java | 1 + hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java | 1 + 2 files changed, 2 insertions(+) diff --git a/hotspot/test/gc/g1/plab/TestPLABResize.java b/hotspot/test/gc/g1/plab/TestPLABResize.java index 07a05ce90c3..b07b769baa3 100644 --- a/hotspot/test/gc/g1/plab/TestPLABResize.java +++ b/hotspot/test/gc/g1/plab/TestPLABResize.java @@ -35,6 +35,7 @@ * gc.g1.plab.lib.MemoryConsumer * gc.g1.plab.lib.PLABUtils * gc.g1.plab.lib.AppPLABResize + * @ignore 8150183 * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main gc.g1.plab.TestPLABResize diff --git a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java index ad4d5871a20..f0db464e46b 100644 --- a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java +++ b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java @@ -38,6 +38,7 @@ import org.testng.annotations.Test; * java.management * jdk.jvmstat/sun.jvmstat.monitor * @build ClassFileInstaller jdk.test.lib.* SimpleJvmtiAgent + * @ignore 8150318 * @run main ClassFileInstaller SimpleJvmtiAgent * @run testng LoadAgentDcmdTest */ From ea65e14762fe124be3134aefa33348f200fd4f48 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Feb 2016 09:41:38 -0800 Subject: [PATCH 118/311] Added tag jdk-9+107 for changeset d632f62d9397 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index aaae670d176..87f89fa25a5 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -349,3 +349,4 @@ c4d72a1620835b5d657b7b6792c2879367d0154f jdk-9+101 9a38f8b4ba220708db198d08d82fd2144a64777d jdk-9+104 be58b02c11f90b88c67e4d0e2cb5e4cf2d9b3c57 jdk-9+105 54575d8783b3a39a2d710c28cda675d44261f9d9 jdk-9+106 +4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107 From 5d8cb4fdb98da45f401d90702e4fa51f42191673 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Feb 2016 09:41:40 -0800 Subject: [PATCH 119/311] Added tag jdk-9+107 for changeset f3c43d82c968 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 30bbd8fe337..0e5ef59edfc 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -509,3 +509,4 @@ c5f55130b1b69510d9a6f4a3105b58e21cd7ffe1 jdk-9+103 534c50395957c6025fb6627e93b35756f8d48a08 jdk-9+104 266fa9bb5297bf02cb2a7b038b10a109817d2b48 jdk-9+105 7232de4c17c37f60aecec4f3191090bd3d41d334 jdk-9+106 +c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107 From 83729ea481c68751e7ef5fcc73503e0436cec52a Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Feb 2016 09:41:40 -0800 Subject: [PATCH 120/311] Added tag jdk-9+107 for changeset 5924078ce428 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 88b455ba6fb..25cb1c388d2 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -349,3 +349,4 @@ ea285530245cf4e0edf0479121a41347d3030eba jdk-9+98 e385e95e6101711d5c63e7b1a827e99b6ec7a1cc jdk-9+104 64006ae915b3aa85ac7e6fac679024d2da7fe526 jdk-9+105 8ec4f97943fe56f93e4621f622b56b7144c0181a jdk-9+106 +49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107 From 1465d75ecb58b27499f4fe9f70f5d9be12ec1303 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Feb 2016 09:41:44 -0800 Subject: [PATCH 121/311] Added tag jdk-9+107 for changeset 1632bf7a3665 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index a985e31fc94..2aa2e1a0723 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -349,3 +349,4 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 58448465334e1d8bf1cfc09052783937b1cc21c0 jdk-9+104 5acf6071d4d610068a19c79e004ba8e59cf1b087 jdk-9+105 65d615f71e81bae46dcb4d053e590582e5705879 jdk-9+106 +781b83dadcae89b8ae7545bb4044ddc62c6fa006 jdk-9+107 From 07cfd93e884d1f15a2787e845672e41de0e98a5a Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Feb 2016 09:41:44 -0800 Subject: [PATCH 122/311] Added tag jdk-9+107 for changeset c464fa9657f3 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index f7f802b6f6b..08e4cc59c68 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -352,3 +352,4 @@ eb5e005a17e50d7d8340daaf21a5c3c5ae358d68 jdk-9+103 0f557aa096e2a5c9733d406d8cf0c2e6b1f8ca60 jdk-9+104 45a666c58e4c7d07638878684ad09decb3229dc9 jdk-9+105 c072c572d14948563ef5d86e1921699b3a2396ab jdk-9+106 +fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107 From bf4f843350a836e5e6f1db4d7f4ad34ea5701f1a Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Feb 2016 09:41:46 -0800 Subject: [PATCH 123/311] Added tag jdk-9+107 for changeset e1580bae8eb5 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 5b88bcd99f8..65cb5c825bd 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -349,3 +349,4 @@ eee1ced1d8e78293f2a004af818ca474387dbebf jdk-9+103 8faf1aec77a9517c69d2f4d8dd146429852ace7f jdk-9+104 55518739e399a1066c8613e19100d51b38d9f223 jdk-9+105 6e9ecae50b4e0d37483fb2719202eea5dca026a4 jdk-9+106 +8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107 From 0c3874e1efa2e389f62d00e3cd97a9ab125d7ee2 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Feb 2016 09:41:51 -0800 Subject: [PATCH 124/311] Added tag jdk-9+107 for changeset 9643bffe2105 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index c6a2d3a75cd..2021df477ff 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -349,3 +349,4 @@ cb73b474703e2de266542b505cffd658bcc052da jdk-9+99 3f60a4808377a276f6398ff19e61c1b9086f4d97 jdk-9+104 81bd82222f8a1f2b291a44a49e063973caa4e73b jdk-9+105 dd05d3761a341143ef4a6b1a245e0960cc125b76 jdk-9+106 +7a0c343551497bd0e38ad69a77cc57d9f396615a jdk-9+107 From 2f1144c5ff4c76f2c476cefb7dc45501d4b800ec Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 25 Feb 2016 09:41:52 -0800 Subject: [PATCH 125/311] Added tag jdk-9+107 for changeset ad5ff5d5459b --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index a2b4cd909db..8c38f51d90e 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -340,3 +340,4 @@ c9406f325a23e9093fa667ad3c594e2efe078f47 jdk-9+103 a618d3e89fdea5361895ef142a59074fe7ae3d98 jdk-9+104 4e9749cc32f15251d9b2d0eab4373529952902a3 jdk-9+105 cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106 +8042e81b530e480dfdad41fd53a7a26f69ebba26 jdk-9+107 From 4f6dba156809d016802eee6c3f128a173665a4b7 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Thu, 25 Feb 2016 13:09:17 -0500 Subject: [PATCH 126/311] 8150103: Convert TraceClassPaths to Unified Logging TraceClassPaths has been reimplemented with Unified Logging Reviewed-by: coleenp, dholmes, iklam --- .../src/share/vm/classfile/classLoader.cpp | 49 +++++++++---------- .../src/share/vm/classfile/classLoader.hpp | 4 +- .../vm/classfile/sharedPathsMiscInfo.cpp | 39 ++++++++++----- .../vm/classfile/sharedPathsMiscInfo.hpp | 19 +------ hotspot/src/share/vm/logging/logTag.hpp | 1 + hotspot/src/share/vm/memory/filemap.cpp | 20 +++----- hotspot/src/share/vm/runtime/arguments.cpp | 13 ++--- hotspot/src/share/vm/runtime/globals.hpp | 3 -- 8 files changed, 64 insertions(+), 84 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 14feb9876cf..0a1e20df3f0 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -37,6 +37,7 @@ #include "gc/shared/generation.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/oopMapCache.hpp" +#include "logging/logTag.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/oopFactory.hpp" @@ -417,34 +418,30 @@ bool ClassPathImageEntry::is_jrt() { #if INCLUDE_CDS void ClassLoader::exit_with_path_failure(const char* error, const char* message) { assert(DumpSharedSpaces, "only called at dump time"); - tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure"); + tty->print_cr("Hint: enable -Xlog:classpath=info to diagnose the failure"); vm_exit_during_initialization(error, message); } #endif -void ClassLoader::trace_class_path(outputStream* out, const char* msg, const char* name) { - if (!TraceClassPaths) { - return; - } - - if (msg) { - out->print("%s", msg); - } - if (name) { - if (strlen(name) < 256) { - out->print("%s", name); - } else { - // For very long paths, we need to print each character separately, - // as print_cr() has a length limit - while (name[0] != '\0') { - out->print("%c", name[0]); - name++; +void ClassLoader::trace_class_path(const char* msg, const char* name) { + if (log_is_enabled(Info, classpath)) { + ResourceMark rm; + outputStream* out = LogHandle(classpath)::info_stream(); + if (msg) { + out->print("%s", msg); + } + if (name) { + if (strlen(name) < 256) { + out->print("%s", name); + } else { + // For very long paths, we need to print each character separately, + // as print_cr() has a length limit + while (name[0] != '\0') { + out->print("%c", name[0]); + name++; + } } } - } - if (msg && msg[0] == '[') { - out->print_cr("]"); - } else { out->cr(); } } @@ -470,11 +467,13 @@ void ClassLoader::check_shared_classpath(const char *path) { void ClassLoader::setup_bootstrap_search_path() { assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); const char* sys_class_path = Arguments::get_sysclasspath(); + const char* java_class_path = Arguments::get_appclasspath(); if (PrintSharedArchiveAndExit) { // Don't print sys_class_path - this is the bootcp of this current VM process, not necessarily // the same as the bootcp of the shared archive. } else { - trace_class_path(tty, "[Bootstrap loader class path=", sys_class_path); + trace_class_path("bootstrap loader class path=", sys_class_path); + trace_class_path("classpath: ", java_class_path); } #if INCLUDE_CDS if (DumpSharedSpaces) { @@ -578,9 +577,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str } } } - if (TraceClassPaths) { - tty->print_cr("[Opened %s]", path); - } + log_info(classpath)("opened: %s", path); log_info(classload)("opened: %s", path); } else { // Directory diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 92ee90f2675..c2a68c04b09 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -331,7 +331,7 @@ class ClassLoader: AllStatic { static void exit_with_path_failure(const char* error, const char* message); #endif - static void trace_class_path(outputStream* out, const char* msg, const char* name = NULL); + static void trace_class_path(const char* msg, const char* name = NULL); // VM monitoring and management support static jlong classloader_time_ms(); diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp index 9233e3243ad..40843700bd6 100644 --- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -26,15 +26,15 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/sharedPathsMiscInfo.hpp" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/metaspaceShared.hpp" #include "runtime/arguments.hpp" +#include "utilities/ostream.hpp" void SharedPathsMiscInfo::add_path(const char* path, int type) { - if (TraceClassPaths) { - tty->print("[type=%s] ", type_name(type)); - trace_class_path("[Add misc shared path ", path); - } + log_info(classpath)("type=%s ", type_name(type)); + ClassLoader::trace_class_path("add misc shared path ", path); write(path, strlen(path) + 1); write_jint(jint(type)); } @@ -67,11 +67,29 @@ bool SharedPathsMiscInfo::read(void* ptr, size_t size) { } bool SharedPathsMiscInfo::fail(const char* msg, const char* name) { - ClassLoader::trace_class_path(tty, msg, name); + ClassLoader::trace_class_path(msg, name); MetaspaceShared::set_archive_loading_failed(); return false; } +void SharedPathsMiscInfo::print_path(int type, const char* path) { + ResourceMark rm; + outputStream* out = LogHandle(classpath)::info_stream(); + switch (type) { + case BOOT: + out->print("Expecting -Dsun.boot.class.path=%s", path); + break; + case NON_EXIST: + out->print("Expecting that %s does not exist", path); + break; + case REQUIRED: + out->print("Expecting that file %s must exist and is not altered", path); + break; + default: + ShouldNotReachHere(); + } +} + bool SharedPathsMiscInfo::check() { // The whole buffer must be 0 terminated so that we can use strlen and strcmp // without fear. @@ -90,17 +108,14 @@ bool SharedPathsMiscInfo::check() { if (!read_jint(&type)) { return fail("Corrupted archive file header"); } - if (TraceClassPaths) { - tty->print("[type=%s ", type_name(type)); - print_path(tty, type, path); - tty->print_cr("]"); - } + log_info(classpath)("type=%s ", type_name(type)); + print_path(type, path); if (!check(type, path)) { if (!PrintSharedArchiveAndExit) { return false; } } else { - trace_class_path("[ok"); + ClassLoader::trace_class_path("ok"); } } diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp index 652d20c883a..435630febac 100644 --- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp @@ -64,9 +64,6 @@ protected: void write(const void* ptr, size_t size); bool read(void* ptr, size_t size); - static void trace_class_path(const char* msg, const char* name = NULL) { - ClassLoader::trace_class_path(tty, msg, name); - } protected: static bool fail(const char* msg, const char* name = NULL); virtual bool check(jint type, const char* path); @@ -144,21 +141,7 @@ public: } } - virtual void print_path(outputStream* out, int type, const char* path) { - switch (type) { - case BOOT: - out->print("Expecting -Dsun.boot.class.path=%s", path); - break; - case NON_EXIST: - out->print("Expecting that %s does not exist", path); - break; - case REQUIRED: - out->print("Expecting that file %s must exist and is not altered", path); - break; - default: - ShouldNotReachHere(); - } - } + virtual void print_path(int type, const char* path); bool check(); bool read_jint(jint *ptr) { diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 16a91cfbddf..08a78c6b2ba 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -43,6 +43,7 @@ LOG_TAG(classload) /* Trace all classes loaded */ \ LOG_TAG(classloaderdata) /* class loader loader_data lifetime */ \ LOG_TAG(classunload) /* Trace unloading of classes */ \ + LOG_TAG(classpath) \ LOG_TAG(compaction) \ LOG_TAG(cpu) \ LOG_TAG(cset) \ diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index 2a82e60c063..1b21736315c 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -208,9 +208,7 @@ void FileMapInfo::allocate_classpath_entry_table() { count ++; bytes += (int)entry_size; bytes += name_bytes; - if (TraceClassPaths) { - tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name); - } + log_info(classpath)("add main shared path (%s) %s", (cpe->is_jar_file() ? "jar" : "dir"), name); } else { SharedClassPathEntry* ent = shared_classpath(cur_entry); if (cpe->is_jar_file()) { @@ -275,9 +273,7 @@ bool FileMapInfo::validate_classpath_entry_table() { struct stat st; const char* name = ent->_name; bool ok = true; - if (TraceClassPaths) { - tty->print_cr("[Checking shared classpath entry: %s]", name); - } + log_info(classpath)("checking shared classpath entry: %s", name); if (os::stat(name, &st) != 0) { fail_continue("Required classpath entry does not exist: %s", name); ok = false; @@ -301,9 +297,7 @@ bool FileMapInfo::validate_classpath_entry_table() { } } if (ok) { - if (TraceClassPaths) { - tty->print_cr("[ok]"); - } + log_info(classpath)("ok"); } else if (!PrintSharedArchiveAndExit) { _validating_classpath_entry_table = false; return false; @@ -888,10 +882,8 @@ bool FileMapInfo::FileMapHeader::validate() { char header_version[JVM_IDENT_MAX]; get_header_version(header_version); if (strncmp(_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) { - if (TraceClassPaths) { - tty->print_cr("Expected: %s", header_version); - tty->print_cr("Actual: %s", _jvm_ident); - } + log_info(classpath)("expected: %s", header_version); + log_info(classpath)("actual: %s", _jvm_ident); FileMapInfo::fail_continue("The shared archive file was created by a different" " version or build of HotSpot"); return false; @@ -919,7 +911,7 @@ bool FileMapInfo::validate_header() { if (status) { if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) { if (!PrintSharedArchiveAndExit) { - fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)"); + fail_continue("shared class paths mismatch (hint: enable -Xlog:classpath=info to diagnose the failure)"); status = false; } } diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index f43a7a1372f..512c29fc94d 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -405,8 +405,9 @@ static AliasedFlag const aliased_jvm_flags[] = { static AliasedLoggingFlag const aliased_logging_flags[] = { { "TraceClassLoading", LogLevel::Info, true, LogTag::_classload }, - { "TraceClassUnloading", LogLevel::Info, true, LogTag::_classunload }, + { "TraceClassPaths", LogLevel::Info, true, LogTag::_classpath }, { "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve }, + { "TraceClassUnloading", LogLevel::Info, true, LogTag::_classunload }, { "TraceExceptions", LogLevel::Info, true, LogTag::_exceptions }, { "TraceMonitorInflation", LogLevel::Debug, true, LogTag::_monitorinflation }, { "TraceBiasedLocking", LogLevel::Info, true, LogTag::_biasedlocking }, @@ -3255,7 +3256,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, // PrintSharedArchiveAndExit will turn on // -Xshare:on - // -XX:+TraceClassPaths + // -Xlog:classpath=info if (PrintSharedArchiveAndExit) { if (FLAG_SET_CMDLINE(bool, UseSharedSpaces, true) != Flag::SUCCESS) { return JNI_EINVAL; @@ -3263,9 +3264,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, if (FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true) != Flag::SUCCESS) { return JNI_EINVAL; } - if (FLAG_SET_CMDLINE(bool, TraceClassPaths, true) != Flag::SUCCESS) { - return JNI_EINVAL; - } + LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(classpath)); } // Change the default value for flags which have different default values @@ -3318,10 +3317,6 @@ void Arguments::fix_appclasspath() { _java_class_path->set_value(copy); FreeHeap(copy); // a copy was made by set_value, so don't need this anymore } - - if (!PrintSharedArchiveAndExit) { - ClassLoader::trace_class_path(tty, "[classpath: ", _java_class_path->value()); - } } static bool has_jar_files(const char* directory) { diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index ce36ff1db49..3c6219a4402 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2403,9 +2403,6 @@ public: product(bool, IgnoreEmptyClassPaths, false, \ "Ignore empty path elements in -classpath") \ \ - product(bool, TraceClassPaths, false, \ - "Trace processing of class paths") \ - \ product(bool, TraceClassLoadingPreorder, false, \ "Trace all classes loaded in order referenced (not loaded)") \ \ From 66073d9f8eec891ff6002810d133c13706cdcb1e Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Thu, 25 Feb 2016 23:00:55 +0000 Subject: [PATCH 127/311] 8087112: HTTP API and HTTP/1.1 implementation Reviewed-by: alanb, chegar, coffeys, psandoz, rriggs --- make/common/CORE_PKGS.gmk | 1 + modules.xml | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/make/common/CORE_PKGS.gmk b/make/common/CORE_PKGS.gmk index 6a3ba63a243..eb6ac3d769e 100644 --- a/make/common/CORE_PKGS.gmk +++ b/make/common/CORE_PKGS.gmk @@ -103,6 +103,7 @@ CORE_PKGS = \ java.lang.reflect \ java.math \ java.net \ + java.net.http \ java.net.spi \ java.nio \ java.nio.channels \ diff --git a/modules.xml b/modules.xml index 458859b5327..75a523a8cc8 100644 --- a/modules.xml +++ b/modules.xml @@ -315,6 +315,10 @@ jdk.zipfs java.instrument + + sun.net + java.httpclient + sun.net.dns java.security.jgss @@ -496,6 +500,7 @@ java.logging java.management java.prefs + java.httpclient sun.util.resources @@ -520,6 +525,7 @@ java.compact2 java.compiler java.instrument + java.httpclient java.management java.naming java.prefs @@ -837,6 +843,13 @@ jdk.jshell + + java.httpclient + java.base + + java.net.http + + java.instrument java.base From 095027bd7407253c7b86bfe7a45079cef8852b6a Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Thu, 25 Feb 2016 23:14:22 +0000 Subject: [PATCH 128/311] 8087112: HTTP API and HTTP/1.1 implementation Reviewed-by: alanb, chegar, coffeys, psandoz, rriggs --- .../classes/build/tools/module/boot.modules | 1 + .../share/classes/java/net/Authenticator.java | 42 + .../share/classes/java/net/ProxySelector.java | 45 + .../share/classes/java/net/package-info.java | 3 +- .../classes/java/net/http/AsyncEvent.java | 58 + .../java/net/http/AuthenticationFilter.java | 306 +++ .../classes/java/net/http/BufferHandler.java | 37 + .../classes/java/net/http/ConnectionPool.java | 272 +++ .../classes/java/net/http/CookieFilter.java | 66 + .../share/classes/java/net/http/Exchange.java | 419 ++++ .../classes/java/net/http/ExchangeImpl.java | 133 ++ .../java/net/http/ExecutorWrapper.java | 100 + .../classes/java/net/http/FilterFactory.java | 49 + .../classes/java/net/http/HeaderFilter.java | 45 + .../classes/java/net/http/HeaderParser.java | 245 +++ .../classes/java/net/http/Http1Exchange.java | 309 +++ .../classes/java/net/http/Http1Request.java | 362 ++++ .../classes/java/net/http/Http1Response.java | 290 +++ .../java/net/http/Http2ClientImpl.java | 33 + .../java/net/http/Http2Connection.java | 65 + .../classes/java/net/http/HttpClient.java | 415 ++++ .../java/net/http/HttpClientBuilderImpl.java | 133 ++ .../classes/java/net/http/HttpClientImpl.java | 499 +++++ .../classes/java/net/http/HttpConnection.java | 367 ++++ .../classes/java/net/http/HttpHeaders.java | 81 + .../classes/java/net/http/HttpHeaders1.java | 29 + .../java/net/http/HttpHeadersImpl.java | 136 ++ .../java/net/http/HttpRedirectImpl.java | 104 + .../classes/java/net/http/HttpRequest.java | 871 ++++++++ .../java/net/http/HttpRequestBuilderImpl.java | 177 ++ .../java/net/http/HttpRequestImpl.java | 285 +++ .../classes/java/net/http/HttpResponse.java | 977 +++++++++ .../java/net/http/HttpResponseImpl.java | 157 ++ .../java/net/http/HttpTimeoutException.java | 40 + .../share/classes/java/net/http/Log.java | 170 ++ .../classes/java/net/http/MultiExchange.java | 275 +++ .../share/classes/java/net/http/Pair.java | 46 + .../java/net/http/PlainHttpConnection.java | 228 +++ .../java/net/http/PlainProxyConnection.java | 39 + .../net/http/PlainTunnelingConnection.java | 143 ++ .../classes/java/net/http/RawChannel.java | 148 ++ .../classes/java/net/http/RedirectFilter.java | 96 + .../java/net/http/ResponseContent.java | 323 +++ .../java/net/http/ResponseHeaders.java | 480 +++++ .../classes/java/net/http/SSLConnection.java | 178 ++ .../classes/java/net/http/SSLDelegate.java | 457 +++++ .../java/net/http/SSLTunnelConnection.java | 179 ++ .../share/classes/java/net/http/Stream.java | 101 + .../classes/java/net/http/TimeoutEvent.java | 47 + .../share/classes/java/net/http/Utils.java | 221 ++ .../classes/java/net/http/package-info.java | 40 + .../sun/net/httpserver/FileServerHandler.java | 80 +- jdk/test/java/net/httpclient/APIErrors.java | 207 ++ .../java/net/httpclient/BasicAuthTest.java | 162 ++ jdk/test/java/net/httpclient/HeadersTest.java | 64 + jdk/test/java/net/httpclient/HttpUtils.java | 174 ++ .../java/net/httpclient/ImmutableHeaders.java | 116 ++ .../net/httpclient/LightWeightHttpServer.java | 313 +++ .../java/net/httpclient/ManyRequests.java | 194 ++ jdk/test/java/net/httpclient/ProxyServer.java | 319 +++ .../java/net/httpclient/QuickResponses.java | 104 + .../java/net/httpclient/RequestBodyTest.java | 169 ++ jdk/test/java/net/httpclient/Server.java | 259 +++ jdk/test/java/net/httpclient/SmokeTest.java | 949 +++++++++ .../java/net/httpclient/SplitResponse.java | 117 ++ jdk/test/java/net/httpclient/TimeoutTest.java | 158 ++ .../java/net/httpclient/docs/files/foo.txt | 1 + .../httpclient/docs/files/notsobigfile.txt | 34 + .../net/httpclient/docs/files/smallfile.txt | 1792 +++++++++++++++++ .../java/net/httpclient/security/0.policy | 24 + .../java/net/httpclient/security/1.policy | 24 + .../java/net/httpclient/security/10.policy | 22 + .../java/net/httpclient/security/11.policy | 24 + .../java/net/httpclient/security/12.policy | 24 + .../java/net/httpclient/security/15.policy | 27 + .../java/net/httpclient/security/2.policy | 24 + .../java/net/httpclient/security/3.policy | 24 + .../java/net/httpclient/security/4.policy | 25 + .../java/net/httpclient/security/5.policy | 24 + .../java/net/httpclient/security/6.policy | 24 + .../java/net/httpclient/security/7.policy | 24 + .../java/net/httpclient/security/8.policy | 24 + .../java/net/httpclient/security/9.policy | 24 + .../net/httpclient/security/Security.java | 475 +++++ 84 files changed, 16343 insertions(+), 4 deletions(-) create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Log.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Pair.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Stream.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Utils.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/package-info.java create mode 100644 jdk/test/java/net/httpclient/APIErrors.java create mode 100644 jdk/test/java/net/httpclient/BasicAuthTest.java create mode 100644 jdk/test/java/net/httpclient/HeadersTest.java create mode 100644 jdk/test/java/net/httpclient/HttpUtils.java create mode 100644 jdk/test/java/net/httpclient/ImmutableHeaders.java create mode 100644 jdk/test/java/net/httpclient/LightWeightHttpServer.java create mode 100644 jdk/test/java/net/httpclient/ManyRequests.java create mode 100644 jdk/test/java/net/httpclient/ProxyServer.java create mode 100644 jdk/test/java/net/httpclient/QuickResponses.java create mode 100644 jdk/test/java/net/httpclient/RequestBodyTest.java create mode 100644 jdk/test/java/net/httpclient/Server.java create mode 100644 jdk/test/java/net/httpclient/SmokeTest.java create mode 100644 jdk/test/java/net/httpclient/SplitResponse.java create mode 100644 jdk/test/java/net/httpclient/TimeoutTest.java create mode 100644 jdk/test/java/net/httpclient/docs/files/foo.txt create mode 100644 jdk/test/java/net/httpclient/docs/files/notsobigfile.txt create mode 100644 jdk/test/java/net/httpclient/docs/files/smallfile.txt create mode 100644 jdk/test/java/net/httpclient/security/0.policy create mode 100644 jdk/test/java/net/httpclient/security/1.policy create mode 100644 jdk/test/java/net/httpclient/security/10.policy create mode 100644 jdk/test/java/net/httpclient/security/11.policy create mode 100644 jdk/test/java/net/httpclient/security/12.policy create mode 100644 jdk/test/java/net/httpclient/security/15.policy create mode 100644 jdk/test/java/net/httpclient/security/2.policy create mode 100644 jdk/test/java/net/httpclient/security/3.policy create mode 100644 jdk/test/java/net/httpclient/security/4.policy create mode 100644 jdk/test/java/net/httpclient/security/5.policy create mode 100644 jdk/test/java/net/httpclient/security/6.policy create mode 100644 jdk/test/java/net/httpclient/security/7.policy create mode 100644 jdk/test/java/net/httpclient/security/8.policy create mode 100644 jdk/test/java/net/httpclient/security/9.policy create mode 100644 jdk/test/java/net/httpclient/security/Security.java diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index f7f21225a5d..a22b4af52b9 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -2,6 +2,7 @@ java.base java.compiler java.datatransfer java.desktop +java.httpclient java.instrument java.logging java.management diff --git a/jdk/src/java.base/share/classes/java/net/Authenticator.java b/jdk/src/java.base/share/classes/java/net/Authenticator.java index e62e169099c..8b59db010f3 100644 --- a/jdk/src/java.base/share/classes/java/net/Authenticator.java +++ b/jdk/src/java.base/share/classes/java/net/Authenticator.java @@ -319,6 +319,48 @@ class Authenticator { } } + /** + * Ask this authenticator for a password. + * + * @param host The hostname of the site requesting authentication. + * @param addr The InetAddress of the site requesting authorization, + * or null if not known. + * @param port the port for the requested connection + * @param protocol The protocol that's requesting the connection + * ({@link java.net.Authenticator#getRequestingProtocol()}) + * @param prompt A prompt string for the user + * @param scheme The authentication scheme + * @param url The requesting URL that caused the authentication + * @param reqType The type (server or proxy) of the entity requesting + * authentication. + * + * @return The username/password, or null if one can't be gotten + * + * @since 9 + */ + public PasswordAuthentication + requestPasswordAuthenticationInstance(String host, + InetAddress addr, + int port, + String protocol, + String prompt, + String scheme, + URL url, + RequestorType reqType) { + synchronized (this) { + this.reset(); + this.requestingHost = host; + this.requestingSite = addr; + this.requestingPort = port; + this.requestingProtocol = protocol; + this.requestingPrompt = prompt; + this.requestingScheme = scheme; + this.requestingURL = url; + this.requestingAuthType = reqType; + return this.getPasswordAuthentication(); + } + } + /** * Gets the {@code hostname} of the * site or proxy requesting authentication, or {@code null} diff --git a/jdk/src/java.base/share/classes/java/net/ProxySelector.java b/jdk/src/java.base/share/classes/java/net/ProxySelector.java index d6bb53656fd..04c675cedc8 100644 --- a/jdk/src/java.base/share/classes/java/net/ProxySelector.java +++ b/jdk/src/java.base/share/classes/java/net/ProxySelector.java @@ -162,4 +162,49 @@ public abstract class ProxySelector { * @throws IllegalArgumentException if either argument is null */ public abstract void connectFailed(URI uri, SocketAddress sa, IOException ioe); + + /** + * Returns a ProxySelector which uses the given proxy address for all HTTP + * and HTTPS requests. If proxy is {@code null} then proxying is disabled. + * + * @param proxyAddress + * The address of the proxy + * + * @return a ProxySelector + * + * @since 9 + */ + public static ProxySelector of(InetSocketAddress proxyAddress) { + return new StaticProxySelector(proxyAddress); + } + + static class StaticProxySelector extends ProxySelector { + private static final List NO_PROXY_LIST = List.of(Proxy.NO_PROXY); + final List list; + + StaticProxySelector(InetSocketAddress address){ + Proxy p; + if (address == null) { + p = Proxy.NO_PROXY; + } else { + p = new Proxy(Proxy.Type.HTTP, address); + } + list = List.of(p); + } + + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException e) { + /* ignore */ + } + + @Override + public synchronized List select(URI uri) { + String scheme = uri.getScheme().toLowerCase(); + if (scheme.equals("http") || scheme.equals("https")) { + return list; + } else { + return NO_PROXY_LIST; + } + } + } } diff --git a/jdk/src/java.base/share/classes/java/net/package-info.java b/jdk/src/java.base/share/classes/java/net/package-info.java index 2279cca479f..37a4ea69de1 100644 --- a/jdk/src/java.base/share/classes/java/net/package-info.java +++ b/jdk/src/java.base/share/classes/java/net/package-info.java @@ -121,7 +121,8 @@ * underlying protocol handlers like http or https. *
    • {@link java.net.HttpURLConnection} is a subclass of URLConnection * and provides some additional functionalities specific to the - * HTTP protocol.
    • + * HTTP protocol. This API has been superceded by the newer + HTTP client API described in the previous section. * *

      The recommended usage is to use {@link java.net.URI} to identify * resources, then convert it into a {@link java.net.URL} when it is time to diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java new file mode 100644 index 00000000000..1cd606fe7a5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.nio.channels.SelectableChannel; + +/** + * Event handling interface from HttpClientImpl's selector. + * + *

      If blockingChannel is true, then the channel will be put in blocking + * mode prior to handle() being called. If false, then it remains non-blocking. + */ +abstract class AsyncEvent { + + /** + * Implement this if channel should be made blocking before calling handle() + */ + public interface Blocking { } + + /** + * Implement this if channel should remain non-blocking before calling handle() + */ + public interface NonBlocking { } + + /** Returns the channel */ + public abstract SelectableChannel channel(); + + /** Returns the selector interest op flags OR'd */ + public abstract int interestOps(); + + /** Called when event occurs */ + public abstract void handle(); + + /** Called when selector is shutting down. Abort all exchanges. */ + public abstract void abort(); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java new file mode 100644 index 00000000000..c06f3886a85 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import static java.net.Authenticator.RequestorType.PROXY; +import static java.net.Authenticator.RequestorType.SERVER; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.InetSocketAddress; +import java.net.URISyntaxException; +import java.util.Base64; +import java.util.HashMap; +import java.util.LinkedList; +import static java.nio.charset.StandardCharsets.ISO_8859_1; + +/** + * Implementation of Http Basic authentication. + */ +class AuthenticationFilter implements HeaderFilter { + + static private final Base64.Encoder encoder = Base64.getEncoder(); + + static final int DEFAULT_RETRY_LIMIT = 3; + + static final int retry_limit = Utils.getIntegerNetProperty( + "sun.net.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT); + + static final int UNAUTHORIZED = 401; + static final int PROXY_UNAUTHORIZED = 407; + + private PasswordAuthentication getCredentials(String header, + boolean proxy, + HttpRequestImpl req) + throws IOException + { + HttpClientImpl client = req.client(); + java.net.Authenticator auth = + client.authenticator() + .orElseThrow(() -> new IOException("No authenticator set")); + URI uri = req.uri(); + HeaderParser parser = new HeaderParser(header); + String authscheme = parser.findKey(0); + + String realm = parser.findValue("realm"); + java.net.Authenticator.RequestorType rtype = proxy ? PROXY : SERVER; + + // needs to be instance method in Authenticator + return auth.requestPasswordAuthenticationInstance(uri.getHost(), + null, + uri.getPort(), + uri.getScheme(), + realm, + authscheme, + uri.toURL(), + rtype + ); + } + + private URI getProxyURI(HttpRequestImpl r) { + InetSocketAddress proxy = r.proxy(); + if (proxy == null) { + return null; + } + + // our own private scheme for proxy URLs + // eg. proxy.http://host:port/ + String scheme = "proxy." + r.uri().getScheme(); + try { + return new URI(scheme, + null, + proxy.getHostString(), + proxy.getPort(), + null, + null, + null); + } catch (URISyntaxException e) { + throw new InternalError(e); + } + } + + @Override + public void request(HttpRequestImpl r) throws IOException { + // use preemptive authentication if an entry exists. + Cache cache = getCache(r); + + // Proxy + if (r.exchange.proxyauth == null) { + URI proxyURI = getProxyURI(r); + if (proxyURI != null) { + CacheEntry ca = cache.get(proxyURI, true); + if (ca != null) { + r.exchange.proxyauth = new AuthInfo(true, ca.scheme, null, ca); + addBasicCredentials(r, true, ca.value); + } + } + } + + // Server + if (r.exchange.serverauth == null) { + CacheEntry ca = cache.get(r.uri(), false); + if (ca != null) { + r.exchange.serverauth = new AuthInfo(true, ca.scheme, null, ca); + addBasicCredentials(r, false, ca.value); + } + } + } + + // TODO: refactor into per auth scheme class + static private void addBasicCredentials(HttpRequestImpl r, + boolean proxy, + PasswordAuthentication pw) { + String hdrname = proxy ? "Proxy-Authorization" : "Authorization"; + StringBuilder sb = new StringBuilder(128); + sb.append(pw.getUserName()).append(':').append(pw.getPassword()); + String s = encoder.encodeToString(sb.toString().getBytes(ISO_8859_1)); + String value = "Basic " + s; + r.setSystemHeader(hdrname, value); + } + + // Information attached to a HttpRequestImpl relating to authentication + static class AuthInfo { + final boolean fromcache; + final String scheme; + int retries; + PasswordAuthentication credentials; // used in request + CacheEntry cacheEntry; // if used + + AuthInfo(boolean fromcache, + String scheme, + PasswordAuthentication credentials) { + this.fromcache = fromcache; + this.scheme = scheme; + this.credentials = credentials; + this.retries = 1; + } + + AuthInfo(boolean fromcache, + String scheme, + PasswordAuthentication credentials, + CacheEntry ca) { + this(fromcache, scheme, credentials); + assert credentials == null || (ca != null && ca.value == null); + cacheEntry = ca; + } + } + + @Override + public HttpRequestImpl response(HttpResponseImpl r) throws IOException { + Cache cache = getCache(r.request); + int status = r.statusCode(); + HttpHeaders hdrs = r.headers(); + HttpRequestImpl req = r.request(); + + if (status != UNAUTHORIZED && status != PROXY_UNAUTHORIZED) { + // check if any authentication succeeded for first time + if (req.exchange.serverauth != null && !req.exchange.serverauth.fromcache) { + AuthInfo au = req.exchange.serverauth; + cache.store(au.scheme, req.uri(), false, au.credentials); + } + if (req.exchange.proxyauth != null && !req.exchange.proxyauth.fromcache) { + AuthInfo au = req.exchange.proxyauth; + cache.store(au.scheme, req.uri(), false, au.credentials); + } + return null; + } + + boolean proxy = status == PROXY_UNAUTHORIZED; + String authname = proxy ? "Proxy-Authentication" : "WWW-Authenticate"; + String authval = hdrs.firstValue(authname).orElseThrow(() -> { + return new IOException("Invalid auth header"); + }); + HeaderParser parser = new HeaderParser(authval); + String scheme = parser.findKey(0); + + // TODO: Need to generalise from Basic only. Delegate to a provider class etc. + + if (!scheme.equalsIgnoreCase("Basic")) { + return null; // error gets returned to app + } + + String realm = parser.findValue("realm"); + AuthInfo au = proxy ? req.exchange.proxyauth : req.exchange.serverauth; + if (au == null) { + PasswordAuthentication pw = getCredentials(authval, proxy, req); + if (pw == null) { + throw new IOException("No credentials provided"); + } + // No authentication in request. Get credentials from user + au = new AuthInfo(false, "Basic", pw); + if (proxy) + req.exchange.proxyauth = au; + else + req.exchange.serverauth = au; + addBasicCredentials(req, proxy, pw); + return req; + } else if (au.retries > retry_limit) { + throw new IOException("too many authentication attempts"); + } else { + // we sent credentials, but they were rejected + if (au.fromcache) { + cache.remove(au.cacheEntry); + } + // try again + au.credentials = getCredentials(authval, proxy, req); + addBasicCredentials(req, proxy, au.credentials); + au.retries++; + return req; + } + } + + static final HashMap caches = new HashMap<>(); + + static synchronized Cache getCache(HttpRequestImpl req) { + HttpClientImpl client = req.client(); + Cache c = caches.get(client); + if (c == null) { + c = new Cache(); + caches.put(client, c); + } + return c; + } + + static class Cache { + final LinkedList entries = new LinkedList<>(); + + synchronized CacheEntry get(URI uri, boolean proxy) { + for (CacheEntry entry : entries) { + if (entry.equalsKey(uri, proxy)) { + return entry; + } + } + return null; + } + + synchronized void remove(String authscheme, URI domain, boolean proxy) { + for (CacheEntry entry : entries) { + if (entry.equalsKey(domain, proxy)) { + entries.remove(entry); + } + } + } + + synchronized void remove(CacheEntry entry) { + entries.remove(entry); + } + + synchronized void store(String authscheme, + URI domain, + boolean proxy, + PasswordAuthentication value) { + remove(authscheme, domain, proxy); + entries.add(new CacheEntry(authscheme, domain, proxy, value)); + } + } + + static class CacheEntry { + final String root; + final String scheme; + final boolean proxy; + final PasswordAuthentication value; + + CacheEntry(String authscheme, + URI uri, + boolean proxy, + PasswordAuthentication value) { + this.scheme = authscheme; + this.root = uri.resolve(".").toString(); // remove extraneous components + this.proxy = proxy; + this.value = value; + } + + public PasswordAuthentication value() { + return value; + } + + public boolean equalsKey(URI uri, boolean proxy) { + if (this.proxy != proxy) { + return false; + } + String other = uri.toString(); + return other.startsWith(root); + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java new file mode 100644 index 00000000000..a311422a782 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.nio.ByteBuffer; + +/** + * Implemented by buffer pools. + */ +interface BufferHandler { + + ByteBuffer getBuffer(); + + void returnBuffer(ByteBuffer buffer); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java new file mode 100644 index 00000000000..70e475ec6e3 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.ListIterator; +import java.util.Objects; + +/** + * Http 1.1 connection pool. + */ +class ConnectionPool { + + static final long KEEP_ALIVE = Utils.getIntegerNetProperty( + "sun.net.httpclient.keepalive.timeout", 1200); // seconds + + // Pools of idle connections + + final HashMap> plainPool; + final HashMap> sslPool; + CacheCleaner cleaner; + + /** + * Entries in connection pool are keyed by destination address and/or + * proxy address: + * case 1: plain TCP not via proxy (destination only) + * case 2: plain TCP via proxy (proxy only) + * case 3: SSL not via proxy (destination only) + * case 4: SSL over tunnel (destination and proxy) + */ + static class CacheKey { + final InetSocketAddress proxy; + final InetSocketAddress destination; + + CacheKey(InetSocketAddress destination, InetSocketAddress proxy) { + this.proxy = proxy; + this.destination = destination; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final CacheKey other = (CacheKey) obj; + if (!Objects.equals(this.proxy, other.proxy)) { + return false; + } + if (!Objects.equals(this.destination, other.destination)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return Objects.hash(proxy, destination); + } + } + + static class ExpiryEntry { + final HttpConnection connection; + final long expiry; // absolute time in seconds of expiry time + ExpiryEntry(HttpConnection connection, long expiry) { + this.connection = connection; + this.expiry = expiry; + } + } + + final LinkedList expiryList; + + /** + * There should be one of these per HttpClient. + */ + ConnectionPool() { + plainPool = new HashMap<>(); + sslPool = new HashMap<>(); + expiryList = new LinkedList<>(); + cleaner = new CacheCleaner(); + } + + void start() { + cleaner.start(); + } + + static CacheKey cacheKey(InetSocketAddress destination, + InetSocketAddress proxy) { + return new CacheKey(destination, proxy); + } + + synchronized HttpConnection getConnection(boolean secure, + InetSocketAddress addr, + InetSocketAddress proxy) { + CacheKey key = new CacheKey(addr, proxy); + HttpConnection c = secure ? findConnection(key, sslPool) + : findConnection(key, plainPool); + //System.out.println ("getConnection returning: " + c); + return c; + } + + /** + * Returns the connection to the pool. + * + * @param conn + */ + synchronized void returnToPool(HttpConnection conn) { + if (conn instanceof PlainHttpConnection) { + putConnection(conn, plainPool); + } else { + putConnection(conn, sslPool); + } + addToExpiryList(conn); + //System.out.println("Return to pool: " + conn); + } + + private HttpConnection + findConnection(CacheKey key, + HashMap> pool) { + LinkedList l = pool.get(key); + if (l == null || l.size() == 0) { + return null; + } else { + HttpConnection c = l.removeFirst(); + removeFromExpiryList(c); + return c; + } + } + + /* called from cache cleaner only */ + private void + removeFromPool(HttpConnection c, + HashMap> pool) { + //System.out.println("cacheCleaner removing: " + c); + LinkedList l = pool.get(c.cacheKey()); + assert l != null; + boolean wasPresent = l.remove(c); + assert wasPresent; + } + + private void + putConnection(HttpConnection c, + HashMap> pool) { + CacheKey key = c.cacheKey(); + LinkedList l = pool.get(key); + if (l == null) { + l = new LinkedList<>(); + pool.put(key, l); + } + l.add(c); + } + + // only runs while entries exist in cache + + class CacheCleaner extends Thread { + + volatile boolean stopping; + + CacheCleaner() { + super(null, null, "HTTP-Cache-cleaner", 0, false); + setDaemon(true); + } + + synchronized boolean stopping() { + return stopping; + } + + synchronized void stopCleaner() { + stopping = true; + } + + @Override + public void run() { + while (!stopping()) { + try { + Thread.sleep(3000); + } catch (InterruptedException e) {} + cleanCache(); + } + } + } + + synchronized void removeFromExpiryList(HttpConnection c) { + if (c == null) { + return; + } + ListIterator li = expiryList.listIterator(); + while (li.hasNext()) { + ExpiryEntry e = li.next(); + if (e.connection.equals(c)) { + li.remove(); + return; + } + } + if (expiryList.isEmpty()) { + cleaner.stopCleaner(); + } + } + + private void cleanCache() { + long now = System.currentTimeMillis() / 1000; + LinkedList closelist = new LinkedList<>(); + + synchronized (this) { + ListIterator li = expiryList.listIterator(); + while (li.hasNext()) { + ExpiryEntry entry = li.next(); + if (entry.expiry <= now) { + li.remove(); + HttpConnection c = entry.connection; + closelist.add(c); + if (c instanceof PlainHttpConnection) { + removeFromPool(c, plainPool); + } else { + removeFromPool(c, sslPool); + } + } + } + } + for (HttpConnection c : closelist) { + //System.out.println ("KAC: closing " + c); + c.close(); + } + } + + private synchronized void addToExpiryList(HttpConnection conn) { + long now = System.currentTimeMillis() / 1000; + long then = now + KEEP_ALIVE; + + if (expiryList.isEmpty()) + cleaner = new CacheCleaner(); + + ListIterator li = expiryList.listIterator(); + while (li.hasNext()) { + ExpiryEntry entry = li.next(); + + if (then > entry.expiry) { + li.previous(); + // insert here + li.add(new ExpiryEntry(conn, then)); + return; + } + } + // first element of list + expiryList.add(new ExpiryEntry(conn, then)); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java new file mode 100644 index 00000000000..1a95b667fdd --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.net.CookieManager; +import java.util.List; +import java.util.Map; +import java.util.Set; + +class CookieFilter implements HeaderFilter { + + final HttpClientImpl client; + final CookieManager cookieMan; + + CookieFilter(HttpClientImpl client) { + this.client = client; + this.cookieMan = client.cookieManager().orElseThrow( + () -> new IllegalArgumentException("no cookie manager")); + } + + @Override + public void request(HttpRequestImpl r) throws IOException { + Map> userheaders, cookies; + userheaders = r.getUserHeaders().directMap(); + cookies = cookieMan.get(r.uri(), userheaders); + // add the returned cookies + HttpHeadersImpl systemHeaders = r.getSystemHeaders(); + Set keys = cookies.keySet(); + for (String hdrname : keys) { + List vals = cookies.get(hdrname); + for (String val : vals) { + systemHeaders.addHeader(hdrname, val); + } + } + } + + @Override + public HttpRequestImpl response(HttpResponseImpl r) throws IOException { + HttpHeaders hdrs = r.headers(); + cookieMan.put(r.uri(), hdrs.map()); + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java new file mode 100644 index 00000000000..597b4c0b6a1 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.InetSocketAddress; +import java.net.SocketPermission; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLPermission; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +/** + * One request/response exchange (handles 100/101 intermediate response also). + * depth field used to track number of times a new request is being sent + * for a given API request. If limit exceeded exception is thrown. + * + * Security check is performed here: + * - uses AccessControlContext captured at API level + * - checks for appropriate URLPermission for request + * - if permission allowed, grants equivalent SocketPermission to call + * - in case of direct HTTP proxy, checks additionally for access to proxy + * (CONNECT proxying uses its own Exchange, so check done there) + * + */ +class Exchange { + + final HttpRequestImpl request; + final HttpClientImpl client; + ExchangeImpl exchImpl; + HttpResponseImpl response; + final List permissions = new LinkedList<>(); + AccessControlContext acc; + boolean upgrading; // to HTTP/2 + + Exchange(HttpRequestImpl request) { + this.request = request; + this.upgrading = false; + this.client = request.client(); + } + + /* If different AccessControlContext to be used */ + Exchange(HttpRequestImpl request, AccessControlContext acc) { + this.request = request; + this.acc = acc; + this.upgrading = false; + this.client = request.client(); + } + + public HttpRequestImpl request() { + return request; + } + + public HttpResponseImpl response() throws IOException, InterruptedException { + response = responseImpl(null); + return response; + } + + public void cancel() { + if (exchImpl != null) + exchImpl.cancel(); + } + + public void h2Upgrade() { + upgrading = true; + request.setH2Upgrade(); + } + + static final SocketPermission[] SOCKET_ARRAY = new SocketPermission[0]; + + HttpResponseImpl responseImpl(HttpConnection connection) + throws IOException, InterruptedException + { + if (acc == null) { + acc = request.getAccessControlContext(); + } + SecurityException e = securityCheck(acc); + if (e != null) + throw e; + + if (permissions.size() > 0) { + try { + return AccessController.doPrivileged( + (PrivilegedExceptionAction)() -> + responseImpl0(connection), + null, + permissions.toArray(SOCKET_ARRAY)); + } catch (Throwable ee) { + if (ee instanceof PrivilegedActionException) { + ee = ee.getCause(); + } + if (ee instanceof IOException) + throw (IOException)ee; + else + throw new RuntimeException(ee); // TODO: fix + } + } else { + return responseImpl0(connection); + } + } + + HttpResponseImpl responseImpl0(HttpConnection connection) + throws IOException, InterruptedException + { + exchImpl = ExchangeImpl.get(this, connection); + if (request.expectContinue()) { + request.addSystemHeader("Expect", "100-Continue"); + exchImpl.sendHeadersOnly(); + HttpResponseImpl resp = exchImpl.getResponse(); + logResponse(resp); + if (resp.statusCode() != 100) { + return resp; + } + exchImpl.sendBody(); + return exchImpl.getResponse(); + } else { + exchImpl.sendRequest(); + HttpResponseImpl resp = exchImpl.getResponse(); + logResponse(resp); + return checkForUpgrade(resp, exchImpl); + } + } + + // Completed HttpResponse will be null if response succeeded + // will be a non null responseAsync if expect continue returns an error + + public CompletableFuture responseAsync(Void v) { + return responseAsyncImpl(null); + } + + CompletableFuture responseAsyncImpl(HttpConnection connection) { + if (acc == null) { + acc = request.getAccessControlContext(); + } + SecurityException e = securityCheck(acc); + if (e != null) { + CompletableFuture cf = new CompletableFuture<>(); + cf.completeExceptionally(e); + return cf; + } + if (permissions.size() > 0) { + return AccessController.doPrivileged( + (PrivilegedAction>)() -> + responseAsyncImpl0(connection), + null, + permissions.toArray(SOCKET_ARRAY)); + } else { + return responseAsyncImpl0(connection); + } + } + + CompletableFuture responseAsyncImpl0(HttpConnection connection) { + try { + exchImpl = ExchangeImpl.get(this, connection); + } catch (IOException | InterruptedException e) { + CompletableFuture cf = new CompletableFuture<>(); + cf.completeExceptionally(e); + return cf; + } + if (request.expectContinue()) { + request.addSystemHeader("Expect", "100-Continue"); + return exchImpl.sendHeadersAsync() + .thenCompose(exchImpl::getResponseAsync) + .thenCompose((HttpResponseImpl r1) -> { + int rcode = r1.statusCode(); + CompletableFuture cf = + checkForUpgradeAsync(r1, exchImpl); + if (cf != null) + return cf; + if (rcode == 100) { + return exchImpl.sendBodyAsync() + .thenCompose(exchImpl::getResponseAsync) + .thenApply((r) -> { + logResponse(r); + return r; + }); + } else { + Exchange.this.response = r1; + logResponse(r1); + return CompletableFuture.completedFuture(r1); + } + }); + } else { + return exchImpl + .sendHeadersAsync() + .thenCompose((Void v) -> { + // send body and get response at same time + exchImpl.sendBodyAsync(); + return exchImpl.getResponseAsync(null); + }) + .thenCompose((HttpResponseImpl r1) -> { + int rcode = r1.statusCode(); + CompletableFuture cf = + checkForUpgradeAsync(r1, exchImpl); + if (cf != null) { + return cf; + } else { + Exchange.this.response = r1; + logResponse(r1); + return CompletableFuture.completedFuture(r1); + } + }) + .thenApply((HttpResponseImpl response) -> { + this.response = response; + logResponse(response); + return response; + }); + } + } + + // if this response was received in reply to an upgrade + // then create the Http2Connection from the HttpConnection + // initialize it and wait for the real response on a newly created Stream + + private CompletableFuture + checkForUpgradeAsync(HttpResponseImpl resp, + ExchangeImpl ex) { + int rcode = resp.statusCode(); + if (upgrading && (rcode == 101)) { + Http1Exchange e = (Http1Exchange)ex; + // check for 101 switching protocols + return e.responseBodyAsync(HttpResponse.ignoreBody()) + .thenCompose((Void v) -> + Http2Connection.createAsync(e.connection(), + client.client2(), + this) + .thenCompose((Http2Connection c) -> { + Stream s = c.getStream(1); + exchImpl = s; + c.putConnection(); + return s.getResponseAsync(null); + }) + ); + } + return CompletableFuture.completedFuture(resp); + } + + private HttpResponseImpl checkForUpgrade(HttpResponseImpl resp, + ExchangeImpl ex) + throws IOException, InterruptedException + { + int rcode = resp.statusCode(); + if (upgrading && (rcode == 101)) { + Http1Exchange e = (Http1Exchange) ex; + // must get connection from Http1Exchange + e.responseBody(HttpResponse.ignoreBody(), false); + Http2Connection h2con = new Http2Connection(e.connection(), + client.client2(), + this); + h2con.putConnection(); + Stream s = h2con.getStream(1); + exchImpl = s; + return s.getResponse(); + } + return resp; + } + + + T responseBody(HttpResponse.BodyProcessor processor) { + try { + return exchImpl.responseBody(processor); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + + private void logResponse(HttpResponseImpl r) { + if (!Log.requests()) + return; + StringBuilder sb = new StringBuilder(); + String method = r.request().method(); + URI uri = r.uri(); + String uristring = uri == null ? "" : uri.toString(); + sb.append('(') + .append(method) + .append(" ") + .append(uristring) + .append(") ") + .append(Integer.toString(r.statusCode())); + Log.logResponse(sb.toString()); + } + + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return exchImpl.responseBodyAsync(processor); + } + + private URI getURIForSecurityCheck() { + URI u; + String method = request.method(); + InetSocketAddress authority = request.authority(); + URI uri = request.uri(); + + // CONNECT should be restricted at API level + if (method.equalsIgnoreCase("CONNECT")) { + try { + u = new URI("socket", + null, + authority.getHostString(), + authority.getPort(), + null, + null, + null); + } catch (URISyntaxException e) { + throw new InternalError(e); // shouldn't happen + } + } else { + u = uri; + } + return u; + } + + /** + * Do the security check and return any exception. + * Return null if no check needed or passes. + * + * Also adds any generated permissions to the "permissions" list. + */ + private SecurityException securityCheck(AccessControlContext acc) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + return null; + } + + String method = request.method(); + HttpHeadersImpl userHeaders = request.getUserHeaders(); + URI u = getURIForSecurityCheck(); + URLPermission p = Utils.getPermission(u, method, userHeaders.directMap()); + + try { + assert acc != null; + sm.checkPermission(p, acc); + permissions.add(getSocketPermissionFor(u)); + } catch (SecurityException e) { + return e; + } + InetSocketAddress proxy = request.proxy(); + if (proxy != null) { + // may need additional check + if (!method.equals("CONNECT")) { + // a direct http proxy. Need to check access to proxy + try { + u = new URI("socket", null, proxy.getHostString(), + proxy.getPort(), null, null, null); + } catch (URISyntaxException e) { + throw new InternalError(e); // shouldn't happen + } + p = new URLPermission(u.toString(), "CONNECT"); + try { + sm.checkPermission(p, acc); + } catch (SecurityException e) { + permissions.clear(); + return e; + } + String sockperm = proxy.getHostString() + + ":" + Integer.toString(proxy.getPort()); + + permissions.add(new SocketPermission(sockperm, "connect,resolve")); + } + } + return null; + } + + private static SocketPermission getSocketPermissionFor(URI url) { + if (System.getSecurityManager() == null) + return null; + + StringBuilder sb = new StringBuilder(); + String host = url.getHost(); + sb.append(host); + int port = url.getPort(); + if (port == -1) { + String scheme = url.getScheme(); + if ("http".equals(scheme)) { + sb.append(":80"); + } else { // scheme must be https + sb.append(":443"); + } + } else { + sb.append(':') + .append(Integer.toString(port)); + } + String target = sb.toString(); + return new SocketPermission(target, "connect"); + } + + AccessControlContext getAccessControlContext() { + return acc; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java new file mode 100644 index 00000000000..bc3b6508d3c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import static java.net.http.HttpClient.Version.HTTP_1_1; + +/** + * Splits request so that headers and body can be sent separately with optional + * (multiple) responses in between (e.g. 100 Continue). Also request and + * response always sent/received in different calls. + * + * Synchronous and asynchronous versions of each method are provided. + * + * Separate implementations of this class exist for HTTP/1.1 and HTTP/2 + * Http1Exchange (HTTP/1.1) + * Stream (HTTP/2) + * + * These implementation classes are where work is allocated to threads. + */ +abstract class ExchangeImpl { + + final Exchange exchange; + + ExchangeImpl(Exchange e) { + this.exchange = e; + } + + /** + * Initiates a new exchange and assigns it to a connection if one exists + * already. connection usually null. + */ + static ExchangeImpl get(Exchange exchange, HttpConnection connection) + throws IOException, InterruptedException + { + HttpRequestImpl req = exchange.request(); + if (req.version() == HTTP_1_1) { + return new Http1Exchange(exchange, connection); + } else { + Http2ClientImpl c2 = exchange.request().client().client2(); // TODO: improve + HttpRequestImpl request = exchange.request(); + Http2Connection c = c2.getConnectionFor(request); + if (c == null) { + // no existing connection. Send request with HTTP 1 and then + // upgrade if successful + ExchangeImpl ex = new Http1Exchange(exchange, connection); + exchange.h2Upgrade(); + return ex; + } + return c.createStream(exchange); + } + } + + /* The following methods have separate HTTP/1.1 and HTTP/2 implementations */ + + /** + * Sends the request headers only. May block until all sent. + */ + abstract void sendHeadersOnly() throws IOException, InterruptedException; + + /** + * Gets response headers by blocking if necessary. This may be an + * intermediate response (like 101) or a final response 200 etc. + */ + abstract HttpResponseImpl getResponse() throws IOException; + + /** + * Sends a request body after request headers. + */ + abstract void sendBody() throws IOException, InterruptedException; + + /** + * Sends the entire request (headers and body) blocking. + */ + abstract void sendRequest() throws IOException, InterruptedException; + + /** + * Asynchronous version of sendHeaders(). + */ + abstract CompletableFuture sendHeadersAsync(); + + /** + * Asynchronous version of getResponse(). Requires void parameter for + * CompletableFuture chaining. + */ + abstract CompletableFuture getResponseAsync(Void v); + + /** + * Asynchronous version of sendBody(). + */ + abstract CompletableFuture sendBodyAsync(); + + /** + * Cancels a request. Not currently exposed through API. + */ + abstract void cancel(); + + /** + * Asynchronous version of sendRequest(). + */ + abstract CompletableFuture sendRequestAsync(); + + abstract T responseBody(HttpResponse.BodyProcessor processor) + throws IOException; + + /** + * Asynchronous version of responseBody(). + */ + abstract CompletableFuture + responseBodyAsync(HttpResponse.BodyProcessor processor); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java b/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java new file mode 100644 index 00000000000..ba8a07cf1cc --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.function.Supplier; + +/** + * Wraps the supplied user ExecutorService. + * + * 1) when a Security manager set, the correct access control context + * is used to execute task + * + * 2) memory fence implemented + */ +class ExecutorWrapper { + + final ExecutorService userExecutor; // the actual executor service used + final Executor executor; + + public static ExecutorWrapper wrap(ExecutorService userExecutor) { + return new ExecutorWrapper(userExecutor); + } + + /** + * Returns a dummy ExecutorWrapper which uses the calling thread + */ + public static ExecutorWrapper callingThread() { + return new ExecutorWrapper(); + } + + private ExecutorWrapper(ExecutorService userExecutor) { + // used for executing in calling thread + this.userExecutor = userExecutor; + this.executor = userExecutor; + } + + private ExecutorWrapper() { + this.userExecutor = null; + this.executor = (Runnable command) -> { + command.run(); + }; + } + + public ExecutorService userExecutor() { + return userExecutor; + } + + public synchronized void synchronize() {} + + public void execute(Runnable r, Supplier ctxSupplier) { + synchronize(); + Runnable r1 = () -> { + try { + r.run(); + } catch (Throwable t) { + Log.logError(t); + } + }; + + if (ctxSupplier != null && System.getSecurityManager() != null) { + AccessControlContext acc = ctxSupplier.get(); + if (acc == null) { + throw new InternalError(); + } + AccessController.doPrivilegedWithCombiner( + (PrivilegedAction)() -> { + executor.execute(r1); // all throwables must be caught + return null; + }, acc); + } else { + executor.execute(r1); // all throwables must be caught + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java new file mode 100644 index 00000000000..cf67771331a --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.util.LinkedList; +import java.util.List; + +class FilterFactory { + + final LinkedList> filterClasses = new LinkedList<>(); + + public void addFilter(Class type) { + filterClasses.add(type); + } + + List getFilterChain() { + List l = new LinkedList<>(); + for (Class clazz : filterClasses) { + try { + l.add(clazz.newInstance()); + } catch (ReflectiveOperationException e) { + throw new InternalError(e); + } + } + return l; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java new file mode 100644 index 00000000000..d0fae94ada8 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.io.IOException; + +/** + * A header filter that can examine or modify, typically system headers for + * requests before they are sent, and responses before they are returned to the + * user. Some ability to resend requests is provided. + * + */ +interface HeaderFilter { + + void request(HttpRequestImpl r) throws IOException; + + /** + * Returns null if response ok to be given to user. Non null is a request + * that must be resent and its response given to user. If impl throws an + * exception that is returned to user instead. + */ + HttpRequestImpl response(HttpResponseImpl r) throws IOException; +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java new file mode 100644 index 00000000000..d4922d6a141 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.util.Iterator; +import java.util.Locale; +import java.util.NoSuchElementException; + +/* This is useful for the nightmare of parsing multi-part HTTP/RFC822 headers + * sensibly: + * From a String like: 'timeout=15, max=5' + * create an array of Strings: + * { {"timeout", "15"}, + * {"max", "5"} + * } + * From one like: 'Basic Realm="FuzzFace" Foo="Biz Bar Baz"' + * create one like (no quotes in literal): + * { {"basic", null}, + * {"realm", "FuzzFace"} + * {"foo", "Biz Bar Baz"} + * } + * keys are converted to lower case, vals are left as is.... + */ +class HeaderParser { + + /* table of key/val pairs */ + String raw; + String[][] tab; + int nkeys; + int asize = 10; // initial size of array is 10 + + public HeaderParser(String raw) { + this.raw = raw; + tab = new String[asize][2]; + parse(); + } + + private HeaderParser () { } + + /** + * Creates a new HeaderParser from this, whose keys (and corresponding + * values) range from "start" to "end-1" + */ + public HeaderParser subsequence(int start, int end) { + if (start == 0 && end == nkeys) { + return this; + } + if (start < 0 || start >= end || end > nkeys) + throw new IllegalArgumentException("invalid start or end"); + HeaderParser n = new HeaderParser(); + n.tab = new String [asize][2]; + n.asize = asize; + System.arraycopy (tab, start, n.tab, 0, (end-start)); + n.nkeys= (end-start); + return n; + } + + private void parse() { + + if (raw != null) { + raw = raw.trim(); + char[] ca = raw.toCharArray(); + int beg = 0, end = 0, i = 0; + boolean inKey = true; + boolean inQuote = false; + int len = ca.length; + while (end < len) { + char c = ca[end]; + if ((c == '=') && !inQuote) { // end of a key + tab[i][0] = new String(ca, beg, end-beg).toLowerCase(Locale.US); + inKey = false; + end++; + beg = end; + } else if (c == '\"') { + if (inQuote) { + tab[i++][1]= new String(ca, beg, end-beg); + inQuote=false; + do { + end++; + } while (end < len && (ca[end] == ' ' || ca[end] == ',')); + inKey=true; + beg=end; + } else { + inQuote=true; + end++; + beg=end; + } + } else if (c == ' ' || c == ',') { // end key/val, of whatever we're in + if (inQuote) { + end++; + continue; + } else if (inKey) { + tab[i++][0] = (new String(ca, beg, end-beg)).toLowerCase(Locale.US); + } else { + tab[i++][1] = (new String(ca, beg, end-beg)); + } + while (end < len && (ca[end] == ' ' || ca[end] == ',')) { + end++; + } + inKey = true; + beg = end; + } else { + end++; + } + if (i == asize) { + asize = asize * 2; + String[][] ntab = new String[asize][2]; + System.arraycopy (tab, 0, ntab, 0, tab.length); + tab = ntab; + } + } + // get last key/val, if any + if (--end > beg) { + if (!inKey) { + if (ca[end] == '\"') { + tab[i++][1] = (new String(ca, beg, end-beg)); + } else { + tab[i++][1] = (new String(ca, beg, end-beg+1)); + } + } else { + tab[i++][0] = (new String(ca, beg, end-beg+1)).toLowerCase(); + } + } else if (end == beg) { + if (!inKey) { + if (ca[end] == '\"') { + tab[i++][1] = String.valueOf(ca[end-1]); + } else { + tab[i++][1] = String.valueOf(ca[end]); + } + } else { + tab[i++][0] = String.valueOf(ca[end]).toLowerCase(); + } + } + nkeys=i; + } + } + + public String findKey(int i) { + if (i < 0 || i > asize) + return null; + return tab[i][0]; + } + + public String findValue(int i) { + if (i < 0 || i > asize) + return null; + return tab[i][1]; + } + + public String findValue(String key) { + return findValue(key, null); + } + + public String findValue(String k, String Default) { + if (k == null) + return Default; + k = k.toLowerCase(Locale.US); + for (int i = 0; i < asize; ++i) { + if (tab[i][0] == null) { + return Default; + } else if (k.equals(tab[i][0])) { + return tab[i][1]; + } + } + return Default; + } + + class ParserIterator implements Iterator { + int index; + boolean returnsValue; // or key + + ParserIterator (boolean returnValue) { + returnsValue = returnValue; + } + @Override + public boolean hasNext () { + return index= nkeys) + throw new NoSuchElementException(); + return tab[index++][returnsValue?1:0]; + } + } + + public Iterator keys () { + return new ParserIterator (false); + } + + public Iterator values () { + return new ParserIterator (true); + } + + @Override + public String toString () { + Iterator k = keys(); + StringBuilder sb = new StringBuilder(); + sb.append("{size=").append(asize).append(" nkeys=").append(nkeys) + .append(' '); + for (int i=0; k.hasNext(); i++) { + String key = k.next(); + String val = findValue (i); + if (val != null && "".equals (val)) { + val = null; + } + sb.append(" {").append(key).append(val == null ? "" : "," + val) + .append('}'); + if (k.hasNext()) { + sb.append (','); + } + } + sb.append (" }"); + return sb.toString(); + } + + public int findInt(String k, int Default) { + try { + return Integer.parseInt(findValue(k, String.valueOf(Default))); + } catch (Throwable t) { + return Default; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java new file mode 100644 index 00000000000..3266eada6c6 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.concurrent.CompletableFuture; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Encapsulates one HTTP/1.1 request/responseAsync exchange. + */ +class Http1Exchange extends ExchangeImpl { + + final HttpRequestImpl request; // main request + final List> operations; // used for cancel + final Http1Request requestAction; + volatile Http1Response response; + final HttpConnection connection; + final HttpClientImpl client; + final ExecutorWrapper executor; + + @Override + public String toString() { + return request.toString(); + } + + HttpRequestImpl request() { + return request; + } + + Http1Exchange(Exchange exchange, HttpConnection connection) + throws IOException + { + super(exchange); + this.request = exchange.request(); + this.client = request.client(); + this.executor = client.executorWrapper(); + this.operations = Collections.synchronizedList(new LinkedList<>()); + if (connection != null) { + this.connection = connection; + } else { + InetSocketAddress addr = getAddress(request); + this.connection = HttpConnection.getConnection(addr, request); + } + this.requestAction = new Http1Request(request, this.connection); + } + + private static InetSocketAddress getAddress(HttpRequestImpl req) { + URI uri = req.uri(); + if (uri == null) { + return req.authority(); + } + int port = uri.getPort(); + if (port == -1) { + if (uri.getScheme().equalsIgnoreCase("https")) { + port = 443; + } else { + port = 80; + } + } + String host = uri.getHost(); + if (req.proxy() == null) { + return new InetSocketAddress(host, port); + } else { + return InetSocketAddress.createUnresolved(host, port); + } + } + + HttpConnection connection() { + return connection; + } + + @Override + T responseBody(HttpResponse.BodyProcessor processor) + throws IOException + { + return responseBody(processor, true); + } + + T responseBody(HttpResponse.BodyProcessor processor, + boolean return2Cache) + throws IOException + { + try { + T body = response.readBody(processor, return2Cache); + return body; + } catch (Throwable t) { + connection.close(); + throw t; + } + } + + @Override + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + CompletableFuture cf = new CompletableFuture<>(); + request.client() + .executorWrapper() + .execute(() -> { + try { + T body = responseBody(processor); + cf.complete(body); + } catch (Throwable e) { + cf.completeExceptionally(e); + } + }, + () -> response.response.getAccessControlContext()); // TODO: fix + return cf; + } + + @Override + void sendHeadersOnly() throws IOException, InterruptedException { + try { + if (!connection.connected()) { + connection.connect(); + } + requestAction.sendHeadersOnly(); + } catch (Throwable e) { + connection.close(); + throw e; + } + } + + @Override + void sendBody() throws IOException { + try { + requestAction.continueRequest(); + } catch (Throwable e) { + connection.close(); + throw e; + } + } + + @Override + HttpResponseImpl getResponse() throws IOException { + try { + response = new Http1Response(connection, this); + response.readHeaders(); + return response.response(); + } catch (Throwable t) { + connection.close(); + throw t; + } + } + + @Override + void sendRequest() throws IOException, InterruptedException { + try { + if (!connection.connected()) { + connection.connect(); + } + requestAction.sendRequest(); + } catch (Throwable t) { + connection.close(); + throw t; + } + } + + private void closeConnection() { + connection.close(); + } + + @Override + CompletableFuture sendHeadersAsync() { + if (!connection.connected()) { + CompletableFuture op = connection.connectAsync() + .thenCompose(this::sendHdrsAsyncImpl) + .whenComplete((Void b, Throwable t) -> { + if (t != null) + closeConnection(); + }); + operations.add(op); + return op; + } else { + return sendHdrsAsyncImpl(null); + } + } + + private CompletableFuture sendHdrsAsyncImpl(Void v) { + CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + requestAction.sendHeadersOnly(); + cf.complete(null); + } catch (Throwable e) { + cf.completeExceptionally(e); + connection.close(); + } + }, + () -> request.getAccessControlContext()); + operations.add(cf); + return cf; + } + + /** + * Cancel checks to see if request and responseAsync finished already. + * If not it closes the connection and completes all pending operations + */ + @Override + synchronized void cancel() { + if (requestAction != null && requestAction.finished() + && response != null && response.finished()) { + return; + } + connection.close(); + IOException e = new IOException("Request cancelled"); + int count = 0; + for (CompletableFuture cf : operations) { + cf.completeExceptionally(e); + count++; + } + Log.logError("Http1Exchange.cancel: count=" + count); + } + + CompletableFuture getResponseAsyncImpl(Void v) { + CompletableFuture cf = new CompletableFuture<>(); + try { + response = new Http1Response(connection, Http1Exchange.this); + response.readHeaders(); + cf.complete(response.response()); + } catch (IOException e) { + cf.completeExceptionally(e); + } + return cf; + } + + @Override + CompletableFuture getResponseAsync(Void v) { + CompletableFuture cf = + connection.whenReceivingResponse() + .thenCompose(this::getResponseAsyncImpl); + + operations.add(cf); + return cf; + } + + @Override + CompletableFuture sendBodyAsync() { + final CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + requestAction.continueRequest(); + cf.complete(null); + } catch (Throwable e) { + cf.completeExceptionally(e); + connection.close(); + } + }, () -> request.getAccessControlContext()); + operations.add(cf); + return cf; + } + + @Override + CompletableFuture sendRequestAsync() { + CompletableFuture op; + if (!connection.connected()) { + op = connection.connectAsync() + .thenCompose(this::sendRequestAsyncImpl) + .whenComplete((Void v, Throwable t) -> { + if (t != null) { + closeConnection(); + } + }); + } else { + op = sendRequestAsyncImpl(null); + } + operations.add(op); + return op; + } + + CompletableFuture sendRequestAsyncImpl(Void v) { + CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + requestAction.sendRequest(); + cf.complete(null); + } catch (Throwable e) { + cf.completeExceptionally(e); + connection.close(); + } + }, () -> request.getAccessControlContext()); + operations.add(cf); + return cf; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java new file mode 100644 index 00000000000..f0da88b3b5c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.function.LongConsumer; +import static java.nio.charset.StandardCharsets.US_ASCII; + +/** + * A HTTP/1.1 request. + * + * send() -> Writes the request + body to the given channel, in one blocking + * operation. + */ +class Http1Request { + + final HttpRequestImpl request; + final HttpConnection chan; + // Multiple buffers are used to hold different parts of request + // See line 206 and below for description + final ByteBuffer[] buffers; + final HttpRequest.BodyProcessor requestProc; + final HttpHeadersImpl userHeaders, systemHeaders; + final LongConsumer flowController; + boolean streaming; + long contentLength; + + Http1Request(HttpRequestImpl request, HttpConnection connection) + throws IOException + { + this.request = request; + this.chan = connection; + buffers = new ByteBuffer[5]; // TODO: check + this.requestProc = request.requestProcessor(); + this.userHeaders = request.getUserHeaders(); + this.systemHeaders = request.getSystemHeaders(); + this.flowController = this::dummy; + } + + private void logHeaders() throws IOException { + StringBuilder sb = new StringBuilder(256); + sb.append("REQUEST HEADERS:\r\n"); + collectHeaders1(sb, request, systemHeaders); + collectHeaders1(sb, request, userHeaders); + Log.logHeaders(sb.toString()); + } + + private void dummy(long x) { + // not used in this class + } + + private void collectHeaders0() throws IOException { + if (Log.headers()) { + logHeaders(); + } + StringBuilder sb = new StringBuilder(256); + collectHeaders1(sb, request, systemHeaders); + collectHeaders1(sb, request, userHeaders); + sb.append("\r\n"); + String headers = sb.toString(); + buffers[1] = ByteBuffer.wrap(headers.getBytes(StandardCharsets.US_ASCII)); + } + + private void collectHeaders1(StringBuilder sb, + HttpRequestImpl request, + HttpHeadersImpl headers) + throws IOException + { + Map> h = headers.directMap(); + Set>> entries = h.entrySet(); + + for (Map.Entry> entry : entries) { + String key = entry.getKey(); + sb.append(key).append(": "); + List values = entry.getValue(); + int num = values.size(); + for (String value : values) { + sb.append(value); + if (--num > 0) { + sb.append(','); + } + } + sb.append("\r\n"); + } + } + + private static final int BUFSIZE = 64 * 1024; // TODO: configurable? + + private String getPathAndQuery(URI uri) { + String path = uri.getPath(); + String query = uri.getQuery(); + if (path == null || path.equals("")) { + path = "/"; + } + if (query == null) { + query = ""; + } + if (query.equals("")) { + return path; + } else { + return path + "?" + query; + } + } + + private String authorityString(InetSocketAddress addr) { + return addr.getHostString() + ":" + addr.getPort(); + } + + private String requestURI() { + URI uri = request.uri(); + String method = request.method(); + + if ((request.proxy() == null && !method.equals("CONNECT")) + || request.isWebSocket()) { + return getPathAndQuery(uri); + } + if (request.secure()) { + if (request.method().equals("CONNECT")) { + // use authority for connect itself + return authorityString(request.authority()); + } else { + // requests over tunnel do not require full URL + return getPathAndQuery(uri); + } + } + return uri == null? authorityString(request.authority()) : uri.toString(); + } + + void sendHeadersOnly() throws IOException { + collectHeaders(); + chan.write(buffers, 0, 2); + } + + void sendRequest() throws IOException { + collectHeaders(); + if (contentLength == 0) { + chan.write(buffers, 0, 2); + } else if (contentLength > 0) { + writeFixedContent(true); + } else { + writeStreamedContent(true); + } + setFinished(); + } + + private boolean finished; + + synchronized boolean finished() { + return finished; + } + + synchronized void setFinished() { + finished = true; + } + + private void collectHeaders() throws IOException { + if (Log.requests() && request != null) { + Log.logRequest(request.toString()); + } + String uriString = requestURI(); + StringBuilder sb = new StringBuilder(64); + sb.append(request.method()) + .append(' ') + .append(uriString) + .append(" HTTP/1.1\r\n"); + String cmd = sb.toString(); + + buffers[0] = ByteBuffer.wrap(cmd.getBytes(StandardCharsets.US_ASCII)); + URI uri = request.uri(); + if (uri != null) { + systemHeaders.setHeader("Host", uri.getHost()); + } + if (request == null) { + // this is not a user request. No content + contentLength = 0; + } else { + contentLength = requestProc.onRequestStart(request, flowController); + } + + if (contentLength == 0) { + systemHeaders.setHeader("Content-Length", "0"); + collectHeaders0(); + } else if (contentLength > 0) { + /* [0] request line [1] headers [2] body */ + systemHeaders.setHeader("Content-Length", + Integer.toString((int) contentLength)); + streaming = false; + collectHeaders0(); + buffers[2] = chan.getBuffer(); + } else { + /* Chunked: + * + * [0] request line [1] headers [2] chunk header [3] chunk data [4] + * final chunk header and trailing CRLF of previous chunks + * + * 2,3,4 used repeatedly */ + streaming = true; + systemHeaders.setHeader("Transfer-encoding", "chunked"); + collectHeaders0(); + buffers[3] = chan.getBuffer(); + } + } + + // The following two methods used by Http1Exchange to handle expect continue + + void continueRequest() throws IOException { + if (streaming) { + writeStreamedContent(false); + } else { + writeFixedContent(false); + } + setFinished(); + } + + /* Entire request is sent, or just body only */ + private void writeStreamedContent(boolean includeHeaders) + throws IOException + { + if (requestProc instanceof HttpRequest.BodyProcessor) { + HttpRequest.BodyProcessor pullproc = requestProc; + int startbuf, nbufs; + + if (includeHeaders) { + startbuf = 0; + nbufs = 5; + } else { + startbuf = 2; + nbufs = 3; + } + try { + // TODO: currently each write goes out as one chunk + // TODO: should be collecting data and buffer it. + + buffers[3].clear(); + boolean done = pullproc.onRequestBodyChunk(buffers[3]); + int chunklen = buffers[3].position(); + buffers[2] = getHeader(chunklen); + buffers[3].flip(); + buffers[4] = CRLF_BUFFER(); + chan.write(buffers, startbuf, nbufs); + while (!done) { + buffers[3].clear(); + done = pullproc.onRequestBodyChunk(buffers[3]); + if (done) + break; + buffers[3].flip(); + chunklen = buffers[3].remaining(); + buffers[2] = getHeader(chunklen); + buffers[4] = CRLF_BUFFER(); + chan.write(buffers, 2, 3); + } + buffers[3] = EMPTY_CHUNK_HEADER(); + buffers[4] = CRLF_BUFFER(); + chan.write(buffers, 3, 2); + } catch (IOException e) { + requestProc.onRequestError(e); + throw e; + } + } + } + /* Entire request is sent, or just body only */ + private void writeFixedContent(boolean includeHeaders) + throws IOException + { + try { + int startbuf, nbufs; + + if (contentLength == 0) { + return; + } + if (includeHeaders) { + startbuf = 0; + nbufs = 3; + } else { + startbuf = 2; + nbufs = 1; + buffers[0].clear().flip(); + buffers[1].clear().flip(); + } + buffers[2] = chan.getBuffer(); + if (requestProc instanceof HttpRequest.BodyProcessor) { + HttpRequest.BodyProcessor pullproc = requestProc; + + boolean done = pullproc.onRequestBodyChunk(buffers[2]); + buffers[2].flip(); + long headersLength = buffers[0].remaining() + buffers[1].remaining(); + long contentWritten = buffers[2].remaining(); + chan.checkWrite(headersLength + contentWritten, + buffers, + startbuf, + nbufs); + while (!done) { + buffers[2].clear(); + done = pullproc.onRequestBodyChunk(buffers[2]); + buffers[2].flip(); + long len = buffers[2].remaining(); + if (contentWritten + len > contentLength) { + break; + } + chan.checkWrite(len, buffers[2]); + contentWritten += len; + } + if (contentWritten != contentLength) { + throw new IOException("wrong content length"); + } + } + } catch (IOException e) { + requestProc.onRequestError(e); + throw e; + } + } + + private static final byte[] CRLF = {'\r', '\n'}; + private static final byte[] EMPTY_CHUNK_BYTES = {'0', '\r', '\n'}; + + private ByteBuffer CRLF_BUFFER() { + return ByteBuffer.wrap(CRLF); + } + + private ByteBuffer EMPTY_CHUNK_HEADER() { + return ByteBuffer.wrap(EMPTY_CHUNK_BYTES); + } + + /* Returns a header for a particular chunk size */ + private static ByteBuffer getHeader(int size){ + String hexStr = Integer.toHexString(size); + byte[] hexBytes = hexStr.getBytes(US_ASCII); + byte[] header = new byte[hexStr.length()+2]; + System.arraycopy(hexBytes, 0, header, 0, hexBytes.length); + header[hexBytes.length] = CRLF[0]; + header[hexBytes.length+1] = CRLF[1]; + return ByteBuffer.wrap(header); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java new file mode 100644 index 00000000000..6fad37b6b8f --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.LongConsumer; +import static java.net.http.HttpClient.Version.HTTP_1_1; + +/** + * Handles a HTTP/1.1 response in two blocking calls. readHeaders() and + * readBody(). There can be more than one of these per Http exchange. + */ +class Http1Response { + + private ResponseContent content; + private final HttpRequestImpl request; + HttpResponseImpl response; + private final HttpConnection connection; + private ResponseHeaders headers; + private int responseCode; + private ByteBuffer buffer; // same buffer used for reading status line and headers + private final Http1Exchange exchange; + private final boolean redirecting; // redirecting + private boolean return2Cache; // return connection to cache when finished + + Http1Response(HttpConnection conn, Http1Exchange exchange) { + this.request = exchange.request(); + this.exchange = exchange; + this.connection = conn; + this.redirecting = false; + buffer = connection.getRemaining(); + } + + // called when the initial read should come from a buffer left + // over from a previous response. + void setBuffer(ByteBuffer buffer) { + this.buffer = buffer; + } + + @SuppressWarnings("unchecked") + public void readHeaders() throws IOException { + String statusline = readStatusLine(); + if (statusline == null) { + if (Log.errors()) { + Log.logError("Connection closed. Retry"); + } + connection.close(); + // connection was closed + throw new IOException("Connection closed"); + } + if (!statusline.startsWith("HTTP/1.")) { + throw new IOException("Invalid status line: " + statusline); + } + char c = statusline.charAt(7); + responseCode = Integer.parseInt(statusline.substring(9, 12)); + + headers = new ResponseHeaders(connection, buffer); + headers.initHeaders(); + if (Log.headers()) { + logHeaders(headers); + } + response = new HttpResponseImpl(responseCode, + exchange.exchange, + headers, + null, + connection.sslParameters(), + HTTP_1_1, + connection); + } + + private boolean finished; + + synchronized void completed() { + finished = true; + } + + synchronized boolean finished() { + return finished; + } + + // Blocking flow controller implementation. Only works when a + // thread is dedicated to reading response body + + static class FlowController implements LongConsumer { + long window ; + + @Override + public synchronized void accept(long value) { + window += value; + notifyAll(); + } + + public synchronized void request(long value) throws InterruptedException { + while (window < value) { + wait(); + } + window -= value; + } + } + + FlowController flowController; + + int fixupContentLen(int clen) { + if (request.method().equalsIgnoreCase("HEAD")) { + return 0; + } + if (clen == -1) { + if (headers.firstValue("Transfer-encoding").orElse("") + .equalsIgnoreCase("chunked")) { + return -1; + } + return 0; + } + return clen; + } + + private void returnBuffer(ByteBuffer buf) { + // not currently used, but will be when we change SSL to use fixed + // sized buffers and a single buffer pool for HttpClientImpl + } + + @SuppressWarnings("unchecked") + public T readBody(java.net.http.HttpResponse.BodyProcessor p, + boolean return2Cache) + throws IOException + { + T body = null; // TODO: check null case below + this.return2Cache = return2Cache; + final java.net.http.HttpResponse.BodyProcessor pusher = p; + + int clen0 = headers.getContentLength(); + final int clen = fixupContentLen(clen0); + + flowController = new FlowController(); + + body = pusher.onResponseBodyStart(clen, headers, flowController); + + ExecutorWrapper executor; + if (body == null) { + executor = ExecutorWrapper.callingThread(); + } else { + executor = request.client().executorWrapper(); + } + + final ResponseHeaders h = headers; + if (body == null) { + content = new ResponseContent(connection, + clen, + h, + pusher, + flowController); + content.pushBody(headers.getResidue()); + body = pusher.onResponseComplete(); + completed(); + onFinished(); + return body; + } else { + executor.execute(() -> { + try { + content = new ResponseContent(connection, + clen, + h, + pusher, + flowController); + content.pushBody(headers.getResidue()); + pusher.onResponseComplete(); + completed(); + onFinished(); + } catch (Throwable e) { + pusher.onResponseError(e); + } + }, + () -> response.getAccessControlContext()); + } + return body; + } + + private void onFinished() { + connection.buffer = content.getResidue(); + if (return2Cache) { + connection.returnToCache(headers); + } + } + + private void logHeaders(ResponseHeaders headers) { + Map> h = headers.mapInternal(); + Set keys = h.keySet(); + Set>> entries = h.entrySet(); + for (Map.Entry> entry : entries) { + String key = entry.getKey(); + StringBuilder sb = new StringBuilder(); + sb.append(key).append(": "); + List values = entry.getValue(); + if (values != null) { + for (String value : values) { + sb.append(value).append(' '); + } + } + Log.logHeaders(sb.toString()); + } + } + + HttpResponseImpl response() { + return response; + } + + boolean redirecting() { + return redirecting; + } + + HttpHeaders responseHeaders() { + return headers; + } + + int responseCode() { + return responseCode; + } + + static final char CR = '\r'; + static final char LF = '\n'; + + private ByteBuffer getBuffer() throws IOException { + if (buffer == null || !buffer.hasRemaining()) { + buffer = connection.read(); + } + return buffer; + } + + ByteBuffer buffer() { + return buffer; + } + + String readStatusLine() throws IOException { + boolean cr = false; + StringBuilder statusLine = new StringBuilder(128); + ByteBuffer b; + while ((b = getBuffer()) != null) { + byte[] buf = b.array(); + int offset = b.position(); + int len = b.limit() - offset; + + for (int i = 0; i < len; i++) { + char c = (char) buf[i+offset]; + + if (cr) { + if (c == LF) { + b.position(i + 1 + offset); + return statusLine.toString(); + } else { + throw new IOException("invalid status line"); + } + } + if (c == CR) { + cr = true; + } else { + statusLine.append(c); + } + } + // unlikely, but possible, that multiple reads required + b.position(b.limit()); + } + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java new file mode 100644 index 00000000000..4491168225b --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, 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 + */ +package java.net.http; + +class Http2ClientImpl { + Http2ClientImpl(HttpClientImpl t) {} + String getSettingsString() {return "";} + void debugPrint() {} + Http2Connection getConnectionFor(HttpRequestImpl r) { + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java new file mode 100644 index 00000000000..3f60c4f805e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.ProxySelector; +import java.net.URI; +import static java.net.http.Utils.BUFSIZE; +import java.nio.ByteBuffer; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import static java.nio.channels.SelectionKey.OP_CONNECT; +import static java.nio.channels.SelectionKey.OP_READ; +import static java.nio.channels.SelectionKey.OP_WRITE; +import java.nio.channels.Selector; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.*; +import java.security.NoSuchAlgorithmException; +import java.util.ListIterator; +import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +class Http2Connection { + static CompletableFuture createAsync( + HttpConnection connection, Http2ClientImpl client2, Exchange exchange) { + return null; + } + + Http2Connection(HttpConnection connection, Http2ClientImpl client2, + Exchange exchange) throws IOException, InterruptedException { + } + + Stream getStream(int i) {return null;} + Stream createStream(Exchange ex) {return null;} + void putConnection() {} +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java new file mode 100644 index 00000000000..d0989f399cb --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ + +package java.net.http; + +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.InetSocketAddress; +import java.net.NetPermission; +import java.net.ProxySelector; +import java.net.URI; +import java.util.Optional; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +/** + * A container for configuration information common to multiple {@link + * HttpRequest}s. All requests are associated with, and created from a {@code + * HttpClient}. + * + *

      {@code HttpClient}s are immutable and created from a builder returned + * from {@link HttpClient#create()}. Request builders that are associated with + * an application created client, are created by calling {@link #request(URI) }. + * It is also possible to create a request builder directly which is associated + * with the default {@code HttpClient} by calling {@link + * HttpRequest#create(URI)}. + * + *

      The HTTP API functions asynchronously (using {@link + * java.util.concurrent.CompletableFuture}) and also in a simple synchronous + * mode, where all work may be done on the calling thread. In asynchronous mode, + * work is done on the threads supplied by the client's {@link + * java.util.concurrent.ExecutorService}. + * + *

      The default {@code HttpClient} is + * used whenever a request is created without specifying a client explicitly + * (by calling {@link HttpRequest#create(java.net.URI) HttpRequest.create}). + * There is only one static instance of this {@code HttpClient}. A reference to + * the default client can be obtained by calling {@link #getDefault() }. If a + * security manager is set, then a permission is required for this. + * + *

      See {@link HttpRequest} for examples of usage of this API. + * + * @since 9 + */ +public abstract class HttpClient { + + HttpClient() {} + + private static HttpClient defaultClient; + + /** + * Creates a new {@code HttpClient} builder. + * + * @return a {@code HttpClient.Builder} + */ + public static Builder create() { + return new HttpClientBuilderImpl(); + } + + //public abstract void debugPrint(); + + /** + * Returns the default {@code HttpClient} that is used when a {@link + * HttpRequest} is created without specifying a client. If a security + * manager is set, then its {@code checkPermission} method is called with a + * {@link java.net.NetPermission} specifying the name "getDefaultHttpClient". + * If the caller does not possess this permission a {@code SecurityException} + * is thrown. + * + * @implNote Code running under a security manager can avoid the security + * manager check by creating a {@code HttpClient} explicitly. + * + * @return the default {@code HttpClient} + * @throws SecurityException if the caller does not have the required + * permission + */ + public synchronized static HttpClient getDefault() { + Utils.checkNetPermission("getDefaultHttpClient"); + if (defaultClient == null) { + Builder b = create(); + defaultClient = b.executorService(Executors.newCachedThreadPool()) + .build(); + } + return defaultClient; + } + + /** + * Creates a {@code HttpRequest} builder associated with this client. + * + * @return a new builder + */ + public abstract HttpRequest.Builder request(); + + /** + * Creates a {@code HttpRequest} builder associated with this client and + * using the given request URI. + * + * @param uri the request URI + * @return a new builder + */ + public abstract HttpRequest.Builder request(URI uri); + + /** + * A builder of immutable {@link HttpClient}s. {@code HttpClient.Builder}s + * are created by calling {@link HttpClient#create()}. + * + *

      Each of the setter methods in this class modifies the state of the + * builder and returns this (ie. the same instance). The methods are + * not synchronized and should not be called from multiple threads without + * external synchronization. + * + *

      {@link #build() } returns a new {@code HttpClient} each time it is + * called. + * + * @since 9 + */ + public abstract static class Builder { + + Builder() {} + + /** + * Sets a cookie manager. + * + * @param manager the CookieManager + * @return this builder + * @throws NullPointerException if {@code manager} is null + */ + public abstract Builder cookieManager(CookieManager manager); + + /** + * Sets an SSLContext. If a security manager is set, then the caller + * must have the {@link java.net.NetPermission NetPermission} + * ("setSSLContext") + * + *

      The effect of not calling this method, is that a default {@link + * javax.net.ssl.SSLContext} is used, which is normally adequate for + * client applications that do not need to specify protocols, or require + * client authentication. + * + * @param sslContext the SSLContext + * @return this builder + * @throws NullPointerException if {@code sslContext} is null + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission + */ + public abstract Builder sslContext(SSLContext sslContext); + + /** + * Sets an SSLParameters. If this method is not called, then a default + * set of parameters are used. The contents of the given object are + * copied. Some parameters which are used internally by the HTTP protocol + * implementation (such as application protocol list) should not be set + * by callers, as they are ignored. + * + * @param sslParameters the SSLParameters + * @return this builder + * @throws NullPointerException if {@code sslParameters} is null + */ + public abstract Builder sslParameters(SSLParameters sslParameters); + + /** + * Sets the ExecutorService to be used for sending and receiving + * asynchronous requests. If this method is not called, a default + * executor service is set, which is the one returned from {@link + * java.util.concurrent.Executors#newCachedThreadPool() + * Executors.newCachedThreadPool}. + * + * @param s the ExecutorService + * @return this builder + * @throws NullPointerException if {@code s} is null + */ + public abstract Builder executorService(ExecutorService s); + + /** + * Specifies whether requests will automatically follow redirects issued + * by the server. This setting can be overridden on each request. The + * default value for this setting is {@link Redirect#NEVER NEVER} + * + * @param policy the redirection policy + * @return this builder + * @throws NullPointerException if {@code policy} is null + */ + public abstract Builder followRedirects(Redirect policy); + + /** + * Requests a specific HTTP protocol version where possible. If not set, + * the version defaults to {@link HttpClient.Version#HTTP_1_1}. If + * {@link HttpClient.Version#HTTP_2} is set, then each request will + * attempt to upgrade to HTTP/2. If the upgrade succeeds, then the + * response to this request will use HTTP/2 and all subsequent requests + * and responses to the same + * origin server + * will use HTTP/2. If the upgrade fails, then the response will be + * handled using HTTP/1.1 + * + *

      This setting can be over-ridden per request. + * + * @param version the requested HTTP protocol version + * @return this builder + * @throws NullPointerException if {@code version} is null + */ + public abstract Builder version(HttpClient.Version version); + + /** + * Sets the default priority for any HTTP/2 requests sent from this + * client. The value provided must be between {@code 1} and {@code 255}. + * + * @param priority the priority weighting + * @return this builder + * @throws IllegalArgumentException if the given priority is out of range + */ + public abstract Builder priority(int priority); + + /** + * Enables pipelining mode for HTTP/1.1 requests sent through this + * client. When pipelining is enabled requests to the same destination + * are sent over existing TCP connections that may already have requests + * outstanding. This reduces the number of connections, but may have + * a performance impact since responses must be delivered in the same + * order that they were sent. By default, pipelining is disabled. + * + * @param enable {@code true} enables pipelining + * @return this builder + * @throws UnsupportedOperationException if pipelining mode is not + * supported by this implementation + */ + public abstract Builder pipelining(boolean enable); + + /** + * Sets a {@link java.net.ProxySelector} for this client. If no selector + * is set, then no proxies are used. If a {@code null} parameter is + * given then the system wide default proxy selector is used. + * + * @implNote {@link java.net.ProxySelector#of(InetSocketAddress)} + * provides a ProxySelector which uses one proxy for all requests. + * + * @param selector the ProxySelector + * @return this builder + */ + public abstract Builder proxy(ProxySelector selector); + + /** + * Sets an authenticator to use for HTTP authentication. + * + * @param a the Authenticator + * @return this builder + */ + public abstract Builder authenticator(Authenticator a); + + /** + * Returns a {@link HttpClient} built from the current state of this + * builder. + * + * @return this builder + */ + public abstract HttpClient build(); + } + + + /** + * Returns an {@code Optional} which contains this client's {@link + * CookieManager}. If no CookieManager was set in this client's builder, + * then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's CookieManager + */ + public abstract Optional cookieManager(); + + /** + * Returns the follow-redirects setting for this client. The default value + * for this setting is {@link HttpClient.Redirect#NEVER} + * + * @return this client's follow redirects setting + */ + public abstract Redirect followRedirects(); + + /** + * Returns an {@code Optional} containing the ProxySelector for this client. + * If no proxy is set then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's proxy selector + */ + public abstract Optional proxy(); + + /** + * Returns the SSLContext, if one was set on this client. If a security + * manager is set then then caller must then the caller must have the + * {@link java.net.NetPermission NetPermission}("getSSLContext") permission. + * If no SSLContext was set, then the default context is returned. + * + * @return this client's SSLContext + */ + public abstract SSLContext sslContext(); + + /** + * Returns an {@code Optional} containing the {@link SSLParameters} set on + * this client. If no {@code SSLParameters} were set in the client's builder, + * then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's SSLParameters + */ + public abstract Optional sslParameters(); + + /** + * Returns an {@code Optional} containing the {@link Authenticator} set on + * this client. If no {@code Authenticator} was set in the client's builder, + * then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's Authenticator + */ + public abstract Optional authenticator(); + + /** + * Returns the HTTP protocol version requested for this client. The default + * value is {@link HttpClient.Version#HTTP_1_1} + * + * @return the HTTP protocol version requested + */ + public abstract HttpClient.Version version(); + + /** + * Returns whether this client supports HTTP/1.1 pipelining. + * + * @return whether pipelining allowed + */ + public abstract boolean pipelining(); + + /** + * Returns the {@code ExecutorService} set on this client. If an {@code + * ExecutorService} was not set on the client's builder, then a default + * object is returned. The default ExecutorService is created independently + * for each client. + * + * @return this client's ExecutorService + */ + public abstract ExecutorService executorService(); + + /** + * The HTTP protocol version. + * + * @since 9 + */ + public static enum Version { + + /** + * HTTP version 1.1 + */ + HTTP_1_1, + + /** + * HTTP version 2 + */ + HTTP_2 + } + + /** + * Defines automatic redirection policy. This is checked whenever a 3XX + * response code is received. If redirection does not happen automatically + * then the response is returned to the user, where it can be handled + * manually. + * + *

      {@code Redirect} policy is set via the {@link + * HttpClient.Builder#followRedirects(HttpClient.Redirect)} method. + * + * @since 9 + */ + public static enum Redirect { + + /** + * Never redirect. + */ + NEVER, + + /** + * Always redirect. + */ + ALWAYS, + + /** + * Redirect to same protocol only. Redirection may occur from HTTP URLs + * to other HTTP URLs, and from HTTPS URLs to other HTTPS URLs. + */ + SAME_PROTOCOL, + + /** + * Redirect always except from HTTPS URLs to HTTP URLs. + */ + SECURE + } + +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java new file mode 100644 index 00000000000..c93025d477a --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.ProxySelector; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +class HttpClientBuilderImpl extends HttpClient.Builder { + + CookieManager cookieManager; + HttpClient.Redirect followRedirects; + ProxySelector proxy; + Authenticator authenticator; + HttpClient.Version version = HttpClient.Version.HTTP_1_1; + ExecutorService executor; + // Security parameters + SSLContext sslContext; + SSLParameters sslParams; + int priority = -1; + + @Override + public HttpClientBuilderImpl cookieManager(CookieManager manager) { + Objects.requireNonNull(manager); + this.cookieManager = manager; + return this; + } + + + @Override + public HttpClientBuilderImpl sslContext(SSLContext sslContext) { + Objects.requireNonNull(sslContext); + Utils.checkNetPermission("setSSLContext"); + this.sslContext = sslContext; + return this; + } + + + @Override + public HttpClientBuilderImpl sslParameters(SSLParameters sslParameters) { + Objects.requireNonNull(sslParameters); + this.sslParams = sslParameters; + return this; + } + + + @Override + public HttpClientBuilderImpl executorService(ExecutorService s) { + Objects.requireNonNull(s); + this.executor = s; + return this; + } + + + @Override + public HttpClientBuilderImpl followRedirects(HttpClient.Redirect policy) { + Objects.requireNonNull(policy); + this.followRedirects = policy; + return this; + } + + + @Override + public HttpClientBuilderImpl version(HttpClient.Version version) { + Objects.requireNonNull(version); + this.version = version; + return this; + } + + + @Override + public HttpClientBuilderImpl priority(int priority) { + if (priority < 1 || priority > 255) { + throw new IllegalArgumentException("priority must be between 1 and 255"); + } + this.priority = priority; + return this; + } + + + @Override + public HttpClientBuilderImpl pipelining(boolean enable) { + //To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } + + + @Override + public HttpClientBuilderImpl proxy(ProxySelector proxy) { + Objects.requireNonNull(proxy); + this.proxy = proxy; + return this; + } + + + @Override + public HttpClientBuilderImpl authenticator(Authenticator a) { + Objects.requireNonNull(a); + this.authenticator = a; + return this; + } + + @Override + public HttpClient build() { + return HttpClientImpl.create(this); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java new file mode 100644 index 00000000000..e7e53bd6346 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.ProxySelector; +import java.net.URI; +import static java.net.http.Utils.BUFSIZE; +import java.nio.ByteBuffer; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import static java.nio.channels.SelectionKey.OP_CONNECT; +import static java.nio.channels.SelectionKey.OP_READ; +import static java.nio.channels.SelectionKey.OP_WRITE; +import java.nio.channels.Selector; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.security.NoSuchAlgorithmException; +import java.util.ListIterator; +import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +/** + * Client implementation. Contains all configuration information and also + * the selector manager thread which allows async events to be registered + * and delivered when they occur. See AsyncEvent. + */ +class HttpClientImpl extends HttpClient implements BufferHandler { + + private final CookieManager cookieManager; + private final Redirect followRedirects; + private final ProxySelector proxySelector; + private final Authenticator authenticator; + private final Version version; + private boolean pipelining = false; + private final ConnectionPool connections; + private final ExecutorWrapper executor; + // Security parameters + private final SSLContext sslContext; + private final SSLParameters sslParams; + private final SelectorManager selmgr; + private final FilterFactory filters; + private final Http2ClientImpl client2; + private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); + private final LinkedList timeouts; + + //@Override + void debugPrint() { + selmgr.debugPrint(); + client2.debugPrint(); + } + + public static HttpClientImpl create(HttpClientBuilderImpl builder) { + HttpClientImpl impl = new HttpClientImpl(builder); + impl.start(); + return impl; + } + + private HttpClientImpl(HttpClientBuilderImpl builder) { + if (builder.sslContext == null) { + try { + sslContext = SSLContext.getDefault(); + } catch (NoSuchAlgorithmException ex) { + throw new InternalError(ex); + } + } else { + sslContext = builder.sslContext; + } + ExecutorService ex = builder.executor; + if (ex == null) { + ex = Executors.newCachedThreadPool((r) -> { + Thread t = defaultFactory.newThread(r); + t.setDaemon(true); + return t; + }); + } else { + ex = builder.executor; + } + client2 = new Http2ClientImpl(this); + executor = ExecutorWrapper.wrap(ex); + cookieManager = builder.cookieManager; + followRedirects = builder.followRedirects == null ? + Redirect.NEVER : builder.followRedirects; + this.proxySelector = builder.proxy; + authenticator = builder.authenticator; + version = builder.version; + sslParams = builder.sslParams; + connections = new ConnectionPool(); + connections.start(); + timeouts = new LinkedList<>(); + try { + selmgr = new SelectorManager(); + } catch (IOException e) { + // unlikely + throw new InternalError(e); + } + selmgr.setDaemon(true); + selmgr.setName("HttpSelector"); + filters = new FilterFactory(); + initFilters(); + } + + private void start() { + selmgr.start(); + } + + /** + * Wait for activity on given exchange (assuming blocking = false). + * It's a no-op if blocking = true. In particular, the following occurs + * in the SelectorManager thread. + * + * 1) mark the connection non-blocking + * 2) add to selector + * 3) If selector fires for this exchange then + * 4) - mark connection as blocking + * 5) - call AsyncEvent.handle() + * + * If exchange needs to block again, then call registerEvent() again + */ + void registerEvent(AsyncEvent exchange) throws IOException { + selmgr.register(exchange); + } + + Http2ClientImpl client2() { + return client2; + } + + LinkedList freelist = new LinkedList<>(); + + @Override + public synchronized ByteBuffer getBuffer() { + if (freelist.isEmpty()) { + return ByteBuffer.allocate(BUFSIZE); + } + return freelist.removeFirst(); + } + + @Override + public synchronized void returnBuffer(ByteBuffer buffer) { + buffer.clear(); + freelist.add(buffer); + } + + + // Main loop for this client's selector + + class SelectorManager extends Thread { + + final Selector selector; + boolean closed; + + final List readyList; + final List registrations; + + List debugList; + + SelectorManager() throws IOException { + readyList = new LinkedList<>(); + registrations = new LinkedList<>(); + debugList = new LinkedList<>(); + selector = Selector.open(); + } + + // This returns immediately. So caller not allowed to send/receive + // on connection. + + synchronized void register(AsyncEvent e) throws IOException { + registrations.add(e); + selector.wakeup(); + } + + void wakeupSelector() { + selector.wakeup(); + } + + synchronized void shutdown() { + closed = true; + try { + selector.close(); + } catch (IOException e) {} + } + + private List copy(List list) { + LinkedList c = new LinkedList<>(); + for (AsyncEvent e : list) { + c.add(e); + } + return c; + } + + synchronized void debugPrint() { + System.err.println("Selecting on:"); + for (AsyncEvent e : debugList) { + System.err.println(opvals(e.interestOps())); + } + } + + String opvals(int i) { + StringBuilder sb = new StringBuilder(); + if ((i & OP_READ) != 0) + sb.append("OP_READ "); + if ((i & OP_CONNECT) != 0) + sb.append("OP_CONNECT "); + if ((i & OP_WRITE) != 0) + sb.append("OP_WRITE "); + return sb.toString(); + } + + @Override + public void run() { + try { + while (true) { + synchronized (this) { + debugList = copy(registrations); + for (AsyncEvent exchange : registrations) { + SelectableChannel c = exchange.channel(); + try { + c.configureBlocking(false); + c.register(selector, + exchange.interestOps(), + exchange); + } catch (IOException e) { + Log.logError("HttpClientImpl: " + e); + c.close(); + // let the exchange deal with it + handleEvent(exchange); + } + } + registrations.clear(); + } + long timeval = getTimeoutValue(); + long now = System.currentTimeMillis(); + int n = selector.select(timeval); + if (n == 0) { + signalTimeouts(now); + continue; + } + Set keys = selector.selectedKeys(); + + for (SelectionKey key : keys) { + if (key.isReadable() || key.isConnectable() || key.isWritable()) { + key.cancel(); + AsyncEvent exchange = (AsyncEvent) key.attachment(); + readyList.add(exchange); + } + } + selector.selectNow(); // complete cancellation + selector.selectedKeys().clear(); + + for (AsyncEvent exchange : readyList) { + if (exchange instanceof AsyncEvent.Blocking) { + exchange.channel().configureBlocking(true); + } else { + assert exchange instanceof AsyncEvent.NonBlocking; + } + executor.synchronize(); + handleEvent(exchange); // will be delegated to executor + } + readyList.clear(); + } + } catch (Throwable e) { + if (!closed) { + System.err.println("HttpClientImpl terminating on error"); + // This terminates thread. So, better just print stack trace + String err = Utils.stackTrace(e); + Log.logError("HttpClientImpl: fatal error: " + err); + } + } + } + + void handleEvent(AsyncEvent e) { + if (closed) { + e.abort(); + } else { + e.handle(); + } + } + } + + /** + * Creates a HttpRequest associated with this group. + * + * @throws IllegalStateException if the group has been stopped + */ + @Override + public HttpRequestBuilderImpl request() { + return new HttpRequestBuilderImpl(this, null); + } + + /** + * Creates a HttpRequest associated with this group. + * + * @throws IllegalStateException if the group has been stopped + */ + @Override + public HttpRequestBuilderImpl request(URI uri) { + return new HttpRequestBuilderImpl(this, uri); + } + + @Override + public SSLContext sslContext() { + Utils.checkNetPermission("getSSLContext"); + return sslContext; + } + + @Override + public Optional sslParameters() { + return Optional.ofNullable(sslParams); + } + + @Override + public Optional authenticator() { + return Optional.ofNullable(authenticator); + } + + @Override + public ExecutorService executorService() { + return executor.userExecutor(); + } + + ExecutorWrapper executorWrapper() { + return executor; + } + + @Override + public boolean pipelining() { + return this.pipelining; + } + + ConnectionPool connectionPool() { + return connections; + } + + @Override + public Redirect followRedirects() { + return followRedirects; + } + + + @Override + public Optional cookieManager() { + return Optional.ofNullable(cookieManager); + } + + @Override + public Optional proxy() { + return Optional.ofNullable(this.proxySelector); + } + + @Override + public Version version() { + return version; + } + + //private final HashMap http2NotSupported = new HashMap<>(); + + boolean getHttp2Allowed() { + return version.equals(Version.HTTP_2); + } + + //void setHttp2NotSupported(String host) { + //http2NotSupported.put(host, false); + //} + + final void initFilters() { + addFilter(AuthenticationFilter.class); + addFilter(RedirectFilter.class); + } + + final void addFilter(Class f) { + filters.addFilter(f); + } + + final List filterChain() { + return filters.getFilterChain(); + } + + // Timer controls. Timers are implemented through timed Selector.select() + // calls. + synchronized void registerTimer(TimeoutEvent event) { + long elapse = event.timevalMillis(); + ListIterator iter = timeouts.listIterator(); + long listval = 0; + event.delta = event.timeval; // in case list empty + TimeoutEvent next; + while (iter.hasNext()) { + next = iter.next(); + listval += next.delta; + if (elapse < listval) { + listval -= next.delta; + event.delta = elapse - listval; + next.delta -= event.delta; + iter.previous(); + break; + } else if (!iter.hasNext()) { + event.delta = event.timeval - listval ; + } + } + iter.add(event); + //debugPrintList("register"); + selmgr.wakeupSelector(); + } + + void debugPrintList(String s) { + System.err.printf("%s: {", s); + for (TimeoutEvent e : timeouts) { + System.err.printf("(%d,%d) ", e.delta, e.timeval); + } + System.err.println("}"); + } + + synchronized void signalTimeouts(long then) { + if (timeouts.isEmpty()) { + return; + } + long now = System.currentTimeMillis(); + long duration = now - then; + ListIterator iter = timeouts.listIterator(); + TimeoutEvent event = iter.next(); + long delta = event.delta; + if (duration < delta) { + event.delta -= duration; + return; + } + event.handle(); + iter.remove(); + while (iter.hasNext()) { + event = iter.next(); + if (event.delta == 0) { + event.handle(); + iter.remove(); + } else { + event.delta += delta; + break; + } + } + //debugPrintList("signalTimeouts"); + } + + synchronized void cancelTimer(TimeoutEvent event) { + ListIterator iter = timeouts.listIterator(); + while (iter.hasNext()) { + TimeoutEvent ev = iter.next(); + if (event == ev) { + if (iter.hasNext()) { + // adjust + TimeoutEvent next = iter.next(); + next.delta += ev.delta; + iter.previous(); + } + iter.remove(); + } + } + } + + // used for the connection window + int getReceiveBufferSize() { + return Utils.getIntegerNetProperty( + "sun.net.httpclient.connectionWindowSize", 256 * 1024 + ); + } + + // returns 0 meaning block forever, or a number of millis to block for + synchronized long getTimeoutValue() { + if (timeouts.isEmpty()) { + return 0; + } else { + return timeouts.get(0).delta; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java new file mode 100644 index 00000000000..ea82531b469 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLParameters; + +/** + * Wraps socket channel layer and takes care of SSL also. + * + * Subtypes are: + * PlainHttpConnection: regular direct TCP connection to server + * PlainProxyConnection: plain text proxy connection + * PlainTunnelingConnection: opens plain text (CONNECT) tunnel to server + * SSLConnection: TLS channel direct to server + * SSLTunnelConnection: TLS channel via (CONNECT) proxy tunnel + */ +abstract class HttpConnection implements BufferHandler { + + // address we are connected to. Could be a server or a proxy + final InetSocketAddress address; + final HttpClientImpl client; + protected volatile ByteBuffer buffer; + + HttpConnection(InetSocketAddress address, HttpClientImpl client) { + this.address = address; + this.client = client; + } + + /** + * Public API to this class. addr is the ultimate destination. Any proxies + * etc are figured out from the request. Returns an instance of one of the + * following + * PlainHttpConnection + * PlainTunnelingConnection + * SSLConnection + * SSLTunnelConnection + * + * When object returned, connect() or connectAsync() must be called, which + * when it returns/completes, the connection is usable for requests. + */ + public static HttpConnection getConnection(InetSocketAddress addr, + HttpRequestImpl request) { + return getConnectionImpl(addr, request); + } + + public abstract void connect() throws IOException, InterruptedException; + + public abstract CompletableFuture connectAsync(); + + /** + * Returns whether this connection is connected to its destination + */ + abstract boolean connected(); + + abstract boolean isSecure(); + + abstract boolean isProxied(); + + /** + * Completes when the first byte of the response is available to be read. + */ + abstract CompletableFuture whenReceivingResponse(); + + // must be called before reading any data off connection + // at beginning of response. + ByteBuffer getRemaining() { + ByteBuffer b = buffer; + buffer = null; + return b; + } + + final boolean isOpen() { + return channel().isOpen(); + } + + /* Returns either a plain HTTP connection or a plain tunnelling connection + * for proxied websockets */ + private static HttpConnection getPlainConnection(InetSocketAddress addr, + InetSocketAddress proxy, + HttpRequestImpl request) { + HttpClientImpl client = request.client(); + + if (request.isWebSocket() && proxy != null) { + return new PlainTunnelingConnection(addr, + proxy, + client, + request.getAccessControlContext()); + } else { + if (proxy == null) { + return new PlainHttpConnection(addr, client); + } else { + return new PlainProxyConnection(proxy, client); + } + } + } + + private static HttpConnection getSSLConnection(InetSocketAddress addr, + InetSocketAddress proxy, + HttpRequestImpl request, + String[] alpn) { + HttpClientImpl client = request.client(); + if (proxy != null) { + return new SSLTunnelConnection(addr, + client, + proxy, + request.getAccessControlContext()); + } else { + return new SSLConnection(addr, client, alpn); + } + } + + /** + * Main factory method. Gets a HttpConnection, either cached or new if + * none available. + */ + private static HttpConnection getConnectionImpl(InetSocketAddress addr, + HttpRequestImpl request) { + HttpConnection c; + HttpClientImpl client = request.client(); + InetSocketAddress proxy = request.proxy(); + boolean secure = request.secure(); + ConnectionPool pool = client.connectionPool(); + String[] alpn = null; + + if (secure && request.requestHttp2()) { + alpn = new String[1]; + alpn[0] = "h2"; + } + + if (!secure) { + c = pool.getConnection(false, addr, proxy); + if (c != null) { + return c; + } else { + return getPlainConnection(addr, proxy, request); + } + } else { + c = pool.getConnection(true, addr, proxy); + if (c != null) { + return c; + } else { + return getSSLConnection(addr, proxy, request, alpn); + } + } + } + + void returnToCache(HttpHeaders hdrs) { + if (hdrs == null) { + // the connection was closed by server + close(); + return; + } + if (!isOpen()) { + return; + } + ConnectionPool pool = client.connectionPool(); + boolean keepAlive = hdrs.firstValue("Connection") + .map((s) -> !s.equalsIgnoreCase("close")) + .orElse(true); + + if (keepAlive) { + pool.returnToPool(this); + } else { + close(); + } + } + + /** + * Also check that the number of bytes written is what was expected. This + * could be different if the buffer is user-supplied and its internal + * pointers were manipulated in a race condition. + */ + final void checkWrite(long expected, ByteBuffer buffer) throws IOException { + long written = write(buffer); + if (written != expected) { + throw new IOException("incorrect number of bytes written"); + } + } + + final void checkWrite(long expected, + ByteBuffer[] buffers, + int start, + int length) + throws IOException + { + long written = write(buffers, start, length); + if (written != expected) { + throw new IOException("incorrect number of bytes written"); + } + } + + abstract SocketChannel channel(); + + final InetSocketAddress address() { + return address; + } + + void configureBlocking(boolean mode) throws IOException { + channel().configureBlocking(mode); + } + + abstract ConnectionPool.CacheKey cacheKey(); + + /* + static PrintStream ps; + + static { + try { + String propval = Utils.getNetProperty("java.net.httpclient.showData"); + if (propval != null && propval.equalsIgnoreCase("true")) { + ps = new PrintStream(new FileOutputStream("/tmp/httplog.txt"), false); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + synchronized final void debugPrint(String s, ByteBuffer b) { + ByteBuffer[] bufs = new ByteBuffer[1]; + bufs[0] = b; + debugPrint(s, bufs, 0, 1); + } + + synchronized final void debugPrint(String s, + ByteBuffer[] bufs, + int start, + int number) { + if (ps == null) { + return; + } + + ps.printf("\n%s:\n", s); + + for (int i=start; i 0x20 && c <= 0x7F) { + ps.printf("%c", (char)c); + } else { + ps.printf("0x%02x ", c); + } + } + } + ps.printf("\n---------------------\n"); + } + + */ + + // overridden in SSL only + SSLParameters sslParameters() { + return null; + } + + // Methods to be implemented for Plain TCP and SSL + + abstract long write(ByteBuffer[] buffers, int start, int number) + throws IOException; + + abstract long write(ByteBuffer buffer) throws IOException; + + /** + * Closes this connection, by returning the socket to its connection pool. + */ + abstract void close(); + + /** + * Returns a ByteBuffer with data, or null if EOF. + */ + final ByteBuffer read() throws IOException { + return read(-1); + } + + /** + * Puts position to limit and limit to capacity so we can resume reading + * into this buffer, but if required > 0 then limit may be reduced so that + * no more than required bytes are read next time. + */ + static void resumeChannelRead(ByteBuffer buf, int required) { + int limit = buf.limit(); + buf.position(limit); + int capacity = buf.capacity() - limit; + if (required > 0 && required < capacity) { + buf.limit(limit + required); + } else { + buf.limit(buf.capacity()); + } + } + + /** + * Blocks ands return requested amount. + */ + final ByteBuffer read(int length) throws IOException { + if (length <= 0) { + buffer = readImpl(length); + return buffer; + } + buffer = readImpl(length); + int required = length - buffer.remaining(); + while (buffer.remaining() < length) { + resumeChannelRead(buffer, required); + int n = readImpl(buffer); + required -= n; + } + return buffer; + } + + final int read(ByteBuffer buffer) throws IOException { + int n = readImpl(buffer); + return n; + } + + /** Reads up to length bytes. */ + protected abstract ByteBuffer readImpl(int length) throws IOException; + + /** Reads as much as possible into given buffer and returns amount read. */ + protected abstract int readImpl(ByteBuffer buffer) throws IOException; + + @Override + public String toString() { + return "HttpConnection: " + channel().toString(); + } + + @Override + public final ByteBuffer getBuffer() { + return client.getBuffer(); + } + + @Override + public final void returnBuffer(ByteBuffer buffer) { + client.returnBuffer(buffer); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java new file mode 100644 index 00000000000..587e0af14bf --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ + +package java.net.http; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * A read-only view of a set of received HTTP headers. + * + * @since 9 + */ +public interface HttpHeaders { + + /** + * Returns an {@link java.util.Optional} containing the first value of the + * given named (and possibly multi-valued) header. If the header is not + * present, then the returned {@code Optional} is empty. + * + * @param name the header name + * @return an {@code Optional} for the first named value + */ + public Optional firstValue(String name); + + /** + * Returns an {@link java.util.Optional} containing the first value of the + * named header field as an {@literal Optional}. If the header is not + * present, then the Optional is empty. If the header is present but + * contains a value that does not parse as a {@code Long} value, then an + * exception is thrown. + * + * @param name the header name + * @return an {@code Optional} + * @throws NumberFormatException if a value is found, but does not parse as + * a Long + */ + public Optional firstValueAsLong(String name); + + /** + * Returns an unmodifiable List of all of the values of the given named + * header. Always returns a List, which may be empty if the header is not + * present. + * + * @param name the header name + * @return a List of String values + */ + public List allValues(String name); + + /** + * Returns an unmodifiable multi Map view of this HttpHeaders. This + * interface should only be used when it is required to iterate over the + * entire set of headers. + * + * @return the Map + */ + public Map> map(); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java new file mode 100644 index 00000000000..c9ff689a931 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +public interface HttpHeaders1 extends HttpHeaders { + public void makeUnmodifiable(); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java new file mode 100644 index 00000000000..532625e65da --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Implementation of HttpHeaders. + */ +class HttpHeadersImpl implements HttpHeaders1 { + + private final HashMap> headers; + private boolean isUnmodifiable = false; + + public HttpHeadersImpl() { + headers = new HashMap<>(); + } + + /** + * Replace all List in headers with unmodifiable Lists. Call + * this only after all headers are added. The headers HashMap + * is wrapped with an unmodifiable HashMap in map() + */ + @Override + public void makeUnmodifiable() { + if (isUnmodifiable) + return; + + Set keys = new HashSet<>(headers.keySet()); + for (String key : keys) { + List values = headers.remove(key); + if (values != null) { + headers.put(key, Collections.unmodifiableList(values)); + } + } + isUnmodifiable = true; + } + + @Override + public Optional firstValue(String name) { + List l = headers.get(name); + return Optional.ofNullable(l == null ? null : l.get(0)); + } + + @Override + public List allValues(String name) { + return headers.get(name); + } + + @Override + public Map> map() { + return Collections.unmodifiableMap(headers); + } + + Map> directMap() { + return headers; + } + + // package private mutators + + public HttpHeadersImpl deepCopy() { + HttpHeadersImpl h1 = new HttpHeadersImpl(); + HashMap> headers1 = h1.headers; + Set keys = headers.keySet(); + for (String key : keys) { + List vals = headers.get(key); + LinkedList vals1 = new LinkedList<>(vals); + headers1.put(key, vals1); + } + return h1; + } + + private List getOrCreate(String name) { + List l = headers.get(name); + if (l == null) { + l = new LinkedList<>(); + headers.put(name, l); + } + return l; + } + + void addHeader(String name, String value) { + List l = getOrCreate(name); + l.add(value); + } + + void setHeader(String name, String value) { + List l = getOrCreate(name); + l.clear(); + l.add(value); + } + + @Override + public Optional firstValueAsLong(String name) { + List l = headers.get(name); + if (l == null) { + return Optional.ofNullable(null); + } else { + String v = l.get(0); + Long lv = Long.parseLong(v); + return Optional.of(lv); + } + } + + void clear() { + headers.clear(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java new file mode 100644 index 00000000000..fd177827fe3 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ + +package java.net.http; + +import java.net.*; + +interface HttpRedirectImpl { + + static HttpRedirectImpl getRedirects(java.net.http.HttpClient.Redirect redir) { + switch (redir) { + case NEVER: + return HttpRedirectImpl.NEVER; + case ALWAYS: + return HttpRedirectImpl.ALWAYS; + case SECURE: + return HttpRedirectImpl.SECURE; + case SAME_PROTOCOL: + return HttpRedirectImpl.SAME_PROTOCOL; + } + return HttpRedirectImpl.NEVER; + } + + static HttpClient.Redirect getRedirects(HttpRedirectImpl redir) { + if (redir == HttpRedirectImpl.NEVER) { + return HttpClient.Redirect.NEVER; + } else if (redir == HttpRedirectImpl.ALWAYS) { + return HttpClient.Redirect.ALWAYS; + } else if (redir == HttpRedirectImpl.SECURE) { + return HttpClient.Redirect.SECURE; + } else { + return HttpClient.Redirect.SAME_PROTOCOL; + } + } + + /** + * Called to determine whether the given intermediate response + * with a redirection response code should be redirected. The target URI + * can be obtained from the "Location" header in the given response object. + * + * @param rsp the response from the redirected resource + * @return {@code true} if the redirect should be attempted automatically + * or {@code false} if not. + */ + boolean redirect(HttpResponse rsp); + + /** + * Never redirect. + */ + static HttpRedirectImpl NEVER = (HttpResponse rsp) -> false; + + /** + * Always redirect. + */ + static HttpRedirectImpl ALWAYS = (HttpResponse rsp) -> true; + + /** + * Redirect to same protocol only. Redirection may occur from HTTP URLs to + * other THHP URLs and from HTTPS URLs to other HTTPS URLs. + */ + static HttpRedirectImpl SAME_PROTOCOL = (HttpResponse rsp) -> { + String orig = rsp.request().uri().getScheme().toLowerCase(); + String redirect = URI.create( + rsp.headers().firstValue("Location").orElse("")) + .getScheme().toLowerCase(); + return orig.equals(redirect); + }; + + /** + * Redirect always except from HTTPS URLs to HTTP URLs. + */ + static HttpRedirectImpl SECURE = (HttpResponse rsp) -> { + String orig = rsp.request().uri().getScheme().toLowerCase(); + String redirect = URI.create( + rsp.headers().firstValue("Location").orElse("")) + .getScheme().toLowerCase(); + if (orig.equals("https")) { + return redirect.equals("https"); + } + return true; + }; +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java new file mode 100644 index 00000000000..66f84e360ce --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java @@ -0,0 +1,871 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ + +package java.net.http; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.net.URI; +import java.net.ProxySelector; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.*; +import java.nio.file.Path; +import java.util.Iterator; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.LongConsumer; + +/** + * Represents one HTTP request which can be sent to a server. {@code + * HttpRequest}s are built from {@code HttpRequest} {@link HttpRequest.Builder + * builder}s. {@code HttpRequest} builders are obtained from a {@link HttpClient} + * by calling {@link HttpClient#request(java.net.URI) HttpClient.request}, or + * by calling {@link #create(java.net.URI) HttpRequest.create} which returns a + * builder on the default client. + * A request's {@link java.net.URI}, headers and body can be set. Request bodies + * are provided through a {@link BodyProcessor} object. Once all required + * parameters have been set in the builder, one of the builder methods should be + * called, which sets the request method and returns a {@code HttpRequest}. + * These methods are {@link Builder#GET() GET}, {@link HttpRequest.Builder#POST() + * POST} and {@link HttpRequest.Builder#PUT() PUT} which return a GET, POST or + * PUT request respectively. Alternatively, {@link + * HttpRequest.Builder#method(String) method} can be called to set an arbitrary + * method type (and return a {@code HttpRequest}). Builders can also be copied + * and modified multiple times in order to build multiple related requests that + * differ in some parameters. + * + *

      Two simple, example HTTP interactions are shown below: + *

      + * {@code
      + *      // GET
      + *      HttpResponse response = HttpRequest
      + *          .create(new URI("http://www.foo.com"))
      + *          .headers("Foo", "foovalue", "Bar", "barvalue")
      + *          .GET()
      + *          .response();
      + *
      + *      int statusCode = response.statusCode();
      + *      String responseBody = response.body(asString());
      + *
      + *      // POST
      + *      response = HttpRequest
      + *          .create(new URI("http://www.foo.com"))
      + *          .body(fromString("param1=foo,param2=bar"))
      + *          .POST()
      + *          .response();}
      + * 
      + * + *

      The request is sent and the response obtained by calling one of the + * following methods. + *

      • {@link #response() response} blocks until the entire request has been + * sent and the response status code and headers have been received.
      • + *
      • {@link #responseAsync() responseAsync} sends the request and receives the + * response asynchronously. Returns immediately with a + * {@link java.util.concurrent.CompletableFuture CompletableFuture}<{@link + * HttpResponse}>.
      • + *
      • {@link #multiResponseAsync(HttpResponse.MultiProcessor) multiResponseAsync} + * sends the request asynchronously, expecting multiple responses. This + * capability is of most relevance to HTTP/2 server push, but can be used for + * single responses (HTTP/1.1 or HTTP/2) also.
      • + *
      + * + *

      Once a request has been sent, it is an error to try and send it again. + * + *

      Once a {@code HttpResponse} is received, the headers and response code are + * available. The body can then be received by calling one of the body methods + * on {@code HttpResponse}. + * + *

      See below for discussion of synchronous versus asynchronous usage. + * + *

      Request bodies + * + *

      Request bodies are sent using one of the request processor implementations + * below provided in {@code HttpRequest}, or else a custom implementation can be + * used. + *

        + *
      • {@link #fromByteArray(byte[]) } from byte array
      • + *
      • {@link #fromByteArrays(java.util.Iterator) fromByteArrays(Iterator)} + * from an iterator of byte arrays
      • + *
      • {@link #fromFile(java.nio.file.Path) fromFile(Path)} from the file located + * at the given Path
      • + *
      • {@link #fromString(java.lang.String) fromString(String)} from a String
      • + *
      • {@link #fromInputStream(java.io.InputStream) fromInputStream(InputStream)} + * request body from InputStream
      • + *
      • {@link #noBody() } no request body is sent
      • + *
      + * + *

      Response bodies + * + *

      Responses bodies are handled by the {@link HttpResponse.BodyProcessor} + * {@code } supplied to the {@link HttpResponse#body(HttpResponse.BodyProcessor) + * HttpResponse.body} and {@link HttpResponse#bodyAsync(HttpResponse.BodyProcessor) + * HttpResponse.bodyAsync} methods. Some implementations of {@code + * HttpResponse.BodyProcessor} are provided in {@link HttpResponse}: + *

        + *
      • {@link HttpResponse#asByteArray() } stores the body in a byte array
      • + *
      • {@link HttpResponse#asString()} stores the body as a String
      • + *
      • {@link HttpResponse#asFile(java.nio.file.Path) } stores the body in a + * named file
      • + *
      • {@link HttpResponse#ignoreBody() } ignores any received response body
      • + *
      + * + *

      The output of a response processor is the response body, and its + * parameterized type {@code T} determines the type of the body object returned + * from {@code HttpResponse.body} and {@code HttpResponse.bodyAsync}. Therefore, + * as an example, the second response processor in the list above has the type + * {@code HttpResponse.BodyProcessor} which means the type returned by + * {@code HttpResponse.body()} is a String. Response processors can be defined + * to return potentially any type as body. + * + *

      Multi responses + * + *

      With HTTP/2 it is possible for a server to return a main response and zero + * or more additional responses (known as server pushes) to a client-initiated + * request. These are handled using a special response processor called {@link + * HttpResponse.MultiProcessor}. + * + *

      Blocking/asynchronous behavior and thread usage + * + *

      There are two styles of request sending: synchronous and + * asynchronous. {@link #response() response} blocks the calling thread + * until the request has been sent and the response received. + * + *

      {@link #responseAsync() responseAsync} is asynchronous and returns + * immediately with a {@link java.util.concurrent.CompletableFuture}<{@link + * HttpResponse}> and when this object completes (in a background thread) the + * response has been received. + * + *

      {@link #multiResponseAsync(HttpResponse.MultiProcessor) multiResponseAsync} + * is the variant for multi responses and is also asynchronous. + * + *

      CompletableFutures can be combined in different ways to declare the + * dependencies among several asynchronous tasks, while allowing for the maximum + * level of parallelism to be utilized. + * + *

      Security checks + * + *

      If a security manager is present then security checks are performed by + * the {@link #response() } and {@link #responseAsync() } methods. A {@link + * java.net.URLPermission} or {@link java.net.SocketPermission} is required to + * access any destination origin server and proxy server utilised. URLPermissions + * should be preferred in policy files over SocketPermissions given the more + * limited scope of URLPermission. Permission is always implicitly granted to a + * system's default proxies. The URLPermission form used to access proxies uses + * a method parameter of "CONNECT" (for all kinds of proxying) and a url string + * of the form "socket://host:port" where host and port specify the proxy's + * address. + * + *

      Examples + *

      + *     import static java.net.http.HttpRequest.*;
      + *     import static java.net.http.HttpResponse.*;
      + *
      + *     //Simple blocking
      + *
      + *     HttpResponse r1 = HttpRequest.create(new URI("http://www.foo.com/"))
      + *                                  .GET()
      + *                                 .response();
      + *     int responseCode = r1.statusCode());
      + *     String body = r1.body(asString());
      + *
      + *     HttpResponse r2 = HttpRequest.create(new URI("http://www.foo.com/"))
      + *                                  .GET()
      + *                                  .response();
      + *
      + *     System.out.println("Response was " + r1.statusCode());
      + *     Path body1 = r2.body(asFile(Paths.get("/tmp/response.txt")));
      + *     // Content stored in /tmp/response.txt
      + *
      + *     HttpResponse r3 = HttpRequest.create(new URI("http://www.foo.com/"))
      + *                                  .body(fromString("param1=1, param2=2"))
      + *                                  .POST()
      + *                                  .response();
      + *
      + *     Void body2 = r3.body(ignoreBody()); // body is Void in this case
      + * 
      + * + *

      Asynchronous Example + * + *

      All of the above examples will work asynchronously, if {@link + * #responseAsync()} is used instead of {@link #response()} in which case the + * returned object is a {@code CompletableFuture} instead of + * {@code HttpResponse}. The following example shows how multiple requests can + * be sent asynchronously. It also shows how dependent asynchronous operations + * (receiving response, and receiving response body) can be chained easily using + * one of the many methods in {@code CompletableFuture}. + *

      + * {@code
      + *      // fetch a list of target URIs asynchronously and store them in Files.
      + *
      + *      List targets = ...
      + *
      + *      List> futures = targets
      + *          .stream()
      + *          .map(target -> {
      + *              return HttpRequest
      + *                  .create(target)
      + *                  .GET()
      + *                  .responseAsync()
      + *                  .thenCompose(response -> {
      + *                      Path dest = Paths.get("base", target.getPath());
      + *                      if (response.statusCode() == 200) {
      + *                          return response.bodyAsync(asFile(dest));
      + *                      } else {
      + *                          return CompletableFuture.completedFuture(dest);
      + *                      }
      + *                  })
      + *                  // convert Path -> File
      + *                  .thenApply((Path dest) -> {
      + *                      return dest.toFile();
      + *                  });
      + *              })
      + *          .collect(Collectors.toList());
      + *
      + *      // all async operations waited for here
      + *
      + *      CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
      + *          .join();
      + *
      + *      // all elements of futures have completed and can be examined.
      + *      // Use File.exists() to check whether file was successfully downloaded
      + * }
      + * 
      + * + * @since 9 + */ +public abstract class HttpRequest { + + HttpRequest() {} + + /** + * A builder of {@link HttpRequest}s. {@code HttpRequest.Builder}s are + * created by calling {@link HttpRequest#create(URI)} or {@link + * HttpClient#request(URI)}. + * + *

      Each of the setter methods in this class modifies the state of the + * builder and returns this (ie. the same instance). The methods are + * not synchronized and should not be called from multiple threads without + * external synchronization. + * + *

      The build methods return a new {@code HttpRequest} each time they are + * called. + * + * @since 9 + */ + public abstract static class Builder { + + Builder() {} + + /** + * Sets this HttpRequest's request URI. + * + * @param uri the request URI + * @return this request builder + */ + public abstract Builder uri(URI uri); + + /** + * Specifies whether this request will automatically follow redirects + * issued by the server. The default value for this setting is the value + * of {@link HttpClient#followRedirects() } + * + * @param policy the redirection policy + * @return this request builder + */ + public abstract Builder followRedirects(HttpClient.Redirect policy); + + /** + * Request server to acknowledge request before sending request + * body. This is disabled by default. If enabled, the server is requested + * to send an error response or a 100-Continue response before the client + * sends the request body. This means the request processor for the + * request will not be invoked until this interim response is received. + * + * @param enable {@code true} if Expect continue to be sent + * @return this request builder + */ + public abstract Builder expectContinue(boolean enable); + + /** + * Overrides the {@link HttpClient#version() } setting for this + * request. + * + * @param version the HTTP protocol version requested + * @return this request builder + */ + public abstract Builder version(HttpClient.Version version); + + /** + * Adds the given name value pair to the set of headers for this request. + * + * @param name the header name + * @param value the header value + * @return this request builder + */ + public abstract Builder header(String name, String value); + + /** + * Overrides the ProxySelector set on the request's client for this + * request. + * + * @param proxy the ProxySelector to use + * @return this request builder + */ + public abstract Builder proxy(ProxySelector proxy); + + /** + * Adds the given name value pairs to the set of headers for this + * request. The supplied Strings must alternate as names and values. + * + * @param headers the list of String name value pairs + * @return this request builder + * @throws IllegalArgumentException if there is an odd number of + * parameters + */ + public abstract Builder headers(String... headers); + + /** + * Sets a timeout for this request. If the response is not received + * within the specified timeout then a {@link HttpTimeoutException} is + * thrown from {@link #response() } or {@link #responseAsync() } + * completes exceptionally with a {@code HttpTimeoutException}. + * + * @param unit the timeout units + * @param timeval the number of units to wait for + * @return this request builder + */ + public abstract Builder timeout(TimeUnit unit, long timeval); + + /** + * Sets the given name value pair to the set of headers for this + * request. This overwrites any previously set values for name. + * + * @param name the header name + * @param value the header value + * @return this request builder + */ + public abstract Builder setHeader(String name, String value); + + /** + * Sets a request body for this builder. See {@link HttpRequest} + * for example {@code BodyProcessor} implementations. + * If no body is specified, then no body is sent with the request. + * + * @param reqproc the request body processor + * @return this request builder + */ + public abstract Builder body(BodyProcessor reqproc); + + /** + * Builds and returns a GET {@link HttpRequest} from this builder. + * + * @return a {@code HttpRequest} + */ + public abstract HttpRequest GET(); + + /** + * Builds and returns a POST {@link HttpRequest} from this builder. + * + * @return a {@code HttpRequest} + */ + public abstract HttpRequest POST(); + + /** + * Builds and returns a PUT {@link HttpRequest} from this builder. + * + * @return a {@code HttpRequest} + */ + public abstract HttpRequest PUT(); + + /** + * Builds and returns a {@link HttpRequest} from this builder using + * the given method String. The method string is case-sensitive, and + * may be rejected if an upper-case string is not used. + * + * @param method the method to use + * @return a {@code HttpRequest} + * @throws IllegalArgumentException if an unrecognised method is used + */ + public abstract HttpRequest method(String method); + + /** + * Returns an exact duplicate copy of this Builder based on current + * state. The new builder can then be modified independently of this + * builder. + * + * @return an exact copy of this Builder + */ + public abstract Builder copy(); + } + + /** + * Creates a HttpRequest builder from the default HttpClient. + * + * @param uri the request URI + * @return a new request builder + */ + public static HttpRequest.Builder create(URI uri) { + return HttpClient.getDefault().request(uri); + } + + /** + * Returns the follow-redirects setting for this request. + * + * @return follow redirects setting + */ + public abstract HttpClient.Redirect followRedirects(); + + /** + * Returns the response to this request, by sending it and blocking if + * necessary to get the response. The {@link HttpResponse} contains the + * response status and headers. + * + * @return a HttpResponse for this request + * @throws IOException if an I/O error occurs + * @throws InterruptedException if the operation was interrupted + * @throws SecurityException if the caller does not have the required + * permission + * @throws IllegalStateException if called more than once or if + * responseAsync() called previously + */ + public abstract HttpResponse response() + throws IOException, InterruptedException; + + /** + * Sends the request and returns the response asynchronously. This method + * returns immediately with a {@link CompletableFuture}<{@link + * HttpResponse}> + * + * @return a {@code CompletableFuture} + * @throws IllegalStateException if called more than once or if response() + * called previously. + */ + public abstract CompletableFuture responseAsync(); + + /** + * Sends the request asynchronously expecting multiple responses. + * + *

      This method must be given a {@link HttpResponse.MultiProcessor} to + * handle the multiple responses. + * + *

      If a security manager is set, the caller must possess a {@link + * java.net.URLPermission} for the request's URI, method and any user set + * headers. The security manager is also checked for each incoming + * additional server generated request/response. Any request that fails the + * security check, is canceled and ignored. + * + *

      This method can be used for both HTTP/1.1 and HTTP/2, but in cases + * where multiple responses are not supported, the MultiProcessor + * only receives the main response. + * + *

      The aggregate {@code CompletableFuture} returned from this method + * returns a {@code } defined by the {@link HttpResponse.MultiProcessor} + * implementation supplied. This will typically be a Collection of + * HttpResponses or of some response body type. + * + * @param the aggregate response type + * @param rspproc the MultiProcessor for the request + * @return a {@code CompletableFuture} + * @throws IllegalStateException if the request has already been sent. + */ + public abstract CompletableFuture + multiResponseAsync(HttpResponse.MultiProcessor rspproc); + + /** + * Returns the request method for this request. If not set explicitly, + * the default method for any request is "GET". + * + * @return this request's method + */ + public abstract String method(); + + /** + * Returns this request's {@link HttpRequest.Builder#expectContinue(boolean) + * expect continue } setting. + * + * @return this request's expect continue setting + */ + public abstract boolean expectContinue(); + + /** + * Returns this request's request URI. + * + * @return this request's URI + */ + public abstract URI uri(); + + /** + * Returns this request's {@link HttpClient}. + * + * @return this request's HttpClient + */ + public abstract HttpClient client(); + + /** + * Returns the HTTP protocol version that this request will use or used. + * + * @return HTTP protocol version + */ + public abstract HttpClient.Version version(); + + /** + * The (user-accessible) request headers that this request was (or will be) + * sent with. + * + * @return this request's HttpHeaders + */ + public abstract HttpHeaders headers(); + + /** + * Returns a request processor whose body is the given String, converted + * using the {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1} + * character set. + * + * @param body the String containing the body + * @return a BodyProcessor + */ + public static BodyProcessor fromString(String body) { + return fromString(body, StandardCharsets.ISO_8859_1); + } + + /** + * A request processor that takes data from the contents of a File. + * + * @param path the path to the file containing the body + * @return a BodyProcessor + */ + public static BodyProcessor fromFile(Path path) { + FileChannel fc; + long size; + + try { + fc = FileChannel.open(path); + size = fc.size(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + return new BodyProcessor() { + LongConsumer flow; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + // could return exact file length, but for now -1 + this.flow = flow; + flow.accept(1); + if (size != 0) { + return size; + } else { + return -1; + } + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) throws IOException { + int n = fc.read(buffer); + if (n == -1) { + fc.close(); + return true; + } + flow.accept(1); + return false; + } + + @Override + public void onRequestError(Throwable t) { + try { + fc.close(); + } catch (IOException ex) { + Log.logError(ex.toString()); + } + } + }; + } + + /** + * Returns a request processor whose body is the given String, converted + * using the given character set. + * + * @param s the String containing the body + * @param charset the character set to convert the string to bytes + * @return a BodyProcessor + */ + public static BodyProcessor fromString(String s, Charset charset) { + return fromByteArray(s.getBytes(charset)); + } + + /** + * Returns a request processor whose body is the given byte array. + * + * @param buf the byte array containing the body + * @return a BodyProcessor + */ + public static BodyProcessor fromByteArray(byte[] buf) { + return fromByteArray(buf, 0, buf.length); + } + + /** + * Returns a request processor whose body is the content of the given byte + * array length bytes starting from the specified offset. + * + * @param buf the byte array containing the body + * @param offset the offset of the first byte + * @param length the number of bytes to use + * @return a BodyProcessor + */ + public static BodyProcessor fromByteArray(byte[] buf, int offset, int length) { + + return new BodyProcessor() { + LongConsumer flow; + byte[] barray; + int index; + int sent; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + this.flow = flow; + flow.accept(1); + barray = buf; + index = offset; + return length; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + if (sent == length) { + return true; + } + + int remaining = buffer.remaining(); + int left = length - sent; + int n = remaining > left ? left : remaining; + buffer.put(barray, index, n); + index += n; + sent += n; + flow.accept(1); + return sent == length; + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor that takes data from an Iterator of byte arrays. + * + * @param iter an Iterator of byte arrays + * @return a BodyProcessor + */ + public static BodyProcessor fromByteArrays(Iterator iter) { + + return new BodyProcessor() { + LongConsumer flow; + byte[] current; + int curIndex; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + this.flow = flow; + flow.accept(1); + return -1; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + int remaining; + + while ((remaining = buffer.remaining()) > 0) { + if (current == null) { + if (!iter.hasNext()) { + return true; + } + current = iter.next(); + curIndex = 0; + } + int n = Math.min(remaining, current.length - curIndex); + buffer.put(current, curIndex, n); + curIndex += n; + + if (curIndex == current.length) { + current = null; + flow.accept(1); + return false; + } + } + flow.accept(1); + return false; + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor that reads its data from an InputStream. + * + * @param stream an InputStream + * @return a BodyProcessor + */ + public static BodyProcessor fromInputStream(InputStream stream) { + // for now, this blocks. It could be offloaded to a separate thread + // to do reading and guarantee that onRequestBodyChunk() won't block + return new BodyProcessor() { + LongConsumer flow; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + this.flow = flow; + flow.accept(1); + return -1; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + int remaining = buffer.remaining(); + int n = stream.read(buffer.array(), buffer.arrayOffset(), remaining); + if (n == -1) { + stream.close(); + return true; + } + buffer.position(buffer.position() + n); + flow.accept(1); + return false; + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor which sends no request body. + * + * @return a BodyProcessor + */ + public static BodyProcessor noBody() { + return new BodyProcessor() { + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + return 0; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + throw new InternalError("should never reach here"); + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor which obtains the request body from some source. + * Implementations of this interface are provided which allow request bodies + * to be supplied from standard types, such as {@code String, byte[], File, + * InputStream}. Other implementations can be provided. + * + *

      The methods of this interface may be called from multiple threads, + * but only one method is invoked at a time, and behaves as if called from + * one thread. + * + *

      See {@link HttpRequest} for implementations that take request bodies + * from {@code byte arrays, Strings, Paths} etc. + * + * @since 9 + */ + public interface BodyProcessor { + + /** + * Called before a request is sent. Is expected to return the content + * length of the request body. Zero means no content. Less than zero + * means an unknown positive content-length, and the body will be + * streamed. + * + *

      The flowController object must be used to manage the flow of + * calls to {@link #onRequestBodyChunk(ByteBuffer)}. The typical usage + * for a non-blocking processor is to call it once inside + * onRequestStart() and once during each call to onRequestBodyChunk(). + * + * @param hr the request + * @param flowController the HttpFlowController + * @return the content length + * @throws IOException if an I/O error occurs + */ + long onRequestStart(HttpRequest hr, LongConsumer flowController) + throws IOException; + + /** + * Called if sending a request body fails. + * + * @implSpec The default implementation does nothing. + * + * @param t the Throwable that caused the failure + */ + default void onRequestError(Throwable t) { } + + /** + * Called to obtain a buffer of data to send. The data must be placed + * in the provided buffer. The implementation should not block. The + * boolean return code notifies the protocol implementation if the + * supplied buffer is the final one (or not). + * + * @param buffer a ByteBuffer to write data into + * @return whether or not this is the last buffer + * @throws IOException if an I/O error occurs + */ + boolean onRequestBodyChunk(ByteBuffer buffer) throws IOException; + + /** + * Called when the request body has been completely sent. + * + * @implSpec The default implementation does nothing + */ + default void onComplete() { + // TODO: need to call this + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java new file mode 100644 index 00000000000..bc04ab3e921 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.net.URI; +import java.net.ProxySelector; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +class HttpRequestBuilderImpl extends HttpRequest.Builder { + + private HttpHeadersImpl userHeaders; + private URI uri; + private String method; + private HttpClient.Redirect followRedirects; + private boolean expectContinue; + private HttpRequest.BodyProcessor body; + private HttpClient.Version version; + private final HttpClientImpl client; + private ProxySelector proxy; + private long timeval = 0; + + public HttpRequestBuilderImpl(HttpClientImpl client, URI uri) { + this.client = client; + this.uri = uri; + this.version = client.version(); + this.userHeaders = new HttpHeadersImpl(); + } + + @Override + public HttpRequestBuilderImpl body(HttpRequest.BodyProcessor reqproc) { + Objects.requireNonNull(reqproc); + this.body = reqproc; + return this; + } + + @Override + public HttpRequestBuilderImpl uri(URI uri) { + Objects.requireNonNull(uri); + this.uri = uri; + return this; + } + + @Override + public HttpRequestBuilderImpl followRedirects(HttpClient.Redirect follow) { + Objects.requireNonNull(follow); + this.followRedirects = follow; + return this; + } + + @Override + public HttpRequestBuilderImpl header(String name, String value) { + Objects.requireNonNull(name); + Objects.requireNonNull(value); + Utils.validateToken(name, "invalid header name"); + userHeaders.addHeader(name, value); + return this; + } + + @Override + public HttpRequestBuilderImpl headers(String... params) { + Objects.requireNonNull(params); + if (params.length % 2 != 0) { + throw new IllegalArgumentException("wrong number of parameters"); + } + for (int i=0; i DISALLOWED_HEADERS_SET = Set.of( + "authorization", "connection", "cookie", "content-length", + "date", "expect", "from", "host", "origin", "proxy-authorization", + "referer", "user-agent", "upgrade", "via", "warning"); + + + // we silently drop headers that are disallowed + private void dropDisallowedHeaders() { + Set hdrnames = userHeaders.directMap().keySet(); + + hdrnames.removeIf((s) -> + DISALLOWED_HEADERS_SET.contains(s.toLowerCase()) + ); + } + + private synchronized void receiving() { + if (receiving) { + throw new IllegalStateException("already receiving response"); + } + receiving = true; + } + + /* + * Response filters may result in a new HttpRequestImpl being created + * (but still associated with the same API HttpRequest) and the process + * is repeated. + */ + @Override + public HttpResponse response() throws IOException, InterruptedException { + receiving(); // TODO: update docs + if (System.getSecurityManager() != null) { + acc = AccessController.getContext(); + } + return exchange.response(); + } + + @Override + public synchronized CompletableFuture responseAsync() { + receiving(); // TODO: update docs + if (System.getSecurityManager() != null) { + acc = AccessController.getContext(); + } + return exchange.responseAsync(null) + .thenApply((r) -> (HttpResponse)r); + } + + public CompletableFuture + sendAsyncMulti(HttpResponse.MultiProcessor rspproc) { + // To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean expectContinue() { return expectContinue; } + + public boolean requestHttp2() { + return version.equals(HttpClient.Version.HTTP_2); + //return client.getHttp2Allowed(); + } + + AccessControlContext getAccessControlContext() { return acc; } + + InetSocketAddress proxy() { + ProxySelector ps = this.proxy; + if (ps == null) { + ps = client.proxy().orElse(null); + } + if (ps == null || method.equalsIgnoreCase("CONNECT")) { + return null; + } + return (InetSocketAddress)ps.select(uri).get(0).address(); + } + + boolean secure() { return secure; } + + void isWebSocket(boolean is) { + isWebSocket = is; + } + + boolean isWebSocket() { + return isWebSocket; + } + + /** Returns the follow-redirects setting for this request. */ + @Override + public java.net.http.HttpClient.Redirect followRedirects() { + return getRedirects(followRedirects); + } + + HttpRedirectImpl followRedirectsImpl() { return followRedirects; } + + /** + * Returns the request method for this request. If not set explicitly, + * the default method for any request is "GET". + */ + @Override + public String method() { return method; } + + @Override + public URI uri() { return uri; } + + HttpHeadersImpl getUserHeaders() { return userHeaders; } + + HttpHeadersImpl getSystemHeaders() { return systemHeaders; } + + HttpClientImpl getClient() { return client; } + + BodyProcessor requestProcessor() { return requestProcessor; } + + @Override + public Version version() { return version; } + + void addSystemHeader(String name, String value) { + systemHeaders.addHeader(name, value); + } + + void setSystemHeader(String name, String value) { + systemHeaders.setHeader(name, value); + } + + long timeval() { return timeval; } + + @Override + public CompletableFuture + multiResponseAsync(MultiProcessor rspproc) { + //To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java new file mode 100644 index 00000000000..c1ff5adb44e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java @@ -0,0 +1,977 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ +package java.net.http; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.LongConsumer; +import javax.net.ssl.SSLParameters; + +/** + * Represents a response to a {@link HttpRequest}. A {@code HttpResponse} is + * available when the response status code and headers have been received, but + * before the response body is received. + * + *

      Methods are provided in this class for accessing the response headers, + * and status code immediately and also methods for retrieving the response body. + * Static methods are provided which implement {@link BodyProcessor} for + * standard body types such as {@code String, byte arrays, files}. + * + *

      The {@link #body(BodyProcessor) body} or {@link #bodyAsync(BodyProcessor) + * bodyAsync} which retrieve any response body must be called to ensure that the + * TCP connection can be re-used subsequently, and any response trailers + * accessed, if they exist, unless it is known that no response body was received. + * + * @since 9 + */ +public abstract class HttpResponse { + + HttpResponse() { } + + /** + * Returns the status code for this response. + * + * @return the response code + */ + public abstract int statusCode(); + + /** + * Returns the {@link HttpRequest} for this response. + * + * @return the request + */ + public abstract HttpRequest request(); + + /** + * Returns the received response headers. + * + * @return the response headers + */ + public abstract HttpHeaders headers(); + + /** + * Returns the received response trailers, if there are any. This must only + * be called after the response body has been received. + * + * @return the response trailers (may be empty) + * @throws IllegalStateException if the response body has not been received + * yet + */ + public abstract HttpHeaders trailers(); + + /** + * Returns the body, blocking if necessary. The type T is determined by the + * {@link BodyProcessor} implementation supplied. The body object will be + * returned immediately if it is a type (such as {@link java.io.InputStream} + * which reads the data itself. If the body object represents the fully read + * body then it blocks until it is fully read. + * + * @param the type of the returned body object + * @param processor the processor to handle the response body + * @return the body + * @throws java.io.UncheckedIOException if an I/O error occurs reading the + * response + */ + public abstract T body(BodyProcessor processor); + + /** + * Returns a {@link java.util.concurrent.CompletableFuture} of type T. This + * always returns immediately and the future completes when the body object + * is available. The body will be available immediately if it is a type + * (such as {@link java.io.InputStream} which reads the data itself. If the + * body object represents the fully read body then it will not be available + * until it is fully read. + * + * @param the type of the returned body object + * @param processor the processor to handle the response body + * @return a CompletableFuture + */ + public abstract CompletableFuture bodyAsync(BodyProcessor processor); + + /** + * Returns the {@link javax.net.ssl.SSLParameters} in effect for this + * response. Returns {@code null} if this is not a https response. + * + * @return the SSLParameters associated with the response + */ + public abstract SSLParameters sslParameters(); + + /** + * Returns the URI that the response was received from. This may be + * different from the request URI if redirection occurred. + * + * @return the URI of the response + */ + public abstract URI uri(); + + /** + * Returns the HTTP protocol version that was used for this response. + * + * @return HTTP protocol version + */ + public abstract HttpClient.Version version(); + + /** + * Returns a {@link BodyProcessor}<{@link java.nio.file.Path}> where + * the file is created if it does not already exist. When the Path object is + * returned, the body has been completely written to the file. + * + * @param file the file to store the body in + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asFile(Path file) { + return asFile(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE); + } + + /** + * Returns a {@link BodyProcessor}<{@link java.nio.file.Path}> where + * the download directory is specified, but the filename is obtained from + * the Content-Disposition response header. The Content-Disposition header + * must specify the attachment type and must also contain a + * filename parameter. If the filename specifies multiple path + * components only the final component is used as the filename (with the + * given directory name). When the Path object is returned, the body has + * been completely written to the file. The returned Path is the combination + * of the supplied directory name and the file name supplied by the server. + * If the destination directory does not exist or cannot be written to, then + * the response will fail with an IOException. + * + * @param directory the directory to store the file in + * @param openOptions open options + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asFileDownload(Path directory, + OpenOption... openOptions) { + return new AbstractResponseProcessor() { + + FileChannel fc; + Path file; + + @Override + public Path onResponseBodyStartImpl(long contentLength, + HttpHeaders headers) + throws IOException + { + String dispoHeader = headers.firstValue("Content-Disposition") + .orElseThrow(() -> new IOException("No Content-Disposition")); + if (!dispoHeader.startsWith("attachment;")) { + throw new IOException("Unknown Content-Disposition type"); + } + int n = dispoHeader.indexOf("filename="); + if (n == -1) { + throw new IOException("Bad Content-Disposition type"); + } + String disposition = dispoHeader.substring(n + 9, + dispoHeader.lastIndexOf(';')); + file = Paths.get(directory.toString(), disposition); + fc = FileChannel.open(file, openOptions); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) throws IOException { + fc.write(b); + } + + @Override + public Path onResponseComplete() throws IOException { + fc.close(); + return file; + } + + @Override + public void onResponseError(Throwable t) { + try { + if (fc != null) { + fc.close(); + } + } catch (IOException e) { + } + } + }; + } + + /** + * Returns a {@link BodyProcessor}<{@link java.nio.file.Path}>. + * + *

      {@link HttpResponse}s returned using this response processor complete + * after the entire response, including body has been read. + * + * @param file the filename to store the body in + * @param openOptions any options to use when opening/creating the file + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asFile(Path file, + OpenOption... openOptions) { + return new AbstractResponseProcessor() { + + FileChannel fc; + + @Override + public Path onResponseBodyStartImpl(long contentLength, + HttpHeaders headers) + throws IOException + { + fc = FileChannel.open(file, openOptions); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) + throws IOException + { + fc.write(b); + } + + @Override + public Path onResponseComplete() throws IOException { + fc.close(); + return file; + } + + @Override + public void onResponseError(Throwable t) { + try { + if (fc != null) { + fc.close(); + } + } catch (IOException e) { + } + } + }; + } + + static class ByteArrayResponseProcessor { + + static final int INITIAL_BUFLEN = 1024; + + byte[] buffer; + int capacity; + boolean knownLength; + int position; + + ByteArrayResponseProcessor() { } + + public byte[] onStart(long contentLength) throws IOException { + if (contentLength > Integer.MAX_VALUE) { + throw new IllegalArgumentException( + "byte array response limited to MAX_INT size"); + } + capacity = (int) contentLength; + if (capacity != -1) { + buffer = new byte[capacity]; + knownLength = true; + } else { + buffer = new byte[INITIAL_BUFLEN]; + capacity = INITIAL_BUFLEN; + knownLength = false; + } + position = 0; + return null; + } + + public void onBodyContent(ByteBuffer b) throws IOException { + int toCopy = b.remaining(); + int size = capacity; + if (toCopy > capacity - position) { + // resize + size += toCopy * 2; + } + if (size != capacity) { + if (knownLength) { + // capacity should have been right from start + throw new IOException("Inconsistent content length"); + } + byte[] newbuf = new byte[size]; + System.arraycopy(buffer, 0, newbuf, 0, position); + buffer = newbuf; + capacity = size; + } + int srcposition = b.arrayOffset() + b.position(); + System.arraycopy(b.array(), srcposition, buffer, position, toCopy); + b.position(b.limit()); + position += toCopy; + } + + public byte[] onComplete() throws IOException { + if (knownLength) { + if (position != capacity) { + throw new IOException("Wrong number of bytes received"); + } + return buffer; + } + byte[] buf1 = new byte[position]; + System.arraycopy(buffer, 0, buf1, 0, position); + return buf1; + } + + public void onError(Throwable t) { + // TODO: + } + } + + static final byte[] EMPTY = new byte[0]; + + /** + * Returns a response processor which supplies the response body to the + * given Consumer. Each time data is received the consumer is invoked with a + * byte[] containing at least one byte of data. After the final buffer is + * received, the consumer is invoked one last time, with an empty byte + * array. + * + * @param consumer a Consumer to accept the response body + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asByteArrayConsumer(Consumer consumer) { + return new AbstractResponseProcessor() { + @Override + public Void onResponseBodyStartImpl(long clen, + HttpHeaders h) + throws IOException + { + return null; + } + + @Override + public void onResponseError(Throwable t) { + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) throws IOException { + if (!b.hasRemaining()) { + return; + } + byte[] buf = new byte[b.remaining()]; + b.get(buf); + consumer.accept(buf); + } + + @Override + public Void onResponseComplete() throws IOException { + consumer.accept(EMPTY); + return null; + } + }; + } + + /** + * Returns a BodyProcessor which delivers the response data to a + * {@link java.util.concurrent.Flow.Subscriber}{@code ByteBuffer}. + *

      + * The given {@code Supplier} is invoked when the Flow is completed in + * order to convert the flow data into the U object that is returned as the + * response body. + * + * @param the response body type + * @param subscriber the Flow.Subscriber + * @param bufferSize the maximum number of bytes of data to be supplied in + * each ByteBuffer + * @param bodySupplier an object that converts the received data to the body + * type U. + * @return a BodyProcessor + * + * public static BodyProcessor> + * asFlowSubscriber() { + * + * return new BodyProcessor() { Flow.Subscriber subscriber; + * LongConsumer flowController; FlowSubscription subscription; Supplier + * bodySupplier; int bufferSize; // down-stream Flow window. long + * buffersWindow; // upstream window long bytesWindow; + * LinkedList buffers = new LinkedList<>(); + * + * class FlowSubscription implements Subscription { int recurseLevel = 0; + * @Override public void request(long n) { boolean goodToGo = recurseLevel++ + * == 0; + * + * while (goodToGo && buffers.size() > 0 && n > 0) { ByteBuffer buf = + * buffers.get(0); subscriber.onNext(buf); n--; } buffersWindow += n; + * flowController.accept(n * bufferSize); recurseLevel--; } + * + * @Override public void cancel() { // ?? set flag and throw exception on + * next receipt of buffer } } + * + * @Override public U onResponseBodyStart(long contentLength, HttpHeaders + * responseHeaders, LongConsumer flowController) throws IOException { + * this.subscriber = subscriber; this.flowController = flowController; + * this.subscription = new FlowSubscription(); this.bufferSize = bufferSize; + * subscriber.onSubscribe(subscription); return null; } + * + * @Override public void onResponseError(Throwable t) { + * subscriber.onError(t); } + * + * @Override public void onResponseBodyChunk(ByteBuffer b) throws + * IOException { if (buffersWindow > 0) { buffersWindow --; + * subscriber.onNext(b); } else { buffers.add(b); // or could combine + * buffers? } } + * + * @Override public U onResponseComplete() throws IOException { + * subscriber.onComplete(); return bodySupplier.get(); } }; } + */ + private static final ByteBuffer EOF = ByteBuffer.allocate(0); + private static final ByteBuffer CLOSED = ByteBuffer.allocate(0); + + // prototype using ByteBuffer based flow control. InputStream feeds off a + // BlockingQueue. Size of Q is determined from the the bufsize (bytes) and + // the default ByteBuffer size. bufsize should be a reasonable multiple of + // ByteBuffer size to prevent underflow/starvation. The InputStream updates + // the flowControl window by one as each ByteBuffer is fully consumed. + // Special sentinels are used to indicate stream closed and EOF. + /** + * Returns a response body processor which provides an InputStream to read + * the body. + * + * @implNote This mechanism is provided primarily for backwards + * compatibility for code that expects InputStream. It is recommended for + * better performance to use one of the other response processor + * implementations. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asInputStream() { + return new BodyProcessor() { + int queueSize = 2; + private volatile Throwable throwable; + + BlockingQueue queue = new LinkedBlockingQueue<>(); + + private void closeImpl() { + try { + queue.put(CLOSED); + } catch (InterruptedException e) { } + } + + @Override + public InputStream onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer flowController) + throws IOException + { + flowController.accept(queueSize); + + return new InputStream() { + ByteBuffer buffer; + + @Override + public int read() throws IOException { + byte[] bb = new byte[1]; + int n = read(bb, 0, 1); + if (n == -1) { + return -1; + } else { + return bb[0]; + } + } + + @Override + public int read(byte[] bb) throws IOException { + return read(bb, 0, bb.length); + } + + @Override + public int read(byte[] bb, int offset, int length) + throws IOException + { + int n; + if (getBuffer()) { + return -1; // EOF + } else { + int remaining = buffer.remaining(); + if (length >= remaining) { + buffer.get(bb, offset, remaining); + return remaining; + } else { + buffer.get(bb, offset, length); + return length; + } + } + } + + @Override + public void close() { + closeImpl(); + } + + private boolean getBuffer() throws IOException { + while (buffer == null || (buffer != EOF && + buffer != CLOSED && !buffer.hasRemaining())) { + try { + buffer = queue.take(); + flowController.accept(1); + } catch (InterruptedException e) { + throw new IOException(e); + } + } + if (buffer == CLOSED) { + if (throwable != null) { + if (throwable instanceof IOException) { + throw (IOException) throwable; + } else { + throw new IOException(throwable); + } + } + throw new IOException("Closed"); + } + + if (buffer == EOF) { + return true; // EOF + } + return false; // not EOF + } + + }; + } + + @Override + public void onResponseError(Throwable t) { + throwable = t; + closeImpl(); + } + + @Override + public void onResponseBodyChunk(ByteBuffer b) throws IOException { + try { + queue.put(Utils.copy(b)); + } catch (InterruptedException e) { + // shouldn't happen as queue should never block + throw new IOException(e); + } + } + + @Override + public InputStream onResponseComplete() throws IOException { + try { + queue.put(EOF); + } catch (InterruptedException e) { + throw new IOException(e); // can't happen + } + return null; + } + + }; + } + + /** + * Common super class that takes care of flow control + * + * @param + */ + private static abstract class AbstractResponseProcessor + implements BodyProcessor + { + LongConsumer flowController; + + @Override + public final T onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer flowController) + throws IOException + { + this.flowController = flowController; + flowController.accept(1); + return onResponseBodyStartImpl(contentLength, responseHeaders); + } + + public abstract T onResponseBodyStartImpl(long contentLength, + HttpHeaders responseHeaders) + throws IOException; + + public abstract void onResponseBodyChunkImpl(ByteBuffer b) + throws IOException; + + @Override + public final void onResponseBodyChunk(ByteBuffer b) throws IOException { + onResponseBodyChunkImpl(b); + flowController.accept(1); + } + } + + /** + * Returns a {@link BodyProcessor}<byte[]> which returns the response + * body as a {@code byte array}. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asByteArray() { + ByteArrayResponseProcessor brp = new ByteArrayResponseProcessor(); + + return new AbstractResponseProcessor() { + + @Override + public byte[] onResponseBodyStartImpl(long contentLength, + HttpHeaders h) + throws IOException + { + brp.onStart(contentLength); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) + throws IOException + { + brp.onBodyContent(b); + } + + @Override + public byte[] onResponseComplete() throws IOException { + return brp.onComplete(); + } + + @Override + public void onResponseError(Throwable t) { + brp.onError(t); + } + }; + } + + /** + * Returns a response processor which decodes the body using the character + * set specified in the {@code Content-encoding} response header. If there + * is no such header, or the character set is not supported, then + * {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1} is used. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asString() { + return asString(null); + } + + /** + * Returns a MultiProcessor that handles multiple responses, writes the + * response bodies to files and which returns an aggregate response object + * that is a {@code Map}. The keyset of the Map represents the + * URIs of the original request and any additional requests generated by the + * server. The values are the paths of the destination files. Each path uses + * the URI path of the request offset from the destination parent directory + * provided. + * + *

      All incoming additional requests (push promises) are accepted by this + * multi response processor. Errors are effectively ignored and any failed + * responses are simply omitted from the result Map. Other implementations + * of MultiProcessor can handle these situations + * + *

      Example usage + *

      +     * {@code
      +     *    CompletableFuture> cf =
      +     *    HttpRequest.create(new URI("https://www.foo.com/"))
      +     *               .version(Version.HTTP2)
      +     *               .GET()
      +     *               .sendAsyncMulti(HttpResponse.multiFile("/usr/destination"));
      +     *
      +     *    Map results = cf.join();
      +     * }
      +     * 
      + * + * @param destination the destination parent directory of all response + * bodies + * @return a MultiProcessor + */ + public static MultiProcessor> multiFile(Path destination) { + + return new MultiProcessor>() { + Map> bodyCFs = new HashMap<>(); + + Map results = new HashMap<>(); + + @Override + public BiFunction, Boolean> + onStart(HttpRequest mainRequest, + CompletableFuture response) { + bodyCFs.put(mainRequest.uri(), getBody(mainRequest, response)); + return (HttpRequest additional, CompletableFuture cf) -> { + CompletableFuture bcf = getBody(additional, cf); + bodyCFs.put(additional.uri(), bcf); + // we accept all comers + return true; + }; + } + + private CompletableFuture getBody(HttpRequest req, + CompletableFuture cf) { + URI u = req.uri(); + String path = u.getPath(); + return cf.thenCompose((HttpResponse resp) -> { + return resp.bodyAsync(HttpResponse.asFile(destination.resolve(path))); + }); + } + + @Override + public Map onComplete() { + // all CFs have completed normally or in error. + Set>> entries = bodyCFs.entrySet(); + for (Map.Entry> entry : entries) { + CompletableFuture v = entry.getValue(); + URI uri = entry.getKey(); + if (v.isDone() && !v.isCompletedExceptionally()) { + results.put(uri, v.join()); + } + } + return results; + } + }; + } + + /** + * Returns a {@link BodyProcessor}<{@link String}>. + * + * @param charset the name of the charset to interpret the body as. If + * {@code null} then the processor tries to determine the character set from + * the {@code Content-encoding} header. If that charset is not supported + * then {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1} is + * used. + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asString(Charset charset) { + + ByteArrayResponseProcessor brp = new ByteArrayResponseProcessor(); + + return new AbstractResponseProcessor() { + Charset cs = charset; + HttpHeaders headers; + + @Override + public String onResponseBodyStartImpl(long contentLength, + HttpHeaders h) + throws IOException + { + headers = h; + brp.onStart(contentLength); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) throws IOException { + brp.onBodyContent(b); + } + + @Override + public String onResponseComplete() throws IOException { + byte[] buf = brp.onComplete(); + if (cs == null) { + cs = headers.firstValue("Content-encoding") + .map((String s) -> Charset.forName(s)) + .orElse(StandardCharsets.ISO_8859_1); + } + return new String(buf, cs); + } + + @Override + public void onResponseError(Throwable t) { + brp.onError(t); + } + + }; + } + + /** + * Returns a response processor which ignores the response body. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor ignoreBody() { + return asByteArrayConsumer((byte[] buf) -> { /* ignore */ }); + } + + /** + * A processor for response bodies, which determines the type of the + * response body returned from {@link HttpResponse}. Response processors can + * either return an object that represents the body itself (after it has + * been read) or else an object that is used to read the body (such as an + * {@code InputStream}). The parameterized type {@code } is the type of + * the returned body object from + * {@link HttpResponse#body(BodyProcessor) HttpResponse.body} and + * (indirectly) from {@link HttpResponse#bodyAsync(BodyProcessor) + * HttpResponse.bodyAsync}. + * + *

      Implementations of this interface are provided in {@link HttpResponse} + * which write responses to {@code String, byte[], File, Consumer}. + * Custom implementations can also be used. + * + *

      The methods of this interface may be called from multiple threads, + * but only one method is invoked at a time, and behaves as if called from + * one thread. + * + * @param the type of the response body + * + * @since 9 + */ + public interface BodyProcessor { + + /** + * Called immediately before the response body is read. If {@code } + * is an object used to read or accept the response body, such as a + * {@code Consumer} or {@code InputStream} then it should be returned + * from this method, and the body object will be returned before any + * data is read. If {@code } represents the body itself after being + * read, then this method must return {@code null} and the body will be + * returned from {@link #onResponseComplete()}. In both cases, the + * actual body data is provided by the + * {@link #onResponseBodyChunk(ByteBuffer) onResponseBodyChunk} method + * in exactly the same way. + * + *

      flowController is a consumer of long values and is used for + * updating a flow control window as follows. The window represents the + * number of times + * {@link #onResponseBodyChunk(java.nio.ByteBuffer) onResponseBodyChunk} + * may be called before receiving further updates to the window. Each + * time it is called, the window is reduced by {@code 1}. When the + * window reaches zero {@code onResponseBodyChunk()} will not be called + * again until the window has opened again with further calls to + * flowController.accept(). + * {@link java.util.function.LongConsumer#accept(long) flowcontroller.accept()} + * must be called to open (increase) the window by the specified amount. + * The initial value is zero. This implies that if {@code + * onResponseBodyStart()} does not call {@code flowController.accept()} + * with a positive value no data will ever be delivered. + * + * @param contentLength {@code -1} signifies unknown content length. + * Otherwise, a positive integer, or zero. + * @param responseHeaders the response headers + * @param flowController a LongConsumer used to update the flow control + * window + * @return {@code null} or an object that can be used to read the + * response body. + * @throws IOException if an exception occurs starting the response + * body receive + */ + T onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer flowController) + throws IOException; + + /** + * Called if an error occurs while reading the response body. This + * terminates the operation and no further calls will occur after this. + * + * @param t the Throwable + */ + void onResponseError(Throwable t); + + /** + * Called for each buffer of data received for this response. + * ByteBuffers can be reused as soon as this method returns. + * + * @param b a ByteBuffer whose position is at the first byte that can be + * read, and whose limit is after the last byte that can be read + * @throws IOException in case of I/O error + */ + void onResponseBodyChunk(ByteBuffer b) throws IOException; + + /** + * Called after the last time + * {@link #onResponseBodyChunk(java.nio.ByteBuffer)} has been called and + * returned indicating that the entire content has been read. This + * method must return an object that represents or contains the response + * body just received, but only if an object was not returned from + * {@link #onResponseBodyStart(long, HttpHeaders, LongConsumer) + * onResponseBodyStart}. + * + * @return a T, or {@code null} if an object was already returned + * @throws IOException in case of I/O error + */ + T onResponseComplete() throws IOException; + } + + /** + * A response processor for a HTTP/2 multi response. A multi response + * comprises a main response, and zero or more additional responses. Each + * additional response is sent by the server in response to requests that + * the server also generates. Additional responses are typically resources + * that the server guesses the client will need which are related to the + * initial request. + * + *

      The server generated requests are also known as push promises. + * The server is permitted to send any number of these requests up to the + * point where the main response is fully received. Therefore, after + * completion of the main response body, the final number of additional + * responses is known. Additional responses may be cancelled, but given that + * the server does not wait for any acknowledgment before sending the + * response, this must be done quickly to avoid unnecessary data transmission. + * + *

      {@code MultiProcessor}s are parameterised with a type {@code T} which + * represents some meaningful aggregate of the responses received. This + * would typically be a Collection of response or response body objects. One + * example implementation can be found at {@link + * HttpResponse#multiFile(java.nio.file.Path)}. + * + * @param a type representing the aggregated results + * + * @since 9 + */ + public interface MultiProcessor { + + /** + * Called before or soon after a multi request is sent. The request that + * initiated the multi response is supplied, as well as a + * CompletableFuture for the main response. The implementation of this + * method must return a BiFunction which is called once for each push + * promise received. + * + *

      The parameters to the {@code BiFunction} are the {@code HttpRequest} + * for the push promise and a {@code CompletableFuture} for its + * response. The function must return a Boolean indicating whether the + * push promise has been accepted (true) or should be canceled (false). + * The CompletableFutures for any canceled pushes are themselves + * completed exceptionally soon after the function returns. + * + * @param mainRequest the main request + * @param response a CompletableFuture for the main response + * @return a BiFunction that is called for each push promise + */ + BiFunction, Boolean> + onStart(HttpRequest mainRequest, + CompletableFuture response); + + /** + * Called after all responses associated with the multi response have + * been fully processed, including response bodies. + * + *

      Example types for {@code T} could be Collections of response body + * types or {@code Map}s from request {@code URI} to a response body + * type. + * + * @return the aggregate response object + */ + T onComplete(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java new file mode 100644 index 00000000000..c71f53a04ea --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ + +package java.net.http; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.util.concurrent.CompletableFuture; +import java.util.function.LongConsumer; +import javax.net.ssl.SSLParameters; + +/** + * The implementation class for HttpResponse + */ +class HttpResponseImpl extends HttpResponse { + + int responseCode; + Exchange exchange; + HttpRequestImpl request; + HttpHeaders1 headers; + HttpHeaders1 trailers; + SSLParameters sslParameters; + URI uri; + HttpClient.Version version; + AccessControlContext acc; + RawChannel rawchan; + HttpConnection connection; + + public HttpResponseImpl(int responseCode, Exchange exch, HttpHeaders1 headers, + HttpHeaders1 trailers, SSLParameters sslParameters, + HttpClient.Version version, HttpConnection connection) { + this.responseCode = responseCode; + this.exchange = exch; + this.request = exchange.request(); + this.headers = headers; + this.trailers = trailers; + this.sslParameters = sslParameters; + this.uri = request.uri(); + this.version = version; + this.connection = connection; + } + + @Override + public int statusCode() { + return responseCode; + } + + @Override + public HttpRequestImpl request() { + return request; + } + + @Override + public HttpHeaders headers() { + headers.makeUnmodifiable(); + return headers; + } + + @Override + public HttpHeaders trailers() { + trailers.makeUnmodifiable(); + return trailers; + } + + + @Override + public T body(java.net.http.HttpResponse.BodyProcessor processor) { + return exchange.responseBody(processor); + } + + @Override + public CompletableFuture bodyAsync(java.net.http.HttpResponse.BodyProcessor processor) { + acc = AccessController.getContext(); + return exchange.responseBodyAsync(processor); + } + + @Override + public SSLParameters sslParameters() { + return sslParameters; + } + + public AccessControlContext getAccessControlContext() { + return acc; + } + + @Override + public URI uri() { + return uri; + } + + @Override + public HttpClient.Version version() { + return version; + } + // keepalive flag determines whether connection is closed or kept alive + // by reading/skipping data + + public static java.net.http.HttpResponse.BodyProcessor ignoreBody(boolean keepalive) { + return new java.net.http.HttpResponse.BodyProcessor() { + + @Override + public Void onResponseBodyStart(long clen, HttpHeaders h, + LongConsumer flowController) throws IOException { + return null; + } + + @Override + public void onResponseBodyChunk(ByteBuffer b) throws IOException { + } + + @Override + public Void onResponseComplete() throws IOException { + return null; + } + + @Override + public void onResponseError(Throwable t) { + } + }; + } + + /** + * + * @return + */ + RawChannel rawChannel() { + if (rawchan == null) { + rawchan = new RawChannel(request.client(), connection); + } + return rawchan; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java new file mode 100644 index 00000000000..448fda35156 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ + +package java.net.http; + +import java.io.IOException; + +/** + * Thrown when a response is not received within a specified time period. + */ +public class HttpTimeoutException extends IOException { + + private static final long serialVersionUID = 981344271622632951L; + + public HttpTimeoutException(String message) { + super(message); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java new file mode 100644 index 00000000000..d696854c5b5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.util.Locale; +import sun.util.logging.PlatformLogger; + +/** + * -Djava.net.HttpClient.log=errors,requests,headers,frames[:type:type2:..],content + * + * Any of errors, requests, headers or content are optional. + * + * Other handlers may be added. All logging is at level INFO + * + * Logger name is "java.net.http.HttpClient" + */ +class Log { + + final static String logProp = "java.net.http.HttpClient.log"; + + public static final int OFF = 0; + public static final int ERRORS = 0x1; + public static final int REQUESTS = 0x2; + public static final int HEADERS = 0x4; + public static final int CONTENT = 0x8; + public static final int FRAMES = 0x10; + public static final int SSL = 0x20; + static int logging; + + // Frame types: "control", "data", "window", "all" + public static final int CONTROL = 1; // all except DATA and WINDOW_UPDATES + public static final int DATA = 2; + public static final int WINDOW_UPDATES = 4; + public static final int ALL = CONTROL| DATA | WINDOW_UPDATES; + static int frametypes; + + static sun.util.logging.PlatformLogger logger; + + static { + String s = Utils.getNetProperty(logProp); + if (s == null) { + logging = OFF; + } else { + String[] vals = s.split(","); + for (String val : vals) { + switch (val.toLowerCase(Locale.US)) { + case "errors": + logging |= ERRORS; + break; + case "requests": + logging |= REQUESTS; + break; + case "headers": + logging |= HEADERS; + break; + case "content": + logging |= CONTENT; + break; + case "ssl": + logging |= SSL; + break; + case "all": + logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS; + break; + } + if (val.startsWith("frames")) { + logging |= FRAMES; + String[] types = val.split(":"); + if (types.length == 1) { + frametypes = CONTROL | DATA | WINDOW_UPDATES; + } else { + for (String type : types) { + switch (type.toLowerCase()) { + case "control": + frametypes |= CONTROL; + break; + case "data": + frametypes |= DATA; + break; + case "window": + frametypes |= WINDOW_UPDATES; + break; + case "all": + frametypes = ALL; + break; + } + } + } + } + } + } + if (logging != OFF) { + logger = PlatformLogger.getLogger("java.net.http.HttpClient"); + } + } + + static boolean errors() { + return (logging & ERRORS) != 0; + } + + static boolean requests() { + return (logging & REQUESTS) != 0; + } + + static boolean headers() { + return (logging & HEADERS) != 0; + } + + static boolean ssl() { + return (logging & SSL) != 0; + } + + static boolean frames() { + return (logging & FRAMES) != 0; + } + + static void logError(String s) { + if (errors()) + logger.info("ERROR: " + s); + } + + static void logError(Throwable t) { + if (errors()) { + String s = Utils.stackTrace(t); + logger.info("ERROR: " + s); + } + } + + static void logSSL(String s) { + if (ssl()) + logger.info("SSL: " + s); + } + + static void logRequest(String s) { + if (requests()) + logger.info("REQUEST: " + s); + } + + static void logResponse(String s) { + if (requests()) + logger.info("RESPONSE: " + s); + } + + static void logHeaders(String s) { + if (headers()) + logger.info("HEADERS: " + s); + } +// END HTTP2 +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java new file mode 100644 index 00000000000..8a53565ae51 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.function.BiFunction; + +import static java.net.http.Pair.pair; + +/** + * Encapsulates multiple Exchanges belonging to one HttpRequestImpl. + * - manages filters + * - retries due to filters. + * - I/O errors and most other exceptions get returned directly to user + * + * Creates a new Exchange for each request/response interaction + */ +class MultiExchange { + + final HttpRequestImpl request; // the user request + final HttpClientImpl client; + HttpRequestImpl currentreq; // used for async only + Exchange exchange; // the current exchange + Exchange previous; + int attempts; + // Maximum number of times a request will be retried/redirected + // for any reason + + final static int DEFAULT_MAX_ATTEMPTS = 5; + final static int max_attempts = Utils.getIntegerNetProperty( + "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS + ); + + private final List filters; + TimedEvent td; + boolean cancelled = false; + + /** + * Filter fields. These are attached as required by filters + * and only used by the filter implementations. This could be + * generalised into Objects that are passed explicitly to the filters + * (one per MultiExchange object, and one per Exchange object possibly) + */ + volatile AuthenticationFilter.AuthInfo serverauth, proxyauth; + // RedirectHandler + volatile int numberOfRedirects = 0; + + /** + */ + MultiExchange(HttpRequestImpl request) { + this.exchange = new Exchange(request); + this.previous = null; + this.request = request; + this.currentreq = request; + this.attempts = 0; + this.client = request.client(); + this.filters = client.filterChain(); + } + + public HttpResponseImpl response() throws IOException, InterruptedException { + HttpRequestImpl r = request; + if (r.timeval() != 0) { + // set timer + td = new TimedEvent(r.timeval()); + client.registerTimer(td); + } + while (attempts < max_attempts) { + try { + attempts++; + Exchange currExchange = getExchange(); + requestFilters(r); + HttpResponseImpl response = currExchange.response(); + Pair filterResult = responseFilters(response); + HttpRequestImpl newreq = filterResult.second; + if (newreq == null) { + if (attempts > 1) { + Log.logError("Succeeded on attempt: " + attempts); + } + cancelTimer(); + return response; + } + response.body(HttpResponse.ignoreBody()); + setExchange(new Exchange(newreq, currExchange.getAccessControlContext() )); + r = newreq; + } catch (IOException e) { + if (cancelled) { + throw new HttpTimeoutException("Request timed out"); + } + throw e; + } + } + cancelTimer(); + throw new IOException("Retry limit exceeded"); + } + + private synchronized Exchange getExchange() { + return exchange; + } + + private synchronized void setExchange(Exchange exchange) { + this.exchange = exchange; + } + + private void cancelTimer() { + if (td != null) { + client.cancelTimer(td); + } + } + + private void requestFilters(HttpRequestImpl r) throws IOException { + for (HeaderFilter filter : filters) { + filter.request(r); + } + } + + // Filters are assumed to be non-blocking so the async + // versions of these methods just call the blocking ones + + private CompletableFuture requestFiltersAsync(HttpRequestImpl r) { + CompletableFuture cf = new CompletableFuture<>(); + try { + requestFilters(r); + cf.complete(null); + } catch(Throwable e) { + cf.completeExceptionally(e); + } + return cf; + } + + + private Pair + responseFilters(HttpResponse response) throws IOException + { + for (HeaderFilter filter : filters) { + HttpRequestImpl newreq = filter.response((HttpResponseImpl)response); + if (newreq != null) { + return pair(null, newreq); + } + } + return pair(response, null); + } + + private CompletableFuture> + responseFiltersAsync(HttpResponse response) + { + CompletableFuture> cf = new CompletableFuture<>(); + try { + Pair n = responseFilters(response); // assumed to be fast + cf.complete(n); + } catch (Throwable e) { + cf.completeExceptionally(e); + } + return cf; + } + + public void cancel() { + cancelled = true; + getExchange().cancel(); + } + + public CompletableFuture responseAsync(Void v) { + CompletableFuture cf; + if (++attempts > max_attempts) { + cf = new CompletableFuture<>(); + cf.completeExceptionally(new IOException("Too many retries")); + } else { + if (currentreq.timeval() != 0) { + // set timer + td = new TimedEvent(currentreq.timeval()); + client.registerTimer(td); + } + Exchange exch = getExchange(); + cf = requestFiltersAsync(currentreq) + .thenCompose(exch::responseAsync) + .thenCompose(this::responseFiltersAsync) + .thenCompose((Pair pair) -> { + HttpResponseImpl resp = (HttpResponseImpl)pair.first; + if (resp != null) { + if (attempts > 1) { + Log.logError("Succeeded on attempt: " + attempts); + } + return CompletableFuture.completedFuture(resp); + } else { + currentreq = pair.second; + Exchange previous = exch; + setExchange(new Exchange(currentreq, + currentreq.getAccessControlContext())); + //reads body off previous, and then waits for next response + return previous + .responseBodyAsync(HttpResponse.ignoreBody()) + .thenCompose(this::responseAsync); + } + }) + .handle((BiFunction>) Pair::new) + .thenCompose((Pair obj) -> { + HttpResponseImpl response = (HttpResponseImpl)obj.first; + if (response != null) { + return CompletableFuture.completedFuture(response); + } + // all exceptions thrown are handled here + CompletableFuture error = getExceptionalCF(obj.second); + if (error == null) { + cancelTimer(); + return responseAsync(null); + } else { + return error; + } + }); + } + return cf; + } + + /** + * Take a Throwable and return a suitable CompletableFuture that is + * completed exceptionally. + */ + private CompletableFuture getExceptionalCF(Throwable t) { + CompletableFuture error = new CompletableFuture<>(); + if ((t instanceof CompletionException) || (t instanceof ExecutionException)) { + if (t.getCause() != null) { + t = t.getCause(); + } + } + if (cancelled && t instanceof IOException) { + t = new HttpTimeoutException("request timed out"); + } + error.completeExceptionally(t); + return error; + } + + T responseBody(HttpResponse.BodyProcessor processor) { + return getExchange().responseBody(processor); + } + + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return getExchange().responseBodyAsync(processor); + } + + class TimedEvent extends TimeoutEvent { + TimedEvent(long timeval) { + super(timeval); + } + @Override + public void handle() { + cancel(); + } + + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java new file mode 100644 index 00000000000..5ffeaf6c961 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 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 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 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 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 java.net.http; + +/** + * A simple paired value class + */ +final class Pair { + + Pair(T first, U second) { + this.second = second; + this.first = first; + } + + final T first; + final U second; + + // Because 'pair()' is shorter than 'new Pair<>()'. + // Sometimes this difference might be very significant (especially in a + // 80-ish characters boundary). Sorry diamond operator. + static Pair pair(T first, U second) { + return new Pair<>(first, second); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java new file mode 100644 index 00000000000..e206f9204e2 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; + +/** + * Plain raw TCP connection direct to destination + */ +class PlainHttpConnection extends HttpConnection { + + protected SocketChannel chan; + private volatile boolean connected; + private boolean closed; + + class ConnectEvent extends AsyncEvent implements AsyncEvent.Blocking { + CompletableFuture cf; + + ConnectEvent(CompletableFuture cf) { + this.cf = cf; + } + + @Override + public SelectableChannel channel() { + return chan; + } + + @Override + public int interestOps() { + return SelectionKey.OP_CONNECT; + } + + @Override + public void handle() { + try { + chan.finishConnect(); + } catch (IOException e) { + cf.completeExceptionally(e); + } + connected = true; + cf.complete(null); + } + + @Override + public void abort() { + close(); + } + } + + @Override + public CompletableFuture connectAsync() { + CompletableFuture plainFuture = new CompletableFuture<>(); + try { + chan.configureBlocking(false); + chan.connect(address); + client.registerEvent(new ConnectEvent(plainFuture)); + } catch (IOException e) { + plainFuture.completeExceptionally(e); + } + return plainFuture; + } + + @Override + public void connect() throws IOException { + chan.connect(address); + connected = true; + } + + @Override + SocketChannel channel() { + return chan; + } + + PlainHttpConnection(InetSocketAddress addr, HttpClientImpl client) { + super(addr, client); + try { + this.chan = SocketChannel.open(); + int bufsize = client.getReceiveBufferSize(); + chan.setOption(StandardSocketOptions.SO_RCVBUF, bufsize); + } catch (IOException e) { + throw new InternalError(e); + } + } + + @Override + long write(ByteBuffer[] buffers, int start, int number) throws IOException { + //debugPrint("Send", buffers, start, number); + return chan.write(buffers, start, number); + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + return chan.write(buffer); + } + + @Override + public String toString() { + return "PlainHttpConnection: " + super.toString(); + } + + /** + * Close this connection + */ + @Override + synchronized void close() { + if (closed) + return; + closed = true; + try { + Log.logError("Closing: " + toString()); + //System.out.println("Closing: " + this); + chan.close(); + } catch (IOException e) {} + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + ByteBuffer buf = getBuffer(); // TODO not using length + int n = chan.read(buf); + if (n == -1) { + return null; + } + buf.flip(); + String s = "Receive (" + n + " bytes) "; + //debugPrint(s, buf); + return buf; + } + + @Override + protected int readImpl(ByteBuffer buf) throws IOException { + int mark = buf.position(); + int n = chan.read(buf); + if (n == -1) { + return -1; + } + Utils.flipToMark(buffer, mark); + String s = "Receive (" + n + " bytes) "; + //debugPrint(s, buf); + return n; + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return new ConnectionPool.CacheKey(address, null); + } + + @Override + synchronized boolean connected() { + return connected; + } + + class ReceiveResponseEvent extends AsyncEvent implements AsyncEvent.Blocking { + CompletableFuture cf; + + ReceiveResponseEvent(CompletableFuture cf) { + this.cf = cf; + } + @Override + public SelectableChannel channel() { + return chan; + } + + @Override + public void handle() { + cf.complete(null); + } + + @Override + public int interestOps() { + return SelectionKey.OP_READ; + } + + @Override + public void abort() { + close(); + } + } + + @Override + boolean isSecure() { + return false; + } + + @Override + boolean isProxied() { + return false; + } + + @Override + CompletableFuture whenReceivingResponse() { + CompletableFuture cf = new CompletableFuture<>(); + try { + client.registerEvent(new ReceiveResponseEvent(cf)); + } catch (IOException e) { + cf.completeExceptionally(e); + } + return cf; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java new file mode 100644 index 00000000000..1e1170ad184 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.net.InetSocketAddress; + +class PlainProxyConnection extends PlainHttpConnection { + + PlainProxyConnection(InetSocketAddress proxy, HttpClientImpl client) { + super(proxy, client); + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return new ConnectionPool.CacheKey(null, address); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java new file mode 100644 index 00000000000..2042baa2c4e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.security.AccessControlContext; +import java.util.concurrent.CompletableFuture; + +/** + * A plain text socket tunnel through a proxy. Uses "CONNECT" but does not + * encrypt. Used by WebSockets. Subclassed in SSLTunnelConnection for encryption. + */ +class PlainTunnelingConnection extends HttpConnection { + + final PlainHttpConnection delegate; + protected final InetSocketAddress proxyAddr; + private volatile boolean connected; + private final AccessControlContext acc; + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync() + .thenCompose((Void v) -> { + HttpRequestImpl req = new HttpRequestImpl(client, "CONNECT", address); + Exchange connectExchange = new Exchange(req, acc); + return connectExchange + .responseAsyncImpl(delegate) + .thenCompose((HttpResponse r) -> { + CompletableFuture cf = new CompletableFuture<>(); + if (r.statusCode() != 200) { + cf.completeExceptionally(new IOException("Tunnel failed")); + } else { + connected = true; + cf.complete(null); + } + return cf; + }); + }); + } + + @Override + public void connect() throws IOException, InterruptedException { + delegate.connect(); + HttpRequestImpl req = new HttpRequestImpl(client, "CONNECT", address); + Exchange connectExchange = new Exchange(req, acc); + HttpResponse r = connectExchange.responseImpl(delegate); + if (r.statusCode() != 200) { + throw new IOException("Tunnel failed"); + } + connected = true; + } + + @Override + boolean connected() { + return connected; + } + + protected PlainTunnelingConnection(InetSocketAddress addr, + InetSocketAddress proxy, + HttpClientImpl client, + AccessControlContext acc) { + super(addr, client); + this.proxyAddr = proxy; + this.acc = acc; + delegate = new PlainHttpConnection(proxy, client); + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return new ConnectionPool.CacheKey(null, proxyAddr); + } + + @Override + long write(ByteBuffer[] buffers, int start, int number) throws IOException { + return delegate.write(buffers, start, number); + } + + @Override + long write(ByteBuffer buffer) throws IOException { + return delegate.write(buffer); + } + + @Override + void close() { + delegate.close(); + connected = false; + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + return delegate.readImpl(length); + } + + @Override + CompletableFuture whenReceivingResponse() { + return delegate.whenReceivingResponse(); + } + + @Override + protected int readImpl(ByteBuffer buffer) throws IOException { + return delegate.readImpl(buffer); + } + + @Override + boolean isSecure() { + return false; + } + + @Override + boolean isProxied() { + return true; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java new file mode 100644 index 00000000000..9566eeb555c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.GatheringByteChannel; +import java.nio.channels.SelectableChannel; + +/** + * Used to implement WebSocket. Each RawChannel corresponds to + * a TCP connection (SocketChannel) but is connected to a Selector + * and an ExecutorService for invoking the send and receive callbacks + * Also includes SSL processing. + */ +class RawChannel implements ByteChannel, GatheringByteChannel { + + private final HttpClientImpl client; + private final HttpConnection connection; + private boolean closed; + + private interface RawEvent { + + /** must return the selector interest op flags OR'd. */ + int interestOps(); + + /** called when event occurs. */ + void handle(); + } + + interface BlockingEvent extends RawEvent { } + + interface NonBlockingEvent extends RawEvent { } + + RawChannel(HttpClientImpl client, HttpConnection connection) { + this.client = client; + this.connection = connection; + } + + private class RawAsyncEvent extends AsyncEvent { + + private final RawEvent re; + + RawAsyncEvent(RawEvent re) { + this.re = re; + } + + public SelectableChannel channel() { + return connection.channel(); + } + + // must return the selector interest op flags OR'd + public int interestOps() { + return re.interestOps(); + } + + // called when event occurs + public void handle() { + re.handle(); + } + + public void abort() {} + } + + private class BlockingRawAsyncEvent extends RawAsyncEvent + implements AsyncEvent.Blocking { + + BlockingRawAsyncEvent(RawEvent re) { + super(re); + } + } + + private class NonBlockingRawAsyncEvent extends RawAsyncEvent + implements AsyncEvent.NonBlocking { + + NonBlockingRawAsyncEvent(RawEvent re) { + super(re); + } + } + + /* + * Register given event whose callback will be called once only. + * (i.e. register new event for each callback) + */ + public void registerEvent(RawEvent event) throws IOException { + if (event instanceof BlockingEvent) { + client.registerEvent(new BlockingRawAsyncEvent(event)); + } else if (event instanceof NonBlockingEvent) { + client.registerEvent(new NonBlockingRawAsyncEvent(event)); + } else { + throw new InternalError(); + } + } + + @Override + public int read(ByteBuffer dst) throws IOException { + return connection.read(dst); + } + + @Override + public boolean isOpen() { + return !closed; + } + + @Override + public void close() throws IOException { + closed = true; + connection.close(); + } + + @Override + public long write(ByteBuffer[] src) throws IOException { + return connection.write(src, 0, src.length); + } + + @Override + public long write(ByteBuffer[] src, int offset, int len) + throws IOException { + return connection.write(src, offset, len); + } + + @Override + public int write(ByteBuffer src) throws IOException { + return (int) connection.write(src); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java new file mode 100644 index 00000000000..3c3be4d17c5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; + +class RedirectFilter implements HeaderFilter { + + HttpRequestImpl requestImpl; + HttpRequest request; + HttpClientImpl client; + String method; + final static int DEFAULT_MAX_REDIRECTS = 5; + URI uri; + + final static int max_redirects = Utils.getIntegerNetProperty( + "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS + ); + + @Override + public void request(HttpRequestImpl r) throws IOException { + this.request = r; + this.client = r.getClient(); + this.method = r.method(); + this.requestImpl = r; + this.uri = r.uri(); + } + + @Override + public HttpRequestImpl response(HttpResponseImpl r) throws IOException { + return handleResponse(r); + } + + /** + * checks to see if new request needed and returns it. + * Null means response is ok to return to user. + */ + private HttpRequestImpl handleResponse(HttpResponseImpl r) { + int rcode = r.statusCode(); + if (rcode == 200) { + return null; + } + if (rcode >= 300 && rcode <= 399) { + URI redir = getRedirectedURI(r.headers()); + if (canRedirect(r) && ++r.request.exchange.numberOfRedirects < max_redirects) { + //System.out.println("Redirecting to: " + redir); + return new HttpRequestImpl(redir, request, client, method, requestImpl); + } else { + //System.out.println("Redirect: giving up"); + return null; + } + } + return null; + } + + private URI getRedirectedURI(HttpHeaders headers) { + URI redirectedURI; + redirectedURI = headers.firstValue("Location") + .map((s) -> URI.create(s)) + .orElseThrow(() -> new UncheckedIOException( + new IOException("Invalid redirection"))); + + // redirect could be relative to original URL, but if not + // then redirect is used. + redirectedURI = uri.resolve(redirectedURI); + return redirectedURI; + } + + private boolean canRedirect(HttpResponse r) { + return requestImpl.followRedirectsImpl().redirect(r); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java new file mode 100644 index 00000000000..f6e8d7504d9 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * Implements chunked/fixed transfer encodings of HTTP/1.1 responses. + */ +class ResponseContent { + + final HttpResponse.BodyProcessor userProcessor; + final HttpResponse.BodyProcessor pusher; + final HttpConnection connection; + final int contentLength; + ByteBuffer buffer; + ByteBuffer lastBufferUsed; + final ResponseHeaders headers; + final Http1Response.FlowController flowController; + + ResponseContent(HttpConnection connection, + int contentLength, + ResponseHeaders h, + HttpResponse.BodyProcessor userProcessor, + Http1Response.FlowController flowController) { + this.userProcessor = userProcessor; + this.pusher = (HttpResponse.BodyProcessor)userProcessor; + this.connection = connection; + this.contentLength = contentLength; + this.headers = h; + this.flowController = flowController; + } + + static final int LF = 10; + static final int CR = 13; + static final int SP = 0x20; + static final int BUF_SIZE = 1024; + + boolean chunkedContent, chunkedContentInitialized; + + private boolean contentChunked() throws IOException { + if (chunkedContentInitialized) { + return chunkedContent; + } + if (contentLength == -1) { + String tc = headers.firstValue("Transfer-Encoding") + .orElse(""); + if (!tc.equals("")) { + if (tc.equalsIgnoreCase("chunked")) { + chunkedContent = true; + } else { + throw new IOException("invalid content"); + } + } else { + chunkedContent = false; + } + } + chunkedContentInitialized = true; + return chunkedContent; + } + + /** + * Entry point for pusher. b is an initial ByteBuffer that may + * have some data in it. When this method returns, the body + * has been fully processed. + */ + void pushBody(ByteBuffer b) throws IOException { + // TODO: check status + if (contentChunked()) { + pushBodyChunked(b); + } else { + pushBodyFixed(b); + } + } + + // reads and returns chunklen. Position of chunkbuf is first byte + // of chunk on return. chunklen includes the CR LF at end of chunk + int readChunkLen() throws IOException { + chunklen = 0; + boolean cr = false; + while (true) { + getHunk(); + int c = chunkbuf.get(); + if (cr) { + if (c == LF) { + return chunklen + 2; + } else { + throw new IOException("invalid chunk header"); + } + } + if (c == CR) { + cr = true; + } else { + int digit = toDigit(c); + chunklen = chunklen * 16 + digit; + } + } + } + + int chunklen = -1; // number of bytes in chunk (fixed) + int bytesremaining; // number of bytes in chunk left to be read incl CRLF + int bytesread; + ByteBuffer chunkbuf; // initialise + + // make sure we have at least 1 byte to look at + private void getHunk() throws IOException { + while (chunkbuf == null || !chunkbuf.hasRemaining()) { + + if (chunkbuf != null) { + connection.returnBuffer(chunkbuf); + } + chunkbuf = connection.read(); + } + } + + private void consumeBytes(int n) throws IOException { + getHunk(); + while (n > 0) { + int e = Math.min(chunkbuf.remaining(), n); + chunkbuf.position(chunkbuf.position() + e); + n -= e; + if (n > 0) + getHunk(); + } + } + + /** + * Returns a ByteBuffer containing a chunk of data or a "hunk" of data + * (a chunk of a chunk if the chunk size is larger than our ByteBuffers). + */ + ByteBuffer readChunkedBuffer() throws IOException { + if (chunklen == -1) { + // new chunk + bytesremaining = readChunkLen(); + chunklen = bytesremaining - 2; + if (chunklen == 0) { + consumeBytes(2); + return null; + } + } + + getHunk(); + bytesread = chunkbuf.remaining(); + ByteBuffer returnBuffer; + + /** + * Cases. Always at least one byte is read by getHunk() + * + * 1) one read contains exactly 1 chunk. Strip off CRLF and pass buffer on + * 2) one read contains a hunk. If at end of chunk, consume CRLF.Pass buffer up. + * 3) read contains rest of chunk and more data. Copy buffer. + */ + if (bytesread == bytesremaining) { + // common case: 1 read = 1 chunk (or final hunk of chunk) + chunkbuf.limit(chunkbuf.limit() - 2); // remove trailing CRLF + bytesremaining = 0; + returnBuffer = chunkbuf; + chunkbuf = null; + chunklen = -1; + } else if (bytesread < bytesremaining) { + // read a hunk, maybe including CR or LF or both + bytesremaining -= bytesread; + if (bytesremaining <= 2) { + // remove any trailing CR LF already read, and then read the rest + chunkbuf.limit(chunkbuf.limit() - (2 - bytesremaining)); + consumeBytes(bytesremaining); + chunklen = -1; + } + returnBuffer = chunkbuf; + chunkbuf = null; + } else { + // bytesread > bytesremaining + returnBuffer = splitChunkedBuffer(bytesremaining-2); + bytesremaining = 0; + chunklen = -1; + consumeBytes(2); + } + return returnBuffer; + } + + ByteBuffer initialBuffer; + int fixedBytesReturned; + + ByteBuffer getResidue() { + return lastBufferUsed; + } + + private void compactBuffer(ByteBuffer buf) { + buf.compact() + .flip(); + } + + /** + * Copies inbuf (numBytes from its position) to new buffer. The returned + * buffer's position is zero and limit is at end (numBytes) + */ + private ByteBuffer copyBuffer(ByteBuffer inbuf, int numBytes) { + ByteBuffer b1 = connection.getBuffer(); + assert b1.remaining() >= numBytes; + byte[] b = b1.array(); + inbuf.get(b, 0, numBytes); + b1.limit(numBytes); + return b1; + } + + /** + * Split numBytes of data out of chunkbuf from the remainder, + * copying whichever part is smaller. chunkbuf points to second part + * of buffer on return. The returned buffer is the data from position + * to position + numBytes. Both buffers positions are reset so same + * data can be re-read. + */ + private ByteBuffer splitChunkedBuffer(int numBytes) { + ByteBuffer newbuf = connection.getBuffer(); + byte[] b = newbuf.array(); + int midpoint = chunkbuf.position() + numBytes; + int remainder = chunkbuf.limit() - midpoint; + + if (numBytes < remainder) { + // copy first part of chunkbuf to new buf + chunkbuf.get(b, 0, numBytes); + newbuf.limit(numBytes); + return newbuf; + } else { + // copy remainder of chunkbuf to newbuf and make newbuf chunkbuf + chunkbuf.mark(); + chunkbuf.position(midpoint); + chunkbuf.get(b, 0, remainder); + chunkbuf.reset(); + chunkbuf.limit(midpoint); + newbuf.limit(remainder); + newbuf.position(0); + ByteBuffer tmp = chunkbuf; + chunkbuf = newbuf; + return tmp; + } + } + + private void pushBodyChunked(ByteBuffer b) throws IOException { + chunkbuf = b; + while (true) { + ByteBuffer b1 = readChunkedBuffer(); + if (b1 != null) { + if (b1.hasRemaining()) { + request(1); // wait till we can send + pusher.onResponseBodyChunk(b1); + lastBufferUsed = b1; + } + } else { + return; + } + } + } + + private int toDigit(int b) throws IOException { + if (b >= 0x30 && b <= 0x39) { + return b - 0x30; + } + if (b >= 0x41 && b <= 0x46) { + return b - 0x41 + 10; + } + if (b >= 0x61 && b <= 0x66) { + return b - 0x61 + 10; + } + throw new IOException("Invalid chunk header byte " + b); + } + + private void request(long value) throws IOException { + try { + flowController.request(value); + } catch (InterruptedException e) { + throw new IOException(e); + } + } + + private void pushBodyFixed(ByteBuffer b) throws IOException { + lastBufferUsed = b; + for (int remaining = contentLength; remaining > 0;) { + int bufsize = b.remaining(); + if (bufsize > remaining) { + // more data available than required, must copy + lastBufferUsed = b; + b = copyBuffer(b, remaining); + remaining = 0; + } else { + // pass entire buffer up to user + remaining -= bufsize; + compactBuffer(b); + } + request(1); // wait till we can send + pusher.onResponseBodyChunk(b); + if (remaining > 0) { + b = connection.read(); + if (b == null) { + throw new IOException("Error reading response"); + } + lastBufferUsed = b; + } + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java new file mode 100644 index 00000000000..b378e784c51 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Reads response headers off channel, in blocking mode. Entire header + * block is collected in a byte[]. The offset location of the start of + * each header name is recorded in an array to facilitate later searching. + * + * The location of "Content-length" is recorded explicitly. Similar approach + * could be taken for other common headers. + * + * This class is not thread-safe + */ +class ResponseHeaders implements HttpHeaders1 { + + static final int DATA_SIZE = 16 * 1024; // initial space for headers + static final int NUM_HEADERS = 50; // initial expected max number of headers + + final HttpConnection connection; + byte[] data; + int contentlen = -2; // means not initialized + ByteBuffer buffer; + + /** + * Following used for scanning the array looking for: + * - well known headers + * - end of header block + */ + int[] headerOffsets; // index into data + int numHeaders; + int count; + + ByteBuffer residue; // after headers processed, data may be here + + ResponseHeaders(HttpConnection connection, ByteBuffer buffer) { + this.connection = connection; + initOffsets(); + this.buffer = buffer; + data = new byte[DATA_SIZE]; + } + + int getContentLength() throws IOException { + if (contentlen != -2) { + return contentlen; + } + int[] search = findHeaderValue("Content-length"); + if (search[0] == -1) { + contentlen = -1; + return -1; + } + + int i = search[0]; + + while (data[i] == ' ' || data[i] == '\t') { + i++; + if (i == data.length || data[i] == CR || data[i] == LF) { + throw new IOException("Bad header"); + } + } + contentlen = 0; + int digit = data[i++] - 0x30; + while (digit >= 0 && digit <= 9) { + contentlen = contentlen * 10 + digit; + digit = data[i++] - 0x30; + } + return contentlen; + } + + void log() { + populateMap(false); + } + + void populateMap(boolean clearOffsets) { + StringBuilder sb; + + for (int i = 0; i < numHeaders; i++) { + sb = new StringBuilder(32); + int offset = headerOffsets[i]; + if (offset == -1) { + continue; + } + int j; + for (j=0; data[offset+j] != ':'; j++) { + // byte to char promotion ok for US-ASCII + sb.append((char)data[offset+j]); + } + String name = sb.toString(); + List l = getOrCreate(name); + addEntry(l, name, offset + j + 1); + // clear the offset + if (clearOffsets) + headerOffsets[i] = -1; + } + } + + void addEntry(List l, String name, int j) { + + while (data[j] == ' ' || data[j] == '\t') { + j++; + } + + int vstart = j; + // TODO: back slash ?? + + while (data[j] != CR) { + j++; + } + try { + String value = new String(data, vstart, j - vstart, "US-ASCII"); + l.add(value); + } catch (UnsupportedEncodingException e) { + // can't happen + throw new InternalError(e); + } + } + + // returns an int[2]: [0] = offset of value in data[] + // [1] = offset in headerOffsets. Both are -1 in error + + private int[] findHeaderValue(String name) { + int[] result = new int[2]; + byte[] namebytes = getBytes(name); + + outer: for (int i = 0; i < numHeaders; i++) { + int offset = headerOffsets[i]; + if (offset == -1) { + continue; + } + + for (int j=0; j populateMapEntry(String name) { + List l = getOrCreate(name); + int[] search = findHeaderValue(name); + if (search[0] != -1) { + addEntry(l, name, search[0]); + // clear the offset + headerOffsets[search[1]] = -1; + } + return l; + } + + static final Locale usLocale = Locale.US; + static final Charset ascii = StandardCharsets.US_ASCII; + + private byte[] getBytes(String name) { + return name.toLowerCase(usLocale).getBytes(ascii); + } + + /* + * We read buffers in a loop until we detect end of headers + * CRLFCRLF. Each byte received is copied into the byte[] data + * The position of the first byte of each header (after a CRLF) + * is recorded in a separate array showing the location of + * each header name. + */ + void initHeaders() throws IOException { + + inHeaderName = true; + endOfHeader = true; + + for (int numBuffers = 0; true; numBuffers++) { + + if (numBuffers > 0) { + buffer = connection.read(); + } + + if (buffer == null) { + throw new IOException("Error reading headers"); + } + + if (!buffer.hasRemaining()) { + continue; + } + + // Position set to first byte + int start = buffer.position(); + byte[] backing = buffer.array(); + int len = buffer.limit() - start; + + for (int i = 0; i < len; i++) { + byte b = backing[i + start]; + if (inHeaderName) { + b = lowerCase(b); + } + if (b == ':') { + inHeaderName = false; + } + data[count++] = b; + checkByte(b); + if (firstChar) { + recordHeaderOffset(count-1); + firstChar = false; + } + if (endOfHeader && numHeaders == 0) { + // empty headers + endOfAllHeaders = true; + } + if (endOfAllHeaders) { + int newposition = i + 1 + start; + if (newposition <= buffer.limit()) { + buffer.position(newposition); + residue = buffer; + } else { + residue = null; + } + return; + } + + if (count == data.length) { + resizeData(); + } + } + } + } + + static final int CR = 13; + static final int LF = 10; + int crlfCount = 0; + + // results of checkByte() + boolean endOfHeader; // just seen LF after CR before + boolean endOfAllHeaders; // just seen LF after CRLFCR before + boolean firstChar; // + boolean inHeaderName; // examining header name + + void checkByte(byte b) throws IOException { + if (endOfHeader && b != CR && b != LF) + firstChar = true; + endOfHeader = false; + endOfAllHeaders = false; + switch (crlfCount) { + case 0: + crlfCount = b == CR ? 1 : 0; + break; + case 1: + crlfCount = b == LF ? 2 : 0; + endOfHeader = true; + inHeaderName = true; + break; + case 2: + crlfCount = b == CR ? 3 : 0; + break; + case 3: + if (b != LF) { + throw new IOException("Bad header block termination"); + } + endOfAllHeaders = true; + break; + } + } + + byte lowerCase(byte b) { + if (b >= 0x41 && b <= 0x5A) + b = (byte)(b + 32); + return b; + } + + void resizeData() { + int oldlen = data.length; + int newlen = oldlen * 2; + byte[] newdata = new byte[newlen]; + System.arraycopy(data, 0, newdata, 0, oldlen); + data = newdata; + } + + final void initOffsets() { + headerOffsets = new int[NUM_HEADERS]; + numHeaders = 0; + } + + ByteBuffer getResidue() { + return residue; + } + + void recordHeaderOffset(int index) { + if (numHeaders >= headerOffsets.length) { + int oldlen = headerOffsets.length; + int newlen = oldlen * 2; + int[] new1 = new int[newlen]; + System.arraycopy(headerOffsets, 0, new1, 0, oldlen); + headerOffsets = new1; + } + headerOffsets[numHeaders++] = index; + } + + /** + * As entries are read from the byte[] they are placed in here + * So we always check this map first + */ + Map> headers = new HashMap<>(); + + @Override + public Optional firstValue(String name) { + List l = allValues(name); + if (l == null || l.isEmpty()) { + return Optional.ofNullable(null); + } else { + return Optional.of(l.get(0)); + } + } + + @Override + public List allValues(String name) { + name = name.toLowerCase(usLocale); + List l = headers.get(name); + if (l == null) { + l = populateMapEntry(name); + } + return Collections.unmodifiableList(l); + } + + @Override + public void makeUnmodifiable() { + } + + // Delegates map to HashMap but converts keys to lower case + + static class HeaderMap implements Map> { + Map> inner; + + HeaderMap(Map> inner) { + this.inner = inner; + } + @Override + public int size() { + return inner.size(); + } + + @Override + public boolean isEmpty() { + return inner.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + if (!(key instanceof String)) { + return false; + } + String s = ((String)key).toLowerCase(usLocale); + return inner.containsKey(s); + } + + @Override + public boolean containsValue(Object value) { + return inner.containsValue(value); + } + + @Override + public List get(Object key) { + String s = ((String)key).toLowerCase(usLocale); + return inner.get(s); + } + + @Override + public List put(String key, List value) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public List remove(Object key) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void putAll(Map> m) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void clear() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public Set keySet() { + return inner.keySet(); + } + + @Override + public Collection> values() { + return inner.values(); + } + + @Override + public Set>> entrySet() { + return inner.entrySet(); + } + } + + @Override + public Map> map() { + populateMap(true); + return new HeaderMap(headers); + } + + Map> mapInternal() { + populateMap(false); + return new HeaderMap(headers); + } + + private List getOrCreate(String name) { + List l = headers.get(name); + if (l == null) { + l = new LinkedList<>(); + headers.put(name, l); + } + return l; + } + + @Override + public Optional firstValueAsLong(String name) { + List l = allValues(name); + if (l == null) { + return Optional.ofNullable(null); + } else { + String v = l.get(0); + Long lv = Long.parseLong(v); + return Optional.of(lv); + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java new file mode 100644 index 00000000000..4b8cb3c0516 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLParameters; +import java.net.http.SSLDelegate.BufType; +import java.net.http.SSLDelegate.WrapperResult; + +/** + * An SSL connection built on a Plain TCP connection. + */ +class SSLConnection extends HttpConnection { + + PlainHttpConnection delegate; + SSLDelegate sslDelegate; + final String[] alpn; + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync() + .thenCompose((Void v) -> { + CompletableFuture cf = new CompletableFuture<>(); + try { + this.sslDelegate = new SSLDelegate(delegate.channel(), + client, + alpn); + cf.complete(null); + } catch (IOException e) { + cf.completeExceptionally(e); + } + return cf; + }); + } + + @Override + public void connect() throws IOException { + delegate.connect(); + this.sslDelegate = new SSLDelegate(delegate.channel(), client, alpn); + } + + SSLConnection(InetSocketAddress addr, HttpClientImpl client, String[] ap) { + super(addr, client); + this.alpn = ap; + delegate = new PlainHttpConnection(addr, client); + } + + @Override + SSLParameters sslParameters() { + return sslDelegate.getSSLParameters(); + } + + @Override + public String toString() { + return "SSLConnection: " + super.toString(); + } + + private static long countBytes(ByteBuffer[] buffers, int start, int length) { + long c = 0; + for (int i=0; i 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + long l = buffer.remaining(); + WrapperResult r = sslDelegate.sendData(buffer); + if (r.result.getStatus() == Status.CLOSED) { + if (l > 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + void close() { + try { + //System.err.println ("Closing: " + this); + delegate.channel().close(); // TODO: proper close + } catch (IOException ex) { + Log.logError(ex.toString()); + } + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + ByteBuffer buf = sslDelegate.allocate(BufType.PACKET, length); + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.buf; + } + + @Override + protected int readImpl(ByteBuffer buf) throws IOException { + // TODO: need to ensure that buf is big enough for application data + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.result.bytesProduced(); + } + + @Override + boolean connected() { + return delegate.connected(); + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + CompletableFuture whenReceivingResponse() { + return delegate.whenReceivingResponse(); + } + + @Override + boolean isSecure() { + return true; + } + + @Override + boolean isProxied() { + return false; + } + +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java new file mode 100644 index 00000000000..fbc0674513c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.Arrays; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSession; +import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; + +/** + * Implements the mechanics of SSL by managing an SSLEngine object. + * One of these is associated with each SSLConnection. + */ +class SSLDelegate { + + final SSLEngine engine; + final EngineWrapper wrapper; + final Lock handshaking = new ReentrantLock(); + final SSLParameters sslParameters; + final SocketChannel chan; + final HttpClientImpl client; + + // alpn[] may be null + SSLDelegate(SocketChannel chan, HttpClientImpl client, String[] alpn) + throws IOException + { + SSLContext context = client.sslContext(); + engine = context.createSSLEngine(); + engine.setUseClientMode(true); + SSLParameters sslp = client.sslParameters().orElse(null); + if (sslp == null) { + sslp = context.getDefaultSSLParameters(); + } + sslParameters = Utils.copySSLParameters(sslp); + if (alpn != null) { + sslParameters.setApplicationProtocols(alpn); + Log.logSSL("Setting application protocols: " + Arrays.toString(alpn)); + } else { + Log.logSSL("Warning no application protocols proposed!"); + } + engine.setSSLParameters(sslParameters); + wrapper = new EngineWrapper(chan, engine); + this.chan = chan; + this.client = client; + } + + SSLParameters getSSLParameters() { + return sslParameters; + } + + private static long countBytes(ByteBuffer[] buffers, int start, int number) { + long c = 0; + for (int i=0; i packet_buf_size) { + packet_buf_size = len; + } + size = packet_buf_size; + } else { + if (app_buf_size == 0) { + SSLSession sess = engine.getSession(); + app_buf_size = sess.getApplicationBufferSize(); + } + if (len > app_buf_size) { + app_buf_size = len; + } + size = app_buf_size; + } + return ByteBuffer.allocate (size); + } + } + + /* reallocates the buffer by :- + * 1. creating a new buffer double the size of the old one + * 2. putting the contents of the old buffer into the new one + * 3. set xx_buf_size to the new size if it was smaller than new size + * + * flip is set to true if the old buffer needs to be flipped + * before it is copied. + */ + private ByteBuffer realloc (ByteBuffer b, boolean flip, BufType type) { + synchronized (this) { + int nsize = 2 * b.capacity(); + ByteBuffer n = allocate (type, nsize); + if (flip) { + b.flip(); + } + n.put(b); + b = n; + } + return b; + } + + /** + * This is a thin wrapper over SSLEngine and the SocketChannel, which + * guarantees the ordering of wraps/unwraps with respect to the underlying + * channel read/writes. It handles the UNDER/OVERFLOW status codes + * It does not handle the handshaking status codes, or the CLOSED status code + * though once the engine is closed, any attempt to read/write to it + * will get an exception. The overall result is returned. + * It functions synchronously/blocking + */ + class EngineWrapper { + + SocketChannel chan; + SSLEngine engine; + Object wrapLock, unwrapLock; + ByteBuffer unwrap_src, wrap_dst; + boolean closed = false; + int u_remaining; // the number of bytes left in unwrap_src after an unwrap() + + EngineWrapper (SocketChannel chan, SSLEngine engine) throws IOException { + this.chan = chan; + this.engine = engine; + wrapLock = new Object(); + unwrapLock = new Object(); + unwrap_src = allocate(BufType.PACKET); + wrap_dst = allocate(BufType.PACKET); + } + + void close () throws IOException { + } + + WrapperResult wrapAndSend(ByteBuffer src, boolean ignoreClose) + throws IOException + { + ByteBuffer[] buffers = new ByteBuffer[1]; + buffers[0] = src; + return wrapAndSend(buffers, 0, 1, ignoreClose); + } + + /* try to wrap and send the data in src. Handles OVERFLOW. + * Might block if there is an outbound blockage or if another + * thread is calling wrap(). Also, might not send any data + * if an unwrap is needed. + */ + WrapperResult wrapAndSend(ByteBuffer[] src, + int offset, + int len, + boolean ignoreClose) + throws IOException + { + if (closed && !ignoreClose) { + throw new IOException ("Engine is closed"); + } + Status status; + WrapperResult r = new WrapperResult(); + synchronized (wrapLock) { + wrap_dst.clear(); + do { + r.result = engine.wrap (src, offset, len, wrap_dst); + status = r.result.getStatus(); + if (status == Status.BUFFER_OVERFLOW) { + wrap_dst = realloc (wrap_dst, true, BufType.PACKET); + } + } while (status == Status.BUFFER_OVERFLOW); + if (status == Status.CLOSED && !ignoreClose) { + closed = true; + return r; + } + if (r.result.bytesProduced() > 0) { + wrap_dst.flip(); + int l = wrap_dst.remaining(); + assert l == r.result.bytesProduced(); + while (l>0) { + l -= chan.write (wrap_dst); + } + } + } + return r; + } + + /* block until a complete message is available and return it + * in dst, together with the Result. dst may have been re-allocated + * so caller should check the returned value in Result + * If handshaking is in progress then, possibly no data is returned + */ + WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException { + Status status; + WrapperResult r = new WrapperResult(); + r.buf = dst; + if (closed) { + throw new IOException ("Engine is closed"); + } + boolean needData; + if (u_remaining > 0) { + unwrap_src.compact(); + unwrap_src.flip(); + needData = false; + } else { + unwrap_src.clear(); + needData = true; + } + synchronized (unwrapLock) { + int x; + do { + if (needData) { + do { + x = chan.read (unwrap_src); + } while (x == 0); + if (x == -1) { + throw new IOException ("connection closed for reading"); + } + unwrap_src.flip(); + } + r.result = engine.unwrap (unwrap_src, r.buf); + status = r.result.getStatus(); + if (status == Status.BUFFER_UNDERFLOW) { + if (unwrap_src.limit() == unwrap_src.capacity()) { + /* buffer not big enough */ + unwrap_src = realloc ( + unwrap_src, false, BufType.PACKET + ); + } else { + /* Buffer not full, just need to read more + * data off the channel. Reset pointers + * for reading off SocketChannel + */ + unwrap_src.position (unwrap_src.limit()); + unwrap_src.limit (unwrap_src.capacity()); + } + needData = true; + } else if (status == Status.BUFFER_OVERFLOW) { + r.buf = realloc (r.buf, true, BufType.APPLICATION); + needData = false; + } else if (status == Status.CLOSED) { + closed = true; + r.buf.flip(); + return r; + } + } while (status != Status.OK); + } + u_remaining = unwrap_src.remaining(); + return r; + } + } + + WrapperResult sendData (ByteBuffer src) throws IOException { + ByteBuffer[] buffers = new ByteBuffer[1]; + buffers[0] = src; + return sendData(buffers, 0, 1); + } + + /** + * send the data in the given ByteBuffer. If a handshake is needed + * then this is handled within this method. When this call returns, + * all of the given user data has been sent and any handshake has been + * completed. Caller should check if engine has been closed. + */ + WrapperResult sendData (ByteBuffer[] src, int offset, int len) throws IOException { + WrapperResult r = WrapperResult.createOK(); + while (countBytes(src, offset, len) > 0) { + r = wrapper.wrapAndSend(src, offset, len, false); + Status status = r.result.getStatus(); + if (status == Status.CLOSED) { + doClosure (); + return r; + } + HandshakeStatus hs_status = r.result.getHandshakeStatus(); + if (hs_status != HandshakeStatus.FINISHED && + hs_status != HandshakeStatus.NOT_HANDSHAKING) + { + doHandshake(hs_status); + } + } + return r; + } + + /** + * read data thru the engine into the given ByteBuffer. If the + * given buffer was not large enough, a new one is allocated + * and returned. This call handles handshaking automatically. + * Caller should check if engine has been closed. + */ + WrapperResult recvData (ByteBuffer dst) throws IOException { + /* we wait until some user data arrives */ + int mark = dst.position(); + WrapperResult r = null; + assert dst.position() == 0; + while (dst.position() == 0) { + r = wrapper.recvAndUnwrap (dst); + dst = (r.buf != dst) ? r.buf: dst; + Status status = r.result.getStatus(); + if (status == Status.CLOSED) { + doClosure (); + return r; + } + + HandshakeStatus hs_status = r.result.getHandshakeStatus(); + if (hs_status != HandshakeStatus.FINISHED && + hs_status != HandshakeStatus.NOT_HANDSHAKING) + { + doHandshake (hs_status); + } + } + Utils.flipToMark(dst, mark); + return r; + } + + /* we've received a close notify. Need to call wrap to send + * the response + */ + void doClosure () throws IOException { + try { + handshaking.lock(); + ByteBuffer tmp = allocate(BufType.APPLICATION); + WrapperResult r; + do { + tmp.clear(); + tmp.flip (); + r = wrapper.wrapAndSend(tmp, true); + } while (r.result.getStatus() != Status.CLOSED); + } finally { + handshaking.unlock(); + } + } + + /* do the (complete) handshake after acquiring the handshake lock. + * If two threads call this at the same time, then we depend + * on the wrapper methods being idempotent. eg. if wrapAndSend() + * is called with no data to send then there must be no problem + */ + @SuppressWarnings("fallthrough") + void doHandshake (HandshakeStatus hs_status) throws IOException { + boolean wasBlocking = false; + try { + wasBlocking = chan.isBlocking(); + handshaking.lock(); + chan.configureBlocking(true); + ByteBuffer tmp = allocate(BufType.APPLICATION); + while (hs_status != HandshakeStatus.FINISHED && + hs_status != HandshakeStatus.NOT_HANDSHAKING) + { + WrapperResult r = null; + switch (hs_status) { + case NEED_TASK: + Runnable task; + while ((task = engine.getDelegatedTask()) != null) { + /* run in current thread, because we are already + * running an external Executor + */ + task.run(); + } + /* fall thru - call wrap again */ + case NEED_WRAP: + tmp.clear(); + tmp.flip(); + r = wrapper.wrapAndSend(tmp, false); + break; + + case NEED_UNWRAP: + tmp.clear(); + r = wrapper.recvAndUnwrap (tmp); + if (r.buf != tmp) { + tmp = r.buf; + } + assert tmp.position() == 0; + break; + } + hs_status = r.result.getHandshakeStatus(); + } + Log.logSSL(getSessionInfo()); + if (!wasBlocking) { + chan.configureBlocking(false); + } + } finally { + handshaking.unlock(); + } + } + + String getSessionInfo() { + StringBuilder sb = new StringBuilder(); + String application = engine.getApplicationProtocol(); + SSLSession sess = engine.getSession(); + String cipher = sess.getCipherSuite(); + String protocol = sess.getProtocol(); + sb.append("Handshake complete alpn: ") + .append(application) + .append(", Cipher: ") + .append(cipher) + .append(", Protocol: ") + .append(protocol); + return sb.toString(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java new file mode 100644 index 00000000000..8ec5786a687 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.security.AccessControlContext; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLParameters; +import java.net.http.SSLDelegate.BufType; +import java.net.http.SSLDelegate.WrapperResult; + +/** + * An SSL tunnel built on a Plain (CONNECT) TCP tunnel. + */ +class SSLTunnelConnection extends HttpConnection { + + final PlainTunnelingConnection delegate; + protected SSLDelegate sslDelegate; + private volatile boolean connected; + + @Override + public void connect() throws IOException, InterruptedException { + delegate.connect(); + this.sslDelegate = new SSLDelegate(delegate.channel(), client, null); + connected = true; + } + + @Override + boolean connected() { + return connected && delegate.connected(); + } + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync() + .thenAccept((Void v) -> { + try { + // can this block? + this.sslDelegate = new SSLDelegate(delegate.channel(), + client, + null); + connected = true; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + } + + SSLTunnelConnection(InetSocketAddress addr, + HttpClientImpl client, + InetSocketAddress proxy, + AccessControlContext acc) { + super(addr, client); + delegate = new PlainTunnelingConnection(addr, proxy, client, acc); + } + + @Override + SSLParameters sslParameters() { + return sslDelegate.getSSLParameters(); + } + + @Override + public String toString() { + return "SSLTunnelConnection: " + super.toString(); + } + + private static long countBytes(ByteBuffer[] buffers, int start, int number) { + long c = 0; + for (int i=0; i 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + long l = buffer.remaining(); + WrapperResult r = sslDelegate.sendData(buffer); + if (r.result.getStatus() == Status.CLOSED) { + if (l > 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + void close() { + try { + //System.err.println ("Closing: " + this); + delegate.channel().close(); // TODO: proper close + } catch (IOException ex) { + } + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + ByteBuffer buf = sslDelegate.allocate(BufType.PACKET, length); + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.buf; + } + + @Override + protected int readImpl(ByteBuffer buf) throws IOException { + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.result.bytesProduced(); + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + CompletableFuture whenReceivingResponse() { + return delegate.whenReceivingResponse(); + } + + @Override + boolean isSecure() { + return true; + } + + @Override + boolean isProxied() { + return true; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java new file mode 100644 index 00000000000..271e81c7a68 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015, 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.function.LongConsumer; + +/** + * Http/2 Stream + */ +class Stream extends ExchangeImpl { + + void debugPrint() { + } + + @Override + @SuppressWarnings("unchecked") + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return null; + } + + Stream(HttpClientImpl client, Http2Connection connection, Exchange e) { + super(e); + } + + @Override + HttpResponseImpl getResponse() throws IOException { + return null; + } + + @Override + void sendRequest() throws IOException, InterruptedException { + } + + @Override + void sendHeadersOnly() throws IOException, InterruptedException { + } + + @Override + void sendBody() throws IOException, InterruptedException { + } + + @Override + CompletableFuture sendHeadersAsync() { + return null; + } + + @Override + CompletableFuture getResponseAsync(Void v) { + return null; + } + + @Override + CompletableFuture sendBodyAsync() { + return null; + } + + @Override + void cancel() { + } + + + @Override + CompletableFuture sendRequestAsync() { + return null; + } + + @Override + T responseBody(HttpResponse.BodyProcessor processor) throws IOException { + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java b/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java new file mode 100644 index 00000000000..87786a62a77 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +/** + * Timeout event delivered by selector thread. Executes given handler + * if the timer not cancelled first. + * + * Register with HttpClientImpl.registerTimer(TimeoutEvent) + * + * Cancel with HttpClientImpl.cancelTimer(TimeoutEvent) + */ +abstract class TimeoutEvent { + + final long timeval; + + long delta; // used when on queue + + TimeoutEvent(long timeval) { this.timeval = timeval; } + + public abstract void handle(); + + /** Returns the timevalue in milli-seconds */ + public long timevalMillis() { return timeval; } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java new file mode 100644 index 00000000000..a201a23f4bd --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +package java.net.http; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.net.NetPermission; +import java.net.URI; +import java.net.URLPermission; +import java.nio.ByteBuffer; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.net.ssl.SSLParameters; +import sun.net.NetProperties; + +/** + * Miscellaneous utilities + */ +class Utils { + + /** + * Allocated buffer size. Must never be higher than 16K. But can be lower + * if smaller allocation units preferred. HTTP/2 mandates that all + * implementations support frame payloads of at least 16K. + */ + public static final int BUFSIZE = 16 * 1024; + + /** Validates a RFC7230 token */ + static void validateToken(String token, String errormsg) { + int length = token.length(); + for (int i = 0; i < length; i++) { + int c = token.codePointAt(i); + if (c >= 0x30 && c <= 0x39 // 0 - 9 + || (c >= 0x61 && c <= 0x7a) // a - z + || (c >= 0x41 && c <= 0x5a) // A - Z + || (c >= 0x21 && c <= 0x2e && c != 0x22 && c != 0x27 && c != 0x2c) + || (c >= 0x5e && c <= 0x60) + || (c == 0x7c) || (c == 0x7e)) { + } else { + throw new IllegalArgumentException(errormsg); + } + } + } + + /** + * Return sthe security permission required for the given details. + * If method is CONNECT, then uri must be of form "scheme://host:port" + */ + static URLPermission getPermission(URI uri, + String method, + Map> headers) { + StringBuilder sb = new StringBuilder(); + + String urlstring, actionstring; + + if (method.equals("CONNECT")) { + urlstring = uri.toString(); + actionstring = "CONNECT"; + } else { + sb.append(uri.getScheme()) + .append("://") + .append(uri.getHost()) + .append(uri.getPath()); + urlstring = sb.toString(); + + sb = new StringBuilder(); + sb.append(method); + if (headers != null && !headers.isEmpty()) { + sb.append(':'); + Set keys = headers.keySet(); + boolean first = true; + for (String key : keys) { + if (!first) { + sb.append(','); + } + sb.append(key); + first = false; + } + } + actionstring = sb.toString(); + } + return new URLPermission(urlstring, actionstring); + } + + static void checkNetPermission(String target) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) + return; + NetPermission np = new NetPermission(target); + sm.checkPermission(np); + } + + static int getIntegerNetProperty(String name, int defaultValue) { + return AccessController.doPrivileged((PrivilegedAction)() -> + NetProperties.getInteger(name, defaultValue) ); + } + + static String getNetProperty(String name) { + return AccessController.doPrivileged((PrivilegedAction)() -> + NetProperties.get(name) ); + } + + static SSLParameters copySSLParameters(SSLParameters p) { + SSLParameters p1 = new SSLParameters(); + p1.setAlgorithmConstraints(p.getAlgorithmConstraints()); + p1.setCipherSuites(p.getCipherSuites()); + p1.setEnableRetransmissions(p.getEnableRetransmissions()); + p1.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm()); + p1.setMaximumPacketSize(p.getMaximumPacketSize()); + p1.setNeedClientAuth(p.getNeedClientAuth()); + p1.setProtocols(p.getProtocols().clone()); + p1.setSNIMatchers(p.getSNIMatchers()); + p1.setServerNames(p.getServerNames()); + p1.setUseCipherSuitesOrder(p.getUseCipherSuitesOrder()); + p1.setWantClientAuth(p.getWantClientAuth()); + return p1; + } + + + /** Resumes reading into the given buffer. */ + static void unflip(ByteBuffer buf) { + buf.position(buf.limit()); + buf.limit(buf.capacity()); + } + + /** + * Set limit to position, and position to mark. + * + * + * @param buffer + * @param mark + */ + static void flipToMark(ByteBuffer buffer, int mark) { + buffer.limit(buffer.position()); + buffer.position(mark); + } + + /** Compact and leave ready for reading. */ + static void compact(List buffers) { + for (ByteBuffer b : buffers) { + b.compact(); + b.flip(); + } + } + + static String stackTrace(Throwable t) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + String s = null; + try { + PrintStream p = new PrintStream(bos, true, "US-ASCII"); + t.printStackTrace(p); + s = bos.toString("US-ASCII"); + } catch (UnsupportedEncodingException ex) { + // can't happen + } + return s; + } + + /** Copies as much of src to dst as possible. */ + static void copy (ByteBuffer src, ByteBuffer dst) { + int srcLen = src.remaining(); + int dstLen = dst.remaining(); + if (srcLen > dstLen) { + int diff = srcLen - dstLen; + int limit = src.limit(); + src.limit(limit - diff); + dst.put(src); + src.limit(limit); + } else { + dst.put(src); + } + } + + static ByteBuffer copy(ByteBuffer src) { + ByteBuffer dst = ByteBuffer.allocate(src.remaining()); + dst.put(src); + dst.flip(); + return dst; + } + + static String combine(String[] s) { + StringBuilder sb = new StringBuilder(); + sb.append('['); + boolean first = true; + for (String s1 : s) { + if (!first) { + sb.append(", "); + first = false; + } + sb.append(s1); + } + sb.append(']'); + return sb.toString(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java b/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java new file mode 100644 index 00000000000..fd6d4ae2497 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ + +/** + *

      High level HTTP API

      + * This provides a high-level client interface to HTTP (versions 1.1 and 2). + * Synchronous and asynchronous (via + * {@link java.util.concurrent.CompletableFuture}) modes are provided. The main + * classes defined are: + *
        + *
      • {@link java.net.http.HttpClient}
      • + *
      • {@link java.net.http.HttpRequest}
      • + *
      • {@link java.net.http.HttpResponse}
      • + *
      + * + * @since 9 + */ +package java.net.http; diff --git a/jdk/test/com/sun/net/httpserver/FileServerHandler.java b/jdk/test/com/sun/net/httpserver/FileServerHandler.java index c27fe96e406..00ccd7d1a43 100644 --- a/jdk/test/com/sun/net/httpserver/FileServerHandler.java +++ b/jdk/test/com/sun/net/httpserver/FileServerHandler.java @@ -23,6 +23,7 @@ import java.util.*; import java.util.concurrent.*; +import java.util.logging.*; import java.io.*; import java.net.*; import java.security.*; @@ -36,6 +37,10 @@ import com.sun.net.httpserver.*; * Must be given an abs pathname to the document root. * Directory listings together with text + html files * can be served. + * + * File Server created on files sub-path + * + * Echo server created on echo sub-path */ public class FileServerHandler implements HttpHandler { @@ -44,14 +49,24 @@ public class FileServerHandler implements HttpHandler { System.out.println ("usage: java FileServerHandler rootDir port logfilename"); System.exit(1); } + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + String rootDir = args[0]; int port = Integer.parseInt (args[1]); String logfile = args[2]; - HttpServer server = HttpServer.create (new InetSocketAddress (8000), 0); + HttpServer server = HttpServer.create (new InetSocketAddress (port), 0); HttpHandler h = new FileServerHandler (rootDir); + HttpHandler h1 = new EchoHandler (); - HttpContext c = server.createContext ("/", h); + HttpContext c = server.createContext ("/files", h); c.getFilters().add (new LogFilter (new File (logfile))); + HttpContext c1 = server.createContext ("/echo", h1); + c.getFilters().add (new LogFilter (new File (logfile))); + c1.getFilters().add (new LogFilter (new File (logfile))); server.setExecutor (Executors.newCachedThreadPool()); server.start (); } @@ -72,7 +87,8 @@ public class FileServerHandler implements HttpHandler { URI uri = t.getRequestURI(); String path = uri.getPath(); - while (is.read () != -1) ; + int x = 0; + while (is.read () != -1) x++; is.close(); File f = new File (docroot, path); if (!f.exists()) { @@ -164,3 +180,61 @@ public class FileServerHandler implements HttpHandler { t.close(); } } + +class EchoHandler implements HttpHandler { + + byte[] read(InputStream is) throws IOException { + byte[] buf = new byte[1024]; + byte[] result = new byte[0]; + + while (true) { + int n = is.read(buf); + if (n > 0) { + byte[] b1 = new byte[result.length + n]; + System.arraycopy(result, 0, b1, 0, result.length); + System.arraycopy(buf, 0, b1, result.length, n); + result = b1; + } else if (n == -1) { + return result; + } + } + } + + public void handle (HttpExchange t) + throws IOException + { + InputStream is = t.getRequestBody(); + Headers map = t.getRequestHeaders(); + String fixedrequest = map.getFirst ("XFixed"); + + // return the number of bytes received (no echo) + String summary = map.getFirst ("XSummary"); + if (fixedrequest != null && summary == null) { + byte[] in = read(is); + t.sendResponseHeaders(200, in.length); + OutputStream os = t.getResponseBody(); + os.write(in); + os.close(); + is.close(); + } else { + OutputStream os = t.getResponseBody(); + byte[] buf = new byte[64 * 1024]; + t.sendResponseHeaders(200, 0); + int n, count=0;; + + while ((n = is.read(buf)) != -1) { + if (summary == null) { + os.write(buf, 0, n); + } + count += n; + } + if (summary != null) { + String s = Integer.toString(count); + os.write(s.getBytes()); + } + os.close(); + is.close(); + } + } +} + diff --git a/jdk/test/java/net/httpclient/APIErrors.java b/jdk/test/java/net/httpclient/APIErrors.java new file mode 100644 index 00000000000..845c665088a --- /dev/null +++ b/jdk/test/java/net/httpclient/APIErrors.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2015, 2016, 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 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @run main/othervm APIErrors + */ +//package javaapplication16; + +import com.sun.net.httpserver.*; +import java.io.IOException; +import java.net.*; +import java.net.http.*; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.*; +import java.util.function.Supplier; + +/** + * Does stupid things with API, to check appropriate errors/exceptions thrown + */ +public class APIErrors { + + static HttpServer s1 = null; + static ExecutorService executor = null; + static int port; + static HttpClient client; + static String httproot, fileuri, fileroot; + static List clients = new LinkedList<>(); + + public static void main(String[] args) throws Exception { + initServer(); + fileroot = System.getProperty("test.src") + "/docs"; + + client = HttpClient.create().build(); + + clients.add(HttpClient.getDefault()); + + try { + test1(); + test2(); + test3(); + } finally { + s1.stop(0); + executor.shutdownNow(); + for (HttpClient client : clients) + client.executorService().shutdownNow(); + } + } + + static void reject(Runnable r, Class extype) { + try { + r.run(); + throw new RuntimeException("Expected: " + extype); + } catch (Throwable t) { + if (!extype.isAssignableFrom(t.getClass())) { + throw new RuntimeException("Wrong exception type: " + extype + " / " + +t.getClass()); + } + } + } + + static void accept(Runnable r) { + try { + r.run(); + } catch (Throwable t) { + throw new RuntimeException("Unexpected exception: " + t); + } + } + + static void checkNonNull(Supplier r) { + if (r.get() == null) + throw new RuntimeException("Unexpected null return:"); + } + + static void assertTrue(Supplier r) { + if (r.get() == false) + throw new RuntimeException("Assertion failure:"); + } + + // HttpClient.Builder + static void test1() throws Exception { + System.out.println("Test 1"); + HttpClient.Builder cb = HttpClient.create(); + InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 5000); + reject(() -> { cb.priority(-1);}, IllegalArgumentException.class); + reject(() -> { cb.priority(500);}, IllegalArgumentException.class); + accept(() -> { cb.priority(1);}); + accept(() -> { cb.priority(255);}); + + accept(() -> {clients.add(cb.build()); clients.add(cb.build());}); + } + + static void test2() throws Exception { + System.out.println("Test 2"); + HttpClient.Builder cb = HttpClient.create(); + InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 5000); + cb.proxy(ProxySelector.of(addr)); + HttpClient c = cb.build(); + clients.add(c); + checkNonNull(()-> {return c.executorService();}); + assertTrue(()-> {return c.followRedirects() == HttpClient.Redirect.NEVER;}); + assertTrue(()-> {return !c.authenticator().isPresent();}); + } + + static URI accessibleURI() { + return URI.create(fileuri); + } + + static HttpRequest request() { + return HttpRequest.create(accessibleURI()) + .GET(); + } + + static void test3() throws Exception { + System.out.println("Test 3"); + reject(()-> { + try { + HttpRequest r1 = request(); + HttpResponse resp = r1.response(); + HttpResponse resp1 = r1.response(); + } catch (IOException |InterruptedException e) { + throw new RuntimeException(e); + } + }, IllegalStateException.class); + + reject(()-> { + try { + HttpRequest r1 = request(); + HttpResponse resp = r1.response(); + HttpResponse resp1 = r1.responseAsync().get(); + } catch (IOException |InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + }, IllegalStateException.class); + reject(()-> { + try { + HttpRequest r1 = request(); + HttpResponse resp1 = r1.responseAsync().get(); + HttpResponse resp = r1.response(); + } catch (IOException |InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + }, IllegalStateException.class); + } + + static class Auth extends java.net.Authenticator { + int count = 0; + @Override + protected PasswordAuthentication getPasswordAuthentication() { + if (count++ == 0) { + return new PasswordAuthentication("user", "passwd".toCharArray()); + } else { + return new PasswordAuthentication("user", "goober".toCharArray()); + } + } + int count() { + return count; + } + } + + public static void initServer() throws Exception { + String root = System.getProperty ("test.src")+ "/docs"; + InetSocketAddress addr = new InetSocketAddress (0); + s1 = HttpServer.create (addr, 0); + if (s1 instanceof HttpsServer) { + throw new RuntimeException ("should not be httpsserver"); + } + HttpHandler h = new FileServerHandler(root); + + HttpContext c1 = s1.createContext("/files", h); + + executor = Executors.newCachedThreadPool(); + s1.setExecutor (executor); + s1.start(); + + port = s1.getAddress().getPort(); + System.out.println("HTTP server port = " + port); + httproot = "http://127.0.0.1:" + port + "/files/"; + fileuri = httproot + "foo.txt"; + } +} diff --git a/jdk/test/java/net/httpclient/BasicAuthTest.java b/jdk/test/java/net/httpclient/BasicAuthTest.java new file mode 100644 index 00000000000..5e3fa6d3374 --- /dev/null +++ b/jdk/test/java/net/httpclient/BasicAuthTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +/** + * @test + * @bug 8087112 + * @run main/othervm BasicAuthTest + * @summary Basic Authentication Test + */ + +import com.sun.net.httpserver.BasicAuthenticator; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import static java.nio.charset.StandardCharsets.US_ASCII; + +public class BasicAuthTest { + + static volatile boolean ok; + static final String RESPONSE = "Hello world"; + static final String POST_BODY = "This is the POST body 123909090909090"; + + public static void main(String[] args) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(0), 10); + ExecutorService e = Executors.newCachedThreadPool(); + Handler h = new Handler(); + HttpContext serverContext = server.createContext("/test", h); + int port = server.getAddress().getPort(); + System.out.println("Server port = " + port); + + ClientAuth ca = new ClientAuth(); + ServerAuth sa = new ServerAuth("foo realm"); + serverContext.setAuthenticator(sa); + server.setExecutor(e); + server.start(); + HttpClient client = HttpClient.create() + .authenticator(ca) + .build(); + + try { + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/test/foo"); + HttpRequest req = client.request(uri).GET(); + + HttpResponse resp = req.response(); + ok = resp.statusCode() == 200 && + resp.body(HttpResponse.asString()).equals(RESPONSE); + + if (!ok || ca.count != 1) + throw new RuntimeException("Test failed"); + + // repeat same request, should succeed but no additional authenticator calls + + req = client.request(uri).GET(); + resp = req.response(); + ok = resp.statusCode() == 200 && + resp.body(HttpResponse.asString()).equals(RESPONSE); + + if (!ok || ca.count != 1) + throw new RuntimeException("Test failed"); + + // try a POST + + req = client.request(uri) + .body(HttpRequest.fromString(POST_BODY)) + .POST(); + resp = req.response(); + ok = resp.statusCode() == 200; + + if (!ok || ca.count != 1) + throw new RuntimeException("Test failed"); + } finally { + client.executorService().shutdownNow(); + server.stop(0); + e.shutdownNow(); + } + System.out.println("OK"); + } + + static class ServerAuth extends BasicAuthenticator { + + ServerAuth(String realm) { + super(realm); + } + + @Override + public boolean checkCredentials(String username, String password) { + if (!"user".equals(username) || !"passwd".equals(password)) { + return false; + } + return true; + } + + } + + static class ClientAuth extends java.net.Authenticator { + volatile int count = 0; + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + count++; + return new PasswordAuthentication("user", "passwd".toCharArray()); + } + } + + static class Handler implements HttpHandler { + static volatile boolean ok; + + @Override + public void handle(HttpExchange he) throws IOException { + String method = he.getRequestMethod(); + InputStream is = he.getRequestBody(); + if (method.equalsIgnoreCase("POST")) { + String requestBody = new String(is.readAllBytes(), US_ASCII); + if (!requestBody.equals(POST_BODY)) { + he.sendResponseHeaders(500, -1); + ok = false; + } else { + he.sendResponseHeaders(200, -1); + ok = true; + } + } else { // GET + he.sendResponseHeaders(200, RESPONSE.length()); + OutputStream os = he.getResponseBody(); + os.write(RESPONSE.getBytes(US_ASCII)); + os.close(); + ok = true; + } + } + + } +} diff --git a/jdk/test/java/net/httpclient/HeadersTest.java b/jdk/test/java/net/httpclient/HeadersTest.java new file mode 100644 index 00000000000..61faeaa1ec9 --- /dev/null +++ b/jdk/test/java/net/httpclient/HeadersTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, 2016, 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.net.http.HttpRequest; +import java.net.URI; + +/** + * @test + * @bug 8087112 + * @summary Basic test for headers + */ +public class HeadersTest { + + static final URI TEST_URI = URI.create("http://www.foo.com/"); + + static void bad(String name) { + HttpRequest.Builder builder = HttpRequest.create(TEST_URI); + try { + builder.header(name, "foo"); + throw new RuntimeException("Expected IAE for header:" + name); + } catch (IllegalArgumentException expected) { } + } + + static void good(String name) { + HttpRequest.Builder builder = HttpRequest.create(TEST_URI); + try { + builder.header(name, "foo"); + } catch (IllegalArgumentException e) { + throw new RuntimeException("Unexpected IAE for header:" + name); + } + } + + public static void main(String[] args) { + bad("bad:header"); + bad("Foo\n"); + good("X-Foo!"); + good("Bar~"); + good("x"); + bad(" "); + bad("Bar\r\n"); + good("Hello#world"); + good("Qwer#ert"); + } +} diff --git a/jdk/test/java/net/httpclient/HttpUtils.java b/jdk/test/java/net/httpclient/HttpUtils.java new file mode 100644 index 00000000000..206cdab362e --- /dev/null +++ b/jdk/test/java/net/httpclient/HttpUtils.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015, 2016, 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.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import static java.net.http.HttpRequest.fromByteArray; +import static java.net.http.HttpRequest.fromByteArrays; +import static java.net.http.HttpRequest.fromFile; +import static java.net.http.HttpRequest.fromInputStream; +import static java.net.http.HttpRequest.fromString; +import java.net.http.HttpResponse; +import static java.net.http.HttpResponse.asByteArray; +import static java.net.http.HttpResponse.asFile; +import static java.net.http.HttpResponse.asInputStream; +import static java.net.http.HttpResponse.asString; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +public final class HttpUtils { + + static final int DEFAULT_OFFSET = 10; + static final int DEFAULT_LENGTH = 1000; + static final String midSizedFilename = "/files/notsobigfile.txt"; + static final String smallFilename = "/files/smallfile.txt"; + static final Path midSizedFile; + static final Path smallFile; + static final String fileroot; + + public enum RequestBody { + STRING, FILE, BYTE_ARRAY, BYTE_ARRAY_OFFSET, INPUTSTREAM, STRING_WITH_CHARSET, + } + + static { + fileroot = System.getProperty("test.src") + "/docs"; + midSizedFile = Paths.get(fileroot + midSizedFilename); + smallFile = Paths.get(fileroot + smallFilename); + } + + static public String getFileContent(String path) throws IOException { + FileInputStream fis = new FileInputStream(path); + byte[] buf = new byte[2 * 1024]; + StringBuilder sb = new StringBuilder(); + int byteRead; + while ((byteRead = fis.read(buf)) != -1) { + sb.append(new String(buf, 0, byteRead, "US-ASCII")); + } + return sb.toString(); + } + + public static HttpRequest.Builder getHttpRequestBuilder(final HttpClient client, + final String requestType, + final URI uri) + throws IOException + { + HttpRequest.Builder builder; + String filename = smallFile.toFile().getAbsolutePath(); + String fileContents = HttpUtils.getFileContent(filename); + byte buf[] = fileContents.getBytes(); + switch (requestType) { + case "InputStream": + InputStream inputStream = new FileInputStream(smallFile.toFile()); + builder = client.request(uri) + .body(fromInputStream(inputStream)); + break; + case "byteArray": + builder = client.request(uri) + .body(fromByteArray(buf)); + break; + case "byteArrays": + Iterable iterable = Arrays.asList(buf); + builder = client.request(uri) + .body(fromByteArrays(iterable.iterator())); + break; + case "string": + builder = client.request(uri) + .body(fromString(fileContents)); + break; + case "byteArray_offset": + builder = client.request(uri) + .body(fromByteArray(buf, + DEFAULT_OFFSET, + DEFAULT_LENGTH)); + break; + case "file": + builder = client.request(uri) + .body(fromFile(smallFile)); + break; + case "string_charset": + builder = client.request(uri) + .body(fromString(new String(buf), + Charset.defaultCharset())); + break; + default: + builder = null; + break; + } + return builder; + } + + public static void checkResponse(final HttpResponse response, + String requestType, + final String responseType) + throws IOException + { + String filename = smallFile.toFile().getAbsolutePath(); + String fileContents = HttpUtils.getFileContent(filename); + if (requestType.equals("byteArray_offset")) { + fileContents = fileContents.substring(DEFAULT_OFFSET, + DEFAULT_OFFSET + DEFAULT_LENGTH); + } + byte buf[] = fileContents.getBytes(); + String responseBody; + switch (responseType) { + case "string": + responseBody = response.body(asString()); + if (!responseBody.equals(fileContents)) { + throw new RuntimeException(); + } + break; + case "byteArray": + byte arr[] = response.body(asByteArray()); + if (!Arrays.equals(arr, buf)) { + throw new RuntimeException(); + } + break; + case "file": + response.body(asFile(Paths.get("barf.txt"))); + Path downloaded = Paths.get("barf.txt"); + if (Files.size(downloaded) != fileContents.length()) { + throw new RuntimeException("Size mismatch"); + } + break; + case "InputStream": + InputStream is = response.body(asInputStream()); + byte arr1[] = new byte[1024]; + int byteRead; + StringBuilder sb = new StringBuilder(); + while ((byteRead = is.read(arr1)) != -1) { + sb.append(new String(arr1, 0, byteRead)); + } + if (!sb.toString().equals(fileContents)) { + throw new RuntimeException(); + } + break; + } + } +} diff --git a/jdk/test/java/net/httpclient/ImmutableHeaders.java b/jdk/test/java/net/httpclient/ImmutableHeaders.java new file mode 100644 index 00000000000..9fd6a2162cc --- /dev/null +++ b/jdk/test/java/net/httpclient/ImmutableHeaders.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015, 2016, 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 + */ + +/** + * @test + * @bug 8087112 + * @run main/othervm ImmutableHeaders + * @summary ImmutableHeaders + */ + +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.Headers; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.List; +import static java.nio.charset.StandardCharsets.US_ASCII; + +public class ImmutableHeaders { + + final static String RESPONSE = "Hello world"; + + public static void main(String[] args) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(0), 10); + ExecutorService e = Executors.newCachedThreadPool(); + Handler h = new Handler(); + HttpContext serverContext = server.createContext("/test", h); + int port = server.getAddress().getPort(); + System.out.println("Server port = " + port); + + server.setExecutor(e); + server.start(); + HttpClient client = HttpClient.create() + .build(); + + try { + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/test/foo"); + HttpRequest req = client.request(uri) + .headers("X-Foo", "bar") + .headers("X-Bar", "foo") + .GET(); + + try { + HttpHeaders hd = req.headers(); + List v = hd.allValues("X-Foo"); + if (!v.get(0).equals("bar")) + throw new RuntimeException("Test failed"); + v.add("XX"); + throw new RuntimeException("Test failed"); + } catch (UnsupportedOperationException ex) { + } + HttpResponse resp = req.response(); + try { + HttpHeaders hd = resp.headers(); + List v = hd.allValues("X-Foo-Response"); + if (!v.get(0).equals("resp")) + throw new RuntimeException("Test failed"); + v.add("XX"); + throw new RuntimeException("Test failed"); + } catch (UnsupportedOperationException ex) { + } + + } finally { + client.executorService().shutdownNow(); + server.stop(0); + e.shutdownNow(); + } + System.out.println("OK"); + } + + static class Handler implements HttpHandler { + + @Override + public void handle(HttpExchange he) throws IOException { + String method = he.getRequestMethod(); + InputStream is = he.getRequestBody(); + Headers h = he.getResponseHeaders(); + h.add("X-Foo-Response", "resp"); + he.sendResponseHeaders(200, RESPONSE.length()); + OutputStream os = he.getResponseBody(); + os.write(RESPONSE.getBytes(US_ASCII)); + os.close(); + } + + } +} diff --git a/jdk/test/java/net/httpclient/LightWeightHttpServer.java b/jdk/test/java/net/httpclient/LightWeightHttpServer.java new file mode 100644 index 00000000000..315849521a0 --- /dev/null +++ b/jdk/test/java/net/httpclient/LightWeightHttpServer.java @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2015, 2016, 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. + */ + +/** + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + */ +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.net.ssl.SSLContext; +import jdk.testlibrary.SimpleSSLContext; + +public class LightWeightHttpServer { + + static SSLContext ctx; + static HttpServer httpServer; + static HttpsServer httpsServer; + static ExecutorService executor; + static int port; + static int httpsport; + static String httproot; + static String httpsroot; + static ProxyServer proxy; + static int proxyPort; + static RedirectErrorHandler redirectErrorHandler, redirectErrorHandlerSecure; + static RedirectHandler redirectHandler, redirectHandlerSecure; + static DelayHandler delayHandler; + static final String midSizedFilename = "/files/notsobigfile.txt"; + static final String smallFilename = "/files/smallfile.txt"; + static Path midSizedFile; + static Path smallFile; + static String fileroot; + + public static void initServer() throws IOException { + + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + + String root = System.getProperty("test.src") + "/docs"; + InetSocketAddress addr = new InetSocketAddress(0); + httpServer = HttpServer.create(addr, 0); + if (httpServer instanceof HttpsServer) { + throw new RuntimeException("should not be httpsserver"); + } + httpsServer = HttpsServer.create(addr, 0); + HttpHandler h = new FileServerHandler(root); + + HttpContext c1 = httpServer.createContext("/files", h); + HttpContext c2 = httpsServer.createContext("/files", h); + HttpContext c3 = httpServer.createContext("/echo", new EchoHandler()); + redirectHandler = new RedirectHandler("/redirect"); + redirectHandlerSecure = new RedirectHandler("/redirect"); + HttpContext c4 = httpServer.createContext("/redirect", redirectHandler); + HttpContext c41 = httpsServer.createContext("/redirect", redirectHandlerSecure); + HttpContext c5 = httpsServer.createContext("/echo", new EchoHandler()); + HttpContext c6 = httpServer.createContext("/keepalive", new KeepAliveHandler()); + redirectErrorHandler = new RedirectErrorHandler("/redirecterror"); + redirectErrorHandlerSecure = new RedirectErrorHandler("/redirecterror"); + HttpContext c7 = httpServer.createContext("/redirecterror", redirectErrorHandler); + HttpContext c71 = httpsServer.createContext("/redirecterror", redirectErrorHandlerSecure); + delayHandler = new DelayHandler(); + HttpContext c8 = httpServer.createContext("/delay", delayHandler); + HttpContext c81 = httpsServer.createContext("/delay", delayHandler); + + executor = Executors.newCachedThreadPool(); + httpServer.setExecutor(executor); + httpsServer.setExecutor(executor); + ctx = new SimpleSSLContext().get(); + httpsServer.setHttpsConfigurator(new HttpsConfigurator(ctx)); + httpServer.start(); + httpsServer.start(); + + port = httpServer.getAddress().getPort(); + System.out.println("HTTP server port = " + port); + httpsport = httpsServer.getAddress().getPort(); + System.out.println("HTTPS server port = " + httpsport); + httproot = "http://127.0.0.1:" + port + "/"; + httpsroot = "https://127.0.0.1:" + httpsport + "/"; + + proxy = new ProxyServer(0, false); + proxyPort = proxy.getPort(); + System.out.println("Proxy port = " + proxyPort); + } + + public static void stop() throws IOException { + if (httpServer != null) { + httpServer.stop(0); + } + if (httpsServer != null) { + httpsServer.stop(0); + } + if (proxy != null) { + proxy.close(); + } + if (executor != null) { + executor.shutdownNow(); + } + } + + static class RedirectErrorHandler implements HttpHandler { + + String root; + volatile int count = 1; + + RedirectErrorHandler(String root) { + this.root = root; + } + + synchronized int count() { + return count; + } + + synchronized void increment() { + count++; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers map = t.getResponseHeaders(); + String redirect = root + "/foo/" + Integer.toString(count); + increment(); + map.add("Location", redirect); + t.sendResponseHeaders(301, -1); + t.close(); + } + } + + static class RedirectHandler implements HttpHandler { + + String root; + volatile int count = 0; + + RedirectHandler(String root) { + this.root = root; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers map = t.getResponseHeaders(); + + if (count++ < 1) { + map.add("Location", root + "/foo/" + count); + } else { + map.add("Location", SmokeTest.midSizedFilename); + } + t.sendResponseHeaders(301, -1); + t.close(); + } + + int count() { + return count; + } + + void reset() { + count = 0; + } + } + + static class KeepAliveHandler implements HttpHandler { + + volatile int counter = 0; + HashSet portSet = new HashSet<>(); + volatile int[] ports = new int[4]; + + void sleep(int n) { + try { + Thread.sleep(n); + } catch (InterruptedException e) { + } + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + int remotePort = t.getRemoteAddress().getPort(); + String result = "OK"; + + int n = counter++; + /// First test + if (n < 4) { + ports[n] = remotePort; + } + if (n == 3) { + // check all values in ports[] are the same + if (ports[0] != ports[1] || ports[2] != ports[3] + || ports[0] != ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + // Second test + if (n >= 4 && n < 8) { + // delay to ensure ports are different + sleep(500); + ports[n - 4] = remotePort; + } + if (n == 7) { + // should be all different + if (ports[0] == ports[1] || ports[2] == ports[3] + || ports[0] == ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + System.out.printf("Ports: %d, %d, %d, %d\n", + ports[0], ports[1], ports[2], ports[3]); + } + // setup for third test + for (int i = 0; i < 4; i++) { + portSet.add(ports[i]); + } + } + // Third test + if (n > 7) { + // just check that port is one of the ones in portSet + if (!portSet.contains(remotePort)) { + System.out.println("UNEXPECTED REMOTE PORT " + remotePort); + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + byte[] buf = new byte[2048]; + + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + t.sendResponseHeaders(200, result.length()); + OutputStream o = t.getResponseBody(); + o.write(result.getBytes("US-ASCII")); + t.close(); + } + } + + static class DelayHandler implements HttpHandler { + + CyclicBarrier bar1 = new CyclicBarrier(2); + CyclicBarrier bar2 = new CyclicBarrier(2); + CyclicBarrier bar3 = new CyclicBarrier(2); + + CyclicBarrier barrier1() { + return bar1; + } + + CyclicBarrier barrier2() { + return bar2; + } + + @Override + public synchronized void handle(HttpExchange he) throws IOException { + byte[] buf = Util.readAll(he.getRequestBody()); + try { + bar1.await(); + bar2.await(); + } catch (InterruptedException | BrokenBarrierException e) { + } + he.sendResponseHeaders(200, -1); // will probably fail + he.close(); + } + } +} diff --git a/jdk/test/java/net/httpclient/ManyRequests.java b/jdk/test/java/net/httpclient/ManyRequests.java new file mode 100644 index 00000000000..10081f5def7 --- /dev/null +++ b/jdk/test/java/net/httpclient/ManyRequests.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2015, 2016, 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 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @run main/othervm ManyRequests + * @summary Send a large number of requests asynchronously + */ + +//package javaapplication16; + +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Random; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLContext; +import jdk.testlibrary.SimpleSSLContext; + +public class ManyRequests { + + public static void main(String[] args) throws Exception { + SSLContext ctx = new SimpleSSLContext().get(); + + InetSocketAddress addr = new InetSocketAddress(0); + HttpsServer server = HttpsServer.create(addr, 0); + server.setHttpsConfigurator(new HttpsConfigurator(ctx)); + + HttpClient client = HttpClient.create() + .sslContext(ctx) + .build(); + try { + test(server, client); + System.out.println("OK"); + } finally { + server.stop(0); + client.executorService().shutdownNow(); + } + } + + static final int REQUESTS = 1000; + + static void test(HttpsServer server, HttpClient client) throws Exception { + int port = server.getAddress().getPort(); + URI uri = new URI("https://127.0.0.1:" + port + "/foo/x"); + server.createContext("/foo", new EchoHandler()); + server.start(); + + RequestLimiter limiter = new RequestLimiter(40); + Random rand = new Random(); + CompletableFuture[] results = new CompletableFuture[REQUESTS]; + HashMap bodies = new HashMap<>(); + + for (int i=0; i r.responseAsync()) + .thenCompose((resp) -> { + limiter.requestComplete(); + if (resp.statusCode() != 200) { + resp.bodyAsync(HttpResponse.ignoreBody()); + String s = "Expected 200, got: " + resp.statusCode(); + return completedWithIOException(s); + } + return resp.bodyAsync(HttpResponse.asByteArray()) + .thenApply((b) -> new Pair<>(resp, b)); + }) + .thenAccept((pair) -> { + HttpRequest request = pair.t.request(); + byte[] requestBody = bodies.get(request); + check(Arrays.equals(requestBody, pair.u), + "bodies not equal"); + + }); + } + // wait for them all to complete and throw exception in case of error + CompletableFuture.allOf(results).join(); + } + + static CompletableFuture completedWithIOException(String message) { + CompletableFuture cf = new CompletableFuture<>(); + cf.completeExceptionally(new IOException(message)); + return cf; + } + + static final class Pair { + Pair(T t, U u) { + this.t = t; this.u = u; + } + T t; + U u; + } + + /** + * A simple limiter for controlling the number of requests to be run in + * parallel whenOkToSend() is called which returns a CF that allows + * each individual request to proceed, or block temporarily (blocking occurs + * on the waiters list here. As each request actually completes + * requestComplete() is called to notify this object, and allow some + * requests to continue. + */ + static class RequestLimiter { + + static final CompletableFuture COMPLETED_FUTURE = + CompletableFuture.completedFuture(null); + + final int maxnumber; + final LinkedList> waiters; + int number; + boolean blocked; + + RequestLimiter(int maximum) { + waiters = new LinkedList<>(); + maxnumber = maximum; + } + + synchronized void requestComplete() { + number--; + // don't unblock until number of requests has halved. + if ((blocked && number <= maxnumber / 2) || + (!blocked && waiters.size() > 0)) { + int toRelease = Math.min(maxnumber - number, waiters.size()); + for (int i=0; i f = waiters.remove(); + number ++; + f.complete(null); + } + blocked = number >= maxnumber; + } + } + + synchronized CompletableFuture whenOkToSend() { + if (blocked || number + 1 >= maxnumber) { + blocked = true; + CompletableFuture r = new CompletableFuture<>(); + waiters.add(r); + return r; + } else { + number++; + return COMPLETED_FUTURE; + } + } + } + + static void check(boolean cond, Object... msg) { + if (cond) + return; + StringBuilder sb = new StringBuilder(); + for (Object o : msg) + sb.append(o); + throw new RuntimeException(sb.toString()); + } +} diff --git a/jdk/test/java/net/httpclient/ProxyServer.java b/jdk/test/java/net/httpclient/ProxyServer.java new file mode 100644 index 00000000000..4da9b5e1c55 --- /dev/null +++ b/jdk/test/java/net/httpclient/ProxyServer.java @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2015, 2016, 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.net.*; +import java.io.*; +import java.util.*; +import java.security.*; + +/** + * A minimal proxy server that supports CONNECT tunneling. It does not do + * any header transformations. In future this could be added. + * Two threads are created per client connection. So, it's not + * intended for large numbers of parallel connections. + */ +public class ProxyServer extends Thread implements Closeable { + + ServerSocket listener; + int port; + volatile boolean debug; + + /** + * Create proxy on port (zero means don't care). Call getPort() + * to get the assigned port. + */ + public ProxyServer(Integer port) throws IOException { + this(port, false); + } + + public ProxyServer(Integer port, Boolean debug) throws IOException { + this.debug = debug; + listener = new ServerSocket(port); + this.port = listener.getLocalPort(); + setName("ProxyListener"); + setDaemon(true); + connections = new LinkedList<>(); + start(); + } + + public ProxyServer(String s) { } + + /** + * Returns the port number this proxy is listening on + */ + public int getPort() { + return port; + } + + /** + * Shuts down the proxy, probably aborting any connections + * currently open + */ + public void close() throws IOException { + if (debug) System.out.println("Proxy: closing"); + done = true; + listener.close(); + for (Connection c : connections) { + if (c.running()) { + c.close(); + } + } + } + + List connections; + + volatile boolean done; + + public void run() { + if (System.getSecurityManager() == null) { + execute(); + } else { + // so calling domain does not need to have socket permission + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + execute(); + return null; + } + }); + } + } + + public void execute() { + try { + while(!done) { + Socket s = listener.accept(); + if (debug) + System.out.println("Client: " + s); + Connection c = new Connection(s); + connections.add(c); + } + } catch(Throwable e) { + if (debug && !done) { + System.out.println("Fatal error: Listener: " + e); + e.printStackTrace(); + } + } + } + + /** + * Transparently forward everything, once we know what the destination is + */ + class Connection { + + Socket clientSocket, serverSocket; + Thread out, in; + volatile InputStream clientIn, serverIn; + volatile OutputStream clientOut, serverOut; + + boolean forwarding = false; + + final static int CR = 13; + final static int LF = 10; + + Connection(Socket s) throws IOException { + this.clientSocket= s; + this.clientIn = new BufferedInputStream(s.getInputStream()); + this.clientOut = s.getOutputStream(); + init(); + } + + byte[] readHeaders(InputStream is) throws IOException { + byte[] outbuffer = new byte[8000]; + int crlfcount = 0; + int bytecount = 0; + int c; + while ((c=is.read()) != -1 && bytecount < outbuffer.length) { + outbuffer[bytecount++] = (byte)c; + if (debug) System.out.write(c); + // were looking for CRLFCRLF sequence + if (c == CR || c == LF) { + switch(crlfcount) { + case 0: + if (c == CR) crlfcount ++; + break; + case 1: + if (c == LF) crlfcount ++; + break; + case 2: + if (c == CR) crlfcount ++; + break; + case 3: + if (c == LF) crlfcount ++; + break; + } + } else { + crlfcount = 0; + } + if (crlfcount == 4) { + break; + } + } + byte[] ret = new byte[bytecount]; + System.arraycopy(outbuffer, 0, ret, 0, bytecount); + return ret; + } + + boolean running() { + return out.isAlive() || in.isAlive(); + } + + public void close() throws IOException { + if (debug) System.out.println("Closing connection (proxy)"); + if (serverSocket != null) serverSocket.close(); + if (clientSocket != null) clientSocket.close(); + } + + int findCRLF(byte[] b) { + for (int i=0; i=0) { + buf[i--] = (byte)cmdLine.charAt(x--); + } + i++; + + commonInit(dest, 80); + serverOut.write(buf, i, buf.length-i); + proxyCommon(); + + } catch (URISyntaxException e) { + throw new IOException(e); + } + } + + void commonInit(String dest, int defaultPort) throws IOException { + int port; + String[] hostport = dest.split(":"); + if (hostport.length == 1) { + port = defaultPort; + } else { + port = Integer.parseInt(hostport[1]); + } + if (debug) System.out.printf("Server: (%s/%d)\n", hostport[0], port); + serverSocket = new Socket(hostport[0], port); + serverOut = serverSocket.getOutputStream(); + + serverIn = new BufferedInputStream(serverSocket.getInputStream()); + } + + void proxyCommon() throws IOException { + out = new Thread(() -> { + try { + byte[] bb = new byte[8000]; + int n; + while ((n = clientIn.read(bb)) != -1) { + serverOut.write(bb, 0, n); + } + serverSocket.close(); + clientSocket.close(); + } catch (IOException e) { + if (debug) { + System.out.println (e); + } + } + }); + in = new Thread(() -> { + try { + byte[] bb = new byte[8000]; + int n; + while ((n = serverIn.read(bb)) != -1) { + clientOut.write(bb, 0, n); + } + serverSocket.close(); + clientSocket.close(); + } catch (IOException e) { + if (debug) { + System.out.println(e); + e.printStackTrace(); + } + } + }); + out.setName("Proxy-outbound"); + out.setDaemon(true); + in.setDaemon(true); + in.setName("Proxy-inbound"); + out.start(); + in.start(); + } + + void doTunnel(String dest) throws IOException { + commonInit(dest, 443); + clientOut.write("HTTP/1.1 200 OK\r\n\r\n".getBytes()); + proxyCommon(); + } + } + + public static void main(String[] args) throws Exception { + int port = Integer.parseInt(args[0]); + boolean debug = args.length > 1 && args[1].equals("-debug"); + System.out.println("Debugging : " + debug); + ProxyServer ps = new ProxyServer(port, debug); + System.out.println("Proxy server listening on port " + ps.getPort()); + while (true) { + Thread.sleep(5000); + } + } +} diff --git a/jdk/test/java/net/httpclient/QuickResponses.java b/jdk/test/java/net/httpclient/QuickResponses.java new file mode 100644 index 00000000000..5de1f687552 --- /dev/null +++ b/jdk/test/java/net/httpclient/QuickResponses.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, 2016, 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.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +/** + * @test + * @bug 8087112 + * @build Server + * @run main/othervm -Djava.net.HttpClient.log=all QuickResponses + */ + +/** + * Tests the buffering of data on connections across multiple + * responses + */ +public class QuickResponses { + + static Server server; + + static String response(String body) { + return "HTTP/1.1 200 OK\r\nContent-length: " + Integer.toString(body.length()) + + "\r\n\r\n" + body; + } + + static final String responses[] = { + "Lorem ipsum", + "dolor sit amet", + "consectetur adipiscing elit, sed do eiusmod tempor", + "quis nostrud exercitation ullamco", + "laboris nisi", + "ut", + "aliquip ex ea commodo consequat." + + "Duis aute irure dolor in reprehenderit in voluptate velit esse" + + "cillum dolore eu fugiat nulla pariatur.", + "Excepteur sint occaecat cupidatat non proident." + }; + + static String entireResponse() { + String s = ""; + for (String r : responses) { + s += response(r); + } + return s; + } + + public static void main(String[] args) throws Exception { + server = new Server(0); + URI uri = new URI(server.getURL()); + + HttpRequest request = HttpRequest.create(uri) + .GET(); + + CompletableFuture cf1 = request.responseAsync(); + Server.Connection s1 = server.activity(); + s1.send(entireResponse()); + + + HttpResponse r = cf1.join(); + if (r.statusCode()!= 200 || !r.body(HttpResponse.asString()).equals(responses[0])) + throw new RuntimeException("Failed on first response"); + + //now get the same identical response, synchronously to ensure same connection + int remaining = responses.length - 1; + + for (int i=0; i sockets; + AtomicInteger counter = new AtomicInteger(0); + + // waits up to 20 seconds for something to happen + // dont use this unless certain activity coming. + public Connection activity() { + for (int i = 0; i < 80 * 100; i++) { + for (Connection c : sockets) { + if (c.poll()) { + return c; + } + } + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + } + return null; + } + + // clears all current connections on Server. + public void reset() { + for (Connection c : sockets) { + c.close(); + } + } + + /** + * Reads data into an ArrayBlockingQueue where each String + * is a line of input, that was terminated by CRLF (not included) + */ + class Connection extends Thread { + Connection(Socket s) throws IOException { + this.socket = s; + id = counter.incrementAndGet(); + is = s.getInputStream(); + os = s.getOutputStream(); + incoming = new ArrayBlockingQueue<>(100); + setName("Server-Connection"); + setDaemon(true); + start(); + } + final Socket socket; + final int id; + final InputStream is; + final OutputStream os; + final ArrayBlockingQueue incoming; + + final static String CRLF = "\r\n"; + + // sentinel indicating connection closed + final static String CLOSED = "C.L.O.S.E.D"; + volatile boolean closed = false; + + @Override + public void run() { + byte[] buf = new byte[256]; + String s = ""; + try { + while (true) { + int n = is.read(buf); + if (n == -1) { + cleanup(); + return; + } + String s0 = new String(buf, 0, n, StandardCharsets.ISO_8859_1); + s = s + s0; + int i; + while ((i=s.indexOf(CRLF)) != -1) { + String s1 = s.substring(0, i+2); + incoming.put(s1); + if (i+2 == s.length()) { + s = ""; + break; + } + s = s.substring(i+2); + } + } + } catch (IOException |InterruptedException e1) { + cleanup(); + } catch (Throwable t) { + System.out.println("X: " + t); + cleanup(); + } + } + + @Override + public String toString() { + return "Server.Connection: " + socket.toString(); + } + + public void sendHttpResponse(int code, String body, String... headers) + throws IOException + { + String r1 = "HTTP/1.1 " + Integer.toString(code) + " status" + CRLF; + for (int i=0; i()); + setName("Test-Server"); + setDaemon(true); + start(); + } + + Server() throws IOException { + this(0); + } + + int port() { + return ss.getLocalPort(); + } + + public String getURL() { + return "http://127.0.0.1:" + port() + "/foo/"; + } + + public void close() { + try { + ss.close(); + } catch (IOException e) { + } + for (Connection c : sockets) { + c.close(); + } + } + + @Override + public void run() { + while (true) { + try { + Socket s = ss.accept(); + Connection c = new Connection(s); + sockets.add(c); + } catch (IOException e) { + } + } + } + +} diff --git a/jdk/test/java/net/httpclient/SmokeTest.java b/jdk/test/java/net/httpclient/SmokeTest.java new file mode 100644 index 00000000000..ec516623179 --- /dev/null +++ b/jdk/test/java/net/httpclient/SmokeTest.java @@ -0,0 +1,949 @@ +/* + * Copyright (c) 2015, 2016, 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 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @run main/othervm SmokeTest + */ + +//package javaapplication16; + +import com.sun.net.httpserver.*; +import java.net.*; +import java.net.http.*; +import java.io.*; +import java.util.concurrent.*; +import javax.net.ssl.*; +import java.nio.file.*; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import jdk.testlibrary.SimpleSSLContext; +import static java.net.http.HttpRequest.*; +import static java.net.http.HttpResponse.*; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * * Basic smoke test for Http/1.1 client + * - basic request response + * - request body POST + * - response body GET + * - redirect + * - chunked request/response + * - SSL + * - proxies + * - 100 continue + * - check keep alive appears to be working + * - cancel of long request + * + * Uses a FileServerHandler serving a couple of known files + * in docs directory. + */ +public class SmokeTest { + static SSLContext ctx; + static HttpServer s1 ; + static HttpsServer s2; + static ExecutorService executor; + static int port; + static int httpsport; + static String httproot; + static String httpsroot; + static HttpClient client; + static ProxyServer proxy; + static int proxyPort; + static RedirectErrorHandler redirectErrorHandler, redirectErrorHandlerSecure; + static RedirectHandler redirectHandler, redirectHandlerSecure; + static DelayHandler delayHandler; + final static String midSizedFilename = "/files/notsobigfile.txt"; + final static String smallFilename = "/files/smallfile.txt"; + static Path midSizedFile; + static Path smallFile; + static String fileroot; + + static String getFileContent(String path) throws IOException { + FileInputStream fis = new FileInputStream(path); + byte[] buf = new byte[2000]; + StringBuilder sb = new StringBuilder(); + int n; + while ((n=fis.read(buf)) != -1) { + sb.append(new String(buf, 0, n, "US-ASCII")); + } + return sb.toString(); + } + + public static void main(String[] args) throws Exception { + initServer(); + fileroot = System.getProperty ("test.src", ".")+ "/docs"; + midSizedFile = Paths.get(fileroot + midSizedFilename); + smallFile = Paths.get(fileroot + smallFilename); + + client = HttpClient.create() + .sslContext(ctx) + .followRedirects(HttpClient.Redirect.ALWAYS) + .executorService(Executors.newCachedThreadPool()) + .build(); + + try { + test1(httproot + "files/foo.txt", true); + + test1(httproot + "files/foo.txt", false); + test1(httpsroot + "files/foo.txt", true); + test1(httpsroot + "files/foo.txt", false); + test2(httproot + "echo/foo", "This is a short test"); + test2(httpsroot + "echo/foo", "This is a short test"); + + test3(httproot + "redirect/foo.txt"); + test3(httpsroot + "redirect/foo.txt"); + test4(httproot + "files/foo.txt"); + test4(httpsroot + "files/foo.txt"); + test5(httproot + "echo/foo", true); + test5(httpsroot + "echo/foo", true); + test5(httproot + "echo/foo", false); + test5(httpsroot + "echo/foo", false); + + test6(httproot + "echo/foo", true); + test6(httpsroot + "echo/foo", true); + test6(httproot + "echo/foo", false); + test6(httpsroot + "echo/foo", false); + + test7(httproot + "keepalive/foo"); + + test8(httproot + "files/foo.txt", true); + test8(httproot + "files/foo.txt", false); + test8(httpsroot + "files/foo.txt", true); + test8(httpsroot + "files/foo.txt", false); + // disabled test9(); + + test10(httproot + "redirecterror/foo.txt"); + + test10(httpsroot + "redirecterror/foo.txt"); + + test11(httproot + "echo/foo"); + test11(httpsroot + "echo/foo"); + //test12(httproot + "delay/foo", delayHandler); + + } finally { + s1.stop(0); + s2.stop(0); + proxy.close(); + executor.shutdownNow(); + client.executorService().shutdownNow(); + } + } + + static class Auth extends java.net.Authenticator { + volatile int count = 0; + @Override + protected PasswordAuthentication getPasswordAuthentication() { + if (count++ == 0) { + return new PasswordAuthentication("user", "passwd".toCharArray()); + } else { + return new PasswordAuthentication("user", "goober".toCharArray()); + } + } + int count() { + return count; + } + } + + // Basic test + static void test1(String target, boolean fixedLen) throws Exception { + System.out.print("test1: " + target); + URI uri = new URI(target); + + HttpRequest.Builder builder = client.request(uri) + .body(noBody()); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + String body = response.body(asString()); + if (!body.equals("This is foo.txt\r\n")) { + throw new RuntimeException(); + } + + // repeat async + response = builder.GET().responseAsync().join(); + + body = response.body(asString()); + if (!body.equals("This is foo.txt\r\n")) { + throw new RuntimeException(); + } + System.out.println(" OK"); + } + + // POST use echo to check reply + static void test2(String s, String body) throws Exception { + System.out.print("test2: " + s); + URI uri = new URI(s); + + HttpResponse response = client.request(uri) + .body(fromString(body)) + .POST() + .response(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } + String reply = response.body(asString()); + if (!reply.equals(body)) { + throw new RuntimeException( + "Body mismatch: expected [" + body + "], got [" + reply + "]"); + } + System.out.println(" OK"); + } + + // Redirect + static void test3(String s) throws Exception { + System.out.print("test3: " + s); + URI uri = new URI(s); + RedirectHandler handler = uri.getScheme().equals("https") + ? redirectHandlerSecure : redirectHandler; + + HttpResponse response = client.request(uri) + .body(noBody()) + .GET() + .response(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } else { + response.body(HttpResponse.asFile(Paths.get("redir1.txt"))); + } + + Path downloaded = Paths.get("redir1.txt"); + if (Files.size(downloaded) != Files.size(midSizedFile)) { + throw new RuntimeException("Size mismatch"); + } + + System.out.printf(" (count: %d) ", handler.count()); + // repeat with async api + + handler.reset(); + + response = client.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .join(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } else { + response.body(HttpResponse.asFile(Paths.get("redir2.txt"))); + } + + downloaded = Paths.get("redir2.txt"); + if (Files.size(downloaded) != Files.size(midSizedFile)) { + throw new RuntimeException("Size mismatch 2"); + } + System.out.printf(" (count: %d) ", handler.count()); + System.out.println(" OK"); + } + + // Proxies + static void test4(String s) throws Exception { + System.out.print("test4: " + s); + URI uri = new URI(s); + InetSocketAddress proxyAddr = new InetSocketAddress("127.0.0.1", proxyPort); + String filename = fileroot + uri.getPath(); + + HttpClient cl = HttpClient.create() + .proxy(ProxySelector.of(proxyAddr)) + .sslContext(ctx) + .build(); + + CompletableFuture fut = cl.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .thenCompose((HttpResponse response) -> + response.bodyAsync(asString()) + ); + + String body = fut.get(5, TimeUnit.HOURS); + + String fc = getFileContent(filename); + + if (!body.equals(fc)) { + throw new RuntimeException( + "Body mismatch: expected [" + body + "], got [" + fc + "]"); + } + cl.executorService().shutdownNow(); + System.out.println(" OK"); + } + + // 100 Continue: use echo target + static void test5(String target, boolean fixedLen) throws Exception { + System.out.print("test5: " + target); + URI uri = new URI(target); + String requestBody = generateString(12 * 1024 + 13); + + HttpRequest.Builder builder = client.request(uri) + .expectContinue(true) + .body(fromString(requestBody)); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + String body = response.body(asString()); + + if (!body.equals(requestBody)) { + throw new RuntimeException( + "Body mismatch: expected [" + body + "], got [" + body + "]"); + } + System.out.println(" OK"); + } + + // use echo + static void test6(String target, boolean fixedLen) throws Exception { + System.out.print("test6: " + target); + URI uri = new URI(target); + String requestBody = generateString(12 * 1024 + 3); + + HttpRequest.Builder builder = client.request(uri) + .body(noBody()); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } + + String responseBody = response.body(asString()); + + if (responseBody.equals(requestBody)) { + throw new RuntimeException( + "Body mismatch: expected [" + requestBody + "], got [" + responseBody + "]"); + } + System.out.println(" OK"); + } + + @SuppressWarnings("rawtypes") + static void test7(String target) throws Exception { + System.out.print("test7: " + target); + + // First test + URI uri = new URI(target); + for (int i=0; i<4; i++) { + HttpResponse r = client.request(uri) + .body(noBody()) + .GET() + .response(); + String body = r.body(asString()); + if (!body.equals("OK")) { + throw new RuntimeException("Expected OK, got: " + body); + } + } + + // Second test: 4 x parallel + List> futures = new LinkedList<>(); + for (int i=0; i<4; i++) { + futures.add(client.request(uri) + .body(noBody()) + .GET() + .responseAsync()); + } + // all sent? + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .join(); + + List> futureBodies = new LinkedList<>(); + for (int i=0; i<4; i++) { + futureBodies.add(futures.get(i) + .join() + .bodyAsync(asString())); + } + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .join(); + + for (CompletableFuture future : futureBodies) { + String body = future.get(); + if (!body.equals("OK")) { + throw new RuntimeException("Expected OK, got: " + body); + } + } + + // Third test: Multiple of 4 parallel requests + BlockingQueue q = new LinkedBlockingQueue<>(); + for (int i=0; i<4; i++) { + client.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .thenApply((HttpResponse resp) -> { + String body = resp.body(asString()); + putQ(q, body); + return body; + }); + } + // we've sent four requests. Now, just send another request + // as each response is received. The idea is to ensure that + // only four sockets ever get used. + + for (int i=0; i<100; i++) { + // block until response received + String body = takeQ(q); + if (!body.equals("OK")) { + throw new RuntimeException(body); + } + client.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .thenApply((HttpResponse resp) -> { + String body1 = resp.body(asString()); + putQ(q, body1); + return body1; + }); + } + // should be four left + for (int i=0; i<4; i++) { + takeQ(q); + } + System.out.println(" OK"); + } + + static String takeQ(BlockingQueue q) { + String r = null; + try { + r = q.take(); + } catch (InterruptedException e) {} + + return r; + } + + static void putQ(BlockingQueue q, String o) { + try { + q.put(o); + } catch (InterruptedException e) { + // can't happen + } + } + + static void test8(String target, boolean fixedLen) throws Exception { + System.out.print("test8: " + target); + URI uri = new URI(target); + + HttpRequest.Builder builder = client.request(uri) + .body(noBody()); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + StringBuilder sb = new StringBuilder(); + + InputStream is = response.body(asInputStream()); + int c; + byte[] buf = new byte[2048]; + while ((c = is.read(buf)) != -1) { + for (int i=0; i cf = request.responseAsync(); + request.cancel(); + h.barrier2().await(); + try { + HttpResponse r = cf.get(); + throw new RuntimeException("failed 2"); + } catch (Exception e) { + } + System.out.println(" OK"); + } +*/ + static void delay(int seconds) { + try { + Thread.sleep(seconds * 1000); + } catch (InterruptedException e) { + } + } +/* + // test won't work until sending fully decoupled from receiving in impl + static void test9() throws Exception { + System.out.print("test9: "); + UploadServer up = new UploadServer(1000 * 1000); + int size = up.size(); + String u = "http://127.0.0.1:" + up.port() + "/"; + URI uri = new URI(u); + + HttpRequest request = client + .request(uri) + .body(new HttpRequestBodyProcessor() { + @Override + public ByteBuffer onRequestBodyChunk(ByteBuffer b) throws IOException { + // slow things down + delay(1); + b.position(b.limit()); // fill it + return b; + } + @Override + public long onRequestStart(HttpRequest req) throws IOException { + return size; + } + }) + .PUT(); + + CompletableFuture cf1 = request.sendAsync(); + CompletableFuture cf = request.responseAsync(); + + HttpResponse resp = cf.get(1, TimeUnit.MINUTES); + if (resp.statusCode() != 201) { + throw new RuntimeException("failed: wrong response code"); + } + delay(2); // allow some data to be sent + request.cancel(); + delay(1); + if (up.failed()) { + throw new RuntimeException("failed to cancel request"); + } + System.out.println(" OK"); + } + */ + // Redirect loop: return an error after a certain number of redirects + static void test10(String s) throws Exception { + System.out.print("test10: " + s); + URI uri = new URI(s); + RedirectErrorHandler handler = uri.getScheme().equals("https") + ? redirectErrorHandlerSecure : redirectErrorHandler; + + CompletableFuture cf = client.request(uri) + .body(noBody()) + .GET() + .responseAsync(); + + try { + HttpResponse response = cf.join(); + throw new RuntimeException("Exepected Completion Exception"); + } catch (CompletionException e) { + //System.out.println(e); + } + + System.out.printf(" (Calls %d) ", handler.count()); + System.out.println(" OK"); + } + + static final int NUM = 50; + + static Random random = new Random(); + static final String alphabet = "ABCDEFGHIJKLMNOPQRST"; + + static char randomChar() { + return alphabet.charAt(random.nextInt(alphabet.length())); + } + + static String generateString(int length) { + StringBuilder sb = new StringBuilder(length); + for (int i=0; i= size; + } finally { + try { + ss.close(); + if (s != null) + s.close(); + } catch (IOException e) {} + } + } + } +} + +class RedirectHandler implements HttpHandler { + String root; + volatile int count = 0; + + RedirectHandler(String root) { + this.root = root; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException + { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers responseHeaders = t.getResponseHeaders(); + + if (count++ < 1) { + responseHeaders.add("Location", root + "/foo/" + count); + } else { + responseHeaders.add("Location", SmokeTest.midSizedFilename); + } + t.sendResponseHeaders(301, -1); + t.close(); + } + + int count() { + return count; + } + + void reset() { + count = 0; + } +} + +class RedirectErrorHandler implements HttpHandler { + String root; + volatile int count = 1; + + RedirectErrorHandler(String root) { + this.root = root; + } + + synchronized int count() { + return count; + } + + synchronized void increment() { + count++; + } + + @Override + public synchronized void handle (HttpExchange t) + throws IOException + { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers map = t.getResponseHeaders(); + String redirect = root + "/foo/" + Integer.toString(count); + increment(); + map.add("Location", redirect); + t.sendResponseHeaders(301, -1); + t.close(); + } +} + +class Util { + static byte[] readAll(InputStream is) throws IOException { + byte[] buf = new byte[1024]; + byte[] result = new byte[0]; + + while (true) { + int n = is.read(buf); + if (n > 0) { + byte[] b1 = new byte[result.length + n]; + System.arraycopy(result, 0, b1, 0, result.length); + System.arraycopy(buf, 0, b1, result.length, n); + result = b1; + } else if (n == -1) { + return result; + } + } + } +} + +class DelayHandler implements HttpHandler { + + CyclicBarrier bar1 = new CyclicBarrier(2); + CyclicBarrier bar2 = new CyclicBarrier(2); + CyclicBarrier bar3 = new CyclicBarrier(2); + + CyclicBarrier barrier1() { + return bar1; + } + + CyclicBarrier barrier2() { + return bar2; + } + + @Override + public synchronized void handle(HttpExchange he) throws IOException { + byte[] buf = Util.readAll(he.getRequestBody()); + try { + bar1.await(); + bar2.await(); + } catch (Exception e) {} + he.sendResponseHeaders(200, -1); // will probably fail + he.close(); + } + +} + +// check for simple hardcoded sequence and use remote address +// to check. +// First 4 requests executed in sequence (should use same connection/address) +// Next 4 requests parallel (should use different addresses) +// Then send 4 requests in parallel x 100 times (same four addresses used all time) + +class KeepAliveHandler implements HttpHandler { + volatile int counter = 0; + + HashSet portSet = new HashSet<>(); + + volatile int[] ports = new int[4]; + + void sleep(int n) { + try { + Thread.sleep(n); + } catch (InterruptedException e) {} + } + + @Override + public synchronized void handle (HttpExchange t) + throws IOException + { + int remotePort = t.getRemoteAddress().getPort(); + String result = "OK"; + + int n = counter++; + /// First test + if (n < 4) { + ports[n] = remotePort; + } + if (n == 3) { + // check all values in ports[] are the same + if (ports[0] != ports[1] || ports[2] != ports[3] + || ports[0] != ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + // Second test + if (n >=4 && n < 8) { + // delay to ensure ports are different + sleep(500); + ports[n-4] = remotePort; + } + if (n == 7) { + // should be all different + if (ports[0] == ports[1] || ports[2] == ports[3] + || ports[0] == ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + System.out.printf("Ports: %d, %d, %d, %d\n", ports[0], ports[1], ports[2], ports[3]); + } + // setup for third test + for (int i=0; i<4; i++) { + portSet.add(ports[i]); + } + } + // Third test + if (n > 7) { + // just check that port is one of the ones in portSet + if (!portSet.contains(remotePort)) { + System.out.println ("UNEXPECTED REMOTE PORT " + remotePort); + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + byte[] buf = new byte[2048]; + + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + t.sendResponseHeaders(200, result.length()); + OutputStream o = t.getResponseBody(); + o.write(result.getBytes("US-ASCII")); + t.close(); + } +} diff --git a/jdk/test/java/net/httpclient/SplitResponse.java b/jdk/test/java/net/httpclient/SplitResponse.java new file mode 100644 index 00000000000..cf887c19a0f --- /dev/null +++ b/jdk/test/java/net/httpclient/SplitResponse.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, 2016, 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 javaapplication16; + +import java.io.IOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +/** + * @test + * @bug 8087112 + * @build Server + * @run main/othervm -Djava.net.HttpClient.log=all SplitResponse + */ + +/** + * Similar test to QuickResponses except that each byte of the response + * is sent in a separate packet, which tests the stability of the implementation + * for receiving unusual packet sizes. + */ +public class SplitResponse { + + static Server server; + + static String response(String body) { + return "HTTP/1.1 200 OK\r\nConnection: Close\r\nContent-length: " + + Integer.toString(body.length()) + + "\r\n\r\n" + body; + } + + static final String responses[] = { + "Lorem ipsum", + "dolor sit amet", + "consectetur adipiscing elit, sed do eiusmod tempor", + "quis nostrud exercitation ullamco", + "laboris nisi", + "ut", + "aliquip ex ea commodo consequat." + + "Duis aute irure dolor in reprehenderit in voluptate velit esse" + + "cillum dolore eu fugiat nulla pariatur.", + "Excepteur sint occaecat cupidatat non proident." + }; + + public static void main(String[] args) throws Exception { + server = new Server(0); + URI uri = new URI(server.getURL()); + + HttpRequest request; + HttpResponse r; + CompletableFuture cf1; + + for (int i=0; i { + try { + int len = s.length(); + for (int i = 0; i < len; i++) { + String onechar = s.substring(i, i + 1); + conn.send(onechar); + Thread.sleep(30); + } + System.out.println("sent"); + } catch (IOException | InterruptedException e) { + } + }); + t.setDaemon(true); + t.start(); + } +} diff --git a/jdk/test/java/net/httpclient/TimeoutTest.java b/jdk/test/java/net/httpclient/TimeoutTest.java new file mode 100644 index 00000000000..d7d2ff224a9 --- /dev/null +++ b/jdk/test/java/net/httpclient/TimeoutTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2015, 2016, 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.IOException; +import java.net.ServerSocket; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpTimeoutException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * @test + * @bug 8087112 + * @run main/othervm TimeoutTest + */ + +public class TimeoutTest { + + static int[] timeouts = {6, 4, 8, 6, 6, 4}; + static HttpRequest[] rqs = new HttpRequest[timeouts.length]; + static LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + static volatile boolean error = false; + static ExecutorService executor = Executors.newCachedThreadPool(); + + public static void main(String[] args) throws Exception { + try { + dotest(); + } finally { + HttpClient.getDefault().executorService().shutdownNow(); + executor.shutdownNow(); + } + } + public static void dotest() throws Exception { + System.out.println("Test takes over 40 seconds"); + ServerSocket ss = new ServerSocket(0, 20); + int port = ss.getLocalPort(); + + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/foo"); + int i = 0; + for (int timeout : timeouts) { + HttpRequest request; + (request = rqs[i] = HttpRequest.create(uri) + .timeout(TimeUnit.SECONDS, timeout) + .GET()) + .responseAsync() + .whenComplete((HttpResponse r, Throwable t) -> { + if (!(t.getCause() instanceof HttpTimeoutException)) { + System.out.println("Wrong exception type:" + t.toString()); + error = true; + } + if (t != null) { + queue.add(request); + } + }) + .thenAccept((HttpResponse r) -> { + r.bodyAsync(HttpResponse.ignoreBody()); + }); + i++; + } + + System.out.println("SUBMITTED"); + + checkReturnOrder(); + + if (error) + throw new RuntimeException("Failed"); + + // Repeat blocking in separate threads. Use queue to wait. + System.out.println("DOING BLOCKING"); + + i = 0; + for (int timeout : timeouts) { + HttpRequest req = HttpRequest.create(uri) + .timeout(TimeUnit.SECONDS, timeout) + .GET(); + rqs[i] = req; + executor.execute(() -> { + try { + req.response().body(HttpResponse.ignoreBody()); + } catch (HttpTimeoutException e) { + queue.offer(req); + } catch (IOException | InterruptedException ee) { + error = true; + } + }); + i++; + } + + checkReturnOrder(); + + if (error) + throw new RuntimeException("Failed"); + } + + static void checkReturnOrder() throws InterruptedException { + // wait for exceptions and check order + for (int j = 0; j < timeouts.length; j++) { + HttpRequest req = queue.take(); + switch (j) { + case 0: + case 1: + if (req != rqs[1] && req != rqs[5]) { + System.out.printf("Expected 1 or 5. Got %s\n", getRequest(req)); + throw new RuntimeException("Error"); + } + break; + case 2: + case 3: + case 4: + if (req != rqs[0] && req != rqs[3] && req != rqs[4]) { + System.out.printf("Expected r1, r4 or r5. Got %s\n", getRequest(req)); + throw new RuntimeException("Error"); + } + break; + case 5: + if (req != rqs[2]) { + System.out.printf("Expected r3. Got %s\n", getRequest(req)); + throw new RuntimeException("Error"); + } + } + } + System.out.println("Return order ok"); + } + + static String getRequest(HttpRequest req) { + for (int i=0; i clients = new LinkedList<>(); + static URI uri; + + interface Test { + public void execute() throws IOException, InterruptedException; + } + + static class TestAndResult { + Test test; + boolean result; + + TestAndResult (Test t, boolean result) { + this.test = t; + this.result = result; + } + } + + static TestAndResult test(boolean result, Test t) { + return new TestAndResult(t, result); + } + + static TestAndResult[] tests; + static String testclasses; + static File subdir; + + /** + * The ProxyServer class is compiled by jtreg, but we want to + * move it so it is not on the application claspath. We want to + * load it through a separate classloader so that it has a separate + * protection domain and security permissions. + * + * Its permissions are in the second grant block in each policy file + */ + static void setupProxy() throws IOException, ClassNotFoundException, NoSuchMethodException { + testclasses = System.getProperty("test.classes"); + subdir = new File (testclasses, "proxydir"); + subdir.mkdir(); + + movefile("ProxyServer.class"); + movefile("ProxyServer$Connection.class"); + movefile("ProxyServer$1.class"); + + URL url = subdir.toURL(); + System.out.println("URL for class loader = " + url); + URLClassLoader urlc = new URLClassLoader(new URL[] {url}); + proxyClass = Class.forName("ProxyServer", true, urlc); + proxyConstructor = proxyClass.getConstructor(Integer.class, Boolean.class); + } + + static void movefile(String f) throws IOException { + Path src = Paths.get(testclasses, f); + Path dest = subdir.toPath().resolve(f); + if (!dest.toFile().exists()) { + System.out.printf("moving %s to %s\n", src.toString(), dest.toString()); + Files.move(src, dest, StandardCopyOption.REPLACE_EXISTING); + } else { + System.out.printf("NOT moving %s to %s\n", src.toString(), dest.toString()); + } + } + + static Object getProxy(int port, boolean b) throws Exception { + return proxyConstructor.newInstance(port, b); + } + + static Class proxyClass; + static Constructor proxyConstructor; + + static void setupTests() { + tests = new TestAndResult[]{ + // (0) policy does not have permission for file. Should fail + test(false, () -> { // Policy 0 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (1) policy has permission for file URL + test(true, () -> { //Policy 1 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (2) policy has permission for all file URLs under /files + test(true, () -> { // Policy 2 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (3) policy has permission for first URL but not redirected URL + test(false, () -> { // Policy 3 + URI u = URI.create("http://127.0.0.1:" + port + "/redirect/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (4) policy has permission for both first URL and redirected URL + test(true, () -> { // Policy 4 + URI u = URI.create("http://127.0.0.1:" + port + "/redirect/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (5) policy has permission for redirected but not first URL + test(false, () -> { // Policy 5 + URI u = URI.create("http://127.0.0.1:" + port + "/redirect/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (6) policy has permission for file URL, but not method + test(false, () -> { //Policy 6 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (7) policy has permission for file URL, method, but not header + test(false, () -> { //Policy 7 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .header("X-Foo", "bar") + .GET(); + HttpResponse response = request.response(); + }), + // (8) policy has permission for file URL, method and header + test(true, () -> { //Policy 8 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .header("X-Foo", "bar") + .GET(); + HttpResponse response = request.response(); + }), + // (9) policy has permission for file URL, method and header + test(true, () -> { //Policy 9 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .headers("X-Foo", "bar", "X-Bar", "foo") + .GET(); + HttpResponse response = request.response(); + }), + // (10) policy has permission for destination URL but not for proxy + test(false, () -> { //Policy 10 + directProxyTest(27208, true); + }), + // (11) policy has permission for both destination URL and proxy + test(true, () -> { //Policy 11 + directProxyTest(27301, true); + }), + // (12) policy has permission for both destination URL and proxy + test(false, () -> { //Policy 11 + directProxyTest(28301, false); + }), + // (13) async version of test 0 + test(false, () -> { // Policy 0 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + try { + HttpResponse response = request.responseAsync().get(); + } catch (ExecutionException e) { + if (e.getCause() instanceof SecurityException) { + throw (SecurityException)e.getCause(); + } else { + throw new RuntimeException(e); + } + } + }), + // (14) async version of test 1 + test(true, () -> { //Policy 1 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + try { + HttpResponse response = request.responseAsync().get(); + } catch (ExecutionException e) { + if (e.getCause() instanceof SecurityException) { + throw (SecurityException)e.getCause(); + } else { + throw new RuntimeException(e); + } + } + }), + // (15) check that user provided unprivileged code running on a worker + // thread does not gain ungranted privileges. + test(false, () -> { //Policy 12 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + HttpResponse.BodyProcessor stproc = HttpResponse.asString(); + + CompletableFuture cf; + cf = response.bodyAsync(new HttpResponse.BodyProcessor() { + public void onResponseBodyChunk(ByteBuffer b) throws IOException { + // do some mischief here + SecurityManager sm = System.getSecurityManager(); + System.setSecurityManager(null); + System.setSecurityManager(sm); + // problem if we get this far + stproc.onResponseBodyChunk(b); + } + public String onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer fc) throws IOException { + + SecurityManager sm = System.getSecurityManager(); + // should succeed. + sm.checkPermission(new RuntimePermission("foobar")); + return stproc.onResponseBodyStart(contentLength,responseHeaders, fc); + } + public String onResponseComplete() throws IOException { + return stproc.onResponseComplete(); + } + public void onResponseError(Throwable t) { + stproc.onResponseError(t); + } + } + ); + try { + System.out.println("Body = " + cf.get());// should not reach here + } catch (ExecutionException e) { + if (e.getCause() instanceof SecurityException) { + throw (SecurityException)e.getCause(); + } else { + throw new RuntimeException(e); + } + } + }) + }; + } + + private static void directProxyTest(int proxyPort, boolean samePort) throws IOException, InterruptedException { + Object proxy = null; + try { + proxy = getProxy(proxyPort, true); + } catch (IOException e) { + System.out.println("Cannot bind. Not running test"); + throw new SecurityException("test not run"); + } catch (Exception ee) { + throw new RuntimeException(ee); + } + System.out.println("Proxy port = " + proxyPort); + if (!samePort) + proxyPort++; + + HttpClient cl = HttpClient.create() + .proxy(ProxySelector.of( + new InetSocketAddress("127.0.0.1", proxyPort))) + .build(); + clients.add(cl); + + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = cl.request(u) + .headers("X-Foo", "bar", "X-Bar", "foo") + .GET(); + HttpResponse response = request.response(); + } + + static void runtest(Test r, String policy, boolean succeeds) { + System.out.println("Using policy file: " + policy); + try { + r.execute(); + if (!succeeds) { + System.out.println("FAILED: expected security exception"); + throw new RuntimeException("Failed"); + } + System.out.println (policy + " succeeded as expected"); + } catch (SecurityException e) { + if (succeeds) { + System.out.println("FAILED"); + throw new RuntimeException(e); + } + System.out.println (policy + " threw exception as expected"); + } catch (IOException | InterruptedException ee) { + throw new RuntimeException(ee); + } + } + + public static void main(String[] args) throws Exception { + initServer(); + setupProxy(); + fileroot = System.getProperty ("test.src")+ "/docs"; + int testnum = Integer.parseInt(args[0]); + String policy = args[0]; + + client = HttpClient + .create() + .followRedirects(HttpClient.Redirect.ALWAYS) + .build(); + + clients.add(HttpClient.getDefault()); + clients.add(client); + + try { + setupTests(); + TestAndResult tr = tests[testnum]; + runtest(tr.test, policy, tr.result); + } finally { + s1.stop(0); + //executor.shutdownNow(); + for (HttpClient client : clients) + client.executorService().shutdownNow(); + } + } + + // create Http Server on port range below. So, we can + HttpServer createServer() { + HttpServer server; + for (int i=25800; i<26800; i++) { + InetSocketAddress a = new InetSocketAddress(i); + try { + server = HttpServer.create(a, 0); + return server; + } catch (IOException e) {} + } + return null; + } + + public static void initServer() throws Exception { + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + String root = System.getProperty ("test.src")+ "/docs"; + InetSocketAddress addr = new InetSocketAddress (0); + s1 = HttpServer.create (addr, 0); + if (s1 instanceof HttpsServer) { + throw new RuntimeException ("should not be httpsserver"); + } + HttpHandler h = new FileServerHandler (root); + HttpContext c = s1.createContext ("/files", h); + + HttpHandler h1 = new RedirectHandler ("/redirect"); + HttpContext c1 = s1.createContext ("/redirect", h1); + + executor = Executors.newCachedThreadPool(); + s1.setExecutor (executor); + s1.start(); + + port = s1.getAddress().getPort(); + System.out.println("HTTP server port = " + port); + httproot = "http://127.0.0.1:" + port + "/files/"; + redirectroot = "http://127.0.0.1:" + port + "/redirect/"; + uri = new URI(httproot); + fileuri = httproot + "foo.txt"; + } + + static class RedirectHandler implements HttpHandler { + + String root; + int count = 0; + + RedirectHandler(String root) { + this.root = root; + } + + synchronized int count() { + return count; + } + + synchronized void increment() { + count++; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + byte[] buf = new byte[2048]; + System.out.println("Server: " + t.getRequestURI()); + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + increment(); + if (count() == 1) { + Headers map = t.getResponseHeaders(); + String redirect = "/redirect/bar.txt"; + map.add("Location", redirect); + t.sendResponseHeaders(301, -1); + t.close(); + } else { + String response = "Hello world"; + t.sendResponseHeaders(200, response.length()); + OutputStream os = t.getResponseBody(); + os.write(response.getBytes(StandardCharsets.ISO_8859_1)); + t.close(); + } + } + } +} From 3698f154bf3842daf65313c0f9fee8500ec3a23a Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Mon, 7 Mar 2016 14:52:36 +0000 Subject: [PATCH 129/311] 8151149: CipherSpi implementation of PBEWithSHA1AndDESede returns key size in bytes Reviewed-by: xuelei --- .../crypto/provider/PKCS12PBECipherCore.java | 11 ++- .../provider/Cipher/PBE/CheckPBEKeySize.java | 73 +++++++++++++++++++ 2 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java index a02aa4bd175..52a9e3e01ab 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -50,6 +50,7 @@ final class PKCS12PBECipherCore { private CipherCore cipher; private int blockSize; private int keySize; + private int keyLength; // in bits private String algo = null; private String pbeAlgo = null; private byte[] salt = null; @@ -166,16 +167,18 @@ final class PKCS12PBECipherCore { throws NoSuchAlgorithmException { algo = symmCipherAlg; + keyLength = defKeySize * 8; if (algo.equals("RC4")) { - pbeAlgo = "PBEWithSHA1AndRC4_" + defKeySize * 8; + pbeAlgo = "PBEWithSHA1AndRC4_" + keyLength; } else { SymmetricCipher symmCipher = null; if (algo.equals("DESede")) { symmCipher = new DESedeCrypt(); pbeAlgo = "PBEWithSHA1AndDESede"; + keyLength = 112; // effective key length } else if (algo.equals("RC2")) { symmCipher = new RC2Crypt(); - pbeAlgo = "PBEWithSHA1AndRC2_" + defKeySize * 8; + pbeAlgo = "PBEWithSHA1AndRC2_" + keyLength; } else { throw new NoSuchAlgorithmException("No Cipher implementation " + "for PBEWithSHA1And" + algo); @@ -406,7 +409,7 @@ final class PKCS12PBECipherCore { } int implGetKeySize(Key key) throws InvalidKeyException { - return keySize; + return keyLength; } byte[] implWrap(Key key) throws IllegalBlockSizeException, diff --git a/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java b/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java new file mode 100644 index 00000000000..324d80441fb --- /dev/null +++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, 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 8151149 + * @modules java.base/com.sun.crypto.provider + */ + +import java.lang.reflect.*; +import java.security.*; +import javax.crypto.*; +import javax.crypto.spec.*; +import com.sun.crypto.provider.*; + +public class CheckPBEKeySize { + + private static final String ALGO = "PBEWithSHA1AndDESede"; + private static final int KEYSIZE = 112; // Triple DES effective key size + + public static final void main(String[] args) throws Exception { + + // Generate a PBE key + SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE"); + SecretKey skey = + skFac.generateSecret(new PBEKeySpec("test123".toCharArray())); + + // Initialize the PBE cipher + Cipher cipher = Cipher.getInstance(ALGO); + cipher.init(Cipher.ENCRYPT_MODE, skey); + + // Permit access to the Cipher.spi field (a CipherSpi object) + Field spi = Cipher.class.getDeclaredField("spi"); + spi.setAccessible(true); + Object value = spi.get(cipher); + + // Permit access to the CipherSpi.engineGetKeySize method + Method engineGetKeySize = + PKCS12PBECipherCore$PBEWithSHA1AndDESede.class + .getDeclaredMethod("engineGetKeySize", Key.class); + engineGetKeySize.setAccessible(true); + + // Check the key size + int keySize = (int) engineGetKeySize.invoke(value, skey); + if (keySize == KEYSIZE) { + System.out.println(ALGO + ".engineGetKeySize returns " + keySize + + " bits, as expected"); + System.out.println("OK"); + } else { + throw new Exception("ERROR: " + ALGO + " key size is incorrect"); + } + } +} From e868165acc1fda8a0c8ce643ccedd657078d98ad Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Mon, 7 Mar 2016 10:10:04 -0500 Subject: [PATCH 130/311] 8138653: Default key sizes for the AlgorithmParameterGenerator and KeyPairGenerator implementations should be upgraded Reviewed-by: coffeys, vinnie --- .../com/sun/crypto/provider/DHKeyPairGenerator.java | 6 +++--- .../sun/crypto/provider/DHParameterGenerator.java | 6 +++--- .../classes/java/security/KeyPairGenerator.java | 6 +++--- .../sun/security/rsa/RSAKeyPairGenerator.java | 4 ++-- .../sun/security/mscapi/RSAKeyPairGenerator.java | 4 ++-- .../classes/sun/security/mscapi/SunMSCAPI.java | 4 ++-- .../sun/security/pkcs11/P11KeyPairGenerator.java | 13 ++++++++++--- .../provider/KeyAgreement/TestExponentSize.java | 12 ++++++------ jdk/test/sun/security/pkcs11/PKCS11Test.java | 7 +++++-- 9 files changed, 36 insertions(+), 26 deletions(-) diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java index d86feab3c2b..06a685b2482 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -43,7 +43,7 @@ import sun.security.provider.ParameterCache; *
    • By providing the size in bits of the prime modulus - * This will be used to create a prime modulus and base generator, which will * then be used to create the Diffie-Hellman key pair. The default size of the - * prime modulus is 1024 bits. + * prime modulus is 2048 bits. *
    • By providing a prime modulus and base generator * * @@ -68,7 +68,7 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi { public DHKeyPairGenerator() { super(); - initialize(1024, null); + initialize(2048, null); } /** diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java index 6f25b699a83..86c4cd900bb 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -37,7 +37,7 @@ import javax.crypto.spec.DHGenParameterSpec; * *

      The Diffie-Hellman parameter generation accepts the size in bits of the * prime modulus and the size in bits of the random exponent as input. - * The size of the prime modulus defaults to 1024 bits. + * The size of the prime modulus defaults to 2048 bits. * * @author Jan Luehe * @@ -50,7 +50,7 @@ public final class DHParameterGenerator extends AlgorithmParameterGeneratorSpi { // The size in bits of the prime modulus - private int primeSize = 1024; + private int primeSize = 2048; // The size in bits of the random exponent (private value) private int exponentSize = 0; diff --git a/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java b/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java index 246f140b435..285e19a1639 100644 --- a/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java +++ b/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -71,7 +71,7 @@ import sun.security.util.Debug; * associated with each of the keys. * *

      If the algorithm is the DSA algorithm, and the keysize (modulus - * size) is 512, 768, or 1024, then the Sun provider uses a set of + * size) is 512, 768, 1024, or 2048, then the Sun provider uses a set of * precomputed values for the {@code p}, {@code q}, and * {@code g} parameters. If the modulus size is not one of the above * values, the Sun provider creates a new set of parameters. Other @@ -96,7 +96,7 @@ import sun.security.util.Debug; * (via a call to an {@code initialize} method), each provider must * supply (and document) a default initialization. * For example, the Sun provider uses a default modulus size (keysize) - * of 1024 bits. + * of 1024 bits for DSA key pairs. * *

      Note that this class is abstract and extends from * {@code KeyPairGeneratorSpi} for historical reasons. diff --git a/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java b/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java index 8ca36a1e62c..0901e4c7af6 100644 --- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java +++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -55,7 +55,7 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { public RSAKeyPairGenerator() { // initialize to default in case the app does not call initialize() - initialize(1024, null); + initialize(2048, null); } // initialize the generator. See JCA doc diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java index f0d193eb8a6..f9ffd5fe697 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -46,7 +46,7 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { // Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384 static final int KEY_SIZE_MAX = 16384; - private static final int KEY_SIZE_DEFAULT = 1024; + private static final int KEY_SIZE_DEFAULT = 2048; // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX private int keySize; diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java index 9b36d662081..94b8535ea8f 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -182,7 +182,7 @@ public final class SunMSCAPI extends Provider { * Key Pair Generator engines */ attrs.clear(); - attrs.put("KeySize", "1024"); + attrs.put("KeySize", "16384"); putService(new ProviderService(p, "KeyPairGenerator", "RSA", "sun.security.mscapi.RSAKeyPairGenerator", null, attrs)); diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java index 4adac8ce4bf..bccddb41bd1 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -106,8 +106,15 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { maxKeyLen = 2048; } } else { - // RSA, DH, and DSA - keySize = 1024; + if (algorithm.equals("DSA")) { + // keep default keysize at 1024 since larger keysizes may be + // incompatible with SHA1withDSA and SHA-2 Signature algs + // may not be supported by native pkcs11 implementations + keySize = 1024; + } else { + // RSA and DH + keySize = 2048; + } if ((minKeyLen == -1) || (minKeyLen < 512)) { minKeyLen = 512; } diff --git a/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java b/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java index 6226fe9191d..b304121fa0c 100644 --- a/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java +++ b/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -83,10 +83,10 @@ public class TestExponentSize { KeyPair kp; KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", "SunJCE"); - // Sun's default uses a default psize of 1024 and + // Sun's default uses a default psize of 2048 and // lsize of (pSize / 2) but at least 384 bits kp = kpg.generateKeyPair(); - checkKeyPair(kp, Sizes.ten24, Sizes.five12); + checkKeyPair(kp, Sizes.twenty48, Sizes.ten24); DHPublicKey publicKey = (DHPublicKey)kp.getPublic(); BigInteger p = publicKey.getParams().getP(); @@ -98,15 +98,15 @@ public class TestExponentSize { kpg.initialize(new DHParameterSpec(p, g, Sizes.ten24.getIntSize())); kp = kpg.generateKeyPair(); - checkKeyPair(kp, Sizes.ten24, Sizes.ten24); + checkKeyPair(kp, Sizes.twenty48, Sizes.ten24); kpg.initialize(new DHParameterSpec(p, g, Sizes.five12.getIntSize())); kp = kpg.generateKeyPair(); - checkKeyPair(kp, Sizes.ten24, Sizes.five12); + checkKeyPair(kp, Sizes.twenty48, Sizes.five12); kpg.initialize(new DHParameterSpec(p, g, Sizes.two56.getIntSize())); kp = kpg.generateKeyPair(); - checkKeyPair(kp, Sizes.ten24, Sizes.two56); + checkKeyPair(kp, Sizes.twenty48, Sizes.two56); kpg.initialize(Sizes.five12.getIntSize()); kp = kpg.generateKeyPair(); diff --git a/jdk/test/sun/security/pkcs11/PKCS11Test.java b/jdk/test/sun/security/pkcs11/PKCS11Test.java index 46621e1ae2e..bd85ea6058f 100644 --- a/jdk/test/sun/security/pkcs11/PKCS11Test.java +++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java @@ -380,7 +380,9 @@ public abstract class PKCS11Test { } static double getNSSInfo(String library) { - String nssHeader = "$Header: NSS"; + // look for two types of headers in NSS libraries + String nssHeader1 = "$Header: NSS"; + String nssHeader2 = "Version: NSS"; boolean found = false; String s = null; int i = 0; @@ -408,7 +410,8 @@ public abstract class PKCS11Test { } s = new String(data, 0, read); - if ((i = s.indexOf(nssHeader)) > 0) { + i = s.indexOf(nssHeader1); + if (i > 0 || (i = s.indexOf(nssHeader2)) > 0) { found = true; // If the nssHeader is before 920 we can break, otherwise // we may not have the whole header so do another read. If From e2181b48a52efe99f856a7fc5199396910de0974 Mon Sep 17 00:00:00 2001 From: Steve Drach Date: Mon, 7 Mar 2016 19:37:10 +0000 Subject: [PATCH 131/311] 8151339: Adding fragment to JAR URLs breaks ant Reviewed-by: alanb --- .../java.base/share/classes/sun/misc/URLClassPath.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java index 01afb44a159..ac86bdc5756 100644 --- a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java +++ b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java @@ -758,9 +758,13 @@ public class URLClassPath { final URL url; try { - // add #runtime fragment to tell JarURLConnection to use - // runtime versioning if the underlying jar file is multi-release - url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime"); + if (jar.isMultiRelease()) { + // add #runtime fragment to tell JarURLConnection to use + // runtime versioning if the underlying jar file is multi-release + url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime"); + } else { + url = new URL(getBaseURL(), ParseUtil.encodePath(name, false)); + } if (check) { URLClassPath.check(url); } From f1dc46272b72ab91a798042ae9411280a76b7cde Mon Sep 17 00:00:00 2001 From: David Dehaven Date: Thu, 25 Feb 2016 15:42:01 -0800 Subject: [PATCH 132/311] 8132743: Move netscape.javascript package from jdk.plugin to new module Reviewed-by: kcr, mchung, alanb --- .../classes/build/tools/module/boot.modules | 1 + .../javascript/spi/JSObjectProvider.java | 44 +++++ .../netscape/javascript/JSException.java | 60 ++++++ .../classes/netscape/javascript/JSObject.java | 182 ++++++++++++++++++ .../netscape/javascript/package-info.java | 38 ++++ 5 files changed, 325 insertions(+) create mode 100644 jdk/src/jdk.jsobject/share/classes/jdk/internal/netscape/javascript/spi/JSObjectProvider.java create mode 100644 jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java create mode 100644 jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java create mode 100644 jdk/src/jdk.jsobject/share/classes/netscape/javascript/package-info.java diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index a22b4af52b9..c774b5a0300 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -22,6 +22,7 @@ jdk.deploy jdk.deploy.osx jdk.httpserver jdk.jfr +jdk.jsobject jdk.net jdk.vm.cds jdk.vm.ci diff --git a/jdk/src/jdk.jsobject/share/classes/jdk/internal/netscape/javascript/spi/JSObjectProvider.java b/jdk/src/jdk.jsobject/share/classes/jdk/internal/netscape/javascript/spi/JSObjectProvider.java new file mode 100644 index 00000000000..69c123572d3 --- /dev/null +++ b/jdk/src/jdk.jsobject/share/classes/jdk/internal/netscape/javascript/spi/JSObjectProvider.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, 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. + */ + +package jdk.internal.netscape.javascript.spi; + +import java.applet.Applet; +import netscape.javascript.JSException; +import netscape.javascript.JSObject; + +public interface JSObjectProvider { + /** + * Return a JSObject for the window containing the given applet. + * Implementations of this class should return null if not connected to a + * browser, for example, when running in AppletViewer. + * + * @param applet The applet. + * @return JSObject for the window containing the given applet or null if we + * are not connected to a browser. + * @throws JSException when an error is encountered. + */ + public JSObject getWindow(Applet applet) throws JSException; +} diff --git a/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java new file mode 100644 index 00000000000..a47ed9f1de7 --- /dev/null +++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006, 2016, 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. + */ + +package netscape.javascript; + +/** + * Thrown when an exception is raised in the JavaScript engine. This is merely + * a marker class to indicate an exception relating to the JavaScript + * interface. + */ +public class JSException extends RuntimeException { + private static final long serialVersionUID = 2778103758223661489L; + + /** + * Constructs a new JavaScript exception with null as it's detail message. + */ + public JSException() { + super(); + } + + /** + * Construct a new JavaScript exception with the specified detail message. + * + * @param s The detail message + */ + public JSException(String s) { + super(s); + } + + /** + * Construct a new JavaScript exception with the specified cause. + * + * @param t Throwable cause + */ + public JSException(Throwable t) { + super(t); + } +} diff --git a/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java new file mode 100644 index 00000000000..250825ad676 --- /dev/null +++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2006, 2016, 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. + */ + +package netscape.javascript; + +import jdk.internal.netscape.javascript.spi.JSObjectProvider; +import java.applet.Applet; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Iterator; +import java.util.ServiceLoader; + +/** + *

      + * Allows Java code to manipulate JavaScript objects. + *

      + * + *

      + * When a JavaScript object is passed or returned to Java code, it + * is wrapped in an instance of {@code JSObject}. When a + * {@code JSObject} instance is passed to the JavaScript engine, + * it is unwrapped back to its original JavaScript object. The + * {@code JSObject} class provides a way to invoke JavaScript + * methods and examine JavaScript properties. + *

      + * + *

      Any data returned from the JavaScript engine to Java is + * converted to Java data types. Certain data passed to the JavaScript + * engine is converted to JavaScript data types. + *

      + * + */ +public abstract class JSObject { + /** + * Constructs a new JSObject. Users should neither call this method nor + * subclass JSObject. + */ + protected JSObject() { + } + + /** + * Calls a JavaScript method. Equivalent to + * "this.methodName(args[0], args[1], ...)" in JavaScript. + * + * @param methodName The name of the JavaScript method to be invoked. + * @param args the Java objects passed as arguments to the method. + * @return Result of the method. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract Object call(String methodName, Object... args) throws JSException; + + /** + * Evaluates a JavaScript expression. The expression is a string of + * JavaScript source code which will be evaluated in the context given by + * "this". + * + * @param s The JavaScript expression. + * @return Result of the JavaScript evaluation. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract Object eval(String s) throws JSException; + + /** + * Retrieves a named member of a JavaScript object. Equivalent to + * "this.name" in JavaScript. + * + * @param name The name of the JavaScript property to be accessed. + * @return The value of the propery. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract Object getMember(String name) throws JSException; + + /** + * Sets a named member of a JavaScript object. Equivalent to + * "this.name = value" in JavaScript. + * + * @param name The name of the JavaScript property to be accessed. + * @param value The value of the propery. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract void setMember(String name, Object value) throws JSException; + + /** + * Removes a named member of a JavaScript object. Equivalent + * to "delete this.name" in JavaScript. + * + * @param name The name of the JavaScript property to be removed. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract void removeMember(String name) throws JSException; + + /** + * Retrieves an indexed member of a JavaScript object. Equivalent to + * "this[index]" in JavaScript. + * + * @param index The index of the array to be accessed. + * @return The value of the indexed member. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract Object getSlot(int index) throws JSException; + + /** + * Sets an indexed member of a JavaScript object. Equivalent to + * "this[index] = value" in JavaScript. + * + * @param index The index of the array to be accessed. + * @param value The value to set + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract void setSlot(int index, Object value) throws JSException; + + /** + * Returns a JSObject for the window containing the given applet. This + * method only works when the Java code is running in a browser as an + * applet. The object returned may be used to access the HTML DOM directly. + * + * @param applet The applet. + * @return JSObject representing the window containing the given applet or + * {@code null} if we are not connected to a browser. + * @throws JSException when an error is reported from the browser or + * JavaScript engine or if applet is {@code null} + */ + public static JSObject getWindow(Applet applet) throws JSException { + return ProviderLoader.callGetWindow(applet); + } + + private static class ProviderLoader { + private static final JSObjectProvider provider; + + static { + provider = AccessController.doPrivileged( + new PrivilegedAction<>() { + @Override + public JSObjectProvider run() { + Iterator providers = + ServiceLoader.loadInstalled(JSObjectProvider.class).iterator(); + if (providers.hasNext()) { + return providers.next(); + } + return null; + } + } + ); + } + + private static JSObject callGetWindow(Applet applet) { + if (provider != null) { + return provider.getWindow(applet); + } + return null; + } + } +} diff --git a/jdk/src/jdk.jsobject/share/classes/netscape/javascript/package-info.java b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/package-info.java new file mode 100644 index 00000000000..d3770732bc0 --- /dev/null +++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/package-info.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2008, 2016, 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. + */ + +/** + *

      + * Provides Java code the ability to access the JavaScript engine and the + * HTML DOM in the web browser. + *

      + * + *

      + * The classes in this package were initially specified by Netscape, and are the + * de facto standard mechanism for calling JavaScript from the Java runtime. + *

      + */ + +package netscape.javascript; From 572b48bca55283aa67dc61502792beb2e834e60c Mon Sep 17 00:00:00 2001 From: Jamil Nimeh Date: Thu, 25 Feb 2016 16:10:15 -0800 Subject: [PATCH 133/311] 8145854: SSLContextImpl.statusResponseManager should be generated if required Implement server-side lazy initialization of StatusResponseManagers in the SSLContextImpl class. Reviewed-by: xuelei --- .../sun/security/ssl/ClientHandshaker.java | 9 +- .../sun/security/ssl/SSLContextImpl.java | 33 +- .../sun/security/ssl/ServerHandshaker.java | 43 +- .../net/ssl/Stapling/StapleEnableProps.java | 721 ++++++++++++++++++ 4 files changed, 780 insertions(+), 26 deletions(-) create mode 100644 jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java index 05d5e2f7906..3d2bb763a7b 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -81,9 +81,6 @@ final class ClientHandshaker extends Handshaker { private boolean serverKeyExchangeReceived; - private final boolean enableStatusRequestExtension = - Debug.getBooleanProperty( - "jdk.tls.client.enableStatusRequestExtension", true); private boolean staplingActive = false; private X509Certificate[] deferredCerts; @@ -761,7 +758,7 @@ final class ClientHandshaker extends Handshaker { type == ExtensionType.EXT_STATUS_REQUEST_V2) { // Only enable the stapling feature if the client asserted // these extensions. - if (enableStatusRequestExtension) { + if (sslContext.isStaplingEnabled(true)) { staplingActive = true; } else { fatalSE(Alerts.alert_unexpected_message, "Server set " + @@ -1562,7 +1559,7 @@ final class ClientHandshaker extends Handshaker { } // Add status_request and status_request_v2 extensions - if (enableStatusRequestExtension) { + if (sslContext.isStaplingEnabled(true)) { clientHelloMessage.addCertStatusReqListV2Extension(); clientHelloMessage.addCertStatusRequestExtension(); } diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java index 15b420da172..903f6fb376a 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -55,7 +55,11 @@ public abstract class SSLContextImpl extends SSLContextSpi { // DTLS cookie exchange manager private volatile HelloCookieManager helloCookieManager; - private StatusResponseManager statusResponseManager; + private final boolean clientEnableStapling = Debug.getBooleanProperty( + "jdk.tls.client.enableStatusRequestExtension", true); + private final boolean serverEnableStapling = Debug.getBooleanProperty( + "jdk.tls.server.enableStatusRequestExtension", false); + private volatile StatusResponseManager statusResponseManager; SSLContextImpl() { ephemeralKeyManager = new EphemeralKeyManager(); @@ -80,7 +84,6 @@ public abstract class SSLContextImpl extends SSLContextSpi { } } trustManager = chooseTrustManager(tm); - statusResponseManager = new StatusResponseManager(); if (sr == null) { secureRandom = JsseJce.getSecureRandom(); @@ -258,6 +261,18 @@ public abstract class SSLContextImpl extends SSLContextSpi { } StatusResponseManager getStatusResponseManager() { + if (serverEnableStapling && statusResponseManager == null) { + synchronized (this) { + if (statusResponseManager == null) { + if (debug != null && Debug.isOn("sslctx")) { + System.out.println( + "Initializing StatusResponseManager"); + } + statusResponseManager = new StatusResponseManager(); + } + } + } + return statusResponseManager; } @@ -309,6 +324,18 @@ public abstract class SSLContextImpl extends SSLContextSpi { (cipherSuites == getClientDefaultCipherSuiteList()); } + /** + * Return whether client or server side stapling has been enabled + * for this SSLContextImpl + * @param isClient true if the caller is operating in a client side role, + * false if acting as a server. + * @return true if stapling has been enabled for the specified role, false + * otherwise. + */ + boolean isStaplingEnabled(boolean isClient) { + return isClient ? clientEnableStapling : serverEnableStapling; + } + /* * Return the list of all available CipherSuites with a priority of * minPriority or above. diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java index 0b8072ff679..eb3484c6c4b 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -118,10 +118,6 @@ final class ServerHandshaker extends Handshaker { LegacyAlgorithmConstraints.PROPERTY_TLS_LEGACY_ALGS, new SSLAlgorithmDecomposer()); - // To switch off the status_request[_v2] extensions - private static final boolean enableStatusRequestExtension = - Debug.getBooleanProperty( - "jdk.tls.server.enableStatusRequestExtension", false); private boolean staplingActive = false; private long statusRespTimeout; @@ -589,7 +585,7 @@ final class ServerHandshaker extends Handshaker { (CertStatusReqListV2Extension)mesg.extensions.get( ExtensionType.EXT_STATUS_REQUEST_V2); // Keep stapling active if at least one of the extensions has been set - staplingActive = enableStatusRequestExtension && + staplingActive = sslContext.isStaplingEnabled(false) && (statReqExt != null || statReqExtV2 != null); /* @@ -932,19 +928,32 @@ final class ServerHandshaker extends Handshaker { } if (statReqType != null && statReqData != null) { - // Next, attempt to obtain status responses StatusResponseManager statRespMgr = sslContext.getStatusResponseManager(); - responseMap = statRespMgr.get(statReqType, statReqData, certs, - statusRespTimeout, TimeUnit.MILLISECONDS); - if (!responseMap.isEmpty()) { - // We now can safely assert status_request[_v2] in our - // ServerHello, and know for certain that we can provide - // responses back to this client for this connection. - if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST) { - m1.extensions.add(new CertStatusReqExtension()); - } else if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST_V2) { - m1.extensions.add(new CertStatusReqListV2Extension()); + if (statRespMgr != null) { + responseMap = statRespMgr.get(statReqType, statReqData, + certs, statusRespTimeout, TimeUnit.MILLISECONDS); + if (!responseMap.isEmpty()) { + // We now can safely assert status_request[_v2] in our + // ServerHello, and know for certain that we can provide + // responses back to this client for this connection. + if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST) { + m1.extensions.add(new CertStatusReqExtension()); + } else if (statusRespExt == + ExtensionType.EXT_STATUS_REQUEST_V2) { + m1.extensions.add( + new CertStatusReqListV2Extension()); + } + } + } else { + // This should not happen if stapling is active, but + // if lazy initialization of the StatusResponseManager + // doesn't occur we should turn off stapling. + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Warning: lazy initialization " + + "of the StatusResponseManager failed. " + + "Stapling has been disabled."); + staplingActive = false; } } } diff --git a/jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java b/jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java new file mode 100644 index 00000000000..7dece5ba724 --- /dev/null +++ b/jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java @@ -0,0 +1,721 @@ +/* + * Copyright (c) 2016, 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8145854 + * @summary SSLContextImpl.statusResponseManager should be generated if required + * @library ../../../../java/security/testlibrary + * @build CertificateBuilder SimpleOCSPServer + * @run main/othervm StapleEnableProps + */ + +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.*; +import java.io.*; +import java.math.BigInteger; +import java.security.*; +import java.nio.*; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import sun.security.testlibrary.SimpleOCSPServer; +import sun.security.testlibrary.CertificateBuilder; + +public class StapleEnableProps { + + /* + * Enables logging of the SSLEngine operations. + */ + private static final boolean logging = true; + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + + // These two ByteBuffer references will be used to hang onto ClientHello + // messages with and without the status_request[_v2] extensions. These + // will be used in the server-side stapling tests. + private static ByteBuffer cHelloStaple; + private static ByteBuffer cHelloNoStaple; + + // The following items are used to set up the keystores. + private static final String passwd = "passphrase"; + private static final String ROOT_ALIAS = "root"; + private static final String INT_ALIAS = "intermediate"; + private static final String SSL_ALIAS = "ssl"; + + // PKI components we will need for this test + private static KeyManagerFactory kmf; + private static TrustManagerFactory tmf; + private static KeyStore rootKeystore; // Root CA Keystore + private static KeyStore intKeystore; // Intermediate CA Keystore + private static KeyStore serverKeystore; // SSL Server Keystore + private static KeyStore trustStore; // SSL Client trust store + private static SimpleOCSPServer rootOcsp; // Root CA OCSP Responder + private static int rootOcspPort; // Port for root OCSP + private static SimpleOCSPServer intOcsp; // Intermediate CA OCSP server + private static int intOcspPort; // Port for intermediate OCSP + + // A few helpful TLS definitions to make it easier + private static final int HELLO_EXT_STATUS_REQ = 5; + private static final int HELLO_EXT_STATUS_REQ_V2 = 17; + + /* + * Main entry point for this test. + */ + public static void main(String args[]) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "ssl"); + } + + // Create the PKI we will use for the test and start the OCSP servers + createPKI(); + + // Set up the KeyManagerFactory and TrustManagerFactory + kmf = KeyManagerFactory.getInstance("PKIX"); + kmf.init(serverKeystore, passwd.toCharArray()); + tmf = TrustManagerFactory.getInstance("PKIX"); + tmf.init(trustStore); + + // Run the client and server property tests + testClientProp(); + testServerProp(); + + } + + private static void testClientProp() throws Exception { + SSLEngineResult clientResult; + + // Test with the client-side enable property set to true + System.out.println("========================================="); + System.out.println("Client Test 1: " + + "jdk.tls.client.enableStatusRequestExtension = true"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.client.enableStatusRequestExtension", + "true"); + SSLContext ctxStaple = SSLContext.getInstance("TLS"); + ctxStaple.init(null, tmf.getTrustManagers(), null); + SSLEngine engine = ctxStaple.createSSLEngine(); + engine.setUseClientMode(true); + SSLSession session = engine.getSession(); + ByteBuffer clientOut = ByteBuffer.wrap("I'm a Client".getBytes()); + ByteBuffer cTOs = + ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Create and check the ClientHello message + clientResult = engine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + if (clientResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + clientResult.getStatus()); + } + cTOs.flip(); + System.out.println(dumpHexBytes(cTOs)); + checkClientHello(cTOs, true, true); + cHelloStaple = cTOs; + + // Test with the property set to false + System.out.println("========================================="); + System.out.println("Client Test 2: " + + "jdk.tls.client.enableStatusRequestExtension = false"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.client.enableStatusRequestExtension", + "false"); + SSLContext ctxNoStaple = SSLContext.getInstance("TLS"); + ctxNoStaple.init(null, tmf.getTrustManagers(), null); + engine = ctxNoStaple.createSSLEngine(); + engine.setUseClientMode(true); + session = engine.getSession(); + cTOs = ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Create and check the ClientHello message + clientResult = engine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + if (clientResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + clientResult.getStatus()); + } + cTOs.flip(); + System.out.println(dumpHexBytes(cTOs)); + checkClientHello(cTOs, false, false); + cHelloNoStaple = cTOs; + } + + private static void testServerProp() throws Exception { + SSLEngineResult serverResult; + HandshakeStatus hsStat; + + // Test with the server-side enable property set to true + System.out.println("========================================="); + System.out.println("Server Test 1: " + + "jdk.tls.server.enableStatusRequestExtension = true"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.server.enableStatusRequestExtension", + "true"); + SSLContext ctxStaple = SSLContext.getInstance("TLS"); + ctxStaple.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + SSLEngine engine = ctxStaple.createSSLEngine(); + engine.setUseClientMode(false); + SSLSession session = engine.getSession(); + ByteBuffer serverOut = ByteBuffer.wrap("I'm a Server".getBytes()); + ByteBuffer serverIn = + ByteBuffer.allocate(session.getApplicationBufferSize() + 50); + ByteBuffer sTOc = + ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Consume the client hello + serverResult = engine.unwrap(cHelloStaple, serverIn); + log("server unwrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Server unwrap got status: " + + serverResult.getStatus()); + } else if (serverResult.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_TASK) { + throw new SSLException("Server unwrap expected NEED_TASK, got: " + + serverResult.getHandshakeStatus()); + } + runDelegatedTasks(serverResult, engine); + if (engine.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_WRAP) { + throw new SSLException("Expected NEED_WRAP, got: " + + engine.getHandshakeStatus()); + } + + // Generate a TLS record with the ServerHello + serverResult = engine.wrap(serverOut, sTOc); + log("client wrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + serverResult.getStatus()); + } + sTOc.flip(); + System.out.println(dumpHexBytes(sTOc)); + checkServerHello(sTOc, false, true); + + // Flip the client hello so we can reuse it in the next test. + cHelloStaple.flip(); + + // Test with the server-side enable property set to false + System.out.println("========================================="); + System.out.println("Server Test 2: " + + "jdk.tls.server.enableStatusRequestExtension = false"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.server.enableStatusRequestExtension", + "false"); + SSLContext ctxNoStaple = SSLContext.getInstance("TLS"); + ctxNoStaple.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + engine = ctxNoStaple.createSSLEngine(); + engine.setUseClientMode(false); + session = engine.getSession(); + serverIn = ByteBuffer.allocate(session.getApplicationBufferSize() + 50); + sTOc = ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Consume the client hello + serverResult = engine.unwrap(cHelloStaple, serverIn); + log("server unwrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Server unwrap got status: " + + serverResult.getStatus()); + } else if (serverResult.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_TASK) { + throw new SSLException("Server unwrap expected NEED_TASK, got: " + + serverResult.getHandshakeStatus()); + } + runDelegatedTasks(serverResult, engine); + if (engine.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_WRAP) { + throw new SSLException("Expected NEED_WRAP, got: " + + engine.getHandshakeStatus()); + } + + // Generate a TLS record with the ServerHello + serverResult = engine.wrap(serverOut, sTOc); + log("client wrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + serverResult.getStatus()); + } + sTOc.flip(); + System.out.println(dumpHexBytes(sTOc)); + checkServerHello(sTOc, false, false); + } + + /* + * If the result indicates that we have outstanding tasks to do, + * go ahead and run them in this thread. + */ + private static void runDelegatedTasks(SSLEngineResult result, + SSLEngine engine) throws Exception { + + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + log("\trunning delegated task..."); + runnable.run(); + } + HandshakeStatus hsStatus = engine.getHandshakeStatus(); + if (hsStatus == HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + log("\tnew HandshakeStatus: " + hsStatus); + } + } + + private static void log(String str, SSLEngineResult result) { + if (!logging) { + return; + } + HandshakeStatus hsStatus = result.getHandshakeStatus(); + log(str + + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + log("\t...ready for application data"); + } + } + + private static void log(String str) { + if (logging) { + System.out.println(str); + } + } + + /** + * Dump a ByteBuffer as a hexdump to stdout. The dumping routine will + * start at the current position of the buffer and run to its limit. + * After completing the dump, the position will be returned to its + * starting point. + * + * @param data the ByteBuffer to dump to stdout. + * + * @return the hexdump of the byte array. + */ + private static String dumpHexBytes(ByteBuffer data) { + StringBuilder sb = new StringBuilder(); + if (data != null) { + int i = 0; + data.mark(); + while (data.hasRemaining()) { + if (i % 16 == 0 && i != 0) { + sb.append("\n"); + } + sb.append(String.format("%02X ", data.get())); + i++; + } + data.reset(); + } + + return sb.toString(); + } + + /** + * Tests the ClientHello for the presence (or not) of the status_request + * and status_request_v2 hello extensions. It is assumed that the provided + * ByteBuffer has its position set at the first byte of the TLS record + * containing the ClientHello and contains the entire hello message. Upon + * successful completion of this method the ByteBuffer will have its + * position reset to the initial offset in the buffer. If an exception is + * thrown the position at the time of the exception will be preserved. + * + * @param data the ByteBuffer containing the ClientHello bytes + * @param statReqPresent true if the status_request hello extension should + * be present. + * @param statReqV2Present true if the status_request_v2 hello extension + * should be present. + * + * @throws SSLException if the presence or lack of either the + * status_request or status_request_v2 extensions is inconsistent with + * the expected settings in the statReqPresent or statReqV2Present + * parameters. + */ + private static void checkClientHello(ByteBuffer data, + boolean statReqPresent, boolean statReqV2Present) + throws SSLException { + boolean hasV1 = false; + boolean hasV2 = false; + Objects.requireNonNull(data); + data.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(data.get()); + int ver_major = Byte.toUnsignedInt(data.get()); + int ver_minor = Byte.toUnsignedInt(data.get()); + int recLen = Short.toUnsignedInt(data.getShort()); + + // Simple sanity checks + if (type != 22) { + throw new SSLException("Not a handshake: Type = " + type); + } else if (recLen > data.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + ", Remaining = " + + data.remaining()); + } + + // Grab the handshake message header. + int msgHdr = data.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + + // More simple sanity checks + if (msgType != 1) { + throw new SSLException("Not a ClientHello: Type = " + msgType); + } + + // Skip over the protocol version and client random + data.position(data.position() + 34); + + // Jump past the session ID (if there is one) + int sessLen = Byte.toUnsignedInt(data.get()); + if (sessLen != 0) { + data.position(data.position() + sessLen); + } + + // Jump past the cipher suites + int csLen = Short.toUnsignedInt(data.getShort()); + if (csLen != 0) { + data.position(data.position() + csLen); + } + + // ...and the compression + int compLen = Byte.toUnsignedInt(data.get()); + if (compLen != 0) { + data.position(data.position() + compLen); + } + + // Now for the fun part. Go through the extensions and look + // for the two status request exts. + int extsLen = Short.toUnsignedInt(data.getShort()); + while (data.hasRemaining()) { + int extType = Short.toUnsignedInt(data.getShort()); + int extLen = Short.toUnsignedInt(data.getShort()); + hasV1 |= (extType == HELLO_EXT_STATUS_REQ); + hasV2 |= (extType == HELLO_EXT_STATUS_REQ_V2); + data.position(data.position() + extLen); + } + + if (hasV1 != statReqPresent) { + throw new SSLException("The status_request extension is " + + "inconsistent with the expected result: expected = " + + statReqPresent + ", actual = " + hasV1); + } else if (hasV2 != statReqV2Present) { + throw new SSLException("The status_request_v2 extension is " + + "inconsistent with the expected result: expected = " + + statReqV2Present + ", actual = " + hasV2); + } + + // We should be at the end of the ClientHello + data.reset(); + } + + /** + * Tests the ServerHello for the presence (or not) of the status_request + * or status_request_v2 hello extension. It is assumed that the provided + * ByteBuffer has its position set at the first byte of the TLS record + * containing the ServerHello and contains the entire hello message. Upon + * successful completion of this method the ByteBuffer will have its + * position reset to the initial offset in the buffer. If an exception is + * thrown the position at the time of the exception will be preserved. + * + * @param statReqPresent true if the status_request hello extension should + * be present. + * @param statReqV2Present true if the status_request_v2 hello extension + * should be present. + * + * @throws SSLException if the presence or lack of either the + * status_request or status_request_v2 extensions is inconsistent with + * the expected settings in the statReqPresent or statReqV2Present + * parameters. + */ + private static void checkServerHello(ByteBuffer data, + boolean statReqPresent, boolean statReqV2Present) + throws SSLException { + boolean hasV1 = false; + boolean hasV2 = false; + Objects.requireNonNull(data); + int startPos = data.position(); + data.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(data.get()); + int ver_major = Byte.toUnsignedInt(data.get()); + int ver_minor = Byte.toUnsignedInt(data.get()); + int recLen = Short.toUnsignedInt(data.getShort()); + + // Simple sanity checks + if (type != 22) { + throw new SSLException("Not a handshake: Type = " + type); + } else if (recLen > data.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + ", Remaining = " + + data.remaining()); + } + + // Grab the handshake message header. + int msgHdr = data.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + + // More simple sanity checks + if (msgType != 2) { + throw new SSLException("Not a ServerHello: Type = " + msgType); + } + + // Skip over the protocol version and server random + data.position(data.position() + 34); + + // Jump past the session ID + int sessLen = Byte.toUnsignedInt(data.get()); + if (sessLen != 0) { + data.position(data.position() + sessLen); + } + + // Skip the cipher suite and compression method + data.position(data.position() + 3); + + // Go through the extensions and look for the request extension + // expected by the caller. + int extsLen = Short.toUnsignedInt(data.getShort()); + while (data.position() < recLen + startPos + 5) { + int extType = Short.toUnsignedInt(data.getShort()); + int extLen = Short.toUnsignedInt(data.getShort()); + hasV1 |= (extType == HELLO_EXT_STATUS_REQ); + hasV2 |= (extType == HELLO_EXT_STATUS_REQ_V2); + data.position(data.position() + extLen); + } + + if (hasV1 != statReqPresent) { + throw new SSLException("The status_request extension is " + + "inconsistent with the expected result: expected = " + + statReqPresent + ", actual = " + hasV1); + } else if (hasV2 != statReqV2Present) { + throw new SSLException("The status_request_v2 extension is " + + "inconsistent with the expected result: expected = " + + statReqV2Present + ", actual = " + hasV2); + } + + // Reset the position to the initial spot at the start of this method. + data.reset(); + } + + /** + * Creates the PKI components necessary for this test, including + * Root CA, Intermediate CA and SSL server certificates, the keystores + * for each entity, a client trust store, and starts the OCSP responders. + */ + private static void createPKI() throws Exception { + CertificateBuilder cbld = new CertificateBuilder(); + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(2048); + KeyStore.Builder keyStoreBuilder = + KeyStore.Builder.newInstance("PKCS12", null, + new KeyStore.PasswordProtection(passwd.toCharArray())); + + // Generate Root, IntCA, EE keys + KeyPair rootCaKP = keyGen.genKeyPair(); + log("Generated Root CA KeyPair"); + KeyPair intCaKP = keyGen.genKeyPair(); + log("Generated Intermediate CA KeyPair"); + KeyPair sslKP = keyGen.genKeyPair(); + log("Generated SSL Cert KeyPair"); + + // Set up the Root CA Cert + cbld.setSubjectName("CN=Root CA Cert, O=SomeCompany"); + cbld.setPublicKey(rootCaKP.getPublic()); + cbld.setSerialNumber(new BigInteger("1")); + // Make a 3 year validity starting from 60 days ago + long start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60); + long end = start + TimeUnit.DAYS.toMillis(1085); + cbld.setValidity(new Date(start), new Date(end)); + addCommonExts(cbld, rootCaKP.getPublic(), rootCaKP.getPublic()); + addCommonCAExts(cbld); + // Make our Root CA Cert! + X509Certificate rootCert = cbld.build(null, rootCaKP.getPrivate(), + "SHA256withRSA"); + log("Root CA Created:\n" + certInfo(rootCert)); + + // Now build a keystore and add the keys and cert + rootKeystore = keyStoreBuilder.getKeyStore(); + java.security.cert.Certificate[] rootChain = {rootCert}; + rootKeystore.setKeyEntry(ROOT_ALIAS, rootCaKP.getPrivate(), + passwd.toCharArray(), rootChain); + + // Now fire up the OCSP responder + rootOcsp = new SimpleOCSPServer(rootKeystore, passwd, ROOT_ALIAS, null); + rootOcsp.enableLog(logging); + rootOcsp.setNextUpdateInterval(3600); + rootOcsp.start(); + Thread.sleep(1000); // Give the server a second to start up + rootOcspPort = rootOcsp.getPort(); + String rootRespURI = "http://localhost:" + rootOcspPort; + log("Root OCSP Responder URI is " + rootRespURI); + + // Now that we have the root keystore and OCSP responder we can + // create our intermediate CA. + cbld.reset(); + cbld.setSubjectName("CN=Intermediate CA Cert, O=SomeCompany"); + cbld.setPublicKey(intCaKP.getPublic()); + cbld.setSerialNumber(new BigInteger("100")); + // Make a 2 year validity starting from 30 days ago + start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30); + end = start + TimeUnit.DAYS.toMillis(730); + cbld.setValidity(new Date(start), new Date(end)); + addCommonExts(cbld, intCaKP.getPublic(), rootCaKP.getPublic()); + addCommonCAExts(cbld); + cbld.addAIAExt(Collections.singletonList(rootRespURI)); + // Make our Intermediate CA Cert! + X509Certificate intCaCert = cbld.build(rootCert, rootCaKP.getPrivate(), + "SHA256withRSA"); + log("Intermediate CA Created:\n" + certInfo(intCaCert)); + + // Provide intermediate CA cert revocation info to the Root CA + // OCSP responder. + Map revInfo = + new HashMap<>(); + revInfo.put(intCaCert.getSerialNumber(), + new SimpleOCSPServer.CertStatusInfo( + SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD)); + rootOcsp.updateStatusDb(revInfo); + + // Now build a keystore and add the keys, chain and root cert as a TA + intKeystore = keyStoreBuilder.getKeyStore(); + java.security.cert.Certificate[] intChain = {intCaCert, rootCert}; + intKeystore.setKeyEntry(INT_ALIAS, intCaKP.getPrivate(), + passwd.toCharArray(), intChain); + intKeystore.setCertificateEntry(ROOT_ALIAS, rootCert); + + // Now fire up the Intermediate CA OCSP responder + intOcsp = new SimpleOCSPServer(intKeystore, passwd, + INT_ALIAS, null); + intOcsp.enableLog(logging); + intOcsp.setNextUpdateInterval(3600); + intOcsp.start(); + Thread.sleep(1000); + intOcspPort = intOcsp.getPort(); + String intCaRespURI = "http://localhost:" + intOcspPort; + log("Intermediate CA OCSP Responder URI is " + intCaRespURI); + + // Last but not least, let's make our SSLCert and add it to its own + // Keystore + cbld.reset(); + cbld.setSubjectName("CN=SSLCertificate, O=SomeCompany"); + cbld.setPublicKey(sslKP.getPublic()); + cbld.setSerialNumber(new BigInteger("4096")); + // Make a 1 year validity starting from 7 days ago + start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7); + end = start + TimeUnit.DAYS.toMillis(365); + cbld.setValidity(new Date(start), new Date(end)); + + // Add extensions + addCommonExts(cbld, sslKP.getPublic(), intCaKP.getPublic()); + boolean[] kuBits = {true, false, true, false, false, false, + false, false, false}; + cbld.addKeyUsageExt(kuBits); + List ekuOids = new ArrayList<>(); + ekuOids.add("1.3.6.1.5.5.7.3.1"); + ekuOids.add("1.3.6.1.5.5.7.3.2"); + cbld.addExtendedKeyUsageExt(ekuOids); + cbld.addSubjectAltNameDNSExt(Collections.singletonList("localhost")); + cbld.addAIAExt(Collections.singletonList(intCaRespURI)); + // Make our SSL Server Cert! + X509Certificate sslCert = cbld.build(intCaCert, intCaKP.getPrivate(), + "SHA256withRSA"); + log("SSL Certificate Created:\n" + certInfo(sslCert)); + + // Provide SSL server cert revocation info to the Intermeidate CA + // OCSP responder. + revInfo = new HashMap<>(); + revInfo.put(sslCert.getSerialNumber(), + new SimpleOCSPServer.CertStatusInfo( + SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD)); + intOcsp.updateStatusDb(revInfo); + + // Now build a keystore and add the keys, chain and root cert as a TA + serverKeystore = keyStoreBuilder.getKeyStore(); + java.security.cert.Certificate[] sslChain = {sslCert, intCaCert, rootCert}; + serverKeystore.setKeyEntry(SSL_ALIAS, sslKP.getPrivate(), + passwd.toCharArray(), sslChain); + serverKeystore.setCertificateEntry(ROOT_ALIAS, rootCert); + + // And finally a Trust Store for the client + trustStore = keyStoreBuilder.getKeyStore(); + trustStore.setCertificateEntry(ROOT_ALIAS, rootCert); + } + + private static void addCommonExts(CertificateBuilder cbld, + PublicKey subjKey, PublicKey authKey) throws IOException { + cbld.addSubjectKeyIdExt(subjKey); + cbld.addAuthorityKeyIdExt(authKey); + } + + private static void addCommonCAExts(CertificateBuilder cbld) + throws IOException { + cbld.addBasicConstraintsExt(true, true, -1); + // Set key usage bits for digitalSignature, keyCertSign and cRLSign + boolean[] kuBitSettings = {true, false, false, false, false, true, + true, false, false}; + cbld.addKeyUsageExt(kuBitSettings); + } + + /** + * Helper routine that dumps only a few cert fields rather than + * the whole toString() output. + * + * @param cert an X509Certificate to be displayed + * + * @return the String output of the issuer, subject and + * serial number + */ + private static String certInfo(X509Certificate cert) { + StringBuilder sb = new StringBuilder(); + sb.append("Issuer: ").append(cert.getIssuerX500Principal()). + append("\n"); + sb.append("Subject: ").append(cert.getSubjectX500Principal()). + append("\n"); + sb.append("Serial: ").append(cert.getSerialNumber()).append("\n"); + return sb.toString(); + } +} From 39cfbc6593a4048772a438e2a468b7f312acfee5 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Fri, 26 Feb 2016 09:55:14 +0800 Subject: [PATCH 134/311] 8150608: Mark BashStreams.java as intermittently failing and put to ProblemList Reviewed-by: bpb, rriggs --- jdk/test/ProblemList.txt | 3 +++ jdk/test/java/nio/charset/coders/BashStreams.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5b07bb2d65f..8e1c6a6a1e1 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -200,6 +200,9 @@ java/nio/channels/Selector/OutOfBand.java macosx-all java/nio/file/WatchService/Basic.java solaris-all java/nio/file/WatchService/LotsOfEvents.java solaris-all +# 8149712 +java/nio/charset/coders/BashStreams.java generic-all + ############################################################################ # jdk_rmi diff --git a/jdk/test/java/nio/charset/coders/BashStreams.java b/jdk/test/java/nio/charset/coders/BashStreams.java index 15ea14c3ddf..1658021210b 100644 --- a/jdk/test/java/nio/charset/coders/BashStreams.java +++ b/jdk/test/java/nio/charset/coders/BashStreams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 * @summary Stochastic test of charset-based streams - * @key randomness + * @key randomness intermittent */ import java.io.*; From 2435cd24eff54a88739986a6133ff7af1085140c Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 26 Feb 2016 06:03:12 +0100 Subject: [PATCH 135/311] 8150497: 32 jshell tests failed on Windows 32 bit Reviewed-by: darcy, tbell --- jdk/make/lib/Lib-jdk.jdi.gmk | 1 + jdk/make/lib/Lib-jdk.jdwp.agent.gmk | 1 + jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c | 2 +- .../jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/jdk/make/lib/Lib-jdk.jdi.gmk b/jdk/make/lib/Lib-jdk.jdi.gmk index bb1edfd1c23..f74b1c209a6 100644 --- a/jdk/make/lib/Lib-jdk.jdi.gmk +++ b/jdk/make/lib/Lib-jdk.jdi.gmk @@ -47,6 +47,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows) CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ $(LIBDT_SHMEM_CPPFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ + LDFLAGS_windows := -export:jdwpTransport_OnLoad, \ LIBS := $(JDKLIB_LIBS), \ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ RC_FLAGS := $(RC_FLAGS) \ diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk index 84c05ba6368..fb5de3e1f24 100644 --- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk @@ -46,6 +46,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBDT_SOCKET, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdt_socket/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ + LDFLAGS_windows := -export:jdwpTransport_OnLoad, \ LIBS_linux := -lpthread, \ LIBS_solaris := -lnsl -lsocket -lc, \ LIBS_windows := $(JDKLIB_LIBS) ws2_32.lib, \ diff --git a/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c b/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c index 1b42ad4d12c..81419a9d6a7 100644 --- a/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c +++ b/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c @@ -338,7 +338,7 @@ shmemGetLastError(jdwpTransportEnv* env, char **msgP) return JDWPTRANSPORT_ERROR_NONE; } -JNIEXPORT jint JNICALL +jint JNICALL jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr, jint version, jdwpTransportEnv** result) { diff --git a/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c b/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c index bcd21400ad2..9c86b5a2a27 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c @@ -784,7 +784,7 @@ socketTransport_getLastError(jdwpTransportEnv* env, char** msgP) { return JDWPTRANSPORT_ERROR_NONE; } -JNIEXPORT jint JNICALL +jint JNICALL jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr, jint version, jdwpTransportEnv** result) { From b9e4cabc43b60bda1413055ad382c368055bfcc5 Mon Sep 17 00:00:00 2001 From: Cheleswer Sahu Date: Fri, 26 Feb 2016 16:19:04 +0530 Subject: [PATCH 136/311] 8130425: libjvm crash due to stack overflow in executables with 32k tbss/tdata Reviewed-by: kevinw, dholmes --- .../java.base/share/classes/java/lang/ProcessHandleImpl.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java index e5fcb94d1b9..91fa5623174 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java @@ -81,9 +81,8 @@ final class ProcessHandleImpl implements ProcessHandle { ThreadGroup systemThreadGroup = tg; ThreadFactory threadFactory = grimReaper -> { - // Our thread stack requirement is quite modest. - Thread t = new Thread(systemThreadGroup, grimReaper, - "process reaper", 32768); + long stackSize = Boolean.getBoolean("jdk.lang.processReaperUseDefaultStackSize") ? 0 : 32768; + Thread t = new Thread(systemThreadGroup, grimReaper, "process reaper", stackSize); t.setDaemon(true); // A small attempt (probably futile) to avoid priority inversion t.setPriority(Thread.MAX_PRIORITY); From ae7478607aaae37e27c997f779694cda6d5e3ba9 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Fri, 26 Feb 2016 12:11:28 +0100 Subject: [PATCH 137/311] 8150533: Test java/util/logging/LogManagerAppContextDeadlock.java times out intermittently This is a test bug caused by a Logger being garbage collected too early. Reviewed-by: darcy --- .../java/util/logging/LogManagerAppContextDeadlock.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java b/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java index 2f1641f49e3..f54eb2a7a5c 100644 --- a/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java +++ b/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java @@ -141,6 +141,7 @@ public class LogManagerAppContextDeadlock { t1.setDaemon(true); t1.start(); Thread t2 = new Thread() { + public Object logger; public void run() { sem3.release(); try { @@ -151,7 +152,10 @@ public class LogManagerAppContextDeadlock { Thread.interrupted(); } System.out.println("Logger.getLogger(name).info(name)"); - Logger.getLogger(test.name());//.info(name); + // stick the logger in an instance variable to prevent it + // from being garbage collected before the main thread + // calls LogManager.getLogger() below. + logger = Logger.getLogger(test.name());//.info(name); System.out.println("Done: Logger.getLogger(name).info(name)"); } }; From 917dc3b87c2d3fa0608727085a42189479a24c7e Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 26 Feb 2016 13:02:30 +0100 Subject: [PATCH 138/311] 8140777: Make Adaptive IHOP logging information the same as JFR logging Reviewed-by: tbenson, jmasa --- hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp b/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp index 0cf5dab9448..5759ed0c68f 100644 --- a/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp +++ b/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -47,14 +47,16 @@ void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t allo void G1IHOPControl::print() { size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold(); - log_debug(gc, ihop)("Basic information (value update), threshold: " SIZE_FORMAT "B (%1.2f), target occupancy: " SIZE_FORMAT "B, current occupancy: " SIZE_FORMAT "B," - " recent old gen allocation rate: %1.2f, recent marking phase length: %1.2f", + log_debug(gc, ihop)("Basic information (value update), threshold: " SIZE_FORMAT "B (%1.2f), target occupancy: " SIZE_FORMAT "B, current occupancy: " SIZE_FORMAT "B, " + "recent allocation size: " SIZE_FORMAT "B, recent allocation duration: %1.2fms, recent old gen allocation rate: %1.2fB/s, recent marking phase length: %1.2fms", cur_conc_mark_start_threshold, cur_conc_mark_start_threshold * 100.0 / _target_occupancy, _target_occupancy, G1CollectedHeap::heap()->used(), + _last_allocated_bytes, + _last_allocation_time_s * 1000.0, _last_allocation_time_s > 0.0 ? _last_allocated_bytes / _last_allocation_time_s : 0.0, - last_marking_length_s()); + last_marking_length_s() * 1000.0); } void G1IHOPControl::send_trace_event(G1NewTracer* tracer) { @@ -191,13 +193,16 @@ void G1AdaptiveIHOPControl::update_marking_length(double marking_length_s) { void G1AdaptiveIHOPControl::print() { G1IHOPControl::print(); size_t actual_target = actual_target_threshold(); - log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: " SIZE_FORMAT "B (%1.2f), internal target occupancy: " SIZE_FORMAT "B," - " predicted old gen allocation rate: %1.2f, predicted marking phase length: %1.2f, prediction active: %s", + log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: " SIZE_FORMAT "B (%1.2f), internal target occupancy: " SIZE_FORMAT "B, " + "occupancy: " SIZE_FORMAT "B, additional buffer size: " SIZE_FORMAT "B, predicted old gen allocation rate: %1.2fB/s, " + "predicted marking phase length: %1.2fms, prediction active: %s", get_conc_mark_start_threshold(), percent_of(get_conc_mark_start_threshold(), actual_target), actual_target, + G1CollectedHeap::heap()->used(), + _last_unrestrained_young_size, _predictor->get_new_prediction(&_allocation_rate_s), - _predictor->get_new_prediction(&_marking_times_s), + _predictor->get_new_prediction(&_marking_times_s) * 1000.0, have_enough_data_for_prediction() ? "true" : "false"); } From d00c7378d6fd9b41ae66fece438c1975bf1d835b Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 26 Feb 2016 13:02:30 +0100 Subject: [PATCH 139/311] 8076463: Add logging for the preserve CM referents task Add logging and do minor refactoring to CM referents handling task. Reviewed-by: jmasa --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 25 +++++++++++++------ .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 3 +++ hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp | 6 ++++- hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp | 9 ++++++- hotspot/test/gc/g1/TestGCLogMessages.java | 6 +++-- 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index f241d749045..860df5306a5 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -4398,6 +4398,8 @@ public: { } void work(uint worker_id) { + G1GCParPhaseTimesTracker x(_g1h->g1_policy()->phase_times(), G1GCPhaseTimes::PreserveCMReferents, worker_id); + ResourceMark rm; HandleMark hm; @@ -4461,13 +4463,8 @@ void G1CollectedHeap::process_weak_jni_handles() { g1_policy()->phase_times()->record_ref_proc_time(ref_proc_time * 1000.0); } -// Weak Reference processing during an evacuation pause (part 1). -void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) { - double ref_proc_start = os::elapsedTime(); - - ReferenceProcessor* rp = _ref_processor_stw; - assert(rp->discovery_enabled(), "should have been enabled"); - +void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states) { + double preserve_cm_referents_start = os::elapsedTime(); // Any reference objects, in the collection set, that were 'discovered' // by the CM ref processor should have already been copied (either by // applying the external root copy closure to the discovered lists, or @@ -4495,9 +4492,18 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per per_thread_states, no_of_gc_workers, _task_queues); - workers()->run_task(&keep_cm_referents); + g1_policy()->phase_times()->record_preserve_cm_referents_time_ms((os::elapsedTime() - preserve_cm_referents_start) * 1000.0); +} + +// Weak Reference processing during an evacuation pause (part 1). +void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) { + double ref_proc_start = os::elapsedTime(); + + ReferenceProcessor* rp = _ref_processor_stw; + assert(rp->discovery_enabled(), "should have been enabled"); + // Closure to test whether a referent is alive. G1STWIsAliveClosure is_alive(this); @@ -4529,6 +4535,8 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per NULL, _gc_timer_stw); } else { + uint no_of_gc_workers = workers()->active_workers(); + // Parallel reference processing assert(rp->num_q() == no_of_gc_workers, "sanity"); assert(no_of_gc_workers <= rp->max_num_q(), "sanity"); @@ -4644,6 +4652,7 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in // objects (and their reachable sub-graphs) that were // not copied during the pause. if (g1_policy()->should_process_references()) { + preserve_cm_referents(per_thread_states); process_discovered_references(per_thread_states); } else { ref_processor_stw()->verify_no_references_recorded(); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 3d8badc27bb..f381ee5b7db 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -511,6 +511,9 @@ protected: // allocated block, or else "NULL". HeapWord* expand_and_allocate(size_t word_size, AllocationContext_t context); + // Preserve any referents discovered by concurrent marking that have not yet been + // copied by the STW pause. + void preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states); // Process any reference objects discovered during // an incremental evacuation pause. void process_discovered_references(G1ParScanThreadStateSet* per_thread_states); diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index 706495fdbc7..8fefab03f65 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -129,6 +129,8 @@ G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty:", true, 3); _redirtied_cards = new WorkerDataArray(max_gc_threads, "Redirtied Cards:", true, 3); _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards); + + _gc_par_phases[PreserveCMReferents] = new WorkerDataArray(max_gc_threads, "Parallel Preserve CM Refs:", true, 3); } void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { @@ -392,10 +394,12 @@ void G1GCPhaseTimes::print() { print_stats(Indents[2], "Choose CSet", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); + print_stats(Indents[2], "Preserve CM Refs", _recorded_preserve_cm_referents_time_ms); print_stats(Indents[2], "Ref Proc", _cur_ref_proc_time_ms); print_stats(Indents[2], "Ref Enq", _cur_ref_enq_time_ms); print_stats(Indents[2], "Redirty Cards", _recorded_redirty_logged_cards_time_ms); par_phase_printer.print(RedirtyCards); + par_phase_printer.print(PreserveCMReferents); if (G1EagerReclaimHumongousObjects) { print_stats(Indents[2], "Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp index 5607c3f4ea0..a4e6ff1dec5 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -69,6 +69,7 @@ class G1GCPhaseTimes : public CHeapObj { StringDedupQueueFixup, StringDedupTableFixup, RedirtyCards, + PreserveCMReferents, GCParPhasesSentinel }; @@ -108,6 +109,8 @@ class G1GCPhaseTimes : public CHeapObj { double _recorded_redirty_logged_cards_time_ms; + double _recorded_preserve_cm_referents_time_ms; + double _recorded_young_free_cset_time_ms; double _recorded_non_young_free_cset_time_ms; @@ -234,6 +237,10 @@ class G1GCPhaseTimes : public CHeapObj { _recorded_redirty_logged_cards_time_ms = time_ms; } + void record_preserve_cm_referents_time_ms(double time_ms) { + _recorded_preserve_cm_referents_time_ms = time_ms; + } + void record_cur_collection_start_sec(double time_ms) { _cur_collection_start_sec = time_ms; } diff --git a/hotspot/test/gc/g1/TestGCLogMessages.java b/hotspot/test/gc/g1/TestGCLogMessages.java index 8ab921b0186..c0f83fc1fe0 100644 --- a/hotspot/test/gc/g1/TestGCLogMessages.java +++ b/hotspot/test/gc/g1/TestGCLogMessages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 TestGCLogMessages - * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 + * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 8076463 * @summary Ensure the output for a minor GC with G1 * includes the expected necessary messages. * @key gc @@ -86,6 +86,8 @@ public class TestGCLogMessages { // Humongous Eager Reclaim new LogMessageWithLevel("Humongous Reclaim", Level.DEBUG), new LogMessageWithLevel("Humongous Register", Level.DEBUG), + // Preserve CM Referents + new LogMessageWithLevel("Preserve CM Refs", Level.DEBUG), }; void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { From 6fe8d6e7de9f68558d8350c12935eb28095bbec9 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 26 Feb 2016 13:02:30 +0100 Subject: [PATCH 140/311] 8150630: Add logging for ParScanThreadState merge phase Improve visibility of the per-thread scan state merge phase by adding appropriate logging. Reviewed-by: jmasa, tbenson --- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 8 +++++++- hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp | 3 +++ hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp | 1 + hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp | 6 ++++++ hotspot/test/gc/g1/TestGCLogMessages.java | 4 +++- 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 860df5306a5..6b1f7f0d389 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -4594,6 +4594,12 @@ void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0); } +void G1CollectedHeap::merge_per_thread_state_info(G1ParScanThreadStateSet* per_thread_states) { + double merge_pss_time_start = os::elapsedTime(); + per_thread_states->flush(); + g1_policy()->phase_times()->record_merge_pss_time_ms((os::elapsedTime() - merge_pss_time_start) * 1000.0); +} + void G1CollectedHeap::pre_evacuate_collection_set() { _expand_heap_after_alloc_failure = true; _evacuation_failed = false; @@ -4696,7 +4702,7 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in _allocator->release_gc_alloc_regions(evacuation_info); - per_thread_states->flush(); + merge_per_thread_state_info(per_thread_states); record_obj_copy_mem_stats(); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index f381ee5b7db..bce50eb7a5b 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -522,6 +522,9 @@ protected: // after processing. void enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states); + // Merges the information gathered on a per-thread basis for all worker threads + // during GC into global variables. + void merge_per_thread_state_info(G1ParScanThreadStateSet* per_thread_states); public: WorkGang* workers() const { return _workers; } diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index 8fefab03f65..e8c852b051f 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -413,6 +413,7 @@ void G1GCPhaseTimes::print() { _recorded_non_young_free_cset_time_ms)); log_trace(gc, phases)("%sYoung Free CSet: %.1lf ms", Indents[3], _recorded_young_free_cset_time_ms); log_trace(gc, phases)("%sNon-Young Free CSet: %.1lf ms", Indents[3], _recorded_non_young_free_cset_time_ms); + print_stats(Indents[2], "Merge Per-Thread State", _recorded_merge_pss_time_ms); if (_cur_verify_after_time_ms > 0.0) { print_stats(Indents[2], "Verify After", _cur_verify_after_time_ms); } diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp index a4e6ff1dec5..c474659a849 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp @@ -111,6 +111,8 @@ class G1GCPhaseTimes : public CHeapObj { double _recorded_preserve_cm_referents_time_ms; + double _recorded_merge_pss_time_ms; + double _recorded_young_free_cset_time_ms; double _recorded_non_young_free_cset_time_ms; @@ -241,6 +243,10 @@ class G1GCPhaseTimes : public CHeapObj { _recorded_preserve_cm_referents_time_ms = time_ms; } + void record_merge_pss_time_ms(double time_ms) { + _recorded_merge_pss_time_ms = time_ms; + } + void record_cur_collection_start_sec(double time_ms) { _cur_collection_start_sec = time_ms; } diff --git a/hotspot/test/gc/g1/TestGCLogMessages.java b/hotspot/test/gc/g1/TestGCLogMessages.java index c0f83fc1fe0..0659c98f1c9 100644 --- a/hotspot/test/gc/g1/TestGCLogMessages.java +++ b/hotspot/test/gc/g1/TestGCLogMessages.java @@ -23,7 +23,7 @@ /* * @test TestGCLogMessages - * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 8076463 + * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 8076463 8150630 * @summary Ensure the output for a minor GC with G1 * includes the expected necessary messages. * @key gc @@ -88,6 +88,8 @@ public class TestGCLogMessages { new LogMessageWithLevel("Humongous Register", Level.DEBUG), // Preserve CM Referents new LogMessageWithLevel("Preserve CM Refs", Level.DEBUG), + // Merge PSS + new LogMessageWithLevel("Merge Per-Thread State", Level.DEBUG), }; void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { From d090b747441eaec656cc785e165e61bda27bf037 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 26 Feb 2016 13:02:30 +0100 Subject: [PATCH 141/311] 8150629: Initializing all ParScanThreadStates causes significant unaccounted "Other" times Lazily allocate ParScanThreadStates within the worker threads instead of doing this work upfront serially. Reviewed-by: mgerdin, jmasa --- hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp | 9 ++++++++- hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp | 6 ++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp index f22c6e2195c..b59fc203c6c 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -327,6 +327,9 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, G1ParScanThreadState* G1ParScanThreadStateSet::state_for_worker(uint worker_id) { assert(worker_id < _n_workers, "out of bounds access"); + if (_states[worker_id] == NULL) { + _states[worker_id] = new_par_scan_state(worker_id, _young_cset_length); + } return _states[worker_id]; } @@ -352,6 +355,10 @@ void G1ParScanThreadStateSet::flush() { for (uint worker_index = 0; worker_index < _n_workers; ++worker_index) { G1ParScanThreadState* pss = _states[worker_index]; + if (pss == NULL) { + continue; + } + _total_cards_scanned += _cards_scanned[worker_index]; pss->flush(_surviving_young_words_total); diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp index 47c5328d2b9..6accb48c1de 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -200,6 +200,7 @@ class G1ParScanThreadStateSet : public StackObj { size_t* _surviving_young_words_total; size_t* _cards_scanned; size_t _total_cards_scanned; + size_t _young_cset_length; uint _n_workers; bool _flushed; @@ -210,10 +211,11 @@ class G1ParScanThreadStateSet : public StackObj { _surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, young_cset_length, mtGC)), _cards_scanned(NEW_C_HEAP_ARRAY(size_t, n_workers, mtGC)), _total_cards_scanned(0), + _young_cset_length(young_cset_length), _n_workers(n_workers), _flushed(false) { for (uint i = 0; i < n_workers; ++i) { - _states[i] = new_par_scan_state(i, young_cset_length); + _states[i] = NULL; } memset(_surviving_young_words_total, 0, young_cset_length * sizeof(size_t)); memset(_cards_scanned, 0, n_workers * sizeof(size_t)); From 8cc9a5146bd92919ef836da698a5c75aa0c99efe Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Fri, 26 Feb 2016 13:21:28 +0100 Subject: [PATCH 142/311] 8150727: [JVMCI] add LoadLoad to the implicit memory barriers on AMD64 Reviewed-by: rschatz, twisti --- .../classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java index 37393ff08bc..972aea94231 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java @@ -22,6 +22,7 @@ */ package jdk.vm.ci.amd64; +import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD; import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; import static jdk.vm.ci.code.Register.SPECIAL; @@ -220,7 +221,7 @@ public class AMD64 extends Architecture { private final AMD64Kind largestKind; public AMD64(EnumSet features, EnumSet flags) { - super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, 8); + super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8); this.features = features; this.flags = flags; assert features.contains(CPUFeature.SSE2) : "minimum config for x64"; From 62c5bdbe9de1c89cc28184badcc50cfe888c1185 Mon Sep 17 00:00:00 2001 From: Andreas Eriksson Date: Fri, 26 Feb 2016 16:28:42 +0100 Subject: [PATCH 143/311] 8144732: VM_HeapDumper hits assert with bad dump_len Reviewed-by: dsamersoff --- hotspot/src/share/vm/runtime/arguments.cpp | 1 + hotspot/src/share/vm/runtime/globals.hpp | 4 - hotspot/src/share/vm/services/heapDumper.cpp | 256 +++++++++++-------- 3 files changed, 149 insertions(+), 112 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 512c29fc94d..322516b9ef4 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -372,6 +372,7 @@ static SpecialFlag const special_jvm_flags[] = { { "PreInflateSpin", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "JNIDetachReleasesMonitors", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "UseAltSigs", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "SegmentedHeapDumpThreshold", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS { "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() }, diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 3c6219a4402..848bb5d2607 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1055,10 +1055,6 @@ public: "directory) of the dump file (defaults to java_pid.hprof " \ "in the working directory)") \ \ - develop(size_t, SegmentedHeapDumpThreshold, 2*G, \ - "Generate a segmented heap dump (JAVA PROFILE 1.0.2 format) " \ - "when the heap usage is larger than this") \ - \ develop(size_t, HeapDumpSegmentSize, 1*G, \ "Approximate segment size when generating a segmented heap dump") \ \ diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index 2f01fab4cc9..986855894d2 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -53,8 +53,7 @@ * src/share/demo/jvmti/hprof/hprof_io.c * * - * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" - * (0-terminated) + * header "JAVA PROFILE 1.0.2" (0-terminated) * * u4 size of identifiers. Identifiers are used to represent * UTF8 strings, objects, stack traces, etc. They usually @@ -385,6 +384,8 @@ class DumpWriter : public StackObj { size_t _size; size_t _pos; + jlong _dump_start; + char* _error; // error message when I/O fails void set_file_descriptor(int fd) { _fd = fd; } @@ -408,6 +409,10 @@ class DumpWriter : public StackObj { bool is_open() const { return file_descriptor() >= 0; } void flush(); + jlong dump_start() const { return _dump_start; } + void set_dump_start(jlong pos); + julong current_record_length(); + // total number of bytes written to the disk julong bytes_written() const { return _bytes_written; } @@ -449,6 +454,7 @@ DumpWriter::DumpWriter(const char* path) { _pos = 0; _error = NULL; _bytes_written = 0L; + _dump_start = (jlong)-1; _fd = os::create_binary_file(path, false); // don't replace existing file // if the open failed we record the error @@ -476,6 +482,22 @@ void DumpWriter::close() { } } +// sets the dump starting position +void DumpWriter::set_dump_start(jlong pos) { + _dump_start = pos; +} + +julong DumpWriter::current_record_length() { + if (is_open()) { + // calculate the size of the dump record + julong dump_end = bytes_written() + bytes_unwritten(); + assert(dump_end == (size_t)current_offset(), "checking"); + julong dump_len = dump_end - dump_start() - 4; + return dump_len; + } + return 0; +} + // write directly to the file void DumpWriter::write_internal(void* s, size_t len) { if (is_open()) { @@ -645,6 +667,18 @@ class DumperSupport : AllStatic { static void dump_prim_array(DumpWriter* writer, typeArrayOop array); // create HPROF_FRAME record for the given method and bci static void dump_stack_frame(DumpWriter* writer, int frame_serial_num, int class_serial_num, Method* m, int bci); + + // check if we need to truncate an array + static int calculate_array_max_length(DumpWriter* writer, arrayOop array, short header_size); + + // writes a HPROF_HEAP_DUMP_SEGMENT record + static void write_dump_header(DumpWriter* writer); + + // fixes up the length of the current dump record + static void write_current_dump_record_length(DumpWriter* writer); + + // fixes up the current dump record and writes HPROF_HEAP_DUMP_END record + static void end_of_dump(DumpWriter* writer); }; // write a header of the given type @@ -1005,50 +1039,102 @@ void DumperSupport::dump_basic_type_array_class(DumpWriter* writer, Klass* k) { } } +// Hprof uses an u4 as record length field, +// which means we need to truncate arrays that are too long. +int DumperSupport::calculate_array_max_length(DumpWriter* writer, arrayOop array, short header_size) { + BasicType type = ArrayKlass::cast(array->klass())->element_type(); + assert(type >= T_BOOLEAN && type <= T_OBJECT, "invalid array element type"); + + int length = array->length(); + + int type_size; + if (type == T_OBJECT) { + type_size = sizeof(address); + } else { + type_size = type2aelembytes(type); + } + + size_t length_in_bytes = (size_t)length * type_size; + + // Create a new record if the current record is non-empty and the array can't fit. + julong current_record_length = writer->current_record_length(); + if (current_record_length > 0 && + (current_record_length + header_size + length_in_bytes) > max_juint) { + write_current_dump_record_length(writer); + write_dump_header(writer); + + // We now have an empty record. + current_record_length = 0; + } + + // Calculate max bytes we can use. + uint max_bytes = max_juint - (header_size + current_record_length); + + // Array too long for the record? + // Calculate max length and return it. + if (length_in_bytes > max_bytes) { + length = max_bytes / type_size; + length_in_bytes = (size_t)length * type_size; + + warning("cannot dump array of type %s[] with length %d; truncating to length %d", + type2name_tab[type], array->length(), length); + } + return length; +} + // creates HPROF_GC_OBJ_ARRAY_DUMP record for the given object array void DumperSupport::dump_object_array(DumpWriter* writer, objArrayOop array) { + // sizeof(u1) + 2 * sizeof(u4) + sizeof(objectID) + sizeof(classID) + short header_size = 1 + 2 * 4 + 2 * sizeof(address); + + int length = calculate_array_max_length(writer, array, header_size); writer->write_u1(HPROF_GC_OBJ_ARRAY_DUMP); writer->write_objectID(array); writer->write_u4(STACK_TRACE_ID); - writer->write_u4((u4)array->length()); + writer->write_u4(length); // array class ID writer->write_classID(array->klass()); // [id]* elements - for (int index=0; indexlength(); index++) { + for (int index = 0; index < length; index++) { oop o = array->obj_at(index); writer->write_objectID(o); } } -#define WRITE_ARRAY(Array, Type, Size) \ - for (int i=0; ilength(); i++) { writer->write_##Size((Size)array->Type##_at(i)); } - +#define WRITE_ARRAY(Array, Type, Size, Length) \ + for (int i = 0; i < Length; i++) { writer->write_##Size((Size)Array->Type##_at(i)); } // creates HPROF_GC_PRIM_ARRAY_DUMP record for the given type array void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { BasicType type = TypeArrayKlass::cast(array->klass())->element_type(); + // 2 * sizeof(u1) + 2 * sizeof(u4) + sizeof(objectID) + short header_size = 2 * 1 + 2 * 4 + sizeof(address); + + int length = calculate_array_max_length(writer, array, header_size); + int type_size = type2aelembytes(type); + u4 length_in_bytes = (u4)length * type_size; + writer->write_u1(HPROF_GC_PRIM_ARRAY_DUMP); writer->write_objectID(array); writer->write_u4(STACK_TRACE_ID); - writer->write_u4((u4)array->length()); + writer->write_u4(length); writer->write_u1(type2tag(type)); // nothing to copy - if (array->length() == 0) { + if (length == 0) { return; } // If the byte ordering is big endian then we can copy most types directly - u4 length_in_bytes = (u4)array->length() * type2aelembytes(type); switch (type) { case T_INT : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, int, u4); + WRITE_ARRAY(array, int, u4, length); } else { writer->write_raw((void*)(array->int_at_addr(0)), length_in_bytes); } @@ -1060,7 +1146,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { } case T_CHAR : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, char, u2); + WRITE_ARRAY(array, char, u2, length); } else { writer->write_raw((void*)(array->char_at_addr(0)), length_in_bytes); } @@ -1068,7 +1154,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { } case T_SHORT : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, short, u2); + WRITE_ARRAY(array, short, u2, length); } else { writer->write_raw((void*)(array->short_at_addr(0)), length_in_bytes); } @@ -1076,7 +1162,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { } case T_BOOLEAN : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, bool, u1); + WRITE_ARRAY(array, bool, u1, length); } else { writer->write_raw((void*)(array->bool_at_addr(0)), length_in_bytes); } @@ -1084,7 +1170,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { } case T_LONG : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, long, u8); + WRITE_ARRAY(array, long, u8, length); } else { writer->write_raw((void*)(array->long_at_addr(0)), length_in_bytes); } @@ -1096,14 +1182,14 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { // use IEEE 754. case T_FLOAT : { - for (int i=0; ilength(); i++) { - dump_float( writer, array->float_at(i) ); + for (int i = 0; i < length; i++) { + dump_float(writer, array->float_at(i)); } break; } case T_DOUBLE : { - for (int i=0; ilength(); i++) { - dump_double( writer, array->double_at(i) ); + for (int i = 0; i < length; i++) { + dump_double(writer, array->double_at(i)); } break; } @@ -1320,8 +1406,6 @@ class VM_HeapDumper : public VM_GC_Operation { JavaThread* _oome_thread; Method* _oome_constructor; bool _gc_before_heap_dump; - bool _is_segmented_dump; - jlong _dump_start; GrowableArray* _klass_map; ThreadStackTrace** _stack_traces; int _num_threads; @@ -1340,11 +1424,6 @@ class VM_HeapDumper : public VM_GC_Operation { void clear_global_dumper() { _global_dumper = NULL; } void clear_global_writer() { _global_writer = NULL; } - bool is_segmented_dump() const { return _is_segmented_dump; } - void set_segmented_dump() { _is_segmented_dump = true; } - jlong dump_start() const { return _dump_start; } - void set_dump_start(jlong pos); - bool skip_operation() const; // writes a HPROF_LOAD_CLASS record @@ -1369,16 +1448,6 @@ class VM_HeapDumper : public VM_GC_Operation { // HPROF_TRACE and HPROF_FRAME records void dump_stack_traces(); - // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record - void write_dump_header(); - - // fixes up the length of the current dump record - void write_current_dump_record_length(); - - // fixes up the current dump record )and writes HPROF_HEAP_DUMP_END - // record in the case of a segmented heap dump) - void end_of_dump(); - public: VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump, bool oome) : VM_GC_Operation(0 /* total collections, dummy, ignored */, @@ -1387,8 +1456,6 @@ class VM_HeapDumper : public VM_GC_Operation { gc_before_heap_dump) { _local_writer = writer; _gc_before_heap_dump = gc_before_heap_dump; - _is_segmented_dump = false; - _dump_start = (jlong)-1; _klass_map = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_CLASS_COUNT, true); _stack_traces = NULL; _num_threads = 0; @@ -1428,35 +1495,23 @@ bool VM_HeapDumper::skip_operation() const { return false; } -// sets the dump starting position -void VM_HeapDumper::set_dump_start(jlong pos) { - _dump_start = pos; -} - - // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record -void VM_HeapDumper::write_dump_header() { - if (writer()->is_open()) { - if (is_segmented_dump()) { - writer()->write_u1(HPROF_HEAP_DUMP_SEGMENT); - } else { - writer()->write_u1(HPROF_HEAP_DUMP); - } - writer()->write_u4(0); // current ticks + // writes a HPROF_HEAP_DUMP_SEGMENT record +void DumperSupport::write_dump_header(DumpWriter* writer) { + if (writer->is_open()) { + writer->write_u1(HPROF_HEAP_DUMP_SEGMENT); + writer->write_u4(0); // current ticks // record the starting position for the dump (its length will be fixed up later) - set_dump_start(writer()->current_offset()); - writer()->write_u4(0); + writer->set_dump_start(writer->current_offset()); + writer->write_u4(0); } } // fixes up the length of the current dump record -void VM_HeapDumper::write_current_dump_record_length() { - if (writer()->is_open()) { - assert(dump_start() >= 0, "no dump start recorded"); - - // calculate the size of the dump record - julong dump_end = writer()->current_offset(); - julong dump_len = (dump_end - dump_start() - 4); +void DumperSupport::write_current_dump_record_length(DumpWriter* writer) { + if (writer->is_open()) { + julong dump_end = writer->bytes_written() + writer->bytes_unwritten(); + julong dump_len = writer->current_record_length(); // record length must fit in a u4 if (dump_len > max_juint) { @@ -1464,17 +1519,18 @@ void VM_HeapDumper::write_current_dump_record_length() { } // seek to the dump start and fix-up the length - writer()->seek_to_offset(dump_start()); - writer()->write_u4((u4)dump_len); + assert(writer->dump_start() >= 0, "no dump start recorded"); + writer->seek_to_offset(writer->dump_start()); + writer->write_u4((u4)dump_len); // adjust the total size written to keep the bytes written correct. - writer()->adjust_bytes_written(-((jlong) sizeof(u4))); + writer->adjust_bytes_written(-((jlong) sizeof(u4))); // seek to dump end so we can continue - writer()->seek_to_offset(dump_end); + writer->seek_to_offset(dump_end); // no current dump record - set_dump_start((jlong)-1); + writer->set_dump_start((jlong)-1); } } @@ -1482,33 +1538,23 @@ void VM_HeapDumper::write_current_dump_record_length() { // new segment. void VM_HeapDumper::check_segment_length() { if (writer()->is_open()) { - if (is_segmented_dump()) { - // don't use current_offset that would be too expensive on a per record basis - julong dump_end = writer()->bytes_written() + writer()->bytes_unwritten(); - assert(dump_end == (julong)writer()->current_offset(), "checking"); - julong dump_len = (dump_end - dump_start() - 4); - assert(dump_len <= max_juint, "bad dump length"); + julong dump_len = writer()->current_record_length(); - if (dump_len > HeapDumpSegmentSize) { - write_current_dump_record_length(); - write_dump_header(); - } + if (dump_len > 2UL*G) { + DumperSupport::write_current_dump_record_length(writer()); + DumperSupport::write_dump_header(writer()); } } } -// fixes up the current dump record )and writes HPROF_HEAP_DUMP_END -// record in the case of a segmented heap dump) -void VM_HeapDumper::end_of_dump() { - if (writer()->is_open()) { - write_current_dump_record_length(); +// fixes up the current dump record and writes HPROF_HEAP_DUMP_END record +void DumperSupport::end_of_dump(DumpWriter* writer) { + if (writer->is_open()) { + write_current_dump_record_length(writer); - // for segmented dump we write the end record - if (is_segmented_dump()) { - writer()->write_u1(HPROF_HEAP_DUMP_END); - writer()->write_u4(0); - writer()->write_u4(0); - } + writer->write_u1(HPROF_HEAP_DUMP_END); + writer->write_u4(0); + writer->write_u4(0); } } @@ -1686,16 +1732,17 @@ void VM_HeapDumper::do_threads() { // [HPROF_LOAD_CLASS]* // [[HPROF_FRAME]*|HPROF_TRACE]* // [HPROF_GC_CLASS_DUMP]* -// HPROF_HEAP_DUMP +// [HPROF_HEAP_DUMP_SEGMENT]* +// HPROF_HEAP_DUMP_END // // The HPROF_TRACE records represent the stack traces where the heap dump // is generated and a "dummy trace" record which does not include // any frames. The dummy trace record is used to be referenced as the // unknown object alloc site. // -// The HPROF_HEAP_DUMP record has a length following by sub-records. To allow -// the heap dump be generated in a single pass we remember the position of -// the dump length and fix it up after all sub-records have been written. +// Each HPROF_HEAP_DUMP_SEGMENT record has a length followed by sub-records. +// To allow the heap dump be generated in a single pass we remember the position +// of the dump length and fix it up after all sub-records have been written. // To generate the sub-records we iterate over the heap, writing // HPROF_GC_INSTANCE_DUMP, HPROF_GC_OBJ_ARRAY_DUMP, and HPROF_GC_PRIM_ARRAY_DUMP // records as we go. Once that is done we write records for some of the GC @@ -1722,15 +1769,9 @@ void VM_HeapDumper::doit() { set_global_dumper(); set_global_writer(); - // Write the file header - use 1.0.2 for large heaps, otherwise 1.0.1 + // Write the file header - we always use 1.0.2 size_t used = ch->used(); - const char* header; - if (used > SegmentedHeapDumpThreshold) { - set_segmented_dump(); - header = "JAVA PROFILE 1.0.2"; - } else { - header = "JAVA PROFILE 1.0.1"; - } + const char* header = "JAVA PROFILE 1.0.2"; // header is few bytes long - no chance to overflow int writer()->write_raw((void*)header, (int)strlen(header)); @@ -1750,8 +1791,8 @@ void VM_HeapDumper::doit() { // this must be called after _klass_map is built when iterating the classes above. dump_stack_traces(); - // write HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT - write_dump_header(); + // write HPROF_HEAP_DUMP_SEGMENT + DumperSupport::write_dump_header(writer()); // Writes HPROF_GC_CLASS_DUMP records ClassLoaderDataGraph::classes_do(&do_class_dump); @@ -1759,9 +1800,9 @@ void VM_HeapDumper::doit() { check_segment_length(); // writes HPROF_GC_INSTANCE_DUMP records. - // After each sub-record is written check_segment_length will be invoked. When - // generated a segmented heap dump this allows us to check if the current - // segment exceeds a threshold and if so, then a new segment is started. + // After each sub-record is written check_segment_length will be invoked + // to check if the current segment exceeds a threshold. If so, a new + // segment is started. // The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk // of the heap dump. HeapObjectDumper obj_dumper(this, writer()); @@ -1785,9 +1826,8 @@ void VM_HeapDumper::doit() { StickyClassDumper class_dumper(writer()); SystemDictionary::always_strong_classes_do(&class_dumper); - // fixes up the length of the dump record. In the case of a segmented - // heap then the HPROF_HEAP_DUMP_END record is also written. - end_of_dump(); + // fixes up the length of the dump record and writes the HPROF_HEAP_DUMP_END record. + DumperSupport::end_of_dump(writer()); // Now we clear the global variables, so that a future dumper might run. clear_global_dumper(); From 5d211651719ad5edc31b1231d03064885c03f629 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 26 Feb 2016 18:51:44 +0300 Subject: [PATCH 144/311] 8141553: [macosx] JDK fails to build with Xcode 7 on 10.11 Reviewed-by: aniyogi, ddehaven, cbensen --- .../macosx/native/libawt_lwawt/awt/AWTView.m | 7 +++--- .../native/libawt_lwawt/awt/LWCToolkit.m | 7 +++--- .../macosx/native/libosx/CFileManager.m | 22 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m index 805596cc118..8070995baa6 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 @@ -624,7 +624,8 @@ AWT_ASSERT_APPKIT_THREAD; { NSString *selectedText = [self accessibleSelectedText]; NSAttributedString *styledText = [[NSAttributedString alloc] initWithString:selectedText]; - NSData *rtfdData = [styledText RTFDFromRange:NSMakeRange(0, [styledText length]) documentAttributes:nil]; + NSData *rtfdData = [styledText RTFDFromRange:NSMakeRange(0, [styledText length]) + documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}]; [styledText release]; return rtfdData; } @@ -681,7 +682,7 @@ AWT_ASSERT_APPKIT_THREAD; if ([[pboard types] containsObject:NSRTFDPboardType]) { NSData *rtfdData = [pboard dataForType:NSRTFDPboardType]; - NSAttributedString *styledText = [[NSAttributedString alloc] initWithRTFD:rtfdData documentAttributes:nil]; + NSAttributedString *styledText = [[NSAttributedString alloc] initWithRTFD:rtfdData documentAttributes:NULL]; NSString *text = [styledText string]; [styledText release]; diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m index 8f1e269de8f..9d8326ade6d 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 @@ -743,9 +743,10 @@ Java_sun_lwawt_macosx_LWCToolkit_initAppkit JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { OSXAPP_SetJavaVM(vm); - // We need to let Foundation know that this is a multithreaded application, if it isn't already. + // We need to let Foundation know that this is a multithreaded application, + // if it isn't already. if (![NSThread isMultiThreaded]) { - [NSThread detachNewThreadSelector:nil toTarget:nil withObject:nil]; + [[[[NSThread alloc] init] autorelease] start]; } return JNI_VERSION_1_4; diff --git a/jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m b/jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m index f5e676ad490..52ca5f8eccf 100644 --- a/jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m +++ b/jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 @@ -213,25 +213,23 @@ JNF_COCOA_EXIT(env); */ JNIEXPORT jboolean JNICALL Java_com_apple_eio_FileManager__1moveToTrash -(JNIEnv *env, jclass clz, jstring url) +(JNIEnv *env, jclass clz, jstring fileName) { - __block jboolean returnValue = JNI_FALSE; + __block BOOL returnValue = NO; JNF_COCOA_ENTER(env); - NSString *path = JNFNormalizedNSStringForPath(env, url); + NSString * path = JNFNormalizedNSStringForPath(env, fileName); + NSURL *url = [NSURL fileURLWithPath:path]; [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - NSInteger res = 0; - [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation - source:[path stringByDeletingLastPathComponent] - destination:nil - files:[NSArray arrayWithObject:[path lastPathComponent]] - tag:&res]; - returnValue = (res == 0); + + returnValue = [[NSFileManager defaultManager] trashItemAtURL:url + resultingItemURL:nil + error:nil]; }]; JNF_COCOA_EXIT(env); - return returnValue; + return returnValue ? JNI_TRUE: JNI_FALSE; } /* From 43a028f60837bc5cd069eaf0dc446ac504d8ea86 Mon Sep 17 00:00:00 2001 From: Alexander Stepanov Date: Fri, 26 Feb 2016 19:24:06 +0300 Subject: [PATCH 145/311] 8150643: [TEST] add test for JDK-8150176 Reviewed-by: serb --- .../MultiResolutionTrayIconTest.html | 41 +++++++ .../MultiResolutionTrayIconTest.java | 116 ++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.html create mode 100644 jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java diff --git a/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.html b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.html new file mode 100644 index 00000000000..7ff1134a69d --- /dev/null +++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.html @@ -0,0 +1,41 @@ + + + + + MultiResolutionTrayIconTest + + + + +To run test please push "Start" (if system tray is not supported, push "Pass"). + +Two tray icons will appear (note: sometimes they can go to the tray icons pool). + +Please check if both of them have correct size and +the same colouring (white rectagle in a blue mount). In this case please push "Pass". + +Otherwise (if the 2nd red-white small icon appears) please push "Fail". + + + diff --git a/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java new file mode 100644 index 00000000000..f6f069b0ed8 --- /dev/null +++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, 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 8150176 + @ignore 8150176 + @summary Check if correct resolution variant is used for tray icon. + @author a.stepanov + @run applet/manual=yesno MultiResolutionTrayIconTest.html +*/ + + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; + + +public class MultiResolutionTrayIconTest extends Applet { + + private SystemTray tray; + private TrayIcon icon, iconMRI; + + public void init() { this.setLayout(new BorderLayout()); } + + public void start() { + + boolean trayIsSupported = SystemTray.isSupported(); + Button b = new Button("Start"); + if (trayIsSupported) { + + prepareIcons(); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { doTest(); } + }); + } else { + b.setLabel("not supported"); + b.setEnabled(false); + System.out.println("system tray is not supported"); + } + add(b, BorderLayout.CENTER); + + validate(); + setVisible(true); + } + + private BufferedImage generateImage(int w, int h, Color c) { + + BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(c); + g.fillRect(0, 0, w, h); + g.setColor(Color.WHITE); + int r = (Math.min(w, h) >= 8) ? 3 : 1; + g.fillRect(r, r, w - 2 * r, h - 2 * r); + return img; + } + + private void prepareIcons() { + + tray = SystemTray.getSystemTray(); + Dimension d = tray.getTrayIconSize(); + int w = d.width, h = d.height; + + BufferedImage img = generateImage(w, h, Color.BLUE); + // use wrong icon size for "nok" + BufferedImage nok = generateImage(w / 2 + 2, h / 2 + 2, Color.RED); + BaseMultiResolutionImage mri = + new BaseMultiResolutionImage(new BufferedImage[] {nok, img}); + icon = new TrayIcon(img); + iconMRI = new TrayIcon(mri); + } + + private void doTest() { + + if (tray.getTrayIcons().length > 0) { return; } // icons were added already + try { + tray.add(icon); + tray.add(iconMRI); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void stop() { + + // check for null, just in case + if (tray != null) { + tray.remove(icon); + tray.remove(iconMRI); + } + } +} From 6d7d3228e7b3fd1e3b4c2b51b8a7de6f04acdb0b Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Fri, 26 Feb 2016 09:13:22 -0800 Subject: [PATCH 146/311] 8147978: Remove Method::_method_data for C1 Method::_method_data field removed when not using C2 or JVMCI Reviewed-by: dholmes, kvn --- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 26 ++++++++++++---------- hotspot/src/share/vm/oops/method.cpp | 5 +++-- hotspot/src/share/vm/oops/method.hpp | 18 +++++++++++++++ hotspot/src/share/vm/runtime/arguments.cpp | 6 +++++ hotspot/src/share/vm/runtime/vmStructs.cpp | 2 +- hotspot/src/share/vm/utilities/macros.hpp | 11 ++++++++- 6 files changed, 52 insertions(+), 16 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 92c721575d0..01e639258c8 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -1502,21 +1502,23 @@ JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* thread)) nm->make_not_entrant(); methodHandle m(nm->method()); - MethodData* mdo = m->method_data(); + if (ProfileInterpreter) { + MethodData* mdo = m->method_data(); - if (mdo == NULL && !HAS_PENDING_EXCEPTION) { - // Build an MDO. Ignore errors like OutOfMemory; - // that simply means we won't have an MDO to update. - Method::build_interpreter_method_data(m, THREAD); - if (HAS_PENDING_EXCEPTION) { - assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here"); - CLEAR_PENDING_EXCEPTION; + if (mdo == NULL && !HAS_PENDING_EXCEPTION) { + // Build an MDO. Ignore errors like OutOfMemory; + // that simply means we won't have an MDO to update. + Method::build_interpreter_method_data(m, THREAD); + if (HAS_PENDING_EXCEPTION) { + assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here"); + CLEAR_PENDING_EXCEPTION; + } + mdo = m->method_data(); } - mdo = m->method_data(); - } - if (mdo != NULL) { - mdo->inc_trap_count(Deoptimization::Reason_none); + if (mdo != NULL) { + mdo->inc_trap_count(Deoptimization::Reason_none); + } } if (TracePredicateFailedTraps) { diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 7620ea9f985..1f3eb751413 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -383,14 +383,15 @@ void Method::build_interpreter_method_data(const methodHandle& method, TRAPS) { MutexLocker ml(MethodData_lock, THREAD); if (method->method_data() == NULL) { ClassLoaderData* loader_data = method->method_holder()->class_loader_data(); +#if defined(COMPILER2) || INCLUDE_JVMCI MethodData* method_data = MethodData::allocate(loader_data, method, THREAD); if (HAS_PENDING_EXCEPTION) { CompileBroker::log_metaspace_failure(); ClassLoaderDataGraph::set_metaspace_oom(true); return; // return the exception (which is cleared) } - method->set_method_data(method_data); +#endif if (PrintMethodData && (Verbose || WizardMode)) { ResourceMark rm(THREAD); tty->print("build_interpreter_method_data for "); @@ -920,7 +921,7 @@ void Method::unlink_method() { // shared class that failed to load, this->link_method() may // have already been called (before an exception happened), so // this->_method_data may not be NULL. - assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?"); + assert(!DumpSharedSpaces || method_data() == NULL, "unexpected method data?"); set_method_data(NULL); clear_method_counters(); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 8fc7b133a16..fdf7d1f9fb0 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -64,7 +64,9 @@ class Method : public Metadata { friend class JVMCIVMStructs; private: ConstMethod* _constMethod; // Method read-only data. +#if defined(COMPILER2) || INCLUDE_JVMCI MethodData* _method_data; +#endif MethodCounters* _method_counters; AccessFlags _access_flags; // Access flags int _vtable_index; // vtable index of this method (see VtableIndexFlag) @@ -319,6 +321,7 @@ class Method : public Metadata { // InterpreterRuntime::exception_handler_for_exception. static int fast_exception_handler_bci_for(methodHandle mh, KlassHandle ex_klass, int throw_bci, TRAPS); +#if defined(COMPILER2) || INCLUDE_JVMCI // method data access MethodData* method_data() const { return _method_data; @@ -330,6 +333,10 @@ class Method : public Metadata { // the initialization of data otherwise. OrderAccess::release_store_ptr((volatile void *)&_method_data, data); } +#else + MethodData* method_data() const { return NULL; } + void set_method_data(MethodData* data) { } +#endif MethodCounters* method_counters() const { return _method_counters; @@ -639,9 +646,16 @@ class Method : public Metadata { #endif /* CC_INTERP */ static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); } static ByteSize code_offset() { return byte_offset_of(Method, _code); } +#if defined(COMPILER2) || INCLUDE_JVMCI static ByteSize method_data_offset() { return byte_offset_of(Method, _method_data); } +#else + static ByteSize method_data_offset() { + ShouldNotReachHere(); + return in_ByteSize(0); + } +#endif static ByteSize method_counters_offset() { return byte_offset_of(Method, _method_counters); } @@ -654,7 +668,11 @@ class Method : public Metadata { static ByteSize signature_handler_offset() { return in_ByteSize(sizeof(Method) + wordSize); } // for code generation +#if defined(COMPILER2) || INCLUDE_JVMCI static int method_data_offset_in_bytes() { return offset_of(Method, _method_data); } +#else + static int method_data_offset_in_bytes() { ShouldNotReachHere(); return 0; } +#endif static int intrinsic_id_offset_in_bytes() { return offset_of(Method, _intrinsic_id); } static int intrinsic_id_size_in_bytes() { return sizeof(u2); } diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 006e3c94739..ca25748543e 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -3464,6 +3464,12 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req } #endif +#if !defined(COMPILER2) && !INCLUDE_JVMCI + UNSUPPORTED_OPTION(ProfileInterpreter, "ProfileInterpreter"); + NOT_PRODUCT(UNSUPPORTED_OPTION(TraceProfileInterpreter, "TraceProfileInterpreter")); + UNSUPPORTED_OPTION(PrintMethodData, "PrintMethodData"); +#endif + #ifndef TIERED // Tiered compilation is undefined. UNSUPPORTED_OPTION(TieredCompilation, "TieredCompilation"); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 84d2c6ebd3b..6630da1633c 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -390,7 +390,7 @@ typedef CompactHashtable SymbolCompactHashTable; nonstatic_field(MethodCounters, _invocation_counter, InvocationCounter) \ nonstatic_field(MethodCounters, _backedge_counter, InvocationCounter) \ nonstatic_field(Method, _constMethod, ConstMethod*) \ - nonstatic_field(Method, _method_data, MethodData*) \ + COMPILER2_OR_JVMCI_PRESENT(nonstatic_field(Method, _method_data, MethodData*)) \ nonstatic_field(Method, _method_counters, MethodCounters*) \ nonstatic_field(Method, _access_flags, AccessFlags) \ nonstatic_field(Method, _vtable_index, int) \ diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index ccdb90813b7..11b4fe4f3aa 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -206,6 +206,15 @@ #define NOT_COMPILER2(code) code #endif // COMPILER2 +// COMPILER2 or JVMCI +#if defined(COMPILER2) || INCLUDE_JVMCI +#define COMPILER2_OR_JVMCI_PRESENT(code) code +#define NOT_COMPILER2_OR_JVMCI(code) +#else +#define COMPILER2_OR_JVMCI_PRESENT(code) +#define NOT_COMPILER2_OR_JVMCI(code) code +#endif + #ifdef TIERED #define TIERED_ONLY(code) code #define NOT_TIERED(code) From 41c0116f6ef2f0e1e12de4909b5e56a4662d51fd Mon Sep 17 00:00:00 2001 From: Joseph Provino Date: Fri, 26 Feb 2016 14:02:39 -0500 Subject: [PATCH 147/311] 8139651: ConcurrentG1Refine uses ints for many of its members that should be unsigned types Ints need to be changed to size_t Reviewed-by: kbarrett, tbenson --- .../src/share/vm/gc/g1/concurrentG1Refine.cpp | 8 +++---- .../src/share/vm/gc/g1/concurrentG1Refine.hpp | 24 +++++++++---------- .../vm/gc/g1/concurrentG1RefineThread.cpp | 12 ++++++---- .../vm/gc/g1/concurrentG1RefineThread.hpp | 8 +++---- hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp | 14 ++++++----- hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp | 4 ++-- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 4 ++-- .../src/share/vm/gc/g1/g1CollectorPolicy.cpp | 16 ++++++------- .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 4 ++-- hotspot/src/share/vm/gc/g1/g1RemSet.cpp | 1 - hotspot/src/share/vm/gc/g1/g1_globals.hpp | 22 ++++++++--------- hotspot/src/share/vm/gc/g1/ptrQueue.cpp | 12 ++++++---- hotspot/src/share/vm/gc/g1/ptrQueue.hpp | 12 +++++----- 13 files changed, 73 insertions(+), 68 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp index 0e2f4dd4bb3..5edec2775ed 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -36,19 +36,19 @@ ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) : { // Ergonomically select initial concurrent refinement parameters if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, (intx)ParallelGCThreads); + FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, ParallelGCThreads); } set_green_zone(G1ConcRefinementGreenZone); if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { FLAG_SET_DEFAULT(G1ConcRefinementYellowZone, green_zone() * 3); } - set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); + set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); if (FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2); } - set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); + set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); } ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) { diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp index 0e5525f73c2..2333fea311f 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -61,11 +61,11 @@ class ConcurrentG1Refine: public CHeapObj { * 2) green = 0. Means no caching. Can be a good way to minimize the * amount of time spent updating rsets during a collection. */ - int _green_zone; - int _yellow_zone; - int _red_zone; + size_t _green_zone; + size_t _yellow_zone; + size_t _red_zone; - int _thread_threshold_step; + size_t _thread_threshold_step; // We delay the refinement of 'hot' cards using the hot card cache. G1HotCardCache _hot_card_cache; @@ -100,17 +100,17 @@ class ConcurrentG1Refine: public CHeapObj { void print_worker_threads_on(outputStream* st) const; - void set_green_zone(int x) { _green_zone = x; } - void set_yellow_zone(int x) { _yellow_zone = x; } - void set_red_zone(int x) { _red_zone = x; } + void set_green_zone(size_t x) { _green_zone = x; } + void set_yellow_zone(size_t x) { _yellow_zone = x; } + void set_red_zone(size_t x) { _red_zone = x; } - int green_zone() const { return _green_zone; } - int yellow_zone() const { return _yellow_zone; } - int red_zone() const { return _red_zone; } + size_t green_zone() const { return _green_zone; } + size_t yellow_zone() const { return _yellow_zone; } + size_t red_zone() const { return _red_zone; } uint worker_thread_num() const { return _n_worker_threads; } - int thread_threshold_step() const { return _thread_threshold_step; } + size_t thread_threshold_step() const { return _thread_threshold_step; } G1HotCardCache* hot_card_cache() { return &_hot_card_cache; } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index cefcab3065b..1e8081e53e0 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -67,10 +67,12 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex void ConcurrentG1RefineThread::initialize() { // Current thread activation threshold - _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), + _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), cg1r()->yellow_zone()); // A thread deactivates once the number of buffer reached a deactivation threshold - _deactivation_threshold = MAX2(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone()); + _deactivation_threshold = + MAX2(_threshold - MIN2(_threshold, cg1r()->thread_threshold_step()), + cg1r()->green_zone()); } void ConcurrentG1RefineThread::wait_for_completed_buffers() { @@ -127,14 +129,14 @@ void ConcurrentG1RefineThread::run_service() { } DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); - log_debug(gc, refine)("Activated %d, on threshold: %d, current: %d", + log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, _worker_id, _threshold, dcqs.completed_buffers_num()); { SuspendibleThreadSetJoiner sts_join; do { - int curr_buffer_num = (int)dcqs.completed_buffers_num(); + size_t curr_buffer_num = dcqs.completed_buffers_num(); // If the number of the buffers falls down into the yellow zone, // that means that the transition period after the evacuation pause has ended. if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { @@ -151,7 +153,7 @@ void ConcurrentG1RefineThread::run_service() { false /* during_pause */)); deactivate(); - log_debug(gc, refine)("Deactivated %d, off threshold: %d, current: %d", + log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, _worker_id, _deactivation_threshold, dcqs.completed_buffers_num()); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp index 5b6d3ed79d5..40071766d6f 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -53,11 +53,11 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread { // The closure applied to completed log buffers. CardTableEntryClosure* _refine_closure; - int _thread_threshold_step; + size_t _thread_threshold_step; // This thread activation threshold - int _threshold; + size_t _threshold; // This thread deactivation threshold - int _deactivation_threshold; + size_t _deactivation_threshold; void wait_for_completed_buffers(); diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp index 4c33fb9b211..d79ac8066b9 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp @@ -207,22 +207,24 @@ bool DirtyCardQueueSet::mut_process_buffer(void** buf) { } -BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) { +BufferNode* DirtyCardQueueSet::get_completed_buffer(size_t stop_at) { BufferNode* nd = NULL; MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - if ((int)_n_completed_buffers <= stop_at) { + if (_n_completed_buffers <= stop_at) { _process_completed = false; return NULL; } if (_completed_buffers_head != NULL) { nd = _completed_buffers_head; + assert(_n_completed_buffers > 0, "Invariant"); _completed_buffers_head = nd->next(); - if (_completed_buffers_head == NULL) - _completed_buffers_tail = NULL; _n_completed_buffers--; - assert(_n_completed_buffers >= 0, "Invariant"); + if (_completed_buffers_head == NULL) { + assert(_n_completed_buffers == 0, "Invariant"); + _completed_buffers_tail = NULL; + } } DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); return nd; @@ -230,7 +232,7 @@ BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) { bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, uint worker_i, - int stop_at, + size_t stop_at, bool during_pause) { assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); BufferNode* nd = get_completed_buffer(stop_at); diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp index 17c92bb8ecf..96865a5784b 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp @@ -134,10 +134,10 @@ public: // is returned to the completed buffer set, and this call returns false. bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl, uint worker_i, - int stop_at, + size_t stop_at, bool during_pause); - BufferNode* get_completed_buffer(int stop_at); + BufferNode* get_completed_buffer(size_t stop_at); // Applies the current closure to all completed buffers, // non-consumptively. diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index be30e88c541..01907547340 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1984,8 +1984,8 @@ jint G1CollectedHeap::initialize() { JavaThread::dirty_card_queue_set().initialize(_refine_cte_cl, DirtyCardQ_CBL_mon, DirtyCardQ_FL_lock, - concurrent_g1_refine()->yellow_zone(), - concurrent_g1_refine()->red_zone(), + (int)concurrent_g1_refine()->yellow_zone(), + (int)concurrent_g1_refine()->red_zone(), Shared_DirtyCardQ_lock, NULL, // fl_owner true); // init_free_ids diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index f14e360ce44..bd98877eded 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -1301,12 +1301,12 @@ void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, const int k_gy = 3, k_gr = 6; const double inc_k = 1.1, dec_k = 0.9; - int g = cg1r->green_zone(); + size_t g = cg1r->green_zone(); if (update_rs_time > goal_ms) { - g = (int)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. + g = (size_t)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. } else { if (update_rs_time < goal_ms && update_rs_processed_buffers > g) { - g = (int)MAX2(g * inc_k, g + 1.0); + g = (size_t)MAX2(g * inc_k, g + 1.0); } } // Change the refinement threads params @@ -1315,15 +1315,15 @@ void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, cg1r->set_red_zone(g * k_gr); cg1r->reinitialize_threads(); - int processing_threshold_delta = MAX2((int)(cg1r->green_zone() * _predictor.sigma()), 1); - int processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta, + size_t processing_threshold_delta = MAX2(cg1r->green_zone() * _predictor.sigma(), 1); + size_t processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta, cg1r->yellow_zone()); // Change the barrier params - dcqs.set_process_completed_threshold(processing_threshold); - dcqs.set_max_completed_queue(cg1r->red_zone()); + dcqs.set_process_completed_threshold((int)processing_threshold); + dcqs.set_max_completed_queue((int)cg1r->red_zone()); } - int curr_queue_size = dcqs.completed_buffers_num(); + size_t curr_queue_size = dcqs.completed_buffers_num(); if (curr_queue_size >= cg1r->yellow_zone()) { dcqs.set_completed_queue_padding(curr_queue_size); } else { diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index edfb510d6fe..6605b0cf621 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -2271,7 +2271,7 @@ void G1ConcurrentMark::checkpointRootsFinalWork() { SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); guarantee(has_overflown() || satb_mq_set.completed_buffers_num() == 0, - "Invariant: has_overflown = %s, num buffers = %d", + "Invariant: has_overflown = %s, num buffers = " SIZE_FORMAT, BOOL_TO_STR(has_overflown()), satb_mq_set.completed_buffers_num()); diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index 40e3959c886..3d2917a2184 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -291,7 +291,6 @@ void G1RemSet::cleanup_after_oops_into_collection_set_do() { _g1->cleanUpCardTable(); DirtyCardQueueSet& into_cset_dcqs = _into_cset_dirty_card_queue_set; - int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num(); if (_g1->evacuation_failed()) { double restore_remembered_set_start = os::elapsedTime(); diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index 086e27bd589..370ba86eb09 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -107,35 +107,35 @@ "Size of an update buffer") \ range(1, NOT_LP64(32*M) LP64_ONLY(1*G)) \ \ - product(intx, G1ConcRefinementYellowZone, 0, \ + product(size_t, G1ConcRefinementYellowZone, 0, \ "Number of enqueued update buffers that will " \ "trigger concurrent processing. Will be selected ergonomically " \ "by default.") \ - range(0, max_intx) \ + range(0, SIZE_MAX) \ \ - product(intx, G1ConcRefinementRedZone, 0, \ + product(size_t, G1ConcRefinementRedZone, 0, \ "Maximum number of enqueued update buffers before mutator " \ "threads start processing new ones instead of enqueueing them. " \ "Will be selected ergonomically by default. Zero will disable " \ "concurrent processing.") \ - range(0, max_intx) \ + range(0, SIZE_MAX) \ \ - product(intx, G1ConcRefinementGreenZone, 0, \ + product(size_t, G1ConcRefinementGreenZone, 0, \ "The number of update buffers that are left in the queue by the " \ "concurrent processing threads. Will be selected ergonomically " \ "by default.") \ - range(0, max_intx) \ + range(0, SIZE_MAX) \ \ - product(intx, G1ConcRefinementServiceIntervalMillis, 300, \ + product(uintx, G1ConcRefinementServiceIntervalMillis, 300, \ "The last concurrent refinement thread wakes up every " \ "specified number of milliseconds to do miscellaneous work.") \ - range(0, max_jint) \ + range(0, max_uintx) \ \ - product(intx, G1ConcRefinementThresholdStep, 0, \ + product(size_t, G1ConcRefinementThresholdStep, 0, \ "Each time the rset update queue increases by this amount " \ "activate the next refinement thread if available. " \ "Will be selected ergonomically by default.") \ - range(0, max_jint) \ + range(0, SIZE_MAX) \ \ product(intx, G1RSetUpdatingPauseTimePercent, 10, \ "A target percentage of time that is allowed to be spend on " \ diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp index 55b41a0b605..d6cf5c50e6a 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp @@ -271,16 +271,17 @@ void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) { _n_completed_buffers++; if (!_process_completed && _process_completed_threshold >= 0 && - _n_completed_buffers >= _process_completed_threshold) { + _n_completed_buffers >= (size_t)_process_completed_threshold) { _process_completed = true; - if (_notify_when_complete) + if (_notify_when_complete) { _cbl_mon->notify(); + } } DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); } -int PtrQueueSet::completed_buffers_list_length() { - int n = 0; +size_t PtrQueueSet::completed_buffers_list_length() { + size_t n = 0; BufferNode* cbn = _completed_buffers_head; while (cbn != NULL) { n++; @@ -334,7 +335,8 @@ void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) { void PtrQueueSet::notify_if_necessary() { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - if (_n_completed_buffers >= _process_completed_threshold || _max_completed_queue == 0) { + assert(_process_completed_threshold >= 0, "_process_completed is negative"); + if (_n_completed_buffers >= (size_t)_process_completed_threshold || _max_completed_queue == 0) { _process_completed = true; if (_notify_when_complete) _cbl_mon->notify(); diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp index a2207641238..4d5c5e6c28a 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp @@ -209,7 +209,7 @@ protected: Monitor* _cbl_mon; // Protects the fields below. BufferNode* _completed_buffers_head; BufferNode* _completed_buffers_tail; - int _n_completed_buffers; + size_t _n_completed_buffers; int _process_completed_threshold; volatile bool _process_completed; @@ -233,9 +233,9 @@ protected: // Maximum number of elements allowed on completed queue: after that, // enqueuer does the work itself. Zero indicates no maximum. int _max_completed_queue; - int _completed_queue_padding; + size_t _completed_queue_padding; - int completed_buffers_list_length(); + size_t completed_buffers_list_length(); void assert_completed_buffer_list_len_correct_locked(); void assert_completed_buffer_list_len_correct(); @@ -299,15 +299,15 @@ public: // list size may be reduced, if that is deemed desirable. void reduce_free_list(); - int completed_buffers_num() { return _n_completed_buffers; } + size_t completed_buffers_num() { return _n_completed_buffers; } void merge_bufferlists(PtrQueueSet* src); void set_max_completed_queue(int m) { _max_completed_queue = m; } int max_completed_queue() { return _max_completed_queue; } - void set_completed_queue_padding(int padding) { _completed_queue_padding = padding; } - int completed_queue_padding() { return _completed_queue_padding; } + void set_completed_queue_padding(size_t padding) { _completed_queue_padding = padding; } + size_t completed_queue_padding() { return _completed_queue_padding; } // Notify the consumer if the number of buffers crossed the threshold void notify_if_necessary(); From 234373ff31ee35fb5cad93317baa30b26fa6edbe Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Sun, 28 Feb 2016 12:22:05 -0500 Subject: [PATCH 148/311] 8150421: Delete experimental G1UseConcMarkReferenceProcessing Removed the option and supporting code. Reviewed-by: jmasa, tamao --- hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp | 7 ++----- hotspot/src/share/vm/gc/g1/g1_globals.hpp | 4 ---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index 6605b0cf621..5ece63cea5d 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -2702,11 +2702,8 @@ public: }; static ReferenceProcessor* get_cm_oop_closure_ref_processor(G1CollectedHeap* g1h) { - ReferenceProcessor* result = NULL; - if (G1UseConcMarkReferenceProcessing) { - result = g1h->ref_processor_cm(); - assert(result != NULL, "should not be NULL"); - } + ReferenceProcessor* result = g1h->ref_processor_cm(); + assert(result != NULL, "CM reference processor should not be NULL"); return result; } diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index 370ba86eb09..fa210295098 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -71,10 +71,6 @@ "draining concurrent marking work queues.") \ range(1, max_intx) \ \ - experimental(bool, G1UseConcMarkReferenceProcessing, true, \ - "If true, enable reference discovery during concurrent " \ - "marking and reference processing at the end of remark.") \ - \ experimental(double, G1LastPLABAverageOccupancy, 50.0, \ "The expected average occupancy of the last PLAB in " \ "percent.") \ From dc8f45fc7dad5c788afc1f8317aa27ef3546df55 Mon Sep 17 00:00:00 2001 From: Zoltan Majo Date: Mon, 29 Feb 2016 07:58:45 +0100 Subject: [PATCH 149/311] 8148940: java/lang/ref/FinalizeOverride.java can time out due to frequent safepointing Reduce the freqency of triggering GCs by sleeping between GCs. Reviewed-by: thartmann, shade --- jdk/test/java/lang/ref/FinalizeOverride.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/lang/ref/FinalizeOverride.java b/jdk/test/java/lang/ref/FinalizeOverride.java index eeb86fe4ab2..7701f5844ea 100644 --- a/jdk/test/java/lang/ref/FinalizeOverride.java +++ b/jdk/test/java/lang/ref/FinalizeOverride.java @@ -29,7 +29,7 @@ import java.nio.file.Paths; import java.util.concurrent.atomic.AtomicInteger; /* @test - * @bug 8027351 + * @bug 8027351 8148940 * @summary Basic test of the finalize method */ @@ -63,6 +63,19 @@ public class FinalizeOverride { while (finalizedCount.get() != (count+1)) { System.gc(); System.runFinalization(); + // Running System.gc() and System.runFinalization() in a + // tight loop can trigger frequent safepointing that slows + // down the VM and, as a result, the test. (With the + // HotSpot VM, the effect of frequent safepointing is + // especially noticeable if the test is run with the + // -Xcomp flag.) Sleeping for a second after every + // garbage collection and finalization cycle gives the VM + // time to make progress. + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println("Main thread interrupted, continuing execution."); + } } if (privateFinalizeInvoked) { From 31f86a2308104bcbf173193ee988c25ece2ec05e Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Mon, 29 Feb 2016 08:50:57 +0100 Subject: [PATCH 150/311] 8150619: Improve thread based logging introduced with 8149036 Reviewed-by: coleenp, dholmes --- hotspot/src/os/aix/vm/os_aix.cpp | 18 ++--- hotspot/src/os/bsd/vm/os_bsd.cpp | 6 +- hotspot/src/os/linux/vm/os_linux.cpp | 2 +- hotspot/src/os/solaris/vm/os_solaris.cpp | 9 ++- hotspot/src/os/windows/vm/os_windows.cpp | 5 +- hotspot/src/share/vm/runtime/thread.cpp | 8 +-- .../runtime/logging/ThreadLoggingTest.java | 69 +++++++++++++++++++ 7 files changed, 92 insertions(+), 25 deletions(-) create mode 100644 hotspot/test/runtime/logging/ThreadLoggingTest.java diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index c38d2a3fbd0..2193a9611a3 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. 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 @@ -792,8 +792,8 @@ static void *java_start(Thread *thread) { const pthread_t pthread_id = ::pthread_self(); const tid_t kernel_thread_id = ::thread_self(); - log_info(os, thread)("Thread is alive (pthread id " UINTX_FORMAT ", tid " UINTX_FORMAT ")", - (uintx) pthread_id, (uintx) kernel_thread_id); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) kernel_thread_id); // Normally, pthread stacks on AIX live in the data segment (are allocated with malloc() // by the pthread library). In rare cases, this may not be the case, e.g. when third-party @@ -801,7 +801,7 @@ static void *java_start(Thread *thread) { // guard pages on those stacks, because the stacks may reside in memory which is not // protectable (shmated). if (thread->stack_base() > ::sbrk(0)) { - log_warning(os, thread)("Thread " UINTX_FORMAT ": stack not in data segment.", (uintx)pthread_id); + log_warning(os, thread)("Thread stack not in data segment."); } // Try to randomize the cache line index of hot stack frames. @@ -835,8 +835,8 @@ static void *java_start(Thread *thread) { // Call one more level start routine. thread->run(); - log_info(os, thread)("Thread finished (pthread id " UINTX_FORMAT ", tid " UINTX_FORMAT ").", - (uintx) pthread_id, (uintx) kernel_thread_id); + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) kernel_thread_id); return 0; } @@ -978,8 +978,8 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Aix::hotspot_sigmask(thread); - log_info(os, thread)("Thread attached (pthread id " UINTX_FORMAT ", tid " UINTX_FORMAT ")", - (uintx) pthread_id, (uintx) kernel_thread_id); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) kernel_thread_id); return true; } diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 51fce416eda..3d6f8fd6422 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -682,7 +682,7 @@ static void *java_start(Thread *thread) { osthread->set_thread_id(os::Bsd::gettid()); - log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ".", + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", os::current_thread_id(), (uintx) pthread_self()); #ifdef __APPLE__ @@ -720,7 +720,7 @@ static void *java_start(Thread *thread) { // call one more level start routine thread->run(); - log_info(os, thread)("Thread finished (tid " UINTX_FORMAT ", pthread id " UINTX_FORMAT ").", + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", os::current_thread_id(), (uintx) pthread_self()); return 0; @@ -871,7 +871,7 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Bsd::hotspot_sigmask(thread); - log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ".", + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", os::current_thread_id(), (uintx) pthread_self()); return true; diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 5bf366d3997..d46a1146dd7 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -694,7 +694,7 @@ static void *java_start(Thread *thread) { // call one more level start routine thread->run(); - log_info(os, thread)("Thread finished (tid " UINTX_FORMAT ", pthread id " UINTX_FORMAT ").", + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", os::current_thread_id(), (uintx) pthread_self()); return 0; diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index e454ed165c7..bc8138db6ff 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -891,12 +891,11 @@ bool os::create_main_thread(JavaThread* thread) { // Helper function to trace thread attributes, similar to os::Posix::describe_pthread_attr() static char* describe_thr_create_attributes(char* buf, size_t buflen, - size_t stacksize, long flags) -{ + size_t stacksize, long flags) { stringStream ss(buf, buflen); ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024); ss.print("flags: "); - #define PRINT_FLAG(f) if (flags & f) ss.print( XSTR(f) " "); + #define PRINT_FLAG(f) if (flags & f) ss.print( #f " "); #define ALL(X) \ X(THR_SUSPENDED) \ X(THR_DETACHED) \ @@ -1006,7 +1005,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, char buf[64]; if (status == 0) { - log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + log_info(os, thread)("Thread started (tid: " UINTX_FORMAT ", attributes: %s). ", (uintx) tid, describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); } else { log_warning(os, thread)("Failed to start thread - thr_create failed (%s) for attributes: %s.", diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 7b371739e09..f8bc6081d8b 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -543,8 +543,7 @@ bool os::create_main_thread(JavaThread* thread) { // Helper function to trace _beginthreadex attributes, // similar to os::Posix::describe_pthread_attr() static char* describe_beginthreadex_attributes(char* buf, size_t buflen, - size_t stacksize, unsigned initflag) -{ + size_t stacksize, unsigned initflag) { stringStream ss(buf, buflen); if (stacksize == 0) { ss.print("stacksize: default, "); @@ -552,7 +551,7 @@ static char* describe_beginthreadex_attributes(char* buf, size_t buflen, ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024); } ss.print("flags: "); - #define PRINT_FLAG(f) if (initflag & f) ss.print( XSTR(f) " "); + #define PRINT_FLAG(f) if (initflag & f) ss.print( #f " "); #define ALL(X) \ X(CREATE_SUSPENDED) \ X(STACK_SIZE_PARAM_IS_A_RESERVATION) diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 654aebd9e70..8e1e997f8c1 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1806,10 +1806,6 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { // Call after last event on thread EVENT_THREAD_EXIT(this); - log_info(os, thread)("Thread " UINTX_FORMAT " %s.", - os::current_thread_id(), - exit_type == JavaThread::normal_exit ? "exiting" : "detaching"); - // Call Thread.exit(). We try 3 times in case we got another Thread.stop during // the execution of the method. If that is not enough, then we don't really care. Thread.stop // is deprecated anyhow. @@ -1932,6 +1928,10 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { } #endif // INCLUDE_ALL_GCS + log_info(os, thread)("JavaThread %s (tid: " UINTX_FORMAT ").", + exit_type == JavaThread::normal_exit ? "exiting" : "detaching", + os::current_thread_id()); + // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread Threads::remove(this); } diff --git a/hotspot/test/runtime/logging/ThreadLoggingTest.java b/hotspot/test/runtime/logging/ThreadLoggingTest.java new file mode 100644 index 00000000000..a5cde9c845c --- /dev/null +++ b/hotspot/test/runtime/logging/ThreadLoggingTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, SAP SE 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 8149036 8150619 + * @summary os+thread output should contain logging calls for thread start stop attaches detaches + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver ThreadLoggingTest + * @author Thomas Stuefe (SAP) + */ + +import java.io.File; +import java.util.Map; +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; + +public class ThreadLoggingTest { + + static void analyzeOutputForInfoLevel(OutputAnalyzer output) throws Exception { + output.shouldContain("Thread started"); + output.shouldContain("Thread is alive"); + output.shouldContain("Thread finished"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputForDebugLevel(OutputAnalyzer output) throws Exception { + analyzeOutputForInfoLevel(output); + output.shouldContain("stack dimensions"); + output.shouldContain("stack guard pages"); + } + + public static void main(String[] args) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+thread", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + analyzeOutputForInfoLevel(output); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+thread=debug", "-version"); + output = new OutputAnalyzer(pb.start()); + analyzeOutputForDebugLevel(output); + + } + +} From 98fc723fbf46d4da77782316a67d3fbd3a7dcf91 Mon Sep 17 00:00:00 2001 From: Prem Balakrishnan Date: Mon, 29 Feb 2016 14:19:40 +0530 Subject: [PATCH 151/311] 7126823: JInternalFrame.getNormalBounds() returns bad value after iconify/deiconify Reviewed-by: ssadetsky, rchamyal --- .../javax/swing/DefaultDesktopManager.java | 6 - .../swing/plaf/synth/SynthDesktopPaneUI.java | 3 - .../JInternalFrame/NormalBoundsTest.java | 301 ++++++++++++++++++ 3 files changed, 301 insertions(+), 9 deletions(-) create mode 100644 jdk/test/javax/swing/JInternalFrame/NormalBoundsTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java b/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java index 18f30579f4e..74778d50267 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java @@ -191,12 +191,6 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab JLayeredPane.putLayer(desktopIcon, layer); } - // If we are maximized we already have the normal bounds recorded - // don't try to re-record them, otherwise we incorrectly set the - // normal bounds to maximized state. - if (!f.isMaximum()) { - f.setNormalBounds(f.getBounds()); - } if (findNext) { if (d.selectFrame(true) == null) { // The icon is the last frame. diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java index b22941c8f6f..f7b370eb35b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java @@ -362,9 +362,6 @@ public class SynthDesktopPaneUI extends BasicDesktopPaneUI implements setWasIcon(f, Boolean.TRUE); } - if (!f.isMaximum()) { - f.setNormalBounds(f.getBounds()); - } c.remove(f); c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight()); try { diff --git a/jdk/test/javax/swing/JInternalFrame/NormalBoundsTest.java b/jdk/test/javax/swing/JInternalFrame/NormalBoundsTest.java new file mode 100644 index 00000000000..2a6d7f998a9 --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/NormalBoundsTest.java @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2016, 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 7126823 + @summary Verify NormalBounds upon iconify/deiconify sequence + @run main NormalBoundsTest + */ +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.beans.PropertyVetoException; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.WindowConstants; + +public class NormalBoundsTest { + + private static JFrame mainFrame; + private static JInternalFrame internalFrame; + private static Rectangle bounds; + + private static void createUI(String lookAndFeelString) { + internalFrame = new JInternalFrame("Internal", true, true, true, true); + internalFrame.setDefaultCloseOperation( + WindowConstants.DO_NOTHING_ON_CLOSE); + internalFrame.setSize(200, 200); + + JDesktopPane desktopPane = new JDesktopPane(); + desktopPane.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); + desktopPane.add(internalFrame); + + mainFrame = new JFrame(lookAndFeelString); + mainFrame.setSize(640, 480); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + mainFrame.setContentPane(desktopPane); + + mainFrame.setVisible(true); + internalFrame.setVisible(true); + + } + + private static int signWOZero(int i) { + return (i > 0) ? 1 : -1; + } + + private static void mouseMove(Robot robot, Point startPt, Point endPt) { + int dx = endPt.x - startPt.x; + int dy = endPt.y - startPt.y; + + int ax = Math.abs(dx) * 2; + int ay = Math.abs(dy) * 2; + + int sx = signWOZero(dx); + int sy = signWOZero(dy); + + int x = startPt.x; + int y = startPt.y; + + int d = 0; + + if (ax > ay) { + d = ay - ax / 2; + while (true) { + robot.mouseMove(x, y); + robot.delay(50); + + if (x == endPt.x) { + return; + } + if (d >= 0) { + y = y + sy; + d = d - ax; + } + x = x + sx; + d = d + ay; + } + } else { + d = ax - ay / 2; + while (true) { + robot.mouseMove(x, y); + robot.delay(50); + + if (y == endPt.y) { + return; + } + if (d >= 0) { + x = x + sx; + d = d - ay; + } + y = y + sy; + d = d + ax; + } + } + } + + private static void drag(Robot r, Point startPt, Point endPt, int button) { + if (!(button == InputEvent.BUTTON1_MASK + || button == InputEvent.BUTTON2_MASK + || button == InputEvent.BUTTON3_MASK)) { + throw new IllegalArgumentException("invalid mouse button"); + } + + r.mouseMove(startPt.x, startPt.y); + r.mousePress(button); + try { + mouseMove(r, startPt, endPt); + } finally { + r.mouseRelease(button); + } + } + + private static boolean tryLookAndFeel(String lookAndFeelString) { + try { + UIManager.setLookAndFeel(lookAndFeelString); + return true; + } catch (UnsupportedLookAndFeelException | ClassNotFoundException | + InstantiationException | IllegalAccessException e) { + return false; + } + } + + public static void executeTest(Robot robot) throws Exception { + + // Iconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(true); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Iconize InternalFrame Failed"); + } + } + }); + robot.waitForIdle(); + + // Deiconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(false); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Deiconize InternalFrame" + + " Failed"); + } + } + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + Point loc = internalFrame.getLocationOnScreen(); + // Drag Frame + drag(robot, + new Point((int) loc.x + 80, (int) loc.y + 12), + new Point((int) loc.x + 100, (int) loc.y + 40), + InputEvent.BUTTON1_MASK); + } + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + bounds = internalFrame.getBounds(); + if (!internalFrame.getNormalBounds().equals(bounds)) { + mainFrame.dispose(); + throw new RuntimeException("Invalid NormalBounds"); + } + } + }); + robot.waitForIdle(); + + // Regression Test Bug ID: 4424247 + // Maximize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setMaximum(true); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Maximize InternalFrame Failed"); + } + } + }); + robot.waitForIdle(); + + // Iconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(true); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Iconize InternalFrame Failed"); + } + } + }); + robot.waitForIdle(); + + // DeIconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(false); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("DeIcoize InternalFrame " + + " Failed"); + } + } + }); + robot.waitForIdle(); + + // Restore/Undo Maximize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setMaximum(false); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Restore InternalFrame " + + " Failed"); + } + } + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + if (!internalFrame.getBounds().equals(bounds)) { + mainFrame.dispose(); + throw new RuntimeException("Regression Test Failed"); + } + } + }); + robot.waitForIdle(); + + mainFrame.dispose(); + } + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + String lookAndFeelString = lookAndFeelItem.getClassName(); + if (tryLookAndFeel(lookAndFeelString)) { + // create UI + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + createUI(lookAndFeelString); + } + }); + + robot.waitForIdle(); + executeTest(robot); + } else { + throw new RuntimeException("Setting Look and Feel Failed"); + } + } + + } +} From 762fc4fca774f810a005bbe516ed2d1b3e326c13 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Mon, 29 Feb 2016 09:49:46 +0100 Subject: [PATCH 152/311] 8150814: correct package declaration in Nashorn test Reviewed-by: sundar --- .../src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java b/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java index fcf3df7251b..43b9c4b2b23 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.nashorn.internal.runtime.test; +package jdk.nashorn.api.scripting.test; import java.util.Arrays; import javax.script.ScriptEngine; @@ -70,4 +70,4 @@ public class JDK_8148140_Test { assertEquals(RESULT, engine.eval("Function.prototype.apply.call(f, null, [1,2,3])")); } -} \ No newline at end of file +} From c63980511c2671a81ba32b977a040729f1abcf6a Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 29 Feb 2016 11:54:06 +0100 Subject: [PATCH 153/311] 8131027: JShell API/tool: suggest imports for a class Adding two new actions to JShell: add imports and create variable. Reviewed-by: rfield --- .../jshell/tool/ConsoleIOContext.java | 194 +++++++ .../jdk/internal/jshell/tool/JShellTool.java | 20 +- .../share/classes/jdk/jshell/Eval.java | 2 +- .../share/classes/jdk/jshell/JShell.java | 18 +- .../jdk/jshell/SourceCodeAnalysis.java | 85 ++- .../jdk/jshell/SourceCodeAnalysisImpl.java | 506 ++++++++++++++---- .../classes/jdk/jshell/TreeDissector.java | 17 +- .../test/jdk/jshell/ComputeFQNsTest.java | 118 ++++ langtools/test/jdk/jshell/InferTypeTest.java | 68 +++ langtools/test/jdk/jshell/KullaTesting.java | 35 ++ 10 files changed, 949 insertions(+), 114 deletions(-) create mode 100644 langtools/test/jdk/jshell/ComputeFQNsTest.java create mode 100644 langtools/test/jdk/jshell/InferTypeTest.java diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java index ebc11be5b75..53df5fe0221 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java @@ -26,6 +26,7 @@ package jdk.internal.jshell.tool; import jdk.jshell.SourceCodeAnalysis.CompletionInfo; +import jdk.jshell.SourceCodeAnalysis.QualifiedNames; import jdk.jshell.SourceCodeAnalysis.Suggestion; import java.awt.event.ActionListener; @@ -34,8 +35,12 @@ import java.io.InputStream; import java.io.PrintStream; import java.io.UncheckedIOException; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; @@ -144,6 +149,11 @@ class ConsoleIOContext extends IOContext { bind(DOCUMENTATION_SHORTCUT, (ActionListener) evt -> documentation(repl)); bind(CTRL_UP, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::previousSnippet)); bind(CTRL_DOWN, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::nextSnippet)); + for (FixComputer computer : FIX_COMPUTERS) { + for (String shortcuts : SHORTCUT_FIXES) { + bind(shortcuts + computer.shortcut, (ActionListener) evt -> fixes(computer)); + } + } } @Override @@ -216,6 +226,11 @@ class ConsoleIOContext extends IOContext { private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB private static final String CTRL_UP = "\033\133\061\073\065\101"; //Ctrl-UP private static final String CTRL_DOWN = "\033\133\061\073\065\102"; //Ctrl-DOWN + private static final String[] SHORTCUT_FIXES = { + "\033\015", //Alt-Enter (Linux) + "\033\133\061\067\176", //F6/Alt-F1 (Mac) + "\u001BO3P" //Alt-F1 (Linux) + }; private void documentation(JShellTool repl) { String buffer = in.getCursorBuffer().buffer.toString(); @@ -290,6 +305,185 @@ class ConsoleIOContext extends IOContext { history.fullHistoryReplace(source); } + //compute possible options/Fixes based on the selected FixComputer, present them to the user, + //and perform the selected one: + private void fixes(FixComputer computer) { + String input = prefix + in.getCursorBuffer().toString(); + int cursor = prefix.length() + in.getCursorBuffer().cursor; + FixResult candidates = computer.compute(repl, input, cursor); + + try { + final boolean printError = candidates.error != null && !candidates.error.isEmpty(); + if (printError) { + in.println(candidates.error); + } + if (candidates.fixes.isEmpty()) { + in.beep(); + if (printError) { + in.redrawLine(); + in.flush(); + } + } else if (candidates.fixes.size() == 1 && !computer.showMenu) { + if (printError) { + in.redrawLine(); + in.flush(); + } + candidates.fixes.get(0).perform(in); + } else { + List fixes = new ArrayList<>(candidates.fixes); + fixes.add(0, new Fix() { + @Override + public String displayName() { + return "Do nothing"; + } + + @Override + public void perform(ConsoleReader in) throws IOException { + in.redrawLine(); + } + }); + + Map char2Fix = new HashMap<>(); + in.println(); + for (int i = 0; i < fixes.size(); i++) { + Fix fix = fixes.get(i); + char2Fix.put((char) ('0' + i), fix); + in.println("" + i + ": " + fixes.get(i).displayName()); + } + in.print("Choice: "); + in.flush(); + int read; + + read = in.readCharacter(); + + Fix fix = char2Fix.get((char) read); + + if (fix == null) { + in.beep(); + fix = fixes.get(0); + } + + in.println(); + + fix.perform(in); + + in.flush(); + } + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + /** + * A possible action which the user can choose to perform. + */ + public interface Fix { + /** + * A name that should be shown to the user. + */ + public String displayName(); + /** + * Perform the given action. + */ + public void perform(ConsoleReader in) throws IOException; + } + + /** + * A factory for {@link Fix}es. + */ + public abstract static class FixComputer { + private final char shortcut; + private final boolean showMenu; + + /** + * Construct a new FixComputer. {@code shortcut} defines the key which should trigger this FixComputer. + * If {@code showMenu} is {@code false}, and this computer returns exactly one {@code Fix}, + * no options will be show to the user, and the given {@code Fix} will be performed. + */ + public FixComputer(char shortcut, boolean showMenu) { + this.shortcut = shortcut; + this.showMenu = showMenu; + } + + /** + * Compute possible actions for the given code. + */ + public abstract FixResult compute(JShellTool repl, String code, int cursor); + } + + /** + * A list of {@code Fix}es with a possible error that should be shown to the user. + */ + public static class FixResult { + public final List fixes; + public final String error; + + public FixResult(List fixes, String error) { + this.fixes = fixes; + this.error = error; + } + } + + private static final FixComputer[] FIX_COMPUTERS = new FixComputer[] { + new FixComputer('v', false) { //compute "Introduce variable" Fix: + @Override + public FixResult compute(JShellTool repl, String code, int cursor) { + String type = repl.analysis.analyzeType(code, cursor); + if (type == null) { + return new FixResult(Collections.emptyList(), null); + } + return new FixResult(Collections.singletonList(new Fix() { + @Override + public String displayName() { + return "Create variable"; + } + @Override + public void perform(ConsoleReader in) throws IOException { + in.redrawLine(); + in.setCursorPosition(0); + in.putString(type + " = "); + in.setCursorPosition(in.getCursorBuffer().cursor - 3); + in.flush(); + } + }), null); + } + }, + new FixComputer('i', true) { //compute "Add import" Fixes: + @Override + public FixResult compute(JShellTool repl, String code, int cursor) { + QualifiedNames res = repl.analysis.listQualifiedNames(code, cursor); + List fixes = new ArrayList<>(); + for (String fqn : res.getNames()) { + fixes.add(new Fix() { + @Override + public String displayName() { + return "import: " + fqn; + } + @Override + public void perform(ConsoleReader in) throws IOException { + repl.state.eval("import " + fqn + ";"); + in.println("Imported: " + fqn); + in.redrawLine(); + } + }); + } + if (res.isResolvable()) { + return new FixResult(Collections.emptyList(), + "\nThe identifier is resolvable in this context."); + } else { + String error = ""; + if (fixes.isEmpty()) { + error = "\nNo candidate fully qualified names found to import."; + } + if (!res.isUpToDate()) { + error += "\nResults may be incomplete; try again later for complete results."; + } + return new FixResult(fixes, error); + } + } + } + }; + private static final class JShellUnixTerminal extends NoInterruptUnixTerminal { private final StopDetectingInputStream input; diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index fe80db74ffe..fd14be2a612 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -988,13 +988,19 @@ public class JShellTool { CommandKind.HELP_SUBJECT)); registerCommand(new Command("shortcuts", "Describe shortcuts", "Supported shortcuts include:\n\n" + - " -- After entering the first few letters of a Java identifier,\n" + - " a jshell command, or, in some cases, a jshell command argument,\n" + - " press the key to complete the input.\n" + - " If there is more than one completion, show possible completions.\n" + - "Shift- -- After the name and open parenthesis of a method or constructor invocation,\n" + - " hold the key and press the to see a synopsis of all\n" + - " matching methods/constructors.\n", + " -- After entering the first few letters of a Java identifier,\n" + + " a jshell command, or, in some cases, a jshell command argument,\n" + + " press the key to complete the input.\n" + + " If there is more than one completion, show possible completions.\n" + + "Shift- -- After the name and open parenthesis of a method or constructor invocation,\n" + + " hold the key and press the to see a synopsis of all\n" + + " matching methods/constructors.\n" + + " v -- After a complete expression, press \" v\" to introduce a new variable\n" + + " whose type is based on the type of the expression.\n" + + " The \"\" is either Alt-F1 or Alt-Enter, depending on the platform.\n" + + " i -- After an unresolvable identifier, press \" i\" and jshell will propose\n" + + " possible fully qualified names based on the content of the specified classpath.\n" + + " The \"\" is either Alt-F1 or Alt-Enter, depending on the platform.\n", CommandKind.HELP_SUBJECT)); } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java index aede678b0b6..3f01908b782 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java @@ -420,7 +420,7 @@ class Eval { TaskFactory.AnalyzeTask at = trialCompile(guts); if (!at.hasErrors() && at.firstCuTree() != null) { return TreeDissector.createByFirstClass(at) - .typeOfReturnStatement(at.messages(), state.maps::fullClassNameAndPackageToClass); + .typeOfReturnStatement(at, state); } return null; } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java index 858aee274dd..2c731f5ba0c 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java @@ -346,10 +346,20 @@ public class JShell implements AutoCloseable { * @see JShell#onShutdown(java.util.function.Consumer) */ public List eval(String input) throws IllegalStateException { - checkIfAlive(); - List events = eval.eval(input); - events.forEach(this::notifyKeyStatusEvent); - return Collections.unmodifiableList(events); + SourceCodeAnalysisImpl a = sourceCodeAnalysis; + if (a != null) { + a.suspendIndexing(); + } + try { + checkIfAlive(); + List events = eval.eval(input); + events.forEach(this::notifyKeyStatusEvent); + return Collections.unmodifiableList(events); + } finally { + if (a != null) { + a.resumeIndexing(); + } + } } /** diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java index f9a31f1de76..3aee3204425 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java @@ -69,6 +69,28 @@ public abstract class SourceCodeAnalysis { */ public abstract String documentation(String input, int cursor); + /** + * Infer the type of the given expression. The expression spans from the beginning of {@code code} + * to the given {@code cursor} position. Returns null if the type of the expression cannot + * be inferred. + * + * @param code the expression for which the type should be inferred + * @param cursor current cursor position in the given code + * @return the inferred type, or null if it cannot be inferred + */ + public abstract String analyzeType(String code, int cursor); + + /** + * List qualified names known for the simple name in the given code immediately + * to the left of the given cursor position. The qualified names are gathered by inspecting the + * classpath used by eval (see {@link JShell#addToClasspath(java.lang.String)}). + * + * @param code the expression for which the candidate qualified names should be computed + * @param cursor current cursor position in the given code + * @return the known qualified names + */ + public abstract QualifiedNames listQualifiedNames(String code, int cursor); + /** * Internal only constructor */ @@ -80,7 +102,7 @@ public abstract class SourceCodeAnalysis { */ public static class CompletionInfo { - public CompletionInfo(Completeness completeness, int unitEndPos, String source, String remaining) { + CompletionInfo(Completeness completeness, int unitEndPos, String source, String remaining) { this.completeness = completeness; this.unitEndPos = unitEndPos; this.source = source; @@ -198,4 +220,65 @@ public abstract class SourceCodeAnalysis { */ public final boolean isSmart; } + + /** + * List of possible qualified names. + */ + public static final class QualifiedNames { + + private final List names; + private final int simpleNameLength; + private final boolean upToDate; + private final boolean resolvable; + + QualifiedNames(List names, int simpleNameLength, boolean upToDate, boolean resolvable) { + this.names = names; + this.simpleNameLength = simpleNameLength; + this.upToDate = upToDate; + this.resolvable = resolvable; + } + + /** + * Known qualified names for the given simple name in the original code. + * + * @return known qualified names + */ + public List getNames() { + return names; + } + + /** + * The length of the simple name in the original code for which the + * qualified names where gathered. + * + * @return the length of the simple name; -1 if there is no name immediately left to the cursor for + * which the candidates could be computed + */ + public int getSimpleNameLength() { + return simpleNameLength; + } + + /** + * Whether the result is based on up to date data. The + * {@link SourceCodeAnalysis#listQualifiedNames(java.lang.String, int) listQualifiedNames} + * method may return before the classpath is fully inspected, in which case this method will + * return {@code false}. If the result is based on a fully inspected classpath, this method + * will return {@code true}. + * + * @return true iff the results is based on up-to-date data + */ + public boolean isUpToDate() { + return upToDate; + } + + /** + * Whether the given simple name in the original code refers to a resolvable element. + * + * @return true iff the given simple name in the original code refers to a resolvable element + */ + public boolean isResolvable() { + return resolvable; + } + + } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index bbd3c286322..2fbb46a2722 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -79,13 +79,23 @@ import java.net.URI; import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Arrays; +import java.util.Collection; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -99,6 +109,7 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.lang.model.SourceVersion; + import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.QualifiedNameable; @@ -118,12 +129,30 @@ import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; * @author Robert Field */ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { + + private static final Map PATH_TO_INDEX = new HashMap<>(); + private static final ExecutorService INDEXER = Executors.newFixedThreadPool(1, r -> { + Thread t = new Thread(r); + t.setDaemon(true); + t.setUncaughtExceptionHandler((thread, ex) -> ex.printStackTrace()); + return t; + }); + private final JShell proc; private final CompletenessAnalyzer ca; + private final Map currentIndexes = new HashMap<>(); + private int indexVersion; + private int classpathVersion; + private final Object suspendLock = new Object(); + private int suspend; SourceCodeAnalysisImpl(JShell proc) { this.proc = proc; this.ca = new CompletenessAnalyzer(proc); + + int cpVersion = classpathVersion = 1; + + INDEXER.submit(() -> refreshIndexes(cpVersion)); } @Override @@ -203,6 +232,15 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { @Override public List completionSuggestions(String code, int cursor, int[] anchor) { + suspendIndexing(); + try { + return completionSuggestionsImpl(code, cursor, anchor); + } finally { + resumeIndexing(); + } + } + + private List completionSuggestionsImpl(String code, int cursor, int[] anchor) { code = code.substring(0, cursor); Matcher m = JAVA_IDENTIFIER.matcher(code); String identifier = ""; @@ -390,8 +428,11 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { long start = sp.getStartPosition(topLevel, tree); long end = sp.getEndPosition(topLevel, tree); + long prevEnd = deepest[0] != null ? sp.getEndPosition(topLevel, deepest[0].getLeaf()) : -1; - if (start <= pos && pos <= end) { + if (start <= pos && pos <= end && + (start != end || prevEnd != end || deepest[0] == null || + deepest[0].getParentPath().getLeaf() != getCurrentPath().getLeaf())) { deepest[0] = new TreePath(getCurrentPath(), tree); return super.scan(tree, p); } @@ -589,32 +630,28 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { .collect(toList()); } - private Set emptyContextPackages = null; - void classpathChanged() { - emptyContextPackages = null; + synchronized (currentIndexes) { + int cpVersion = ++classpathVersion; + + INDEXER.submit(() -> refreshIndexes(cpVersion)); + } } private Set listPackages(AnalyzeTask at, String enclosingPackage) { - Set packs; - - if (enclosingPackage.isEmpty() && emptyContextPackages != null) { - packs = emptyContextPackages; - } else { - packs = new HashSet<>(); - - listPackages(StandardLocation.PLATFORM_CLASS_PATH, enclosingPackage, packs); - listPackages(StandardLocation.CLASS_PATH, enclosingPackage, packs); - listPackages(StandardLocation.SOURCE_PATH, enclosingPackage, packs); - - if (enclosingPackage.isEmpty()) { - emptyContextPackages = packs; - } + synchronized (currentIndexes) { + return currentIndexes.values() + .stream() + .flatMap(idx -> idx.packages.stream()) + .filter(p -> enclosingPackage.isEmpty() || p.startsWith(enclosingPackage + ".")) + .map(p -> { + int dot = p.indexOf('.', enclosingPackage.length() + 1); + return dot == (-1) ? p : p.substring(0, dot); + }) + .distinct() + .map(p -> createPackageElement(at, p)) + .collect(Collectors.toSet()); } - - return packs.stream() - .map(pkg -> createPackageElement(at, pkg)) - .collect(Collectors.toSet()); } private PackageElement createPackageElement(AnalyzeTask at, String packageName) { @@ -625,79 +662,6 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { return existing; } - private void listPackages(Location loc, String enclosing, Set packs) { - Iterable paths = proc.taskFactory.fileManager().getLocationAsPaths(loc); - - if (paths == null) - return ; - - for (Path p : paths) { - listPackages(p, enclosing, packs); - } - } - - private void listPackages(Path path, String enclosing, Set packages) { - try { - if (path.equals(Paths.get("JRT_MARKER_FILE"))) { - FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/")); - Path modules = jrtfs.getPath("modules"); - try (DirectoryStream stream = Files.newDirectoryStream(modules)) { - for (Path c : stream) { - listDirectory(c, enclosing, packages); - } - } - } else if (!Files.isDirectory(path)) { - if (Files.exists(path)) { - ClassLoader cl = SourceCodeAnalysisImpl.class.getClassLoader(); - - try (FileSystem zip = FileSystems.newFileSystem(path, cl)) { - listDirectory(zip.getRootDirectories().iterator().next(), enclosing, packages); - } - } - } else { - listDirectory(path, enclosing, packages); - } - } catch (IOException ex) { - proc.debug(ex, "SourceCodeAnalysisImpl.listPackages(" + path.toString() + ", " + enclosing + ", " + packages + ")"); - } - } - - private void listDirectory(Path path, String enclosing, Set packages) throws IOException { - String separator = path.getFileSystem().getSeparator(); - Path resolved = path.resolve(enclosing.replace(".", separator)); - - if (Files.isDirectory(resolved)) { - try (DirectoryStream ds = Files.newDirectoryStream(resolved)) { - for (Path entry : ds) { - String name = pathName(entry); - - if (SourceVersion.isIdentifier(name) && - Files.isDirectory(entry) && - validPackageCandidate(entry)) { - packages.add(enclosing + (enclosing.isEmpty() ? "" : ".") + name); - } - } - } - } - } - - private boolean validPackageCandidate(Path p) throws IOException { - try (Stream dir = Files.list(p)) { - return dir.anyMatch(e -> Files.isDirectory(e) && SourceVersion.isIdentifier(pathName(e)) || - e.getFileName().toString().endsWith(".class")); - } - } - - private String pathName(Path p) { - String separator = p.getFileSystem().getSeparator(); - String name = p.getFileName().toString(); - - if (name.endsWith(separator)) //jars have '/' appended - name = name.substring(0, name.length() - separator.length()); - - return name; - } - private Element createArrayLengthSymbol(AnalyzeTask at, TypeMirror site) { Name length = Names.instance(at.getContext()).length; Type intType = Symtab.instance(at.getContext()).intType; @@ -965,6 +929,15 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { @Override public String documentation(String code, int cursor) { + suspendIndexing(); + try { + return documentationImpl(code, cursor); + } finally { + resumeIndexing(); + } + } + + private String documentationImpl(String code, int cursor) { code = code.substring(0, cursor); if (code.trim().isEmpty()) { //TODO: comment handling code += ";"; @@ -1074,4 +1047,347 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { } return arrayType; } + + @Override + public String analyzeType(String code, int cursor) { + code = code.substring(0, cursor); + CompletionInfo completionInfo = analyzeCompletion(code); + if (!completionInfo.completeness.isComplete) + return null; + if (completionInfo.completeness == Completeness.COMPLETE_WITH_SEMI) { + code += ";"; + } + + OuterWrap codeWrap; + switch (guessKind(code)) { + case IMPORT: case METHOD: case CLASS: case ENUM: + case INTERFACE: case ANNOTATION_TYPE: case VARIABLE: + return null; + default: + codeWrap = wrapInClass(Wrap.methodWrap(code)); + break; + } + AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); + SourcePositions sp = at.trees().getSourcePositions(); + CompilationUnitTree topLevel = at.firstCuTree(); + int pos = codeWrap.snippetIndexToWrapIndex(code.length()); + TreePath tp = pathFor(topLevel, sp, pos); + while (ExpressionTree.class.isAssignableFrom(tp.getParentPath().getLeaf().getKind().asInterface()) && + tp.getParentPath().getLeaf().getKind() != Kind.ERRONEOUS && + tp.getParentPath().getParentPath() != null) + tp = tp.getParentPath(); + TypeMirror type = at.trees().getTypeMirror(tp); + + if (type == null) + return null; + + switch (type.getKind()) { + case ERROR: case NONE: case OTHER: + case PACKAGE: case VOID: + return null; //not usable + case NULL: + type = at.getElements().getTypeElement("java.lang.Object").asType(); + break; + } + + return TreeDissector.printType(at, proc, type); + } + + @Override + public QualifiedNames listQualifiedNames(String code, int cursor) { + code = code.substring(0, cursor); + if (code.trim().isEmpty()) { + return new QualifiedNames(Collections.emptyList(), -1, true, false); + } + OuterWrap codeWrap; + switch (guessKind(code)) { + case IMPORT: + return new QualifiedNames(Collections.emptyList(), -1, true, false); + case METHOD: + codeWrap = wrapInClass(Wrap.classMemberWrap(code)); + break; + default: + codeWrap = wrapInClass(Wrap.methodWrap(code)); + break; + } + AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); + SourcePositions sp = at.trees().getSourcePositions(); + CompilationUnitTree topLevel = at.firstCuTree(); + TreePath tp = pathFor(topLevel, sp, codeWrap.snippetIndexToWrapIndex(code.length())); + if (tp.getLeaf().getKind() != Kind.IDENTIFIER) { + return new QualifiedNames(Collections.emptyList(), -1, true, false); + } + Scope scope = at.trees().getScope(tp); + TypeMirror type = at.trees().getTypeMirror(tp); + Element el = at.trees().getElement(tp); + + boolean erroneous = (type.getKind() == TypeKind.ERROR && el.getKind() == ElementKind.CLASS) || + (el.getKind() == ElementKind.PACKAGE && el.getEnclosedElements().isEmpty()); + String simpleName = ((IdentifierTree) tp.getLeaf()).getName().toString(); + boolean upToDate; + List result; + + synchronized (currentIndexes) { + upToDate = classpathVersion == indexVersion; + result = currentIndexes.values() + .stream() + .flatMap(idx -> idx.classSimpleName2FQN.getOrDefault(simpleName, + Collections.emptyList()).stream()) + .distinct() + .filter(fqn -> isAccessible(at, scope, fqn)) + .sorted() + .collect(Collectors.toList()); + } + + return new QualifiedNames(result, simpleName.length(), upToDate, !erroneous); + } + + private boolean isAccessible(AnalyzeTask at, Scope scope, String fqn) { + TypeElement type = at.getElements().getTypeElement(fqn); + if (type == null) + return false; + return at.trees().isAccessible(scope, type); + } + + //-------------------- + // classpath indexing: + //-------------------- + + //the indexing can be suspended when a more important task is running: + private void waitIndexingNotSuspended() { + boolean suspendedNotified = false; + synchronized (suspendLock) { + while (suspend > 0) { + if (!suspendedNotified) { + suspendedNotified = true; + } + try { + suspendLock.wait(); + } catch (InterruptedException ex) { + } + } + } + } + + public void suspendIndexing() { + synchronized (suspendLock) { + suspend++; + } + } + + public void resumeIndexing() { + synchronized (suspendLock) { + if (--suspend == 0) { + suspendLock.notifyAll(); + } + } + } + + //update indexes, either initially or after a classpath change: + private void refreshIndexes(int version) { + try { + Collection paths = new ArrayList<>(); + MemoryFileManager fm = proc.taskFactory.fileManager(); + + appendPaths(fm, StandardLocation.PLATFORM_CLASS_PATH, paths); + appendPaths(fm, StandardLocation.CLASS_PATH, paths); + appendPaths(fm, StandardLocation.SOURCE_PATH, paths); + + Map newIndexes = new HashMap<>(); + + //setup existing/last known data: + for (Path p : paths) { + ClassIndex index = PATH_TO_INDEX.get(p); + if (index != null) { + newIndexes.put(p, index); + } + } + + synchronized (currentIndexes) { + //temporary setting old data: + currentIndexes.clear(); + currentIndexes.putAll(newIndexes); + } + + //update/compute the indexes if needed: + for (Path p : paths) { + waitIndexingNotSuspended(); + + ClassIndex index = indexForPath(p); + newIndexes.put(p, index); + } + + synchronized (currentIndexes) { + currentIndexes.clear(); + currentIndexes.putAll(newIndexes); + } + } catch (Exception ex) { + proc.debug(ex, "SourceCodeAnalysisImpl.refreshIndexes(" + version + ")"); + } finally { + synchronized (currentIndexes) { + indexVersion = version; + } + } + } + + private void appendPaths(MemoryFileManager fm, Location loc, Collection paths) { + Iterable locationPaths = fm.getLocationAsPaths(loc); + if (locationPaths == null) + return ; + for (Path path : locationPaths) { + if (".".equals(path.toString())) { + //skip CWD + continue; + } + + paths.add(path); + } + } + + //create/update index a given JavaFileManager entry (which may be a JDK installation, a jar/zip file or a directory): + //if an index exists for the given entry, the existing index is kept unless the timestamp is modified + private ClassIndex indexForPath(Path path) { + if (isJRTMarkerFile(path)) { + FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/")); + Path modules = jrtfs.getPath("modules"); + return PATH_TO_INDEX.compute(path, (p, index) -> { + try { + long lastModified = Files.getLastModifiedTime(modules).toMillis(); + if (index == null || index.timestamp != lastModified) { + try (DirectoryStream stream = Files.newDirectoryStream(modules)) { + index = doIndex(lastModified, path, stream); + } + } + return index; + } catch (IOException ex) { + proc.debug(ex, "SourceCodeAnalysisImpl.indexesForPath(" + path.toString() + ")"); + return new ClassIndex(-1, path, Collections.emptySet(), Collections.emptyMap()); + } + }); + } else if (!Files.isDirectory(path)) { + if (Files.exists(path)) { + return PATH_TO_INDEX.compute(path, (p, index) -> { + try { + long lastModified = Files.getLastModifiedTime(p).toMillis(); + if (index == null || index.timestamp != lastModified) { + ClassLoader cl = SourceCodeAnalysisImpl.class.getClassLoader(); + + try (FileSystem zip = FileSystems.newFileSystem(path, cl)) { + index = doIndex(lastModified, path, zip.getRootDirectories()); + } + } + return index; + } catch (IOException ex) { + proc.debug(ex, "SourceCodeAnalysisImpl.indexesForPath(" + path.toString() + ")"); + return new ClassIndex(-1, path, Collections.emptySet(), Collections.emptyMap()); + } + }); + } else { + return new ClassIndex(-1, path, Collections.emptySet(), Collections.emptyMap()); + } + } else { + return PATH_TO_INDEX.compute(path, (p, index) -> { + //no persistence for directories, as we cannot check timestamps: + if (index == null) { + index = doIndex(-1, path, Arrays.asList(p)); + } + return index; + }); + } + } + + static boolean isJRTMarkerFile(Path path) { + return path.equals(Paths.get("JRT_MARKER_FILE")); + } + + //create an index based on the content of the given dirs; the original JavaFileManager entry is originalPath. + private ClassIndex doIndex(long timestamp, Path originalPath, Iterable dirs) { + Set packages = new HashSet<>(); + Map> classSimpleName2FQN = new HashMap<>(); + + for (Path d : dirs) { + try { + Files.walkFileTree(d, new FileVisitor() { + int depth; + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + waitIndexingNotSuspended(); + if (depth++ == 0) + return FileVisitResult.CONTINUE; + String dirName = dir.getFileName().toString(); + String sep = dir.getFileSystem().getSeparator(); + dirName = dirName.endsWith(sep) ? dirName.substring(0, dirName.length() - sep.length()) + : dirName; + if (SourceVersion.isIdentifier(dirName)) + return FileVisitResult.CONTINUE; + return FileVisitResult.SKIP_SUBTREE; + } + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + waitIndexingNotSuspended(); + if (file.getFileName().toString().endsWith(".class")) { + String relativePath = d.relativize(file).toString(); + String binaryName = relativePath.substring(0, relativePath.length() - 6).replace('/', '.'); + int packageDot = binaryName.lastIndexOf('.'); + if (packageDot > (-1)) { + packages.add(binaryName.substring(0, packageDot)); + } + String typeName = binaryName.replace('$', '.'); + addClassName2Map(classSimpleName2FQN, typeName); + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + depth--; + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException ex) { + proc.debug(ex, "doIndex(" + d.toString() + ")"); + } + } + + return new ClassIndex(timestamp, originalPath, packages, classSimpleName2FQN); + } + + private static void addClassName2Map(Map> classSimpleName2FQN, String typeName) { + int simpleNameDot = typeName.lastIndexOf('.'); + classSimpleName2FQN.computeIfAbsent(typeName.substring(simpleNameDot + 1), n -> new LinkedHashSet<>()) + .add(typeName); + } + + //holder for indexed data about a given path + public static final class ClassIndex { + public final long timestamp; + public final Path forPath; + public final Set packages; + public final Map> classSimpleName2FQN; + + public ClassIndex(long timestamp, Path forPath, Set packages, Map> classSimpleName2FQN) { + this.timestamp = timestamp; + this.forPath = forPath; + this.packages = packages; + this.classSimpleName2FQN = classSimpleName2FQN; + } + + } + + //for tests, to be able to wait until the indexing finishes: + public void waitBackgroundTaskFinished() throws Exception { + boolean upToDate; + synchronized (currentIndexes) { + upToDate = classpathVersion == indexVersion; + } + while (!upToDate) { + INDEXER.submit(() -> {}).get(); + synchronized (currentIndexes) { + upToDate = classpathVersion == indexVersion; + } + } + } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java index aad59b54a42..f59d10b0d3a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java @@ -41,13 +41,14 @@ import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.MethodType; import com.sun.tools.javac.code.Types; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; -import com.sun.tools.javac.util.JavacMessages; import com.sun.tools.javac.util.Name; import static jdk.jshell.Util.isDoIt; +import jdk.jshell.TaskFactory.AnalyzeTask; import jdk.jshell.Wrap.Range; + import java.util.List; import java.util.Locale; -import java.util.function.BinaryOperator; + import java.util.function.Predicate; import java.util.stream.Stream; import javax.lang.model.type.TypeMirror; @@ -209,7 +210,7 @@ class TreeDissector { } - ExpressionInfo typeOfReturnStatement(JavacMessages messages, BinaryOperator fullClassNameAndPackageToClass) { + ExpressionInfo typeOfReturnStatement(AnalyzeTask at, JShell state) { ExpressionInfo ei = new ExpressionInfo(); Tree unitTree = firstStatement(); if (unitTree instanceof ReturnTree) { @@ -219,9 +220,7 @@ class TreeDissector { if (viPath != null) { TypeMirror tm = trees().getTypeMirror(viPath); if (tm != null) { - Type type = (Type)tm; - TypePrinter tp = new TypePrinter(messages, fullClassNameAndPackageToClass, type); - ei.typeName = tp.visit(type, Locale.getDefault()); + ei.typeName = printType(at, state, tm); switch (tm.getKind()) { case VOID: case NONE: @@ -263,6 +262,12 @@ class TreeDissector { return sg.toString(); } + public static String printType(AnalyzeTask at, JShell state, TypeMirror type) { + Type typeImpl = (Type) type; + TypePrinter tp = new TypePrinter(at.messages(), state.maps::fullClassNameAndPackageToClass, typeImpl); + return tp.visit(typeImpl, Locale.getDefault()); + } + /** * Signature Generation */ diff --git a/langtools/test/jdk/jshell/ComputeFQNsTest.java b/langtools/test/jdk/jshell/ComputeFQNsTest.java new file mode 100644 index 00000000000..a16ec1cb0c9 --- /dev/null +++ b/langtools/test/jdk/jshell/ComputeFQNsTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015, 2016, 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 8131027 + * @summary Test Get FQNs + * @library /tools/lib + * @build KullaTesting TestingInputStream ToolBox Compiler + * @run testng ComputeFQNsTest + */ + +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +import jdk.jshell.SourceCodeAnalysis.QualifiedNames; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +@Test +public class ComputeFQNsTest extends KullaTesting { + + private final Compiler compiler = new Compiler(); + private final Path outDir = Paths.get("ComputeFQNsTest"); + + public void testAddImport() throws Exception { + compiler.compile(outDir, "package test1; public class TestClass { }", "package test2; public class TestClass { }"); + String jarName = "test.jar"; + compiler.jar(outDir, jarName, "test1/TestClass.class", "test2/TestClass.class"); + addToClasspath(compiler.getPath(outDir).resolve(jarName)); + + assertInferredFQNs("LinkedList", "java.util.LinkedList"); + assertInferredFQNs("ArrayList", "java.util.ArrayList"); + assertInferredFQNs("TestClass", "test1.TestClass", "test2.TestClass"); + assertInferredFQNs("CharSequence", "CharSequence".length(), true, "java.lang.CharSequence"); + assertInferredFQNs("unresolvable"); + assertInferredFQNs("void test(ArrayList", "ArrayList".length(), false, "java.util.ArrayList"); + assertInferredFQNs("void test(ArrayList l) throws InvocationTargetException", "InvocationTargetException".length(), false, "java.lang.reflect.InvocationTargetException"); + assertInferredFQNs("void test(ArrayList l) { ArrayList", "ArrayList".length(), false, "java.util.ArrayList"); + assertInferredFQNs("()", "ArrayList"); + assertInferredType("null", "Object"); + assertInferredType("1 + ", null); //incomplete + assertInferredType("undef", null); //unresolvable + assertEval("List l1;"); + assertEval("List l2;"); + assertEval("List l3;"); + assertInferredType("l1", "List"); + assertInferredType("l2", "List"); + assertInferredType("l3", "List"); + assertInferredType("l1.get(0)", "String"); + assertInferredType("l2.get(0)", "String"); + assertInferredType("l3.get(0)", "Object"); + assertInferredType("\"\" + 1", "String"); + assertEval("int i = 0;"); + assertInferredType("i++", "int"); + assertInferredType("++i", "int"); + assertInferredType("i == 0 ? l1.get(0) : l2.get(0)", "String"); + assertInferredType("", null); + assertInferredType("void test() { }", null); + assertInferredType("class Test { }", null); + assertInferredType("enum Test { A; }", null); + assertInferredType("interface Test { }", null); + assertInferredType("@interface Test { }", null); + assertInferredType("Object o;", null); + } + +} diff --git a/langtools/test/jdk/jshell/KullaTesting.java b/langtools/test/jdk/jshell/KullaTesting.java index c74ee862b75..c2ceeea1e06 100644 --- a/langtools/test/jdk/jshell/KullaTesting.java +++ b/langtools/test/jdk/jshell/KullaTesting.java @@ -24,6 +24,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.StringWriter; +import java.lang.reflect.Method; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -61,6 +62,7 @@ import jdk.jshell.SnippetEvent; import jdk.jshell.SourceCodeAnalysis; import jdk.jshell.SourceCodeAnalysis.CompletionInfo; import jdk.jshell.SourceCodeAnalysis.Completeness; +import jdk.jshell.SourceCodeAnalysis.QualifiedNames; import jdk.jshell.SourceCodeAnalysis.Suggestion; import jdk.jshell.UnresolvedReferenceException; import org.testng.annotations.AfterMethod; @@ -862,6 +864,8 @@ public class KullaTesting { } private List computeCompletions(String code, Boolean isSmart) { + waitIndexingFinished(); + int cursor = code.indexOf('|'); code = code.replace("|", ""); assertTrue(cursor > -1, "'|' expected, but not found in: " + code); @@ -874,6 +878,37 @@ public class KullaTesting { .collect(Collectors.toList()); } + public void assertInferredType(String code, String expectedType) { + String inferredType = getAnalysis().analyzeType(code, code.length()); + + assertEquals(inferredType, expectedType, "Input: " + code + ", " + inferredType); + } + + public void assertInferredFQNs(String code, String... fqns) { + assertInferredFQNs(code, code.length(), false, fqns); + } + + public void assertInferredFQNs(String code, int simpleNameLen, boolean resolvable, String... fqns) { + waitIndexingFinished(); + + QualifiedNames candidates = getAnalysis().listQualifiedNames(code, code.length()); + + assertEquals(candidates.getNames(), Arrays.asList(fqns), "Input: " + code + ", candidates=" + candidates.getNames()); + assertEquals(candidates.getSimpleNameLength(), simpleNameLen, "Input: " + code + ", simpleNameLen=" + candidates.getSimpleNameLength()); + assertEquals(candidates.isResolvable(), resolvable, "Input: " + code + ", resolvable=" + candidates.isResolvable()); + } + + protected void waitIndexingFinished() { + try { + Method waitBackgroundTaskFinished = getAnalysis().getClass().getDeclaredMethod("waitBackgroundTaskFinished"); + + waitBackgroundTaskFinished.setAccessible(true); + waitBackgroundTaskFinished.invoke(getAnalysis()); + } catch (Exception ex) { + throw new AssertionError("Cannot wait for indexing end.", ex); + } + } + public void assertDocumentation(String code, String... expected) { int cursor = code.indexOf('|'); code = code.replace("|", ""); From 190c092900e680cb72c423fadbdb811ba4ec9983 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Mon, 29 Feb 2016 13:06:03 +0100 Subject: [PATCH 154/311] 8150068: Log the main G1 phases at info level Reviewed-by: sjohanss, tschatzl --- .../src/share/vm/gc/g1/g1CollectorPolicy.cpp | 9 +- hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp | 421 ++++++------------ hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp | 23 +- hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp | 5 +- hotspot/src/share/vm/gc/g1/g1RemSet.cpp | 2 +- .../src/share/vm/gc/g1/workerDataArray.cpp | 50 ++- .../src/share/vm/gc/g1/workerDataArray.hpp | 46 +- .../share/vm/gc/g1/workerDataArray.inline.hpp | 64 ++- hotspot/src/share/vm/logging/logPrefix.hpp | 1 + hotspot/test/gc/g1/TestGCLogMessages.java | 68 +-- 10 files changed, 295 insertions(+), 394 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index bd98877eded..eda5e18e1a8 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -1117,14 +1117,15 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t _short_lived_surv_rate_group->start_adding_regions(); // Do that for any other surv rate groups + double scan_hcc_time_ms = ConcurrentG1Refine::hot_card_cache_enabled() ? average_time_ms(G1GCPhaseTimes::ScanHCC) : 0.0; + if (update_stats) { double cost_per_card_ms = 0.0; - double cost_scan_hcc = average_time_ms(G1GCPhaseTimes::ScanHCC); if (_pending_cards > 0) { - cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS) - cost_scan_hcc) / (double) _pending_cards; + cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms) / (double) _pending_cards; _cost_per_card_ms_seq->add(cost_per_card_ms); } - _cost_scan_hcc_seq->add(cost_scan_hcc); + _cost_scan_hcc_seq->add(scan_hcc_time_ms); double cost_per_entry_ms = 0.0; if (cards_scanned > 10) { @@ -1214,8 +1215,6 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t // Note that _mmu_tracker->max_gc_time() returns the time in seconds. double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; - double scan_hcc_time_ms = average_time_ms(G1GCPhaseTimes::ScanHCC); - if (update_rs_time_goal_ms < scan_hcc_time_ms) { log_debug(gc, ergo, refine)("Adjust concurrent refinement thresholds (scanning the HCC expected to take longer than Update RS time goal)." "Update RS time goal: %1.2fms Scan HCC time: %1.2fms", diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index e8c852b051f..b5dce4ffc3d 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -28,109 +28,70 @@ #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/g1/workerDataArray.inline.hpp" -#include "memory/allocation.hpp" +#include "memory/resourceArea.hpp" #include "logging/log.hpp" #include "runtime/timer.hpp" #include "runtime/os.hpp" -// Helper class for avoiding interleaved logging -class LineBuffer: public StackObj { - -private: - static const int BUFFER_LEN = 1024; - static const int INDENT_CHARS = 3; - char _buffer[BUFFER_LEN]; - int _indent_level; - int _cur; - - void vappend(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0) { - int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap); - if (res != -1) { - _cur += res; - } else { - DEBUG_ONLY(warning("buffer too small in LineBuffer");) - _buffer[BUFFER_LEN -1] = 0; - _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again - } - } - -public: - explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) { - for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) { - _buffer[_cur] = ' '; - } - } - -#ifndef PRODUCT - ~LineBuffer() { - assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?"); - } -#endif - - void append(const char* format, ...) ATTRIBUTE_PRINTF(2, 3) { - va_list ap; - va_start(ap, format); - vappend(format, ap); - va_end(ap); - } - - const char* to_string() { - _cur = _indent_level * INDENT_CHARS; - return _buffer; - } -}; - -static const char* Indents[4] = {"", " ", " ", " "}; +static const char* Indents[5] = {"", " ", " ", " ", " "}; G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _max_gc_threads(max_gc_threads) { assert(max_gc_threads > 0, "Must have some GC threads"); - _gc_par_phases[GCWorkerStart] = new WorkerDataArray(max_gc_threads, "GC Worker Start:", false, 2); - _gc_par_phases[ExtRootScan] = new WorkerDataArray(max_gc_threads, "Ext Root Scanning:", true, 2); + _gc_par_phases[GCWorkerStart] = new WorkerDataArray(max_gc_threads, "GC Worker Start (ms):"); + _gc_par_phases[ExtRootScan] = new WorkerDataArray(max_gc_threads, "Ext Root Scanning (ms):"); // Root scanning phases - _gc_par_phases[ThreadRoots] = new WorkerDataArray(max_gc_threads, "Thread Roots:", true, 3); - _gc_par_phases[StringTableRoots] = new WorkerDataArray(max_gc_threads, "StringTable Roots:", true, 3); - _gc_par_phases[UniverseRoots] = new WorkerDataArray(max_gc_threads, "Universe Roots:", true, 3); - _gc_par_phases[JNIRoots] = new WorkerDataArray(max_gc_threads, "JNI Handles Roots:", true, 3); - _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray(max_gc_threads, "ObjectSynchronizer Roots:", true, 3); - _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray(max_gc_threads, "FlatProfiler Roots:", true, 3); - _gc_par_phases[ManagementRoots] = new WorkerDataArray(max_gc_threads, "Management Roots:", true, 3); - _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray(max_gc_threads, "SystemDictionary Roots:", true, 3); - _gc_par_phases[CLDGRoots] = new WorkerDataArray(max_gc_threads, "CLDG Roots:", true, 3); - _gc_par_phases[JVMTIRoots] = new WorkerDataArray(max_gc_threads, "JVMTI Roots:", true, 3); - _gc_par_phases[CMRefRoots] = new WorkerDataArray(max_gc_threads, "CM RefProcessor Roots:", true, 3); - _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray(max_gc_threads, "Wait For Strong CLD:", true, 3); - _gc_par_phases[WeakCLDRoots] = new WorkerDataArray(max_gc_threads, "Weak CLD Roots:", true, 3); - _gc_par_phases[SATBFiltering] = new WorkerDataArray(max_gc_threads, "SATB Filtering:", true, 3); + _gc_par_phases[ThreadRoots] = new WorkerDataArray(max_gc_threads, "Thread Roots (ms):"); + _gc_par_phases[StringTableRoots] = new WorkerDataArray(max_gc_threads, "StringTable Roots (ms):"); + _gc_par_phases[UniverseRoots] = new WorkerDataArray(max_gc_threads, "Universe Roots (ms):"); + _gc_par_phases[JNIRoots] = new WorkerDataArray(max_gc_threads, "JNI Handles Roots (ms):"); + _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray(max_gc_threads, "ObjectSynchronizer Roots (ms):"); + _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray(max_gc_threads, "FlatProfiler Roots (ms):"); + _gc_par_phases[ManagementRoots] = new WorkerDataArray(max_gc_threads, "Management Roots (ms):"); + _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray(max_gc_threads, "SystemDictionary Roots (ms):"); + _gc_par_phases[CLDGRoots] = new WorkerDataArray(max_gc_threads, "CLDG Roots (ms):"); + _gc_par_phases[JVMTIRoots] = new WorkerDataArray(max_gc_threads, "JVMTI Roots (ms):"); + _gc_par_phases[CMRefRoots] = new WorkerDataArray(max_gc_threads, "CM RefProcessor Roots (ms):"); + _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray(max_gc_threads, "Wait For Strong CLD (ms):"); + _gc_par_phases[WeakCLDRoots] = new WorkerDataArray(max_gc_threads, "Weak CLD Roots (ms):"); + _gc_par_phases[SATBFiltering] = new WorkerDataArray(max_gc_threads, "SATB Filtering (ms):"); - _gc_par_phases[UpdateRS] = new WorkerDataArray(max_gc_threads, "Update RS:", true, 2); - _gc_par_phases[ScanHCC] = new WorkerDataArray(max_gc_threads, "Scan HCC:", true, 3); - _gc_par_phases[ScanHCC]->set_enabled(ConcurrentG1Refine::hot_card_cache_enabled()); - _gc_par_phases[ScanRS] = new WorkerDataArray(max_gc_threads, "Scan RS:", true, 2); - _gc_par_phases[CodeRoots] = new WorkerDataArray(max_gc_threads, "Code Root Scanning:", true, 2); - _gc_par_phases[ObjCopy] = new WorkerDataArray(max_gc_threads, "Object Copy:", true, 2); - _gc_par_phases[Termination] = new WorkerDataArray(max_gc_threads, "Termination:", true, 2); - _gc_par_phases[GCWorkerTotal] = new WorkerDataArray(max_gc_threads, "GC Worker Total:", true, 2); - _gc_par_phases[GCWorkerEnd] = new WorkerDataArray(max_gc_threads, "GC Worker End:", false, 2); - _gc_par_phases[Other] = new WorkerDataArray(max_gc_threads, "GC Worker Other:", true, 2); + _gc_par_phases[UpdateRS] = new WorkerDataArray(max_gc_threads, "Update RS (ms):"); + if (ConcurrentG1Refine::hot_card_cache_enabled()) { + _gc_par_phases[ScanHCC] = new WorkerDataArray(max_gc_threads, "Scan HCC (ms):"); + } else { + _gc_par_phases[ScanHCC] = NULL; + } + _gc_par_phases[ScanRS] = new WorkerDataArray(max_gc_threads, "Scan RS (ms):"); + _gc_par_phases[CodeRoots] = new WorkerDataArray(max_gc_threads, "Code Root Scanning (ms):"); + _gc_par_phases[ObjCopy] = new WorkerDataArray(max_gc_threads, "Object Copy (ms):"); + _gc_par_phases[Termination] = new WorkerDataArray(max_gc_threads, "Termination (ms):"); + _gc_par_phases[GCWorkerTotal] = new WorkerDataArray(max_gc_threads, "GC Worker Total (ms):"); + _gc_par_phases[GCWorkerEnd] = new WorkerDataArray(max_gc_threads, "GC Worker End (ms):"); + _gc_par_phases[Other] = new WorkerDataArray(max_gc_threads, "GC Worker Other (ms):"); - _update_rs_processed_buffers = new WorkerDataArray(max_gc_threads, "Processed Buffers:", true, 3); + _update_rs_processed_buffers = new WorkerDataArray(max_gc_threads, "Processed Buffers:"); _gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_processed_buffers); - _termination_attempts = new WorkerDataArray(max_gc_threads, "Termination Attempts:", true, 3); + _termination_attempts = new WorkerDataArray(max_gc_threads, "Termination Attempts:"); _gc_par_phases[Termination]->link_thread_work_items(_termination_attempts); - _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray(max_gc_threads, "Queue Fixup:", true, 2); - _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray(max_gc_threads, "Table Fixup:", true, 2); + if (UseStringDeduplication) { + _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray(max_gc_threads, "Queue Fixup (ms):"); + _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray(max_gc_threads, "Table Fixup (ms):"); + } else { + _gc_par_phases[StringDedupQueueFixup] = NULL; + _gc_par_phases[StringDedupTableFixup] = NULL; + } - _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty:", true, 3); - _redirtied_cards = new WorkerDataArray(max_gc_threads, "Redirtied Cards:", true, 3); + _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty (ms):"); + _redirtied_cards = new WorkerDataArray(max_gc_threads, "Redirtied Cards:"); _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards); - _gc_par_phases[PreserveCMReferents] = new WorkerDataArray(max_gc_threads, "Parallel Preserve CM Refs:", true, 3); + _gc_par_phases[PreserveCMReferents] = new WorkerDataArray(max_gc_threads, "Parallel Preserve CM Refs (ms):"); } void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { @@ -142,11 +103,10 @@ void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { _external_accounted_time_ms = 0.0; for (int i = 0; i < GCParPhasesSentinel; i++) { - _gc_par_phases[i]->reset(); + if (_gc_par_phases[i] != NULL) { + _gc_par_phases[i]->reset(); + } } - - _gc_par_phases[StringDedupQueueFixup]->set_enabled(G1StringDedup::is_enabled()); - _gc_par_phases[StringDedupTableFixup]->set_enabled(G1StringDedup::is_enabled()); } void G1GCPhaseTimes::note_gc_end() { @@ -168,43 +128,10 @@ void G1GCPhaseTimes::note_gc_end() { } for (int i = 0; i < GCParPhasesSentinel; i++) { - _gc_par_phases[i]->verify(_active_gc_threads); - } -} - -void G1GCPhaseTimes::print_stats(const char* indent, const char* str, double value) { - log_debug(gc, phases)("%s%s: %.1lf ms", indent, str, value); -} - -double G1GCPhaseTimes::accounted_time_ms() { - // First subtract any externally accounted time - double misc_time_ms = _external_accounted_time_ms; - - // Subtract the root region scanning wait time. It's initialized to - // zero at the start of the pause. - misc_time_ms += _root_region_scan_wait_time_ms; - - misc_time_ms += _cur_collection_par_time_ms; - - // Now subtract the time taken to fix up roots in generated code - misc_time_ms += _cur_collection_code_root_fixup_time_ms; - - // Strong code root purge time - misc_time_ms += _cur_strong_code_root_purge_time_ms; - - if (G1StringDedup::is_enabled()) { - // String dedup fixup time - misc_time_ms += _cur_string_dedup_fixup_time_ms; + if (_gc_par_phases[i] != NULL) { + _gc_par_phases[i]->verify(_active_gc_threads); } - - // Subtract the time taken to clean the card table from the - // current value of "other time" - misc_time_ms += _cur_clear_ct_time_ms; - - // Remove expand heap time from "other time" - misc_time_ms += _cur_expand_heap_time_ms; - - return misc_time_ms; + } } // record the time a phase took in seconds @@ -226,196 +153,144 @@ double G1GCPhaseTimes::average_time_ms(GCParPhases phase) { return _gc_par_phases[phase]->average(_active_gc_threads) * 1000.0; } -double G1GCPhaseTimes::get_time_ms(GCParPhases phase, uint worker_i) { - return _gc_par_phases[phase]->get(worker_i) * 1000.0; -} - -double G1GCPhaseTimes::sum_time_ms(GCParPhases phase) { - return _gc_par_phases[phase]->sum(_active_gc_threads) * 1000.0; -} - -double G1GCPhaseTimes::min_time_ms(GCParPhases phase) { - return _gc_par_phases[phase]->minimum(_active_gc_threads) * 1000.0; -} - -double G1GCPhaseTimes::max_time_ms(GCParPhases phase) { - return _gc_par_phases[phase]->maximum(_active_gc_threads) * 1000.0; -} - -size_t G1GCPhaseTimes::get_thread_work_item(GCParPhases phase, uint worker_i) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->get(worker_i); -} - size_t G1GCPhaseTimes::sum_thread_work_items(GCParPhases phase) { assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); return _gc_par_phases[phase]->thread_work_items()->sum(_active_gc_threads); } -double G1GCPhaseTimes::average_thread_work_items(GCParPhases phase) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->average(_active_gc_threads); +template +void G1GCPhaseTimes::details(T* phase, const char* indent) { + LogHandle(gc, phases, task) log; + if (log.is_level(LogLevel::Trace)) { + outputStream* trace_out = log.trace_stream(); + trace_out->print("%s", indent); + phase->print_details_on(trace_out, _active_gc_threads); + } } -size_t G1GCPhaseTimes::min_thread_work_items(GCParPhases phase) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->minimum(_active_gc_threads); +void G1GCPhaseTimes::log_phase(WorkerDataArray* phase, uint indent, outputStream* out, bool print_sum) { + out->print("%s", Indents[indent]); + phase->print_summary_on(out, _active_gc_threads, print_sum); + details(phase, Indents[indent]); + + WorkerDataArray* work_items = phase->thread_work_items(); + if (work_items != NULL) { + out->print("%s", Indents[indent + 1]); + work_items->print_summary_on(out, _active_gc_threads, true); + details(work_items, Indents[indent + 1]); + } } -size_t G1GCPhaseTimes::max_thread_work_items(GCParPhases phase) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->maximum(_active_gc_threads); +void G1GCPhaseTimes::debug_phase(WorkerDataArray* phase) { + LogHandle(gc, phases) log; + if (log.is_level(LogLevel::Debug)) { + ResourceMark rm; + log_phase(phase, 2, log.debug_stream(), true); + } } -class G1GCParPhasePrinter : public StackObj { - G1GCPhaseTimes* _phase_times; - public: - G1GCParPhasePrinter(G1GCPhaseTimes* phase_times) : _phase_times(phase_times) {} - - void print(G1GCPhaseTimes::GCParPhases phase_id) { - WorkerDataArray* phase = _phase_times->_gc_par_phases[phase_id]; - - if (phase->_length == 1) { - print_single_length(phase_id, phase); - } else { - print_multi_length(phase_id, phase); - } +void G1GCPhaseTimes::trace_phase(WorkerDataArray* phase, bool print_sum) { + LogHandle(gc, phases) log; + if (log.is_level(LogLevel::Trace)) { + ResourceMark rm; + log_phase(phase, 3, log.trace_stream(), print_sum); } +} +#define PHASE_DOUBLE_FORMAT "%s%s: %.1lfms" +#define PHASE_SIZE_FORMAT "%s%s: " SIZE_FORMAT - private: - void print_single_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* phase) { - // No need for min, max, average and sum for only one worker - log_debug(gc, phases)("%s%s: %.1lf", Indents[phase->_indent_level], phase->_title, _phase_times->get_time_ms(phase_id, 0)); +#define info_line(str, value) \ + log_info(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[1], str, value); - WorkerDataArray* work_items = phase->_thread_work_items; - if (work_items != NULL) { - log_debug(gc, phases)("%s%s: " SIZE_FORMAT, Indents[work_items->_indent_level], work_items->_title, _phase_times->sum_thread_work_items(phase_id)); - } - } +#define debug_line(str, value) \ + log_debug(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[2], str, value); - void print_time_values(const char* indent, G1GCPhaseTimes::GCParPhases phase_id) { - if (log_is_enabled(Trace, gc)) { - LineBuffer buf(0); - uint active_length = _phase_times->_active_gc_threads; - for (uint i = 0; i < active_length; ++i) { - buf.append(" %4.1lf", _phase_times->get_time_ms(phase_id, i)); - } - const char* line = buf.to_string(); - log_trace(gc, phases)("%s%-25s%s", indent, "", line); - } - } +#define trace_line(str, value) \ + log_trace(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[3], str, value); - void print_count_values(const char* indent, G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* thread_work_items) { - if (log_is_enabled(Trace, gc)) { - LineBuffer buf(0); - uint active_length = _phase_times->_active_gc_threads; - for (uint i = 0; i < active_length; ++i) { - buf.append(" " SIZE_FORMAT, _phase_times->get_thread_work_item(phase_id, i)); - } - const char* line = buf.to_string(); - log_trace(gc, phases)("%s%-25s%s", indent, "", line); - } - } +#define trace_line_sz(str, value) \ + log_trace(gc, phases)(PHASE_SIZE_FORMAT, Indents[3], str, value); - void print_thread_work_items(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* thread_work_items) { - const char* indent = Indents[thread_work_items->_indent_level]; +#define trace_line_ms(str, value) \ + log_trace(gc, phases)(PHASE_SIZE_FORMAT, Indents[3], str, value); - assert(thread_work_items->_print_sum, "%s does not have print sum true even though it is a count", thread_work_items->_title); - - log_debug(gc, phases)("%s%-25s Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT ", Sum: " SIZE_FORMAT, - indent, thread_work_items->_title, - _phase_times->min_thread_work_items(phase_id), _phase_times->average_thread_work_items(phase_id), _phase_times->max_thread_work_items(phase_id), - _phase_times->max_thread_work_items(phase_id) - _phase_times->min_thread_work_items(phase_id), _phase_times->sum_thread_work_items(phase_id)); - - print_count_values(indent, phase_id, thread_work_items); - } - - void print_multi_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* phase) { - const char* indent = Indents[phase->_indent_level]; - - if (phase->_print_sum) { - log_debug(gc, phases)("%s%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf, Sum: %4.1lf", - indent, phase->_title, - _phase_times->min_time_ms(phase_id), _phase_times->average_time_ms(phase_id), _phase_times->max_time_ms(phase_id), - _phase_times->max_time_ms(phase_id) - _phase_times->min_time_ms(phase_id), _phase_times->sum_time_ms(phase_id)); - } else { - log_debug(gc, phases)("%s%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", - indent, phase->_title, - _phase_times->min_time_ms(phase_id), _phase_times->average_time_ms(phase_id), _phase_times->max_time_ms(phase_id), - _phase_times->max_time_ms(phase_id) - _phase_times->min_time_ms(phase_id)); - } - - print_time_values(indent, phase_id); - - if (phase->_thread_work_items != NULL) { - print_thread_work_items(phase_id, phase->_thread_work_items); - } - } -}; +#define info_line_and_account(str, value) \ + info_line(str, value); \ + accounted_time_ms += value; void G1GCPhaseTimes::print() { note_gc_end(); - G1GCParPhasePrinter par_phase_printer(this); - + double accounted_time_ms = _external_accounted_time_ms; if (_root_region_scan_wait_time_ms > 0.0) { - print_stats(Indents[1], "Root Region Scan Waiting", _root_region_scan_wait_time_ms); + info_line_and_account("Root Region Scan Waiting", _root_region_scan_wait_time_ms); } - print_stats(Indents[1], "Parallel Time", _cur_collection_par_time_ms); - for (int i = 0; i <= GCMainParPhasesLast; i++) { - par_phase_printer.print((GCParPhases) i); + info_line_and_account("Evacuate Collection Set", _cur_collection_par_time_ms); + trace_phase(_gc_par_phases[GCWorkerStart], false); + debug_phase(_gc_par_phases[ExtRootScan]); + for (int i = ThreadRoots; i <= SATBFiltering; i++) { + trace_phase(_gc_par_phases[i]); } + debug_phase(_gc_par_phases[UpdateRS]); + if (ConcurrentG1Refine::hot_card_cache_enabled()) { + trace_phase(_gc_par_phases[ScanHCC]); + } + debug_phase(_gc_par_phases[ScanRS]); + debug_phase(_gc_par_phases[CodeRoots]); + debug_phase(_gc_par_phases[ObjCopy]); + debug_phase(_gc_par_phases[Termination]); + debug_phase(_gc_par_phases[Other]); + debug_phase(_gc_par_phases[GCWorkerTotal]); + trace_phase(_gc_par_phases[GCWorkerEnd], false); + + info_line_and_account("Code Roots", _cur_collection_code_root_fixup_time_ms + _cur_strong_code_root_purge_time_ms); + debug_line("Code Roots Fixup", _cur_collection_code_root_fixup_time_ms); + debug_line("Code Roots Purge", _cur_strong_code_root_purge_time_ms); - print_stats(Indents[1], "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); - print_stats(Indents[1], "Code Root Purge", _cur_strong_code_root_purge_time_ms); if (G1StringDedup::is_enabled()) { - print_stats(Indents[1], "String Dedup Fixup", _cur_string_dedup_fixup_time_ms); - for (int i = StringDedupPhasesFirst; i <= StringDedupPhasesLast; i++) { - par_phase_printer.print((GCParPhases) i); - } + info_line_and_account("String Dedup Fixup", _cur_string_dedup_fixup_time_ms); + debug_phase(_gc_par_phases[StringDedupQueueFixup]); + debug_phase(_gc_par_phases[StringDedupTableFixup]); } - print_stats(Indents[1], "Clear CT", _cur_clear_ct_time_ms); - print_stats(Indents[1], "Expand Heap After Collection", _cur_expand_heap_time_ms); - double misc_time_ms = _gc_pause_time_ms - accounted_time_ms(); - print_stats(Indents[1], "Other", misc_time_ms); + info_line_and_account("Clear Card Table", _cur_clear_ct_time_ms); + info_line_and_account("Expand Heap After Collection", _cur_expand_heap_time_ms); + + double free_cset_time = _recorded_young_free_cset_time_ms + _recorded_non_young_free_cset_time_ms; + info_line_and_account("Free Collection Set", free_cset_time); + debug_line("Young Free Collection Set", _recorded_young_free_cset_time_ms); + debug_line("Non-Young Free Collection Set", _recorded_non_young_free_cset_time_ms); + info_line_and_account("Merge Per-Thread State", _recorded_merge_pss_time_ms); + + info_line("Other", _gc_pause_time_ms - accounted_time_ms); if (_cur_verify_before_time_ms > 0.0) { - print_stats(Indents[2], "Verify Before", _cur_verify_before_time_ms); + debug_line("Verify Before", _cur_verify_before_time_ms); } if (G1CollectedHeap::heap()->evacuation_failed()) { double evac_fail_handling = _cur_evac_fail_recalc_used + _cur_evac_fail_remove_self_forwards + _cur_evac_fail_restore_remsets; - print_stats(Indents[2], "Evacuation Failure", evac_fail_handling); - log_trace(gc, phases)("%sRecalculate Used: %.1lf ms", Indents[3], _cur_evac_fail_recalc_used); - log_trace(gc, phases)("%sRemove Self Forwards: %.1lf ms", Indents[3], _cur_evac_fail_remove_self_forwards); - log_trace(gc, phases)("%sRestore RemSet: %.1lf ms", Indents[3], _cur_evac_fail_restore_remsets); + debug_line("Evacuation Failure", evac_fail_handling); + trace_line("Recalculate Used", _cur_evac_fail_recalc_used); + trace_line("Remove Self Forwards",_cur_evac_fail_remove_self_forwards); + trace_line("Restore RemSet", _cur_evac_fail_restore_remsets); } - print_stats(Indents[2], "Choose CSet", - (_recorded_young_cset_choice_time_ms + - _recorded_non_young_cset_choice_time_ms)); - print_stats(Indents[2], "Preserve CM Refs", _recorded_preserve_cm_referents_time_ms); - print_stats(Indents[2], "Ref Proc", _cur_ref_proc_time_ms); - print_stats(Indents[2], "Ref Enq", _cur_ref_enq_time_ms); - print_stats(Indents[2], "Redirty Cards", _recorded_redirty_logged_cards_time_ms); - par_phase_printer.print(RedirtyCards); - par_phase_printer.print(PreserveCMReferents); + debug_line("Choose CSet", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); + debug_line("Preserve CM Refs", _recorded_preserve_cm_referents_time_ms); + debug_line("Ref Proc", _cur_ref_proc_time_ms); + debug_line("Ref Enq", _cur_ref_enq_time_ms); + debug_line("Redirty Cards", _recorded_redirty_logged_cards_time_ms); + trace_phase(_gc_par_phases[RedirtyCards]); + trace_phase(_gc_par_phases[PreserveCMReferents]); if (G1EagerReclaimHumongousObjects) { - print_stats(Indents[2], "Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); - - log_trace(gc, phases)("%sHumongous Total: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_total); - log_trace(gc, phases)("%sHumongous Candidate: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_candidates); - print_stats(Indents[2], "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); - log_trace(gc, phases)("%sHumongous Reclaimed: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_reclaimed); + debug_line("Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); + trace_line_sz("Humongous Total", _cur_fast_reclaim_humongous_total); + trace_line_sz("Humongous Candidate", _cur_fast_reclaim_humongous_candidates); + debug_line("Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); + trace_line_sz("Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed); } - print_stats(Indents[2], "Free CSet", - (_recorded_young_free_cset_time_ms + - _recorded_non_young_free_cset_time_ms)); - log_trace(gc, phases)("%sYoung Free CSet: %.1lf ms", Indents[3], _recorded_young_free_cset_time_ms); - log_trace(gc, phases)("%sNon-Young Free CSet: %.1lf ms", Indents[3], _recorded_non_young_free_cset_time_ms); - print_stats(Indents[2], "Merge Per-Thread State", _recorded_merge_pss_time_ms); if (_cur_verify_after_time_ms > 0.0) { - print_stats(Indents[2], "Verify After", _cur_verify_after_time_ms); + debug_line("Verify After", _cur_verify_after_time_ms); } } diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp index c474659a849..e87075b5e93 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp @@ -32,8 +32,6 @@ class LineBuffer; template class WorkerDataArray; class G1GCPhaseTimes : public CHeapObj { - friend class G1GCParPhasePrinter; - uint _active_gc_threads; uint _max_gc_threads; jlong _gc_start_counter; @@ -125,11 +123,14 @@ class G1GCPhaseTimes : public CHeapObj { double _cur_verify_before_time_ms; double _cur_verify_after_time_ms; - // Helper methods for detailed logging - void print_stats(const char*, const char* str, double value); - void note_gc_end(); + template + void details(T* phase, const char* indent); + void log_phase(WorkerDataArray* phase, uint indent, outputStream* out, bool print_sum); + void debug_phase(WorkerDataArray* phase); + void trace_phase(WorkerDataArray* phase, bool print_sum = true); + public: G1GCPhaseTimes(uint max_gc_threads); void note_gc_start(uint active_gc_threads); @@ -148,16 +149,6 @@ class G1GCPhaseTimes : public CHeapObj { size_t sum_thread_work_items(GCParPhases phase); - private: - double get_time_ms(GCParPhases phase, uint worker_i); - double sum_time_ms(GCParPhases phase); - double min_time_ms(GCParPhases phase); - double max_time_ms(GCParPhases phase); - size_t get_thread_work_item(GCParPhases phase, uint worker_i); - double average_thread_work_items(GCParPhases phase); - size_t min_thread_work_items(GCParPhases phase); - size_t max_thread_work_items(GCParPhases phase); - public: void record_clear_ct_time(double ms) { @@ -263,8 +254,6 @@ class G1GCPhaseTimes : public CHeapObj { _external_accounted_time_ms += time_ms; } - double accounted_time_ms(); - double cur_collection_start_sec() { return _cur_collection_start_sec; } diff --git a/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp b/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp index b7c176d632b..013be1a12f8 100644 --- a/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp +++ b/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp @@ -81,10 +81,7 @@ jbyte* G1HotCardCache::insert(jbyte* card_ptr) { } void G1HotCardCache::drain(CardTableEntryClosure* cl, uint worker_i) { - if (!default_use_cache()) { - assert(_hot_cache == NULL, "Logic"); - return; - } + assert(default_use_cache(), "Drain only necessary if we use the hot card cache."); assert(_hot_cache != NULL, "Logic"); assert(!use_cache(), "cache should be disabled"); diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index 3d2917a2184..8c31430e185 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -238,7 +238,7 @@ void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) { RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i); - { + if (ConcurrentG1Refine::hot_card_cache_enabled()) { // Apply the closure to the entries of the hot card cache. G1GCParPhaseTimesTracker y(_g1p->phase_times(), G1GCPhaseTimes::ScanHCC, worker_i); _g1->iterate_hcc_closure(&into_cset_update_rs_cl, worker_i); diff --git a/hotspot/src/share/vm/gc/g1/workerDataArray.cpp b/hotspot/src/share/vm/gc/g1/workerDataArray.cpp index 0e3305d5c2a..62b66559a53 100644 --- a/hotspot/src/share/vm/gc/g1/workerDataArray.cpp +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.cpp @@ -24,18 +24,53 @@ #include "precompiled.hpp" #include "gc/g1/workerDataArray.inline.hpp" +#include "utilities/ostream.hpp" + +template <> +void WorkerDataArray::WDAPrinter::summary(outputStream* out, const char* title, double min, double avg, double max, double diff, double sum, bool print_sum) { + out->print("%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", title, min * MILLIUNITS, avg * MILLIUNITS, max * MILLIUNITS, diff* MILLIUNITS); + if (print_sum) { + out->print_cr(", Sum: %4.1lf", sum * MILLIUNITS); + } else { + out->cr(); + } +} + +template <> +void WorkerDataArray::WDAPrinter::summary(outputStream* out, const char* title, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum) { + out->print("%-25s Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT, title, min, avg, max, diff); + if (print_sum) { + out->print_cr(", Sum: " SIZE_FORMAT, sum); + } else { + out->cr(); + } +} + +template <> +void WorkerDataArray::WDAPrinter::details(const WorkerDataArray* phase, outputStream* out, uint active_threads) { + out->print("%-25s", ""); + for (uint i = 0; i < active_threads; ++i) { + out->print(" %4.1lf", phase->get(i) * 1000.0); + } + out->cr(); +} + +template <> +void WorkerDataArray::WDAPrinter::details(const WorkerDataArray* phase, outputStream* out, uint active_threads) { + out->print("%-25s", ""); + for (uint i = 0; i < active_threads; ++i) { + out->print(" " SIZE_FORMAT, phase->get(i)); + } + out->cr(); +} #ifndef PRODUCT void WorkerDataArray_test() { const uint length = 3; const char* title = "Test array"; - const bool print_sum = false; - const uint indent_level = 2; - WorkerDataArray array(length, title, print_sum, indent_level); + WorkerDataArray array(length, title); assert(strncmp(array.title(), title, strlen(title)) == 0 , "Expected titles to match"); - assert(array.should_print_sum() == print_sum, "Expected should_print_sum to match print_sum"); - assert(array.indentation() == indent_level, "Expected indentation to match"); const size_t expected[length] = {5, 3, 7}; for (uint i = 0; i < length; i++) { @@ -46,10 +81,7 @@ void WorkerDataArray_test() { } assert(array.sum(length) == (5 + 3 + 7), "Expected sums to match"); - assert(array.minimum(length) == 3, "Expected mininum to match"); - assert(array.maximum(length) == 7, "Expected maximum to match"); - assert(array.diff(length) == (7 - 3), "Expected diffs to match"); - assert(array.average(length) == 5, "Expected averages to match"); + assert(array.average(length) == 5.0, "Expected averages to match"); for (uint i = 0; i < length; i++) { array.add(i, 1); diff --git a/hotspot/src/share/vm/gc/g1/workerDataArray.hpp b/hotspot/src/share/vm/gc/g1/workerDataArray.hpp index 09f0b61a5f7..e1e972327ea 100644 --- a/hotspot/src/share/vm/gc/g1/workerDataArray.hpp +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.hpp @@ -22,18 +22,19 @@ * */ +#ifndef SHARE_VM_GC_G1_WORKERDATAARRAY_HPP +#define SHARE_VM_GC_G1_WORKERDATAARRAY_HPP + #include "memory/allocation.hpp" #include "utilities/debug.hpp" +class outputStream; + template class WorkerDataArray : public CHeapObj { - friend class G1GCParPhasePrinter; T* _data; uint _length; const char* _title; - bool _print_sum; - uint _indent_level; - bool _enabled; WorkerDataArray* _thread_work_items; @@ -42,11 +43,7 @@ class WorkerDataArray : public CHeapObj { void set_all(T value); public: - WorkerDataArray(uint length, - const char* title, - bool print_sum, - uint indent_level); - + WorkerDataArray(uint length, const char* title); ~WorkerDataArray(); void link_thread_work_items(WorkerDataArray* thread_work_items); @@ -62,27 +59,30 @@ class WorkerDataArray : public CHeapObj { double average(uint active_threads) const; T sum(uint active_threads) const; - T minimum(uint active_threads) const; - T maximum(uint active_threads) const; - T diff(uint active_threads) const; - - uint indentation() const { - return _indent_level; - } const char* title() const { return _title; } - bool should_print_sum() const { - return _print_sum; - } - void clear(); - void set_enabled(bool enabled) { - _enabled = enabled; - } void reset() PRODUCT_RETURN; void verify(uint active_threads) const PRODUCT_RETURN; + + + private: + class WDAPrinter { + public: + static void summary(outputStream* out, const char* title, double min, double avg, double max, double diff, double sum, bool print_sum); + static void summary(outputStream* out, const char* title, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum); + + static void details(const WorkerDataArray* phase, outputStream* out, uint active_threads); + static void details(const WorkerDataArray* phase, outputStream* out, uint active_threads); + }; + + public: + void print_summary_on(outputStream* out, uint active_threads, bool print_sum = true) const; + void print_details_on(outputStream* out, uint active_threads) const; }; + +#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_HPP diff --git a/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp b/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp index 713eb125cff..7b4df8628b8 100644 --- a/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp @@ -22,20 +22,18 @@ * */ +#ifndef SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP +#define SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP + #include "gc/g1/workerDataArray.hpp" #include "memory/allocation.inline.hpp" +#include "utilities/ostream.hpp" template -WorkerDataArray::WorkerDataArray(uint length, - const char* title, - bool print_sum, - uint indent_level) : +WorkerDataArray::WorkerDataArray(uint length, const char* title) : _title(title), _length(0), - _print_sum(print_sum), - _indent_level(indent_level), - _thread_work_items(NULL), - _enabled(true) { + _thread_work_items(NULL) { assert(length > 0, "Must have some workers to store data for"); _length = length; _data = NEW_C_HEAP_ARRAY(T, _length, mtGC); @@ -93,29 +91,6 @@ T WorkerDataArray::sum(uint active_threads) const { return s; } -template -T WorkerDataArray::minimum(uint active_threads) const { - T min = get(0); - for (uint i = 1; i < active_threads; ++i) { - min = MIN2(min, get(i)); - } - return min; -} - -template -T WorkerDataArray::maximum(uint active_threads) const { - T max = get(0); - for (uint i = 1; i < active_threads; ++i) { - max = MAX2(max, get(i)); - } - return max; -} - -template -T WorkerDataArray::diff(uint active_threads) const { - return maximum(active_threads) - minimum(active_threads); -} - template void WorkerDataArray::clear() { set_all(0); @@ -128,6 +103,27 @@ void WorkerDataArray::set_all(T value) { } } +template +void WorkerDataArray::print_summary_on(outputStream* out, uint active_threads, bool print_sum) const { + T max = get(0); + T min = max; + T sum = 0; + for (uint i = 1; i < active_threads; ++i) { + T value = get(i); + max = MAX2(max, value); + min = MIN2(min, value); + sum += value; + } + T diff = max - min; + double avg = sum / (double) active_threads; + WDAPrinter::summary(out, title(), min, avg, max, diff, sum, print_sum); +} + +template +void WorkerDataArray::print_details_on(outputStream* out, uint active_threads) const { + WDAPrinter::details(this, out, active_threads); +} + #ifndef PRODUCT template void WorkerDataArray::reset() { @@ -139,10 +135,6 @@ void WorkerDataArray::reset() { template void WorkerDataArray::verify(uint active_threads) const { - if (!_enabled) { - return; - } - assert(active_threads <= _length, "Wrong number of active threads"); for (uint i = 0; i < active_threads; i++) { assert(_data[i] != uninitialized(), @@ -163,3 +155,5 @@ inline double WorkerDataArray::uninitialized() const { return -1.0; } #endif + +#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP diff --git a/hotspot/src/share/vm/logging/logPrefix.hpp b/hotspot/src/share/vm/logging/logPrefix.hpp index 039e5f44416..213fa7c2806 100644 --- a/hotspot/src/share/vm/logging/logPrefix.hpp +++ b/hotspot/src/share/vm/logging/logPrefix.hpp @@ -58,6 +58,7 @@ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, metaspace)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, start)) \ + LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, task)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, plab)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, region)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, remset)) \ diff --git a/hotspot/test/gc/g1/TestGCLogMessages.java b/hotspot/test/gc/g1/TestGCLogMessages.java index 0659c98f1c9..81526644c59 100644 --- a/hotspot/test/gc/g1/TestGCLogMessages.java +++ b/hotspot/test/gc/g1/TestGCLogMessages.java @@ -38,10 +38,24 @@ import jdk.test.lib.OutputAnalyzer; public class TestGCLogMessages { private enum Level { - OFF, DEBUG, TRACE; - public boolean lessOrEqualTo(Level other) { + OFF(""), + INFO("info"), + DEBUG("debug"), + TRACE("trace"); + + private String logName; + + Level(String logName) { + this.logName = logName; + } + + public boolean lessThan(Level other) { return this.compareTo(other) < 0; } + + public String toString() { + return logName; + } } private class LogMessageWithLevel { @@ -56,48 +70,48 @@ public class TestGCLogMessages { private LogMessageWithLevel allLogMessages[] = new LogMessageWithLevel[] { // Update RS - new LogMessageWithLevel("Scan HCC", Level.DEBUG), + new LogMessageWithLevel("Scan HCC", Level.TRACE), // Ext Root Scan - new LogMessageWithLevel("Thread Roots:", Level.DEBUG), - new LogMessageWithLevel("StringTable Roots:", Level.DEBUG), - new LogMessageWithLevel("Universe Roots:", Level.DEBUG), - new LogMessageWithLevel("JNI Handles Roots:", Level.DEBUG), - new LogMessageWithLevel("ObjectSynchronizer Roots:", Level.DEBUG), - new LogMessageWithLevel("FlatProfiler Roots", Level.DEBUG), - new LogMessageWithLevel("Management Roots", Level.DEBUG), - new LogMessageWithLevel("SystemDictionary Roots", Level.DEBUG), - new LogMessageWithLevel("CLDG Roots", Level.DEBUG), - new LogMessageWithLevel("JVMTI Roots", Level.DEBUG), - new LogMessageWithLevel("SATB Filtering", Level.DEBUG), - new LogMessageWithLevel("CM RefProcessor Roots", Level.DEBUG), - new LogMessageWithLevel("Wait For Strong CLD", Level.DEBUG), - new LogMessageWithLevel("Weak CLD Roots", Level.DEBUG), + new LogMessageWithLevel("Thread Roots", Level.TRACE), + new LogMessageWithLevel("StringTable Roots", Level.TRACE), + new LogMessageWithLevel("Universe Roots", Level.TRACE), + new LogMessageWithLevel("JNI Handles Roots", Level.TRACE), + new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE), + new LogMessageWithLevel("FlatProfiler Roots", Level.TRACE), + new LogMessageWithLevel("Management Roots", Level.TRACE), + new LogMessageWithLevel("SystemDictionary Roots", Level.TRACE), + new LogMessageWithLevel("CLDG Roots", Level.TRACE), + new LogMessageWithLevel("JVMTI Roots", Level.TRACE), + new LogMessageWithLevel("SATB Filtering", Level.TRACE), + new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE), + new LogMessageWithLevel("Wait For Strong CLD", Level.TRACE), + new LogMessageWithLevel("Weak CLD Roots", Level.TRACE), // Redirty Cards new LogMessageWithLevel("Redirty Cards", Level.DEBUG), - new LogMessageWithLevel("Parallel Redirty", Level.DEBUG), - new LogMessageWithLevel("Redirtied Cards", Level.DEBUG), + new LogMessageWithLevel("Parallel Redirty", Level.TRACE), + new LogMessageWithLevel("Redirtied Cards", Level.TRACE), // Misc Top-level - new LogMessageWithLevel("Code Root Purge", Level.DEBUG), - new LogMessageWithLevel("String Dedup Fixup", Level.DEBUG), - new LogMessageWithLevel("Expand Heap After Collection", Level.DEBUG), + new LogMessageWithLevel("Code Roots Purge", Level.DEBUG), + new LogMessageWithLevel("String Dedup Fixup", Level.INFO), + new LogMessageWithLevel("Expand Heap After Collection", Level.INFO), // Free CSet - new LogMessageWithLevel("Young Free CSet", Level.TRACE), - new LogMessageWithLevel("Non-Young Free CSet", Level.TRACE), + new LogMessageWithLevel("Young Free Collection Set", Level.DEBUG), + new LogMessageWithLevel("Non-Young Free Collection Set", Level.DEBUG), // Humongous Eager Reclaim new LogMessageWithLevel("Humongous Reclaim", Level.DEBUG), new LogMessageWithLevel("Humongous Register", Level.DEBUG), // Preserve CM Referents new LogMessageWithLevel("Preserve CM Refs", Level.DEBUG), // Merge PSS - new LogMessageWithLevel("Merge Per-Thread State", Level.DEBUG), + new LogMessageWithLevel("Merge Per-Thread State", Level.INFO), }; void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { for (LogMessageWithLevel l : messages) { - if (level.lessOrEqualTo(l.level)) { + if (level.lessThan(l.level)) { output.shouldNotContain(l.message); } else { - output.shouldContain(l.message); + output.shouldMatch("\\[" + l.level + ".*" + l.message); } } } From 49850dd82fd8b2eb1c445227f763dfcfb3714c6b Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Mon, 29 Feb 2016 13:24:01 +0100 Subject: [PATCH 155/311] 8147569: Error messages from sjavac server does not always get relayed back to client Refactored how logging works in sjavac. Reviewed-by: jlahoda --- .../com/sun/tools/sjavac/CleanProperties.java | 4 +- .../sun/tools/sjavac/CompileJavaPackages.java | 28 ++--- .../sun/tools/sjavac/CompileProperties.java | 4 +- .../com/sun/tools/sjavac/CopyFile.java | 4 +- .../com/sun/tools/sjavac/JavacState.java | 23 ++-- .../classes/com/sun/tools/sjavac/Log.java | 114 ++++++++++++------ .../com/sun/tools/sjavac/Transformer.java | 4 +- .../classes/com/sun/tools/sjavac/Util.java | 8 ++ .../sun/tools/sjavac/client/ClientMain.java | 6 +- .../sun/tools/sjavac/client/SjavacClient.java | 112 ++++++++--------- .../sun/tools/sjavac/comp/PooledSjavac.java | 15 +-- .../com/sun/tools/sjavac/comp/SjavacImpl.java | 24 ++-- .../tools/sjavac/server/IdleResetSjavac.java | 15 ++- .../sjavac/server/LinePrefixFilterWriter.java | 77 ------------ .../tools/sjavac/server/PortFileMonitor.java | 14 ++- .../tools/sjavac/server/RequestHandler.java | 61 +++++++--- .../sun/tools/sjavac/server/ServerMain.java | 46 ++++++- .../com/sun/tools/sjavac/server/Sjavac.java | 4 +- .../sun/tools/sjavac/server/SjavacServer.java | 81 ++++--------- .../sjavac/server/log/LazyInitFileLog.java | 80 ++++++++++++ .../server/log/LoggingOutputStream.java | 74 ++++++++++++ langtools/test/tools/sjavac/IdleShutdown.java | 8 +- .../test/tools/sjavac/PooledExecution.java | 8 +- 23 files changed, 482 insertions(+), 332 deletions(-) delete mode 100644 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/LinePrefixFilterWriter.java create mode 100644 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LazyInitFileLog.java create mode 100644 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LoggingOutputStream.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java index 03f02d8e42c..ef1602eb396 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java @@ -75,9 +75,7 @@ public class CleanProperties implements Transformer { Map dependencyPublicApis, int debugLevel, boolean incremental, - int numCores, - Writer out, - Writer err) { + int numCores) { boolean rc = true; for (String pkgName : pkgSrcs.keySet()) { String pkgNameF = pkgName.replace('.',File.separatorChar); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java index 14fc859048b..f6ac5d2ad44 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java @@ -42,6 +42,8 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.regex.Pattern; +import java.util.stream.Stream; import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; @@ -89,9 +91,7 @@ public class CompileJavaPackages implements Transformer { final Map dependencyPubapis, int debugLevel, boolean incremental, - int numCores, - final Writer out, - final Writer err) { + int numCores) { Log.debug("Performing CompileJavaPackages transform..."); @@ -219,7 +219,9 @@ public class CompileJavaPackages implements Transformer { } String chunkId = id + "-" + String.valueOf(i); + Log log = Log.get(); compilationCalls.add(() -> { + Log.setLogForCurrentThread(log); CompilationSubResult result = sjavac.compile("n/a", chunkId, args.prepJavacArgs(), @@ -227,8 +229,8 @@ public class CompileJavaPackages implements Transformer { cc.srcs, visibleSources); synchronized (lock) { - safeWrite(result.stdout, out); - safeWrite(result.stderr, err); + Util.getLines(result.stdout).forEach(Log::info); + Util.getLines(result.stderr).forEach(Log::error); } return result; }); @@ -246,8 +248,10 @@ public class CompileJavaPackages implements Transformer { subResults.add(fut.get()); } catch (ExecutionException ee) { Log.error("Compilation failed: " + ee.getMessage()); - } catch (InterruptedException ee) { - Log.error("Compilation interrupted: " + ee.getMessage()); + Log.error(ee); + } catch (InterruptedException ie) { + Log.error("Compilation interrupted: " + ie.getMessage()); + Log.error(ie); Thread.currentThread().interrupt(); } } @@ -292,16 +296,6 @@ public class CompileJavaPackages implements Transformer { return rc; } - private void safeWrite(String str, Writer w) { - if (str.length() > 0) { - try { - w.write(str); - } catch (IOException e) { - Log.error("Could not print compilation output."); - } - } - } - /** * Split up the sources into compile chunks. If old package dependents information * is available, sort the order of the chunks into the most dependent first! diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java index 3ca37b547f6..7045bc14afd 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java @@ -83,9 +83,7 @@ public class CompileProperties implements Transformer { Map dependencyPublicApis, int debugLevel, boolean incremental, - int numCores, - Writer out, - Writer err) { + int numCores) { boolean rc = true; for (String pkgName : pkgSrcs.keySet()) { String pkgNameF = Util.toFileSystemPath(pkgName); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java index 5ab8d22fc7a..d3685eacfc6 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java @@ -70,9 +70,7 @@ public class CopyFile implements Transformer { Map dependencyPubapis, int debugLevel, boolean incremental, - int numCores, - Writer out, - Writer err) + int numCores) { boolean rc = true; String dest_filename; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java index 114d1282fc1..93749f61676 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java @@ -123,16 +123,11 @@ public class JavacState { // Setup transform that always exist. private CompileJavaPackages compileJavaPackages = new CompileJavaPackages(); - // Where to send stdout and stderr. - private Writer out, err; - // Command line options. private Options options; - JavacState(Options op, boolean removeJavacState, Writer o, Writer e) { + JavacState(Options op, boolean removeJavacState) { options = op; - out = o; - err = e; numCores = options.getNumCores(); theArgs = options.getStateArgsString(); binDir = Util.pathToFile(options.getDestDir()); @@ -294,8 +289,8 @@ public class JavacState { /** * Load a javac_state file. */ - public static JavacState load(Options options, Writer out, Writer err) { - JavacState db = new JavacState(options, false, out, err); + public static JavacState load(Options options) { + JavacState db = new JavacState(options, false); Module lastModule = null; Package lastPackage = null; Source lastSource = null; @@ -367,22 +362,22 @@ public class JavacState { noFileFound = true; } catch (IOException e) { Log.info("Dropping old javac_state because of errors when reading it."); - db = new JavacState(options, true, out, err); + db = new JavacState(options, true); foundCorrectVerNr = true; newCommandLine = false; syntaxError = false; } if (foundCorrectVerNr == false && !noFileFound) { Log.info("Dropping old javac_state since it is of an old version."); - db = new JavacState(options, true, out, err); + db = new JavacState(options, true); } else if (newCommandLine == true && !noFileFound) { Log.info("Dropping old javac_state since a new command line is used!"); - db = new JavacState(options, true, out, err); + db = new JavacState(options, true); } else if (syntaxError == true) { Log.info("Dropping old javac_state since it contains syntax errors."); - db = new JavacState(options, true, out, err); + db = new JavacState(options, true); } db.prev.calculateDependents(); return db; @@ -812,9 +807,7 @@ public class JavacState { dependencyPublicApis, 0, isIncremental(), - numCores, - out, - err); + numCores); if (!r) rc = false; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java index 60f513fc80c..39788ebba6b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -26,11 +26,24 @@ package com.sun.tools.sjavac; import java.io.PrintWriter; +import java.io.StringWriter; import java.io.Writer; +import java.util.Locale; /** * Utility class only for sjavac logging. - * The log level can be set using for example --log=DEBUG on the sjavac command line. + * + * Logging in sjavac has special requirements when running in server/client + * mode. Most of the log messages is generated server-side, but the server + * is typically spawned by the client in the background, so the user usually + * does not see the server stdout/stderr. For this reason log messages needs + * to relayed back to the client that performed the request that generated the + * log message. To support this use case this class maintains a per-thread log + * instance so that each connected client can have its own instance that + * relays messages back to the requesting client. + * + * On the client-side (or when running sjavac without server-mode) there will + * typically just be one Log instance. * *

      This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. @@ -38,61 +51,94 @@ import java.io.Writer; * deletion without notice. */ public class Log { - private static PrintWriter out, err; - public final static int WARN = 1; - public final static int INFO = 2; - public final static int DEBUG = 3; - public final static int TRACE = 4; - private static int level = WARN; + public enum Level { + ERROR, + WARN, + INFO, + DEBUG, + TRACE; + } + + private static Log stdOutErr = new Log(new PrintWriter(System.out), new PrintWriter(System.err)); + private static ThreadLocal loggers = new ThreadLocal<>(); + + protected PrintWriter err; // Used for error and warning messages + protected PrintWriter out; // Used for other messages + protected Level level = Level.INFO; + + public Log(Writer out, Writer err) { + this.out = out == null ? null : new PrintWriter(out, true); + this.err = err == null ? null : new PrintWriter(err, true); + } + + public static void setLogForCurrentThread(Log log) { + loggers.set(log); + } + + public static void setLogLevel(String l) { + setLogLevel(Level.valueOf(l.toUpperCase(Locale.US))); + } + + public static void setLogLevel(Level l) { + get().level = l; + } static public void trace(String msg) { - if (level >= TRACE) { - out.println(msg); - } + log(Level.TRACE, msg); } static public void debug(String msg) { - if (level >= DEBUG) { - out.println(msg); - } + log(Level.DEBUG, msg); } static public void info(String msg) { - if (level >= INFO) { - out.println(msg); - } + log(Level.INFO, msg); } static public void warn(String msg) { - err.println(msg); + log(Level.WARN, msg); } static public void error(String msg) { - err.println(msg); + log(Level.ERROR, msg); } - static public void initializeLog(Writer o, Writer e) { - out = new PrintWriter(o); - err = new PrintWriter(e); + static public void error(Throwable t) { + log(Level.ERROR, t); } - static public void setLogLevel(String l) { - switch (l) { - case "warn": level = WARN; break; - case "info": level = INFO; break; - case "debug": level = DEBUG; break; - case "trace": level = TRACE; break; - default: - throw new IllegalArgumentException("No such log level \"" + l + "\""); - } + static public void log(Level l, String msg) { + get().printLogMsg(l, msg); } - static public boolean isTracing() { - return level >= TRACE; + public static void debug(Throwable t) { + log(Level.DEBUG, t); + } + + public static void log(Level l, Throwable t) { + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw, true)); + log(l, sw.toString()); } static public boolean isDebugging() { - return level >= DEBUG; + return get().isLevelLogged(Level.DEBUG); + } + + protected boolean isLevelLogged(Level l) { + return l.ordinal() <= level.ordinal(); + } + + public static Log get() { + Log log = loggers.get(); + return log != null ? log : stdOutErr; + } + + protected void printLogMsg(Level msgLevel, String msg) { + if (isLevelLogged(msgLevel)) { + PrintWriter pw = msgLevel.ordinal() <= Level.WARN.ordinal() ? err : out; + pw.println(msg); + } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java index 7fcac272176..c9e2c62865c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java @@ -95,9 +95,7 @@ public interface Transformer { Map dependencyApis, int debugLevel, boolean incremental, - int numCores, - Writer out, - Writer err); + int numCores); void setExtra(String e); void setExtra(Options args); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java index d010cfa7b82..1bcad774b24 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java @@ -36,7 +36,9 @@ import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.function.Function; +import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Utilities. @@ -236,4 +238,10 @@ public class Util { int dotIndex = fileNameStr.indexOf('.'); return dotIndex == -1 ? "" : fileNameStr.substring(dotIndex); } + + public static Stream getLines(String str) { + return str.isEmpty() + ? Stream.empty() + : Stream.of(str.split(Pattern.quote(System.lineSeparator()))); + } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java index 0e62feaed2d..f7aa9b9ce66 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java @@ -51,7 +51,7 @@ public class ClientMain { public static int run(String[] args, Writer out, Writer err) { - Log.initializeLog(out, err); + Log.setLogForCurrentThread(new Log(out, err)); Options options; try { @@ -61,6 +61,8 @@ public class ClientMain { return -1; } + Log.setLogLevel(options.getLogLevel()); + Log.debug("=========================================================="); Log.debug("Launching sjavac client with the following parameters:"); Log.debug(" " + options.getStateArgsString()); @@ -81,7 +83,7 @@ public class ClientMain { sjavac = new SjavacImpl(); } - int rc = sjavac.compile(args, out, err); + int rc = sjavac.compile(args); // If sjavac is running in the foreground we should shut it down at this point if (!useServer) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java index e13c9455ff9..e5e63ef2441 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; +import java.io.Reader; import java.io.Writer; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -40,6 +41,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner; +import java.util.stream.Stream; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; @@ -50,6 +52,8 @@ import com.sun.tools.sjavac.server.PortFile; import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.SjavacServer; +import static java.util.stream.Collectors.joining; + /** * Sjavac implementation that delegates requests to a SjavacServer. * @@ -64,8 +68,6 @@ public class SjavacClient implements Sjavac { // JavaCompiler instance for several compiles using the same id. private final String id; private final PortFile portFile; - private final String logfile; - private final String stdouterrfile; // Default keepalive for server is 120 seconds. // I.e. it will accept 120 seconds of inactivity before quitting. @@ -102,8 +104,6 @@ public class SjavacClient implements Sjavac { Log.error("Port file inaccessable: " + e); throw e; } - logfile = Util.extractStringOption("logfile", serverConf, portfileName + ".javaclog"); - stdouterrfile = Util.extractStringOption("stdouterrfile", serverConf, portfileName + ".stdouterr"); sjavacForkCmd = Util.extractStringOption("sjavac", serverConf, "sjavac"); int poolsize = Util.extractIntOption("poolsize", serverConf); keepalive = Util.extractIntOption("keepalive", serverConf, 120); @@ -121,7 +121,7 @@ public class SjavacClient implements Sjavac { } @Override - public int compile(String[] args, Writer stdout, Writer stderr) { + public int compile(String[] args) { int result = -1; try (Socket socket = tryConnect()) { PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); @@ -136,32 +136,33 @@ public class SjavacClient implements Sjavac { // Read server response line by line String line; while (null != (line = in.readLine())) { + if (!line.contains(":")) { + throw new AssertionError("Could not parse protocol line: >>\"" + line + "\"<<"); + } String[] typeAndContent = line.split(":", 2); String type = typeAndContent[0]; String content = typeAndContent[1]; - switch (type) { - case SjavacServer.LINE_TYPE_STDOUT: - stdout.write(content); - stdout.write('\n'); - break; - case SjavacServer.LINE_TYPE_STDERR: - stderr.write(content); - stderr.write('\n'); - break; - case SjavacServer.LINE_TYPE_RC: + + try { + Log.log(Log.Level.valueOf(type), "[server] " + content); + continue; + } catch (IllegalArgumentException e) { + // Parsing of 'type' as log level failed. + } + + if (type.equals(SjavacServer.LINE_TYPE_RC)) { result = Integer.parseInt(content); - break; } } } catch (IOException ioe) { - Log.error("[CLIENT] Exception caught: " + ioe); + Log.error("IOException caught during compilation: " + ioe.getMessage()); + Log.debug(ioe); result = CompilationSubResult.ERROR_FATAL; - ioe.printStackTrace(new PrintWriter(stderr)); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Restore interrupt - Log.error("[CLIENT] compile interrupted."); + Log.error("Compilation interrupted."); + Log.debug(ie); result = CompilationSubResult.ERROR_FATAL; - ie.printStackTrace(new PrintWriter(stderr)); } return result; } @@ -215,11 +216,8 @@ public class SjavacClient implements Sjavac { // Fork a new server and wait for it to start SjavacClient.fork(sjavacForkCmd, portFile, - logfile, poolsize, - keepalive, - System.err, - stdouterrfile); + keepalive); } @Override @@ -230,51 +228,53 @@ public class SjavacClient implements Sjavac { /* * Fork a server process process and wait for server to come around */ - public static void fork(String sjavacCmd, - PortFile portFile, - String logfile, - int poolsize, - int keepalive, - final PrintStream err, - String stdouterrfile) - throws IOException, InterruptedException { + public static void fork(String sjavacCmd, PortFile portFile, int poolsize, int keepalive) + throws IOException, InterruptedException { List cmd = new ArrayList<>(); cmd.addAll(Arrays.asList(OptionHelper.unescapeCmdArg(sjavacCmd).split(" "))); cmd.add("--startserver:" + "portfile=" + portFile.getFilename() - + ",logfile=" + logfile - + ",stdouterrfile=" + stdouterrfile + ",poolsize=" + poolsize + ",keepalive="+ keepalive); - Process p = null; + Process serverProcess; Log.info("Starting server. Command: " + String.join(" ", cmd)); try { - // If the cmd for some reason can't be executed (file not found, or - // is not executable) this will throw an IOException with a decent - // error message. - p = new ProcessBuilder(cmd) - .redirectErrorStream(true) - .redirectOutput(new File(stdouterrfile)) - .start(); + // If the cmd for some reason can't be executed (file is not found, + // or is not executable for instance) this will throw an + // IOException and p == null. + serverProcess = new ProcessBuilder(cmd) + .redirectErrorStream(true) + .start(); + } catch (IOException ex) { + // Message is typically something like: + // Cannot run program "xyz": error=2, No such file or directory + Log.error("Failed to create server process: " + ex.getMessage()); + Log.debug(ex); + throw new IOException(ex); + } + // serverProcess != null at this point. + try { // Throws an IOException if no valid values materialize portFile.waitForValidValues(); - } catch (IOException ex) { - // Log and rethrow exception - Log.error("Faild to launch server."); - Log.error(" Message: " + ex.getMessage()); - String rc = p == null || p.isAlive() ? "n/a" : "" + p.exitValue(); - Log.error(" Server process exit code: " + rc); - Log.error("Server log:"); - Log.error("------- Server log start -------"); - try (Scanner s = new Scanner(new File(stdouterrfile))) { - while (s.hasNextLine()) - Log.error(s.nextLine()); + // Process was started, but server failed to initialize. This could + // for instance be due to the JVM not finding the server class, + // or the server running in to some exception early on. + Log.error("Sjavac server failed to initialize: " + ex.getMessage()); + Log.error("Process output:"); + Reader serverStdoutStderr = new InputStreamReader(serverProcess.getInputStream()); + try (BufferedReader br = new BufferedReader(serverStdoutStderr)) { + br.lines().forEach(Log::error); } - Log.error("------- Server log end ---------"); - throw ex; + Log.error(""); + try { + Log.error("Process exit code: " + serverProcess.exitValue()); + } catch (IllegalThreadStateException e) { + // Server is presumably still running. + } + throw new IOException("Server failed to initialize: " + ex.getMessage(), ex); } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java index caabc38df1d..82be0ae3b16 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -25,15 +25,14 @@ package com.sun.tools.sjavac.comp; -import java.io.Writer; +import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.server.Sjavac; + import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import com.sun.tools.sjavac.Log; -import com.sun.tools.sjavac.server.Sjavac; - /** * An sjavac implementation that limits the number of concurrent calls by * wrapping invocations in Callables and delegating them to a FixedThreadPool. @@ -55,10 +54,12 @@ public class PooledSjavac implements Sjavac { } @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { + Log log = Log.get(); try { return pool.submit(() -> { - return delegate.compile(args, out, err); + Log.setLogForCurrentThread(log); + return delegate.compile(args); }).get(); } catch (Exception e) { e.printStackTrace(); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java index 79835ab6c28..a8ccd32356c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java @@ -27,6 +27,7 @@ package com.sun.tools.sjavac.comp; import java.io.IOException; import java.io.PrintWriter; +import java.io.StringWriter; import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; @@ -68,7 +69,7 @@ import javax.tools.JavaFileManager; public class SjavacImpl implements Sjavac { @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { Options options; try { options = Options.parseArgs(args); @@ -77,8 +78,6 @@ public class SjavacImpl implements Sjavac { return RC_FATAL; } - Log.setLogLevel(options.getLogLevel()); - if (!validateOptions(options)) return RC_FATAL; @@ -100,18 +99,21 @@ public class SjavacImpl implements Sjavac { if (stateDir == null) { // Prepare context. Direct logging to our byte array stream. Context context = new Context(); - PrintWriter writer = new PrintWriter(err); - com.sun.tools.javac.util.Log.preRegister(context, writer); + StringWriter strWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(strWriter); + com.sun.tools.javac.util.Log.preRegister(context, printWriter); JavacFileManager.preRegister(context); // Prepare arguments String[] passThroughArgs = Stream.of(args) .filter(arg -> !arg.startsWith(Option.SERVER.arg)) .toArray(String[]::new); - // Compile - com.sun.tools.javac.main.Main compiler = new com.sun.tools.javac.main.Main("javac", writer); - Main.Result result = compiler.compile(passThroughArgs, context); + Main.Result result = new Main("javac", printWriter).compile(passThroughArgs, context); + + // Process compiler output (which is always errors) + printWriter.flush(); + Util.getLines(strWriter.toString()).forEach(Log::error); // Clean up JavaFileManager fileManager = context.get(JavaFileManager.class); @@ -126,7 +128,7 @@ public class SjavacImpl implements Sjavac { } else { // Load the prev build state database. - JavacState javac_state = JavacState.load(options, out, err); + JavacState javac_state = JavacState.load(options); // Setup the suffix rules from the command line. Map suffixRules = new HashMap<>(); @@ -288,10 +290,12 @@ public class SjavacImpl implements Sjavac { return rc[0] ? RC_OK : RC_FATAL; } catch (ProblemException e) { + // For instance make file list mismatch. Log.error(e.getMessage()); + Log.debug(e); return RC_FATAL; } catch (Exception e) { - e.printStackTrace(new PrintWriter(err)); + Log.error(e); return RC_FATAL; } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java index 111d9c9ff32..8b7d17b0c0c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -25,6 +25,10 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.sjavac.Log; + +import java.io.FileWriter; +import java.io.IOException; import java.io.Writer; import java.util.Timer; import java.util.TimerTask; @@ -53,8 +57,8 @@ public class IdleResetSjavac implements Sjavac { private TimerTask idlenessTimerTask; public IdleResetSjavac(Sjavac delegate, - Terminable toShutdown, - long idleTimeout) { + Terminable toShutdown, + long idleTimeout) { this.delegate = delegate; this.toShutdown = toShutdown; this.idleTimeout = idleTimeout; @@ -62,10 +66,10 @@ public class IdleResetSjavac implements Sjavac { } @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { startCall(); try { - return delegate.compile(args, out, err); + return delegate.compile(args); } finally { endCall(); } @@ -95,6 +99,7 @@ public class IdleResetSjavac implements Sjavac { throw new IllegalStateException("Idle timeout already scheduled"); idlenessTimerTask = new TimerTask() { public void run() { + Log.setLogForCurrentThread(ServerMain.getErrorLog()); toShutdown.shutdown("Server has been idle for " + (idleTimeout / 1000) + " seconds."); } }; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/LinePrefixFilterWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/LinePrefixFilterWriter.java deleted file mode 100644 index 0cdc2cc7dfa..00000000000 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/LinePrefixFilterWriter.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2015, 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. - */ - -package com.sun.tools.sjavac.server; - -import java.io.FilterWriter; -import java.io.IOException; -import java.io.Writer; - -/** - * Inserts {@literal prefix} in front of each line written. - * - * A line is considered to be terminated by any one of a line feed, a carriage - * return, or a carriage return followed immediately by a line feed. - */ -public class LinePrefixFilterWriter extends FilterWriter { - - private final String prefix; - private boolean atBeginningOfLine = true; - private char lastChar = '\0'; - - protected LinePrefixFilterWriter(Writer out, String prefix) { - super(out); - this.prefix = prefix; - } - - @Override - public void write(String str, int off, int len) throws IOException { - for (int i = 0; i < len; i++) { - write(str.charAt(off + i)); - } - } - - @Override - public void write(char[] cbuf, int off, int len) throws IOException { - for (int i = 0; i < len; i++) { - write(cbuf[off + i]); - } - } - - @Override - public void write(int c) throws IOException { - if (lastChar == '\r' && c == '\n') { - // Second character of CR+LF sequence. - // Do nothing. We already started a new line on last character. - } else { - if (atBeginningOfLine) { - super.write(prefix, 0, prefix.length()); - } - super.write(c); - atBeginningOfLine = c == '\r' || c == '\n'; - } - lastChar = (char) c; - } -} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java index d3e68565533..7b37d3753ae 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -25,6 +25,8 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.sjavac.Log; + import java.io.IOException; import java.util.Timer; import java.util.TimerTask; @@ -56,8 +58,11 @@ public class PortFileMonitor { } public void start() { + Log log = Log.get(); TimerTask shutdownCheck = new TimerTask() { public void run() { + Log.setLogForCurrentThread(log); + Log.debug("Checking port file status..."); try { if (!portFile.exists()) { // Time to quit because the portfile was deleted by another @@ -74,12 +79,11 @@ public class PortFileMonitor { server.shutdown("Quitting because portfile is now owned by another javac server!"); } } catch (IOException e) { - e.printStackTrace(server.theLog); - server.flushLog(); + Log.error("IOException caught in PortFileMonitor."); + Log.debug(e); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - e.printStackTrace(server.theLog); - server.flushLog(); + Log.error(e); } } }; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java index 253c1724a26..62ba3b995a9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -25,19 +25,16 @@ package com.sun.tools.sjavac.server; -import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_RC; -import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_STDERR; -import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_STDOUT; +import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.Util; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; import java.net.Socket; +import java.nio.file.Path; -import com.sun.tools.sjavac.AutoFlushWriter; -import com.sun.tools.sjavac.Log; +import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_RC; /** @@ -56,7 +53,7 @@ import com.sun.tools.sjavac.Log; * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class RequestHandler implements Runnable { +public class RequestHandler extends Thread { private final Socket socket; private final Sjavac sjavac; @@ -68,9 +65,30 @@ public class RequestHandler implements Runnable { @Override public void run() { + try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { + // Set up logging for this thread. Stream back logging messages to + // client on the format format "level:msg". + Log.setLogForCurrentThread(new Log(out, out) { + @Override + protected boolean isLevelLogged(Level l) { + // Make sure it is up to the client to decide whether or + // not this message should be displayed. + return true; + } + + @Override + protected void printLogMsg(Level msgLevel, String msg) { + // Follow sjavac server/client protocol: Send one line + // at a time and prefix with message with "level:". + Util.getLines(msg) + .map(line -> msgLevel + ":" + line) + .forEach(line -> super.printLogMsg(msgLevel, line)); + } + }); + // Read argument array int n = Integer.parseInt(in.readLine()); String[] args = new String[n]; @@ -78,23 +96,32 @@ public class RequestHandler implements Runnable { args[i] = in.readLine(); } + // If there has been any internal errors, notify client + checkInternalErrorLog(); + // Perform compilation - Writer stdout = new LinePrefixFilterWriter(new AutoFlushWriter(out), LINE_TYPE_STDOUT + ":"); - Writer stderr = new LinePrefixFilterWriter(new AutoFlushWriter(out), LINE_TYPE_STDERR + ":"); - int rc = sjavac.compile(args, stdout, stderr); - stdout.flush(); - stderr.flush(); + int rc = sjavac.compile(args); // Send return code back to client out.println(LINE_TYPE_RC + ":" + rc); + // Check for internal errors again. + checkInternalErrorLog(); } catch (Exception ex) { // Not much to be done at this point. The client side request // code will most likely throw an IOException and the // compilation will fail. - StringWriter sw = new StringWriter(); - ex.printStackTrace(new PrintWriter(sw)); - Log.error(sw.toString()); + Log.error(ex); + } finally { + Log.setLogForCurrentThread(null); + } + } + + private void checkInternalErrorLog() { + Path errorLog = ServerMain.getErrorLog().getLogDestination(); + if (errorLog != null) { + Log.error("Server has encountered an internal error. See " + errorLog.toAbsolutePath() + + " for details."); } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java index aab5ada4ae2..6690c3ece70 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -25,10 +25,20 @@ package com.sun.tools.sjavac.server; +import java.io.FileWriter; +import java.io.FilterOutputStream; +import java.io.FilterWriter; import java.io.IOException; -import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.lang.Thread.UncaughtExceptionHandler; import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.Log.Level; +import com.sun.tools.sjavac.server.log.LazyInitFileLog; +import com.sun.tools.sjavac.server.log.LoggingOutputStream; + +import static com.sun.tools.sjavac.Log.Level.ERROR; +import static com.sun.tools.sjavac.Log.Level.INFO; /** *

      This is NOT part of any supported API. @@ -37,20 +47,40 @@ import com.sun.tools.sjavac.Log; * deletion without notice. */ public class ServerMain { + + // For logging server internal (non request specific) errors. + private static LazyInitFileLog errorLog; + public static int run(String[] args) { - Log.initializeLog(new OutputStreamWriter(System.out), - new OutputStreamWriter(System.err)); + // Under normal operation, all logging messages generated server-side + // are due to compilation requests. These logging messages should + // be relayed back to the requesting client rather than written to the + // server log. The only messages that should be written to the server + // log (in production mode) should be errors, + Log.setLogForCurrentThread(errorLog = new LazyInitFileLog("server.log")); + Log.setLogLevel(ERROR); // should be set to ERROR. + + // Make sure no exceptions go under the radar + Thread.setDefaultUncaughtExceptionHandler((t, e) -> { + Log.setLogForCurrentThread(errorLog); + Log.error(e); + }); + + // Inevitably someone will try to print messages using System.{out,err}. + // Make sure this output also ends up in the log. + System.setOut(new PrintStream(new LoggingOutputStream(System.out, INFO, "[stdout] "))); + System.setErr(new PrintStream(new LoggingOutputStream(System.err, ERROR, "[stderr] "))); // Any options other than --startserver? if (args.length > 1) { - System.err.println("When spawning a background server, only a single --startserver argument is allowed."); + Log.error("When spawning a background server, only a single --startserver argument is allowed."); return 1; } int exitCode; try { - SjavacServer server = new SjavacServer(args[0], System.err); + SjavacServer server = new SjavacServer(args[0]); exitCode = server.startServer(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(); @@ -59,4 +89,8 @@ public class ServerMain { return exitCode; } + + public static LazyInitFileLog getErrorLog() { + return errorLog; + } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java index 837fb633b33..91063c5a809 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -42,6 +42,6 @@ public interface Sjavac { final static int RC_FATAL = -1; final static int RC_OK = 0; - int compile(String[] args, Writer stdout, Writer stderr); + int compile(String[] args); void shutdown(); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java index 1f9ec7504d4..6d5d541d7f6 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java @@ -26,6 +26,7 @@ package com.sun.tools.sjavac.server; import java.io.FileNotFoundException; +import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; @@ -39,6 +40,7 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; +import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; import com.sun.tools.sjavac.client.PortFileInaccessibleException; import com.sun.tools.sjavac.comp.PooledSjavac; @@ -54,17 +56,12 @@ import com.sun.tools.sjavac.comp.SjavacImpl; */ public class SjavacServer implements Terminable { - // Used in protocol to tell the content of each line + // Prefix of line containing return code. public final static String LINE_TYPE_RC = "RC"; - public final static String LINE_TYPE_STDOUT = "STDOUT"; - public final static String LINE_TYPE_STDERR = "STDERR"; final private String portfilename; - final private String logfile; - final private String stdouterrfile; final private int poolsize; final private int keepalive; - final private PrintStream err; // The secret cookie shared between server and client through the port file. // Used to prevent clients from believing that they are communicating with @@ -75,9 +72,6 @@ public class SjavacServer implements Terminable { // Accumulated build time, not counting idle time, used for logging purposes private long totalBuildTime; - // The javac server specific log file. - PrintWriter theLog; - // The sjavac implementation to delegate requests to Sjavac sjavac; @@ -92,40 +86,29 @@ public class SjavacServer implements Terminable { // For the client, all port files fetched, one per started javac server. // Though usually only one javac server is started by a client. private static Map allPortFiles; - private static Map maxServerMemory; - public SjavacServer(String settings, PrintStream err) throws FileNotFoundException { + public SjavacServer(String settings) throws FileNotFoundException { this(Util.extractStringOption("portfile", settings), - Util.extractStringOption("logfile", settings), - Util.extractStringOption("stdouterrfile", settings), Util.extractIntOption("poolsize", settings, Runtime.getRuntime().availableProcessors()), - Util.extractIntOption("keepalive", settings, 120), - err); + Util.extractIntOption("keepalive", settings, 120)); } public SjavacServer(String portfilename, - String logfile, - String stdouterrfile, int poolsize, - int keepalive, - PrintStream err) + int keepalive) throws FileNotFoundException { this.portfilename = portfilename; - this.logfile = logfile; - this.stdouterrfile = stdouterrfile; this.poolsize = poolsize; this.keepalive = keepalive; - this.err = err; - - myCookie = new Random().nextLong(); - theLog = new PrintWriter(logfile); + this.myCookie = new Random().nextLong(); } /** * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. */ - public static synchronized PortFile getPortFile(String filename) throws PortFileInaccessibleException { + public static synchronized PortFile getPortFile(String filename) + throws PortFileInaccessibleException { if (allPortFiles == null) { allPortFiles = new HashMap<>(); } @@ -169,26 +152,6 @@ public class SjavacServer implements Terminable { totalBuildTime += inc; } - /** - * Log this message. - */ - public void log(String msg) { - if (theLog != null) { - theLog.println(msg); - } else { - System.err.println(msg); - } - } - - /** - * Make sure the log is flushed. - */ - public void flushLog() { - if (theLog != null) { - theLog.flush(); - } - } - /** * Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3" * is sent as the settings parameter. Returns 0 on success, -1 on failure. @@ -203,7 +166,7 @@ public class SjavacServer implements Terminable { portFile.lock(); portFile.getValues(); if (portFile.containsPortInfo()) { - err.println("Javac server not started because portfile exists!"); + Log.info("Javac server not started because portfile exists!"); portFile.unlock(); return -1; } @@ -230,23 +193,23 @@ public class SjavacServer implements Terminable { portFileMonitor = new PortFileMonitor(portFile, this); portFileMonitor.start(); - log("Sjavac server started. Accepting connections..."); - log(" port: " + getPort()); - log(" time: " + new java.util.Date()); - log(" poolsize: " + poolsize); - flushLog(); + Log.info("Sjavac server started. Accepting connections..."); + Log.info(" port: " + getPort()); + Log.info(" time: " + new java.util.Date()); + Log.info(" poolsize: " + poolsize); + keepAcceptingRequests.set(true); do { try { Socket socket = serverSocket.accept(); - new Thread(new RequestHandler(socket, sjavac)).start(); + new RequestHandler(socket, sjavac).start(); } catch (SocketException se) { // Caused by serverSocket.close() and indicates shutdown } } while (keepAcceptingRequests.get()); - log("Shutting down."); + Log.info("Shutting down."); // No more connections accepted. If any client managed to connect after // the accept() was interrupted but before the server socket is closed @@ -254,8 +217,7 @@ public class SjavacServer implements Terminable { // IOException on the client side. long realTime = System.currentTimeMillis() - serverStart; - log("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); - flushLog(); + Log.info("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); // Shut down sjavac.shutdown(); @@ -270,8 +232,7 @@ public class SjavacServer implements Terminable { return; } - log("Quitting: " + quitMsg); - flushLog(); + Log.info("Quitting: " + quitMsg); portFileMonitor.shutdown(); // No longer any need to monitor port file @@ -280,12 +241,12 @@ public class SjavacServer implements Terminable { try { portFile.delete(); } catch (IOException | InterruptedException e) { - e.printStackTrace(theLog); + Log.error(e); } try { serverSocket.close(); } catch (IOException e) { - e.printStackTrace(theLog); + Log.error(e); } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LazyInitFileLog.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LazyInitFileLog.java new file mode 100644 index 00000000000..2b6cf9cee65 --- /dev/null +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LazyInitFileLog.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, 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. + */ + +package com.sun.tools.sjavac.server.log; + +import com.sun.tools.sjavac.Log; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class LazyInitFileLog extends Log { + + String baseFilename; + Path destination = null; + + public LazyInitFileLog(String baseFilename) { + super(null, null); + this.baseFilename = baseFilename; + } + + protected void printLogMsg(Level msgLevel, String msg) { + try { + // Lazily initialize out/err + if (out == null && isLevelLogged(msgLevel)) { + destination = getAvailableDestination(); + out = err = new PrintWriter(new FileWriter(destination.toFile()), true); + } + // Proceed to log the message + super.printLogMsg(msgLevel, msg); + } catch (IOException e) { + // This could be bad. We might have run into an error and we can't + // log it. Resort to printing on stdout. + System.out.println("IO error occurred: " + e.getMessage()); + System.out.println("Original message: [" + msgLevel + "] " + msg); + } + } + + /** + * @return The first available path of baseFilename, baseFilename.1, + * basefilename.2, ... + */ + private Path getAvailableDestination() { + Path p = Paths.get(baseFilename); + int i = 1; + while (Files.exists(p)) { + p = Paths.get(baseFilename + "." + i++); + } + return p; + } + + public Path getLogDestination() { + return destination; + } +} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LoggingOutputStream.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LoggingOutputStream.java new file mode 100644 index 00000000000..56b048376ce --- /dev/null +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LoggingOutputStream.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016, 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. + */ + +package com.sun.tools.sjavac.server.log; + +import com.sun.tools.sjavac.Log; + +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class LoggingOutputStream extends FilterOutputStream { + + private static final byte[] LINE_SEP = System.lineSeparator().getBytes(); + + private final Log.Level level; + private final String linePrefix; + private EolTrackingByteArrayOutputStream buf = new EolTrackingByteArrayOutputStream(); + + public LoggingOutputStream(OutputStream out, Log.Level level, String linePrefix) { + super(out); + this.level = level; + this.linePrefix = linePrefix; + } + + @Override + public void write(int b) throws IOException { + super.write(b); + buf.write(b); + if (buf.isLineComplete()) { + String line = new String(buf.toByteArray(), 0, buf.size() - LINE_SEP.length); + Log.log(level, linePrefix + line); + buf = new EolTrackingByteArrayOutputStream(); + } + } + + private static class EolTrackingByteArrayOutputStream extends ByteArrayOutputStream { + private static final byte[] EOL = System.lineSeparator().getBytes(); + private boolean isLineComplete() { + if (count < EOL.length) { + return false; + } + for (int i = 0; i < EOL.length; i++) { + if (buf[count - EOL.length + i] != EOL[i]) { + return false; + } + } + return true; + } + } +} diff --git a/langtools/test/tools/sjavac/IdleShutdown.java b/langtools/test/tools/sjavac/IdleShutdown.java index 567677e529a..7178d6c89e5 100644 --- a/langtools/test/tools/sjavac/IdleShutdown.java +++ b/langtools/test/tools/sjavac/IdleShutdown.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -65,11 +65,11 @@ public class IdleShutdown { // Use Sjavac object and wait less than TIMEOUT_MS in between calls Thread.sleep(TIMEOUT_MS - 1000); log("Compiling"); - service.compile(new String[0], null, null); + service.compile(new String[0]); Thread.sleep(TIMEOUT_MS - 1000); log("Compiling"); - service.compile(new String[0], null, null); + service.compile(new String[0]); if (timeoutTimestamp.get() != -1) throw new AssertionError("Premature timeout detected."); @@ -103,7 +103,7 @@ public class IdleShutdown { public void shutdown() { } @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { // Attempt to trigger idle timeout during a call by sleeping try { Thread.sleep(TIMEOUT_MS + 1000); diff --git a/langtools/test/tools/sjavac/PooledExecution.java b/langtools/test/tools/sjavac/PooledExecution.java index 28c0105bf5a..ccd4265fee2 100644 --- a/langtools/test/tools/sjavac/PooledExecution.java +++ b/langtools/test/tools/sjavac/PooledExecution.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -30,10 +30,12 @@ * @build Wrapper * @run main Wrapper PooledExecution */ +import java.io.PrintWriter; import java.io.Writer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; +import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.server.Sjavac; @@ -67,7 +69,7 @@ public class PooledExecution { for (int i = 0; i < NUM_REQUESTS; i++) { tasks[i] = new Thread() { public void run() { - service.compile(new String[0], null, null); + service.compile(new String[0]); tasksFinished.incrementAndGet(); } }; @@ -109,7 +111,7 @@ public class PooledExecution { AtomicInteger activeRequests = new AtomicInteger(0); @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { leftToStart.countDown(); int numActiveRequests = activeRequests.incrementAndGet(); System.out.printf("Left to start: %2d / Currently active: %2d%n", From 889b3cc5eb13df28b0819a2cfeaef9366e41d249 Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Mon, 29 Feb 2016 13:37:29 +0100 Subject: [PATCH 156/311] 8147571: Information about written .h files is printed on the wrong logging level Changed how SmartWriter outputs log messages. Reviewed-by: jlahoda --- .../sun/tools/sjavac/comp/CompilationService.java | 11 +++-------- .../sun/tools/sjavac/comp/SmartFileManager.java | 10 ++-------- .../com/sun/tools/sjavac/comp/SmartFileObject.java | 8 +++----- .../com/sun/tools/sjavac/comp/SmartWriter.java | 14 +++++++------- 4 files changed, 15 insertions(+), 28 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java index 6569e28c076..0eb4f7e2358 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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,11 +95,8 @@ public class CompilationService { for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH)); - // Create a new logger - StringWriter stdoutLog = new StringWriter(); + // Create a log to capture compiler output StringWriter stderrLog = new StringWriter(); - PrintWriter stdout = new PrintWriter(stdoutLog); - PrintWriter stderr = new PrintWriter(stderrLog); com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; PublicApiCollector pubApiCollector = new PublicApiCollector(context, explicitJFOs); PathAndPackageVerifier papVerifier = new PathAndPackageVerifier(); @@ -108,11 +105,10 @@ public class CompilationService { if (explicitJFOs.size() > 0) { sfm.setVisibleSources(visibleSources); sfm.cleanArtifacts(); - sfm.setLog(stdout); // Do the compilation! JavacTaskImpl task = - (JavacTaskImpl) compiler.getTask(stderr, + (JavacTaskImpl) compiler.getTask(new PrintWriter(stderrLog), sfm, null, Arrays.asList(args), @@ -144,7 +140,6 @@ public class CompilationService { compilationResult.packagePubapis = pubApiCollector.getPubApis(true); compilationResult.dependencyPubapis = pubApiCollector.getPubApis(false); - compilationResult.stdout = stdoutLog.toString(); compilationResult.stderr = stderrLog.toString(); compilationResult.returnCode = rc.exitCode; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java index db66e4ab59f..496f039eb9a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -63,8 +63,6 @@ public class SmartFileManager extends ForwardingJavaFileManager Set visibleSources = new HashSet<>(); // Map from modulename:packagename to artifacts. Map> packageArtifacts = new HashMap<>(); - // Where to print informational messages. - PrintWriter stdout; public SmartFileManager(JavaFileManager fileManager) { super(fileManager); @@ -78,10 +76,6 @@ public class SmartFileManager extends ForwardingJavaFileManager packageArtifacts = new HashMap<>(); } - public void setLog(PrintWriter pw) { - stdout = pw; - } - /** * Set whether or not to use ct.sym as an alternate to rt.jar. */ @@ -188,7 +182,7 @@ public class SmartFileManager extends ForwardingJavaFileManager if (file == null) return file; if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && superFile instanceof JavaFileObject) { - file = new SmartFileObject((JavaFileObject) file, stdout); + file = new SmartFileObject((JavaFileObject) file); packageName = ":" + packageNameFromFileName(relativeName); } if (packageName.equals("")) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java index c7ac09d5868..e5295a16eb1 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -49,11 +49,9 @@ import com.sun.tools.javac.util.DefinedBy.Api; public class SmartFileObject implements JavaFileObject { JavaFileObject file; - PrintWriter stdout; - public SmartFileObject(JavaFileObject r, PrintWriter pw) { + public SmartFileObject(JavaFileObject r) { file = r; - stdout = pw; } @Override @@ -113,7 +111,7 @@ public class SmartFileObject implements JavaFileObject { } catch (FileNotFoundException | NoSuchFileException e) { // Perfectly ok. } - return new SmartWriter(file, s.toString(), file.getName(), stdout); + return new SmartWriter(file, s.toString(), file.getName()); } @DefinedBy(Api.COMPILER) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java index 0aabb65f4ce..2d1fa389858 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -25,6 +25,8 @@ package com.sun.tools.sjavac.comp; +import com.sun.tools.sjavac.Log; + import java.io.*; import javax.tools.JavaFileObject; @@ -45,19 +47,17 @@ public class SmartWriter extends Writer { JavaFileObject file; String oldContent; StringWriter newContent = new StringWriter(); - PrintWriter stdout; boolean closed; - public SmartWriter(JavaFileObject f, String s, String n, PrintWriter pw) { + + public SmartWriter(JavaFileObject f, String s, String n) { name = n; file = f; oldContent = s; newContent = new StringWriter(); - stdout = pw; closed = false; } - public void write(char[] chars, int i, int i1) - { + public void write(char[] chars, int i, int i1) { newContent.write(chars, i, i1); } @@ -70,7 +70,7 @@ public class SmartWriter extends Writer { try (Writer writer = file.openWriter()) { writer.write(s); } - stdout.println("Writing "+file.getName().substring(p+1)); + Log.debug("Writing " + file.getName().substring(p + 1)); } } From 2d20eec823a3d0c7d553ed8779a628011b1dc3bb Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Mon, 29 Feb 2016 14:16:20 +0100 Subject: [PATCH 157/311] 8150825: MethodHandles.tryFinally throws IndexOutOfBoundsException for non-conforming parameter lists Reviewed-by: redestad --- .../java/lang/invoke/MethodHandles.java | 6 ++++-- jdk/test/java/lang/invoke/T8139885.java | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index befe2520ec7..c35e3af28ab 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4137,8 +4137,10 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); // The cleanup parameter list (minus the leading Throwable and result parameters) must be a sublist of the // target parameter list. int cleanupArgIndex = rtype == void.class ? 1 : 2; - if (!cleanupParamTypes.subList(cleanupArgIndex, cleanupParamTypes.size()). - equals(target.type().parameterList().subList(0, cleanupParamTypes.size() - cleanupArgIndex))) { + List> cleanupArgSuffix = cleanupParamTypes.subList(cleanupArgIndex, cleanupParamTypes.size()); + List> targetParamTypes = target.type().parameterList(); + if (targetParamTypes.size() < cleanupArgSuffix.size() || + !cleanupArgSuffix.equals(targetParamTypes.subList(0, cleanupParamTypes.size() - cleanupArgIndex))) { throw misMatchedTypes("cleanup parameters after (Throwable,result) and target parameter list prefix", cleanup.type(), target.type()); } diff --git a/jdk/test/java/lang/invoke/T8139885.java b/jdk/test/java/lang/invoke/T8139885.java index d9bcb6b3a61..183ff9a9aca 100644 --- a/jdk/test/java/lang/invoke/T8139885.java +++ b/jdk/test/java/lang/invoke/T8139885.java @@ -26,6 +26,7 @@ /* @test * @bug 8139885 * @bug 8143798 + * @bug 8150825 * @run testng/othervm -ea -esa test.java.lang.invoke.T8139885 */ @@ -315,14 +316,17 @@ public class T8139885 { {intid, MethodHandles.identity(double.class)}, {intid, MethodHandles.dropArguments(intid, 0, String.class)}, {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class)}, - {errTarget, errCleanup} + {errTarget, errCleanup}, + {TryFinally.MH_voidTarget, TryFinally.MH_voidCleanup} }; String[] messages = { "target and return types must match: double != int", "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable", "cleanup second argument and target return type must match: (Throwable,double,int)int != int", "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " + - errCleanup.type() + " != " + errTarget.type() + errCleanup.type() + " != " + errTarget.type(), + "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " + + TryFinally.MH_voidCleanup.type() + " != " + TryFinally.MH_voidTarget.type() }; for (int i = 0; i < cases.length; ++i) { boolean caught = false; @@ -908,6 +912,10 @@ public class T8139885 { return r + " (but " + first + " first)!"; } + static void voidTarget() {} + + static void voidCleanup(Throwable t, int a) {} + static final Class TRY_FINALLY = TryFinally.class; static final MethodType MT_greet = methodType(String.class, String.class); @@ -916,6 +924,8 @@ public class T8139885 { static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class); static final MethodType MT_greetMore = methodType(String.class, String.class, String.class); static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class); + static final MethodType MT_voidTarget = methodType(void.class); + static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class, int.class); static final MethodHandle MH_greet; static final MethodHandle MH_exclaim; @@ -923,6 +933,8 @@ public class T8139885 { static final MethodHandle MH_printMore; static final MethodHandle MH_greetMore; static final MethodHandle MH_exclaimMore; + static final MethodHandle MH_voidTarget; + static final MethodHandle MH_voidCleanup; static final MethodType MT_hello = methodType(String.class, String.class); static final MethodType MT_printHello = methodType(void.class, String.class); @@ -936,6 +948,8 @@ public class T8139885 { MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore); MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore); MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore); + MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget); + MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup); } catch (Exception e) { throw new ExceptionInInitializerError(e); } From cd790e86a4d52a177cc7f3e99d5f9abe31107b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 1 Mar 2016 23:41:57 +0100 Subject: [PATCH 158/311] 8143228: Update module exports for Java Flight Recorder Reviewed-by: alanb, egahlin --- common/bin/compare_exceptions.sh.incl | 2 -- modules.xml | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/common/bin/compare_exceptions.sh.incl b/common/bin/compare_exceptions.sh.incl index fb68ede81d4..30ae49c6fc1 100644 --- a/common/bin/compare_exceptions.sh.incl +++ b/common/bin/compare_exceptions.sh.incl @@ -185,7 +185,6 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; ./lib/amd64/libjava.so ./lib/amd64/libjawt.so ./lib/amd64/libjdwp.so - ./lib/amd64/libjfr.so ./lib/amd64/libjpeg.so ./lib/amd64/libjsdt.so ./lib/amd64/libjsound.so @@ -321,7 +320,6 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "sparcv9" ] ./lib/sparcv9/libjava.so ./lib/sparcv9/libjawt.so ./lib/sparcv9/libjdwp.so - ./lib/sparcv9/libjfr.so ./lib/sparcv9/libjpeg.so ./lib/sparcv9/libjsdt.so ./lib/sparcv9/libjsound.so diff --git a/modules.xml b/modules.xml index 75a523a8cc8..7c3ab34f827 100644 --- a/modules.xml +++ b/modules.xml @@ -239,6 +239,7 @@ java.xml jdk.charsets jdk.management.resource + jdk.jfr jdk.net jdk.scripting.nashorn jdk.vm.ci @@ -249,6 +250,22 @@ java.management jdk.jvmstat + + jdk.internal.org.xml.sax + jdk.jfr + + + jdk.internal.org.xml.sax.helpers + jdk.jfr + + + jdk.internal.util.xml + jdk.jfr + + + jdk.internal.util.xml.impl + jdk.jfr + jdk.internal.org.objectweb.asm java.instrument @@ -314,6 +331,7 @@ jdk.vm.ci jdk.zipfs java.instrument + jdk.jfr sun.net @@ -914,6 +932,7 @@ sun.management.spi jdk.management jdk.management.cmm + jdk.management.jfr From 2d3d1ed1476a9af6f22d25754dbe04d6cd260dfe Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Mon, 29 Feb 2016 22:55:13 +0900 Subject: [PATCH 159/311] 8150723: HSDB toolbar icons are missing Reviewed-by: erikj, dsamersoff --- make/CompileJavaModules.gmk | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index 8593b3c784f..e8928e2130d 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -368,21 +368,7 @@ jdk.compiler_CLEAN_FILES := $(wildcard \ ################################################################################ jdk.hotspot.agent_ADD_JAVAC_FLAGS := $(DISABLE_WARNINGS),-overrides -jdk.hotspot.agent_COPY := .png sa.js .properties - -ifeq ($(MODULE), jdk.hotspot.agent) - ### Copy gif files - # Special handling to copy gif files in images/toolbarButtonGraphics \ - # -> classes/toolbarButtonGraphics. - # These can't be handled by COPY to SetupJavaCompilation since they chop off - # one directory level. - $(eval $(call SetupCopyFiles, COPY_SA_IMAGES, \ - SRC := $(HOTSPOT_TOPDIR)/src/jdk.hotspot.agent/share/classes/images, \ - DEST := $(JDK_OUTPUTDIR)/modules/$(MODULE), \ - FILES := $(wildcard $(HOTSPOT_TOPDIR)/src/jdk.hotspot.agent/share/classes/images/*/*/*.gif), \ - )) - jdk.hotspot.agent: $(COPY_SA_IMAGES) -endif +jdk.hotspot.agent_COPY := .gif .png sa.js .properties ################################################################################ From dbaa70361f45f8801b4854cce64cd64a1da29329 Mon Sep 17 00:00:00 2001 From: Derek White Date: Mon, 29 Feb 2016 11:32:12 -0500 Subject: [PATCH 160/311] 8140600: Convert unnecessarily malloc'd Monitors to value members Change a malloc'd monitor into an embedded monitor. Reviewed-by: tschatzl, kbarrett --- .../vm/gc/g1/g1YoungRemSetSamplingThread.cpp | 20 +++++++++---------- .../vm/gc/g1/g1YoungRemSetSamplingThread.hpp | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp index 8c8d216478c..060b7feb3ad 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp @@ -57,21 +57,21 @@ void G1YoungRemSetSamplingThread::stop() { } } -G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : ConcurrentGCThread() { - _monitor = new Monitor(Mutex::nonleaf, - "G1YoungRemSetSamplingThread monitor", - true, - Monitor::_safepoint_check_never); - +G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : + ConcurrentGCThread(), + _monitor(Mutex::nonleaf, + "G1YoungRemSetSamplingThread monitor", + true, + Monitor::_safepoint_check_never) { set_name("G1 Young RemSet Sampling"); create_and_start(); } void G1YoungRemSetSamplingThread::sleep_before_next_cycle() { - MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); if (!_should_terminate) { intx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? - _monitor->wait(Mutex::_no_safepoint_check_flag, waitms); + _monitor.wait(Mutex::_no_safepoint_check_flag, waitms); } } @@ -92,8 +92,8 @@ void G1YoungRemSetSamplingThread::run_service() { } void G1YoungRemSetSamplingThread::stop_service() { - MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); - _monitor->notify(); + MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); + _monitor.notify(); } void G1YoungRemSetSamplingThread::sample_young_list_rs_lengths() { diff --git a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp index d5837e42aee..78e82e7e352 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -41,7 +41,7 @@ // increase the young gen size to keep pause time length goal. class G1YoungRemSetSamplingThread: public ConcurrentGCThread { private: - Monitor* _monitor; + Monitor _monitor; void sample_young_list_rs_lengths(); From 10ce24734bee9c6e782183b21a12a28a4f0e9079 Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Mon, 29 Feb 2016 19:07:05 +0100 Subject: [PATCH 161/311] 8148498: The sjavac client should never create a port file Sjavac client now avoids creating a port file. Reviewed-by: jlahoda --- .../sun/tools/sjavac/client/ClientMain.java | 17 +++-------- .../sun/tools/sjavac/client/SjavacClient.java | 26 ++++++++--------- .../com/sun/tools/sjavac/server/PortFile.java | 28 +++++++++++++------ .../sun/tools/sjavac/server/SjavacServer.java | 3 +- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java index f7aa9b9ce66..54c1e51952f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java @@ -70,24 +70,15 @@ public class ClientMain { // Prepare sjavac object boolean useServer = options.getServerConf() != null; - Sjavac sjavac; - // Create an sjavac implementation to be used for compilation - if (useServer) { - try { - sjavac = new SjavacClient(options); - } catch (PortFileInaccessibleException e) { - Log.error("Port file inaccessible."); - return -1; - } - } else { - sjavac = new SjavacImpl(); - } + Sjavac sjavac = useServer ? new SjavacClient(options) : new SjavacImpl(); + // Perform compilation int rc = sjavac.compile(args); // If sjavac is running in the foreground we should shut it down at this point - if (!useServer) + if (!useServer) { sjavac.shutdown(); + } return rc; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java index e5e63ef2441..b9b039354d4 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java @@ -88,7 +88,7 @@ public class SjavacClient implements Sjavac { // Store the server conf settings here. private final String settings; - public SjavacClient(Options options) throws PortFileInaccessibleException { + public SjavacClient(Options options) { String tmpServerConf = options.getServerConf(); String serverConf = (tmpServerConf!=null)? tmpServerConf : ""; String tmpId = Util.extractStringOption("id", serverConf); @@ -98,12 +98,7 @@ public class SjavacClient implements Sjavac { .toAbsolutePath() .toString(); String portfileName = Util.extractStringOption("portfile", serverConf, defaultPortfile); - try { - portFile = SjavacServer.getPortFile(portfileName); - } catch (PortFileInaccessibleException e) { - Log.error("Port file inaccessable: " + e); - throw e; - } + portFile = SjavacServer.getPortFile(portfileName); sjavacForkCmd = Util.extractStringOption("sjavac", serverConf, "sjavac"); int poolsize = Util.extractIntOption("poolsize", serverConf); keepalive = Util.extractIntOption("keepalive", serverConf, 120); @@ -154,6 +149,9 @@ public class SjavacClient implements Sjavac { result = Integer.parseInt(content); } } + } catch (PortFileInaccessibleException e) { + Log.error("Port file inaccessible."); + result = CompilationSubResult.ERROR_FATAL; } catch (IOException ioe) { Log.error("IOException caught during compilation: " + ioe.getMessage()); Log.debug(ioe); @@ -204,13 +202,15 @@ public class SjavacClient implements Sjavac { private void makeSureServerIsRunning(PortFile portFile) throws IOException, InterruptedException { - portFile.lock(); - portFile.getValues(); - portFile.unlock(); + if (portFile.exists()) { + portFile.lock(); + portFile.getValues(); + portFile.unlock(); - if (portFile.containsPortInfo()) { - // Server seems to already be running - return; + if (portFile.containsPortInfo()) { + // Server seems to already be running + return; + } } // Fork a new server and wait for it to start diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java index d1a290adade..3bbdca22c4e 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java @@ -81,10 +81,15 @@ public class PortFile { * Create a new portfile. * @param fn is the path to the file. */ - public PortFile(String fn) throws PortFileInaccessibleException { + public PortFile(String fn) { filename = fn; file = new File(filename); stopFile = new File(filename+".stop"); + containsPortInfo = false; + lock = null; + } + + private void initializeChannel() throws PortFileInaccessibleException { try { rwfile = new RandomAccessFile(file, "rw"); } catch (FileNotFoundException e) { @@ -94,14 +99,15 @@ public class PortFile { // The rwfile should only be readable by the owner of the process // and no other! How do we do that on a RandomAccessFile? channel = rwfile.getChannel(); - containsPortInfo = false; - lock = null; } /** * Lock the port file. */ public void lock() throws IOException, InterruptedException { + if (channel == null) { + initializeChannel(); + } lockSem.acquire(); lock = channel.lock(); } @@ -204,8 +210,8 @@ public class PortFile { if (stopFile.exists()) { try { stopFile.delete(); - } catch (Exception e) - {} + } catch (Exception e) { + } return true; } return false; @@ -215,7 +221,9 @@ public class PortFile { * Unlock the port file. */ public void unlock() throws IOException { - Assert.check(lock != null); + if (lock == null) { + return; + } lock.release(); lock = null; lockSem.release(); @@ -230,9 +238,11 @@ public class PortFile { long timeout = startTime + getServerStartupTimeoutSeconds() * 1000; while (true) { Log.debug("Looking for valid port file values..."); - lock(); - getValues(); - unlock(); + if (exists()) { + lock(); + getValues(); + unlock(); + } if (containsPortInfo) { Log.debug("Valid port file values found after " + (System.currentTimeMillis() - startTime) + " ms"); return; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java index 6d5d541d7f6..ea9720886bf 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java @@ -107,8 +107,7 @@ public class SjavacServer implements Terminable { /** * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. */ - public static synchronized PortFile getPortFile(String filename) - throws PortFileInaccessibleException { + public static synchronized PortFile getPortFile(String filename) { if (allPortFiles == null) { allPortFiles = new HashMap<>(); } From 972e0af19385696f24c36935cd2d8d0e0839461e Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 29 Feb 2016 19:52:51 +0100 Subject: [PATCH 162/311] 8150874: Disable the ComputeFQNsTest.testSuspendIndexing test Reviewed-by: rfield --- langtools/test/jdk/jshell/ComputeFQNsTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/test/jdk/jshell/ComputeFQNsTest.java b/langtools/test/jdk/jshell/ComputeFQNsTest.java index a16ec1cb0c9..0f87fc7b950 100644 --- a/langtools/test/jdk/jshell/ComputeFQNsTest.java +++ b/langtools/test/jdk/jshell/ComputeFQNsTest.java @@ -73,6 +73,7 @@ public class ComputeFQNsTest extends KullaTesting { assertInferredFQNs("class X { ArrayList", "ArrayList".length(), false, "java.util.ArrayList"); } + @Test(enabled = false) //JDK-8150860 public void testSuspendIndexing() throws Exception { compiler.compile(outDir, "package test; public class FQNTest { }"); String jarName = "test.jar"; From 5a873632f38264c0f5cd14898fedaa3177f12274 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Mon, 29 Feb 2016 16:58:09 -0500 Subject: [PATCH 163/311] 8149064: TraceProtectionDomainVerification has been converted to Unified Logging TraceProtectionDomainVerification has been converted to Unified Logging with tag protectiondomain. Reviewed-by: coleenp, iklam --- hotspot/src/share/vm/classfile/dictionary.cpp | 6 +- hotspot/src/share/vm/classfile/dictionary.hpp | 5 +- .../share/vm/classfile/systemDictionary.cpp | 24 +++---- hotspot/src/share/vm/logging/logTag.hpp | 1 + hotspot/src/share/vm/runtime/globals.hpp | 3 - .../ProtectionDomainVerificationTest.java | 62 +++++++++++++++++++ 6 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 hotspot/test/runtime/logging/ProtectionDomainVerificationTest.java diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index 6f70ef9b47e..61c3bad0f8e 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -135,8 +135,10 @@ void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_dom // via a store to _pd_set. OrderAccess::release_store_ptr(&_pd_set, new_head); } - if (TraceProtectionDomainVerification && WizardMode) { - print(); + if (log_is_enabled(Trace, protectiondomain)) { + ResourceMark rm; + outputStream* log = LogHandle(protectiondomain)::trace_stream(); + print_count(log); } } diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp index a77f33717f3..a873fdd3e47 100644 --- a/hotspot/src/share/vm/classfile/dictionary.hpp +++ b/hotspot/src/share/vm/classfile/dictionary.hpp @@ -29,6 +29,7 @@ #include "oops/instanceKlass.hpp" #include "oops/oop.hpp" #include "utilities/hashtable.hpp" +#include "utilities/ostream.hpp" class DictionaryEntry; class PSPromotionManager; @@ -323,14 +324,14 @@ class DictionaryEntry : public HashtableEntry { return (klass->name() == class_name && _loader_data == loader_data); } - void print() { + void print_count(outputStream *st) { int count = 0; for (ProtectionDomainEntry* current = _pd_set; current != NULL; current = current->_next) { count++; } - tty->print_cr("pd set = #%d", count); + st->print_cr("pd set count = #%d", count); } }; diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 2a61613e910..549182e82cf 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -430,12 +430,15 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, // Now we have to call back to java to check if the initating class has access JavaValue result(T_VOID); - if (TraceProtectionDomainVerification) { + if (log_is_enabled(Debug, protectiondomain)) { + ResourceMark rm; // Print out trace information - tty->print_cr("Checking package access"); - tty->print(" - class loader: "); class_loader()->print_value_on(tty); tty->cr(); - tty->print(" - protection domain: "); protection_domain()->print_value_on(tty); tty->cr(); - tty->print(" - loading: "); klass()->print_value_on(tty); tty->cr(); + outputStream* log = LogHandle(protectiondomain)::debug_stream(); + log->print_cr("Checking package access"); + log->print("class loader: "); class_loader()->print_value_on(log); + log->print(" protection domain: "); protection_domain()->print_value_on(log); + log->print(" loading: "); klass()->print_value_on(log); + log->cr(); } KlassHandle system_loader(THREAD, SystemDictionary::ClassLoader_klass()); @@ -448,13 +451,10 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, protection_domain, THREAD); - if (TraceProtectionDomainVerification) { - if (HAS_PENDING_EXCEPTION) { - tty->print_cr(" -> DENIED !!!!!!!!!!!!!!!!!!!!!"); - } else { - tty->print_cr(" -> granted"); - } - tty->cr(); + if (HAS_PENDING_EXCEPTION) { + log_debug(protectiondomain)("DENIED !!!!!!!!!!!!!!!!!!!!!"); + } else { + log_debug(protectiondomain)("granted"); } if (HAS_PENDING_EXCEPTION) return; diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 08a78c6b2ba..d292c8339e9 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -67,6 +67,7 @@ LOG_TAG(phases) \ LOG_TAG(plab) \ LOG_TAG(promotion) \ + LOG_TAG(protectiondomain) /* "Trace protection domain verification" */ \ LOG_TAG(ref) \ LOG_TAG(refine) \ LOG_TAG(region) \ diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 848bb5d2607..672b3c340ab 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1478,9 +1478,6 @@ public: develop(bool, TraceCompiledIC, false, \ "Trace changes of compiled IC") \ \ - develop(bool, TraceProtectionDomainVerification, false, \ - "Trace protection domain verification") \ - \ develop(bool, TraceClearedExceptions, false, \ "Print when an exception is forcibly cleared") \ \ diff --git a/hotspot/test/runtime/logging/ProtectionDomainVerificationTest.java b/hotspot/test/runtime/logging/ProtectionDomainVerificationTest.java new file mode 100644 index 00000000000..57790ad1248 --- /dev/null +++ b/hotspot/test/runtime/logging/ProtectionDomainVerificationTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, 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 ProtectionDomainVerificationTest + * @bug 8149064 + * @library /testlibrary + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.Platform jdk.test.lib.ProcessTools + * @run driver ProtectionDomainVerificationTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.ProcessTools; + +public class ProtectionDomainVerificationTest { + + public static void main(String... args) throws Exception { + + // -Xlog:protectiondomain=trace + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:protectiondomain=trace", + "-Xmx64m", + Hello.class.getName()); + OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldContain("[protectiondomain] Checking package access"); + out.shouldContain("[protectiondomain] pd set count = #"); + + // -Xlog:protectiondomain=debug + pb = ProcessTools.createJavaProcessBuilder("-Xlog:protectiondomain=debug", + "-Xmx64m", + Hello.class.getName()); + out = new OutputAnalyzer(pb.start()); + out.shouldContain("[protectiondomain] Checking package access"); + out.shouldNotContain("pd set count = #"); + } + + public static class Hello { + public static void main(String[] args) { + System.out.print("Hello!"); + } + } +} From c881ca81db80de620e1f4437152cd69b83617e6a Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Mon, 29 Feb 2016 18:00:40 -0500 Subject: [PATCH 164/311] 8150346: java/lang/ProcessHandle/InfoTest.java failed - startTime after process spawn completed Reviewed-by: redestad, martin --- jdk/test/java/lang/ProcessHandle/Basic.java | 2 +- jdk/test/java/lang/ProcessHandle/InfoTest.java | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/jdk/test/java/lang/ProcessHandle/Basic.java b/jdk/test/java/lang/ProcessHandle/Basic.java index dae37952c65..005fd538f60 100644 --- a/jdk/test/java/lang/ProcessHandle/Basic.java +++ b/jdk/test/java/lang/ProcessHandle/Basic.java @@ -37,7 +37,7 @@ import org.testng.annotations.Test; /* * @test * @library /test/lib/share/classes - * @run testng InfoTest + * @run testng Basic * @summary Basic tests for ProcessHandler * @author Roger Riggs */ diff --git a/jdk/test/java/lang/ProcessHandle/InfoTest.java b/jdk/test/java/lang/ProcessHandle/InfoTest.java index cfb21d868db..1688c369343 100644 --- a/jdk/test/java/lang/ProcessHandle/InfoTest.java +++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java @@ -114,9 +114,13 @@ public class InfoTest { long cpuLoopTime = 100; // 100 ms String[] extraArgs = {"pid", "parent", "stdin"}; JavaChild p1 = JavaChild.spawnJavaChild((Object[])extraArgs); - Instant afterStart = Instant.now(); + Instant afterStart = null; try (BufferedReader lines = p1.outputReader()) { + // Read the args line to know the subprocess has started + lines.readLine(); + afterStart = Instant.now(); + Duration lastCpu = Duration.ofMillis(0L); for (int j = 0; j < 10; j++) { @@ -126,8 +130,7 @@ public class InfoTest { // Read cputime from child Duration childCpuTime = null; // Read lines from the child until the result from cputime is returned - String s; - while ((s = lines.readLine()) != null) { + for (String s; (s = lines.readLine()) != null;) { String[] split = s.trim().split(" "); if (split.length == 3 && split[1].equals("cputime")) { long nanos = Long.valueOf(split[2]); From 12d9b13eee9abdb71a4e4817e25a2b3dd17b9f88 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Tue, 1 Mar 2016 09:42:19 +0100 Subject: [PATCH 165/311] 8150822: Fix typo in JDK-8150201 Reviewed-by: ihse, dholmes --- hotspot/make/solaris/makefiles/amd64.make | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/solaris/makefiles/amd64.make b/hotspot/make/solaris/makefiles/amd64.make index 7b1bdf3d8b3..3eb6dee9b92 100644 --- a/hotspot/make/solaris/makefiles/amd64.make +++ b/hotspot/make/solaris/makefiles/amd64.make @@ -39,7 +39,7 @@ OPT_CFLAGS/c1_LinearScan.o = -xO2 # of OPT_CFLAGS. Restore it here. ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) OPT_CFLAGS/generateOptoStub.o += -g0 -xs - OPT_CFLAGS/LinearScan.o += -g0 -xs + OPT_CFLAGS/c1_LinearScan.o += -g0 -xs endif else From 34ae7a246ed2a46e104eea6cce0d78517fa745df Mon Sep 17 00:00:00 2001 From: Harsha Wardhana B Date: Tue, 1 Mar 2016 09:48:49 +0100 Subject: [PATCH 166/311] 8147610: javax/management/mxbean/MXBeanLoadingTest1.java assumes URLClassLoader Reviewed-by: jbachorik --- .../management/mxbean/MXBeanLoadingTest1.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java b/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java index 699260777d1..2dd9abdaaa6 100644 --- a/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java +++ b/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -33,7 +33,6 @@ import java.lang.ref.WeakReference; import java.net.URL; -import java.net.URLClassLoader; import java.util.Arrays; import java.util.Map; import javax.management.Attribute; @@ -70,16 +69,16 @@ public class MXBeanLoadingTest1 { + " some little extra check of Descriptors, MBean*Info."); ClassLoader myClassLoader = MXBeanLoadingTest1.class.getClassLoader(); + if(myClassLoader == null) + throw new RuntimeException("Test Failed : Null Classloader for test"); + URL url = myClassLoader.getResource( + MXBeanLoadingTest1.class.getCanonicalName() + .replace(".", "/") + ".class"); + String clsLoadPath = url.toURI().toString(). + replaceAll(MXBeanLoadingTest1.class.getSimpleName() + + ".class", ""); - if (!(myClassLoader instanceof URLClassLoader)) { - String message = "(ERROR) Test's class loader is not " + - "a URLClassLoader"; - System.out.println(message); - throw new RuntimeException(message); - } - - URLClassLoader myURLClassLoader = (URLClassLoader) myClassLoader; - URL[] urls = myURLClassLoader.getURLs(); + URL[] urls = new URL[]{new URL(clsLoadPath)}; PrivateMLet mlet = new PrivateMLet(urls, null, false); Class shadowClass = mlet.loadClass(TestMXBean.class.getName()); From a2f7bf924cab264898ff681622d8af0767d132b8 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Tue, 1 Mar 2016 12:05:14 +0100 Subject: [PATCH 167/311] 8150856: Inconsistent API documentation for @param caller in System.LoggerFinder.getLogger @throws clause is correct; @param caller documentation fixed: caller must not be null. Reviewed-by: martin --- jdk/src/java.base/share/classes/java/lang/System.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index 1919264ce52..3f12f08eab4 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, 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 @@ -1418,8 +1418,7 @@ public final class System { * for the given {@code caller}. * * @param name the name of the logger. - * @param caller the class for which the logger is being requested; - * can be {@code null}. + * @param caller the class for which the logger is being requested. * * @return a {@link Logger logger} suitable for the given caller's * use. From 274a8c99ce88751d9e2e42db484180bd2ea06d2e Mon Sep 17 00:00:00 2001 From: Aleksei Efimov Date: Tue, 1 Mar 2016 17:19:31 +0300 Subject: [PATCH 168/311] 8150174: Update JAX-WS RI integration to latest version (2.3.0-SNAPSHOT) Reviewed-by: lancea --- .../bind/v2/runtime/reflect/opt/Const.java | 18 +++---- .../runtime/unmarshaller/StructureLoader.java | 23 +++------ .../bind/v2/schemagen/XmlSchemaGenerator.java | 33 +++++++++++-- .../saaj/client/p2p/HttpSOAPConnection.java | 10 ++-- .../mime/internet/InternetHeaders.java | 4 +- .../packaging/mime/internet/MimeBodyPart.java | 5 +- .../internal/ws/api/pipe/ThreadHelper.java | 20 ++++---- .../xml/internal/ws/transport/Headers.java | 14 +++++- .../xml/internal/ws/util/ServiceFinder.java | 6 +-- .../xml/internal/ws/util/version.properties | 4 +- .../classes/javax/xml/soap/FactoryFinder.java | 4 +- .../javax/xml/ws/spi/FactoryFinder.java | 5 +- .../com/sun/codemodel/internal/JJavaName.java | 4 +- .../internal/jxc/MessageBundle.properties | 49 +++++++++++++++++++ .../internal/jxc/MessageBundle_de.properties | 34 +++++++++++++ .../internal/jxc/MessageBundle_es.properties | 34 +++++++++++++ .../internal/jxc/MessageBundle_fr.properties | 34 +++++++++++++ .../internal/jxc/MessageBundle_it.properties | 34 +++++++++++++ .../internal/jxc/MessageBundle_ja.properties | 34 +++++++++++++ .../internal/jxc/MessageBundle_ko.properties | 34 +++++++++++++ .../jxc/MessageBundle_pt_BR.properties | 34 +++++++++++++ .../jxc/MessageBundle_zh_CN.properties | 34 +++++++++++++ .../jxc/MessageBundle_zh_TW.properties | 34 +++++++++++++ .../internal/jxc/ap/MessageBundle.properties | 33 +++++++++++++ .../jxc/ap/MessageBundle_de.properties | 30 ++++++++++++ .../jxc/ap/MessageBundle_es.properties | 30 ++++++++++++ .../jxc/ap/MessageBundle_fr.properties | 30 ++++++++++++ .../jxc/ap/MessageBundle_it.properties | 30 ++++++++++++ .../jxc/ap/MessageBundle_ja.properties | 30 ++++++++++++ .../jxc/ap/MessageBundle_ko.properties | 30 ++++++++++++ .../jxc/ap/MessageBundle_pt_BR.properties | 30 ++++++++++++ .../jxc/ap/MessageBundle_zh_CN.properties | 30 ++++++++++++ .../jxc/ap/MessageBundle_zh_TW.properties | 30 ++++++++++++ .../tools/internal/xjc/model/CTypeRef.java | 16 +++--- .../sun/tools/internal/ws/version.properties | 4 +- 35 files changed, 756 insertions(+), 72 deletions(-) create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_de.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_es.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_fr.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_it.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ja.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ko.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_pt_BR.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_CN.properties create mode 100644 jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_TW.properties diff --git a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java index 0cbec252c26..8b658911397 100644 --- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java +++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -29,12 +29,12 @@ package com.sun.xml.internal.bind.v2.runtime.reflect.opt; * @author Kohsuke Kawaguchi */ public final class Const { - public static byte default_value_byte = 0; - public static boolean default_value_boolean = false; - public static char default_value_char = 0; - public static float default_value_float = 0; - public static double default_value_double = 0; - public static int default_value_int = 0; - public static long default_value_long = 0; - public static short default_value_short = 0; + public static final byte default_value_byte = 0; + public static final boolean default_value_boolean = false; + public static final char default_value_char = 0; + public static final float default_value_float = 0; + public static final double default_value_double = 0; + public static final int default_value_int = 0; + public static final long default_value_long = 0; + public static final short default_value_short = 0; } diff --git a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java index 0d4fa2647db..9becb9dd086 100644 --- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java +++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -231,22 +231,11 @@ public final class StructureLoader extends Loader { @Override public void childElement(UnmarshallingContext.State state, TagName arg) throws SAXException { ChildLoader child = childUnmarshallers.get(arg.uri,arg.local); - if(child==null) { - if ((beanInfo != null) && (beanInfo.getTypeNames() != null)) { - Iterator typeNamesIt = beanInfo.getTypeNames().iterator(); - QName parentQName = null; - if ((typeNamesIt != null) && (typeNamesIt.hasNext()) && (catchAll == null)) { - parentQName = (QName) typeNamesIt.next(); - String parentUri = parentQName.getNamespaceURI(); - child = childUnmarshallers.get(parentUri, arg.local); - } - } - if (child == null) { - child = catchAll; - if(child==null) { - super.childElement(state,arg); - return; - } + if (child == null) { + child = catchAll; + if (child==null) { + super.childElement(state,arg); + return; } } diff --git a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java index b292e450fa8..42ef308e632 100644 --- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java +++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -110,6 +110,7 @@ import com.sun.xml.internal.txw2.TypedXmlWriter; import com.sun.xml.internal.txw2.output.ResultFactory; import com.sun.xml.internal.txw2.output.XmlSerializer; import java.util.Collection; +import java.util.HashSet; import org.xml.sax.SAXParseException; /** @@ -436,7 +437,7 @@ public final class XmlSchemaGenerator { if(logger.isLoggable(Level.FINE)) { // debug logging to see what's going on. - logger.log(Level.FINE,"Wrigin XML Schema for "+toString(),new StackRecorder()); + logger.log(Level.FINE,"Writing XML Schema for "+toString(),new StackRecorder()); } // make it fool-proof @@ -465,6 +466,8 @@ public final class XmlSchemaGenerator { systemIds.put(n,output.getSystemId()); } } + //Clear the namespace specific set with already written classes + n.resetWritten(); } // then write'em all @@ -542,12 +545,24 @@ public final class XmlSchemaGenerator { */ private boolean useMimeNs; + /** + * Container for already processed classes + */ + private final Set written = new HashSet(); + public Namespace(String uri) { this.uri = uri; assert !XmlSchemaGenerator.this.namespaces.containsKey(uri); XmlSchemaGenerator.this.namespaces.put(uri,this); } + /** + * Clear out the set of already processed classes for this namespace + */ + void resetWritten() { + written.clear(); + } + /** * Process the given PropertyInfo looking for references to namespaces that * are foreign to the given namespace. Any foreign namespace references @@ -853,6 +868,10 @@ public final class XmlSchemaGenerator { * @param parent the writer of the parent element into which the type will be defined */ private void writeClass(ClassInfo c, TypeHost parent) { + if (written.contains(c)) { // to avoid cycles let's check if we haven't already processed the class + return; + } + written.add(c); // special handling for value properties if (containsValueProp(c)) { if (c.getProperties().size() == 1) { @@ -1080,9 +1099,13 @@ public final class XmlSchemaGenerator { } } } - if (cImpl != null) - e.ref(new QName(cImpl.getElementName().getNamespaceURI(), tn.getLocalPart())); - else + if (cImpl != null) { + if (tn.getNamespaceURI() != null && tn.getNamespaceURI().trim().length() != 0) { + e.ref(new QName(tn.getNamespaceURI(), tn.getLocalPart())); + } else { + e.ref(new QName(cImpl.getElementName().getNamespaceURI(), tn.getLocalPart())); + } + } else e.ref(new QName("", tn.getLocalPart())); } else e.ref(tn); diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java index 4a8bf2ad05c..4ff655a0051 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -512,13 +512,9 @@ class HttpSOAPConnection extends SOAPConnection { : httpConnection.getInputStream()); // If no reply message is returned, // content-Length header field value is expected to be zero. - // java SE 6 documentation says : - // available() : an estimate of the number of bytes that can be read - //(or skipped over) from this input stream without blocking - //or 0 when it reaches the end of the input stream. + // InputStream#available() can't be used here - it just says no data *YET*! if ((httpIn == null ) - || (httpConnection.getContentLength() == 0) - || (httpIn.available() == 0)) { + || (httpConnection.getContentLength() == 0)) { response = null; log.warning("SAAJ0014.p2p.content.zero"); } else { diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java index 38071ae07ed..bf39ee7540b 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -285,7 +285,7 @@ public final class InternetHeaders { * * @return Header objects */ - public FinalArrayList getAllHeaders() { + public List getAllHeaders() { return headers; // conceptually it should be read-only, but for performance reason I'm not wrapping it here } diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java index 47077fa4393..6642dfa19ce 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ package com.sun.xml.internal.messaging.saaj.packaging.mime.internet; +import com.sun.xml.internal.messaging.saaj.packaging.mime.Header; import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException; import com.sun.xml.internal.messaging.saaj.packaging.mime.util.OutputUtil; import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream; @@ -1041,7 +1042,7 @@ public final class MimeBodyPart { * Return all the headers from this Message as an Enumeration of * Header objects. */ - public FinalArrayList getAllHeaders() { + public List getAllHeaders() { return headers.getAllHeaders(); } diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java index a29edc91cc2..25e0462c3bb 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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,7 +32,7 @@ import java.util.concurrent.ThreadFactory; /** * Simple utility class to instantiate correct Thread instance - * depending on runtime context (jdk/non-jdk usage) and Java version. + * depending on Java version. * * @author miroslav.kos@oracle.com */ @@ -101,16 +101,16 @@ final class ThreadHelper { SunMiscThreadFactory(Constructor ctr) { this.ctr = ctr; } @Override public Thread newThread(Runnable r) { return AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public Thread run() { - try { - return (Thread) ctr.newInstance(r); - } catch (Exception e) { - return new Thread(r); + new PrivilegedAction() { + @Override + public Thread run() { + try { + return (Thread) ctr.newInstance(r); + } catch (Exception e) { + return new Thread(r); + } } } - } ); } } diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java index 4e52e928157..1548196df9e 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -127,5 +127,17 @@ public class Headers extends TreeMap> { l.add (value); put(key, l); } + /** + * Added to fix issue + * putAll() is easier to deal with as it doesn't return anything + */ + public void putAll(Map> map) { + for (String k : map.keySet()) { + List list = map.get(k); + for (String v : list) { + add(k,v); + } + } + } } diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java index bae830f73df..63f42c2c6be 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -338,13 +338,13 @@ public final class ServiceFinder implements Iterable { int lc = 1; while ((lc = parseLine(service, u, r, lc, names, returned)) >= 0) ; } catch (IOException x) { - fail(service, ": " + x); + fail(service, ": " + x +";URL is :"+u.toString()); } finally { try { if (r != null) r.close(); if (in != null) in.close(); } catch (IOException y) { - fail(service, ": " + y); + fail(service, ": " + y +";URL is :"+u.toString()); } } return names.iterator(); diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties index 462e4882799..8d2adcadac9 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, 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 @@ -26,4 +26,4 @@ build-id=2.3.0-SNAPSHOT build-version=JAX-WS RI 2.3.0-SNAPSHOT major-version=2.3.0 -svn-revision=ffaa49e66cc05e1bb2ddc103076a340dad5df997 +svn-revision=282759e2b822078de9ba78c743ed663541c16ead diff --git a/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java b/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java index 6dcb4b1f1aa..ef5500a0627 100644 --- a/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java +++ b/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, 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 @@ -184,7 +184,7 @@ class FactoryFinder { private static String fromJDKProperties(String factoryId, String deprecatedFactoryId) { Path path = null; try { - String JAVA_HOME = System.getProperty("java.home"); + String JAVA_HOME = getSystemProperty("java.home"); path = Paths.get(JAVA_HOME, "conf", "jaxm.properties"); logger.log(Level.FINE, "Checking configuration in {0}", path); diff --git a/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java b/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java index 8c308b8d907..c7f4aab3b35 100644 --- a/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java +++ b/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -137,7 +137,8 @@ class FactoryFinder { } catch (Exception ignored) { logger.log(Level.SEVERE, "Error reading JAX-WS configuration from [" + path + "] file. Check it is accessible and has correct format.", ignored); - } return null; + } + return null; } private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader"; diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java b/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java index 6c024456b89..1af2c5d9a31 100644 --- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -85,7 +85,7 @@ public class JJavaName { * ("my_children","MyChildren","myChildren", and "MY-CHILDREN", "CODE003-children" respectively) *

      * Although this method only works for English words, it handles non-English - * words gracefully (by just returning it as-is.) For example, 日本語 + * words gracefully (by just returning it as-is.) For example, "日本語" * will be returned as-is without modified, not "日本語s" *

      * This method doesn't handle suffixes very well. For example, passing diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties new file mode 100644 index 00000000000..0cc3e21ee84 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties @@ -0,0 +1,49 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = \ + Unexpected {0} appears at line {1} column {2} + +BASEDIR_DOESNT_EXIST = \ + Non-existent directory: {0} + +VERSION = \ + schemagen 2.3.0-SNAPSHOT + +FULLVERSION = \ + schemagen full version "2.3.0-SNAPSHOT" + +USAGE = \ +Usage: schemagen [-options ...] \n\ +Options: \n\ +\ \ \ \ -d : specify where to place processor and javac generated class files\n\ +\ \ \ \ -cp : specify where to find user specified files\n\ +\ \ \ \ -classpath : specify where to find user specified files\n\ +\ \ \ \ -encoding : specify encoding to be used for annotation processing/javac invocation \n\ +\ \ \ \ -episode : generate episode file for separate compilation\n\ +\ \ \ \ -disableXmlSecurity : disables XML security features for usage on xml parsing apis \n\ +\ \ \ \ -version : display version information\n\ +\ \ \ \ -fullversion : display full version information\n\ +\ \ \ \ -help : display this usage message diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties new file mode 100644 index 00000000000..3158ce32236 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = Nicht erkanntes {0} in Zeile {1} Spalte {2} + +BASEDIR_DOESNT_EXIST = Nicht vorhandenes Verzeichnis: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen vollst\u00E4ndige Version "2.3.0-SNAPSHOT" + +USAGE = Verwendung: schemagen [-options ...] \nOptionen: \n\\ \\ \\ \\ -d : Gibt an, wo die von Prozessor und javac generierten Klassendateien gespeichert werden sollen\n\\ \\ \\ \\ -cp : Gibt an, wo die vom Benutzer angegebenen Dateien gespeichert sind\n\\ \\ \\ \\ -classpath : Gibt an, wo die vom Benutzer angegebenen Dateien gespeichert sind\n\\ \\ \\ \\ -encoding : Gibt die Codierung f\u00FCr die Annotationsverarbeitung/den javac-Aufruf an \n\\ \\ \\ \\ -episode : Generiert Episodendatei f\u00FCr separate Kompilierung\n\\ \\ \\ \\ -version : Zeigt Versionsinformation an\n\\ \\ \\ \\ -fullversion : Zeigt vollst\u00E4ndige Versionsinformationen an\n\\ \\ \\ \\ -help : Zeigt diese Verwendungsmeldung an diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties new file mode 100644 index 00000000000..81d9274dc3c --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = Aparece un {0} inesperado en la l\u00EDnea {1} y la columna {2} + +BASEDIR_DOESNT_EXIST = Directorio no existente: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = versi\u00F3n completa de schemagen "2.3.0-SNAPSHOT" + +USAGE = Sintaxis: schemagen [-options ...] \nOpciones: \n\\ \\ \\ \\ -d : especifique d\u00F3nde se colocan los archivos de clase generados por javac y el procesador\n\\ \\ \\ \\ -cp : especifique d\u00F3nde se encuentran los archivos especificados por el usuario\n\\ \\ \\ \\ -encoding : especifique la codificaci\u00F3n que se va a utilizar para el procesamiento de anotaciones/llamada de javac\n\\ \\ \\ \\ -episode : genera un archivo de episodio para una compilaci\u00F3n diferente\n\\ \\ \\ \\ -version : muestra la informaci\u00F3n de la versi\u00F3n\n\\ \\ \\ \\ -fullversion : muestra la informaci\u00F3n completa de la versi\u00F3n\n\\ \\ \\ \\ -help : muestra este mensaje de sintaxis diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties new file mode 100644 index 00000000000..597ce0e512b --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = Un \u00E9l\u00E9ment {0} inattendu appara\u00EEt \u00E0 la ligne {1}, colonne {2} + +BASEDIR_DOESNT_EXIST = R\u00E9pertoire {0} inexistant + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = version compl\u00E8te de schemagen "2.3.0-SNAPSHOT" + +USAGE = Syntaxe : schemagen [-options ...] \nOptions : \n\ \ \ \ -d : indiquez o\u00F9 placer les fichiers de classe g\u00E9n\u00E9r\u00E9s par le processeur et le compilateur javac\n\ \ \ \ -cp : indiquez o\u00F9 trouver les fichiers sp\u00E9cifi\u00E9s par l'utilisateur\n\ \ \ \ -classpath : indiquez o\u00F9 trouver les fichiers sp\u00E9cifi\u00E9s par l'utilisateur\n\ \ \ \ -encoding : indiquez l'encodage \u00E0 utiliser pour l'appel de javac/traitement de l'annotation \n\ \ \ \ -episode : g\u00E9n\u00E9rez un fichier d'\u00E9pisode pour la compilation s\u00E9par\u00E9e\n\ \ \ \ -version : affichez les informations de version\n\ \ \ \ -fullversion : affichez les informations compl\u00E8tes de version\n\ \ \ \ -help : affichez ce message de syntaxe diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties new file mode 100644 index 00000000000..c7ef575e06e --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = {0} imprevisto visualizzato sulla riga {1} colonna {2} + +BASEDIR_DOESNT_EXIST = Directory non esistente: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = versione completa schemagen "2.3.0-SNAPSHOT" + +USAGE = Uso: schemagen [-options ...] \nOpzioni: \n\ \ \ \ -d : specifica dove posizionare il processore e i file della classe generata javac\n\ \ \ \ -cp : specifica dove trovare i file specificati dall'utente\n\ \ \ \ -classpath : specifica dove trovare i file specificati dall'utente\n\ \ \ \ -encoding : specifica la codifica da usare per l'elaborazione dell'annotazione/richiamo javac \n\ \ \ \ -episode : genera il file di episodio per la compilazione separata\n\ \ \ \ -version : visualizza le informazioni sulla versione\n\ \ \ \ -fullversion : visualizza le informazioni sulla versione completa\n\ \ \ \ -help : visualizza questo messaggio sull'uso diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties new file mode 100644 index 00000000000..e07c234ff85 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = \u4E88\u671F\u3057\u306A\u3044{0}\u304C\u884C{1}\u3001\u5217{2}\u306B\u3042\u308A\u307E\u3059 + +BASEDIR_DOESNT_EXIST = \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen\u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3"2.3.0-SNAPSHOT" + +USAGE = \u4F7F\u7528\u65B9\u6CD5: schemagen [-options ...] \n\u30AA\u30D7\u30B7\u30E7\u30F3: \n\ \ \ \ -d : \u30D7\u30ED\u30BB\u30C3\u30B5\u304A\u3088\u3073javac\u304C\u751F\u6210\u3057\u305F\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u7F6E\u304F\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -cp : \u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -classpath : \u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -encoding : \u6CE8\u91C8\u51E6\u7406/javac\u547C\u51FA\u3057\u306B\u4F7F\u7528\u3059\u308B\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -episode : \u30B3\u30F3\u30D1\u30A4\u30EB\u3054\u3068\u306B\u30A8\u30D4\u30BD\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u751F\u6210\u3057\u307E\u3059\n\ \ \ \ -version : \u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\n\ \ \ \ -fullversion : \u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\n\ \ \ \ -help : \u3053\u306E\u4F7F\u7528\u4F8B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u307E\u3059 diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties new file mode 100644 index 00000000000..f4e5fa4d62e --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = \uC608\uC0C1\uCE58 \uC54A\uC740 {0}\uC774(\uAC00) {1}\uD589 {2}\uC5F4\uC5D0 \uB098\uD0C0\uB0A9\uB2C8\uB2E4. + +BASEDIR_DOESNT_EXIST = \uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uB514\uB809\uD1A0\uB9AC: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen \uC815\uC2DD \uBC84\uC804 "2.3.0-SNAPSHOT" + +USAGE = \uC0AC\uC6A9\uBC95: schemagen [-options ...] \n\uC635\uC158: \n\ \ \ \ -d : \uD504\uB85C\uC138\uC11C \uBC0F javac\uC5D0\uC11C \uC0DD\uC131\uD55C \uD074\uB798\uC2A4 \uD30C\uC77C\uC744 \uBC30\uCE58\uD560 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -cp : \uC0AC\uC6A9\uC790\uAC00 \uC9C0\uC815\uD55C \uD30C\uC77C\uC744 \uCC3E\uC744 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -classpath : \uC0AC\uC6A9\uC790\uAC00 \uC9C0\uC815\uD55C \uD30C\uC77C\uC744 \uCC3E\uC744 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -encoding : \uC8FC\uC11D \uCC98\uB9AC/javac \uD638\uCD9C\uC5D0 \uC0AC\uC6A9\uD560 \uC778\uCF54\uB529\uC744 \uC9C0\uC815\uD569\uB2C8\uB2E4. \n\ \ \ \ -episode : \uBCC4\uB3C4 \uCEF4\uD30C\uC77C\uC744 \uC704\uD574 episode \uD30C\uC77C\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4.\n\ \ \ \ -version : \uBC84\uC804 \uC815\uBCF4\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.\n\ \ \ \ -fullversion : \uC815\uC2DD \uBC84\uC804 \uC815\uBCF4\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.\n\ \ \ \ -help : \uC774 \uC0AC\uC6A9\uBC95 \uBA54\uC2DC\uC9C0\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties new file mode 100644 index 00000000000..d56ca3894d5 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = {0} inesperado aparece na linha {1} coluna {2} + +BASEDIR_DOESNT_EXIST = Diret\u00F3rio n\u00E3o existente: {0} + +VERSION = gera\u00E7\u00E3o do esquema 2.3.0-SNAPSHOT + +FULLVERSION = vers\u00E3o completa da gera\u00E7\u00E3o do esquema "2.3.0-SNAPSHOT" + +USAGE = Uso: gera\u00E7\u00E3o do esquema [-options ...] \nOp\u00E7\u00F5es: \n\\ \\ \\ \\ -d : especificar onde colocar o processador e os arquivos da classe gerados por javac\n\\ \\ \\ \\ -cp : especificar onde localizar arquivos especificados pelo usu\u00E1rio\n\\ \\ \\ \\ -classpath : especificar onde localizar os arquivos especificados pelo usu\u00E1rio\n\\ \\ \\ \\ -encoding : especificar codifica\u00E7\u00E3o a ser usada para processamento de anota\u00E7\u00E3o/chamada javac \n\\ \\ \\ \\ -episode : gerar arquivo do epis\u00F3dio para compila\u00E7\u00E3o separada\n\\ \\ \\ \\ -version : exibir informa\u00E7\u00F5es da vers\u00E3o\n\\ \\ \\ \\ -fullversion : exibir informa\u00E7\u00F5es da vers\u00E3o completa\n\\ \\ \\ \\ -help : exibir esta mensagem de uso diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties new file mode 100644 index 00000000000..c1be9f0f704 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = \u5728\u7B2C {1} \u884C, \u7B2C {2} \u5217\u51FA\u73B0\u610F\u5916\u7684{0} + +BASEDIR_DOESNT_EXIST = \u4E0D\u5B58\u5728\u7684\u76EE\u5F55: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.0-SNAPSHOT" + +USAGE = \u7528\u6CD5: schemagen [-options ...] \n\u9009\u9879: \n\ \ \ \ -d : \u6307\u5B9A\u653E\u7F6E\u5904\u7406\u7A0B\u5E8F\u548C javac \u751F\u6210\u7684\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -cp : \u6307\u5B9A\u67E5\u627E\u7528\u6237\u6307\u5B9A\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -classpath : \u6307\u5B9A\u67E5\u627E\u7528\u6237\u6307\u5B9A\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -encoding : \u6307\u5B9A\u7528\u4E8E\u6CE8\u91CA\u5904\u7406/javac \u8C03\u7528\u7684\u7F16\u7801\n\ \ \ \ -episode : \u751F\u6210\u7247\u6BB5\u6587\u4EF6\u4EE5\u4F9B\u5355\u72EC\u7F16\u8BD1\n\ \ \ \ -version : \u663E\u793A\u7248\u672C\u4FE1\u606F\n\ \ \ \ -fullversion : \u663E\u793A\u5B8C\u6574\u7684\u7248\u672C\u4FE1\u606F\n\ \ \ \ -help : \u663E\u793A\u6B64\u7528\u6CD5\u6D88\u606F diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties new file mode 100644 index 00000000000..dcd7976be7c --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +UNEXPECTED_NGCC_TOKEN = \u672A\u9810\u671F\u7684 {0} \u986F\u793A\u65BC\u884C {1} \u8CC7\u6599\u6B04 {2} + +BASEDIR_DOESNT_EXIST = \u4E0D\u5B58\u5728\u7684\u76EE\u9304: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.0-SNAPSHOT" + +USAGE = \u7528\u6CD5: schemagen [-options ...] \n\u9078\u9805: \n\\ \\ \\ \\ -d : \u6307\u5B9A\u8655\u7406\u5668\u4EE5\u53CA javac \u7522\u751F\u7684\u985E\u5225\u6A94\u6848\u653E\u7F6E\u4F4D\u7F6E\n\\ \\ \\ \\ -cp : \u6307\u5B9A\u8981\u5C0B\u627E\u4F7F\u7528\u8005\u6307\u5B9A\u6A94\u6848\u7684\u4F4D\u7F6E\n\\ \\ \\ \\ -classpath : \u6307\u5B9A\u8981\u5C0B\u627E\u4F7F\u7528\u8005\u6307\u5B9A\u6A94\u6848\u7684\u4F4D\u7F6E\n\\ \\ \\ \\ -encoding : \u6307\u5B9A\u8981\u7528\u65BC\u8A3B\u89E3\u8655\u7406/javac \u547C\u53EB\u7684\u7DE8\u78BC \n\\ \\ \\ \\ -episode : \u7522\u751F\u7368\u7ACB\u7DE8\u8B6F\u7684\u4E8B\u4EF6 (episode) \u6A94\u6848\n\\ \\ \\ \\ -version : \u986F\u793A\u7248\u672C\u8CC7\u8A0A\n\\ \\ \\ \\ -fullversion : \u986F\u793A\u5B8C\u6574\u7248\u672C\u8CC7\u8A0A\n\\ \\ \\ \\ -help : \u986F\u793A\u6B64\u7528\u6CD5\u8A0A\u606F diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle.properties new file mode 100644 index 00000000000..d744da53d0d --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle.properties @@ -0,0 +1,33 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = \ + Directory "{0}" doesn't exist. + +UNRECOGNIZED_PARAMETER = \ + Unrecognized option {0} is not valid. + +OPERAND_MISSING = \ + Option "{0}" is missing an operand. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_de.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_de.properties new file mode 100644 index 00000000000..614b1664eaa --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_de.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = Verzeichnis "{0}" ist nicht vorhanden. + +UNRECOGNIZED_PARAMETER = Unbekannte Option {0} ist nicht g\u00FCltig. + +OPERAND_MISSING = In Option "{0}" fehlt ein Operand. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_es.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_es.properties new file mode 100644 index 00000000000..c32a9bd869f --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_es.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = El directorio "{0}" no existe. + +UNRECOGNIZED_PARAMETER = La opci\u00F3n no reconocida {0} no es v\u00E1lida. + +OPERAND_MISSING = A la opci\u00F3n "{0}" le falta un operando. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_fr.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_fr.properties new file mode 100644 index 00000000000..c7d0bf184bd --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_fr.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = Le r\u00E9pertoire "{0}" n''existe pas. + +UNRECOGNIZED_PARAMETER = L''option {0} non reconnue n''est pas valide. + +OPERAND_MISSING = Un op\u00E9rande est manquant dans l''option "{0}". diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_it.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_it.properties new file mode 100644 index 00000000000..7e78899f47d --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_it.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = La directory "{0}" non esiste. + +UNRECOGNIZED_PARAMETER = L''opzione non riconosciuta {0} non \u00E8 valida. + +OPERAND_MISSING = Operando mancante nell''opzione "{0}". diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ja.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ja.properties new file mode 100644 index 00000000000..490f37151ba --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ja.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA"{0}"\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002 + +UNRECOGNIZED_PARAMETER = \u8A8D\u8B58\u3055\u308C\u306A\u3044\u30AA\u30D7\u30B7\u30E7\u30F3{0}\u306F\u7121\u52B9\u3067\u3059\u3002 + +OPERAND_MISSING = \u30AA\u30D7\u30B7\u30E7\u30F3"{0}"\u306B\u30AA\u30DA\u30E9\u30F3\u30C9\u304C\u3042\u308A\u307E\u305B\u3093\u3002 diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ko.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ko.properties new file mode 100644 index 00000000000..5a22607fbe7 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ko.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = "{0}" \uB514\uB809\uD1A0\uB9AC\uAC00 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. + +UNRECOGNIZED_PARAMETER = \uC778\uC2DD\uD560 \uC218 \uC5C6\uB294 \uC635\uC158 {0}\uC740(\uB294) \uBD80\uC801\uD569\uD569\uB2C8\uB2E4. + +OPERAND_MISSING = "{0}" \uC635\uC158\uC5D0 \uD53C\uC5F0\uC0B0\uC790\uAC00 \uB204\uB77D\uB418\uC5C8\uC2B5\uB2C8\uB2E4. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_pt_BR.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_pt_BR.properties new file mode 100644 index 00000000000..f6d654fe950 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_pt_BR.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = O diret\u00F3rio "{0}" n\u00E3o existe. + +UNRECOGNIZED_PARAMETER = A op\u00E7\u00E3o {0} n\u00E3o reconhecida \u00E9 inv\u00E1lida. + +OPERAND_MISSING = A op\u00E7\u00E3o "{0}" n\u00E3o encontrou um operando. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_CN.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_CN.properties new file mode 100644 index 00000000000..1300088afde --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_CN.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = \u76EE\u5F55 "{0}" \u4E0D\u5B58\u5728\u3002 + +UNRECOGNIZED_PARAMETER = \u65E0\u6CD5\u8BC6\u522B\u7684\u9009\u9879{0}, \u8BE5\u9009\u9879\u65E0\u6548\u3002 + +OPERAND_MISSING = \u9009\u9879 "{0}" \u7F3A\u5C11\u64CD\u4F5C\u6570\u3002 diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_TW.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_TW.properties new file mode 100644 index 00000000000..042c9816897 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_TW.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, 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. +# + +NON_EXISTENT_FILE = \u76EE\u9304 "{0}" \u4E0D\u5B58\u5728. + +UNRECOGNIZED_PARAMETER = \u7121\u6CD5\u8FA8\u8B58\u7684\u9078\u9805 {0} \u7121\u6548. + +OPERAND_MISSING = \u9078\u9805 "{0}" \u907A\u6F0F\u904B\u7B97\u5143. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java index 396d88dc187..bc803684776 100644 --- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -68,7 +68,6 @@ public final class CTypeRef implements TypeRef { public CTypeRef(CNonElement type, XSElementDecl decl) { this(type, BGMBuilder.getName(decl),getSimpleTypeName(decl), decl.isNillable(), decl.getDefaultValue() ); - } public QName getTypeName() { @@ -100,10 +99,15 @@ public final class CTypeRef implements TypeRef { */ private static QName resolveSimpleTypeName(XSType declType) { QName name = BGMBuilder.getName(declType); - if (name != null && !XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(name.getNamespaceURI())) - return resolveSimpleTypeName(declType.getBaseType()); - else - return name; + QName result = null; + if (name != null && !XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(name.getNamespaceURI())) { + result = resolveSimpleTypeName(declType.getBaseType()); + } else { + if ( !"anySimpleType".equals(declType.getName()) ) { + result = name; + } + } + return result; } public CTypeRef(CNonElement type, QName elementName, QName typeName, boolean nillable, XmlString defaultValue) { diff --git a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties index 462e4882799..8d2adcadac9 100644 --- a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties +++ b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, 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 @@ -26,4 +26,4 @@ build-id=2.3.0-SNAPSHOT build-version=JAX-WS RI 2.3.0-SNAPSHOT major-version=2.3.0 -svn-revision=ffaa49e66cc05e1bb2ddc103076a340dad5df997 +svn-revision=282759e2b822078de9ba78c743ed663541c16ead From a1b61d28278f48e2ad0b8072e4ce04ea41df5a25 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Tue, 1 Mar 2016 20:06:47 +0300 Subject: [PATCH 169/311] 8150933: System::arraycopy intrinsic doesn't mark mismatched loads Reviewed-by: kvn, shade --- hotspot/src/share/vm/opto/macroArrayCopy.cpp | 10 ++++++++-- hotspot/src/share/vm/opto/memnode.cpp | 9 ++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/opto/macroArrayCopy.cpp b/hotspot/src/share/vm/opto/macroArrayCopy.cpp index 82816b2462b..17065895bff 100644 --- a/hotspot/src/share/vm/opto/macroArrayCopy.cpp +++ b/hotspot/src/share/vm/opto/macroArrayCopy.cpp @@ -880,8 +880,14 @@ bool PhaseMacroExpand::generate_block_arraycopy(Node** ctrl, MergeMemNode** mem, Node* sptr = basic_plus_adr(src, src_off); Node* dptr = basic_plus_adr(dest, dest_off); uint alias_idx = C->get_alias_index(adr_type); - Node* sval = transform_later(LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), sptr, adr_type, TypeInt::INT, T_INT, MemNode::unordered)); - Node* st = transform_later(StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), dptr, adr_type, sval, T_INT, MemNode::unordered)); + bool is_mismatched = (basic_elem_type != T_INT); + Node* sval = transform_later( + LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), sptr, adr_type, + TypeInt::INT, T_INT, MemNode::unordered, LoadNode::DependsOnlyOnTest, + false /*unaligned*/, is_mismatched)); + Node* st = transform_later( + StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), dptr, adr_type, + sval, T_INT, MemNode::unordered)); (*mem)->set_memory_at(alias_idx, st); src_off += BytesPerInt; dest_off += BytesPerInt; diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 2d2b40d334e..51733c8fa65 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -1582,7 +1582,6 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls, return NULL; } -#ifdef ASSERT static bool is_mismatched_access(ciConstant con, BasicType loadbt) { BasicType conbt = con.basic_type(); switch (conbt) { @@ -1597,7 +1596,6 @@ static bool is_mismatched_access(ciConstant con, BasicType loadbt) { } return (conbt != loadbt); } -#endif // ASSERT // Try to constant-fold a stable array element. static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) { @@ -1608,10 +1606,11 @@ static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicTyp ciArray* aobj = ary->const_oop()->as_array(); ciConstant con = aobj->element_value_by_offset(off); if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) { - assert(!is_mismatched_access(con, loadbt), - "conbt=%s; loadbt=%s", type2name(con.basic_type()), type2name(loadbt)); + bool is_mismatched = is_mismatched_access(con, loadbt); + assert(!is_mismatched, "conbt=%s; loadbt=%s", type2name(con.basic_type()), type2name(loadbt)); const Type* con_type = Type::make_from_constant(con); - if (con_type != NULL) { + // Guard against erroneous constant folding. + if (!is_mismatched && con_type != NULL) { if (con_type->isa_aryptr()) { // Join with the array element type, in case it is also stable. int dim = ary->stable_dimension(); From fbca99beb2de1e73e3ce26c60170293e98071060 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Tue, 1 Mar 2016 12:35:21 -0800 Subject: [PATCH 170/311] 8134119: Use new API to get cache line sizes Using new sysconf and sysinfo API on Solaris 12, avoid using libpicl and libkstat. Reviewed-by: kvn --- hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp | 34 ++++ hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp | 2 +- .../vm/vm_version_solaris_sparc.cpp | 162 ++++++++++++------ 3 files changed, 140 insertions(+), 58 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 9a6679d17ab..34041ed9943 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -463,3 +463,37 @@ unsigned int VM_Version::calc_parallel_worker_threads() { } return result; } + + +int VM_Version::parse_features(const char* implementation) { + int features = unknown_m; + // Convert to UPPER case before compare. + char* impl = os::strdup_check_oom(implementation); + + for (int i = 0; impl[i] != 0; i++) + impl[i] = (char)toupper((uint)impl[i]); + + if (strstr(impl, "SPARC64") != NULL) { + features |= sparc64_family_m; + } else if (strstr(impl, "SPARC-M") != NULL) { + // M-series SPARC is based on T-series. + features |= (M_family_m | T_family_m); + } else if (strstr(impl, "SPARC-T") != NULL) { + features |= T_family_m; + if (strstr(impl, "SPARC-T1") != NULL) { + features |= T1_model_m; + } + } else { + if (strstr(impl, "SPARC") == NULL) { +#ifndef PRODUCT + // kstat on Solaris 8 virtual machines (branded zones) + // returns "(unsupported)" implementation. Solaris 8 is not + // supported anymore, but include this check to be on the + // safe side. + warning("Can't parse CPU implementation = '%s', assume generic SPARC", impl); +#endif + } + } + os::free((void*)impl); + return features; +} diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp index 0609fa8b9a0..f2c5955905e 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp @@ -121,7 +121,7 @@ protected: static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); } static int maximum_niagara1_processor_count() { return 32; } - + static int parse_features(const char* implementation); public: // Initialization static void initialize(); diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index 971fa84fc64..837607e6781 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -264,6 +264,7 @@ void PICL::close_library() { // We need to keep these here as long as we have to build on Solaris // versions before 10. + #ifndef SI_ARCHITECTURE_32 #define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */ #endif @@ -272,36 +273,87 @@ void PICL::close_library() { #define SI_ARCHITECTURE_64 517 /* basic 64-bit SI_ARCHITECTURE */ #endif -static void do_sysinfo(int si, const char* string, int* features, int mask) { - char tmp; - size_t bufsize = sysinfo(si, &tmp, 1); +#ifndef SI_CPUBRAND +#define SI_CPUBRAND 523 /* return cpu brand string */ +#endif - // All SI defines used below must be supported. - guarantee(bufsize != -1, "must be supported"); +class Sysinfo { + char* _string; +public: + Sysinfo(int si) : _string(NULL) { + char tmp; + size_t bufsize = sysinfo(si, &tmp, 1); - char* buf = (char*) os::malloc(bufsize, mtInternal); - - if (buf == NULL) - return; - - if (sysinfo(si, buf, bufsize) == bufsize) { - // Compare the string. - if (strcmp(buf, string) == 0) { - *features |= mask; + if (bufsize != -1) { + char* buf = (char*) os::malloc(bufsize, mtInternal); + if (buf != NULL) { + if (sysinfo(si, buf, bufsize) == bufsize) { + _string = buf; + } else { + os::free(buf); + } + } } } - os::free(buf); -} + ~Sysinfo() { + if (_string != NULL) { + os::free(_string); + } + } + + const char* value() const { + return _string; + } + + bool valid() const { + return _string != NULL; + } + + bool match(const char* s) const { + return valid() ? strcmp(_string, s) == 0 : false; + } + + bool match_substring(const char* s) const { + return valid() ? strstr(_string, s) != NULL : false; + } +}; + +class Sysconf { + int _value; +public: + Sysconf(int sc) : _value(-1) { + _value = sysconf(sc); + } + bool valid() const { + return _value != -1; + } + int value() const { + return _value; + } +}; + + +#ifndef _SC_DCACHE_LINESZ +#define _SC_DCACHE_LINESZ 508 /* Data cache line size */ +#endif + +#ifndef _SC_L2CACHE_LINESZ +#define _SC_L2CACHE_LINESZ 527 /* Size of L2 cache line */ +#endif int VM_Version::platform_features(int features) { assert(os::Solaris::supports_getisax(), "getisax() must be available"); // Check 32-bit architecture. - do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m); + if (Sysinfo(SI_ARCHITECTURE_32).match("sparc")) { + features |= v8_instructions_m; + } // Check 64-bit architecture. - do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m); + if (Sysinfo(SI_ARCHITECTURE_64).match("sparcv9")) { + features |= generic_v9_m; + } // Extract valid instruction set extensions. uint_t avs[2]; @@ -388,67 +440,63 @@ int VM_Version::platform_features(int features) { if (av & AV_SPARC_SHA512) features |= sha512_instruction_m; // Determine the machine type. - do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m); + if (Sysinfo(SI_MACHINE).match("sun4v")) { + features |= sun4v_m; + } - { - // Using kstat to determine the machine type. + bool use_solaris_12_api = false; + Sysinfo impl(SI_CPUBRAND); + if (impl.valid()) { + // If SI_CPUBRAND works, that means Solaris 12 API to get the cache line sizes + // is available to us as well + use_solaris_12_api = true; + features |= parse_features(impl.value()); + } else { + // Otherwise use kstat to determine the machine type. kstat_ctl_t* kc = kstat_open(); kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL); - const char* implementation = "UNKNOWN"; + const char* implementation; + bool has_implementation = false; if (ksp != NULL) { if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) { kstat_named_t* knm = (kstat_named_t *)ksp->ks_data; for (int i = 0; i < ksp->ks_ndata; i++) { if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { implementation = KSTAT_NAMED_STR_PTR(&knm[i]); + has_implementation = true; #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print_cr("cpu_info.implementation: %s", implementation); } #endif - // Convert to UPPER case before compare. - char* impl = os::strdup_check_oom(implementation); - - for (int i = 0; impl[i] != 0; i++) - impl[i] = (char)toupper((uint)impl[i]); - - if (strstr(impl, "SPARC64") != NULL) { - features |= sparc64_family_m; - } else if (strstr(impl, "SPARC-M") != NULL) { - // M-series SPARC is based on T-series. - features |= (M_family_m | T_family_m); - } else if (strstr(impl, "SPARC-T") != NULL) { - features |= T_family_m; - if (strstr(impl, "SPARC-T1") != NULL) { - features |= T1_model_m; - } - } else { - if (strstr(impl, "SPARC") == NULL) { -#ifndef PRODUCT - // kstat on Solaris 8 virtual machines (branded zones) - // returns "(unsupported)" implementation. Solaris 8 is not - // supported anymore, but include this check to be on the - // safe side. - warning("kstat cpu_info implementation = '%s', assume generic SPARC", impl); -#endif - implementation = "SPARC"; - } - } - os::free((void*)impl); + features |= parse_features(implementation); break; } } // for( } } - assert(strcmp(implementation, "UNKNOWN") != 0, - "unknown cpu info (changed kstat interface?)"); + assert(has_implementation, "unknown cpu info (changed kstat interface?)"); kstat_close(kc); } - // Figure out cache line sizes using PICL - PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0); - _L1_data_cache_line_size = picl.L1_data_cache_line_size(); - _L2_data_cache_line_size = picl.L2_data_cache_line_size(); + bool is_sun4v = (features & sun4v_m) != 0; + if (use_solaris_12_api && is_sun4v) { + // If Solaris 12 API is supported and it's sun4v use sysconf() to get the cache line sizes + Sysconf l1_dcache_line_size(_SC_DCACHE_LINESZ); + if (l1_dcache_line_size.valid()) { + _L1_data_cache_line_size = l1_dcache_line_size.value(); + } + Sysconf l2_dcache_line_size(_SC_L2CACHE_LINESZ); + if (l2_dcache_line_size.valid()) { + _L2_data_cache_line_size = l2_dcache_line_size.value(); + } + } else { + // Otherwise figure out the cache line sizes using PICL + bool is_fujitsu = (features & sparc64_family_m) != 0; + PICL picl(is_fujitsu, is_sun4v); + _L1_data_cache_line_size = picl.L1_data_cache_line_size(); + _L2_data_cache_line_size = picl.L2_data_cache_line_size(); + } return features; } From 0e44e963d234ef483085d4ca1eac0279f455a63c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 1 Mar 2016 23:46:09 +0100 Subject: [PATCH 171/311] 8143226: Minor updates to Event Based tracing Reviewed-by: jbachorik, egahlin --- hotspot/make/aix/makefiles/trace.make | 10 +- hotspot/make/bsd/makefiles/trace.make | 10 +- hotspot/make/linux/makefiles/trace.make | 10 +- hotspot/make/solaris/makefiles/trace.make | 8 +- hotspot/make/windows/makefiles/trace.make | 12 +- hotspot/src/share/vm/c1/c1_Compiler.cpp | 2 - hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 40 +---- hotspot/src/share/vm/c1/c1_LIRGenerator.hpp | 5 +- .../share/vm/classfile/classFileParser.cpp | 2 +- hotspot/src/share/vm/classfile/vmSymbols.cpp | 2 - .../src/share/vm/gc/shared/copyFailedInfo.hpp | 19 +- .../src/share/vm/gc/shared/gcTraceSend.cpp | 4 +- hotspot/src/share/vm/oops/arrayKlass.cpp | 2 +- hotspot/src/share/vm/oops/instanceKlass.hpp | 4 +- hotspot/src/share/vm/oops/klass.cpp | 4 +- hotspot/src/share/vm/oops/klass.hpp | 4 +- hotspot/src/share/vm/opto/c2compiler.cpp | 2 - hotspot/src/share/vm/opto/library_call.cpp | 55 +----- hotspot/src/share/vm/prims/jni.cpp | 5 +- hotspot/src/share/vm/runtime/java.cpp | 3 +- .../src/share/vm/runtime/objectMonitor.cpp | 17 +- hotspot/src/share/vm/runtime/thread.cpp | 13 +- hotspot/src/share/vm/runtime/thread.hpp | 5 +- hotspot/src/share/vm/runtime/vmThread.cpp | 4 +- hotspot/src/share/vm/trace/trace.xml | 19 +- hotspot/src/share/vm/trace/traceBackend.hpp | 6 +- hotspot/src/share/vm/trace/traceDataTypes.hpp | 41 ++--- hotspot/src/share/vm/trace/traceEvent.hpp | 9 +- .../src/share/vm/trace/traceEventClasses.xsl | 6 +- hotspot/src/share/vm/trace/traceEventIds.xsl | 2 +- hotspot/src/share/vm/trace/traceMacros.hpp | 21 ++- hotspot/src/share/vm/trace/tracetypes.xml | 168 ++++++++---------- hotspot/src/share/vm/utilities/debug.cpp | 13 ++ hotspot/src/share/vm/utilities/hashtable.cpp | 5 + 34 files changed, 211 insertions(+), 321 deletions(-) diff --git a/hotspot/make/aix/makefiles/trace.make b/hotspot/make/aix/makefiles/trace.make index c00b0e3383a..549acb21190 100644 --- a/hotspot/make/aix/makefiles/trace.make +++ b/hotspot/make/aix/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, 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 @@ -57,11 +57,6 @@ ifeq ($(HAS_ALT_SRC), true) TraceGeneratedNames += \ traceRequestables.hpp \ traceEventControl.hpp - -ifneq ($(INCLUDE_TRACE), false) -TraceGeneratedNames += traceProducer.cpp -endif - endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) @@ -100,9 +95,6 @@ else $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/bsd/makefiles/trace.make b/hotspot/make/bsd/makefiles/trace.make index c7ef3d8ea01..88f17a7326e 100644 --- a/hotspot/make/bsd/makefiles/trace.make +++ b/hotspot/make/bsd/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, 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 @@ -57,11 +57,6 @@ ifeq ($(HAS_ALT_SRC), true) TraceGeneratedNames += \ traceRequestables.hpp \ traceEventControl.hpp - -ifneq ($(INCLUDE_TRACE), false) -TraceGeneratedNames += traceProducer.cpp -endif - endif @@ -101,9 +96,6 @@ else $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/linux/makefiles/trace.make b/hotspot/make/linux/makefiles/trace.make index 7218adc27b3..229b68c434b 100644 --- a/hotspot/make/linux/makefiles/trace.make +++ b/hotspot/make/linux/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, 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 @@ -57,11 +57,6 @@ ifeq ($(HAS_ALT_SRC), true) TraceGeneratedNames += \ traceRequestables.hpp \ traceEventControl.hpp - -ifneq ($(INCLUDE_TRACE), false) -TraceGeneratedNames += traceProducer.cpp -endif - endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) @@ -100,9 +95,6 @@ else $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/solaris/makefiles/trace.make b/hotspot/make/solaris/makefiles/trace.make index ab96c7ffd65..09979558ea7 100644 --- a/hotspot/make/solaris/makefiles/trace.make +++ b/hotspot/make/solaris/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, 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 @@ -56,8 +56,7 @@ TraceGeneratedNames = \ ifeq ($(HAS_ALT_SRC), true) TraceGeneratedNames += \ traceRequestables.hpp \ - traceEventControl.hpp \ - traceProducer.cpp + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) @@ -96,9 +95,6 @@ else $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/windows/makefiles/trace.make b/hotspot/make/windows/makefiles/trace.make index 58fee24653c..b32646e3310 100644 --- a/hotspot/make/windows/makefiles/trace.make +++ b/hotspot/make/windows/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, 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 @@ -43,8 +43,7 @@ TraceGeneratedNames = \ !if EXISTS($(TraceAltSrcDir)) TraceGeneratedNames = $(TraceGeneratedNames) \ traceRequestables.hpp \ - traceEventControl.hpp \ - traceProducer.cpp + traceEventControl.hpp !endif @@ -58,8 +57,7 @@ TraceGeneratedFiles = \ !if EXISTS($(TraceAltSrcDir)) TraceGeneratedFiles = $(TraceGeneratedFiles) \ $(TraceOutDir)/traceRequestables.hpp \ - $(TraceOutDir)/traceEventControl.hpp \ - $(TraceOutDir)/traceProducer.cpp + $(TraceOutDir)/traceEventControl.hpp !endif XSLT = $(QUIETLY) $(REMOTE) $(RUN_JAVA) -classpath $(JvmtiOutDir) jvmtiGen @@ -98,10 +96,6 @@ $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir) @echo Generating AltSrc $@ @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceEventClasses.xsl -OUT $(TraceOutDir)/traceEventClasses.hpp -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - @echo Generating AltSrc $@ - @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceProducer.xsl -OUT $(TraceOutDir)/traceProducer.cpp - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) @echo Generating AltSrc $@ @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceRequestables.xsl -OUT $(TraceOutDir)/traceRequestables.hpp diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp index 5dbe6c209f3..78d71b89444 100644 --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp @@ -228,8 +228,6 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_getCharStringU: case vmIntrinsics::_putCharStringU: #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - case vmIntrinsics::_threadID: case vmIntrinsics::_counterTime: #endif break; diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 30ae8f86e9f..a3a2ce52f42 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -43,6 +43,9 @@ #if INCLUDE_ALL_GCS #include "gc/g1/heapRegion.hpp" #endif // INCLUDE_ALL_GCS +#ifdef TRACE_HAVE_INTRINSICS +#include "trace/traceMacros.hpp" +#endif #ifdef ASSERT #define __ gen()->lir(__FILE__, __LINE__)-> @@ -3067,42 +3070,7 @@ void LIRGenerator::do_RuntimeCall(address routine, Intrinsic* x) { __ move(reg, result); } -#ifdef TRACE_HAVE_INTRINSICS -void LIRGenerator::do_ThreadIDIntrinsic(Intrinsic* x) { - LIR_Opr thread = getThreadPointer(); - LIR_Opr osthread = new_pointer_register(); - __ move(new LIR_Address(thread, in_bytes(JavaThread::osthread_offset()), osthread->type()), osthread); - size_t thread_id_size = OSThread::thread_id_size(); - if (thread_id_size == (size_t) BytesPerLong) { - LIR_Opr id = new_register(T_LONG); - __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_LONG), id); - __ convert(Bytecodes::_l2i, id, rlock_result(x)); - } else if (thread_id_size == (size_t) BytesPerInt) { - __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_INT), rlock_result(x)); - } else { - ShouldNotReachHere(); - } -} -void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) { - CodeEmitInfo* info = state_for(x); - CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check - BasicType klass_pointer_type = NOT_LP64(T_INT) LP64_ONLY(T_LONG); - assert(info != NULL, "must have info"); - LIRItem arg(x->argument_at(1), this); - arg.load_item(); - LIR_Opr klass = new_pointer_register(); - __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), klass_pointer_type), klass, info); - LIR_Opr id = new_register(T_LONG); - ByteSize offset = TRACE_ID_OFFSET; - LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG); - __ move(trace_id_addr, id); - __ logical_or(id, LIR_OprFact::longConst(0x01l), id); - __ store(id, trace_id_addr); - __ logical_and(id, LIR_OprFact::longConst(~0x3l), id); - __ move(id, rlock_result(x)); -} -#endif void LIRGenerator::do_Intrinsic(Intrinsic* x) { switch (x->id()) { @@ -3115,8 +3083,6 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { } #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_threadID: do_ThreadIDIntrinsic(x); break; - case vmIntrinsics::_classID: do_ClassIDIntrinsic(x); break; case vmIntrinsics::_counterTime: do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), x); break; diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index 9438d77288c..4f459dbd1a0 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -440,10 +440,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux); void do_RuntimeCall(address routine, Intrinsic* x); -#ifdef TRACE_HAVE_INTRINSICS - void do_ThreadIDIntrinsic(Intrinsic* x); - void do_ClassIDIntrinsic(Intrinsic* x); -#endif + ciKlass* profile_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k, ciKlass* callee_signature_k); diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index a75504d2025..97d6bdfcd56 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -5380,7 +5380,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) { } } - TRACE_INIT_ID(ik); + TRACE_INIT_KLASS_ID(ik); // If we reach here, all is well. // Now remove the InstanceKlass* from the _klass_to_deallocate field diff --git a/hotspot/src/share/vm/classfile/vmSymbols.cpp b/hotspot/src/share/vm/classfile/vmSymbols.cpp index 81dda6e4fd0..287db197252 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp @@ -328,8 +328,6 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); switch(id) { #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - case vmIntrinsics::_threadID: case vmIntrinsics::_counterTime: #endif case vmIntrinsics::_currentTimeMillis: diff --git a/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp b/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp index 6a6a64e31eb..b7e0bbe98b0 100644 --- a/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp +++ b/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -26,6 +26,7 @@ #define SHARE_VM_GC_SHARED_COPYFAILEDINFO_HPP #include "runtime/thread.hpp" +#include "trace/traceMacros.hpp" #include "utilities/globalDefinitions.hpp" class CopyFailedInfo : public CHeapObj { @@ -63,26 +64,28 @@ class CopyFailedInfo : public CHeapObj { }; class PromotionFailedInfo : public CopyFailedInfo { - OSThread* _thread; + traceid _thread_trace_id; public: - PromotionFailedInfo() : CopyFailedInfo(), _thread(NULL) {} + PromotionFailedInfo() : CopyFailedInfo(), _thread_trace_id(0) {} void register_copy_failure(size_t size) { CopyFailedInfo::register_copy_failure(size); - if (_thread == NULL) { - _thread = Thread::current()->osthread(); + if (_thread_trace_id == 0) { + _thread_trace_id = THREAD_TRACE_ID(Thread::current()); } else { - assert(_thread == Thread::current()->osthread(), "The PromotionFailedInfo should be thread local."); + assert(THREAD_TRACE_ID(Thread::current()) == _thread_trace_id, + "The PromotionFailedInfo should be thread local."); } } void reset() { CopyFailedInfo::reset(); - _thread = NULL; + _thread_trace_id = 0; } - OSThread* thread() const { return _thread; } + traceid thread_trace_id() const { return _thread_trace_id; } + }; class EvacuationFailedInfo : public CopyFailedInfo {}; diff --git a/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp b/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp index 0bd6fef7471..db538eb4f41 100644 --- a/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp +++ b/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -174,7 +174,7 @@ void YoungGCTracer::send_promotion_failed_event(const PromotionFailedInfo& pf_in if (e.should_commit()) { e.set_gcId(GCId::current()); e.set_data(to_trace_struct(pf_info)); - e.set_thread(pf_info.thread()->thread_id()); + e.set_thread(pf_info.thread_trace_id()); e.commit(); } } diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index e92df43076f..2278ce92471 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -89,7 +89,7 @@ ArrayKlass::ArrayKlass(Symbol* name) : set_super(Universe::is_bootstrapping() ? (Klass*)NULL : SystemDictionary::Object_klass()); set_layout_helper(Klass::_lh_neutral_value); set_is_cloneable(); // All arrays are considered to be cloneable (See JLS 20.1.5) - TRACE_INIT_ID(this); + TRACE_INIT_KLASS_ID(this); } diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index f7a3a24800f..7e5d8360596 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -839,7 +839,7 @@ public: // support for stub routines static ByteSize init_state_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_state)); } - TRACE_DEFINE_OFFSET; + TRACE_DEFINE_KLASS_TRACE_ID_OFFSET; static ByteSize init_thread_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_thread)); } // subclass/subinterface checks diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index b391f222d6a..3cedd3470f0 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -494,7 +494,7 @@ void Klass::remove_unshareable_info() { } void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { - TRACE_INIT_ID(this); + TRACE_INIT_KLASS_ID(this); // If an exception happened during CDS restore, some of these fields may already be // set. We leave the class on the CLD list, even if incomplete so that we don't // modify the CLD list outside a safepoint. diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 00fe28d614b..cff1d74d6ef 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -132,7 +132,7 @@ class Klass : public Metadata { jint _modifier_flags; // Processed access flags, for use by Class.getModifiers. AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. - TRACE_DEFINE_KLASS_TRACE_ID; + TRACE_DEFINE_TRACE_ID_FIELD; // Biased locking implementation and statistics // (the 64-bit chunk goes first, to avoid some fragmentation) @@ -569,7 +569,7 @@ protected: jlong last_biased_lock_bulk_revocation_time() { return _last_biased_lock_bulk_revocation_time; } void set_last_biased_lock_bulk_revocation_time(jlong cur_time) { _last_biased_lock_bulk_revocation_time = cur_time; } - TRACE_DEFINE_KLASS_METHODS; + TRACE_DEFINE_TRACE_ID_METHODS; // garbage collection support void oops_do(OopClosure* cl); diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index 7068b5cfb1a..bc08a298dc6 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -400,8 +400,6 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt case vmIntrinsics::_currentThread: case vmIntrinsics::_isInterrupted: #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - case vmIntrinsics::_threadID: case vmIntrinsics::_counterTime: #endif case vmIntrinsics::_currentTimeMillis: diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 753612c206f..f9942825e23 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -49,7 +49,9 @@ #include "opto/subnode.hpp" #include "prims/nativeLookup.hpp" #include "runtime/sharedRuntime.hpp" +#ifdef TRACE_HAVE_INTRINSICS #include "trace/traceMacros.hpp" +#endif class LibraryIntrinsic : public InlineCallGenerator { // Extend the set of intrinsics known to the runtime: @@ -246,10 +248,7 @@ class LibraryCallKit : public GraphKit { bool inline_unsafe_allocate(); bool inline_unsafe_copyMemory(); bool inline_native_currentThread(); -#ifdef TRACE_HAVE_INTRINSICS - bool inline_native_classID(); - bool inline_native_threadID(); -#endif + bool inline_native_time_funcs(address method, const char* funcName); bool inline_native_isInterrupted(); bool inline_native_Class_query(vmIntrinsics::ID id); @@ -642,8 +641,6 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_isInterrupted: return inline_native_isInterrupted(); #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: return inline_native_classID(); - case vmIntrinsics::_threadID: return inline_native_threadID(); case vmIntrinsics::_counterTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime"); #endif case vmIntrinsics::_currentTimeMillis: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis"); @@ -2932,52 +2929,6 @@ bool LibraryCallKit::inline_unsafe_allocate() { return true; } -#ifdef TRACE_HAVE_INTRINSICS -/* - * oop -> myklass - * myklass->trace_id |= USED - * return myklass->trace_id & ~0x3 - */ -bool LibraryCallKit::inline_native_classID() { - null_check_receiver(); // null-check, then ignore - Node* cls = null_check(argument(1), T_OBJECT); - Node* kls = load_klass_from_mirror(cls, false, NULL, 0); - kls = null_check(kls, T_OBJECT); - ByteSize offset = TRACE_ID_OFFSET; - Node* insp = basic_plus_adr(kls, in_bytes(offset)); - Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG, MemNode::unordered); - Node* bits = longcon(~0x03l); // ignore bit 0 & 1 - Node* andl = _gvn.transform(new AndLNode(tvalue, bits)); - Node* clsused = longcon(0x01l); // set the class bit - Node* orl = _gvn.transform(new OrLNode(tvalue, clsused)); - - const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); - store_to_memory(control(), insp, orl, T_LONG, adr_type, MemNode::unordered); - set_result(andl); - return true; -} - -bool LibraryCallKit::inline_native_threadID() { - Node* tls_ptr = NULL; - Node* cur_thr = generate_current_thread(tls_ptr); - Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); - Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered); - p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset())); - - Node* threadid = NULL; - size_t thread_id_size = OSThread::thread_id_size(); - if (thread_id_size == (size_t) BytesPerLong) { - threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG, MemNode::unordered)); - } else if (thread_id_size == (size_t) BytesPerInt) { - threadid = make_load(control(), p, TypeInt::INT, T_INT, MemNode::unordered); - } else { - ShouldNotReachHere(); - } - set_result(threadid); - return true; -} -#endif - //------------------------inline_native_time_funcs-------------- // inline code for System.currentTimeMillis() and System.nanoTime() // these have the same type and signature diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 419963ef412..ffca3342ebd 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -73,6 +73,7 @@ #include "runtime/vm_operations.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" +#include "trace/traceMacros.hpp" #include "trace/tracing.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" @@ -3929,7 +3930,7 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) { EventThreadStart event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.set_thread(THREAD_TRACE_ID(thread)); event.commit(); } @@ -4149,7 +4150,7 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae EventThreadStart event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.set_thread(THREAD_TRACE_ID(thread)); event.commit(); } diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index 84235d8803f..a30acc9a9bd 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -64,6 +64,7 @@ #include "runtime/timer.hpp" #include "runtime/vm_operations.hpp" #include "services/memTracker.hpp" +#include "trace/traceMacros.hpp" #include "trace/tracing.hpp" #include "utilities/dtrace.hpp" #include "utilities/globalDefinitions.hpp" @@ -485,7 +486,7 @@ void before_exit(JavaThread* thread) { EventThreadEnd event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.set_thread(THREAD_TRACE_ID(thread)); event.commit(); } diff --git a/hotspot/src/share/vm/runtime/objectMonitor.cpp b/hotspot/src/share/vm/runtime/objectMonitor.cpp index 2f7937d4f3e..6258d64ad2f 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -401,7 +401,7 @@ void NOINLINE ObjectMonitor::enter(TRAPS) { if (event.should_commit()) { event.set_klass(((oop)this->object())->klass()); - event.set_previousOwner((TYPE_JAVALANGTHREAD)_previous_owner_tid); + event.set_previousOwner((TYPE_THREAD)_previous_owner_tid); event.set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr())); event.commit(); } @@ -937,7 +937,7 @@ void NOINLINE ObjectMonitor::exit(bool not_suspended, TRAPS) { // get the owner's thread id for the MonitorEnter event // if it is enabled and the thread isn't suspended if (not_suspended && Tracing::is_event_enabled(TraceJavaMonitorEnterEvent)) { - _previous_owner_tid = SharedRuntime::get_java_tid(Self); + _previous_owner_tid = THREAD_TRACE_ID(Self); } #endif @@ -1391,11 +1391,12 @@ void ObjectMonitor::post_monitor_wait_event(EventJavaMonitorWait* event, jlong notifier_tid, jlong timeout, bool timedout) { + assert(event != NULL, "invariant"); event->set_klass(((oop)this->object())->klass()); - event->set_timeout((TYPE_ULONG)timeout); - event->set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr())); - event->set_notifier((TYPE_OSTHREAD)notifier_tid); - event->set_timedOut((TYPE_BOOLEAN)timedout); + event->set_timeout(timeout); + event->set_address((TYPE_ADDRESS)this->object_addr()); + event->set_notifier(notifier_tid); + event->set_timedOut(timedout); event->commit(); } @@ -1655,7 +1656,7 @@ void ObjectMonitor::INotify(Thread * Self) { iterator->TState = ObjectWaiter::TS_ENTER; } iterator->_notified = 1; - iterator->_notifier_tid = Self->osthread()->thread_id(); + iterator->_notifier_tid = THREAD_TRACE_ID(Self); ObjectWaiter * list = _EntryList; if (list != NULL) { diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 8e1e997f8c1..a411b6868dc 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1694,7 +1694,7 @@ void JavaThread::run() { EventThreadStart event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj())); + event.set_thread(THREAD_TRACE_ID(this)); event.commit(); } @@ -1799,7 +1799,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { // from java_lang_Thread object EventThreadEnd event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj())); + event.set_thread(THREAD_TRACE_ID(this)); event.commit(); } @@ -3554,6 +3554,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { return status; } + if (TRACE_INITIALIZE() != JNI_OK) { + vm_exit_during_initialization("Failed to initialize tracing backend"); + } + // Should be done after the heap is fully created main_thread->cache_global_variables(); @@ -3622,11 +3626,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { quicken_jni_functions(); - // Must be run after init_ft which initializes ft_enabled - if (TRACE_INITIALIZE() != JNI_OK) { - vm_exit_during_initialization("Failed to initialize tracing backend"); - } - // No more stub generation allowed after that point. StubCodeDesc::freeze(); diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 4d94026e313..eed983d3841 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -448,7 +448,8 @@ class Thread: public ThreadShadow { void incr_allocated_bytes(jlong size) { _allocated_bytes += size; } inline jlong cooked_allocated_bytes(); - TRACE_DATA* trace_data() { return &_trace_data; } + TRACE_DEFINE_THREAD_TRACE_DATA_OFFSET; + TRACE_DATA* trace_data() const { return &_trace_data; } const ThreadExt& ext() const { return _ext; } ThreadExt& ext() { return _ext; } diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index 77935603075..f4584b1fc9b 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -359,7 +359,7 @@ void VMThread::evaluate_operation(VM_Operation* op) { // Only write caller thread information for non-concurrent vm operations. // For concurrent vm operations, the thread id is set to 0 indicating thread is unknown. // This is because the caller thread could have exited already. - event.set_caller(is_concurrent ? 0 : op->calling_thread()->osthread()->thread_id()); + event.set_caller(is_concurrent ? 0 : THREAD_TRACE_ID(op->calling_thread())); event.commit(); } diff --git a/hotspot/src/share/vm/trace/trace.xml b/hotspot/src/share/vm/trace/trace.xml index 7e357f4c106..d6d76d9398f 100644 --- a/hotspot/src/share/vm/trace/trace.xml +++ b/hotspot/src/share/vm/trace/trace.xml @@ -1,6 +1,6 @@ - + diff --git a/hotspot/src/share/vm/trace/traceBackend.hpp b/hotspot/src/share/vm/trace/traceBackend.hpp index c65d89e41d8..36635321ad6 100644 --- a/hotspot/src/share/vm/trace/traceBackend.hpp +++ b/hotspot/src/share/vm/trace/traceBackend.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -47,6 +47,10 @@ public: static void on_unloading_classes(void) { } + + static void on_vm_error(bool) { + } + }; class TraceThreadData { diff --git a/hotspot/src/share/vm/trace/traceDataTypes.hpp b/hotspot/src/share/vm/trace/traceDataTypes.hpp index 31004d934b5..b51343d9575 100644 --- a/hotspot/src/share/vm/trace/traceDataTypes.hpp +++ b/hotspot/src/share/vm/trace/traceDataTypes.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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,39 +31,32 @@ enum { CONTENT_TYPE_NONE = 0, - CONTENT_TYPE_BYTES = 1, - CONTENT_TYPE_EPOCHMILLIS = 2, - CONTENT_TYPE_MILLIS = 3, - CONTENT_TYPE_NANOS = 4, - CONTENT_TYPE_TICKS = 5, - CONTENT_TYPE_ADDRESS = 6, + CONTENT_TYPE_CLASS = 20, + CONTENT_TYPE_UTF8 = 21, + CONTENT_TYPE_THREAD = 22, + CONTENT_TYPE_STACKTRACE = 23, + CONTENT_TYPE_BYTES = 24, + CONTENT_TYPE_EPOCHMILLIS = 25, + CONTENT_TYPE_MILLIS = 26, + CONTENT_TYPE_NANOS = 27, + CONTENT_TYPE_TICKS = 28, + CONTENT_TYPE_ADDRESS = 29, + CONTENT_TYPE_PERCENTAGE = 30, - CONTENT_TYPE_OSTHREAD, - CONTENT_TYPE_JAVALANGTHREAD, - CONTENT_TYPE_STACKTRACE, - CONTENT_TYPE_CLASS, - CONTENT_TYPE_PERCENTAGE, - - JVM_CONTENT_TYPES_START = 30, - JVM_CONTENT_TYPES_END = 100 + JVM_CONTENT_TYPES_START = 33, + JVM_CONTENT_TYPES_END = 255 }; enum ReservedEvent { - EVENT_PRODUCERS, + EVENT_METADATA, EVENT_CHECKPOINT, EVENT_BUFFERLOST, - NUM_RESERVED_EVENTS + NUM_RESERVED_EVENTS = JVM_CONTENT_TYPES_END }; typedef enum ReservedEvent ReservedEvent; -typedef u8 classid; -typedef u8 stacktraceid; -typedef u8 methodid; -typedef u8 fieldid; - -class TraceUnicodeString; +class Symbol; #endif // SHARE_VM_TRACE_TRACEDATATYPES_HPP - diff --git a/hotspot/src/share/vm/trace/traceEvent.hpp b/hotspot/src/share/vm/trace/traceEvent.hpp index a0548d76513..f56ea19f716 100644 --- a/hotspot/src/share/vm/trace/traceEvent.hpp +++ b/hotspot/src/share/vm/trace/traceEvent.hpp @@ -99,8 +99,13 @@ class TraceEvent : public StackObj { cancel(); return; } - if (_endTime == 0) { - static_cast(this)->set_endtime(Tracing::time()); + + if (_startTime == 0) { + static_cast(this)->set_starttime(Tracing::time()); + } else { + if (_endTime == 0) { + static_cast(this)->set_endtime(Tracing::time()); + } } if (static_cast(this)->should_write()) { static_cast(this)->writeEvent(); diff --git a/hotspot/src/share/vm/trace/traceEventClasses.xsl b/hotspot/src/share/vm/trace/traceEventClasses.xsl index 41d3a446a9e..16b30c7b909 100644 --- a/hotspot/src/share/vm/trace/traceEventClasses.xsl +++ b/hotspot/src/share/vm/trace/traceEventClasses.xsl @@ -1,6 +1,6 @@ - + - + - - + - - - + type="const char*" sizeop="sizeof_utf(%)"/> + type="const Symbol*" sizeop="sizeof(u8)"/> + type="const Klass*" sizeop="sizeof(u8)"/> + type="const Method*" sizeop="sizeof(u8)"/> - - - - - - - - + + - + sizeop="sizeof(u8)"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp index 8d6a9398764..f0aa8371f17 100644 --- a/hotspot/src/share/vm/utilities/debug.cpp +++ b/hotspot/src/share/vm/utilities/debug.cpp @@ -51,9 +51,14 @@ #include "services/heapDumper.hpp" #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" #include "utilities/vmError.hpp" +#if INCLUDE_TRACE +#include "trace/tracing.hpp" +#endif + #ifndef ASSERT # ifdef _DEBUG // NOTE: don't turn the lines below into a comment -- if you're getting @@ -280,6 +285,12 @@ void report_out_of_shared_space(SharedSpaceType shared_space) { exit(2); } +static void notify_tracing() { +#if INCLUDE_TRACE + Tracing::on_vm_error(true); +#endif +} + void report_insufficient_metaspace(size_t required_size) { warning("\nThe MaxMetaspaceSize of " SIZE_FORMAT " bytes is not large enough.\n" "Either don't specify the -XX:MaxMetaspaceSize=\n" @@ -302,6 +313,8 @@ void report_java_out_of_memory(const char* message) { HeapDumper::dump_heap_from_oome(); } + notify_tracing(); + if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { VMError::report_java_out_of_memory(message); } diff --git a/hotspot/src/share/vm/utilities/hashtable.cpp b/hotspot/src/share/vm/utilities/hashtable.cpp index 10f4456274a..8af6156ed45 100644 --- a/hotspot/src/share/vm/utilities/hashtable.cpp +++ b/hotspot/src/share/vm/utilities/hashtable.cpp @@ -383,4 +383,9 @@ template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; +#if INCLUDE_TRACE +template class Hashtable; +template class HashtableEntry; +template class BasicHashtable; +#endif template class BasicHashtable; From 1593edaf5947e841a2e162553bebb749dca9faf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 1 Mar 2016 23:47:30 +0100 Subject: [PATCH 172/311] 8066814: Reduce accessibility in TraceEvent Reviewed-by: egahlin, jbachorik --- hotspot/src/share/vm/trace/traceEvent.hpp | 76 ++++++++++++----------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/hotspot/src/share/vm/trace/traceEvent.hpp b/hotspot/src/share/vm/trace/traceEvent.hpp index f56ea19f716..3a083c402ce 100644 --- a/hotspot/src/share/vm/trace/traceEvent.hpp +++ b/hotspot/src/share/vm/trace/traceEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -62,7 +62,6 @@ class TraceEvent : public StackObj { _endTime = time; } - public: TraceEvent(EventStartTime timing=TIMED) : _startTime(0), _endTime(0), @@ -76,12 +75,21 @@ class TraceEvent : public StackObj { { if (T::is_enabled()) { _started = true; - if (timing == TIMED && !T::isInstant) { - static_cast(this)->set_starttime(Tracing::time()); + if (TIMED == timing && !T::isInstant) { + static_cast(this)->set_starttime(Tracing::time()); } } } + public: + void set_starttime(const Ticks& time) { + _startTime = time.value(); + } + + void set_endtime(const Ticks& time) { + _endTime = time.value(); + } + static bool is_enabled() { return Tracing::is_event_enabled(T::eventId); } @@ -90,72 +98,68 @@ class TraceEvent : public StackObj { return _started; } - void ignoreCheck() { - DEBUG_ONLY(_ignore_check = true); - } - void commit() { if (!should_commit()) { - cancel(); - return; + DEBUG_ONLY(cancel()); + return; } - + assert(!_cancelled, "Committing an event that has already been cancelled"); if (_startTime == 0) { static_cast(this)->set_starttime(Tracing::time()); - } else { - if (_endTime == 0) { - static_cast(this)->set_endtime(Tracing::time()); - } + } else if (_endTime == 0) { + static_cast(this)->set_endtime(Tracing::time()); } if (static_cast(this)->should_write()) { static_cast(this)->writeEvent(); } - set_commited(); + DEBUG_ONLY(set_commited()); } - void set_starttime(const Ticks& time) { - _startTime = time.value(); - } - - void set_endtime(const Ticks& time) { - _endTime = time.value(); - } - - TraceEventId id() const { + static TraceEventId id() { return T::eventId; } - bool is_instant() const { + static bool is_instant() { return T::isInstant; } - bool is_requestable() const { + static bool is_requestable() { return T::isRequestable; } - bool has_thread() const { + static bool has_thread() { return T::hasThread; } - bool has_stacktrace() const { + static bool has_stacktrace() { return T::hasStackTrace; } void cancel() { - assert(!_committed && !_cancelled, "event was already committed/cancelled"); + assert(!_committed && !_cancelled, + "event was already committed/cancelled"); DEBUG_ONLY(_cancelled = true); } - void set_commited() { - assert(!_committed, "event has already been committed"); - DEBUG_ONLY(_committed = true); - } - ~TraceEvent() { if (_started) { - assert(_ignore_check || _committed || _cancelled, "event was not committed/cancelled"); + assert(_ignore_check || _committed || _cancelled, + "event was not committed/cancelled"); } } + +#ifdef ASSERT + protected: + void ignoreCheck() { + _ignore_check = true; + } + + private: + void set_commited() { + assert(!_committed, "event has already been committed"); + _committed = true; + } +#endif // ASSERT }; #endif // INCLUDE_TRACE From 64f55fb26703749d8d07063a347c3a2d773323fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 1 Mar 2016 23:48:46 +0100 Subject: [PATCH 173/311] 8147442: Event-based tracing to allow for tracing Klass creation Reviewed-by: jbachorik, egahlin --- hotspot/src/share/vm/classfile/klassFactory.cpp | 5 ++++- hotspot/src/share/vm/trace/traceMacros.hpp | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/classfile/klassFactory.cpp b/hotspot/src/share/vm/classfile/klassFactory.cpp index 14af5574021..033d9bfb660 100644 --- a/hotspot/src/share/vm/classfile/klassFactory.cpp +++ b/hotspot/src/share/vm/classfile/klassFactory.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2015, 2016, 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 @@ -29,6 +29,7 @@ #include "classfile/klassFactory.hpp" #include "memory/resourceArea.hpp" #include "prims/jvmtiEnvBase.hpp" +#include "trace/traceMacros.hpp" static ClassFileStream* prologue(ClassFileStream* stream, Symbol* name, @@ -136,5 +137,7 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream, result->set_cached_class_file(cached_class_file); } + TRACE_KLASS_CREATION(result, parser, THREAD); + return result; } diff --git a/hotspot/src/share/vm/trace/traceMacros.hpp b/hotspot/src/share/vm/trace/traceMacros.hpp index ee9be4a8967..c67024ae3f0 100644 --- a/hotspot/src/share/vm/trace/traceMacros.hpp +++ b/hotspot/src/share/vm/trace/traceMacros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -29,6 +29,7 @@ typedef u8 traceid; #define EVENT_THREAD_EXIT(thread) #define EVENT_THREAD_DESTRUCT(thread) +#define TRACE_KLASS_CREATION(k, p, t) #define TRACE_INIT_KLASS_ID(k) #define TRACE_INIT_THREAD_ID(td) From 85ee898a02cff9cec1d4636ba198085db1694d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 1 Mar 2016 23:54:05 +0100 Subject: [PATCH 174/311] 8143235: Remove libjfr mapfile Reviewed-by: jbachorik, egahlin --- jdk/make/mapfiles/libjfr/mapfile-vers | 45 ------------------- .../classes/build/tools/module/boot.modules | 1 + 2 files changed, 1 insertion(+), 45 deletions(-) delete mode 100644 jdk/make/mapfiles/libjfr/mapfile-vers diff --git a/jdk/make/mapfiles/libjfr/mapfile-vers b/jdk/make/mapfiles/libjfr/mapfile-vers deleted file mode 100644 index 0bb2cbcb8bc..00000000000 --- a/jdk/make/mapfiles/libjfr/mapfile-vers +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. -# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. -# - -# Define library interface. - -SUNWprivate_1.1 { - global: - Java_oracle_jrockit_jfr_Process_getpid; - Java_oracle_jrockit_jfr_Timing_counterTime; - Java_oracle_jrockit_jfr_Timing_init; - Java_oracle_jrockit_jfr_Logger_output0; - Java_oracle_jrockit_jfr_JFR_isCommercialFeaturesUnlocked; - Java_oracle_jrockit_jfr_JFR_isStarted; - Java_oracle_jrockit_jfr_JFR_isSupportedInVM; - Java_oracle_jrockit_jfr_JFR_startFlightRecorder; - Java_oracle_jrockit_jfr_JFR_isDisabledOnCommandLine; - Java_oracle_jrockit_jfr_JFR_isEnabled; - Java_oracle_jrockit_jfr_VMJFR_options; - Java_oracle_jrockit_jfr_VMJFR_init; - Java_oracle_jrockit_jfr_VMJFR_addConstPool; - Java_oracle_jrockit_jfr_VMJFR_removeConstPool; - Java_oracle_jrockit_jfr_VMJFR_storeConstPool; - Java_oracle_jrockit_jfr_VMJFR_classID0; - Java_oracle_jrockit_jfr_VMJFR_stackTraceID; - Java_oracle_jrockit_jfr_VMJFR_threadID; - Java_oracle_jrockit_jfr_VMJFR_rotate; - Java_oracle_jrockit_jfr_VMJFR_shutdown; - Java_oracle_jrockit_jfr_VMJFR_start; - Java_oracle_jrockit_jfr_VMJFR_stop; - Java_oracle_jrockit_jfr_VMJFR_buffer; - Java_oracle_jrockit_jfr_VMJFR_flush; - Java_oracle_jrockit_jfr_VMJFR_write; - Java_oracle_jrockit_jfr_VMJFR_add; - Java_oracle_jrockit_jfr_VMJFR_remove; - Java_oracle_jrockit_jfr_VMJFR_setThreshold; - Java_oracle_jrockit_jfr_VMJFR_setPeriod; - Java_oracle_jrockit_jfr_VMJFR_getPeriod; - Java_oracle_jrockit_jfr_VMJFR_descriptors; - Java_oracle_jrockit_jfr_VMJFR_retransformClasses0; - JNI_OnLoad; - local: - *; -}; diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index a22b4af52b9..5bac3ea896c 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -27,6 +27,7 @@ jdk.vm.cds jdk.vm.ci jdk.management jdk.management.cmm +jdk.management.jfr jdk.management.resource jdk.naming.rmi jdk.sctp From 75b02a64c682529204a11bfa3f252cc43e5732c6 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Wed, 2 Mar 2016 08:41:02 +0100 Subject: [PATCH 175/311] 8058944: Unify the reporting strings for the GC debug level logging in G1 Reviewed-by: sjohanss, tschatzl --- hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp | 4 ++-- hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index 5ece63cea5d..33e001122ae 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -1097,7 +1097,7 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { reset_marking_state(); } else { { - GCTraceTime(Debug, gc) trace("GC Aggregate Data", g1h->gc_timer_cm()); + GCTraceTime(Debug, gc) trace("Aggregate Data", g1h->gc_timer_cm()); // Aggregate the per-task counting data that we have accumulated // while marking. @@ -2018,7 +2018,7 @@ void G1ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { // Inner scope to exclude the cleaning of the string and symbol // tables from the displayed time. { - GCTraceTime(Debug, gc) trace("GC Ref Proc", g1h->gc_timer_cm()); + GCTraceTime(Debug, gc) trace("Reference Processing", g1h->gc_timer_cm()); ReferenceProcessor* rp = g1h->ref_processor_cm(); diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index b5dce4ffc3d..9ab25e6a73f 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -277,8 +277,8 @@ void G1GCPhaseTimes::print() { } debug_line("Choose CSet", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); debug_line("Preserve CM Refs", _recorded_preserve_cm_referents_time_ms); - debug_line("Ref Proc", _cur_ref_proc_time_ms); - debug_line("Ref Enq", _cur_ref_enq_time_ms); + debug_line("Reference Processing", _cur_ref_proc_time_ms); + debug_line("Reference Enqueuing", _cur_ref_enq_time_ms); debug_line("Redirty Cards", _recorded_redirty_logged_cards_time_ms); trace_phase(_gc_par_phases[RedirtyCards]); trace_phase(_gc_par_phases[PreserveCMReferents]); From ff51364bf687223eeae1a74ac9635bdfe49f396b Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 2 Mar 2016 12:29:17 +0300 Subject: [PATCH 176/311] 8151017: [TESTBUG] test/compiler/c1/CanonicalizeArrayLength does not work on product builds Reviewed-by: thartmann, zmajo --- hotspot/test/compiler/c1/CanonicalizeArrayLength.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hotspot/test/compiler/c1/CanonicalizeArrayLength.java b/hotspot/test/compiler/c1/CanonicalizeArrayLength.java index 9971d25bde8..ee2649a3b3a 100644 --- a/hotspot/test/compiler/c1/CanonicalizeArrayLength.java +++ b/hotspot/test/compiler/c1/CanonicalizeArrayLength.java @@ -25,10 +25,10 @@ * @test * @bug 8150102 8150514 8150534 * @summary C1 crashes in Canonicalizer::do_ArrayLength() after fix for JDK-8150102 - * @run main/othervm -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation CanonicalizeArrayLength - * @run main/othervm -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:+PatchALot CanonicalizeArrayLength - * @run main/othervm -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=0 CanonicalizeArrayLength - * @run main/othervm -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=1 CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:+PatchALot CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=0 CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=1 CanonicalizeArrayLength */ public class CanonicalizeArrayLength { int[] arr = new int[42]; From 3059ef621c6d6f486337d543e57aad7465c48e06 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 2 Mar 2016 11:14:35 +0100 Subject: [PATCH 177/311] 8148820: Missing @since Javadoc tag in Logger.log(Level, Supplier) Added @since 1.8 Reviewed-by: lancea, rriggs --- jdk/src/java.logging/share/classes/java/util/logging/Logger.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java index 3cc00d0e630..48210efeaf6 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java @@ -839,6 +839,7 @@ public class Logger { * @param level One of the message level identifiers, e.g., SEVERE * @param msgSupplier A function, which when called, produces the * desired log message + * @since 1.8 */ public void log(Level level, Supplier msgSupplier) { if (!isLoggable(level)) { From 2c101cfb09564a6e0df7fd1210881e0b53e7b737 Mon Sep 17 00:00:00 2001 From: Ivan Gerasimov Date: Wed, 2 Mar 2016 14:10:40 +0300 Subject: [PATCH 178/311] 8149330: Capacity of StringBuilder should not get close to Integer.MAX_VALUE unless necessary Reviewed-by: martin --- .../java/lang/AbstractStringBuilder.java | 71 ++++--- .../java/lang/StringBuilder/Capacity.java | 182 ++++++++++++++++++ .../java/lang/StringBuilder/HugeCapacity.java | 66 +++++++ 3 files changed, 295 insertions(+), 24 deletions(-) create mode 100644 jdk/test/java/lang/StringBuilder/Capacity.java create mode 100644 jdk/test/java/lang/StringBuilder/HugeCapacity.java diff --git a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index f1691969666..2aa9ff36a7f 100644 --- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -133,39 +133,62 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { } /** - * This method has the same contract as ensureCapacity, but is - * never synchronized. + * For positive values of {@code minimumCapacity}, this method + * behaves like {@code ensureCapacity}, however it is never + * synchronized. + * If {@code minimumCapacity} is non positive due to numeric + * overflow, this method throws {@code OutOfMemoryError}. */ private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code - int capacity = value.length >> coder; - if (minimumCapacity - capacity > 0) { - expandCapacity(minimumCapacity); + int oldCapacity = value.length >> coder; + if (minimumCapacity - oldCapacity > 0) { + value = Arrays.copyOf(value, + newCapacity(minimumCapacity) << coder); } } /** - * This implements the expansion semantics of ensureCapacity with no - * size check or synchronization. + * The maximum size of array to allocate (unless necessary). + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit */ - private void expandCapacity(int minimumCapacity) { - int newCapacity = (value.length >> coder) * 2 + 2; - if (newCapacity - minimumCapacity < 0) { - newCapacity = minimumCapacity; + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + /** + * Returns a capacity at least as large as the given minimum capacity. + * Returns the current capacity increased by the same amount + 2 if + * that suffices. + * Will not return a capacity greater than + * {@code (MAX_ARRAY_SIZE >> coder)} unless the given minimum capacity + * is greater than that. + * + * @param minCapacity the desired minimum capacity + * @throws OutOfMemoryError if minCapacity is less than zero or + * greater than (Integer.MAX_VALUE >> coder) + */ + private int newCapacity(int minCapacity) { + // overflow-conscious code + int oldCapacity = value.length >> coder; + int newCapacity = (oldCapacity << 1) + 2; + if (newCapacity - minCapacity < 0) { + newCapacity = minCapacity; } - if (newCapacity < 0) { - if (minimumCapacity < 0) {// overflow - throw new OutOfMemoryError(); - } - newCapacity = Integer.MAX_VALUE; + int SAFE_BOUND = MAX_ARRAY_SIZE >> coder; + return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0) + ? hugeCapacity(minCapacity) + : newCapacity; + } + + private int hugeCapacity(int minCapacity) { + int SAFE_BOUND = MAX_ARRAY_SIZE >> coder; + int UNSAFE_BOUND = Integer.MAX_VALUE >> coder; + if (UNSAFE_BOUND - minCapacity < 0) { // overflow + throw new OutOfMemoryError(); } - if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) { - if (minimumCapacity >= StringUTF16.MAX_LENGTH) { - throw new OutOfMemoryError(); - } - newCapacity = StringUTF16.MAX_LENGTH; - } - this.value = Arrays.copyOf(value, newCapacity << coder); + return (minCapacity > SAFE_BOUND) + ? minCapacity : SAFE_BOUND; } /** diff --git a/jdk/test/java/lang/StringBuilder/Capacity.java b/jdk/test/java/lang/StringBuilder/Capacity.java new file mode 100644 index 00000000000..e23e9151b46 --- /dev/null +++ b/jdk/test/java/lang/StringBuilder/Capacity.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2016, 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 8149330 + * @summary Basic set of tests of capacity management + * @run testng Capacity + */ + +import java.lang.reflect.Field; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SplittableRandom; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.*; + +public class Capacity { + static final int DEFAULT_CAPACITY = 16; + + private static int newCapacity(int oldCapacity, + int desiredCapacity) + { + return Math.max(oldCapacity * 2 + 2, desiredCapacity); + } + + private static int nextNewCapacity(int oldCapacity) { + return newCapacity(oldCapacity, oldCapacity + 1); + } + + @Test(dataProvider = "singleChar") + public void defaultCapacity(Character ch) { + StringBuilder sb = new StringBuilder(); + assertEquals(sb.capacity(), DEFAULT_CAPACITY); + for (int i = 0; i < DEFAULT_CAPACITY; i++) { + sb.append(ch); + assertEquals(sb.capacity(), DEFAULT_CAPACITY); + } + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(DEFAULT_CAPACITY)); + } + + @Test(dataProvider = "charCapacity") + public void explicitCapacity(Character ch, int initCapacity) { + StringBuilder sb = new StringBuilder(initCapacity); + assertEquals(sb.capacity(), initCapacity); + for (int i = 0; i < initCapacity; i++) { + sb.append(ch); + assertEquals(sb.capacity(), initCapacity); + } + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(initCapacity)); + } + + @Test(dataProvider = "singleChar") + public void sbFromString(Character ch) { + String s = "string " + ch; + int expectedCapacity = s.length() + DEFAULT_CAPACITY; + StringBuilder sb = new StringBuilder(s); + assertEquals(sb.capacity(), expectedCapacity); + for (int i = 0; i < DEFAULT_CAPACITY; i++) { + sb.append(ch); + assertEquals(sb.capacity(), expectedCapacity); + } + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(expectedCapacity)); + } + + @Test(dataProvider = "singleChar") + public void sbFromCharSeq(Character ch) { + CharSequence cs = new MyCharSeq("char seq " + ch); + int expectedCapacity = cs.length() + DEFAULT_CAPACITY; + StringBuilder sb = new StringBuilder(cs); + assertEquals(sb.capacity(), expectedCapacity); + for (int i = 0; i < DEFAULT_CAPACITY; i++) { + sb.append(ch); + assertEquals(sb.capacity(), expectedCapacity); + } + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(expectedCapacity)); + } + + @Test(dataProvider = "charCapacity") + public void ensureCapacity(Character ch, int cap) { + StringBuilder sb = new StringBuilder(0); + assertEquals(sb.capacity(), 0); + sb.ensureCapacity(cap); // only has effect if cap > 0 + int newCap = (cap == 0) ? 0 : newCapacity(0, cap); + assertEquals(sb.capacity(), newCap); + sb.ensureCapacity(newCap + 1); + assertEquals(sb.capacity(), nextNewCapacity(newCap)); + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(newCap)); + } + + @Test(dataProvider = "negativeCapacity", + expectedExceptions = NegativeArraySizeException.class) + public void negativeInitialCapacity(int negCap) { + StringBuilder sb = new StringBuilder(negCap); + } + + @Test(dataProvider = "negativeCapacity") + public void ensureNegativeCapacity(int negCap) { + StringBuilder sb = new StringBuilder(); + sb.ensureCapacity(negCap); + assertEquals(sb.capacity(), DEFAULT_CAPACITY); + } + + @Test(dataProvider = "charCapacity") + public void trimToSize(Character ch, int cap) { + StringBuilder sb = new StringBuilder(cap); + int halfOfCap = cap / 2; + for (int i = 0; i < halfOfCap; i++) { + sb.append(ch); + } + sb.trimToSize(); + // according to the spec, capacity doesn't have to + // become exactly the size + assertTrue(sb.capacity() >= halfOfCap); + } + + @DataProvider + public Object[][] singleChar() { + return new Object[][] { {'J'}, {'\u042b'} }; + } + + @DataProvider + public Object[][] charCapacity() { + return new Object[][] { + {'J', 0}, + {'J', 1}, + {'J', 15}, + {'J', DEFAULT_CAPACITY}, + {'J', 1024}, + {'\u042b', 0}, + {'\u042b', 1}, + {'\u042b', 15}, + {'\u042b', DEFAULT_CAPACITY}, + {'\u042b', 1024}, + }; + } + + @DataProvider + public Object[][] negativeCapacity() { + return new Object[][] { {-1}, {Integer.MIN_VALUE} }; + } + + private static class MyCharSeq implements CharSequence { + private CharSequence s; + public MyCharSeq(CharSequence s) { this.s = s; } + public char charAt(int i) { return s.charAt(i); } + public int length() { return s.length(); } + public CharSequence subSequence(int st, int e) { + return s.subSequence(st, e); + } + public String toString() { return s.toString(); } + } +} diff --git a/jdk/test/java/lang/StringBuilder/HugeCapacity.java b/jdk/test/java/lang/StringBuilder/HugeCapacity.java new file mode 100644 index 00000000000..912a2539e96 --- /dev/null +++ b/jdk/test/java/lang/StringBuilder/HugeCapacity.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016, 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 8149330 + * @summary Capacity should not get close to Integer.MAX_VALUE unless + * necessary + * @run main/othervm -Xmx5G HugeCapacity + * @ignore This test has huge memory requirements + */ + +public class HugeCapacity { + private static int failures = 0; + + public static void main(String[] args) { + testLatin1(); + testUtf16(); + if (failures > 0) { + throw new RuntimeException(failures + " tests failed"); + } + } + + private static void testLatin1() { + try { + StringBuilder sb = new StringBuilder(); + sb.ensureCapacity(Integer.MAX_VALUE / 2); + sb.ensureCapacity(Integer.MAX_VALUE / 2 + 1); + } catch (OutOfMemoryError oom) { + oom.printStackTrace(); + failures++; + } + } + + private static void testUtf16() { + try { + StringBuilder sb = new StringBuilder(); + sb.append('\u042b'); + sb.ensureCapacity(Integer.MAX_VALUE / 4); + sb.ensureCapacity(Integer.MAX_VALUE / 4 + 1); + } catch (OutOfMemoryError oom) { + oom.printStackTrace(); + failures++; + } + } +} From b1bb5651a35db0051bd7ec8c69c2bccb19383420 Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Wed, 2 Mar 2016 12:54:56 +0100 Subject: [PATCH 179/311] 8150941: Sjavac should not wait for portfile to materialize if server process is terminated Sjavac cancels forking early if server process dies. Reviewed-by: jlahoda --- .../classes/com/sun/tools/sjavac/client/SjavacClient.java | 2 +- .../share/classes/com/sun/tools/sjavac/server/PortFile.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java index b9b039354d4..4e309210d1f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java @@ -257,7 +257,7 @@ public class SjavacClient implements Sjavac { // serverProcess != null at this point. try { // Throws an IOException if no valid values materialize - portFile.waitForValidValues(); + portFile.waitForValidValues(serverProcess); } catch (IOException ex) { // Process was started, but server failed to initialize. This could // for instance be due to the JVM not finding the server class, diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java index 3bbdca22c4e..a4cda8383d5 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java @@ -232,7 +232,7 @@ public class PortFile { /** * Wait for the port file to contain values that look valid. */ - public void waitForValidValues() throws IOException, InterruptedException { + public void waitForValidValues(Process serverProcess) throws IOException, InterruptedException { final int MS_BETWEEN_ATTEMPTS = 500; long startTime = System.currentTimeMillis(); long timeout = startTime + getServerStartupTimeoutSeconds() * 1000; @@ -250,6 +250,9 @@ public class PortFile { if (System.currentTimeMillis() > timeout) { break; } + if (!serverProcess.isAlive()) { + throw new IOException("Server process terminated."); + } Thread.sleep(MS_BETWEEN_ATTEMPTS); } throw new IOException("No port file values materialized. Giving up after " + From c685f3567fe0790c0533a921c7984487fff788db Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Wed, 2 Mar 2016 13:12:24 +0100 Subject: [PATCH 180/311] 8061320: Sjavac should prevent using source dir as dest dir Sjavac now makes sure that src and dst dirs do not overlap. Reviewed-by: jlahoda --- .../com/sun/tools/sjavac/comp/SjavacImpl.java | 21 +++- .../test/tools/sjavac/OverlappingSrcDst.java | 102 ++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/sjavac/OverlappingSrcDst.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java index a8ccd32356c..b1b77150364 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java @@ -28,7 +28,6 @@ package com.sun.tools.sjavac.comp; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; -import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -81,6 +80,10 @@ public class SjavacImpl implements Sjavac { if (!validateOptions(options)) return RC_FATAL; + if (srcDstOverlap(options.getSources(), options.getDestDir())) { + return RC_FATAL; + } + if (!createIfMissing(options.getDestDir())) return RC_FATAL; @@ -330,6 +333,22 @@ public class SjavacImpl implements Sjavac { } + private static boolean srcDstOverlap(List locs, Path dest) { + for (SourceLocation loc : locs) { + if (isOverlapping(loc.getPath(), dest)) { + Log.error("Source location " + loc.getPath() + " overlaps with destination " + dest); + return true; + } + } + return false; + } + + private static boolean isOverlapping(Path p1, Path p2) { + p1 = p1.toAbsolutePath().normalize(); + p2 = p2.toAbsolutePath().normalize(); + return p1.startsWith(p2) || p2.startsWith(p1); + } + private static boolean createIfMissing(Path dir) { if (Files.isDirectory(dir)) diff --git a/langtools/test/tools/sjavac/OverlappingSrcDst.java b/langtools/test/tools/sjavac/OverlappingSrcDst.java new file mode 100644 index 00000000000..516fb118dd1 --- /dev/null +++ b/langtools/test/tools/sjavac/OverlappingSrcDst.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, 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. + */ + +/* + * @test + * @summary Make sure sjavac doesn't allow overlapping source and destination + * directories. + * @bug 8061320 + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.file + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.sjavac + * @build Wrapper ToolBox + * @run main Wrapper OverlappingSrcDst + */ + +import java.io.File; +import java.nio.file.Paths; + +public class OverlappingSrcDst extends SJavacTester { + public static void main(String... args) { + new OverlappingSrcDst().run(); + } + + public void run() { + String abs = ToolBox.currDir.toAbsolutePath().toString(); + + // Relative vs relative + test("dir", "dir", false); + test("dir", "dir/dst", false); + test("dir/src", "dir", false); + test("src", "dst", true); + + // Absolute vs absolute + test(abs + "/dir", abs + "/dir", false); + test(abs + "/dir", abs + "/dir/dst", false); + test(abs + "/dir/src", abs + "/dir", false); + test(abs + "/src", abs + "/dst", true); + + // Absolute vs relative + test(abs + "/dir", "dir", false); + test(abs + "/dir", "dir/dst", false); + test(abs + "/dir/src", "dir", false); + test(abs + "/src", "dst", true); + + // Relative vs absolute + test("dir", abs + "/dir", false); + test("dir", abs + "/dir/dst", false); + test("dir/src", abs + "/dir", false); + test("src", abs + "/dst", true); + } + + private void test(String srcDir, String dstDir, boolean shouldSucceed) { + boolean succeeded = testCompilation(srcDir, dstDir); + if (shouldSucceed != succeeded) { + throw new AssertionError( + String.format("Test failed for " + + "srcDir=\"%s\", " + + "dstDir=\"%s\". " + + "Compilation was expected to %s but %s.", + srcDir, + dstDir, + shouldSucceed ? "succeed" : "fail", + succeeded ? "succeeded" : "failed")); + } + } + + private boolean testCompilation(String srcDir, String dstDir) { + try { + srcDir = srcDir.replace('/', File.separatorChar); + dstDir = dstDir.replace('/', File.separatorChar); + tb.writeFile(Paths.get(srcDir, "pkg", "A.java"), "package pkg; class A {}"); + compile("--state-dir=state", "-src", srcDir, "-d", dstDir); + return true; + } catch (Exception e) { + return false; + } + } +} From 68ce6b3b9f3a3f1cb848225e90ca0840d4f350ba Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Wed, 2 Mar 2016 15:42:03 +0300 Subject: [PATCH 181/311] 8151020: [TESTBUG] UnsafeGetStableArrayElement::testL_* fail intermittently Reviewed-by: zmajo, shade --- .../unsafe/UnsafeGetStableArrayElement.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java index 0cf5f44dc85..e103d46454e 100644 --- a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java +++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java @@ -182,6 +182,10 @@ public class UnsafeGetStableArrayElement { static long testJ_U() { return U.getLongUnaligned( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET + 1); } } + static void run(Callable c) throws Exception { + run(c, null, null); + } + static void run(Callable c, Runnable sameResultAction, Runnable changeResultAction) throws Exception { Object first = c.call(); @@ -295,13 +299,7 @@ public class UnsafeGetStableArrayElement { testMatched( Test::testD_D, Test::changeD); // Object[], aligned accesses - testMismatched(Test::testL_Z, Test::changeL); - testMismatched(Test::testL_B, Test::changeL); - testMismatched(Test::testL_S, Test::changeL); - testMismatched(Test::testL_C, Test::changeL); - testMismatched(Test::testL_I, Test::changeL); - testMismatched(Test::testL_J, Test::changeL); - testMismatched(Test::testL_F, Test::changeL); + testMismatched(Test::testL_J, Test::changeL); // long & double are always as large as an OOP testMismatched(Test::testL_D, Test::changeL); testMatched( Test::testL_L, Test::changeL); @@ -310,5 +308,17 @@ public class UnsafeGetStableArrayElement { testMismatched(Test::testC_U, Test::changeC); testMismatched(Test::testI_U, Test::changeI); testMismatched(Test::testJ_U, Test::changeJ); + + // No way to reliably check the expected behavior: + // (1) OOPs change during GC; + // (2) there's no way to reliably change some part of an OOP (e.g., when reading a byte from it). + // + // Just trigger the compilation hoping to catch any problems with asserts. + run(Test::testL_B); + run(Test::testL_Z); + run(Test::testL_S); + run(Test::testL_C); + run(Test::testL_I); + run(Test::testL_F); } } From fc2641e57f4d9fee5c0bd59cf15e764d54ba71a2 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Wed, 2 Mar 2016 14:15:15 +0100 Subject: [PATCH 182/311] 8150953: j.l.i.MethodHandles: example section in whileLoop(...) provides example for doWhileLoop Reviewed-by: psandoz --- .../java.base/share/classes/java/lang/invoke/MethodHandles.java | 2 +- jdk/test/java/lang/invoke/JavaDocExamplesTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index c35e3af28ab..2c01f376f71 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -3528,7 +3528,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * return zip; * } * // assume MH_initZip, MH_zipPred, and MH_zipStep are handles to the above methods - * MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred); + * MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep); * List a = Arrays.asList("a", "b", "c", "d"); * List b = Arrays.asList("e", "f", "g", "h"); * List zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h"); diff --git a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java index 9a4b3f3624b..79a31087550 100644 --- a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java +++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java @@ -690,7 +690,7 @@ assertEquals(120, loop.invoke(5)); {{ {} /// JAVADOC // implement the zip function for lists as a loop handle -MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred); +MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep); List a = Arrays.asList("a", "b", "c", "d"); List b = Arrays.asList("e", "f", "g", "h"); List zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h"); From c12efa10b20de92c490bc72b166390b9936a21b2 Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Wed, 2 Mar 2016 19:09:38 +0530 Subject: [PATCH 183/311] 8151016: Migrate asserts introduced in Valhalla code generation to JDK9 dev Reviewed-by: mcimadamore --- .../classes/com/sun/tools/javac/jvm/Gen.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index 6280b8d5cf4..b551b61e8d9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -80,6 +80,11 @@ public class Gen extends JCTree.Visitor { */ private final Type methodType; + /** + * Are we presently traversing a let expression ? Yes if depth != 0 + */ + private int letExprDepth; + public static Gen instance(Context context) { Gen instance = context.get(genKey); if (instance == null) @@ -1006,8 +1011,10 @@ public class Gen extends JCTree.Visitor { if (tree.init != null) { checkStringConstant(tree.init.pos(), v.getConstValue()); if (v.getConstValue() == null || varDebugInfo) { + Assert.check(letExprDepth != 0 || code.state.stacksize == 0); genExpr(tree.init, v.erasure(types)).load(); items.makeLocalItem(v).store(); + Assert.check(letExprDepth != 0 || code.state.stacksize == 0); } } checkDimension(tree.pos(), v.type); @@ -1062,12 +1069,14 @@ public class Gen extends JCTree.Visitor { CondItem c; if (cond != null) { code.statBegin(cond.pos); + Assert.check(code.state.stacksize == 0); c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER); } else { c = items.makeCondItem(goto_); } Chain loopDone = c.jumpFalse(); code.resolve(c.trueJumps); + Assert.check(code.state.stacksize == 0); genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET); code.resolve(loopEnv.info.cont); genStats(step, loopEnv); @@ -1080,11 +1089,13 @@ public class Gen extends JCTree.Visitor { CondItem c; if (cond != null) { code.statBegin(cond.pos); + Assert.check(code.state.stacksize == 0); c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER); } else { c = items.makeCondItem(goto_); } code.resolve(c.jumpTrue(), startpc); + Assert.check(code.state.stacksize == 0); code.resolve(c.falseJumps); } Chain exit = loopEnv.info.exit; @@ -1112,6 +1123,7 @@ public class Gen extends JCTree.Visitor { int limit = code.nextreg; Assert.check(!tree.selector.type.hasTag(CLASS)); int startpcCrt = genCrt ? code.curCP() : 0; + Assert.check(code.state.stacksize == 0); Item sel = genExpr(tree.selector, syms.intType); List cases = tree.cases; if (cases.isEmpty()) { @@ -1280,6 +1292,7 @@ public class Gen extends JCTree.Visitor { int limit = code.nextreg; // Generate code to evaluate lock and save in temporary variable. final LocalItem lockVar = makeTemp(syms.objectType); + Assert.check(code.state.stacksize == 0); genExpr(tree.lock, tree.lock.type).load().duplicate(); lockVar.store(); @@ -1526,9 +1539,11 @@ public class Gen extends JCTree.Visitor { public void visitIf(JCIf tree) { int limit = code.nextreg; Chain thenExit = null; + Assert.check(code.state.stacksize == 0); CondItem c = genCond(TreeInfo.skipParens(tree.cond), CRT_FLOW_CONTROLLER); Chain elseChain = c.jumpFalse(); + Assert.check(code.state.stacksize == 0); if (!c.isFalse()) { code.resolve(c.trueJumps); genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET); @@ -1542,6 +1557,7 @@ public class Gen extends JCTree.Visitor { } code.resolve(thenExit); code.endScopes(limit); + Assert.check(code.state.stacksize == 0); } public void visitExec(JCExpressionStatement tree) { @@ -1555,7 +1571,9 @@ public class Gen extends JCTree.Visitor { ((JCUnary) e).setTag(PREDEC); break; } + Assert.check(code.state.stacksize == 0); genExpr(tree.expr, tree.expr.type).drop(); + Assert.check(code.state.stacksize == 0); } public void visitBreak(JCBreak tree) { @@ -1581,6 +1599,7 @@ public class Gen extends JCTree.Visitor { */ int tmpPos = code.pendingStatPos; if (tree.expr != null) { + Assert.check(code.state.stacksize == 0); Item r = genExpr(tree.expr, pt).load(); if (hasFinally(env.enclMethod, env)) { r = makeTemp(pt); @@ -1600,8 +1619,10 @@ public class Gen extends JCTree.Visitor { } public void visitThrow(JCThrow tree) { + Assert.check(code.state.stacksize == 0); genExpr(tree.expr, tree.expr.type).load(); code.emitop0(athrow); + Assert.check(code.state.stacksize == 0); } /* ************************************************************************ @@ -2101,10 +2122,12 @@ public class Gen extends JCTree.Visitor { } public void visitLetExpr(LetExpr tree) { + letExprDepth++; int limit = code.nextreg; genStats(tree.defs, env); result = genExpr(tree.expr, tree.expr.type).load(); code.endScopes(limit); + letExprDepth--; } private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) { From 9035e8480580c46282773aa75e9d4ca0e39a89c5 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Wed, 2 Mar 2016 17:08:26 +0300 Subject: [PATCH 184/311] 8150318: serviceability/dcmd/jvmti/LoadAgentDcmdTest.java - Could not find JDK_DIR/lib/x86_64/libinstrument.so Refactor test Reviewed-by: jbachorik, sspitsyn --- .../dcmd/jvmti/LoadAgentDcmdTest.java | 76 +++++++++++------ .../dcmd/jvmti/LoadJavaAgentDcmdTest.java | 81 ------------------- .../testlibrary/jdk/test/lib/Platform.java | 29 ++++++- 3 files changed, 81 insertions(+), 105 deletions(-) delete mode 100644 hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java diff --git a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java index f0db464e46b..da7224583e0 100644 --- a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java +++ b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java @@ -22,6 +22,10 @@ */ import java.io.*; import java.nio.file.*; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; import jdk.test.lib.*; import jdk.test.lib.dcmd.*; import org.testng.annotations.Test; @@ -55,12 +59,7 @@ public class LoadAgentDcmdTest { "'-Dtest.jdk=/path/to/jdk'."); } - Path libpath; - if (Platform.isWindows()) { - libpath = Paths.get(jdkPath, "bin", "instrument.dll"); - } else { - libpath = Paths.get(jdkPath, "lib", Platform.getOsArch(), "libinstrument.so"); - } + Path libpath = Paths.get(jdkPath, Platform.jdkLibPath(), Platform.sharedObjectName("instrument")); if (!libpath.toFile().exists()) { throw new FileNotFoundException( @@ -70,31 +69,62 @@ public class LoadAgentDcmdTest { return libpath.toAbsolutePath().toString(); } + + public void createJarFileForAgent() + throws IOException { + + final String jarName = "agent.jar"; + final String agentClass = "SimpleJvmtiAgent"; + + Manifest manifest = new Manifest(); + + manifest.getMainAttributes().put( + Attributes.Name.MANIFEST_VERSION, "1.0"); + + manifest.getMainAttributes().put( + new Attributes.Name("Agent-Class"), agentClass); + + JarOutputStream target = null; + + try { + target = new + JarOutputStream(new FileOutputStream(jarName), manifest); + JarEntry entry = new JarEntry(agentClass + ".class"); + target.putNextEntry(entry); + target.closeEntry(); + } finally { + target.close(); + } + } + public void run(CommandExecutor executor) { try{ - PrintWriter pw = new PrintWriter("MANIFEST.MF"); - pw.println("Agent-Class: SimpleJvmtiAgent"); - pw.close(); - ProcessBuilder pb = new ProcessBuilder(); - pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), - "cmf", - "MANIFEST.MF", - "agent.jar", - "SimpleJvmtiAgent.class"}); - pb.start().waitFor(); + createJarFileForAgent(); String libpath = getLibInstrumentPath(); + OutputAnalyzer output = null; - // Test 1: No argument - OutputAnalyzer output = executor.execute("JVMTI.agent_load " + - libpath + " agent.jar"); - output.stderrShouldBeEmpty(); - - // Test 2: With argument + // Test 1: Native agent, no arguments output = executor.execute("JVMTI.agent_load " + - libpath + " \"agent.jar=foo=bar\""); + libpath + " agent.jar"); output.stderrShouldBeEmpty(); + + // Test 2: Native agent, with arguments + output = executor.execute("JVMTI.agent_load " + + libpath + " \"agent.jar=foo=bar\""); + output.stderrShouldBeEmpty(); + + // Test 3: Java agent, no arguments + output = executor.execute("JVMTI.agent_load " + + "agent.jar"); + output.stderrShouldBeEmpty(); + + // Test 4: Java agent, with arguments + output = executor.execute("JVMTI.agent_load " + + "\"agent.jar=foo=bar\""); + output.stderrShouldBeEmpty(); + } catch (Exception e) { throw new RuntimeException(e); } diff --git a/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java b/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java deleted file mode 100644 index 6c0c17760aa..00000000000 --- a/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2016, 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.*; -import jdk.test.lib.dcmd.*; -import org.testng.annotations.Test; - -/* - * Test to attach JVMTI java agent. - * - * @test - * @bug 8147388 - * @library /testlibrary - * @modules java.base/sun.misc - * java.compiler - * java.instrument - * java.management - * jdk.jvmstat/sun.jvmstat.monitor - * @build ClassFileInstaller jdk.test.lib.* SimpleJvmtiAgent - * @run main ClassFileInstaller SimpleJvmtiAgent - * @run testng LoadJavaAgentDcmdTest - */ -public class LoadJavaAgentDcmdTest { - public void run(CommandExecutor executor) { - try{ - PrintWriter pw = new PrintWriter("MANIFEST.MF"); - pw.println("Agent-Class: SimpleJvmtiAgent"); - pw.close(); - - ProcessBuilder pb = new ProcessBuilder(); - pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), - "cmf", - "MANIFEST.MF", - "agent.jar", - "SimpleJvmtiAgent.class"}); - pb.start().waitFor(); - - // Test 1: No argument - OutputAnalyzer output = executor.execute("JVMTI.agent_load " + - "agent.jar"); - output.stderrShouldBeEmpty(); - - // Test 2: With argument - output = executor.execute("JVMTI.agent_load " + - "\"agent.jar=foo=bar\""); - output.stderrShouldBeEmpty(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Test - public void jmx() throws Throwable { - run(new JMXExecutor()); - } - - @Test - public void cli() throws Throwable { - run(new PidJcmdExecutor()); - } -} diff --git a/hotspot/test/testlibrary/jdk/test/lib/Platform.java b/hotspot/test/testlibrary/jdk/test/lib/Platform.java index ecd6a0f64d5..64773223556 100644 --- a/hotspot/test/testlibrary/jdk/test/lib/Platform.java +++ b/hotspot/test/testlibrary/jdk/test/lib/Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -203,4 +203,31 @@ public class Platform { public static boolean canAttachOSX() throws Exception { return userName.equals("root"); } + + /** + * return path to library inside jdk tree + */ + public static String jdkLibPath() { + if (isWindows()) { + return "bin"; + } + if (isOSX()) { + return "lib"; + } + + return "lib/" + getOsArch(); + } + + /** + * Build name of shared object according to platform rules + */ + public static String sharedObjectName(String name) { + if (isWindows()) { + return name + ".dll"; + } + if (isOSX()) { + return "lib" + name + ".dylib"; + } + return "lib" + name + ".so"; + } } From a07ffdd31d077481ad060e86e45070f610dfd324 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 2 Mar 2016 15:55:47 +0100 Subject: [PATCH 185/311] 8147121: Evacuation failure allocation statistics added too late Move adding evacuation failure statistics to after free_collection_set. Reviewed-by: brutisso, drwhite --- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 846b81805aa..2c0f452ba09 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -3384,6 +3384,10 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { g1_policy()->clear_collection_set(); + record_obj_copy_mem_stats(); + _survivor_evac_stats.adjust_desired_plab_sz(); + _old_evac_stats.adjust_desired_plab_sz(); + // Start a new incremental collection set for the next pause. g1_policy()->start_incremental_cset_building(); @@ -4701,11 +4705,6 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in merge_per_thread_state_info(per_thread_states); - record_obj_copy_mem_stats(); - - _survivor_evac_stats.adjust_desired_plab_sz(); - _old_evac_stats.adjust_desired_plab_sz(); - // Reset and re-enable the hot card cache. // Note the counts for the cards in the regions in the // collection set are reset when the collection set is freed. From 619ec3dd6fff42fb5be1242822c025f1dec600f7 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 2 Mar 2016 15:57:48 +0100 Subject: [PATCH 186/311] 8141141: Young and Old gen PLAB stats are similar in output with -XX:+PrintPLAB Improve PLAB statistic by adding generation, output values are now in bytes, including units, and split it into multiple messages. Reviewed-by: brutisso, sjohanss --- .../src/share/vm/gc/cms/parNewGeneration.cpp | 6 +-- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 4 +- hotspot/src/share/vm/gc/g1/g1EvacStats.cpp | 48 ++++++++++++------- hotspot/src/share/vm/gc/g1/g1EvacStats.hpp | 19 +++----- hotspot/src/share/vm/gc/shared/plab.cpp | 37 ++++++++++++-- hotspot/src/share/vm/gc/shared/plab.hpp | 16 ++++++- hotspot/test/gc/g1/TestPLABOutput.java | 4 +- .../test/gc/g1/plab/TestPLABPromotion.java | 11 ++--- hotspot/test/gc/g1/plab/TestPLABResize.java | 4 +- hotspot/test/gc/g1/plab/lib/LogParser.java | 42 ++++++++-------- 10 files changed, 119 insertions(+), 72 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp index 6962f158e5c..366bf4671b3 100644 --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp @@ -615,7 +615,7 @@ ParNewGeneration::ParNewGeneration(ReservedSpace rs, size_t initial_byte_size) : DefNewGeneration(rs, initial_byte_size, "PCopy"), _overflow_list(NULL), _is_alive_closure(this), - _plab_stats(YoungPLABSize, PLABWeight) + _plab_stats("Young", YoungPLABSize, PLABWeight) { NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) NOT_PRODUCT(_num_par_pushes = 0;) @@ -1008,9 +1008,7 @@ void ParNewGeneration::collect(bool full, from()->set_concurrent_iteration_safe_limit(from()->top()); to()->set_concurrent_iteration_safe_limit(to()->top()); - if (ResizePLAB) { - plab_stats()->adjust_desired_plab_sz(); - } + plab_stats()->adjust_desired_plab_sz(); TASKQUEUE_STATS_ONLY(thread_state_set.print_termination_stats()); TASKQUEUE_STATS_ONLY(thread_state_set.print_taskqueue_stats()); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 2c0f452ba09..743bdd598f7 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1760,8 +1760,8 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : _young_list(new YoungList(this)), _gc_time_stamp(0), _summary_bytes_used(0), - _survivor_evac_stats(YoungPLABSize, PLABWeight), - _old_evac_stats(OldPLABSize, PLABWeight), + _survivor_evac_stats("Young", YoungPLABSize, PLABWeight), + _old_evac_stats("Old", OldPLABSize, PLABWeight), _expand_heap_after_alloc_failure(true), _old_marking_cycles_started(0), _old_marking_cycles_completed(0), diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp index a000a1e40ce..1cb7384ed46 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -29,15 +29,26 @@ #include "logging/log.hpp" #include "trace/tracing.hpp" +void G1EvacStats::log_plab_allocation() { + PLABStats::log_plab_allocation(); + log_debug(gc, plab)("%s other allocation: " + "region end waste: " SIZE_FORMAT "B, " + "regions filled: %u, " + "direct allocated: " SIZE_FORMAT "B, " + "failure used: " SIZE_FORMAT "B, " + "failure wasted: " SIZE_FORMAT "B", + _description, + _region_end_waste * HeapWordSize, + _regions_filled, + _direct_allocated * HeapWordSize, + _failure_used * HeapWordSize, + _failure_waste * HeapWordSize); +} + void G1EvacStats::adjust_desired_plab_sz() { + log_plab_allocation(); + if (!ResizePLAB) { - log_debug(gc, plab)(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " " - "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " " - "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " " - "regions filled = %u direct_allocated = " SIZE_FORMAT " " - "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") ", - _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste, - _regions_filled, _direct_allocated, _failure_used, _failure_waste); // Clear accumulators for next round. reset(); return; @@ -107,18 +118,19 @@ void G1EvacStats::adjust_desired_plab_sz() { // Latch the result _desired_net_plab_sz = plab_sz; - log_debug(gc, plab)(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " " - "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " " - "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " " - "regions filled = %u direct_allocated = " SIZE_FORMAT " " - "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") " - " (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ")", - _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste, - _regions_filled, _direct_allocated, _failure_used, _failure_waste, - cur_plab_sz, plab_sz); - + log_sizing(cur_plab_sz, plab_sz); // Clear accumulators for next round. reset(); } +G1EvacStats::G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt) : + PLABStats(description, desired_plab_sz_, wt), + _region_end_waste(0), + _regions_filled(0), + _direct_allocated(0), + _failure_used(0), + _failure_waste(0) { +} + + G1EvacStats::~G1EvacStats() { } diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp index 1d0a53f5453..b322593e7ea 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -51,20 +51,15 @@ class G1EvacStats : public PLABStats { _failure_waste = 0; } + virtual void log_plab_allocation(); + public: - G1EvacStats(size_t desired_plab_sz_, unsigned wt) : PLABStats(desired_plab_sz_, wt), - _region_end_waste(0), _regions_filled(0), _direct_allocated(0), - _failure_used(0), _failure_waste(0) { - } + G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt); + + ~G1EvacStats(); virtual void adjust_desired_plab_sz(); - size_t allocated() const { return _allocated; } - size_t wasted() const { return _wasted; } - size_t unused() const { return _unused; } - size_t used() const { return allocated() - (wasted() + unused()); } - size_t undo_wasted() const { return _undo_wasted; } - uint regions_filled() const { return _regions_filled; } size_t region_end_waste() const { return _region_end_waste; } size_t direct_allocated() const { return _direct_allocated; } @@ -77,8 +72,6 @@ class G1EvacStats : public PLABStats { inline void add_direct_allocated(size_t value); inline void add_region_end_waste(size_t value); inline void add_failure_used_and_waste(size_t used, size_t waste); - - ~G1EvacStats(); }; #endif // SHARE_VM_GC_G1_G1EVACSTATS_HPP diff --git a/hotspot/src/share/vm/gc/shared/plab.cpp b/hotspot/src/share/vm/gc/shared/plab.cpp index d8566523e7c..1743bffb089 100644 --- a/hotspot/src/share/vm/gc/shared/plab.cpp +++ b/hotspot/src/share/vm/gc/shared/plab.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -110,6 +110,30 @@ void PLAB::undo_allocation(HeapWord* obj, size_t word_sz) { } } +void PLABStats::log_plab_allocation() { + log_debug(gc, plab)("%s PLAB allocation: " + "allocated: " SIZE_FORMAT "B, " + "wasted: " SIZE_FORMAT "B, " + "unused: " SIZE_FORMAT "B, " + "used: " SIZE_FORMAT "B, " + "undo waste: " SIZE_FORMAT "B, ", + _description, + _allocated * HeapWordSize, + _wasted * HeapWordSize, + _unused * HeapWordSize, + used() * HeapWordSize, + _undo_wasted * HeapWordSize); +} + +void PLABStats::log_sizing(size_t calculated_words, size_t net_desired_words) { + log_debug(gc, plab)("%s sizing: " + "calculated: " SIZE_FORMAT "B, " + "actual: " SIZE_FORMAT "B", + _description, + calculated_words * HeapWordSize, + net_desired_words * HeapWordSize); +} + // Calculates plab size for current number of gc worker threads. size_t PLABStats::desired_plab_sz(uint no_of_gc_workers) { return MAX2(min_size(), (size_t)align_object_size(_desired_net_plab_sz / no_of_gc_workers)); @@ -119,7 +143,13 @@ size_t PLABStats::desired_plab_sz(uint no_of_gc_workers) { // use. This should be called once at the end of parallel // scavenge; it clears the sensor accumulators. void PLABStats::adjust_desired_plab_sz() { - assert(ResizePLAB, "Not set"); + log_plab_allocation(); + + if (!ResizePLAB) { + // Clear accumulators for next round. + reset(); + return; + } assert(is_object_aligned(max_size()) && min_size() <= max_size(), "PLAB clipping computation may be incorrect"); @@ -150,8 +180,9 @@ void PLABStats::adjust_desired_plab_sz() { new_plab_sz = MIN2(max_size(), new_plab_sz); new_plab_sz = align_object_size(new_plab_sz); // Latch the result - log_trace(gc, plab)("plab_size = " SIZE_FORMAT " desired_net_plab_sz = " SIZE_FORMAT ") ", recent_plab_sz, new_plab_sz); _desired_net_plab_sz = new_plab_sz; + log_sizing(recent_plab_sz, new_plab_sz); + reset(); } diff --git a/hotspot/src/share/vm/gc/shared/plab.hpp b/hotspot/src/share/vm/gc/shared/plab.hpp index b684769ed61..e73562b301f 100644 --- a/hotspot/src/share/vm/gc/shared/plab.hpp +++ b/hotspot/src/share/vm/gc/shared/plab.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -146,6 +146,8 @@ public: // PLAB book-keeping. class PLABStats : public CHeapObj { protected: + const char* _description; // Identifying string. + size_t _allocated; // Total allocated size_t _wasted; // of which wasted (internal fragmentation) size_t _undo_wasted; // of which wasted on undo (is not used for calculation of PLAB size) @@ -160,8 +162,12 @@ class PLABStats : public CHeapObj { _undo_wasted = 0; _unused = 0; } + + virtual void log_plab_allocation(); + virtual void log_sizing(size_t calculated, size_t net_desired); public: - PLABStats(size_t desired_net_plab_sz_, unsigned wt) : + PLABStats(const char* description, size_t desired_net_plab_sz_, unsigned wt) : + _description(description), _allocated(0), _wasted(0), _undo_wasted(0), @@ -172,6 +178,12 @@ class PLABStats : public CHeapObj { virtual ~PLABStats() { } + size_t allocated() const { return _allocated; } + size_t wasted() const { return _wasted; } + size_t unused() const { return _unused; } + size_t used() const { return allocated() - (wasted() + unused()); } + size_t undo_wasted() const { return _undo_wasted; } + static const size_t min_size() { return PLAB::min_size(); } diff --git a/hotspot/test/gc/g1/TestPLABOutput.java b/hotspot/test/gc/g1/TestPLABOutput.java index a8265ac00c1..4b85b1cbcd6 100644 --- a/hotspot/test/gc/g1/TestPLABOutput.java +++ b/hotspot/test/gc/g1/TestPLABOutput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -65,7 +65,7 @@ public class TestPLABOutput { System.out.println(output.getStdout()); - String pattern = ".*GC\\(0\\) .*allocated = (\\d+).*"; + String pattern = ".*GC\\(0\\) .*allocated: (\\d+).*"; Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(output.getStdout()); diff --git a/hotspot/test/gc/g1/plab/TestPLABPromotion.java b/hotspot/test/gc/g1/plab/TestPLABPromotion.java index 54a56bb5092..7b892f29fa3 100644 --- a/hotspot/test/gc/g1/plab/TestPLABPromotion.java +++ b/hotspot/test/gc/g1/plab/TestPLABPromotion.java @@ -23,7 +23,7 @@ /* * @test TestPLABPromotion - * @bug 8141278 + * @bug 8141278 8141141 * @summary Test PLAB promotion * @requires vm.gc=="G1" | vm.gc=="null" * @requires vm.opt.FlightRecorder != true @@ -130,16 +130,15 @@ public class TestPLABPromotion { long plabAllocatedOld; long directAllocatedOld; long memAllocated = testCase.getMemToFill(); - long wordSize = Platform.is32bit() ? 4l : 8l; LogParser logParser = new LogParser(output); Map survivorStats = getPlabStats(logParser, LogParser.ReportType.SURVIVOR_STATS, GC_ID_SURVIVOR_STATS); Map oldStats = getPlabStats(logParser, LogParser.ReportType.OLD_STATS, GC_ID_OLD_STATS); - plabAllocatedSurvivor = wordSize * survivorStats.get("used"); - directAllocatedSurvivor = wordSize * survivorStats.get("direct_allocated"); - plabAllocatedOld = wordSize * oldStats.get("used"); - directAllocatedOld = wordSize * oldStats.get("direct_allocated"); + plabAllocatedSurvivor = survivorStats.get("used"); + directAllocatedSurvivor = survivorStats.get("direct allocated"); + plabAllocatedOld = oldStats.get("used"); + directAllocatedOld = oldStats.get("direct allocated"); System.out.printf("Survivor PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedSurvivor, directAllocatedSurvivor, memAllocated); System.out.printf("Old PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedOld, directAllocatedOld, memAllocated); diff --git a/hotspot/test/gc/g1/plab/TestPLABResize.java b/hotspot/test/gc/g1/plab/TestPLABResize.java index b07b769baa3..e9aef79c07f 100644 --- a/hotspot/test/gc/g1/plab/TestPLABResize.java +++ b/hotspot/test/gc/g1/plab/TestPLABResize.java @@ -23,7 +23,7 @@ /* * @test TestPLABResize - * @bug 8141278 + * @bug 8141278 8141141 * @summary Test for PLAB resizing * @requires vm.gc=="G1" | vm.gc=="null" * @requires vm.opt.FlightRecorder != true @@ -117,7 +117,7 @@ public class TestPLABResize { .map(item -> { return item.getValue() .get(LogParser.ReportType.SURVIVOR_STATS) - .get("desired_plab_sz"); + .get("actual"); }) .collect(Collectors.toCollection(ArrayList::new)); diff --git a/hotspot/test/gc/g1/plab/lib/LogParser.java b/hotspot/test/gc/g1/plab/lib/LogParser.java index ce2f94ef6e6..2bf933edabd 100644 --- a/hotspot/test/gc/g1/plab/lib/LogParser.java +++ b/hotspot/test/gc/g1/plab/lib/LogParser.java @@ -35,14 +35,12 @@ import java.util.regex.Pattern; * * Typical GC log with PLAB statistics (options - -Xlog:gc=debug,gc+plab=debug) looks like: * - * [2,244s][info ][gc ] GC(30) Concurrent Mark abort - * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,245s][info ][gc ] GC(33) Pause Young (G1 Evacuation Pause) 127M->127M(128M) (2,244s, 2,245s) 0,899ms - * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,246s][info ][gc ] GC(34) Pause Initial Mark (G1 Evacuation Pause) 127M->127M(128M) (2,245s, 2,246s) 0,907ms - + * [0.330s][debug][gc,plab ] GC(0) Young PLAB allocation: allocated: 1825632B, wasted: 29424B, unused: 2320B, used: 1793888B, undo waste: 0B, + * [0.330s][debug][gc,plab ] GC(0) Young other allocation: region end waste: 0B, regions filled: 2, direct allocated: 271520B, failure used: 0B, failure wasted: 0B + * [0.330s][debug][gc,plab ] GC(0) Young sizing: calculated: 358776B, actual: 358776B + * [0.330s][debug][gc,plab ] GC(0) Old PLAB allocation: allocated: 427248B, wasted: 592B, unused: 368584B, used: 58072B, undo waste: 0B, + * [0.330s][debug][gc,plab ] GC(0) Old other allocation: region end waste: 0B, regions filled: 1, direct allocated: 41704B, failure used: 0B, failure wasted: 0B + * [0.330s][debug][gc,plab ] GC(0) Old sizing: calculated: 11608B, actual: 11608B */ final public class LogParser { @@ -53,7 +51,6 @@ final public class LogParser { * Type of parsed log element. */ public static enum ReportType { - SURVIVOR_STATS, OLD_STATS } @@ -64,8 +61,8 @@ final public class LogParser { // GC ID private static final Pattern GC_ID_PATTERN = Pattern.compile("\\[gc,plab\\s*\\] GC\\((\\d+)\\)"); - // Pattern for extraction pair = - private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w+\\s+=\\s+\\d+"); + // Pattern for extraction pair : + private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w* \\w+:\\s+\\d+"); /** * Construct LogParser Object @@ -108,24 +105,29 @@ final public class LogParser { if (matcher.find()) { Map> oneReportItem; ReportType reportType; - // Second line in log is statistics for Old PLAB allocation - if ( !allocationStatistics.containsKey(gc_id.get()) ) { - oneReportItem = new EnumMap<>(ReportType.class); + + if (!allocationStatistics.containsKey(gc_id.get())) { + allocationStatistics.put(gc_id.get(), new EnumMap<>(ReportType.class)); + } + + if ( line.contains("Young") ) { reportType = ReportType.SURVIVOR_STATS; - allocationStatistics.put(gc_id.get(), oneReportItem); } else { - oneReportItem = allocationStatistics.get(gc_id.get()); reportType = ReportType.OLD_STATS; } + oneReportItem = allocationStatistics.get(gc_id.get()); + if (!oneReportItem.containsKey(reportType)) { + oneReportItem.put(reportType,new HashMap()); + } + // Extract all pairs from log. - HashMap plabStats = new HashMap<>(); + Map plabStats = oneReportItem.get(reportType); do { String pair = matcher.group(); - String[] nameValue = pair.replaceAll(" ", "").split("="); - plabStats.put(nameValue[0], Long.parseLong(nameValue[1])); + String[] nameValue = pair.replaceAll(": ", ":").split(":"); + plabStats.put(nameValue[0].trim(), Long.parseLong(nameValue[1])); } while (matcher.find()); - oneReportItem.put(reportType,plabStats); } } } From 2d1daacbc9cc49d8158abbab494980973abfc009 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 2 Mar 2016 18:28:42 +0300 Subject: [PATCH 187/311] 8147994: [macosx] JScrollPane jitters up/down during trackpad scrolling on MacOS/Aqua Reviewed-by: alexp, aivanov --- .../swing/plaf/basic/BasicScrollPaneUI.java | 11 +--- .../HorizontalMouseWheelOnShiftPressed.java} | 55 +++++++++++++------ 2 files changed, 40 insertions(+), 26 deletions(-) rename jdk/test/javax/swing/JScrollPane/{8033000/bug8033000.java => HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java} (78%) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java index a9b0b80e444..2a3df571977 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -962,18 +962,13 @@ public class BasicScrollPaneUI int orientation = SwingConstants.VERTICAL; // find which scrollbar to scroll, or return if none - if (toScroll == null || !toScroll.isVisible()) { + if (toScroll == null || !toScroll.isVisible() + || e.isShiftDown()) { toScroll = scrollpane.getHorizontalScrollBar(); if (toScroll == null || !toScroll.isVisible()) { return; } orientation = SwingConstants.HORIZONTAL; - } else if(e.isShiftDown()){ - JScrollBar hScroll = scrollpane.getHorizontalScrollBar(); - if (hScroll != null && hScroll.isVisible()) { - toScroll = hScroll; - orientation = SwingConstants.HORIZONTAL; - } } e.consume(); diff --git a/jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java b/jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java similarity index 78% rename from jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java rename to jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java index 4e5d23149ab..b8120b9e910 100644 --- a/jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java +++ b/jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -20,6 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + import java.awt.BorderLayout; import java.awt.Point; import java.awt.Robot; @@ -29,24 +30,25 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; -import javax.swing.UIManager; + import jdk.testlibrary.OSInfo; /** * @test - * @bug 8033000 + * @bug 8033000 8147994 * @author Alexander Scherbatiy * @summary No Horizontal Mouse Wheel Support In BasicScrollPaneUI * @library ../../../../lib/testlibrary * @build jdk.testlibrary.OSInfo - * @run main bug8033000 + * @run main HorizontalMouseWheelOnShiftPressed */ -public class bug8033000 { +public class HorizontalMouseWheelOnShiftPressed { private static JScrollPane scrollPane; private static JTextArea textArea; private static Point point; private static final int delta; + private static JFrame frame; static { delta = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ? -30 : 30; @@ -57,9 +59,17 @@ public class bug8033000 { Robot robot = new Robot(); robot.setAutoDelay(50); - SwingUtilities.invokeAndWait(bug8033000::createAndShowGUI); + SwingUtilities.invokeAndWait( + HorizontalMouseWheelOnShiftPressed::createAndShowGUI); robot.waitForIdle(); + try { + test(robot); + } finally { + frame.dispose(); + } + } + private static void test(Robot robot) throws Exception { SwingUtilities.invokeAndWait(() -> { Point locationOnScreen = scrollPane.getLocationOnScreen(); point = new Point( @@ -75,7 +85,7 @@ public class bug8033000 { robot.waitForIdle(); robot.mouseWheel(delta); robot.waitForIdle(); - checkScrollPane(true); + checkScrollPane(true, false); // vertical scroll bar is enabled + shift initScrollPane(true, false); @@ -84,14 +94,14 @@ public class bug8033000 { robot.mouseWheel(delta); robot.keyRelease(KeyEvent.VK_SHIFT); robot.waitForIdle(); - checkScrollPane(true); + checkScrollPane(false, false); // horizontal scroll bar is enabled initScrollPane(false, true); robot.waitForIdle(); robot.mouseWheel(delta); robot.waitForIdle(); - checkScrollPane(false); + checkScrollPane(false, true); // horizontal scroll bar is enabled + shift initScrollPane(false, true); @@ -100,14 +110,14 @@ public class bug8033000 { robot.mouseWheel(delta); robot.keyRelease(KeyEvent.VK_SHIFT); robot.waitForIdle(); - checkScrollPane(false); + checkScrollPane(false, true); // both scroll bars are enabled initScrollPane(true, true); robot.waitForIdle(); robot.mouseWheel(delta); robot.waitForIdle(); - checkScrollPane(true); + checkScrollPane(true, false); // both scroll bars are enabled + shift initScrollPane(true, true); @@ -116,7 +126,7 @@ public class bug8033000 { robot.mouseWheel(delta); robot.keyRelease(KeyEvent.VK_SHIFT); robot.waitForIdle(); - checkScrollPane(false); + checkScrollPane(false, true); } static void initScrollPane(boolean vVisible, boolean hVisible) throws Exception { @@ -131,17 +141,25 @@ public class bug8033000 { }); } - static void checkScrollPane(boolean verticalScrolled) throws Exception { + static void checkScrollPane(boolean verticalScrolled, + boolean horizontalScrolled) throws Exception { SwingUtilities.invokeAndWait(() -> { if (verticalScrolled) { - if (scrollPane.getVerticalScrollBar().getValue() == 0 - || scrollPane.getHorizontalScrollBar().getValue() != 0) { + if (scrollPane.getVerticalScrollBar().getValue() == 0) { throw new RuntimeException("Wrong vertical scrolling!"); } + } else{ + if (scrollPane.getVerticalScrollBar().getValue() != 0) { + throw new RuntimeException("Wrong vertical scrolling!"); + } + } + if (horizontalScrolled) { + if (scrollPane.getHorizontalScrollBar().getValue() == 0) { + throw new RuntimeException("Wrong horizontal scrolling!"); + } } else { - if (scrollPane.getVerticalScrollBar().getValue() != 0 - || scrollPane.getHorizontalScrollBar().getValue() == 0) { + if (scrollPane.getHorizontalScrollBar().getValue() != 0) { throw new RuntimeException("Wrong horizontal scrolling!"); } } @@ -149,9 +167,10 @@ public class bug8033000 { } static void createAndShowGUI() { - JFrame frame = new JFrame(); + frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 300); + frame.setLocationRelativeTo(null); textArea = new JTextArea("Hello World!"); scrollPane = new JScrollPane(textArea); JPanel panel = new JPanel(new BorderLayout()); From 1c5a7710e3d6c3d27d47f898cd9528e308154638 Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Wed, 2 Mar 2016 10:59:25 -0500 Subject: [PATCH 188/311] 8150746: runtime/logging/ItablesTest.java fails with: java.lang.RuntimeException: 'Resolving: klass: ' missing from stdout/stderr Deleted logging line from code and test because unnecessary Reviewed-by: twisti, coleenp --- hotspot/src/share/vm/interpreter/interpreterRuntime.cpp | 8 -------- hotspot/test/runtime/logging/ItablesTest.java | 1 - 2 files changed, 9 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 166390d8d6b..839eec62153 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -762,14 +762,6 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread); if (cp_cache_entry->is_resolved(bytecode)) return; - if (bytecode == Bytecodes::_invokeinterface) { - if (log_develop_is_enabled(Trace, itables)) { - ResourceMark rm(thread); - log_develop_trace(itables)("Resolving: klass: %s to method: %s", - info.resolved_klass()->name()->as_C_string(), - info.resolved_method()->name()->as_C_string()); - } - } #ifdef ASSERT if (bytecode == Bytecodes::_invokeinterface) { if (info.resolved_method()->method_holder() == diff --git a/hotspot/test/runtime/logging/ItablesTest.java b/hotspot/test/runtime/logging/ItablesTest.java index c1cfd33d865..0fe9d84213c 100644 --- a/hotspot/test/runtime/logging/ItablesTest.java +++ b/hotspot/test/runtime/logging/ItablesTest.java @@ -49,7 +49,6 @@ public class ItablesTest { output.shouldContain("invokespecial resolved method: caller-class:ClassB"); output.shouldContain("invokespecial selected method: resolved-class:ClassB"); output.shouldContain("invokeinterface selected method: receiver-class"); - output.shouldContain("Resolving: klass: "); output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder("-Xlog:itables=trace", "ItablesVtableTest"); From 645c21e16f029b4cf3d9e560a254b1f793ee8d09 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 2 Mar 2016 16:25:29 +0000 Subject: [PATCH 189/311] 8150976: JarFile and MRJAR tests should use the JDK specific Version API Reviewed-by: alanb, mchung --- .../share/classes/java/util/jar/JarFile.java | 4 ++-- .../java/util/jar/JarFile/MultiReleaseJarAPI.java | 9 ++++++--- .../util/jar/JarFile/MultiReleaseJarIterators.java | 7 +++++-- .../util/jar/JarFile/MultiReleaseJarProperties.java | 12 +++++++----- .../util/jar/JarFile/MultiReleaseJarSecurity.java | 7 +++++-- jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java | 2 +- 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java index d5032fed2fd..2ea1a69657a 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java @@ -158,7 +158,7 @@ class JarFile extends ZipFile { RUNTIME_VERSION = AccessController.doPrivileged( new PrivilegedAction() { public Integer run() { - Integer v = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 Version integrated + Integer v = jdk.Version.current().major(); Integer i = Integer.getInteger("jdk.util.jar.version", v); i = i < 0 ? 0 : i; return i > v ? v : i; @@ -359,7 +359,7 @@ class JarFile extends ZipFile { } private boolean runtimeVersionExists() { - int version = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 integrated + int version = jdk.Version.current().major(); try { Release.valueOf(version); return true; diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java index 7f7653e9eab..a520d316a58 100644 --- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java @@ -39,9 +39,9 @@ import java.util.Arrays; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import jdk.Version; import static java.util.jar.JarFile.Release; -import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version import org.testng.Assert; import org.testng.annotations.AfterClass; @@ -50,6 +50,9 @@ import org.testng.annotations.Test; public class MultiReleaseJarAPI { + + static final int MAJOR_VERSION = Version.current().major(); + String userdir = System.getProperty("user.dir","."); File unversioned = new File(userdir, "unversioned.jar"); File multirelease = new File(userdir, "multi-release.jar"); @@ -106,7 +109,7 @@ public class MultiReleaseJarAPI { } // assure that we have a Release object corresponding to the actual runtime version - String version = "VERSION_" + jdkMajorVersion(); + String version = "VERSION_" + MAJOR_VERSION; boolean runtimeVersionExists = false; for (Release value : values) { if (version.equals(value.name())) runtimeVersionExists = true; @@ -123,7 +126,7 @@ public class MultiReleaseJarAPI { if (name.equals("BASE")) { prefix = ""; } else if (name.equals("RUNTIME")) { - prefix = "META-INF/versions/" + jdkMajorVersion() + "/"; + prefix = "META-INF/versions/" + MAJOR_VERSION + "/"; } else { prefix = "META-INF/versions/" + name.substring(8) + "/"; } diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java index 587bf6e5da1..59900cf3f7a 100644 --- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java @@ -42,9 +42,9 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; import java.util.zip.ZipFile; +import jdk.Version; import static java.util.jar.JarFile.Release; -import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version import org.testng.Assert; import org.testng.annotations.AfterClass; @@ -53,6 +53,9 @@ import org.testng.annotations.Test; public class MultiReleaseJarIterators { + + static final int MAJOR_VERSION = Version.current().major(); + String userdir = System.getProperty("user.dir", "."); File unversioned = new File(userdir, "unversioned.jar"); File multirelease = new File(userdir, "multi-release.jar"); @@ -121,7 +124,7 @@ public class MultiReleaseJarIterators { try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) { Map expectedEntries; - switch (jdkMajorVersion()) { + switch (MAJOR_VERSION) { case 9: expectedEntries = v9Entries; break; diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java index 978ba328be6..6bf059fb8ea 100644 --- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java @@ -54,8 +54,7 @@ import java.net.URLClassLoader; import java.nio.file.Files; import java.util.jar.JarEntry; import java.util.jar.JarFile; - -import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version +import jdk.Version; import org.testng.Assert; import org.testng.annotations.AfterClass; @@ -63,6 +62,9 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class MultiReleaseJarProperties { + + static final int MAJOR_VERSION = Version.current().major(); + final static int ROOTVERSION = 8; // magic number from knowledge of internals final static String userdir = System.getProperty("user.dir", "."); final static File multirelease = new File(userdir, "multi-release.jar"); @@ -77,14 +79,14 @@ public class MultiReleaseJarProperties { creator.compileEntries(); creator.buildMultiReleaseJar(); - rtVersion = Integer.getInteger("jdk.util.jar.version", jdkMajorVersion()); + rtVersion = Integer.getInteger("jdk.util.jar.version", MAJOR_VERSION); String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", ""); if (mrprop.equals("false")) { rtVersion = ROOTVERSION; } else if (rtVersion < ROOTVERSION) { rtVersion = ROOTVERSION; - } else if (rtVersion > jdkMajorVersion()) { - rtVersion = jdkMajorVersion(); + } else if (rtVersion > MAJOR_VERSION) { + rtVersion = MAJOR_VERSION; } force = mrprop.equals("force"); diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java index 6547c990b2a..348194a3be3 100644 --- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java @@ -40,6 +40,7 @@ import java.util.Arrays; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.zip.ZipFile; +import jdk.Version; import org.testng.Assert; import org.testng.annotations.AfterClass; @@ -47,6 +48,9 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class MultiReleaseJarSecurity { + + static final int MAJOR_VERSION = Version.current().major(); + String userdir = System.getProperty("user.dir","."); File multirelease = new File(userdir, "multi-release.jar"); File signedmultirelease = new File(userdir, "signed-multi-release.jar"); @@ -68,9 +72,8 @@ public class MultiReleaseJarSecurity { @Test public void testCertsAndSigners() throws IOException { try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) { - int version = sun.misc.Version.jdkMajorVersion(); // fixme JEP 223 Version CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class")); - CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + version + "/version/Version.class")); + CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + MAJOR_VERSION + "/version/Version.class")); Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates())); Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners())); } diff --git a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java index f409e2b4cd5..6f87dc68813 100644 --- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java +++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java @@ -44,7 +44,7 @@ import org.testng.Assert; import org.testng.annotations.*; public class MultiReleaseJarTest { - final private int MAJOR_VERSION= Version.current().major(); + final private int MAJOR_VERSION = Version.current().major(); final private String userdir = System.getProperty("user.dir","."); final private Map stringEnv = new HashMap<>(); From 1619ac11c9b35f6caa138588ad179f49a744fa30 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Wed, 2 Mar 2016 20:16:11 +0100 Subject: [PATCH 190/311] 8150635: j.l.i.MethodHandles.loop(...) throws IndexOutOfBoundsException Reviewed-by: psandoz --- .../java/lang/invoke/MethodHandles.java | 69 +++--- jdk/test/java/lang/invoke/T8139885.java | 200 ++++++++++++++++-- 2 files changed, 221 insertions(+), 48 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 2c01f376f71..70791273212 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -3268,12 +3268,17 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); *

    • This list of types is called the "common prefix". * *

      - * Step 1B: Determine loop parameters.

        - *
      1. Examine init function parameter lists. - *
      2. Omitted init functions are deemed to have {@code null} parameter lists. - *
      3. All init function parameter lists must be effectively identical. - *
      4. The longest parameter list (which is necessarily unique) is called the "common suffix". + * Step 1B: Determine loop parameters.
          + *
        • If at least one init function is given,
            + *
          1. Examine init function parameter lists. + *
          2. Omitted init functions are deemed to have {@code null} parameter lists. + *
          3. All init function parameter lists must be effectively identical. + *
          4. The longest parameter list (which is necessarily unique) is called the "common suffix". *
          + *
        • If no init function is given,
            + *
          1. Examine the suffixes of the step, pred, and fini parameter lists, after removing the "common prefix". + *
          2. The longest of these suffixes is taken as the "common suffix". + *
        *

        * Step 1C: Determine loop return type.

          *
        1. Examine fini function return types, disregarding omitted fini functions. @@ -3286,9 +3291,6 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); *
        2. Every non-omitted pred function must have a {@code boolean} return type. *
        *

        - * (Implementation Note: Steps 1A, 1B, 1C, 1D are logically independent of each other, and may be performed in any - * order.) - *

        * Step 2: Determine parameter lists.

          *
        1. The parameter list for the resulting loop handle will be the "common suffix". *
        2. The parameter list for init functions will be adjusted to the "common suffix". (Note that their parameter @@ -3375,10 +3377,10 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); *
          {@code
                * // iterative implementation of the factorial function as a loop handle
                * static int one(int k) { return 1; }
          -     * int inc(int i, int acc, int k) { return i + 1; }
          -     * int mult(int i, int acc, int k) { return i * acc; }
          -     * boolean pred(int i, int acc, int k) { return i < k; }
          -     * int fin(int i, int acc, int k) { return acc; }
          +     * static int inc(int i, int acc, int k) { return i + 1; }
          +     * static int mult(int i, int acc, int k) { return i * acc; }
          +     * static boolean pred(int i, int acc, int k) { return i < k; }
          +     * static int fin(int i, int acc, int k) { return acc; }
                * // assume MH_one, MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods
                * // null initializer for counter, should initialize to 0
                * MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
          @@ -3436,9 +3438,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
                           collect(Collectors.toList());
           
                   // Step 1B: determine loop parameters.
          -        final List> empty = new ArrayList<>();
          -        final List> commonSuffix = init.stream().filter(Objects::nonNull).map(MethodHandle::type).
          -                map(MethodType::parameterList).reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
          +        final List> commonSuffix = buildCommonSuffix(init, step, pred, fini, commonPrefix.size());
                   checkLoop1b(init, commonSuffix);
           
                   // Step 1C: determine loop return type.
          @@ -3520,9 +3520,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
                * @apiNote Example:
                * 
          {@code
                * // implement the zip function for lists as a loop handle
          -     * List initZip(Iterator a, Iterator b) { return new ArrayList<>(); }
          -     * boolean zipPred(List zip, Iterator a, Iterator b) { return a.hasNext() && b.hasNext(); }
          -     * List zipStep(List zip, Iterator a, Iterator b) {
          +     * static List initZip(Iterator a, Iterator b) { return new ArrayList<>(); }
          +     * static boolean zipPred(List zip, Iterator a, Iterator b) { return a.hasNext() && b.hasNext(); }
          +     * static List zipStep(List zip, Iterator a, Iterator b) {
                *   zip.add(a.next());
                *   zip.add(b.next());
                *   return zip;
          @@ -3594,9 +3594,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
                * @apiNote Example:
                * 
          {@code
                * // int i = 0; while (i < limit) { ++i; } return i; => limit
          -     * int zero(int limit) { return 0; }
          -     * int step(int i, int limit) { return i + 1; }
          -     * boolean pred(int i, int limit) { return i < limit; }
          +     * static int zero(int limit) { return 0; }
          +     * static int step(int i, int limit) { return i + 1; }
          +     * static boolean pred(int i, int limit) { return i < limit; }
                * // assume MH_zero, MH_step, and MH_pred are handles to the above methods
                * MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred);
                * assertEquals(23, loop.invoke(23));
          @@ -3664,8 +3664,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
                * 
          {@code
                * // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
                * // => a variation on a well known theme
          -     * String start(String arg) { return arg; }
          -     * String step(int counter, String v, String arg) { return "na " + v; }
          +     * static String start(String arg) { return arg; }
          +     * static String step(int counter, String v, String arg) { return "na " + v; }
                * // assume MH_start and MH_step are handles to the two methods above
                * MethodHandle fit13 = MethodHandles.constant(int.class, 13);
                * MethodHandle loop = MethodHandles.countedLoop(fit13, MH_start, MH_step);
          @@ -3808,11 +3808,11 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
                * @apiNote Example:
                * 
          {@code
                * // reverse a list
          -     * List reverseStep(String e, List r, List l) {
          +     * static List reverseStep(String e, List r, List l) {
                *   r.add(0, e);
                *   return r;
                * }
          -     * List newArrayList(List l) { return new ArrayList<>(); }
          +     * static List newArrayList(List l) { return new ArrayList<>(); }
                * // assume MH_reverseStep, MH_newArrayList are handles to the above methods
                * MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep);
                * List list = Arrays.asList("a", "b", "c", "d", "e");
          @@ -4084,6 +4084,21 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
                   }
               }
           
          +    private static List> buildCommonSuffix(List init, List step, List pred, List fini, int cpSize) {
          +        final List> empty = List.of();
          +        final List nonNullInits = init.stream().filter(Objects::nonNull).collect(Collectors.toList());
          +        if (nonNullInits.isEmpty()) {
          +            final List> longest = Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).
          +                    // take only those that can contribute to a common suffix because they are longer than the prefix
          +                    map(MethodHandle::type).filter(t -> t.parameterCount() > cpSize).map(MethodType::parameterList).
          +                    reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
          +            return longest.size() == 0 ? empty : longest.subList(cpSize, longest.size());
          +        } else {
          +            return nonNullInits.stream().map(MethodHandle::type).map(MethodType::parameterList).
          +                    reduce((p, q) -> p.size() >= q.size() ? p : q).get();
          +        }
          +    }
          +
               private static void checkLoop1b(List init, List> commonSuffix) {
                   if (init.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::parameterList).
                           anyMatch(pl -> !pl.equals(commonSuffix.subList(0, pl.size())))) {
          @@ -4109,8 +4124,10 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
               }
           
               private static void checkLoop2(List step, List pred, List fini, List> commonParameterSequence) {
          +        final int cpSize = commonParameterSequence.size();
                   if (Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).map(MethodHandle::type).
          -                map(MethodType::parameterList).anyMatch(pl -> !pl.equals(commonParameterSequence.subList(0, pl.size())))) {
          +                map(MethodType::parameterList).
          +                anyMatch(pl -> pl.size() > cpSize || !pl.equals(commonParameterSequence.subList(0, pl.size())))) {
                       throw newIllegalArgumentException("found non-effectively identical parameter type lists:\nstep: " + step +
                               "\npred: " + pred + "\nfini: " + fini + " (common parameter sequence: " + commonParameterSequence + ")");
                   }
          diff --git a/jdk/test/java/lang/invoke/T8139885.java b/jdk/test/java/lang/invoke/T8139885.java
          index 183ff9a9aca..f2fdbe7c068 100644
          --- a/jdk/test/java/lang/invoke/T8139885.java
          +++ b/jdk/test/java/lang/invoke/T8139885.java
          @@ -27,6 +27,7 @@
            * @bug 8139885
            * @bug 8143798
            * @bug 8150825
          + * @bug 8150635
            * @run testng/othervm -ea -esa test.java.lang.invoke.T8139885
            */
           
          @@ -76,6 +77,15 @@ public class T8139885 {
                   assertEquals(120, loop.invoke(5));
               }
           
          +    @Test
          +    public static void testLoopNullInit() throws Throwable {
          +        // null initializer for counter, should initialize to 0, one-clause loop
          +        MethodHandle[] counterClause = new MethodHandle[]{null, Loop.MH_inc, Loop.MH_pred, Loop.MH_fin};
          +        MethodHandle loop = MethodHandles.loop(counterClause);
          +        assertEquals(Loop.MT_loop, loop.type());
          +        assertEquals(10, loop.invoke(10));
          +    }
          +
               @Test
               public static void testLoopVoid1() throws Throwable {
                   // construct a post-checked loop that only does one iteration and has a void body and void local state
          @@ -93,6 +103,15 @@ public class T8139885 {
                   loop.invoke();
               }
           
          +    @Test
          +    public static void testLoopVoid3() throws Throwable {
          +        // construct a post-checked loop that only does one iteration and has a void body and void local state,
          +        // and that has a void finalizer
          +        MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_f});
          +        assertEquals(MethodType.methodType(void.class), loop.type());
          +        loop.invoke();
          +    }
          +
               @Test
               public static void testLoopFacWithVoidState() throws Throwable {
                   // like testLoopFac, but with additional void state that outputs a dot
          @@ -104,6 +123,31 @@ public class T8139885 {
                   assertEquals(120, loop.invoke(5));
               }
           
          +    @Test
          +    public static void testLoopVoidInt() throws Throwable {
          +        // construct a post-checked loop that only does one iteration and has a void body and void local state,
          +        // and that returns a constant
          +        MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_c});
          +        assertEquals(MethodType.methodType(int.class), loop.type());
          +        assertEquals(23, loop.invoke());
          +    }
          +
          +    @Test
          +    public static void testLoopWithVirtuals() throws Throwable {
          +        // construct a loop (to calculate factorial) that uses a mix of static and virtual methods
          +        MethodHandle[] counterClause = new MethodHandle[]{null, LoopWithVirtuals.permute(LoopWithVirtuals.MH_inc)};
          +        MethodHandle[] accumulatorClause = new MethodHandle[]{
          +                // init function must indicate the loop arguments (there is no other means to determine them)
          +                MethodHandles.dropArguments(LoopWithVirtuals.MH_one, 0, LoopWithVirtuals.class),
          +                LoopWithVirtuals.permute(LoopWithVirtuals.MH_mult),
          +                LoopWithVirtuals.permute(LoopWithVirtuals.MH_pred),
          +                LoopWithVirtuals.permute(LoopWithVirtuals.MH_fin)
          +        };
          +        MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
          +        assertEquals(LoopWithVirtuals.MT_loop, loop.type());
          +        assertEquals(120, loop.invoke(new LoopWithVirtuals(), 5));
          +    }
          +
               @Test
               public static void testLoopNegative() throws Throwable {
                   MethodHandle mh_loop =
          @@ -121,31 +165,38 @@ public class T8139885 {
                   List nesteps = Arrays.asList(Fac.MH_inc, eek, Fac.MH_dot);
                   List nepreds = Arrays.asList(null, Fac.MH_pred, null);
                   List nefinis = Arrays.asList(null, Fac.MH_fin, null);
          +        List lvsteps = Arrays.asList(LoopWithVirtuals.MH_inc, LoopWithVirtuals.MH_mult);
          +        List lvpreds = Arrays.asList(null, LoopWithVirtuals.MH_pred);
          +        List lvfinis = Arrays.asList(null, LoopWithVirtuals.MH_fin);
                   MethodHandle[][][] cases = {
          -                null,
          -                {},
          -                {{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
          -                {{null, Fac.MH_inc}, null},
          -                {{Fac.MH_zero, Fac.MH_dot}},
          -                {{ii}, {id}, {i3}},
          -                {{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc},
          -                        {null, Counted.MH_start, null, Counted.MH_step}},
          -                {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin}, {null, Fac.MH_dot}},
          -                {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin}, {null, Fac.MH_dot}},
          -                {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin}, {null, Fac.MH_dot}}
          +                /*  1 */ null,
          +                /*  2 */ {},
          +                /*  3 */ {{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
          +                /*  4 */ {{null, Fac.MH_inc}, null},
          +                /*  5 */ {{Fac.MH_zero, Fac.MH_dot}},
          +                /*  6 */ {{ii}, {id}, {i3}},
          +                /*  7 */ {{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc},
          +                            {null, Counted.MH_start, null, Counted.MH_step}},
          +                /*  8 */ {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin}, {null, Fac.MH_dot}},
          +                /*  9 */ {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin}, {null, Fac.MH_dot}},
          +                /* 10 */ {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin}, {null, Fac.MH_dot}},
          +                /* 11 */ {{null, LoopWithVirtuals.MH_inc}, {LoopWithVirtuals.MH_one, LoopWithVirtuals.MH_mult, LoopWithVirtuals.MH_pred, LoopWithVirtuals.MH_fin}}
                   };
                   String[] messages = {
          -                "null or no clauses passed",
          -                "null or no clauses passed",
          -                "All loop clauses must be represented as MethodHandle arrays with at most 4 elements.",
          -                "null clauses are not allowed",
          -                "clause 0: init and step return types must match: int != void",
          -                "found non-effectively identical init parameter type lists: " + inits + " (common suffix: " + ints + ")",
          -                "found non-identical finalizer return types: " + finis + " (return type: int)",
          -                "no predicate found: " + preds1,
          -                "predicates must have boolean return type: " + preds2,
          -                "found non-effectively identical parameter type lists:\nstep: " + nesteps + "\npred: " + nepreds +
          -                        "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")"
          +                /*  1 */ "null or no clauses passed",
          +                /*  2 */ "null or no clauses passed",
          +                /*  3 */ "All loop clauses must be represented as MethodHandle arrays with at most 4 elements.",
          +                /*  4 */ "null clauses are not allowed",
          +                /*  5 */ "clause 0: init and step return types must match: int != void",
          +                /*  6 */ "found non-effectively identical init parameter type lists: " + inits +
          +                            " (common suffix: " + ints + ")",
          +                /*  7 */ "found non-identical finalizer return types: " + finis + " (return type: int)",
          +                /*  8 */ "no predicate found: " + preds1,
          +                /*  9 */ "predicates must have boolean return type: " + preds2,
          +                /* 10 */ "found non-effectively identical parameter type lists:\nstep: " + nesteps +
          +                            "\npred: " + nepreds + "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")",
          +                /* 11 */ "found non-effectively identical parameter type lists:\nstep: " + lvsteps +
          +                            "\npred: " + lvpreds + "\nfini: " + lvfinis + " (common parameter sequence: " + ints + ")"
                   };
                   for (int i = 0; i < cases.length; ++i) {
                       boolean caught = false;
          @@ -570,18 +621,25 @@ public class T8139885 {
                       return false;
                   }
           
          +        static int c() {
          +            return 23;
          +        }
          +
                   static final Class EMPTY = Empty.class;
           
                   static final MethodType MT_f = methodType(void.class);
                   static final MethodType MT_pred = methodType(boolean.class);
          +        static final MethodType MT_c = methodType(int.class);
           
                   static final MethodHandle MH_f;
                   static final MethodHandle MH_pred;
          +        static final MethodHandle MH_c;
           
                   static {
                       try {
                           MH_f = LOOKUP.findStatic(EMPTY, "f", MT_f);
                           MH_pred = LOOKUP.findStatic(EMPTY, "pred", MT_pred);
          +                MH_c = LOOKUP.findStatic(EMPTY, "c", MT_c);
                       } catch (Exception e) {
                           throw new ExceptionInInitializerError(e);
                       }
          @@ -651,6 +709,104 @@ public class T8139885 {
           
               }
           
          +    static class Loop {
          +
          +        static int inc(int i, int k) {
          +            return i + 1;
          +        }
          +
          +        static boolean pred(int i, int k) {
          +            return i < k;
          +        }
          +
          +        static int fin(int i, int k) {
          +            return k;
          +        }
          +
          +        static final Class LOOP = Loop.class;
          +
          +        static final MethodType MT_inc = methodType(int.class, int.class, int.class);
          +        static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
          +        static final MethodType MT_fin = methodType(int.class, int.class, int.class);
          +
          +        static final MethodHandle MH_inc;
          +        static final MethodHandle MH_pred;
          +        static final MethodHandle MH_fin;
          +
          +        static final MethodType MT_loop = methodType(int.class, int.class);
          +
          +        static {
          +            try {
          +                MH_inc = LOOKUP.findStatic(LOOP, "inc", MT_inc);
          +                MH_pred = LOOKUP.findStatic(LOOP, "pred", MT_pred);
          +                MH_fin = LOOKUP.findStatic(LOOP, "fin", MT_fin);
          +            } catch (Exception e) {
          +                throw new ExceptionInInitializerError(e);
          +            }
          +        }
          +
          +    }
          +
          +    static class LoopWithVirtuals {
          +
          +        static int one(int k) {
          +            return 1;
          +        }
          +
          +        int inc(int i, int acc, int k) {
          +            return i + 1;
          +        }
          +
          +        int mult(int i, int acc, int k) {
          +            return i * acc;
          +        }
          +
          +        boolean pred(int i, int acc, int k) {
          +            return i < k;
          +        }
          +
          +        int fin(int i, int acc, int k) {
          +            return acc;
          +        }
          +
          +        static final Class LOOP_WITH_VIRTUALS = LoopWithVirtuals.class;
          +
          +        static final MethodType MT_one = methodType(int.class, int.class);
          +        static final MethodType MT_inc = methodType(int.class, int.class, int.class, int.class);
          +        static final MethodType MT_mult = methodType(int.class, int.class, int.class, int.class);
          +        static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class);
          +        static final MethodType MT_fin = methodType(int.class, int.class, int.class, int.class);
          +
          +        static final MethodHandle MH_one;
          +        static final MethodHandle MH_inc;
          +        static final MethodHandle MH_mult;
          +        static final MethodHandle MH_pred;
          +        static final MethodHandle MH_fin;
          +
          +        static final MethodType MT_loop = methodType(int.class, LOOP_WITH_VIRTUALS, int.class);
          +
          +        static {
          +            try {
          +                MH_one = LOOKUP.findStatic(LOOP_WITH_VIRTUALS, "one", MT_one);
          +                MH_inc = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "inc", MT_inc);
          +                MH_mult = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "mult", MT_mult);
          +                MH_pred = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "pred", MT_pred);
          +                MH_fin = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "fin", MT_fin);
          +            } catch (Exception e) {
          +                throw new ExceptionInInitializerError(e);
          +            }
          +        }
          +
          +        static MethodHandle permute(MethodHandle h) {
          +            // The handles representing virtual methods need to be rearranged to match the required order of arguments
          +            // (loop-local state comes first, then loop arguments). As the receiver comes first in the signature but is
          +            // a loop argument, it must be moved to the appropriate position in the signature.
          +            return MethodHandles.permuteArguments(h,
          +                    methodType(h.type().returnType(), int.class, int.class, LOOP_WITH_VIRTUALS, int.class), 2, 0, 1, 3);
          +        }
          +
          +    }
          +
               static class While {
           
                   static int zero(int limit) {
          
          From 525c0c0972d4d80996330192c9932f503f9f2df0 Mon Sep 17 00:00:00 2001
          From: Michael Haupt 
          Date: Wed, 2 Mar 2016 20:36:00 +0100
          Subject: [PATCH 191/311] 8150832: split T8139885 into several tests by
           functionality
          
          Reviewed-by: redestad
          ---
           jdk/test/java/lang/invoke/FindAccessTest.java | 111 ++++
           jdk/test/java/lang/invoke/FoldTest.java       | 158 +++++
           ...{T8139885.java => LoopCombinatorTest.java} | 605 ++----------------
           .../java/lang/invoke/SpreadCollectTest.java   | 240 +++++++
           jdk/test/java/lang/invoke/TryFinallyTest.java | 179 ++++++
           5 files changed, 740 insertions(+), 553 deletions(-)
           create mode 100644 jdk/test/java/lang/invoke/FindAccessTest.java
           create mode 100644 jdk/test/java/lang/invoke/FoldTest.java
           rename jdk/test/java/lang/invoke/{T8139885.java => LoopCombinatorTest.java} (54%)
           create mode 100644 jdk/test/java/lang/invoke/SpreadCollectTest.java
           create mode 100644 jdk/test/java/lang/invoke/TryFinallyTest.java
          
          diff --git a/jdk/test/java/lang/invoke/FindAccessTest.java b/jdk/test/java/lang/invoke/FindAccessTest.java
          new file mode 100644
          index 00000000000..75cba87e96f
          --- /dev/null
          +++ b/jdk/test/java/lang/invoke/FindAccessTest.java
          @@ -0,0 +1,111 @@
          +/*
          + * Copyright (c) 2015, 2016, 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.
          + */
          +
          +/* @test
          + * @bug 8139885
          + * @run testng/othervm -ea -esa test.java.lang.invoke.FindAccessTest
          + */
          +
          +package test.java.lang.invoke;
          +
          +import java.lang.invoke.MethodHandle;
          +import java.lang.invoke.MethodHandles;
          +import java.lang.invoke.MethodHandles.Lookup;
          +import java.lang.invoke.MethodType;
          +
          +import static org.testng.AssertJUnit.*;
          +
          +import org.testng.annotations.*;
          +
          +/**
          + * Tests for Lookup.findClass/accessClass extensions added in JEP 274.
          + */
          +public class FindAccessTest {
          +
          +    static final Lookup LOOKUP = MethodHandles.lookup();
          +
          +    @Test
          +    public static void testFindSpecial() throws Throwable {
          +        FindSpecial.C c = new FindSpecial.C();
          +        assertEquals("I1.m", c.m());
          +        MethodType t = MethodType.methodType(String.class);
          +        MethodHandle ci1m = LOOKUP.findSpecial(FindSpecial.I1.class, "m", t, FindSpecial.C.class);
          +        assertEquals("I1.m", (String) ci1m.invoke(c));
          +    }
          +
          +    @Test
          +    public static void testFindSpecialAbstract() throws Throwable {
          +        FindSpecial.C c = new FindSpecial.C();
          +        assertEquals("q", c.q());
          +        MethodType t = MethodType.methodType(String.class);
          +        boolean caught = false;
          +        try {
          +            MethodHandle ci3q = LOOKUP.findSpecial(FindSpecial.I3.class, "q", t, FindSpecial.C.class);
          +        } catch (Throwable thrown) {
          +            if (!(thrown instanceof IllegalAccessException) || !FindSpecial.ABSTRACT_ERROR.equals(thrown.getMessage())) {
          +                throw new AssertionError(thrown.getMessage(), thrown);
          +            }
          +            caught = true;
          +        }
          +        assertTrue(caught);
          +    }
          +
          +    @Test(expectedExceptions = {ClassNotFoundException.class})
          +    public static void testFindClassCNFE() throws ClassNotFoundException, IllegalAccessException {
          +        LOOKUP.findClass("does.not.Exist");
          +    }
          +
          +    static class FindSpecial {
          +
          +        interface I1 {
          +            default String m() {
          +                return "I1.m";
          +            }
          +        }
          +
          +        interface I2 {
          +            default String m() {
          +                return "I2.m";
          +            }
          +        }
          +
          +        interface I3 {
          +            String q();
          +        }
          +
          +        static class C implements I1, I2, I3 {
          +            public String m() {
          +                return I1.super.m();
          +            }
          +            public String q() {
          +                return "q";
          +            }
          +        }
          +
          +        static final String ABSTRACT_ERROR = "no such method: test.java.lang.invoke.FindAccessTest$FindSpecial$I3.q()String/invokeSpecial";
          +
          +    }
          +
          +}
          diff --git a/jdk/test/java/lang/invoke/FoldTest.java b/jdk/test/java/lang/invoke/FoldTest.java
          new file mode 100644
          index 00000000000..1e8e4f517db
          --- /dev/null
          +++ b/jdk/test/java/lang/invoke/FoldTest.java
          @@ -0,0 +1,158 @@
          +/*
          + * Copyright (c) 2015, 2016, 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.
          + */
          +
          +/* @test
          + * @bug 8139885
          + * @run testng/othervm -ea -esa test.java.lang.invoke.FoldTest
          + */
          +
          +package test.java.lang.invoke;
          +
          +import java.io.StringWriter;
          +import java.lang.invoke.MethodHandle;
          +import java.lang.invoke.MethodHandles;
          +import java.lang.invoke.MethodHandles.Lookup;
          +import java.lang.invoke.MethodType;
          +
          +import static java.lang.invoke.MethodType.methodType;
          +
          +import static org.testng.AssertJUnit.*;
          +
          +import org.testng.annotations.*;
          +
          +/**
          + * Tests for the new fold method handle combinator added in JEP 274.
          + */
          +public class FoldTest {
          +
          +    static final Lookup LOOKUP = MethodHandles.lookup();
          +
          +    @Test
          +    public static void testFold0a() throws Throwable {
          +        // equivalence to foldArguments(MethodHandle,MethodHandle)
          +        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder);
          +        assertEquals(Fold.MT_folded1, fold.type());
          +        assertEquals(720, (int) fold.invoke(3, 4, 5));
          +    }
          +
          +    @Test
          +    public static void testFold1a() throws Throwable {
          +        // test foldArguments for folding position 1
          +        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1);
          +        assertEquals(Fold.MT_folded1, fold.type());
          +        assertEquals(540, (int) fold.invoke(3, 4, 5));
          +    }
          +
          +    @Test
          +    public static void testFold0b() throws Throwable {
          +        // test foldArguments equivalence with multiple types
          +        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb);
          +        assertEquals(Fold.MT_folded2, fold.type());
          +        assertEquals(23, (int) fold.invoke("true", true, 23));
          +    }
          +
          +    @Test
          +    public static void testFold1b() throws Throwable {
          +        // test folgArguments for folding position 1, with multiple types
          +        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2);
          +        assertEquals(Fold.MT_folded3, fold.type());
          +        assertEquals(1, (int) fold.invoke(true, true, 1));
          +        assertEquals(-1, (int) fold.invoke(true, false, -1));
          +    }
          +
          +    @Test
          +    public static void testFoldArgumentsExample() throws Throwable {
          +        // test the JavaDoc foldArguments-with-pos example
          +        StringWriter swr = new StringWriter();
          +        MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr);
          +        MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class));
          +        assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
          +        MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace);
          +        assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          +        assertEquals("jum", swr.toString());
          +    }
          +
          +    static class Fold {
          +
          +        static int adder(int a, int b, int c) {
          +            return a + b + c;
          +        }
          +
          +        static int adder1(int a, int b) {
          +            return a + b;
          +        }
          +
          +        static int multer(int x, int q, int r, int s) {
          +            return x * q * r * s;
          +        }
          +
          +        static int str(boolean b1, String s, boolean b2, int x) {
          +            return b1 && s.equals(String.valueOf(b2)) ? x : -x;
          +        }
          +
          +        static boolean comb(String s, boolean b2) {
          +            return !s.equals(b2);
          +        }
          +
          +        static String comb2(boolean b2, int x) {
          +            int ib = b2 ? 1 : 0;
          +            return ib == x ? "true" : "false";
          +        }
          +
          +        static final Class FOLD = Fold.class;
          +
          +        static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class);
          +        static final MethodType MT_adder1 = methodType(int.class, int.class, int.class);
          +        static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class);
          +        static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class);
          +        static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class);
          +        static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class);
          +
          +        static final MethodHandle MH_adder;
          +        static final MethodHandle MH_adder1;
          +        static final MethodHandle MH_multer;
          +        static final MethodHandle MH_str;
          +        static final MethodHandle MH_comb;
          +        static final MethodHandle MH_comb2;
          +
          +        static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class);
          +        static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class);
          +        static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class);
          +
          +        static {
          +            try {
          +                MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder);
          +                MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1);
          +                MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer);
          +                MH_str = LOOKUP.findStatic(FOLD, "str", MT_str);
          +                MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb);
          +                MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2);
          +            } catch (Exception e) {
          +                throw new ExceptionInInitializerError(e);
          +            }
          +        }
          +    }
          +
          +}
          diff --git a/jdk/test/java/lang/invoke/T8139885.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java
          similarity index 54%
          rename from jdk/test/java/lang/invoke/T8139885.java
          rename to jdk/test/java/lang/invoke/LoopCombinatorTest.java
          index f2fdbe7c068..191e927a59a 100644
          --- a/jdk/test/java/lang/invoke/T8139885.java
          +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java
          @@ -25,20 +25,16 @@
           
           /* @test
            * @bug 8139885
          - * @bug 8143798
          - * @bug 8150825
            * @bug 8150635
          - * @run testng/othervm -ea -esa test.java.lang.invoke.T8139885
          + * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
            */
           
           package test.java.lang.invoke;
           
          -import java.io.StringWriter;
           import java.lang.invoke.MethodHandle;
           import java.lang.invoke.MethodHandles;
           import java.lang.invoke.MethodHandles.Lookup;
           import java.lang.invoke.MethodType;
          -import java.lang.invoke.WrongMethodTypeException;
           import java.util.*;
           
           import static java.lang.invoke.MethodType.methodType;
          @@ -48,16 +44,12 @@ import static org.testng.AssertJUnit.*;
           import org.testng.annotations.*;
           
           /**
          - * Example-scale and negative tests for JEP 274 extensions.
          + * Tests for the loop combinators introduced in JEP 274.
            */
          -public class T8139885 {
          +public class LoopCombinatorTest {
           
               static final Lookup LOOKUP = MethodHandles.lookup();
           
          -    //
          -    // Tests.
          -    //
          -
               @Test
               public static void testLoopFac() throws Throwable {
                   MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
          @@ -148,10 +140,8 @@ public class T8139885 {
                   assertEquals(120, loop.invoke(new LoopWithVirtuals(), 5));
               }
           
          -    @Test
          -    public static void testLoopNegative() throws Throwable {
          -        MethodHandle mh_loop =
          -                LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class));
          +    @DataProvider
          +    static Object[][] negativeTestData() {
                   MethodHandle i0 = MethodHandles.constant(int.class, 0);
                   MethodHandle ii = MethodHandles.dropArguments(i0, 0, int.class, int.class);
                   MethodHandle id = MethodHandles.dropArguments(i0, 0, int.class, double.class);
          @@ -168,48 +158,57 @@ public class T8139885 {
                   List lvsteps = Arrays.asList(LoopWithVirtuals.MH_inc, LoopWithVirtuals.MH_mult);
                   List lvpreds = Arrays.asList(null, LoopWithVirtuals.MH_pred);
                   List lvfinis = Arrays.asList(null, LoopWithVirtuals.MH_fin);
          -        MethodHandle[][][] cases = {
          -                /*  1 */ null,
          -                /*  2 */ {},
          -                /*  3 */ {{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
          -                /*  4 */ {{null, Fac.MH_inc}, null},
          -                /*  5 */ {{Fac.MH_zero, Fac.MH_dot}},
          -                /*  6 */ {{ii}, {id}, {i3}},
          -                /*  7 */ {{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc},
          -                            {null, Counted.MH_start, null, Counted.MH_step}},
          -                /*  8 */ {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin}, {null, Fac.MH_dot}},
          -                /*  9 */ {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin}, {null, Fac.MH_dot}},
          -                /* 10 */ {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin}, {null, Fac.MH_dot}},
          -                /* 11 */ {{null, LoopWithVirtuals.MH_inc}, {LoopWithVirtuals.MH_one, LoopWithVirtuals.MH_mult, LoopWithVirtuals.MH_pred, LoopWithVirtuals.MH_fin}}
          +        return new Object[][] {
          +                {null, "null or no clauses passed"},
          +                {new MethodHandle[][]{}, "null or no clauses passed"},
          +                {new MethodHandle[][]{{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
          +                        "All loop clauses must be represented as MethodHandle arrays with at most 4 elements."},
          +                {new MethodHandle[][]{{null, Fac.MH_inc}, null}, "null clauses are not allowed"},
          +                {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_dot}},
          +                        "clause 0: init and step return types must match: int != void"},
          +                {new MethodHandle[][]{{ii}, {id}, {i3}},
          +                        "found non-effectively identical init parameter type lists: " + inits +
          +                                " (common suffix: " + ints + ")"},
          +                {new MethodHandle[][]{{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc},
          +                        {null, Counted.MH_start, null, Counted.MH_step}},
          +                        "found non-identical finalizer return types: " + finis + " (return type: int)"},
          +                {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin},
          +                        {null, Fac.MH_dot}}, "no predicate found: " + preds1},
          +                {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin},
          +                        {null, Fac.MH_dot}}, "predicates must have boolean return type: " + preds2},
          +                {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin},
          +                        {null, Fac.MH_dot}},
          +                        "found non-effectively identical parameter type lists:\nstep: " + nesteps +
          +                                "\npred: " + nepreds + "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")"},
          +                {new MethodHandle[][]{{null, LoopWithVirtuals.MH_inc},
          +                        {LoopWithVirtuals.MH_one, LoopWithVirtuals.MH_mult, LoopWithVirtuals.MH_pred, LoopWithVirtuals.MH_fin}},
          +                        "found non-effectively identical parameter type lists:\nstep: " + lvsteps +
          +                                "\npred: " + lvpreds + "\nfini: " + lvfinis + " (common parameter sequence: " + ints + ")"}
                   };
          -        String[] messages = {
          -                /*  1 */ "null or no clauses passed",
          -                /*  2 */ "null or no clauses passed",
          -                /*  3 */ "All loop clauses must be represented as MethodHandle arrays with at most 4 elements.",
          -                /*  4 */ "null clauses are not allowed",
          -                /*  5 */ "clause 0: init and step return types must match: int != void",
          -                /*  6 */ "found non-effectively identical init parameter type lists: " + inits +
          -                            " (common suffix: " + ints + ")",
          -                /*  7 */ "found non-identical finalizer return types: " + finis + " (return type: int)",
          -                /*  8 */ "no predicate found: " + preds1,
          -                /*  9 */ "predicates must have boolean return type: " + preds2,
          -                /* 10 */ "found non-effectively identical parameter type lists:\nstep: " + nesteps +
          -                            "\npred: " + nepreds + "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")",
          -                /* 11 */ "found non-effectively identical parameter type lists:\nstep: " + lvsteps +
          -                            "\npred: " + lvpreds + "\nfini: " + lvfinis + " (common parameter sequence: " + ints + ")"
          -        };
          -        for (int i = 0; i < cases.length; ++i) {
          -            boolean caught = false;
          -            try {
          -                mh_loop.invokeWithArguments(cases[i]);
          -            } catch (IllegalArgumentException iae) {
          -                assertEquals(messages[i], iae.getMessage());
          -                caught = true;
          -            }
          -            assertTrue(caught);
          +    }
          +
          +    static final MethodHandle MH_loop;
          +
          +    static {
          +        try {
          +            MH_loop = LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class));
          +        } catch (NoSuchMethodException | IllegalAccessException e) {
          +            throw new ExceptionInInitializerError(e);
                   }
               }
           
          +    @Test(dataProvider = "negativeTestData")
          +    public static void testLoopNegative(MethodHandle[][] clauses, String expectedMessage) throws Throwable {
          +        boolean caught = false;
          +        try {
          +            MH_loop.invokeWithArguments(clauses);
          +        } catch (IllegalArgumentException iae) {
          +            assertEquals(expectedMessage, iae.getMessage());
          +            caught = true;
          +        }
          +        assertTrue(caught);
          +    }
          +
               @Test
               public static void testWhileLoop() throws Throwable {
                   // int i = 0; while (i < limit) { ++i; } return i; => limit
          @@ -335,284 +334,6 @@ public class T8139885 {
                   assertTrue(caught);
               }
           
          -    @Test
          -    public static void testTryFinally() throws Throwable {
          -        MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim);
          -        assertEquals(TryFinally.MT_hello, hello.type());
          -        assertEquals("Hello, world!", hello.invoke("world"));
          -    }
          -
          -    @Test
          -    public static void testTryFinallyVoid() throws Throwable {
          -        MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore);
          -        assertEquals(TryFinally.MT_printHello, tfVoid.type());
          -        tfVoid.invoke("world");
          -    }
          -
          -    @Test
          -    public static void testTryFinallySublist() throws Throwable {
          -        MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore);
          -        assertEquals(TryFinally.MT_moreHello, helloMore.type());
          -        assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe"));
          -    }
          -
          -    @Test
          -    public static void testTryFinallyNegative() {
          -        MethodHandle intid = MethodHandles.identity(int.class);
          -        MethodHandle intco = MethodHandles.constant(int.class, 0);
          -        MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class);
          -        MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class,
          -                int.class, double.class, Object.class);
          -        MethodHandle[][] cases = {
          -                {intid, MethodHandles.identity(double.class)},
          -                {intid, MethodHandles.dropArguments(intid, 0, String.class)},
          -                {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class)},
          -                {errTarget, errCleanup},
          -                {TryFinally.MH_voidTarget, TryFinally.MH_voidCleanup}
          -        };
          -        String[] messages = {
          -                "target and return types must match: double != int",
          -                "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable",
          -                "cleanup second argument and target return type must match: (Throwable,double,int)int != int",
          -                "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
          -                        errCleanup.type() + " != " + errTarget.type(),
          -                "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
          -                        TryFinally.MH_voidCleanup.type() + " != " + TryFinally.MH_voidTarget.type()
          -        };
          -        for (int i = 0; i < cases.length; ++i) {
          -            boolean caught = false;
          -            try {
          -                MethodHandles.tryFinally(cases[i][0], cases[i][1]);
          -            } catch (IllegalArgumentException iae) {
          -                assertEquals(messages[i], iae.getMessage());
          -                caught = true;
          -            }
          -            assertTrue(caught);
          -        }
          -    }
          -
          -    @Test
          -    public static void testFold0a() throws Throwable {
          -        // equivalence to foldArguments(MethodHandle,MethodHandle)
          -        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder);
          -        assertEquals(Fold.MT_folded1, fold.type());
          -        assertEquals(720, (int) fold.invoke(3, 4, 5));
          -    }
          -
          -    @Test
          -    public static void testFold1a() throws Throwable {
          -        // test foldArguments for folding position 1
          -        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1);
          -        assertEquals(Fold.MT_folded1, fold.type());
          -        assertEquals(540, (int) fold.invoke(3, 4, 5));
          -    }
          -
          -    @Test
          -    public static void testFold0b() throws Throwable {
          -        // test foldArguments equivalence with multiple types
          -        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb);
          -        assertEquals(Fold.MT_folded2, fold.type());
          -        assertEquals(23, (int) fold.invoke("true", true, 23));
          -    }
          -
          -    @Test
          -    public static void testFold1b() throws Throwable {
          -        // test folgArguments for folding position 1, with multiple types
          -        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2);
          -        assertEquals(Fold.MT_folded3, fold.type());
          -        assertEquals(1, (int) fold.invoke(true, true, 1));
          -        assertEquals(-1, (int) fold.invoke(true, false, -1));
          -    }
          -
          -    @Test
          -    public static void testFoldArgumentsExample() throws Throwable {
          -        // test the JavaDoc foldArguments-with-pos example
          -        StringWriter swr = new StringWriter();
          -        MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr);
          -        MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class));
          -        assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
          -        MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace);
          -        assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          -        assertEquals("jum", swr.toString());
          -    }
          -
          -    @Test
          -    public static void testAsSpreader() throws Throwable {
          -        MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3);
          -        assertEquals(SpreadCollect.MT_spreader, spreader.type());
          -        assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B"));
          -    }
          -
          -    @Test
          -    public static void testAsSpreaderExample() throws Throwable {
          -        // test the JavaDoc asSpreader-with-pos example
          -        MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
          -        MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
          -        Object[] ints = new Object[]{3, 9, 7, 7};
          -        Comparator cmp = (a, b) -> a - b;
          -        assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
          -        assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
          -        assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
          -    }
          -
          -    @Test
          -    public static void testAsSpreaderIllegalPos() throws Throwable {
          -        int[] illegalPos = {-7, 3, 19};
          -        int caught = 0;
          -        for (int p : illegalPos) {
          -            try {
          -                SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3);
          -            } catch (IllegalArgumentException iae) {
          -                assertEquals("bad spread position", iae.getMessage());
          -                ++caught;
          -            }
          -        }
          -        assertEquals(illegalPos.length, caught);
          -    }
          -
          -    @Test
          -    public static void testAsSpreaderIllegalMethodType() throws Throwable {
          -        MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class);
          -        boolean caught = false;
          -        try {
          -            MethodHandle s = h.asSpreader(String[].class, 1);
          -        } catch (WrongMethodTypeException wmte) {
          -            caught = true;
          -        }
          -        assertTrue(caught);
          -    }
          -
          -    @Test
          -    public static void testAsCollector() throws Throwable {
          -        MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
          -        assertEquals(SpreadCollect.MT_collector1, collector.type());
          -        assertEquals("A4B", (String) collector.invoke("A", 4, "B"));
          -        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
          -        assertEquals(SpreadCollect.MT_collector2, collector.type());
          -        assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B"));
          -        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
          -        assertEquals(SpreadCollect.MT_collector3, collector.type());
          -        assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B"));
          -    }
          -
          -    @Test
          -    public static void testAsCollectorInvokeWithArguments() throws Throwable {
          -        MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
          -        assertEquals(SpreadCollect.MT_collector1, collector.type());
          -        assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B"));
          -        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
          -        assertEquals(SpreadCollect.MT_collector2, collector.type());
          -        assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B"));
          -        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
          -        assertEquals(SpreadCollect.MT_collector3, collector.type());
          -        assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B"));
          -    }
          -
          -    @Test
          -    public static void testAsCollectorLeading() throws Throwable {
          -        MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
          -        assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
          -        assertEquals("7Q", (String) collector.invoke(7, "Q"));
          -        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
          -        assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
          -        assertEquals("78Q", (String) collector.invoke(7, 8, "Q"));
          -        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
          -        assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
          -        assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q"));
          -    }
          -
          -    @Test
          -    public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable {
          -        MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
          -        assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
          -        assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q"));
          -        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
          -        assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
          -        assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q"));
          -        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
          -        assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
          -        assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q"));
          -    }
          -
          -    @Test
          -    public static void testAsCollectorNone() throws Throwable {
          -        MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0);
          -        assertEquals(SpreadCollect.MT_collector0, collector.type());
          -        assertEquals("AB", (String) collector.invoke("A", "B"));
          -    }
          -
          -    @Test
          -    public static void testAsCollectorIllegalPos() throws Throwable {
          -        int[] illegalPos = {-1, 17};
          -        int caught = 0;
          -        for (int p : illegalPos) {
          -            try {
          -                SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0);
          -            } catch (IllegalArgumentException iae) {
          -                assertEquals("bad collect position", iae.getMessage());
          -                ++caught;
          -            }
          -        }
          -        assertEquals(illegalPos.length, caught);
          -    }
          -
          -    @Test
          -    public static void testAsCollectorExample() throws Throwable {
          -        // test the JavaDoc asCollector-with-pos example
          -        StringWriter swr = new StringWriter();
          -        MethodHandle swWrite = LOOKUP.
          -                findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).
          -                bindTo(swr);
          -        MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
          -        swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
          -        assertEquals("BC", swr.toString());
          -        swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
          -        assertEquals("BCPQRS", swr.toString());
          -        swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
          -        assertEquals("BCPQRSZ", swr.toString());
          -    }
          -
          -    @Test
          -    public static void testFindSpecial() throws Throwable {
          -        FindSpecial.C c = new FindSpecial.C();
          -        assertEquals("I1.m", c.m());
          -        MethodType t = MethodType.methodType(String.class);
          -        MethodHandle ci1m = LOOKUP.findSpecial(FindSpecial.I1.class, "m", t, FindSpecial.C.class);
          -        assertEquals("I1.m", (String) ci1m.invoke(c));
          -    }
          -
          -    @Test
          -    public static void testFindSpecialAbstract() throws Throwable {
          -        FindSpecial.C c = new FindSpecial.C();
          -        assertEquals("q", c.q());
          -        MethodType t = MethodType.methodType(String.class);
          -        boolean caught = false;
          -        try {
          -            MethodHandle ci3q = LOOKUP.findSpecial(FindSpecial.I3.class, "q", t, FindSpecial.C.class);
          -        } catch (Throwable thrown) {
          -            if (!(thrown instanceof IllegalAccessException) || !FindSpecial.ABSTRACT_ERROR.equals(thrown.getMessage())) {
          -                throw new AssertionError(thrown.getMessage(), thrown);
          -            }
          -            caught = true;
          -        }
          -        assertTrue(caught);
          -    }
          -
          -    @Test
          -    public static void testFindClassCNFE() throws Throwable {
          -        boolean caught = false;
          -        try {
          -            LOOKUP.findClass("does.not.Exist");
          -        } catch (ClassNotFoundException cnfe) {
          -            caught = true;
          -        }
          -        assertTrue(caught);
          -    }
          -
          -    //
          -    // Methods used to assemble tests.
          -    //
          -
               static class Empty {
           
                   static void f() { }
          @@ -1042,226 +763,4 @@ public class T8139885 {
           
               }
           
          -    static class TryFinally {
          -
          -        static String greet(String whom) {
          -            return "Hello, " + whom;
          -        }
          -
          -        static String exclaim(Throwable t, String r, String whom) {
          -            return r + "!";
          -        }
          -
          -        static void print(String what) {
          -            System.out.print("Hello, " + what);
          -        }
          -
          -        static void printMore(Throwable t, String what) {
          -            System.out.println("!");
          -        }
          -
          -        static String greetMore(String first, String second) {
          -            return "Hello, " + first + " and " + second;
          -        }
          -
          -        static String exclaimMore(Throwable t, String r, String first) {
          -            return r + " (but " + first + " first)!";
          -        }
          -
          -        static void voidTarget() {}
          -
          -        static void voidCleanup(Throwable t, int a) {}
          -
          -        static final Class TRY_FINALLY = TryFinally.class;
          -
          -        static final MethodType MT_greet = methodType(String.class, String.class);
          -        static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class);
          -        static final MethodType MT_print = methodType(void.class, String.class);
          -        static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class);
          -        static final MethodType MT_greetMore = methodType(String.class, String.class, String.class);
          -        static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class);
          -        static final MethodType MT_voidTarget = methodType(void.class);
          -        static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class, int.class);
          -
          -        static final MethodHandle MH_greet;
          -        static final MethodHandle MH_exclaim;
          -        static final MethodHandle MH_print;
          -        static final MethodHandle MH_printMore;
          -        static final MethodHandle MH_greetMore;
          -        static final MethodHandle MH_exclaimMore;
          -        static final MethodHandle MH_voidTarget;
          -        static final MethodHandle MH_voidCleanup;
          -
          -        static final MethodType MT_hello = methodType(String.class, String.class);
          -        static final MethodType MT_printHello = methodType(void.class, String.class);
          -        static final MethodType MT_moreHello = methodType(String.class, String.class, String.class);
          -
          -        static {
          -            try {
          -                MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet);
          -                MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim);
          -                MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print);
          -                MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore);
          -                MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore);
          -                MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore);
          -                MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget);
          -                MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup);
          -            } catch (Exception e) {
          -                throw new ExceptionInInitializerError(e);
          -            }
          -        }
          -
          -    }
          -
          -    static class Fold {
          -
          -        static int adder(int a, int b, int c) {
          -            return a + b + c;
          -        }
          -
          -        static int adder1(int a, int b) {
          -            return a + b;
          -        }
          -
          -        static int multer(int x, int q, int r, int s) {
          -            return x * q * r * s;
          -        }
          -
          -        static int str(boolean b1, String s, boolean b2, int x) {
          -            return b1 && s.equals(String.valueOf(b2)) ? x : -x;
          -        }
          -
          -        static boolean comb(String s, boolean b2) {
          -            return !s.equals(b2);
          -        }
          -
          -        static String comb2(boolean b2, int x) {
          -            int ib = b2 ? 1 : 0;
          -            return ib == x ? "true" : "false";
          -        }
          -
          -        static final Class FOLD = Fold.class;
          -
          -        static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class);
          -        static final MethodType MT_adder1 = methodType(int.class, int.class, int.class);
          -        static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class);
          -        static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class);
          -        static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class);
          -        static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class);
          -
          -        static final MethodHandle MH_adder;
          -        static final MethodHandle MH_adder1;
          -        static final MethodHandle MH_multer;
          -        static final MethodHandle MH_str;
          -        static final MethodHandle MH_comb;
          -        static final MethodHandle MH_comb2;
          -
          -        static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class);
          -        static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class);
          -        static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class);
          -
          -        static {
          -            try {
          -                MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder);
          -                MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1);
          -                MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer);
          -                MH_str = LOOKUP.findStatic(FOLD, "str", MT_str);
          -                MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb);
          -                MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2);
          -            } catch (Exception e) {
          -                throw new ExceptionInInitializerError(e);
          -            }
          -        }
          -    }
          -
          -    static class SpreadCollect {
          -
          -        static String forSpreading(String s1, int i1, int i2, int i3, String s2) {
          -            return s1 + i1 + i2 + i3 + s2;
          -        }
          -
          -        static String forCollecting(String s1, int[] is, String s2) {
          -            StringBuilder sb = new StringBuilder(s1);
          -            for (int i : is) {
          -                sb.append(i);
          -            }
          -            return sb.append(s2).toString();
          -        }
          -
          -        static String forCollectingLeading(int[] is, String s) {
          -            return forCollecting("", is, s);
          -        }
          -
          -        static final Class SPREAD_COLLECT = SpreadCollect.class;
          -
          -        static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
          -        static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class);
          -        static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class);
          -
          -        static final MethodHandle MH_forSpreading;
          -        static final MethodHandle MH_forCollecting;
          -        static final MethodHandle MH_forCollectingLeading;
          -
          -        static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class);
          -        static final MethodType MT_collector0 = methodType(String.class, String.class, String.class);
          -        static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class);
          -        static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class);
          -        static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
          -        static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class);
          -        static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class);
          -        static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class);
          -
          -        static final String NONE_ERROR = "zero array length in MethodHandle.asCollector";
          -
          -        static {
          -            try {
          -                MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading);
          -                MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting);
          -                MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading);
          -            } catch (Exception e) {
          -                throw new ExceptionInInitializerError(e);
          -            }
          -        }
          -
          -    }
          -
          -    static class FindSpecial {
          -
          -        interface I1 {
          -            default String m() {
          -                return "I1.m";
          -            }
          -        }
          -
          -        interface I2 {
          -            default String m() {
          -                return "I2.m";
          -            }
          -        }
          -
          -        interface I3 {
          -            String q();
          -        }
          -
          -        static class C implements I1, I2, I3 {
          -            public String m() {
          -                return I1.super.m();
          -            }
          -            public String q() {
          -                return "q";
          -            }
          -        }
          -
          -        static final String ABSTRACT_ERROR = "no such method: test.java.lang.invoke.T8139885$FindSpecial$I3.q()String/invokeSpecial";
          -
          -    }
          -
          -    //
          -    // Auxiliary methods.
          -    //
          -
          -    static MethodHandle[] mha(MethodHandle... mhs) {
          -        return mhs;
          -    }
          -
           }
          diff --git a/jdk/test/java/lang/invoke/SpreadCollectTest.java b/jdk/test/java/lang/invoke/SpreadCollectTest.java
          new file mode 100644
          index 00000000000..d6644543081
          --- /dev/null
          +++ b/jdk/test/java/lang/invoke/SpreadCollectTest.java
          @@ -0,0 +1,240 @@
          +/*
          + * Copyright (c) 2015, 2016, 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.
          + */
          +
          +/* @test
          + * @bug 8139885
          + * @bug 8143798
          + * @run testng/othervm -ea -esa test.java.lang.invoke.SpreadCollectTest
          + */
          +
          +package test.java.lang.invoke;
          +
          +import java.io.StringWriter;
          +import java.lang.invoke.MethodHandle;
          +import java.lang.invoke.MethodHandles;
          +import java.lang.invoke.MethodHandles.Lookup;
          +import java.lang.invoke.MethodType;
          +import java.lang.invoke.WrongMethodTypeException;
          +import java.util.*;
          +
          +import static java.lang.invoke.MethodType.methodType;
          +
          +import static org.testng.AssertJUnit.*;
          +
          +import org.testng.annotations.*;
          +
          +/**
          + * Tests for the new asSpreader/asCollector API added in JEP 274.
          + */
          +public class SpreadCollectTest {
          +
          +    static final Lookup LOOKUP = MethodHandles.lookup();
          +
          +    @Test
          +    public static void testAsSpreader() throws Throwable {
          +        MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3);
          +        assertEquals(SpreadCollect.MT_spreader, spreader.type());
          +        assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B"));
          +    }
          +
          +    @Test
          +    public static void testAsSpreaderExample() throws Throwable {
          +        // test the JavaDoc asSpreader-with-pos example
          +        MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
          +        MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
          +        Object[] ints = new Object[]{3, 9, 7, 7};
          +        Comparator cmp = (a, b) -> a - b;
          +        assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
          +        assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
          +        assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
          +    }
          +
          +    @DataProvider
          +    static Object[][] asSpreaderIllegalPositions() {
          +        return new Object[][]{{-7}, {3}, {19}};
          +    }
          +
          +    @Test(dataProvider = "asSpreaderIllegalPositions")
          +    public static void testAsSpreaderIllegalPos(int p) throws Throwable {
          +        boolean caught = false;
          +        try {
          +            SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3);
          +        } catch (IllegalArgumentException iae) {
          +            assertEquals("bad spread position", iae.getMessage());
          +            caught = true;
          +        }
          +        assertTrue(caught);
          +    }
          +
          +    @Test(expectedExceptions = {WrongMethodTypeException.class})
          +    public static void testAsSpreaderIllegalMethodType() {
          +        MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class);
          +        MethodHandle s = h.asSpreader(String[].class, 1);
          +    }
          +
          +    @Test
          +    public static void testAsCollector() throws Throwable {
          +        MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
          +        assertEquals(SpreadCollect.MT_collector1, collector.type());
          +        assertEquals("A4B", (String) collector.invoke("A", 4, "B"));
          +        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
          +        assertEquals(SpreadCollect.MT_collector2, collector.type());
          +        assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B"));
          +        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
          +        assertEquals(SpreadCollect.MT_collector3, collector.type());
          +        assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B"));
          +    }
          +
          +    @Test
          +    public static void testAsCollectorInvokeWithArguments() throws Throwable {
          +        MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
          +        assertEquals(SpreadCollect.MT_collector1, collector.type());
          +        assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B"));
          +        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
          +        assertEquals(SpreadCollect.MT_collector2, collector.type());
          +        assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B"));
          +        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
          +        assertEquals(SpreadCollect.MT_collector3, collector.type());
          +        assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B"));
          +    }
          +
          +    @Test
          +    public static void testAsCollectorLeading() throws Throwable {
          +        MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
          +        assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
          +        assertEquals("7Q", (String) collector.invoke(7, "Q"));
          +        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
          +        assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
          +        assertEquals("78Q", (String) collector.invoke(7, 8, "Q"));
          +        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
          +        assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
          +        assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q"));
          +    }
          +
          +    @Test
          +    public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable {
          +        MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
          +        assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
          +        assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q"));
          +        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
          +        assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
          +        assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q"));
          +        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
          +        assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
          +        assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q"));
          +    }
          +
          +    @Test
          +    public static void testAsCollectorNone() throws Throwable {
          +        MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0);
          +        assertEquals(SpreadCollect.MT_collector0, collector.type());
          +        assertEquals("AB", (String) collector.invoke("A", "B"));
          +    }
          +
          +    @DataProvider
          +    static Object[][] asCollectorIllegalPositions() {
          +        return new Object[][]{{-1}, {17}};
          +    }
          +
          +    @Test(dataProvider = "asCollectorIllegalPositions")
          +    public static void testAsCollectorIllegalPos(int p) {
          +        boolean caught = false;
          +        try {
          +            SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0);
          +        } catch (IllegalArgumentException iae) {
          +            assertEquals("bad collect position", iae.getMessage());
          +            caught = true;
          +        }
          +        assertTrue(caught);
          +    }
          +
          +    @Test
          +    public static void testAsCollectorExample() throws Throwable {
          +        // test the JavaDoc asCollector-with-pos example
          +        StringWriter swr = new StringWriter();
          +        MethodHandle swWrite = LOOKUP.
          +                findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).
          +                bindTo(swr);
          +        MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
          +        swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
          +        assertEquals("BC", swr.toString());
          +        swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
          +        assertEquals("BCPQRS", swr.toString());
          +        swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
          +        assertEquals("BCPQRSZ", swr.toString());
          +    }
          +
          +    static class SpreadCollect {
          +
          +        static String forSpreading(String s1, int i1, int i2, int i3, String s2) {
          +            return s1 + i1 + i2 + i3 + s2;
          +        }
          +
          +        static String forCollecting(String s1, int[] is, String s2) {
          +            StringBuilder sb = new StringBuilder(s1);
          +            for (int i : is) {
          +                sb.append(i);
          +            }
          +            return sb.append(s2).toString();
          +        }
          +
          +        static String forCollectingLeading(int[] is, String s) {
          +            return forCollecting("", is, s);
          +        }
          +
          +        static final Class SPREAD_COLLECT = SpreadCollect.class;
          +
          +        static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
          +        static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class);
          +        static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class);
          +
          +        static final MethodHandle MH_forSpreading;
          +        static final MethodHandle MH_forCollecting;
          +        static final MethodHandle MH_forCollectingLeading;
          +
          +        static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class);
          +        static final MethodType MT_collector0 = methodType(String.class, String.class, String.class);
          +        static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class);
          +        static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class);
          +        static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
          +        static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class);
          +        static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class);
          +        static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class);
          +
          +        static final String NONE_ERROR = "zero array length in MethodHandle.asCollector";
          +
          +        static {
          +            try {
          +                MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading);
          +                MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting);
          +                MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading);
          +            } catch (Exception e) {
          +                throw new ExceptionInInitializerError(e);
          +            }
          +        }
          +
          +    }
          +
          +}
          diff --git a/jdk/test/java/lang/invoke/TryFinallyTest.java b/jdk/test/java/lang/invoke/TryFinallyTest.java
          new file mode 100644
          index 00000000000..efbadeff920
          --- /dev/null
          +++ b/jdk/test/java/lang/invoke/TryFinallyTest.java
          @@ -0,0 +1,179 @@
          +/*
          + * Copyright (c) 2015, 2016, 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.
          + */
          +
          +/* @test
          + * @bug 8139885
          + * @bug 8150825
          + * @run testng/othervm -ea -esa test.java.lang.invoke.TryFinallyTest
          + */
          +
          +package test.java.lang.invoke;
          +
          +import java.lang.invoke.MethodHandle;
          +import java.lang.invoke.MethodHandles;
          +import java.lang.invoke.MethodHandles.Lookup;
          +import java.lang.invoke.MethodType;
          +
          +import static java.lang.invoke.MethodType.methodType;
          +
          +import static org.testng.AssertJUnit.*;
          +
          +import org.testng.annotations.*;
          +
          +/**
          + * Tests for the tryFinally method handle combinator introduced in JEP 274.
          + */
          +public class TryFinallyTest {
          +
          +    static final Lookup LOOKUP = MethodHandles.lookup();
          +
          +    @Test
          +    public static void testTryFinally() throws Throwable {
          +        MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim);
          +        assertEquals(TryFinally.MT_hello, hello.type());
          +        assertEquals("Hello, world!", hello.invoke("world"));
          +    }
          +
          +    @Test
          +    public static void testTryFinallyVoid() throws Throwable {
          +        MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore);
          +        assertEquals(TryFinally.MT_printHello, tfVoid.type());
          +        tfVoid.invoke("world");
          +    }
          +
          +    @Test
          +    public static void testTryFinallySublist() throws Throwable {
          +        MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore);
          +        assertEquals(TryFinally.MT_moreHello, helloMore.type());
          +        assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe"));
          +    }
          +
          +    @DataProvider
          +    static Object[][] negativeTestData() {
          +        MethodHandle intid = MethodHandles.identity(int.class);
          +        MethodHandle intco = MethodHandles.constant(int.class, 0);
          +        MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class);
          +        MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class,
          +                int.class, double.class, Object.class);
          +        return new Object[][]{
          +                {intid, MethodHandles.identity(double.class),
          +                        "target and return types must match: double != int"},
          +                {intid, MethodHandles.dropArguments(intid, 0, String.class),
          +                        "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable"},
          +                {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class),
          +                        "cleanup second argument and target return type must match: (Throwable,double,int)int != int"},
          +                {errTarget, errCleanup,
          +                        "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
          +                                errCleanup.type() + " != " + errTarget.type()},
          +                {TryFinally.MH_voidTarget, TryFinally.MH_voidCleanup,
          +                        "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
          +                                TryFinally.MH_voidCleanup.type() + " != " + TryFinally.MH_voidTarget.type()}
          +        };
          +    }
          +
          +    @Test(dataProvider = "negativeTestData")
          +    public static void testTryFinallyNegative(MethodHandle target, MethodHandle cleanup, String expectedMessage) {
          +        boolean caught = false;
          +        try {
          +            MethodHandles.tryFinally(target, cleanup);
          +        } catch (IllegalArgumentException iae) {
          +            assertEquals(expectedMessage, iae.getMessage());
          +            caught = true;
          +        }
          +        assertTrue(caught);
          +    }
          +
          +    static class TryFinally {
          +
          +        static String greet(String whom) {
          +            return "Hello, " + whom;
          +        }
          +
          +        static String exclaim(Throwable t, String r, String whom) {
          +            return r + "!";
          +        }
          +
          +        static void print(String what) {
          +            System.out.print("Hello, " + what);
          +        }
          +
          +        static void printMore(Throwable t, String what) {
          +            System.out.println("!");
          +        }
          +
          +        static String greetMore(String first, String second) {
          +            return "Hello, " + first + " and " + second;
          +        }
          +
          +        static String exclaimMore(Throwable t, String r, String first) {
          +            return r + " (but " + first + " first)!";
          +        }
          +
          +        static void voidTarget() {}
          +
          +        static void voidCleanup(Throwable t, int a) {}
          +
          +        static final Class TRY_FINALLY = TryFinally.class;
          +
          +        static final MethodType MT_greet = methodType(String.class, String.class);
          +        static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class);
          +        static final MethodType MT_print = methodType(void.class, String.class);
          +        static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class);
          +        static final MethodType MT_greetMore = methodType(String.class, String.class, String.class);
          +        static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class);
          +        static final MethodType MT_voidTarget = methodType(void.class);
          +        static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class, int.class);
          +
          +        static final MethodHandle MH_greet;
          +        static final MethodHandle MH_exclaim;
          +        static final MethodHandle MH_print;
          +        static final MethodHandle MH_printMore;
          +        static final MethodHandle MH_greetMore;
          +        static final MethodHandle MH_exclaimMore;
          +        static final MethodHandle MH_voidTarget;
          +        static final MethodHandle MH_voidCleanup;
          +
          +        static final MethodType MT_hello = methodType(String.class, String.class);
          +        static final MethodType MT_printHello = methodType(void.class, String.class);
          +        static final MethodType MT_moreHello = methodType(String.class, String.class, String.class);
          +
          +        static {
          +            try {
          +                MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet);
          +                MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim);
          +                MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print);
          +                MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore);
          +                MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore);
          +                MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore);
          +                MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget);
          +                MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup);
          +            } catch (Exception e) {
          +                throw new ExceptionInInitializerError(e);
          +            }
          +        }
          +
          +    }
          +
          +}
          
          From 2255be0267ea036750587e2b9aef11e37d25eace Mon Sep 17 00:00:00 2001
          From: Mikael Vidstedt 
          Date: Wed, 2 Mar 2016 13:21:20 -0800
          Subject: [PATCH 192/311] 8149596: Remove java.nio.Bits copy wrapper methods
          
          Reviewed-by: bpb, chegar, psandoz
          ---
           .../share/classes/java/nio/Bits.java          | 193 ------------------
           .../java/nio/Direct-X-Buffer.java.template    |  40 ++--
           2 files changed, 25 insertions(+), 208 deletions(-)
          
          diff --git a/jdk/src/java.base/share/classes/java/nio/Bits.java b/jdk/src/java.base/share/classes/java/nio/Bits.java
          index ea4ba276e88..2b8e8baa49c 100644
          --- a/jdk/src/java.base/share/classes/java/nio/Bits.java
          +++ b/jdk/src/java.base/share/classes/java/nio/Bits.java
          @@ -736,202 +736,9 @@ class Bits {                            // package-private
                   });
               }
           
          -    // -- Bulk get/put acceleration --
          -
               // These numbers represent the point at which we have empirically
               // determined that the average cost of a JNI call exceeds the expense
               // of an element by element copy.  These numbers may change over time.
               static final int JNI_COPY_TO_ARRAY_THRESHOLD   = 6;
               static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
          -
          -    // This number limits the number of bytes to copy per call to Unsafe's
          -    // copyMemory method. A limit is imposed to allow for safepoint polling
          -    // during a large copy
          -    static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
          -
          -    // These methods do no bounds checking.  Verification that the copy will not
          -    // result in memory corruption should be done prior to invocation.
          -    // All positions and lengths are specified in bytes.
          -
          -    /**
          -     * Copy from given source array to destination address.
          -     *
          -     * @param   src
          -     *          source array
          -     * @param   srcBaseOffset
          -     *          offset of first element of storage in source array
          -     * @param   srcPos
          -     *          offset within source array of the first element to read
          -     * @param   dstAddr
          -     *          destination address
          -     * @param   length
          -     *          number of bytes to copy
          -     */
          -    static void copyFromArray(Object src, long srcBaseOffset, long srcPos,
          -                              long dstAddr, long length)
          -    {
          -        long offset = srcBaseOffset + srcPos;
          -        while (length > 0) {
          -            long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
          -            unsafe.copyMemory(src, offset, null, dstAddr, size);
          -            length -= size;
          -            offset += size;
          -            dstAddr += size;
          -        }
          -    }
          -
          -    /**
          -     * Copy from source address into given destination array.
          -     *
          -     * @param   srcAddr
          -     *          source address
          -     * @param   dst
          -     *          destination array
          -     * @param   dstBaseOffset
          -     *          offset of first element of storage in destination array
          -     * @param   dstPos
          -     *          offset within destination array of the first element to write
          -     * @param   length
          -     *          number of bytes to copy
          -     */
          -    static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos,
          -                            long length)
          -    {
          -        long offset = dstBaseOffset + dstPos;
          -        while (length > 0) {
          -            long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
          -            unsafe.copyMemory(null, srcAddr, dst, offset, size);
          -            length -= size;
          -            srcAddr += size;
          -            offset += size;
          -        }
          -    }
          -
          -    /**
          -     * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
          -     *
          -     * @param src
          -     *        the source array, must be a 16-bit primitive array type
          -     * @param srcPos
          -     *        byte offset within source array of the first element to read
          -     * @param dstAddr
          -     *        destination address
          -     * @param length
          -     *        number of bytes to copy
          -     */
          -    static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) {
          -        unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
          -    }
          -
          -    /**
          -     * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
          -     *
          -     * @param srcAddr
          -     *        source address
          -     * @param dst
          -     *        destination array, must be a 16-bit primitive array type
          -     * @param dstPos
          -     *        byte offset within the destination array of the first element to write
          -     * @param length
          -     *        number of bytes to copy
          -     */
          -    static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) {
          -        unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
          -    }
          -
          -    /**
          -     * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
          -     *
          -     * @param src
          -     *        the source array, must be a 16-bit primitive array type
          -     * @param srcPos
          -     *        byte offset within source array of the first element to read
          -     * @param dstAddr
          -     *        destination address
          -     * @param length
          -     *        number of bytes to copy
          -     */
          -    static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) {
          -        unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
          -    }
          -
          -    /**
          -     * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
          -     *
          -     * @param srcAddr
          -     *        source address
          -     * @param dst
          -     *        destination array, must be a 16-bit primitive array type
          -     * @param dstPos
          -     *        byte offset within the destination array of the first element to write
          -     * @param length
          -     *        number of bytes to copy
          -     */
          -    static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) {
          -        unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
          -    }
          -
          -    /**
          -     * Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory
          -     *
          -     * @param src
          -     *        the source array, must be a 32-bit primitive array type
          -     * @param srcPos
          -     *        byte offset within source array of the first element to read
          -     * @param dstAddr
          -     *        destination address
          -     * @param length
          -     *        number of bytes to copy
          -     */
          -    static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) {
          -        unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4);
          -    }
          -
          -    /**
          -     * Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array
          -     *
          -     * @param srcAddr
          -     *        source address
          -     * @param dst
          -     *        destination array, must be a 32-bit primitive array type
          -     * @param dstPos
          -     *        byte offset within the destination array of the first element to write
          -     * @param length
          -     *        number of bytes to copy
          -     */
          -    static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) {
          -        unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4);
          -    }
          -
          -    /**
          -     * Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory
          -     *
          -     * @param src
          -     *        the source array, must be a 64-bit primitive array type
          -     * @param srcPos
          -     *        byte offset within source array of the first element to read
          -     * @param dstAddr
          -     *        destination address
          -     * @param length
          -     *        number of bytes to copy
          -     */
          -    static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) {
          -        unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8);
          -    }
          -
          -    /**
          -     * Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array
          -     *
          -     * @param srcAddr
          -     *        source address
          -     * @param dst
          -     *        destination array, must be a 64-bit primitive array type
          -     * @param dstPos
          -     *        byte offset within the destination array of the first element to write
          -     * @param length
          -     *        number of bytes to copy
          -     */
          -    static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) {
          -        unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8);
          -    }
           }
          diff --git a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
          index 76aa4a9c61b..40a39eb0ed9 100644
          --- a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
          +++ b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
          @@ -1,5 +1,5 @@
           /*
          - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
          + * Copyright (c) 2000, 2016, 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
          @@ -270,16 +270,22 @@ class Direct$Type$Buffer$RW$$BO$
                       if (length > rem)
                           throw new BufferUnderflowException();
           
          +            long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
           #if[!byte]
                       if (order() != ByteOrder.nativeOrder())
          -                Bits.copyTo$Memtype$Array(ix(pos), dst,
          -                                          (long)offset << $LG_BYTES_PER_VALUE$,
          -                                          (long)length << $LG_BYTES_PER_VALUE$);
          +                unsafe.copySwapMemory(null,
          +                                      ix(pos),
          +                                      dst,
          +                                      dstOffset,
          +                                      (long)length << $LG_BYTES_PER_VALUE$,
          +                                      (long)1 << $LG_BYTES_PER_VALUE$);
                       else
           #end[!byte]
          -                Bits.copyToArray(ix(pos), dst, arrayBaseOffset,
          -                                 (long)offset << $LG_BYTES_PER_VALUE$,
          -                                 (long)length << $LG_BYTES_PER_VALUE$);
          +                unsafe.copyMemory(null,
          +                                  ix(pos),
          +                                  dst,
          +                                  dstOffset,
          +                                  (long)length << $LG_BYTES_PER_VALUE$);
                       position(pos + length);
                   } else {
                       super.get(dst, offset, length);
          @@ -362,18 +368,22 @@ class Direct$Type$Buffer$RW$$BO$
                       if (length > rem)
                           throw new BufferOverflowException();
           
          +            long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
           #if[!byte]
                       if (order() != ByteOrder.nativeOrder())
          -                Bits.copyFrom$Memtype$Array(src,
          -                                            (long)offset << $LG_BYTES_PER_VALUE$,
          -                                            ix(pos),
          -                                            (long)length << $LG_BYTES_PER_VALUE$);
          +                unsafe.copySwapMemory(src,
          +                                      srcOffset,
          +                                      null,
          +                                      ix(pos),
          +                                      (long)length << $LG_BYTES_PER_VALUE$,
          +                                      (long)1 << $LG_BYTES_PER_VALUE$);
                       else
           #end[!byte]
          -                Bits.copyFromArray(src, arrayBaseOffset,
          -                                   (long)offset << $LG_BYTES_PER_VALUE$,
          -                                   ix(pos),
          -                                   (long)length << $LG_BYTES_PER_VALUE$);
          +                unsafe.copyMemory(src,
          +                                  srcOffset,
          +                                  null,
          +                                  ix(pos),
          +                                  (long)length << $LG_BYTES_PER_VALUE$);
                       position(pos + length);
                   } else {
                       super.put(src, offset, length);
          
          From 90adb4174ffc981d4497dbb280716d5184e2d119 Mon Sep 17 00:00:00 2001
          From: "Tagir F. Valeev" 
          Date: Thu, 3 Mar 2016 10:06:16 +0100
          Subject: [PATCH 193/311] 8072727: add variation of Stream.iterate() that's
           finite
          
          Reviewed-by: psandoz, briangoetz
          ---
           .../java/util/stream/DoubleStream.java        |  98 +++++++++++++++--
           .../classes/java/util/stream/IntStream.java   | 100 ++++++++++++++---
           .../classes/java/util/stream/LongStream.java  |  98 +++++++++++++++--
           .../classes/java/util/stream/Stream.java      | 101 ++++++++++++++++--
           .../classes/java/util/stream/Streams.java     |   8 --
           .../stream/DoubleStreamTestDataProvider.java  |   3 +
           .../stream/IntStreamTestDataProvider.java     |   2 +
           .../stream/LongStreamTestDataProvider.java    |   3 +
           .../util/stream/StreamTestDataProvider.java   |   2 +
           .../tests/java/util/stream/IterateTest.java   | 100 +++++++++++++++++
           10 files changed, 462 insertions(+), 53 deletions(-)
           create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java
          
          diff --git a/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java b/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java
          index 574e4f17fc7..9d25d902bb4 100644
          --- a/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java
          +++ b/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java
          @@ -1,5 +1,5 @@
           /*
          - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
          + * Copyright (c) 2012, 2016, 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
          @@ -949,24 +949,100 @@ public interface DoubleStream extends BaseStream {
                */
               public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
                   Objects.requireNonNull(f);
          -        final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
          -            double t = seed;
          +        Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE,
          +               Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
          +            double prev;
          +            boolean started;
           
                       @Override
          -            public boolean hasNext() {
          +            public boolean tryAdvance(DoubleConsumer action) {
          +                Objects.requireNonNull(action);
          +                double t;
          +                if (started)
          +                    t = f.applyAsDouble(prev);
          +                else {
          +                    t = seed;
          +                    started = true;
          +                }
          +                action.accept(prev = t);
          +                return true;
          +            }
          +        };
          +        return StreamSupport.doubleStream(spliterator, false);
          +    }
          +
          +    /**
          +     * Returns a sequential ordered {@code DoubleStream} produced by iterative
          +     * application of a function to an initial element, conditioned on
          +     * satisfying the supplied predicate.  The stream terminates as soon as
          +     * the predicate returns false.
          +     *
          +     * 

          + * {@code DoubleStream.iterate} should produce the same sequence of + * elements as produced by the corresponding for-loop: + *

          {@code
          +     *     for (double index=seed; predicate.test(index); index = f.apply(index)) {
          +     *         ...
          +     *     }
          +     * }
          + * + *

          + * The resulting sequence may be empty if the predicate does not hold on + * the seed value. Otherwise the first element will be the supplied seed + * value, the next element (if present) will be the result of applying the + * function f to the seed value, and so on iteratively until the predicate + * indicates that the stream should terminate. + * + * @param seed the initial element + * @param predicate a predicate to apply to elements to determine when the + * stream must terminate. + * @param f a function to be applied to the previous element to produce + * a new element + * @return a new sequential {@code DoubleStream} + * @since 9 + */ + public static DoubleStream iterate(double seed, DoublePredicate predicate, DoubleUnaryOperator f) { + Objects.requireNonNull(f); + Objects.requireNonNull(predicate); + Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + double prev; + boolean started, finished; + + @Override + public boolean tryAdvance(DoubleConsumer action) { + Objects.requireNonNull(action); + if (finished) + return false; + double t; + if (started) + t = f.applyAsDouble(prev); + else { + t = seed; + started = true; + } + if (!predicate.test(t)) { + finished = true; + return false; + } + action.accept(prev = t); return true; } @Override - public double nextDouble() { - double v = t; - t = f.applyAsDouble(t); - return v; + public void forEachRemaining(DoubleConsumer action) { + Objects.requireNonNull(action); + if (finished) + return; + finished = true; + double t = started ? f.applyAsDouble(prev) : seed; + while (predicate.test(t)) { + action.accept(t); + t = f.applyAsDouble(t); + } } }; - return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize( - iterator, - Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false); + return StreamSupport.doubleStream(spliterator, false); } /** diff --git a/jdk/src/java.base/share/classes/java/util/stream/IntStream.java b/jdk/src/java.base/share/classes/java/util/stream/IntStream.java index 91ddad2b2a8..115a782937f 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/IntStream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/IntStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -885,28 +885,104 @@ public interface IntStream extends BaseStream { * @param seed the initial element * @param f a function to be applied to the previous element to produce * a new element - * @return A new sequential {@code IntStream} + * @return a new sequential {@code IntStream} */ public static IntStream iterate(final int seed, final IntUnaryOperator f) { Objects.requireNonNull(f); - final PrimitiveIterator.OfInt iterator = new PrimitiveIterator.OfInt() { - int t = seed; + Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + int prev; + boolean started; @Override - public boolean hasNext() { + public boolean tryAdvance(IntConsumer action) { + Objects.requireNonNull(action); + int t; + if (started) + t = f.applyAsInt(prev); + else { + t = seed; + started = true; + } + action.accept(prev = t); + return true; + } + }; + return StreamSupport.intStream(spliterator, false); + } + + /** + * Returns a sequential ordered {@code IntStream} produced by iterative + * application of a function to an initial element, conditioned on + * satisfying the supplied predicate. The stream terminates as soon as + * the predicate returns false. + * + *

          + * {@code IntStream.iterate} should produce the same sequence of elements + * as produced by the corresponding for-loop: + *

          {@code
          +     *     for (int index=seed; predicate.test(index); index = f.apply(index)) {
          +     *         ...
          +     *     }
          +     * }
          + * + *

          + * The resulting sequence may be empty if the predicate does not hold on + * the seed value. Otherwise the first element will be the supplied seed + * value, the next element (if present) will be the result of applying the + * function f to the seed value, and so on iteratively until the predicate + * indicates that the stream should terminate. + * + * @param seed the initial element + * @param predicate a predicate to apply to elements to determine when the + * stream must terminate. + * @param f a function to be applied to the previous element to produce + * a new element + * @return a new sequential {@code IntStream} + * @since 9 + */ + public static IntStream iterate(int seed, IntPredicate predicate, IntUnaryOperator f) { + Objects.requireNonNull(f); + Objects.requireNonNull(predicate); + Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + int prev; + boolean started, finished; + + @Override + public boolean tryAdvance(IntConsumer action) { + Objects.requireNonNull(action); + if (finished) + return false; + int t; + if (started) + t = f.applyAsInt(prev); + else { + t = seed; + started = true; + } + if (!predicate.test(t)) { + finished = true; + return false; + } + action.accept(prev = t); return true; } @Override - public int nextInt() { - int v = t; - t = f.applyAsInt(t); - return v; + public void forEachRemaining(IntConsumer action) { + Objects.requireNonNull(action); + if (finished) + return; + finished = true; + int t = started ? f.applyAsInt(prev) : seed; + while (predicate.test(t)) { + action.accept(t); + t = f.applyAsInt(t); + } } }; - return StreamSupport.intStream(Spliterators.spliteratorUnknownSize( - iterator, - Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false); + return StreamSupport.intStream(spliterator, false); } /** diff --git a/jdk/src/java.base/share/classes/java/util/stream/LongStream.java b/jdk/src/java.base/share/classes/java/util/stream/LongStream.java index c1a89eb4b76..f987820c5a8 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/LongStream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/LongStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -879,24 +879,100 @@ public interface LongStream extends BaseStream { */ public static LongStream iterate(final long seed, final LongUnaryOperator f) { Objects.requireNonNull(f); - final PrimitiveIterator.OfLong iterator = new PrimitiveIterator.OfLong() { - long t = seed; + Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + long prev; + boolean started; @Override - public boolean hasNext() { + public boolean tryAdvance(LongConsumer action) { + Objects.requireNonNull(action); + long t; + if (started) + t = f.applyAsLong(prev); + else { + t = seed; + started = true; + } + action.accept(prev = t); + return true; + } + }; + return StreamSupport.longStream(spliterator, false); + } + + /** + * Returns a sequential ordered {@code LongStream} produced by iterative + * application of a function to an initial element, conditioned on + * satisfying the supplied predicate. The stream terminates as soon as + * the predicate returns false. + * + *

          + * {@code LongStream.iterate} should produce the same sequence of elements + * as produced by the corresponding for-loop: + *

          {@code
          +     *     for (long index=seed; predicate.test(index); index = f.apply(index)) {
          +     *         ...
          +     *     }
          +     * }
          + * + *

          + * The resulting sequence may be empty if the predicate does not hold on + * the seed value. Otherwise the first element will be the supplied seed + * value, the next element (if present) will be the result of applying the + * function f to the seed value, and so on iteratively until the predicate + * indicates that the stream should terminate. + * + * @param seed the initial element + * @param predicate a predicate to apply to elements to determine when the + * stream must terminate. + * @param f a function to be applied to the previous element to produce + * a new element + * @return a new sequential {@code LongStream} + * @since 9 + */ + public static LongStream iterate(long seed, LongPredicate predicate, LongUnaryOperator f) { + Objects.requireNonNull(f); + Objects.requireNonNull(predicate); + Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + long prev; + boolean started, finished; + + @Override + public boolean tryAdvance(LongConsumer action) { + Objects.requireNonNull(action); + if (finished) + return false; + long t; + if (started) + t = f.applyAsLong(prev); + else { + t = seed; + started = true; + } + if (!predicate.test(t)) { + finished = true; + return false; + } + action.accept(prev = t); return true; } @Override - public long nextLong() { - long v = t; - t = f.applyAsLong(t); - return v; + public void forEachRemaining(LongConsumer action) { + Objects.requireNonNull(action); + if (finished) + return; + finished = true; + long t = started ? f.applyAsLong(prev) : seed; + while (predicate.test(t)) { + action.accept(t); + t = f.applyAsLong(t); + } } }; - return StreamSupport.longStream(Spliterators.spliteratorUnknownSize( - iterator, - Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false); + return StreamSupport.longStream(spliterator, false); } /** diff --git a/jdk/src/java.base/share/classes/java/util/stream/Stream.java b/jdk/src/java.base/share/classes/java/util/stream/Stream.java index aef2581d0eb..1dd1d43f91d 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Stream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Stream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -29,7 +29,6 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; -import java.util.Iterator; import java.util.Objects; import java.util.Optional; import java.util.Spliterator; @@ -1185,23 +1184,103 @@ public interface Stream extends BaseStream> { */ public static Stream iterate(final T seed, final UnaryOperator f) { Objects.requireNonNull(f); - final Iterator iterator = new Iterator() { - @SuppressWarnings("unchecked") - T t = (T) Streams.NONE; + Spliterator spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE) { + T prev; + boolean started; @Override - public boolean hasNext() { + public boolean tryAdvance(Consumer action) { + Objects.requireNonNull(action); + T t; + if (started) + t = f.apply(prev); + else { + t = seed; + started = true; + } + action.accept(prev = t); + return true; + } + }; + return StreamSupport.stream(spliterator, false); + } + + /** + * Returns a sequential ordered {@code Stream} produced by iterative + * application of a function to an initial element, conditioned on + * satisfying the supplied predicate. The stream terminates as soon as + * the predicate returns false. + * + *

          + * {@code Stream.iterate} should produce the same sequence of elements as + * produced by the corresponding for-loop: + *

          {@code
          +     *     for (T index=seed; predicate.test(index); index = f.apply(index)) {
          +     *         ...
          +     *     }
          +     * }
          + * + *

          + * The resulting sequence may be empty if the predicate does not hold on + * the seed value. Otherwise the first element will be the supplied seed + * value, the next element (if present) will be the result of applying the + * function f to the seed value, and so on iteratively until the predicate + * indicates that the stream should terminate. + * + * @param the type of stream elements + * @param seed the initial element + * @param predicate a predicate to apply to elements to determine when the + * stream must terminate. + * @param f a function to be applied to the previous element to produce + * a new element + * @return a new sequential {@code Stream} + * @since 9 + */ + public static Stream iterate(T seed, Predicate predicate, UnaryOperator f) { + Objects.requireNonNull(f); + Objects.requireNonNull(predicate); + Spliterator spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE) { + T prev; + boolean started, finished; + + @Override + public boolean tryAdvance(Consumer action) { + Objects.requireNonNull(action); + if (finished) + return false; + T t; + if (started) + t = f.apply(prev); + else { + t = seed; + started = true; + } + if (!predicate.test(t)) { + prev = null; + finished = true; + return false; + } + action.accept(prev = t); return true; } @Override - public T next() { - return t = (t == Streams.NONE) ? seed : f.apply(t); + public void forEachRemaining(Consumer action) { + Objects.requireNonNull(action); + if (finished) + return; + finished = true; + T t = started ? f.apply(prev) : seed; + prev = null; + while (predicate.test(t)) { + action.accept(t); + t = f.apply(t); + } } }; - return StreamSupport.stream(Spliterators.spliteratorUnknownSize( - iterator, - Spliterator.ORDERED | Spliterator.IMMUTABLE), false); + return StreamSupport.stream(spliterator, false); } /** diff --git a/jdk/src/java.base/share/classes/java/util/stream/Streams.java b/jdk/src/java.base/share/classes/java/util/stream/Streams.java index 4023a3ea0cc..0d2c23051ff 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Streams.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Streams.java @@ -48,14 +48,6 @@ final class Streams { throw new Error("no instances"); } - /** - * An object instance representing no value, that cannot be an actual - * data element of a stream. Used when processing streams that can contain - * {@code null} elements to distinguish between a {@code null} value and no - * value. - */ - static final Object NONE = new Object(); - /** * An {@code int} range spliterator. */ diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java index d9a87bb8115..1b987485aca 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java @@ -126,6 +126,9 @@ public class DoubleStreamTestDataProvider { () -> Spliterators.spliterator(isl.iterator(), doubles.length, 0))); spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name, () -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0))); + spliterators.add(splitDescr("DoubleStream.iterate(0,x->xx+1):" + name, + () -> DoubleStream.iterate(0.0, x -> x < doubles.length, x -> x + 1.0) + .spliterator())); // Need more! } spliteratorTestData = spliterators.toArray(new Object[0][]); diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java index 945cd9580e5..9afbaf76276 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java @@ -136,6 +136,8 @@ public class IntStreamTestDataProvider { () -> IntStream.range(0, ints.length).spliterator())); spliterators.add(splitDescr("IntStream.intRangeClosed(0,l):" + name, () -> IntStream.rangeClosed(0, ints.length).spliterator())); + spliterators.add(splitDescr("IntStream.iterate(0,x->xx+1): " + name, + () -> IntStream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator())); // Need more! } spliteratorTestData = spliterators.toArray(new Object[0][]); diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java index 80b1dcc1019..17fd8185a20 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java @@ -136,6 +136,9 @@ public class LongStreamTestDataProvider { () -> LongStream.range(0, longs.length).spliterator())); spliterators.add(splitDescr("LongStream.longRangeClosed(0,l):" + name, () -> LongStream.rangeClosed(0, longs.length).spliterator())); + spliterators.add(splitDescr("LongStream.iterate(0,x->xx+1):" + name, + () -> LongStream.iterate(0L, x -> x < longs.length, x -> x + 1L) + .spliterator())); // Need more! } spliteratorTestData = spliterators.toArray(new Object[0][]); diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java index b3aa58ac842..05312b44a34 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java @@ -171,6 +171,8 @@ public class StreamTestDataProvider { () -> Spliterators.spliterator(Arrays.asList(ints).iterator(), ints.length, 0))); spliterators.add(splitDescr("Iterators.s(Arrays.s(array).iterator()):" + name, () -> Spliterators.spliteratorUnknownSize(Arrays.asList(ints).iterator(), 0))); + spliterators.add(splitDescr("Stream.iterate(0,x->xx+1): " + name, + () -> Stream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator())); // @@@ Add map and collection spliterators when spliterator() is exposed on Collection or Iterable } spliteratorTestData = spliterators.toArray(new Object[0][]); diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java new file mode 100644 index 00000000000..7843f22563f --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, 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 8072727 + */ + +package org.openjdk.tests.java.util.stream; + +import java.util.List; +import java.util.Objects; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.TestData; +import java.util.stream.TestData.Factory; + +import static java.util.stream.ThowableHelper.checkNPE; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@Test +public class IterateTest extends OpTestCase { + + @DataProvider(name = "IterateStreamsData") + public static Object[][] makeIterateStreamsTestData() { + Object[][] data = { + {List.of(), + Factory.ofSupplier("ref.empty", () -> Stream.iterate(1, x -> x < 0, x -> x * 2))}, + {List.of(1), + Factory.ofSupplier("ref.one", () -> Stream.iterate(1, x -> x < 2, x -> x * 2))}, + {List.of(1, 2, 4, 8, 16, 32, 64, 128, 256, 512), + Factory.ofSupplier("ref.ten", () -> Stream.iterate(1, x -> x < 1000, x -> x * 2))}, + {List.of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), + Factory.ofSupplier("ref.nullCheck", () -> Stream.iterate(10, Objects::nonNull, x -> x > 0 ? x - 1 : null))}, + {List.of(), + Factory.ofIntSupplier("int.empty", () -> IntStream.iterate(1, x -> x < 0, x -> x + 1))}, + {List.of(1), + Factory.ofIntSupplier("int.one", () -> IntStream.iterate(1, x -> x < 2, x -> x + 1))}, + {List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), + Factory.ofIntSupplier("int.ten", () -> IntStream.iterate(1, x -> x <= 10, x -> x + 1))}, + {List.of(5, 4, 3, 2, 1), + Factory.ofIntSupplier("int.divZero", () -> IntStream.iterate(5, x -> x != 0, x -> x - 1/x/2 - 1))}, + {List.of(), + Factory.ofLongSupplier("long.empty", () -> LongStream.iterate(1L, x -> x < 0, x -> x + 1))}, + {List.of(1L), + Factory.ofLongSupplier("long.one", () -> LongStream.iterate(1L, x -> x < 2, x -> x + 1))}, + {List.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L), + Factory.ofLongSupplier("long.ten", () -> LongStream.iterate(1L, x -> x <= 10, x -> x + 1))}, + {List.of(), + Factory.ofDoubleSupplier("double.empty", () -> DoubleStream.iterate(1.0, x -> x < 0, x -> x + 1))}, + {List.of(1.0), + Factory.ofDoubleSupplier("double.one", () -> DoubleStream.iterate(1.0, x -> x < 2, x -> x + 1))}, + {List.of(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0), + Factory.ofDoubleSupplier("double.ten", () -> DoubleStream.iterate(1.0, x -> x <= 10, x -> x + 1))} + }; + return data; + } + + @Test(dataProvider = "IterateStreamsData") + public void testIterate(List expected, TestData data) { + withData(data).stream(s -> s).expectedResult(expected).exercise(); + } + + @Test + public void testNPE() { + checkNPE(() -> Stream.iterate("", null, x -> x + "a")); + checkNPE(() -> Stream.iterate("", String::isEmpty, null)); + checkNPE(() -> IntStream.iterate(0, null, x -> x + 1)); + checkNPE(() -> IntStream.iterate(0, x -> x < 10, null)); + checkNPE(() -> LongStream.iterate(0, null, x -> x + 1)); + checkNPE(() -> LongStream.iterate(0, x -> x < 10, null)); + checkNPE(() -> DoubleStream.iterate(0, null, x -> x + 1)); + checkNPE(() -> DoubleStream.iterate(0, x -> x < 10, null)); + } +} From c880124c81c5151557e427fe6e2c23d2794048f1 Mon Sep 17 00:00:00 2001 From: "Tagir F. Valeev" Date: Thu, 3 Mar 2016 10:06:25 +0100 Subject: [PATCH 194/311] 8147505: BaseStream.onClose() should not allow registering new handlers after stream is consumed Reviewed-by: psandoz --- .../java/util/stream/AbstractPipeline.java | 4 +++- .../java/util/stream/StreamCloseTest.java | 22 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java index 84199462c80..a313b64589d 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java +++ b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -327,6 +327,8 @@ abstract class AbstractPipeline> @Override @SuppressWarnings("unchecked") public S onClose(Runnable closeHandler) { + if (linkedOrConsumed) + throw new IllegalStateException(MSG_STREAM_LINKED); Objects.requireNonNull(closeHandler); Runnable existingHandler = sourceStage.sourceCloseAction; sourceStage.sourceCloseAction = diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java index 6fd24a9816a..d20a6670dac 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -24,7 +24,7 @@ /* * @test * @summary close handlers and closing streams - * @bug 8044047 + * @bug 8044047 8147505 */ package org.openjdk.tests.java.util.stream; @@ -37,6 +37,7 @@ import org.testng.annotations.Test; import static java.util.stream.LambdaTestHelpers.countTo; import static java.util.stream.ThowableHelper.checkNPE; +import static java.util.stream.ThowableHelper.checkISE; @Test(groups = { "serialization-hostile" }) public class StreamCloseTest extends OpTestCase { @@ -170,4 +171,21 @@ public class StreamCloseTest extends OpTestCase { for (int i=0; i s = countTo(100).stream()) { + s.forEach(i -> {}); + // Adding onClose handler when stream is consumed is illegal + // handler must not be registered + checkISE(() -> s.onClose(() -> fail("1"))); + } + + // close() must be idempotent: + // second close() invoked at the end of try-with-resources must have no effect + try(Stream s = countTo(100).stream()) { + s.close(); + // Adding onClose handler when stream is closed is also illegal + checkISE(() -> s.onClose(() -> fail("3"))); + } + } } From d6208a2b4a394010b95dacdbc86577775c4756dc Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 3 Mar 2016 12:07:13 +0000 Subject: [PATCH 195/311] 8150162: Move sun.misc.Version to a truly internal package Reviewed-by: alanb, iris, mchung, rriggs --- jdk/make/gensrc/GensrcMisc.gmk | 6 +- jdk/make/mapfiles/libjava/mapfile-vers | 2 - .../share/classes/java/lang/System.java | 2 +- .../java/lang/VersionProps.java.template | 114 ++++++++ .../classes/sun/misc/Version.java.template | 268 ------------------ .../java.base/share/native/libjava/Version.c | 90 ------ jdk/src/java.base/share/native/libjli/java.c | 2 +- jdk/test/sun/misc/Version/Version.java | 139 --------- 8 files changed, 119 insertions(+), 504 deletions(-) create mode 100644 jdk/src/java.base/share/classes/java/lang/VersionProps.java.template delete mode 100644 jdk/src/java.base/share/classes/sun/misc/Version.java.template delete mode 100644 jdk/src/java.base/share/native/libjava/Version.c delete mode 100644 jdk/test/sun/misc/Version/Version.java diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk index ffefb50a5b0..a69c007cffb 100644 --- a/jdk/make/gensrc/GensrcMisc.gmk +++ b/jdk/make/gensrc/GensrcMisc.gmk @@ -25,11 +25,11 @@ ########################################################################################## # Install the launcher name, release version string, full version -# string and the runtime name into the Version.java file. +# string and the runtime name into the VersionProps.java file. $(eval $(call SetupTextFileProcessing, BUILD_VERSION_JAVA, \ - SOURCE_FILES := $(JDK_TOPDIR)/src/java.base/share/classes/sun/misc/Version.java.template, \ - OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/misc/Version.java, \ + SOURCE_FILES := $(JDK_TOPDIR)/src/java.base/share/classes/java/lang/VersionProps.java.template, \ + OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/VersionProps.java, \ REPLACEMENTS := \ @@LAUNCHER_NAME@@ => $(LAUNCHER_NAME) ; \ @@RUNTIME_NAME@@ => $(RUNTIME_NAME) ; \ diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index 9eb5782f934..ac21dd24890 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -268,8 +268,6 @@ SUNWprivate_1.1 { Java_sun_reflect_Reflection_getCallerClass__; Java_sun_reflect_Reflection_getCallerClass__I; Java_sun_reflect_Reflection_getClassAccessFlags; - Java_sun_misc_Version_getJdkVersionInfo; - Java_sun_misc_Version_getJvmVersionInfo; Java_jdk_internal_misc_VM_latestUserDefinedLoader; Java_jdk_internal_misc_VM_getuid; Java_jdk_internal_misc_VM_geteuid; diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index 3f12f08eab4..c0c7c05156a 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1830,7 +1830,7 @@ public final class System { lineSeparator = props.getProperty("line.separator"); - sun.misc.Version.init(); + VersionProps.init(); FileInputStream fdIn = new FileInputStream(FileDescriptor.in); FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); diff --git a/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template new file mode 100644 index 00000000000..dd0e038936d --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1999, 2016, 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. + */ + +package java.lang; + +import java.io.PrintStream; + +class VersionProps { + + + private static final String launcher_name = + "@@LAUNCHER_NAME@@"; + + private static final String java_version = + "@@VERSION_SHORT@@"; + + private static final String java_runtime_name = + "@@RUNTIME_NAME@@"; + + private static final String java_runtime_version = + "@@VERSION_STRING@@"; + + static { + init(); + } + + public static void init() { + System.setProperty("java.version", java_version); + System.setProperty("java.runtime.version", java_runtime_version); + System.setProperty("java.runtime.name", java_runtime_name); + } + + /** + * In case you were wondering this method is called by java -version. + * Sad that it prints to stderr; would be nicer if default printed on + * stdout. + */ + public static void print() { + print(System.err); + } + + /** + * This is the same as print except that it adds an extra line-feed + * at the end, typically used by the -showversion in the launcher + */ + public static void println() { + print(System.err); + System.err.println(); + } + + /** + * Give a stream, it will print version info on it. + */ + public static void print(PrintStream ps) { + boolean isHeadless = false; + + /* Report that we're running headless if the property is true */ + String headless = System.getProperty("java.awt.headless"); + if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) { + isHeadless = true; + } + + /* First line: platform version. */ + ps.println(launcher_name + " version \"" + java_version + "\""); + + /* Second line: runtime version (ie, libraries). */ + + String jdk_debug_level = System.getProperty("jdk.debug", "release"); + /* Debug level is not printed for "release" builds */ + if ("release".equals(jdk_debug_level)) { + jdk_debug_level = ""; + } else { + jdk_debug_level = jdk_debug_level + " "; + } + + ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version); + + if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) { + // embedded builds report headless state + ps.print(", headless"); + } + ps.println(')'); + + /* Third line: JVM information. */ + String java_vm_name = System.getProperty("java.vm.name"); + String java_vm_version = System.getProperty("java.vm.version"); + String java_vm_info = System.getProperty("java.vm.info"); + ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " + + java_vm_info + ")"); + } + +} \ No newline at end of file diff --git a/jdk/src/java.base/share/classes/sun/misc/Version.java.template b/jdk/src/java.base/share/classes/sun/misc/Version.java.template deleted file mode 100644 index 51b306a0cc4..00000000000 --- a/jdk/src/java.base/share/classes/sun/misc/Version.java.template +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 1999, 2015, 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. - */ - -package sun.misc; -import java.io.PrintStream; - -public class Version { - - - private static final String launcher_name = - "@@LAUNCHER_NAME@@"; - - private static final String java_version = - "@@VERSION_SHORT@@"; - - private static final String java_runtime_name = - "@@RUNTIME_NAME@@"; - - private static final String java_runtime_version = - "@@VERSION_STRING@@"; - - static { - init(); - } - - public static void init() { - System.setProperty("java.version", java_version); - System.setProperty("java.runtime.version", java_runtime_version); - System.setProperty("java.runtime.name", java_runtime_name); - } - - private static boolean versionsInitialized = false; - private static int jvm_major_version = 0; - private static int jvm_minor_version = 0; - private static int jvm_security_version = 0; - private static int jvm_patch_version = 0; - private static int jvm_build_number = 0; - private static int jdk_major_version = 0; - private static int jdk_minor_version = 0; - private static int jdk_security_version = 0; - private static int jdk_patch_version = 0; - private static int jdk_build_number = 0; - - /** - * In case you were wondering this method is called by java -version. - * Sad that it prints to stderr; would be nicer if default printed on - * stdout. - */ - public static void print() { - print(System.err); - } - - /** - * This is the same as print except that it adds an extra line-feed - * at the end, typically used by the -showversion in the launcher - */ - public static void println() { - print(System.err); - System.err.println(); - } - - /** - * Give a stream, it will print version info on it. - */ - public static void print(PrintStream ps) { - boolean isHeadless = false; - - /* Report that we're running headless if the property is true */ - String headless = System.getProperty("java.awt.headless"); - if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) { - isHeadless = true; - } - - /* First line: platform version. */ - ps.println(launcher_name + " version \"" + java_version + "\""); - - /* Second line: runtime version (ie, libraries). */ - - String jdk_debug_level = System.getProperty("jdk.debug", "release"); - /* Debug level is not printed for "release" builds */ - if ("release".equals(jdk_debug_level)) { - jdk_debug_level = ""; - } else { - jdk_debug_level = jdk_debug_level + " "; - } - - ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version); - - if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) { - // embedded builds report headless state - ps.print(", headless"); - } - ps.println(')'); - - /* Third line: JVM information. */ - String java_vm_name = System.getProperty("java.vm.name"); - String java_vm_version = System.getProperty("java.vm.version"); - String java_vm_info = System.getProperty("java.vm.info"); - ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " + - java_vm_info + ")"); - } - - - /** - * Returns the major version of the running JVM. - * @return the major version of the running JVM - * @since 1.6 - */ - public static synchronized int jvmMajorVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_major_version; - } - - /** - * Returns the minor version of the running JVM. - * @return the minor version of the running JVM - * @since 1.6 - */ - public static synchronized int jvmMinorVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_minor_version; - } - - - /** - * Returns the security version of the running JVM. - * @return the security version of the running JVM - * @since 9 - */ - public static synchronized int jvmSecurityVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_security_version; - } - - /** - * Returns the patch release version of the running JVM. - * @return the patch release version of the running JVM - * @since 9 - */ - public static synchronized int jvmPatchVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_patch_version; - } - - /** - * Returns the build number of the running JVM. - * @return the build number of the running JVM - * @since 1.6 - */ - public static synchronized int jvmBuildNumber() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_build_number; - } - - /** - * Returns the major version of the running JDK. - * @return the major version of the running JDK - * @since 1.6 - */ - public static synchronized int jdkMajorVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_major_version; - } - - /** - * Returns the minor version of the running JDK. - * @return the minor version of the running JDK - * @since 1.6 - */ - public static synchronized int jdkMinorVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_minor_version; - } - - /** - * Returns the security version of the running JDK. - * @return the security version of the running JDK - * @since 9 - */ - public static synchronized int jdkSecurityVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_security_version; - } - - /** - * Returns the patch release version of the running JDK. - * @return the patch release version of the running JDK - * @since 9 - */ - public static synchronized int jdkPatchVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_patch_version; - } - - /** - * Returns the build number of the running JDK. - * @return the build number of the running JDK - * @since 1.6 - */ - public static synchronized int jdkBuildNumber() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_build_number; - } - - private static synchronized void initVersions() { - if (versionsInitialized) { - return; - } - if (!getJvmVersionInfo()) { - throw new InternalError("Unable to obtain JVM version info"); - } - getJdkVersionInfo(); - versionsInitialized = true; - } - - // Gets the JVM version info if available and sets the jvm_*_version fields - // and its capabilities. - private static native boolean getJvmVersionInfo(); - private static native void getJdkVersionInfo(); -} - -// Help Emacs a little because this file doesn't end in .java. -// -// Local Variables: *** -// mode: java *** -// End: *** diff --git a/jdk/src/java.base/share/native/libjava/Version.c b/jdk/src/java.base/share/native/libjava/Version.c deleted file mode 100644 index a58e1bb3f3b..00000000000 --- a/jdk/src/java.base/share/native/libjava/Version.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2005, 2015, 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 "jni_util.h" -#include "jvm.h" -#include "jdk_util.h" - -#include "sun_misc_Version.h" - -static void setStaticIntField(JNIEnv* env, jclass cls, const char* name, jint value) -{ - jfieldID fid; - fid = (*env)->GetStaticFieldID(env, cls, name, "I"); - if (fid != 0) { - (*env)->SetStaticIntField(env, cls, fid, value); - } -} - -typedef void (JNICALL *GetJvmVersionInfo_fp)(JNIEnv*, jvm_version_info*, size_t); - -JNIEXPORT jboolean JNICALL -Java_sun_misc_Version_getJvmVersionInfo(JNIEnv *env, jclass cls) -{ - jvm_version_info info; - GetJvmVersionInfo_fp func_p; - - if (!JDK_InitJvmHandle()) { - JNU_ThrowInternalError(env, "Handle for JVM not found for symbol lookup"); - return JNI_FALSE; - } - func_p = (GetJvmVersionInfo_fp) JDK_FindJvmEntry("JVM_GetVersionInfo"); - if (func_p == NULL) { - return JNI_FALSE; - } - - (*func_p)(env, &info, sizeof(info)); - setStaticIntField(env, cls, "jvm_major_version", JVM_VERSION_MAJOR(info.jvm_version)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - setStaticIntField(env, cls, "jvm_minor_version", JVM_VERSION_MINOR(info.jvm_version)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - setStaticIntField(env, cls, "jvm_security_version", JVM_VERSION_SECURITY(info.jvm_version)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - setStaticIntField(env, cls, "jvm_build_number", JVM_VERSION_BUILD(info.jvm_version)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - setStaticIntField(env, cls, "jvm_patch_version", info.patch_version); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - - return JNI_TRUE; -} - -JNIEXPORT void JNICALL -Java_sun_misc_Version_getJdkVersionInfo(JNIEnv *env, jclass cls) -{ - jdk_version_info info; - - JDK_GetVersionInfo0(&info, sizeof(info)); - setStaticIntField(env, cls, "jdk_major_version", JDK_VERSION_MAJOR(info.jdk_version)); - JNU_CHECK_EXCEPTION(env); - setStaticIntField(env, cls, "jdk_minor_version", JDK_VERSION_MINOR(info.jdk_version)); - JNU_CHECK_EXCEPTION(env); - setStaticIntField(env, cls, "jdk_security_version", JDK_VERSION_SECURITY(info.jdk_version)); - JNU_CHECK_EXCEPTION(env); - setStaticIntField(env, cls, "jdk_build_number", JDK_VERSION_BUILD(info.jdk_version)); - JNU_CHECK_EXCEPTION(env); - setStaticIntField(env, cls, "jdk_patch_version", info.patch_version); - JNU_CHECK_EXCEPTION(env); -} diff --git a/jdk/src/java.base/share/native/libjli/java.c b/jdk/src/java.base/share/native/libjli/java.c index 9c7b27052ac..41e0e21f14b 100644 --- a/jdk/src/java.base/share/native/libjli/java.c +++ b/jdk/src/java.base/share/native/libjli/java.c @@ -1470,7 +1470,7 @@ PrintJavaVersion(JNIEnv *env, jboolean extraLF) jclass ver; jmethodID print; - NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version")); + NULL_CHECK(ver = FindBootStrapClass(env, "java/lang/VersionProps")); NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, (extraLF == JNI_TRUE) ? "println" : "print", diff --git a/jdk/test/sun/misc/Version/Version.java b/jdk/test/sun/misc/Version/Version.java deleted file mode 100644 index a2b11242bfc..00000000000 --- a/jdk/test/sun/misc/Version/Version.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2010, 2015, 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 6994413 8134365 - * @summary Check the JDK and JVM version returned by sun.misc.Version - * matches the versions defined in the system properties. - * Should use the API described in JDK-8136651 when available - * @modules java.base/sun.misc - * @compile -XDignore.symbol.file Version.java - * @run main Version - */ - -import static sun.misc.Version.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class Version { - - public static void main(String[] args) throws Exception { - VersionInfo jdk = newVersionInfo(System.getProperty("java.runtime.version")); - VersionInfo v1 = new VersionInfo(jdkMajorVersion(), - jdkMinorVersion(), - jdkSecurityVersion(), - jdkPatchVersion(), - jdkBuildNumber()); - System.out.println("JDK version = " + jdk + " " + v1); - if (!jdk.equals(v1)) { - throw new RuntimeException("Unmatched version: " + jdk + " vs " + v1); - } - VersionInfo jvm = newVersionInfo(System.getProperty("java.vm.version")); - VersionInfo v2 = new VersionInfo(jvmMajorVersion(), - jvmMinorVersion(), - jvmSecurityVersion(), - jvmPatchVersion(), - jvmBuildNumber()); - System.out.println("JVM version = " + jvm + " " + v2); - if (!jvm.equals(v2)) { - throw new RuntimeException("Unmatched version: " + jvm + " vs " + v2); - } - } - - static class VersionInfo { - final int major; - final int minor; - final int security; - final int patch; - final int build; - VersionInfo(int major, int minor, int security, - int patch, int build) { - this.major = major; - this.minor = minor; - this.security = security; - this.patch = patch; - this.build = build; - } - - VersionInfo(int[] fields) { - this.major = fields[0]; - this.minor = fields[1]; - this.security = fields[2]; - this.patch = fields[3]; - this.build = fields[4]; - } - - public boolean equals(VersionInfo v) { - return (this.major == v.major && this.minor == v.minor && - this.security == v.security && this.patch == v.patch && - this.build == v.build); - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - // Do not include trailing zeros - if (patch > 0) { - sb.insert(0, "." + patch); - } - if (security > 0 || sb.length() > 0) { - sb.insert(0, "." + security); - } - if (minor > 0 || sb.length() > 0) { - sb.insert(0, "." + minor); - } - sb.insert(0, major); - - if (build >= 0) - sb.append("+" + build); - - return sb.toString(); - } - } - - private static VersionInfo newVersionInfo(String version) throws Exception { - // Version string fromat as defined by JEP-223 - String jep223Pattern = - "^([0-9]+)(\\.([0-9]+))?(\\.([0-9]+))?(\\.([0-9]+))?" + // $VNUM - "(-([a-zA-Z]+))?(\\.([a-zA-Z]+))?" + // $PRE - "(\\+([0-9]+))?" + // Build Number - "(([-a-zA-Z0-9.]+))?$"; // $OPT - - // Pattern group index for: Major, Minor, Security, Patch, Build - int[] groups = {1, 3, 5, 7, 13}; - // Default values for Major, Minor, Security, Patch, Build - int[] versionFields = {0, 0, 0, 0, 0}; - - Pattern pattern = Pattern.compile(jep223Pattern); - Matcher matcher = pattern.matcher(version); - if (matcher.matches()) { - for (int i = 0; i < versionFields.length; i++) { - String field = matcher.group(groups[i]); - versionFields[i] = (field != null) ? Integer.parseInt(field) : 0; - } - } - - VersionInfo vi = new VersionInfo(versionFields); - System.out.printf("newVersionInfo: input=%s output=%s\n", version, vi); - return vi; - } -} From 622963bd4d756fe4b8a0c0c293896d7c0190acf2 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 3 Mar 2016 12:07:45 +0000 Subject: [PATCH 196/311] 8151140: Replace use of lambda/method ref in jdk.Version constructor Reviewed-by: psandoz --- jdk/src/java.base/share/classes/jdk/Version.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/Version.java b/jdk/src/java.base/share/classes/jdk/Version.java index 9ce9ec9314d..75c6b35c444 100644 --- a/jdk/src/java.base/share/classes/jdk/Version.java +++ b/jdk/src/java.base/share/classes/jdk/Version.java @@ -28,10 +28,10 @@ package jdk; import java.math.BigInteger; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -208,11 +208,10 @@ public final class Version + s + "'"); // $VNUM is a dot-separated list of integers of arbitrary length - version - = Collections.unmodifiableList( - Arrays.stream(m.group(VNUM_GROUP).split("\\.")) - .map(Integer::parseInt) - .collect(Collectors.toList())); + List list = new ArrayList<>(); + for (String i : m.group(VNUM_GROUP).split("\\.")) + list.add(Integer.parseInt(i)); + version = Collections.unmodifiableList(list); pre = Optional.ofNullable(m.group(PRE_GROUP)); From da0ba02676b04509364fd0f24cf4f3d26b1d88ef Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Thu, 3 Mar 2016 14:29:00 +0100 Subject: [PATCH 197/311] 8150957: j.l.i.MethodHandles.whileLoop(...) fails with IOOBE in the case init is null, step and pred have parameters Reviewed-by: psandoz --- .../java/lang/invoke/LoopCombinatorTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 191e927a59a..2bae77e6a2e 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -233,6 +233,16 @@ public class LoopCombinatorTest { assertEquals(23, loop.invoke(23)); } + @Test + public static void testDoWhileNullInit() throws Throwable { + While w = new While(); + int v = 5; + MethodHandle loop = MethodHandles.doWhileLoop(null, While.MH_voidBody.bindTo(w), While.MH_voidPred.bindTo(w)); + assertEquals(While.MT_void, loop.type()); + loop.invoke(v); + assertEquals(v, w.i); + } + @Test public static void testWhileZip() throws Throwable { MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred); @@ -243,6 +253,16 @@ public class LoopCombinatorTest { assertEquals(zipped, (List) loop.invoke(a.iterator(), b.iterator())); } + @Test + public static void testWhileNullInit() throws Throwable { + While w = new While(); + int v = 5; + MethodHandle loop = MethodHandles.whileLoop(null, While.MH_voidPred.bindTo(w), While.MH_voidBody.bindTo(w)); + assertEquals(While.MT_void, loop.type()); + loop.invoke(v); + assertEquals(v, w.i); + } + @Test public static void testCountedLoop() throws Throwable { // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme @@ -568,6 +588,16 @@ public class LoopCombinatorTest { return zip; } + private int i = 0; + + void voidBody(int k) { + ++i; + } + + boolean voidPred(int k) { + return i < k; + } + static final Class WHILE = While.class; static final MethodType MT_zero = methodType(int.class, int.class); @@ -579,6 +609,8 @@ public class LoopCombinatorTest { static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class); static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class); static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class); + static final MethodType MT_voidBody = methodType(void.class, int.class); + static final MethodType MT_voidPred = methodType(boolean.class, int.class); static final MethodHandle MH_zero; static final MethodHandle MH_pred; @@ -589,10 +621,13 @@ public class LoopCombinatorTest { static final MethodHandle MH_zipInitZip; static final MethodHandle MH_zipPred; static final MethodHandle MH_zipStep; + static final MethodHandle MH_voidBody; + static final MethodHandle MH_voidPred; static final MethodType MT_while = methodType(int.class, int.class); static final MethodType MT_string = methodType(String.class); static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class); + static final MethodType MT_void = methodType(void.class, int.class); static { try { @@ -605,6 +640,8 @@ public class LoopCombinatorTest { MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip); MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred); MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep); + MH_voidBody = LOOKUP.findVirtual(WHILE, "voidBody", MT_voidBody); + MH_voidPred = LOOKUP.findVirtual(WHILE, "voidPred", MT_voidPred); } catch (Exception e) { throw new ExceptionInInitializerError(e); } From 96f1a8250d2546ff594147db31163f8e2492f62f Mon Sep 17 00:00:00 2001 From: Vyom Tewari Date: Thu, 3 Mar 2016 17:21:08 +0000 Subject: [PATCH 198/311] 8148609: socket impl supportedOptions() should return an immutable set Reviewed-by: alanb, chegar --- .../classes/java/net/DatagramSocketImpl.java | 34 ++-- .../share/classes/java/net/SocketImpl.java | 32 ++- .../net/SocketOption/ImmutableOptions.java | 184 ++++++++++++++++++ 3 files changed, 215 insertions(+), 35 deletions(-) create mode 100644 jdk/test/java/net/SocketOption/ImmutableOptions.java diff --git a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java index 5621ea3a608..98f06833f9c 100644 --- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java @@ -27,9 +27,7 @@ package java.net; import java.io.FileDescriptor; import java.io.IOException; -import java.io.InterruptedIOException; import java.util.Set; -import java.util.HashSet; /** * Abstract datagram and multicast socket implementation base class. @@ -352,32 +350,32 @@ public abstract class DatagramSocketImpl implements SocketOptions { } } - private static final Set> dgSocketOptions = - new HashSet<>(); + private static final Set> dgSocketOptions; - private static final Set> mcSocketOptions = - new HashSet<>(); + private static final Set> mcSocketOptions; static { - dgSocketOptions.add(StandardSocketOptions.SO_SNDBUF); - dgSocketOptions.add(StandardSocketOptions.SO_RCVBUF); - dgSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); - dgSocketOptions.add(StandardSocketOptions.IP_TOS); + dgSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF, + StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.IP_TOS); - mcSocketOptions.add(StandardSocketOptions.SO_SNDBUF); - mcSocketOptions.add(StandardSocketOptions.SO_RCVBUF); - mcSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); - mcSocketOptions.add(StandardSocketOptions.IP_TOS); - mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_IF); - mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL); - mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP); - }; + mcSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF, + StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.IP_TOS, + StandardSocketOptions.IP_MULTICAST_IF, + StandardSocketOptions.IP_MULTICAST_TTL, + StandardSocketOptions.IP_MULTICAST_LOOP); + } /** * Returns a set of SocketOptions supported by this impl * and by this impl's socket (DatagramSocket or MulticastSocket) * * @return a Set of SocketOptions + * + * @since 9 */ protected Set> supportedOptions() { if (getDatagramSocket() instanceof MulticastSocket) { diff --git a/jdk/src/java.base/share/classes/java/net/SocketImpl.java b/jdk/src/java.base/share/classes/java/net/SocketImpl.java index 7a30173a597..60fe083445a 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java @@ -30,8 +30,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.FileDescriptor; import java.util.Set; -import java.util.HashSet; -import java.util.Collections; /** * The abstract class {@code SocketImpl} is a common superclass @@ -445,31 +443,31 @@ public abstract class SocketImpl implements SocketOptions { } } - private static final Set> socketOptions = - new HashSet<>(); + private static final Set> socketOptions; - private static final Set> serverSocketOptions = - new HashSet<>(); + private static final Set> serverSocketOptions; static { - socketOptions.add(StandardSocketOptions.SO_KEEPALIVE); - socketOptions.add(StandardSocketOptions.SO_SNDBUF); - socketOptions.add(StandardSocketOptions.SO_RCVBUF); - socketOptions.add(StandardSocketOptions.SO_REUSEADDR); - socketOptions.add(StandardSocketOptions.SO_LINGER); - socketOptions.add(StandardSocketOptions.IP_TOS); - socketOptions.add(StandardSocketOptions.TCP_NODELAY); + socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE, + StandardSocketOptions.SO_SNDBUF, + StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.SO_LINGER, + StandardSocketOptions.IP_TOS, + StandardSocketOptions.TCP_NODELAY); - serverSocketOptions.add(StandardSocketOptions.SO_RCVBUF); - serverSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); - serverSocketOptions.add(StandardSocketOptions.IP_TOS); - }; + serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.IP_TOS); + } /** * Returns a set of SocketOptions supported by this impl * and by this impl's socket (Socket or ServerSocket) * * @return a Set of SocketOptions + * + * @since 9 */ protected Set> supportedOptions() { if (getSocket() != null) { diff --git a/jdk/test/java/net/SocketOption/ImmutableOptions.java b/jdk/test/java/net/SocketOption/ImmutableOptions.java new file mode 100644 index 00000000000..49c5f8a6831 --- /dev/null +++ b/jdk/test/java/net/SocketOption/ImmutableOptions.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2016, 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 8148609 + * @run testng/othervm ImmutableOptions + * @summary Assert that the set of socket options are immutable + */ +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.*; +import java.util.Set; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +public class ImmutableOptions { + + @BeforeTest + void setupServerSocketFactory() throws IOException { + ServerSocket.setSocketFactory(new ServerSocketImplFactory()); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void socketThrows() throws IOException { + CustomSocketImpl impl = new CustomSocketImpl(); + Socket socket = new CustomSocket(impl); + socket.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void socketImplThrows() throws IOException { + CustomSocketImpl impl = new CustomSocketImpl(); + impl.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void serverSocketThrows() throws IOException { + ServerSocket ss = new ServerSocket(); + ss.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void serverSocketImplThrows() throws IOException { + ServerSocket ss = new ServerSocket(); + ServerSocketImplFactory.mostRecentlyCreated.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void datagramSocketThrows() throws IOException { + CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl(); + DatagramSocket socket = new CustomDatagramSocket(impl); + socket.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void datagramSocketImplThrows() throws IOException { + CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl(); + impl.supportedOptions().clear(); + } + + + // Socket descendants + static class CustomSocket extends Socket { + public CustomSocket(SocketImpl impl) throws IOException { + super(impl); + } + } + + static class CustomDatagramSocket extends DatagramSocket { + public CustomDatagramSocket(DatagramSocketImpl impl) { + super(impl); + } + } + + static class ServerSocketImplFactory implements SocketImplFactory { + static volatile CustomSocketImpl mostRecentlyCreated; + + @Override public SocketImpl createSocketImpl() { + return mostRecentlyCreated = new CustomSocketImpl(); + } + } + + // Custom impl's + static class CustomSocketImpl extends SocketImpl { + // The only method interesting to this test. + @Override public Set> supportedOptions() { + return super.supportedOptions(); + } + + public void create(boolean stream) throws IOException { } + + public void connect(String host, int port) throws IOException { } + + public void connect(InetAddress addr, int port) throws IOException { } + + public void connect(SocketAddress addr, int timeout) throws IOException { } + + public void bind(InetAddress host, int port) throws IOException { } + + public void listen(int backlog) throws IOException { } + + public void accept(SocketImpl s) throws IOException { } + + public InputStream getInputStream() throws IOException { return null; } + + public OutputStream getOutputStream() throws IOException { return null; } + + public int available() throws IOException { return 0; } + + public void close() throws IOException { } + + public void sendUrgentData(int data) throws IOException { } + + public Object getOption(int i) throws SocketException { return null; } + + public void setOption(int i, Object o) throws SocketException { } + } + + static class CustomDatagramSocketImpl extends DatagramSocketImpl { + // The only method interesting to this test. + @Override public Set> supportedOptions() { + return super.supportedOptions(); + } + + protected void create() throws SocketException { } + + protected void bind(int lport, InetAddress laddr) throws SocketException { } + + protected void send(DatagramPacket p) throws IOException { } + + protected int peek(InetAddress i) throws IOException { return 0; } + + protected int peekData(DatagramPacket p) throws IOException { return 0; } + + protected void receive(DatagramPacket p) throws IOException { } + + protected void setTTL(byte ttl) throws IOException { } + + protected byte getTTL() throws IOException { return 0; } + + protected void setTimeToLive(int ttl) throws IOException { } + + protected int getTimeToLive() throws IOException { return 0; } + + protected void join(InetAddress inetaddr) throws IOException { } + + protected void leave(InetAddress inetaddr) throws IOException { } + + protected void joinGroup(SocketAddress x, NetworkInterface y) + throws IOException { } + + protected void leaveGroup(SocketAddress x, NetworkInterface y) + throws IOException { } + + protected void close() { } + + public void setOption(int optID, Object value) throws SocketException { } + + public Object getOption(int optID) throws SocketException { return null; } + } +} From b053911474d3271d4711f51cd70b539ee84d1fff Mon Sep 17 00:00:00 2001 From: Vyom Tewari Date: Thu, 3 Mar 2016 17:27:35 +0000 Subject: [PATCH 199/311] 8150521: SharedSecrets.getJavaNetInetAddressAccess should ensure that InetAddress is initialised Reviewed-by: alanb, chegar --- .../share/classes/jdk/internal/misc/SharedSecrets.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java index 541c4962bab..307989eed96 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java @@ -118,6 +118,8 @@ public class SharedSecrets { } public static JavaNetInetAddressAccess getJavaNetInetAddressAccess() { + if (javaNetInetAddressAccess == null) + unsafe.ensureClassInitialized(java.net.InetAddress.class); return javaNetInetAddressAccess; } From eb0aa24726070c36a638cd0e8f6c392bc44b9da6 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Thu, 3 Mar 2016 10:32:35 -0800 Subject: [PATCH 200/311] 6842353: Linux testcase failure java/util/WeakHashMap/GCDuringIteration.java Reviewed-by: martin, psandoz, darcy --- .../util/WeakHashMap/GCDuringIteration.java | 115 ++++++++++-------- 1 file changed, 62 insertions(+), 53 deletions(-) diff --git a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java index 663947f78b2..029b51e5cbf 100644 --- a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java +++ b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java @@ -29,26 +29,50 @@ * @run main GCDuringIteration * @summary Check that iterators work properly in the presence of * concurrent finalization and removal of elements. - * @key randomness intermittent + * @key randomness */ -import java.util.*; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.WeakHashMap; import java.util.concurrent.CountDownLatch; +import java.util.function.BooleanSupplier; import jdk.testlibrary.RandomFactory; public class GCDuringIteration { - private static void waitForFinalizersToRun() { - for (int i = 0; i < 2; i++) - tryWaitForFinalizersToRun(); + + /** No guarantees, but effective in practice. */ + static void forceFullGc() { + CountDownLatch finalizeDone = new CountDownLatch(1); + WeakReference ref = new WeakReference(new Object() { + protected void finalize() { finalizeDone.countDown(); }}); + try { + for (int i = 0; i < 10; i++) { + System.gc(); + if (finalizeDone.await(1L, SECONDS) && ref.get() == null) { + System.runFinalization(); // try to pick up stragglers + return; + } + } + } catch (InterruptedException unexpected) { + throw new AssertionError("unexpected InterruptedException"); + } + throw new AssertionError("failed to do a \"full\" gc"); } - private static void tryWaitForFinalizersToRun() { - System.gc(); - final CountDownLatch fin = new CountDownLatch(1); - new Object() { protected void finalize() { fin.countDown(); }}; - System.gc(); - try { fin.await(); } - catch (InterruptedException ie) { throw new Error(ie); } + static void gcAwait(BooleanSupplier s) { + for (int i = 0; i < 10; i++) { + if (s.getAsBoolean()) + return; + forceFullGc(); + } + throw new AssertionError("failed to satisfy condition"); } // A class with the traditional pessimal hashCode implementation, @@ -76,9 +100,13 @@ public class GCDuringIteration { if (rnd.nextBoolean()) check(it.hasNext()); equal(it.next().getValue(), i); } - if (rnd.nextBoolean()) - THROWS(NoSuchElementException.class, - new F(){void f(){it.next();}}); + if (rnd.nextBoolean()) { + try { + it.next(); + throw new AssertionError("should throw"); + } catch (NoSuchElementException success) {} + } + if (rnd.nextBoolean()) check(! it.hasNext()); } @@ -106,9 +134,7 @@ public class GCDuringIteration { int first = firstValue(map); final Iterator> it = map.entrySet().iterator(); foos[first] = null; - for (int i = 0; i < 10 && map.size() != first; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first); + gcAwait(() -> map.size() == first); checkIterator(it, first-1); equal(map.size(), first); equal(firstValue(map), first-1); @@ -119,15 +145,14 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); + int oldSize = map.size(); foos[first] = null; - tryWaitForFinalizersToRun(); - equal(map.size(), first+1); + forceFullGc(); + equal(map.size(), oldSize); System.out.println(map.values()); checkIterator(it, first-1); // first entry no longer protected - for (int i = 0; i < 10 && map.size() != first; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first); + gcAwait(() -> map.size() == first); equal(firstValue(map), first-1); } @@ -137,15 +162,12 @@ public class GCDuringIteration { it.next(); // protects first entry System.out.println(map.values()); foos[first] = foos[first-1] = null; - tryWaitForFinalizersToRun(); - equal(map.size(), first); + gcAwait(() -> map.size() == first); equal(firstValue(map), first); System.out.println(map.values()); checkIterator(it, first-2); // first entry no longer protected - for (int i = 0; i < 10 && map.size() != first-1; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first-1); + gcAwait(() -> map.size() == first-1); equal(firstValue(map), first-2); } @@ -155,16 +177,15 @@ public class GCDuringIteration { it.next(); // protects first entry it.hasNext(); // protects second entry System.out.println(map.values()); + int oldSize = map.size(); foos[first] = foos[first-1] = null; - tryWaitForFinalizersToRun(); + forceFullGc(); + equal(map.size(), oldSize); equal(firstValue(map), first); - equal(map.size(), first+1); System.out.println(map.values()); checkIterator(it, first-1); // first entry no longer protected - for (int i = 0; i < 10 && map.size() != first-1; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first-1); + gcAwait(() -> map.size() == first-1); equal(firstValue(map), first-2); } @@ -173,17 +194,16 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); + equal(map.size(), first+1); foos[first] = foos[first-1] = null; - tryWaitForFinalizersToRun(); + gcAwait(() -> map.size() == first); it.remove(); equal(firstValue(map), first-2); equal(map.size(), first-1); System.out.println(map.values()); checkIterator(it, first-2); // first entry no longer protected - for (int i = 0; i < 10 && map.size() != first-1; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first-1); + gcAwait(() -> map.size() == first-1); equal(firstValue(map), first-2); } @@ -194,15 +214,14 @@ public class GCDuringIteration { it.remove(); it.hasNext(); // protects second entry System.out.println(map.values()); + equal(map.size(), first); foos[first] = foos[first-1] = null; - tryWaitForFinalizersToRun(); + forceFullGc(); equal(firstValue(map), first-1); equal(map.size(), first); System.out.println(map.values()); checkIterator(it, first-1); - for (int i = 0; i < 10 && map.size() != first-1; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first-1); + gcAwait(() -> map.size() == first-1); equal(firstValue(map), first-2); } @@ -211,14 +230,11 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.hasNext(); // protects first entry Arrays.fill(foos, null); - tryWaitForFinalizersToRun(); - equal(map.size(), 1); + gcAwait(() -> map.size() == 1); System.out.println(map.values()); equal(it.next().getValue(), first); check(! it.hasNext()); - for (int i = 0; i < 10 && map.size() != 0; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), 0); + gcAwait(() -> map.size() == 0); check(map.isEmpty()); } } @@ -239,11 +255,4 @@ public class GCDuringIteration { try {test(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - abstract class F {abstract void f() throws Throwable;} - void THROWS(Class k, F... fs) { - for (F f : fs) - try {f.f(); fail("Expected " + k.getName() + " not thrown");} - catch (Throwable t) { - if (k.isAssignableFrom(t.getClass())) pass(); - else unexpected(t);}} } From 90771aabaedc79af07a69d9e9630a43569006922 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Thu, 3 Mar 2016 10:36:08 -0800 Subject: [PATCH 201/311] 8150319: ScheduledExecutorTest:testFixedDelaySequence timeout with slow VMs Reviewed-by: martin, psandoz --- .../util/concurrent/tck/JSR166TestCase.java | 49 +++++++++++-- .../tck/ScheduledExecutorSubclassTest.java | 72 +++++++++++++------ .../concurrent/tck/ScheduledExecutorTest.java | 72 +++++++++++++------ 3 files changed, 140 insertions(+), 53 deletions(-) diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java index 69b2c93d0af..78e7d684046 100644 --- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java +++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java @@ -88,6 +88,7 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -210,11 +211,31 @@ public class JSR166TestCase extends TestCase { private static final int suiteRuns = Integer.getInteger("jsr166.suiteRuns", 1); + private static float systemPropertyValue(String name, float defaultValue) { + String floatString = System.getProperty(name); + if (floatString == null) + return defaultValue; + try { + return Float.parseFloat(floatString); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException( + String.format("Bad float value in system property %s=%s", + name, floatString)); + } + } + /** * The scaling factor to apply to standard delays used in tests. */ - private static final int delayFactor = - Integer.getInteger("jsr166.delay.factor", 1); + private static final float delayFactor = + systemPropertyValue("jsr166.delay.factor", 1.0f); + + /** + * The timeout factor as used in the jtreg test harness. + * See: http://openjdk.java.net/jtreg/tag-spec.html + */ + private static final float jtregTestTimeoutFactor + = systemPropertyValue("test.timeout.factor", 1.0f); public JSR166TestCase() { super(); } public JSR166TestCase(String name) { super(name); } @@ -590,10 +611,12 @@ public class JSR166TestCase extends TestCase { /** * Returns the shortest timed delay. This can be scaled up for - * slow machines using the jsr166.delay.factor system property. + * slow machines using the jsr166.delay.factor system property, + * or via jtreg's -timeoutFactor: flag. + * http://openjdk.java.net/jtreg/command-help.html */ protected long getShortDelay() { - return 50 * delayFactor; + return (long) (50 * delayFactor * jtregTestTimeoutFactor); } /** @@ -906,6 +929,14 @@ public class JSR166TestCase extends TestCase { }}; } + PoolCleaner cleaner(ExecutorService pool, AtomicBoolean flag) { + return new PoolCleanerWithReleaser(pool, releaser(flag)); + } + + Runnable releaser(final AtomicBoolean flag) { + return new Runnable() { public void run() { flag.set(true); }}; + } + /** * Waits out termination of a thread pool or fails doing so. */ @@ -1462,16 +1493,20 @@ public class JSR166TestCase extends TestCase { return new LatchAwaiter(latch); } - public void await(CountDownLatch latch) { + public void await(CountDownLatch latch, long timeoutMillis) { try { - if (!latch.await(LONG_DELAY_MS, MILLISECONDS)) + if (!latch.await(timeoutMillis, MILLISECONDS)) fail("timed out waiting for CountDownLatch for " - + (LONG_DELAY_MS/1000) + " sec"); + + (timeoutMillis/1000) + " sec"); } catch (Throwable fail) { threadUnexpectedException(fail); } } + public void await(CountDownLatch latch) { + await(latch, LONG_DELAY_MS); + } + public void await(Semaphore semaphore) { try { if (!semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS)) diff --git a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java index 50b7b171140..ead869ed648 100644 --- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java +++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java @@ -32,6 +32,7 @@ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; @@ -55,7 +56,9 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import junit.framework.Test; import junit.framework.TestSuite; @@ -226,52 +229,75 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase { } /** - * scheduleAtFixedRate executes series of tasks at given rate + * scheduleAtFixedRate executes series of tasks at given rate. + * Eventually, it must hold that: + * cycles - 1 <= elapsedMillis/delay < cycles */ public void testFixedRateSequence() throws InterruptedException { final CustomExecutor p = new CustomExecutor(1); try (PoolCleaner cleaner = cleaner(p)) { for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { - long startTime = System.nanoTime(); - int cycles = 10; + final long startTime = System.nanoTime(); + final int cycles = 8; final CountDownLatch done = new CountDownLatch(cycles); - Runnable task = new CheckedRunnable() { + final Runnable task = new CheckedRunnable() { public void realRun() { done.countDown(); }}; - ScheduledFuture h = + final ScheduledFuture periodicTask = p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS); - await(done); - h.cancel(true); - double normalizedTime = - (double) millisElapsedSince(startTime) / delay; - if (normalizedTime >= cycles - 1 && - normalizedTime <= cycles) + final int totalDelayMillis = (cycles - 1) * delay; + await(done, totalDelayMillis + LONG_DELAY_MS); + periodicTask.cancel(true); + final long elapsedMillis = millisElapsedSince(startTime); + assertTrue(elapsedMillis >= totalDelayMillis); + if (elapsedMillis <= cycles * delay) return; + // else retry with longer delay } fail("unexpected execution rate"); } } /** - * scheduleWithFixedDelay executes series of tasks with given period + * scheduleWithFixedDelay executes series of tasks with given period. + * Eventually, it must hold that each task starts at least delay and at + * most 2 * delay after the termination of the previous task. */ public void testFixedDelaySequence() throws InterruptedException { final CustomExecutor p = new CustomExecutor(1); try (PoolCleaner cleaner = cleaner(p)) { for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { - long startTime = System.nanoTime(); - int cycles = 10; + final long startTime = System.nanoTime(); + final AtomicLong previous = new AtomicLong(startTime); + final AtomicBoolean tryLongerDelay = new AtomicBoolean(false); + final int cycles = 8; final CountDownLatch done = new CountDownLatch(cycles); - Runnable task = new CheckedRunnable() { - public void realRun() { done.countDown(); }}; - ScheduledFuture h = + final int d = delay; + final Runnable task = new CheckedRunnable() { + public void realRun() { + long now = System.nanoTime(); + long elapsedMillis + = NANOSECONDS.toMillis(now - previous.get()); + if (done.getCount() == cycles) { // first execution + if (elapsedMillis >= d) + tryLongerDelay.set(true); + } else { + assertTrue(elapsedMillis >= d); + if (elapsedMillis >= 2 * d) + tryLongerDelay.set(true); + } + previous.set(now); + done.countDown(); + }}; + final ScheduledFuture periodicTask = p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS); - await(done); - h.cancel(true); - double normalizedTime = - (double) millisElapsedSince(startTime) / delay; - if (normalizedTime >= cycles - 1 && - normalizedTime <= cycles) + final int totalDelayMillis = (cycles - 1) * delay; + await(done, totalDelayMillis + cycles * LONG_DELAY_MS); + periodicTask.cancel(true); + final long elapsedMillis = millisElapsedSince(startTime); + assertTrue(elapsedMillis >= totalDelayMillis); + if (!tryLongerDelay.get()) return; + // else retry with longer delay } fail("unexpected execution rate"); } diff --git a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java index 797dee3a845..53ebc5ea179 100644 --- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java +++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java @@ -34,6 +34,7 @@ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; @@ -52,7 +53,9 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import junit.framework.Test; import junit.framework.TestSuite; @@ -170,52 +173,75 @@ public class ScheduledExecutorTest extends JSR166TestCase { } /** - * scheduleAtFixedRate executes series of tasks at given rate + * scheduleAtFixedRate executes series of tasks at given rate. + * Eventually, it must hold that: + * cycles - 1 <= elapsedMillis/delay < cycles */ public void testFixedRateSequence() throws InterruptedException { final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); try (PoolCleaner cleaner = cleaner(p)) { for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { - long startTime = System.nanoTime(); - int cycles = 10; + final long startTime = System.nanoTime(); + final int cycles = 8; final CountDownLatch done = new CountDownLatch(cycles); - Runnable task = new CheckedRunnable() { + final Runnable task = new CheckedRunnable() { public void realRun() { done.countDown(); }}; - ScheduledFuture h = + final ScheduledFuture periodicTask = p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS); - await(done); - h.cancel(true); - double normalizedTime = - (double) millisElapsedSince(startTime) / delay; - if (normalizedTime >= cycles - 1 && - normalizedTime <= cycles) + final int totalDelayMillis = (cycles - 1) * delay; + await(done, totalDelayMillis + LONG_DELAY_MS); + periodicTask.cancel(true); + final long elapsedMillis = millisElapsedSince(startTime); + assertTrue(elapsedMillis >= totalDelayMillis); + if (elapsedMillis <= cycles * delay) return; + // else retry with longer delay } fail("unexpected execution rate"); } } /** - * scheduleWithFixedDelay executes series of tasks with given period + * scheduleWithFixedDelay executes series of tasks with given period. + * Eventually, it must hold that each task starts at least delay and at + * most 2 * delay after the termination of the previous task. */ public void testFixedDelaySequence() throws InterruptedException { final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); try (PoolCleaner cleaner = cleaner(p)) { for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { - long startTime = System.nanoTime(); - int cycles = 10; + final long startTime = System.nanoTime(); + final AtomicLong previous = new AtomicLong(startTime); + final AtomicBoolean tryLongerDelay = new AtomicBoolean(false); + final int cycles = 8; final CountDownLatch done = new CountDownLatch(cycles); - Runnable task = new CheckedRunnable() { - public void realRun() { done.countDown(); }}; - ScheduledFuture h = + final int d = delay; + final Runnable task = new CheckedRunnable() { + public void realRun() { + long now = System.nanoTime(); + long elapsedMillis + = NANOSECONDS.toMillis(now - previous.get()); + if (done.getCount() == cycles) { // first execution + if (elapsedMillis >= d) + tryLongerDelay.set(true); + } else { + assertTrue(elapsedMillis >= d); + if (elapsedMillis >= 2 * d) + tryLongerDelay.set(true); + } + previous.set(now); + done.countDown(); + }}; + final ScheduledFuture periodicTask = p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS); - await(done); - h.cancel(true); - double normalizedTime = - (double) millisElapsedSince(startTime) / delay; - if (normalizedTime >= cycles - 1 && - normalizedTime <= cycles) + final int totalDelayMillis = (cycles - 1) * delay; + await(done, totalDelayMillis + cycles * LONG_DELAY_MS); + periodicTask.cancel(true); + final long elapsedMillis = millisElapsedSince(startTime); + assertTrue(elapsedMillis >= totalDelayMillis); + if (!tryLongerDelay.get()) return; + // else retry with longer delay } fail("unexpected execution rate"); } From a9c908bcb35eab0a6068ec0f51624c2ef1e1471f Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Thu, 3 Mar 2016 10:39:34 -0800 Subject: [PATCH 202/311] 8150417: Make ThreadLocalRandom more robust against static initialization cycles Reviewed-by: martin, psandoz, dholmes, mhaupt --- .../classes/java/util/SplittableRandom.java | 21 ++-- .../util/concurrent/ThreadLocalRandom.java | 113 +++++++++--------- 2 files changed, 69 insertions(+), 65 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java index f54b3d931b2..579102a2bc7 100644 --- a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java +++ b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java @@ -219,12 +219,20 @@ public final class SplittableRandom { return seed += gamma; } + // IllegalArgumentException messages + static final String BAD_BOUND = "bound must be positive"; + static final String BAD_RANGE = "bound must be greater than origin"; + static final String BAD_SIZE = "size must be non-negative"; + /** * The seed generator for default constructors. */ - private static final AtomicLong defaultGen = new AtomicLong(initialSeed()); + private static final AtomicLong defaultGen + = new AtomicLong(mix64(System.currentTimeMillis()) ^ + mix64(System.nanoTime())); - private static long initialSeed() { + // at end of to survive static initialization circularity + static { if (java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Boolean run() { @@ -234,17 +242,10 @@ public final class SplittableRandom { long s = (long)seedBytes[0] & 0xffL; for (int i = 1; i < 8; ++i) s = (s << 8) | ((long)seedBytes[i] & 0xffL); - return s; + defaultGen.set(s); } - return (mix64(System.currentTimeMillis()) ^ - mix64(System.nanoTime())); } - // IllegalArgumentException messages - static final String BAD_BOUND = "bound must be positive"; - static final String BAD_RANGE = "bound must be greater than origin"; - static final String BAD_SIZE = "size must be non-negative"; - /* * Internal versions of nextX methods used by streams, as well as * the public nextX(origin, bound) methods. These exist mainly to diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index 3e50171cf20..69ecc46cf6d 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -125,53 +125,6 @@ public class ThreadLocalRandom extends Random { * but we provide identical statistical properties. */ - /** Generates per-thread initialization/probe field */ - private static final AtomicInteger probeGenerator = new AtomicInteger(); - - /** - * The next seed for default constructors. - */ - private static final AtomicLong seeder = new AtomicLong(initialSeed()); - - private static long initialSeed() { - if (java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Boolean run() { - return Boolean.getBoolean("java.util.secureRandomSeed"); - }})) { - byte[] seedBytes = java.security.SecureRandom.getSeed(8); - long s = (long)seedBytes[0] & 0xffL; - for (int i = 1; i < 8; ++i) - s = (s << 8) | ((long)seedBytes[i] & 0xffL); - return s; - } - return (mix64(System.currentTimeMillis()) ^ - mix64(System.nanoTime())); - } - - /** - * The seed increment. - */ - private static final long GAMMA = 0x9e3779b97f4a7c15L; - - /** - * The increment for generating probe values. - */ - private static final int PROBE_INCREMENT = 0x9e3779b9; - - /** - * The increment of seeder per new instance. - */ - private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL; - - // Constants from SplittableRandom - private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53) - private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24) - - /** Rarely-used holder for the second of a pair of Gaussians */ - private static final ThreadLocal nextLocalGaussian = - new ThreadLocal<>(); - private static long mix64(long z) { z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL; z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L; @@ -194,9 +147,6 @@ public class ThreadLocalRandom extends Random { initialized = true; // false during super() call } - /** The common ThreadLocalRandom */ - static final ThreadLocalRandom instance = new ThreadLocalRandom(); - /** * Initialize Thread fields for the current thread. Called only * when Thread.threadLocalRandomProbe is zero, indicating that a @@ -248,11 +198,6 @@ public class ThreadLocalRandom extends Random { return (int)(mix64(nextSeed()) >>> (64 - bits)); } - // IllegalArgumentException messages - static final String BAD_BOUND = "bound must be positive"; - static final String BAD_RANGE = "bound must be greater than origin"; - static final String BAD_SIZE = "size must be non-negative"; - /** * The form of nextLong used by LongStream Spliterators. If * origin is greater than bound, acts as unbounded form of @@ -1050,6 +995,32 @@ public class ThreadLocalRandom extends Random { return current(); } + // Static initialization + + /** + * The seed increment. + */ + private static final long GAMMA = 0x9e3779b97f4a7c15L; + + /** + * The increment for generating probe values. + */ + private static final int PROBE_INCREMENT = 0x9e3779b9; + + /** + * The increment of seeder per new instance. + */ + private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL; + + // Constants from SplittableRandom + private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53) + private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24) + + // IllegalArgumentException messages + static final String BAD_BOUND = "bound must be positive"; + static final String BAD_RANGE = "bound must be greater than origin"; + static final String BAD_SIZE = "size must be non-negative"; + // Unsafe mechanics private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long SEED; @@ -1067,4 +1038,36 @@ public class ThreadLocalRandom extends Random { throw new Error(e); } } + + /** Rarely-used holder for the second of a pair of Gaussians */ + private static final ThreadLocal nextLocalGaussian = + new ThreadLocal<>(); + + /** Generates per-thread initialization/probe field */ + private static final AtomicInteger probeGenerator = new AtomicInteger(); + + /** The common ThreadLocalRandom */ + static final ThreadLocalRandom instance = new ThreadLocalRandom(); + + /** + * The next seed for default constructors. + */ + private static final AtomicLong seeder + = new AtomicLong(mix64(System.currentTimeMillis()) ^ + mix64(System.nanoTime())); + + // at end of to survive static initialization circularity + static { + if (java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Boolean run() { + return Boolean.getBoolean("java.util.secureRandomSeed"); + }})) { + byte[] seedBytes = java.security.SecureRandom.getSeed(8); + long s = (long)seedBytes[0] & 0xffL; + for (int i = 1; i < 8; ++i) + s = (s << 8) | ((long)seedBytes[i] & 0xffL); + seeder.set(s); + } + } } From 1c04a6de53da4ca92d51ab1103e5df39338b4761 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Thu, 3 Mar 2016 10:43:07 -0800 Subject: [PATCH 203/311] 8150523: improve jtreg test timeout handling, especially -timeout: Reviewed-by: martin, psandoz, smarks --- .../CancelledProducerConsumerLoops.java | 17 ++++++--- .../concurrent/BlockingQueue/Interrupt.java | 18 +++++---- .../MultipleProducersSingleConsumerLoops.java | 7 +++- .../BlockingQueue/ProducerConsumerLoops.java | 7 +++- .../SingleProducerMultipleConsumerLoops.java | 7 +++- .../concurrent/CompletableFuture/Basic.java | 15 +++++--- .../ConcurrentHashMap/MapLoops.java | 9 +++-- .../ConcurrentQueueLoops.java | 11 +++--- .../ConcurrentQueues/GCRetention.java | 27 +++++++++++++- .../util/concurrent/CyclicBarrier/Basic.java | 16 ++++---- .../util/concurrent/DelayQueue/Stress.java | 1 + .../concurrent/Exchanger/ExchangeLoops.java | 12 +++--- .../ExecutorCompletionServiceLoops.java | 16 ++++---- .../concurrent/Executors/AutoShutdown.java | 18 ++++++--- .../FutureTask/CancelledFutureLoops.java | 9 +++-- .../concurrent/FutureTask/DoneMeansDone.java | 8 +++- .../DelayOverflow.java | 34 ++++++++++------- .../GCRetention.java | 8 +++- .../ZeroCorePoolSize.java | 9 ++++- .../ZeroCoreThreads.java | 37 +++++++++++++++---- .../ThreadPoolExecutor/CoreThreadTimeOut.java | 11 ++++-- .../concurrent/ThreadPoolExecutor/Custom.java | 32 +++++++++++++--- .../FlakyThreadFactory.java | 8 +++- .../ThreadPoolExecutor/SelfInterrupt.java | 8 +++- .../ThreadPoolExecutor/ThreadRestarts.java | 15 ++++++-- .../ThreadPoolExecutor/TimeOutShrink.java | 22 ++++++++--- .../locks/Lock/CheckedLockLoops.java | 7 +++- .../concurrent/locks/Lock/FlakyMutex.java | 7 +++- .../locks/Lock/TimedAcquireLeak.java | 9 ++++- .../locks/LockSupport/ParkLoops.java | 16 ++++---- .../ReentrantLock/LockOncePerThreadLoops.java | 15 ++++---- .../SimpleReentrantLockLoops.java | 11 +++--- .../locks/ReentrantLock/TimeoutLockLoops.java | 8 +++- .../locks/ReentrantReadWriteLock/Count.java | 7 +++- .../ReentrantReadWriteLock/MapLoops.java | 7 +++- .../concurrent/locks/StampedLock/Basic.java | 19 ++++++---- 36 files changed, 340 insertions(+), 148 deletions(-) diff --git a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java index c822e7d3b98..db72bfc44d2 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java @@ -35,8 +35,11 @@ * @test * @bug 4486658 * @summary Checks for responsiveness of blocking queues to cancellation. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.ArrayList; import java.util.List; import java.util.SplittableRandom; @@ -53,8 +56,10 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class CancelledProducerConsumerLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; public static void main(String[] args) throws Exception { @@ -73,7 +78,7 @@ public class CancelledProducerConsumerLoops { new CancelledProducerConsumerLoops(i, queue).run(); } pool.shutdown(); - if (! pool.awaitTermination(10L, TimeUnit.SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out"); pool = null; } @@ -117,18 +122,18 @@ public class CancelledProducerConsumerLoops { assertCancelled(cons[i]); } - if (!producersInterrupted.await(10L, TimeUnit.SECONDS)) + if (!producersInterrupted.await(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out"); - if (!consumersInterrupted.await(10L, TimeUnit.SECONDS)) + if (!consumersInterrupted.await(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out"); if (prods[0].isDone() || prods[0].isCancelled()) throw new AssertionError("completed too early"); done = true; - if (! (prods[0].get(10L, TimeUnit.SECONDS) instanceof Integer)) + if (! (prods[0].get(LONG_DELAY_MS, MILLISECONDS) instanceof Integer)) throw new AssertionError("expected Integer"); - if (! (cons[0].get(10L, TimeUnit.SECONDS) instanceof Integer)) + if (! (cons[0].get(LONG_DELAY_MS, MILLISECONDS) instanceof Integer)) throw new AssertionError("expected Integer"); } @@ -138,7 +143,7 @@ public class CancelledProducerConsumerLoops { if (!future.isCancelled()) throw new AssertionError("not cancelled"); try { - future.get(10L, TimeUnit.SECONDS); + future.get(LONG_DELAY_MS, MILLISECONDS); throw new AssertionError("should throw CancellationException"); } catch (CancellationException success) {} } diff --git a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java index f3f130bb2c7..9677ea5d2e6 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java @@ -26,10 +26,10 @@ * @bug 6384064 * @summary Check proper handling of interrupts * @author Martin Buchholz + * @library /lib/testlibrary/ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; import java.util.List; @@ -41,8 +41,10 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledThreadPoolExecutor; +import jdk.testlibrary.Utils; public class Interrupt { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static void checkInterrupted0(Iterable fs, Executor ex) { for (Fun f : fs) { @@ -71,7 +73,7 @@ public class Interrupt { checkInterrupted0(fs, immediateExecutor); checkInterrupted0(fs, delayedExecutor); stpe.shutdown(); - check(stpe.awaitTermination(10L, SECONDS)); + check(stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } static void testQueue(final BlockingQueue q) { @@ -82,12 +84,12 @@ public class Interrupt { q.clear(); List fs = new ArrayList(); fs.add(() -> q.take()); - fs.add(() -> q.poll(60, SECONDS)); + fs.add(() -> q.poll(LONG_DELAY_MS, MILLISECONDS)); if (deq != null) { fs.add(() -> deq.takeFirst()); fs.add(() -> deq.takeLast()); - fs.add(() -> deq.pollFirst(7, SECONDS)); - fs.add(() -> deq.pollLast(7, SECONDS)); + fs.add(() -> deq.pollFirst(LONG_DELAY_MS, MILLISECONDS)); + fs.add(() -> deq.pollLast(LONG_DELAY_MS, MILLISECONDS)); } checkInterrupted(fs); @@ -99,12 +101,12 @@ public class Interrupt { fs.clear(); fs.add(() -> q.put(1)); - fs.add(() -> q.offer(1, 7, SECONDS)); + fs.add(() -> q.offer(1, LONG_DELAY_MS, MILLISECONDS)); if (deq != null) { fs.add(() -> deq.putFirst(1)); fs.add(() -> deq.putLast(1)); - fs.add(() -> deq.offerFirst(1, 7, SECONDS)); - fs.add(() -> deq.offerLast(1, 7, SECONDS)); + fs.add(() -> deq.offerFirst(1, LONG_DELAY_MS, MILLISECONDS)); + fs.add(() -> deq.offerLast(1, LONG_DELAY_MS, MILLISECONDS)); } checkInterrupted(fs); } catch (Throwable t) { diff --git a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java index 6fafe5453c2..076521266d0 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java @@ -35,10 +35,11 @@ * @test * @bug 4486658 * @summary multiple producers and single consumer using blocking queues + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -51,8 +52,10 @@ import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class MultipleProducersSingleConsumerLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; public static void main(String[] args) throws Exception { @@ -77,7 +80,7 @@ public class MultipleProducersSingleConsumerLoops { } pool.shutdown(); - if (! pool.awaitTermination(10L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); pool = null; } diff --git a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java index 6cc57e7f319..454a58facef 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java @@ -35,10 +35,11 @@ * @test * @bug 4486658 * @summary multiple producers and consumers using blocking queues + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -51,8 +52,10 @@ import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class ProducerConsumerLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; public static void main(String[] args) throws Exception { @@ -77,7 +80,7 @@ public class ProducerConsumerLoops { run(new ArrayBlockingQueue(100, true), i, 100); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); pool = null; } diff --git a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java index 662b6b277aa..d1810680dd9 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java @@ -35,10 +35,11 @@ * @test * @bug 4486658 * @summary check ordering for blocking queues with 1 producer and multiple consumers + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -50,8 +51,10 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.SynchronousQueue; +import jdk.testlibrary.Utils; public class SingleProducerMultipleConsumerLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; public static void main(String[] args) throws Exception { @@ -75,7 +78,7 @@ public class SingleProducerMultipleConsumerLoops { run(new ArrayBlockingQueue(100, true), i, 100); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); pool = null; } diff --git a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java index 4470604b3f0..9b6773d4a8e 100644 --- a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java +++ b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java @@ -34,15 +34,17 @@ /* * @test * @bug 8005696 + * @summary Basic tests for CompletableFuture + * @library /lib/testlibrary/ * @run main Basic * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 Basic - * @summary Basic tests for CompletableFuture * @author Chris Hegarty */ import static java.util.concurrent.CompletableFuture.runAsync; import static java.util.concurrent.CompletableFuture.supplyAsync; import static java.util.concurrent.ForkJoinPool.commonPool; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.lang.reflect.Array; @@ -54,8 +56,10 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class Basic { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static void checkCompletedNormally(CompletableFuture cf, Object value) { checkCompletedNormally(cf, value == null ? null : new Object[] { value }); @@ -109,12 +113,13 @@ public class Basic { } private static void realMain(String[] args) throws Throwable { - ExecutorService executor = Executors.newFixedThreadPool(2); + ExecutorService pool = Executors.newFixedThreadPool(2); try { - test(executor); + test(pool); } finally { - executor.shutdown(); - executor.awaitTermination(30L, SECONDS); + pool.shutdown(); + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) + throw new Error(); } } diff --git a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java index 767f035ab62..6ce67ccf8ff 100644 --- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java +++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java @@ -34,7 +34,6 @@ /* * @test * @bug 4486658 - * @run main/timeout=1600 MapLoops * @summary Exercise multithreaded maps, by default ConcurrentHashMap. * Multithreaded hash table test. Each thread does a random walk * though elements of "key" array. On each iteration, it checks if @@ -42,9 +41,11 @@ * inserts it, and if present, with probability premove it removes * it. (pinsert and premove are expressed as percentages to simplify * parsing from command line.) + * @library /lib/testlibrary/ + * @run main/timeout=1600 MapLoops */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.List; import java.util.Map; @@ -53,8 +54,10 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import jdk.testlibrary.Utils; public class MapLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static int nkeys = 1000; // 10_000 static int pinsert = 60; static int premove = 2; @@ -126,7 +129,7 @@ public class MapLoops { i = k; } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); if (! throwables.isEmpty()) diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java index 8b7511f71e9..8ecc8f84f5e 100644 --- a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java @@ -34,11 +34,12 @@ /* * @test * @bug 4486658 6785442 - * @run main ConcurrentQueueLoops 8 123456 * @summary Checks that a set of threads can repeatedly get and modify items + * @library /lib/testlibrary/ + * @run main ConcurrentQueueLoops 8 123456 */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.ArrayList; import java.util.Collection; @@ -57,8 +58,10 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class ConcurrentQueueLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); ExecutorService pool; AtomicInteger totalItems; boolean print; @@ -106,16 +109,14 @@ public class ConcurrentQueueLoops { print = false; System.out.println("Warmup..."); oneRun(1, items, q); - //Thread.sleep(100); oneRun(3, items, q); - Thread.sleep(100); print = true; for (int i = 1; i <= maxStages; i += (i+1) >>> 1) { oneRun(i, items, q); } pool.shutdown(); - check(pool.awaitTermination(60L, SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } class Stage implements Callable { diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java index befc8ad11f4..314166b8689 100644 --- a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java @@ -38,10 +38,14 @@ * @run main GCRetention 12345 */ +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.lang.ref.WeakReference; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; @@ -59,6 +63,25 @@ public class GCRetention { // Suitable for benchmarking. Overridden by args[0] for testing. int count = 1024 * 1024; + /** No guarantees, but effective in practice. */ + static void forceFullGc() { + CountDownLatch finalizeDone = new CountDownLatch(1); + WeakReference ref = new WeakReference(new Object() { + protected void finalize() { finalizeDone.countDown(); }}); + try { + for (int i = 0; i < 10; i++) { + System.gc(); + if (finalizeDone.await(1L, SECONDS) && ref.get() == null) { + System.runFinalization(); // try to pick up stragglers + return; + } + } + } catch (InterruptedException unexpected) { + throw new AssertionError("unexpected InterruptedException"); + } + throw new AssertionError("failed to do a \"full\" gc"); + } + final Map results = new ConcurrentHashMap(); Collection> queues() { @@ -117,8 +140,8 @@ public class GCRetention { long t0 = System.nanoTime(); for (int i = 0; i < count; i++) check(q.add(Boolean.TRUE)); - System.gc(); - System.gc(); + forceFullGc(); + // forceFullGc(); Boolean x; while ((x = q.poll()) != null) equal(x, Boolean.TRUE); diff --git a/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java b/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java index da62643e5d5..146347ed502 100644 --- a/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java +++ b/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java @@ -25,11 +25,11 @@ * @test * @bug 6253848 6366811 * @summary Basic tests for CyclicBarrier + * @library /lib/testlibrary/ * @author Martin Buchholz, David Holmes */ import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; import java.util.Iterator; @@ -39,8 +39,10 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class Basic { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); private static void checkBroken(final CyclicBarrier barrier) { check(barrier.isBroken()); @@ -77,7 +79,7 @@ public class Basic { private static final CyclicBarrier atTheStartingGate = new CyclicBarrier(3); private static void toTheStartingGate() { - try { atTheStartingGate.await(10, SECONDS); pass(); } + try { atTheStartingGate.await(LONG_DELAY_MS, MILLISECONDS); pass(); } catch (Throwable t) { unexpected(t); reset(atTheStartingGate); @@ -314,13 +316,13 @@ public class Basic { Throwable throwable() { return this.throwable; } boolean interruptBit() { return this.interrupted; } void realRun() throws Throwable { - startingGate.await(10, SECONDS); + startingGate.await(LONG_DELAY_MS, MILLISECONDS); try { - if (timed) barrier.await(10, SECONDS); + if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS); else barrier.await(); } catch (Throwable throwable) { this.throwable = throwable; } - try { doneSignal.await(10, SECONDS); } + try { doneSignal.await(LONG_DELAY_MS, MILLISECONDS); } catch (InterruptedException e) { interrupted = true; } } } @@ -354,7 +356,7 @@ public class Basic { waiter.start(); waiters.add(waiter); } - startingGate.await(10, SECONDS); + startingGate.await(LONG_DELAY_MS, MILLISECONDS); while (barrier.getNumberWaiting() < N) Thread.yield(); barrier.await(); doneSignal.countDown(); @@ -383,7 +385,7 @@ public class Basic { waiter.start(); waiters.add(waiter); } - startingGate.await(10, SECONDS); + startingGate.await(LONG_DELAY_MS, MILLISECONDS); while (barrier.getNumberWaiting() < N) Thread.yield(); for (int i = 0; i < N/2; i++) waiters.get(i).interrupt(); diff --git a/jdk/test/java/util/concurrent/DelayQueue/Stress.java b/jdk/test/java/util/concurrent/DelayQueue/Stress.java index 8d6145819e2..5a25b077521 100644 --- a/jdk/test/java/util/concurrent/DelayQueue/Stress.java +++ b/jdk/test/java/util/concurrent/DelayQueue/Stress.java @@ -26,6 +26,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; /** * This is not a regression test, but a stress benchmark test for diff --git a/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java b/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java index 8af16e2955c..5a20b6b9e2f 100644 --- a/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java +++ b/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java @@ -34,18 +34,20 @@ /* * @test * @bug 4486658 - * @run main/timeout=720 ExchangeLoops * @summary checks to make sure a pipeline of exchangers passes data. + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import jdk.testlibrary.Utils; public class ExchangeLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static boolean print = false; @@ -56,14 +58,14 @@ public class ExchangeLoops { public static void main(String[] args) throws Exception { int maxStages = 5; - int iters = 10000; + int iters = 2000; if (args.length > 0) maxStages = Integer.parseInt(args[0]); print = false; System.out.println("Warmup..."); - oneRun(2, 100000); + oneRun(2, iters); print = true; for (int i = 2; i <= maxStages; i += (i+1) >>> 1) { @@ -71,7 +73,7 @@ public class ExchangeLoops { oneRun(i, iters); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java index 1da7f2335c7..79dc0392f8a 100644 --- a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java +++ b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java @@ -34,19 +34,21 @@ /* * @test * @bug 4965960 - * @run main/timeout=3600 ExecutorCompletionServiceLoops - * @summary Exercise ExecutorCompletionServiceLoops + * @summary Exercise ExecutorCompletionService + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import jdk.testlibrary.Utils; public class ExecutorCompletionServiceLoops { - static final int POOLSIZE = 100; + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static final int POOLSIZE = 10; static final ExecutorService pool = Executors.newFixedThreadPool(POOLSIZE); static final ExecutorCompletionService ecs = @@ -55,23 +57,21 @@ public class ExecutorCompletionServiceLoops { public static void main(String[] args) throws Exception { int max = 8; - int base = 10000; + int base = 2000; if (args.length > 0) max = Integer.parseInt(args[0]); System.out.println("Warmup..."); oneTest(base); - Thread.sleep(100); print = true; for (int i = 1; i <= max; i += (i+1) >>> 1) { System.out.print("n: " + i * base); oneTest(i * base); - Thread.sleep(100); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java index cbec012cbb9..7e34e28bded 100644 --- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java +++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java @@ -24,26 +24,32 @@ /* * @test * @bug 6399443 - * @run main/othervm/timeout=1000 AutoShutdown * @summary Check for auto-shutdown and gc of singleThreadExecutors + * @library /lib/testlibrary/ + * @run main/othervm/timeout=1000 AutoShutdown * @author Martin Buchholz */ +import static java.util.concurrent.Executors.defaultThreadFactory; +import static java.util.concurrent.Executors.newFixedThreadPool; +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; +import static java.util.concurrent.Executors.newSingleThreadExecutor; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -import static java.util.concurrent.Executors.defaultThreadFactory; -import static java.util.concurrent.Executors.newFixedThreadPool; -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; -import static java.util.concurrent.Executors.newSingleThreadExecutor; +import jdk.testlibrary.Utils; public class AutoShutdown { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static void await(CountDownLatch latch) throws InterruptedException { - if (!latch.await(100L, TimeUnit.SECONDS)) + if (!latch.await(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out waiting for latch"); } diff --git a/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java b/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java index 12a26b84302..b6c645e6018 100644 --- a/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java +++ b/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java @@ -34,13 +34,14 @@ /* * @test * @bug 4486658 - * @run main/timeout=2000 CancelledFutureLoops * @summary Checks for responsiveness of futures to cancellation. * Runs under the assumption that ITERS computations require more than * TIMEOUT msecs to complete. + * @library /lib/testlibrary/ + * @run main/timeout=2000 CancelledFutureLoops */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.SplittableRandom; import java.util.concurrent.BrokenBarrierException; @@ -51,8 +52,10 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; +import jdk.testlibrary.Utils; public final class CancelledFutureLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static final SplittableRandom rnd = new SplittableRandom(); static boolean print = false; @@ -80,7 +83,7 @@ public final class CancelledFutureLoops { Thread.sleep(TIMEOUT); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(6 * LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java b/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java index b35de7a3782..7874107d40a 100644 --- a/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java +++ b/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java @@ -36,8 +36,11 @@ * @bug 8073704 * @summary Checks that once isDone() returns true, * get() never throws InterruptedException or TimeoutException + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; @@ -49,8 +52,11 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import jdk.testlibrary.Utils; public class DoneMeansDone { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + public static void main(String[] args) throws Throwable { final int iters = 1000; final int nThreads = 2; @@ -92,7 +98,7 @@ public class DoneMeansDone { } done.set(true); pool.shutdown(); - if (!pool.awaitTermination(10L, TimeUnit.SECONDS)) + if (!pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError(); for (Future future : futures) future.get(); diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java index 36af2e10e5a..071f7b51b15 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java @@ -35,14 +35,21 @@ * @test * @bug 6725789 * @summary Check for long overflow in task time comparison. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.DAYS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class DelayOverflow { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static void waitForNanoTimeTick() { for (long t0 = System.nanoTime(); t0 == System.nanoTime(); ) ; @@ -52,16 +59,16 @@ public class DelayOverflow { Runnable r, int how) { switch (how) { case 0: - pool.schedule(r, 0, TimeUnit.MILLISECONDS); + pool.schedule(r, 0, MILLISECONDS); break; case 1: - pool.schedule(Executors.callable(r), 0, TimeUnit.DAYS); + pool.schedule(Executors.callable(r), 0, DAYS); break; case 2: - pool.scheduleWithFixedDelay(r, 0, 1000, TimeUnit.NANOSECONDS); + pool.scheduleWithFixedDelay(r, 0, 1000, NANOSECONDS); break; case 3: - pool.scheduleAtFixedRate(r, 0, 1000, TimeUnit.MILLISECONDS); + pool.scheduleAtFixedRate(r, 0, 1000, MILLISECONDS); break; default: fail(String.valueOf(how)); @@ -72,16 +79,16 @@ public class DelayOverflow { Runnable r, int how) { switch (how) { case 0: - pool.schedule(r, Long.MAX_VALUE, TimeUnit.MILLISECONDS); + pool.schedule(r, Long.MAX_VALUE, MILLISECONDS); break; case 1: - pool.schedule(Executors.callable(r), Long.MAX_VALUE, TimeUnit.DAYS); + pool.schedule(Executors.callable(r), Long.MAX_VALUE, DAYS); break; case 2: - pool.scheduleWithFixedDelay(r, Long.MAX_VALUE, 1000, TimeUnit.NANOSECONDS); + pool.scheduleWithFixedDelay(r, Long.MAX_VALUE, 1000, NANOSECONDS); break; case 3: - pool.scheduleAtFixedRate(r, Long.MAX_VALUE, 1000, TimeUnit.MILLISECONDS); + pool.scheduleAtFixedRate(r, Long.MAX_VALUE, 1000, MILLISECONDS); break; default: fail(String.valueOf(how)); @@ -114,14 +121,14 @@ public class DelayOverflow { proceedLatch.await(); } catch (Throwable t) { unexpected(t); } }}; - pool.schedule(keepPoolBusy, 0, TimeUnit.SECONDS); + pool.schedule(keepPoolBusy, 0, DAYS); busyLatch.await(); scheduleNow(pool, notifier, nowHow); waitForNanoTimeTick(); scheduleAtTheEndOfTime(pool, neverRuns, thenHow); proceedLatch.countDown(); - check(runLatch.await(10L, TimeUnit.SECONDS)); + check(runLatch.await(LONG_DELAY_MS, MILLISECONDS)); equal(runLatch.getCount(), 0L); pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); @@ -142,10 +149,9 @@ public class DelayOverflow { } catch (Throwable t) { unexpected(t); } }}; pool.scheduleWithFixedDelay(scheduleNowScheduler, - 0, Long.MAX_VALUE, - TimeUnit.NANOSECONDS); + 0, Long.MAX_VALUE, NANOSECONDS); - check(runLatch.await(10L, TimeUnit.SECONDS)); + check(runLatch.await(LONG_DELAY_MS, MILLISECONDS)); equal(runLatch.getCount(), 0L); pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java index c39fcc07cf3..76e5eb9a5f8 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java @@ -34,8 +34,11 @@ /* * @test * @summary Ensure that waiting pool threads don't retain refs to tasks. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.lang.ref.WeakReference; import java.util.concurrent.Delayed; import java.util.concurrent.ExecutionException; @@ -44,8 +47,11 @@ import java.util.concurrent.RunnableScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import jdk.testlibrary.Utils; public class GCRetention { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + /** * A custom thread pool with a custom RunnableScheduledFuture, for the * sole purpose of ensuring that the task retains a strong reference to @@ -116,7 +122,7 @@ public class GCRetention { Thread.sleep(10); } pool.shutdown(); - pool.awaitTermination(10L, TimeUnit.SECONDS); + pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS); if (cleared < size) throw new Error(String.format ("references to %d/%d tasks retained (\"leaked\")", diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java index fefb46747d4..4aff18e2a25 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java @@ -26,16 +26,21 @@ * @bug 7091003 * @summary ScheduledExecutorService never executes Runnable * with corePoolSize of zero + * @library /lib/testlibrary/ * @author Chris Hegarty */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; /** * Verify that tasks can be run even with a core pool size of 0. */ public class ZeroCorePoolSize { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); volatile boolean taskRun; @@ -49,10 +54,10 @@ public class ZeroCorePoolSize { }; check(pool.getCorePoolSize() == 0); - pool.schedule(task, 1, TimeUnit.SECONDS); + pool.schedule(task, 12L, MILLISECONDS); pool.shutdown(); - check(pool.awaitTermination(20L, TimeUnit.SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); check(pool.getCorePoolSize() == 0); check(taskRun); } diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java index 2a610edbf22..f78c8d854d3 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java @@ -35,9 +35,11 @@ * @test * @bug 8022642 8065320 8129861 * @summary Ensure relative sanity when zero core threads + * @library /lib/testlibrary/ */ import static java.util.concurrent.TimeUnit.HOURS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.lang.reflect.Field; @@ -45,8 +47,28 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.BooleanSupplier; +import jdk.testlibrary.Utils; public class ZeroCoreThreads { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + + static long millisElapsedSince(long startTime) { + return (System.nanoTime() - startTime) / (1000L * 1000L); + } + + static void spinWaitUntil(BooleanSupplier predicate, long timeoutMillis) { + long startTime = -1L; + while (!predicate.getAsBoolean()) { + if (startTime == -1L) + startTime = System.nanoTime(); + else if (millisElapsedSince(startTime) > timeoutMillis) + throw new AssertionError( + String.format("timed out after %s ms", timeoutMillis)); + Thread.yield(); + } + } + static boolean hasWaiters(ReentrantLock lock, Condition condition) { lock.lock(); try { @@ -56,6 +78,11 @@ public class ZeroCoreThreads { } } + static void awaitHasWaiters(ReentrantLock lock, Condition condition, + long timeoutMillis) { + spinWaitUntil(() -> hasWaiters(lock, condition), timeoutMillis); + } + static T getField(Object x, String fieldName) { try { Field field = x.getClass().getDeclaredField(fieldName); @@ -72,7 +99,7 @@ public class ZeroCoreThreads { test(p); } finally { p.shutdownNow(); - check(p.awaitTermination(10L, SECONDS)); + check(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } } @@ -89,13 +116,7 @@ public class ZeroCoreThreads { equal(0L, p.getCompletedTaskCount()); p.schedule(dummy, 1L, HOURS); // Ensure one pool thread actually waits in timed queue poll - long t0 = System.nanoTime(); - while (!hasWaiters(lock, available)) { - if (System.nanoTime() - t0 > SECONDS.toNanos(10L)) - throw new AssertionError - ("timed out waiting for a waiter to show up"); - Thread.yield(); - } + awaitHasWaiters(lock, available, LONG_DELAY_MS); equal(1, p.getPoolSize()); equal(1, p.getLargestPoolSize()); equal(1L, p.getTaskCount()); diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java index 8b80814e1d7..088907cae77 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java @@ -25,17 +25,22 @@ * @test * @bug 6233235 6268386 * @summary Test allowsCoreThreadTimeOut + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class CoreThreadTimeOut { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static class IdentifiableThreadFactory implements ThreadFactory { static ThreadFactory defaultThreadFactory @@ -60,8 +65,8 @@ public class CoreThreadTimeOut { return count; } - static long millisElapsedSince(long t0) { - return (System.nanoTime() - t0) / (1000L * 1000L); + static long millisElapsedSince(long startTime) { + return (System.nanoTime() - startTime) / (1000L * 1000L); } void test(String[] args) throws Throwable { @@ -89,7 +94,7 @@ public class CoreThreadTimeOut { equal(countExecutorThreads(), 0); tpe.shutdown(); check(tpe.allowsCoreThreadTimeOut()); - check(tpe.awaitTermination(10L, TimeUnit.SECONDS)); + check(tpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new Exception("Some tests failed"); diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java index 9fded6a58d4..a1a21655b88 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java @@ -25,9 +25,12 @@ * @test * @bug 6277663 * @summary Test TPE extensibility framework + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; @@ -37,8 +40,11 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BooleanSupplier; +import jdk.testlibrary.Utils; public class Custom { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static volatile int passed = 0, failed = 0; static void pass() { passed++; } static void fail() { failed++; Thread.dumpStack(); } @@ -97,6 +103,22 @@ public class Custom { private static final int threadCount = 10; + static long millisElapsedSince(long startTime) { + return (System.nanoTime() - startTime) / (1000L * 1000L); + } + + static void spinWaitUntil(BooleanSupplier predicate, long timeoutMillis) { + long startTime = -1L; + while (!predicate.getAsBoolean()) { + if (startTime == -1L) + startTime = System.nanoTime(); + else if (millisElapsedSince(startTime) > timeoutMillis) + throw new AssertionError( + String.format("timed out after %s ms", timeoutMillis)); + Thread.yield(); + } + } + public static void main(String[] args) throws Throwable { CustomTPE tpe = new CustomTPE(); equal(tpe.getCorePoolSize(), threadCount); @@ -106,9 +128,8 @@ public class Custom { equal(countExecutorThreads(), threadCount); equal(CustomTask.births.get(), threadCount); tpe.shutdown(); - tpe.awaitTermination(120L, TimeUnit.SECONDS); - Thread.sleep(1000); - equal(countExecutorThreads(), 0); + tpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS); + spinWaitUntil(() -> countExecutorThreads() == 0, LONG_DELAY_MS); CustomSTPE stpe = new CustomSTPE(); for (int i = 0; i < threadCount; i++) @@ -116,9 +137,8 @@ public class Custom { equal(CustomSTPE.decorations.get(), threadCount); equal(countExecutorThreads(), threadCount); stpe.shutdown(); - stpe.awaitTermination(120L, TimeUnit.SECONDS); - Thread.sleep(1000); - equal(countExecutorThreads(), 0); + stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS); + spinWaitUntil(() -> countExecutorThreads() == 0, LONG_DELAY_MS); System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new Exception("Some tests failed"); diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java index 325ecef58a2..bb327e817c2 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java @@ -35,14 +35,20 @@ /* * @test * @summary Should be able to shutdown a pool when worker creation failed. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class FlakyThreadFactory { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + void test(String[] args) throws Throwable { test(NullPointerException.class, new ThreadFactory() { @@ -89,7 +95,7 @@ public class FlakyThreadFactory { check(exceptionClass.isInstance(t)); } pool.shutdown(); - check(pool.awaitTermination(10L, TimeUnit.SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } //--------------------- Infrastructure --------------------------- diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java index 9211ff28d95..c93ed9bf4f9 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java @@ -25,14 +25,20 @@ * @test * @bug 6576792 * @summary non-idle worker threads should not be interrupted + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.CountDownLatch; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class SelfInterrupt { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + void test(String[] args) throws Throwable { final int n = 100; final ThreadPoolExecutor pool = @@ -58,7 +64,7 @@ public class SelfInterrupt { } catch (Throwable t) { unexpected(t); }}}); finishLine.await(); pool.shutdown(); - check(pool.awaitTermination(1000L, TimeUnit.SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } //--------------------- Infrastructure --------------------------- diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java index 1b485867ce2..5d10213dc99 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java @@ -36,6 +36,7 @@ * @test * @summary Only one thread should be created when a thread needs to * be kept alive to service a delayed task waiting in the queue. + * @library /lib/testlibrary/ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -44,8 +45,12 @@ import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicLong; +import jdk.testlibrary.Utils; public class ThreadRestarts { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static final long FAR_FUTURE_MS = 10 * LONG_DELAY_MS; + public static void main(String[] args) throws Exception { test(false); test(true); @@ -56,14 +61,15 @@ public class ThreadRestarts { ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(10, ctf); try { + // schedule a dummy task in the "far future" Runnable nop = new Runnable() { public void run() {}}; - stpe.schedule(nop, 10*1000L, MILLISECONDS); + stpe.schedule(nop, FAR_FUTURE_MS, MILLISECONDS); stpe.setKeepAliveTime(1L, MILLISECONDS); stpe.allowCoreThreadTimeOut(allowTimeout); - MILLISECONDS.sleep(100L); + MILLISECONDS.sleep(12L); } finally { stpe.shutdownNow(); - if (!stpe.awaitTermination(60L, SECONDS)) + if (!stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out"); } if (ctf.count.get() > 1) @@ -76,8 +82,9 @@ public class ThreadRestarts { final AtomicLong count = new AtomicLong(0L); public Thread newThread(Runnable r) { - Thread t = new Thread(r); count.getAndIncrement(); + Thread t = new Thread(r); + t.setDaemon(true); return t; } } diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java index 8778b401d27..463d388b5da 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java @@ -25,15 +25,22 @@ * @test * @bug 6458662 * @summary poolSize might shrink below corePoolSize after timeout + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.CyclicBarrier; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class TimeOutShrink { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static final long KEEPALIVE_MS = 12L; + static void checkPoolSizes(ThreadPoolExecutor pool, int size, int core, int max) { equal(pool.getPoolSize(), size); @@ -45,7 +52,8 @@ public class TimeOutShrink { final int n = 4; final CyclicBarrier barrier = new CyclicBarrier(2*n+1); final ThreadPoolExecutor pool - = new ThreadPoolExecutor(n, 2*n, 1L, TimeUnit.SECONDS, + = new ThreadPoolExecutor(n, 2*n, + KEEPALIVE_MS, MILLISECONDS, new SynchronousQueue()); final Runnable r = new Runnable() { public void run() { try { @@ -58,12 +66,16 @@ public class TimeOutShrink { barrier.await(); checkPoolSizes(pool, 2*n, n, 2*n); barrier.await(); - while (pool.getPoolSize() > n) - Thread.sleep(100); - Thread.sleep(100); + long nap = KEEPALIVE_MS + (KEEPALIVE_MS >> 2); + for (long sleepyTime = 0L; pool.getPoolSize() > n; ) { + check((sleepyTime += nap) <= LONG_DELAY_MS); + Thread.sleep(nap); + } + checkPoolSizes(pool, n, n, 2*n); + Thread.sleep(nap); checkPoolSizes(pool, n, n, 2*n); pool.shutdown(); - check(pool.awaitTermination(60L, TimeUnit.SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } //--------------------- Infrastructure --------------------------- diff --git a/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java b/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java index a8f7bbe5daf..2e3d4b28e12 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java +++ b/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java @@ -35,9 +35,10 @@ * @test * @bug 4486658 * @summary basic safety and liveness of ReentrantLocks, and other locks based on them + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; @@ -47,8 +48,10 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import jdk.testlibrary.Utils; public final class CheckedLockLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; static final SplittableRandom rnd = new SplittableRandom(); @@ -63,7 +66,7 @@ public final class CheckedLockLoops { oneTest(i, iters / i); } pool.shutdown(); - if (! pool.awaitTermination(10L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); pool = null; } diff --git a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java index cf1605197cf..82f9ead09f5 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java +++ b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java @@ -25,9 +25,12 @@ * @test * @bug 6503247 6574123 * @summary Test resilience to tryAcquire methods that throw + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.Random; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; @@ -36,6 +39,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; +import jdk.testlibrary.Utils; /** * This uses a variant of the standard Mutex demo, except with a @@ -44,6 +48,7 @@ import java.util.concurrent.locks.Lock; */ @SuppressWarnings("serial") public class FlakyMutex implements Lock { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static class MyError extends Error {} static class MyException extends Exception {} static class MyRuntimeException extends RuntimeException {} @@ -91,7 +96,7 @@ public class FlakyMutex implements Lock { } catch (Throwable t) { unexpected(t); }}});} barrier.await(); es.shutdown(); - check(es.awaitTermination(30L, TimeUnit.SECONDS)); + check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } private static class FlakySync extends AbstractQueuedLongSynchronizer { diff --git a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java index a3440ec8b8d..7d6da0b255e 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java +++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java @@ -25,9 +25,11 @@ * @test * @bug 6460501 6236036 6500694 6490770 * @summary Repeated failed timed waits shouldn't leak memory + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; @@ -54,8 +56,11 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.regex.Matcher; import java.util.regex.Pattern; +import jdk.testlibrary.Utils; public class TimedAcquireLeak { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static String javahome() { String jh = System.getProperty("java.home"); return (jh.endsWith("jre")) ? jh.substring(0, jh.length() - 4) : jh; @@ -191,7 +196,7 @@ public class TimedAcquireLeak { final String[] jobCmd = { java, "-Xmx8m", "-XX:+UsePerfData", - "-classpath", System.getProperty("test.classes", "."), + "-classpath", System.getProperty("test.class.path"), childClassName, uniqueID }; final Process p = new ProcessBuilder(jobCmd).start(); @@ -219,7 +224,7 @@ public class TimedAcquireLeak { check(Math.abs(n1 - n0) < 10); check(n1 < 25); drainers.shutdown(); - if (!drainers.awaitTermination(10L, SECONDS)) { + if (!drainers.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) { drainers.shutdownNow(); // last resort throw new AssertionError("thread pool did not terminate"); } diff --git a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java index 1b098ea953e..5a078a83ea5 100644 --- a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java +++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java @@ -35,11 +35,12 @@ * @test * @bug 8074773 * @summary Stress test looks for lost unparks + * @library /lib/testlibrary/ * @modules java.management - * @run main/timeout=1200 ParkLoops */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.util.SplittableRandom; @@ -49,13 +50,12 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.LockSupport; +import jdk.testlibrary.Utils; public final class ParkLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final int THREADS = 4; - // static final int ITERS = 2_000_000; - // static final int TIMEOUT = 3500; // in seconds - static final int ITERS = 100_000; - static final int TIMEOUT = 1000; // in seconds + static final int ITERS = 30_000; static class Parker implements Runnable { static { @@ -130,13 +130,13 @@ public final class ParkLoops { pool.submit(unparker); } try { - if (!done.await(TIMEOUT, SECONDS)) { + if (!done.await(LONG_DELAY_MS, MILLISECONDS)) { dumpAllStacks(); throw new AssertionError("lost unpark"); } } finally { pool.shutdown(); - pool.awaitTermination(10L, SECONDS); + pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS); } } diff --git a/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java b/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java index b8d49c73863..de9f765b733 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java @@ -34,25 +34,27 @@ /* * @test * @bug 4486658 - * @run main/timeout=15000 LockOncePerThreadLoops * @summary Checks for missed signals by locking and unlocking each of an array of locks once per thread + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantLock; +import jdk.testlibrary.Utils; public final class LockOncePerThreadLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static final SplittableRandom rnd = new SplittableRandom(); static boolean print = false; - static int nlocks = 50000; - static int nthreads = 100; - static int replications = 5; + static int nlocks = 20_000; + static int nthreads = 20; + static int replications = 3; public static void main(String[] args) throws Exception { if (args.length > 0) @@ -66,10 +68,9 @@ public final class LockOncePerThreadLoops { for (int i = 0; i < replications; ++i) { System.out.print("Iteration: " + i); new ReentrantLockLoop().test(); - Thread.sleep(100); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java b/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java index 9e6ed4533f7..8534a391594 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java @@ -34,23 +34,25 @@ /* * @test * @bug 4486658 - * @run main/timeout=4500 SimpleReentrantLockLoops * @summary multiple threads using a single lock + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantLock; +import jdk.testlibrary.Utils; public final class SimpleReentrantLockLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static final SplittableRandom rnd = new SplittableRandom(); static boolean print = false; - static int iters = 1000000; + static int iters = 100_000; public static void main(String[] args) throws Exception { int maxThreads = 5; @@ -66,11 +68,10 @@ public final class SimpleReentrantLockLoops { while (n-- > 0) { System.out.print("Threads: " + i); new ReentrantLockLoop(i).test(); - Thread.sleep(100); } } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java index 3e4e0cfb059..8dc02e4f570 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java @@ -34,18 +34,22 @@ /* * @test * @bug 4486658 5031862 8140471 - * @run main TimeoutLockLoops * @summary Checks for responsiveness of locks to timeouts. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; +import jdk.testlibrary.Utils; public final class TimeoutLockLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static final SplittableRandom rnd = new SplittableRandom(); static boolean print = false; @@ -63,7 +67,7 @@ public final class TimeoutLockLoops { new ReentrantLockLoop(i).test(); } pool.shutdown(); - if (! pool.awaitTermination(60L, TimeUnit.SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java index 6341a817257..e6e094ac76b 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java @@ -25,9 +25,12 @@ * @test * @bug 6207928 6328220 6378321 6625723 * @summary Recursive lock invariant sanity checks + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -42,9 +45,11 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import jdk.testlibrary.Utils; // I am the Cownt, and I lahve to cownt. public class Count { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); final Random rnd = new Random(); void lock(Lock lock) { @@ -102,7 +107,7 @@ public class Count { barrier.await(); } catch (Throwable t) { unexpected(t); }}});} es.shutdown(); - check(es.awaitTermination(10L, TimeUnit.SECONDS)); + check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } void testReentrantLocks(final boolean fair, diff --git a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java index f82327ac8a4..4c44f6a2dbe 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java @@ -41,17 +41,20 @@ * inserts it, and if present, with probability premove it removes * it. (pinsert and premove are expressed as percentages to simplify * parsing from command line.) + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.Map; import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import jdk.testlibrary.Utils; public class MapLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final int NKEYS = 100000; static int pinsert = 60; static int premove = 2; @@ -125,7 +128,7 @@ public class MapLoops { map.clear(); } pool.shutdown(); - if (! pool.awaitTermination(10L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java index dde4fed0030..ea90f3c03de 100644 --- a/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java +++ b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java @@ -35,6 +35,7 @@ * @test * @bug 8005697 * @summary Basic tests for StampedLock + * @library /lib/testlibrary/ * @author Chris Hegarty */ @@ -49,8 +50,10 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.StampedLock; +import jdk.testlibrary.Utils; public class Basic { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static void checkResult(Locker l, Class c) { Throwable t = l.thrown(); @@ -268,7 +271,7 @@ public class Basic { case 2: case 5: return interruptibleReader(sl, -1, SECONDS, gate, view ^= true); default: - return interruptibleReader(sl, 30, SECONDS, gate, view ^= true); }} + return interruptibleReader(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }} public void remove() {throw new UnsupportedOperationException();}}; } @@ -286,7 +289,7 @@ public class Basic { case 2: case 5: return interruptibleWriter(sl, -1, SECONDS, gate, view ^= true); default: - return interruptibleWriter(sl, 30, SECONDS, gate, view ^= true); }} + return interruptibleWriter(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }} public void remove() {throw new UnsupportedOperationException();}}; } @@ -454,13 +457,13 @@ public class Basic { // We test interrupting both before and after trying to acquire boolean view = false; StampedLock sl = new StampedLock(); - for (long timeout : new long[] { -1L, 30L, -1L, 30L }) { + for (long timeout : new long[] { -1L, LONG_DELAY_MS, -1L, LONG_DELAY_MS }) { long stamp; Thread.State state; stamp = sl.writeLock(); try { - Reader r = interruptibleReader(sl, timeout, SECONDS, null, view); + Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view); r.start(); r.interrupt(); r.join(); @@ -471,7 +474,7 @@ public class Basic { stamp = sl.writeLock(); try { - Reader r = interruptibleReader(sl, timeout, SECONDS, null, view); + Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view); r.start(); waitForThreadToBlock(r); r.interrupt(); @@ -483,7 +486,7 @@ public class Basic { stamp = sl.readLock(); try { - Writer w = interruptibleWriter(sl, timeout, SECONDS, null, view); + Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view); w.start(); w.interrupt(); w.join(); @@ -494,7 +497,7 @@ public class Basic { stamp = sl.readLock(); try { - Writer w = interruptibleWriter(sl, timeout, SECONDS, null, view); + Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view); w.start(); waitForThreadToBlock(w); w.interrupt(); @@ -509,7 +512,7 @@ public class Basic { check(!sl.tryUnlockRead()); check(!sl.tryUnlockWrite()); check(sl.tryOptimisticRead() != 0L); - if (timeout == 30L) + if (timeout == LONG_DELAY_MS) view = true; } } catch (Throwable t) { unexpected(t); } From b5d355ac84ded85d689c08e2c3c16a67f63d0023 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Thu, 3 Mar 2016 10:46:22 -0800 Subject: [PATCH 204/311] 8150416: Miscellaneous changes imported from jsr166 CVS 2016-03 Reviewed-by: martin, psandoz --- .../util/concurrent/tck/Collection8Test.java | 40 ++++++++++--------- .../java/util/concurrent/tck/ThreadTest.java | 2 +- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/jdk/test/java/util/concurrent/tck/Collection8Test.java b/jdk/test/java/util/concurrent/tck/Collection8Test.java index 1a10b280228..36f99e157dc 100644 --- a/jdk/test/java/util/concurrent/tck/Collection8Test.java +++ b/jdk/test/java/util/concurrent/tck/Collection8Test.java @@ -37,6 +37,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -98,26 +99,29 @@ public class Collection8Test extends JSR166TestCase { public void testForEachConcurrentStressTest() throws Throwable { if (!impl.isConcurrent()) return; final Collection c = impl.emptyCollection(); - final long testDurationMillis = SHORT_DELAY_MS; + final long testDurationMillis = timeoutMillis(); final AtomicBoolean done = new AtomicBoolean(false); final Object elt = impl.makeElement(1); - ExecutorService pool = Executors.newCachedThreadPool(); - Runnable checkElt = () -> { - while (!done.get()) - c.stream().forEach((x) -> { assertSame(x, elt); }); }; - Runnable addRemove = () -> { - while (!done.get()) { - assertTrue(c.add(elt)); - assertTrue(c.remove(elt)); - }}; - Future f1 = pool.submit(checkElt); - Future f2 = pool.submit(addRemove); - Thread.sleep(testDurationMillis); - done.set(true); - pool.shutdown(); - assertTrue(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); - assertNull(f1.get(LONG_DELAY_MS, MILLISECONDS)); - assertNull(f2.get(LONG_DELAY_MS, MILLISECONDS)); + final Future f1, f2; + final ExecutorService pool = Executors.newCachedThreadPool(); + try (PoolCleaner cleaner = cleaner(pool, done)) { + final CountDownLatch threadsStarted = new CountDownLatch(2); + Runnable checkElt = () -> { + threadsStarted.countDown(); + while (!done.get()) + c.stream().forEach((x) -> { assertSame(x, elt); }); }; + Runnable addRemove = () -> { + threadsStarted.countDown(); + while (!done.get()) { + assertTrue(c.add(elt)); + assertTrue(c.remove(elt)); + }}; + f1 = pool.submit(checkElt); + f2 = pool.submit(addRemove); + Thread.sleep(testDurationMillis); + } + assertNull(f1.get(0L, MILLISECONDS)); + assertNull(f2.get(0L, MILLISECONDS)); } // public void testCollection8DebugFail() { fail(); } diff --git a/jdk/test/java/util/concurrent/tck/ThreadTest.java b/jdk/test/java/util/concurrent/tck/ThreadTest.java index 939d590beb9..92b2aca52a6 100644 --- a/jdk/test/java/util/concurrent/tck/ThreadTest.java +++ b/jdk/test/java/util/concurrent/tck/ThreadTest.java @@ -77,7 +77,7 @@ public class ThreadTest extends JSR166TestCase { */ public void testGetAndSetDefaultUncaughtExceptionHandler() { assertEquals(null, Thread.getDefaultUncaughtExceptionHandler()); - // failure due to securityException is OK. + // failure due to SecurityException is OK. // Would be nice to explicitly test both ways, but cannot yet. Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); From be111eec1ae9cd5a0ab66c5538d00cba79c3054f Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 3 Mar 2016 12:25:57 -0800 Subject: [PATCH 205/311] Added tag jdk-9+108 for changeset 564116a434fa --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 65cb5c825bd..ad3f50825db 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -350,3 +350,4 @@ eee1ced1d8e78293f2a004af818ca474387dbebf jdk-9+103 55518739e399a1066c8613e19100d51b38d9f223 jdk-9+105 6e9ecae50b4e0d37483fb2719202eea5dca026a4 jdk-9+106 8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107 +42794e648cfe9fd67461dcbe8b7594241a84bcff jdk-9+108 From da10efd829256c3df37799b0a0f8ff41c55b5ea8 Mon Sep 17 00:00:00 2001 From: Steve Drach Date: Thu, 3 Mar 2016 09:47:40 -0800 Subject: [PATCH 206/311] 8150679: closed/javax/crypto/CryptoPermission/CallerIdentification.sh fails after fix for JDK-8132734 Also fixes JDK-8150920 Reviewed-by: psandoz, redestad --- .../share/classes/java/util/jar/JarFile.java | 12 ++++++--- .../jar/MultiReleaseJarURLConnection.java | 27 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java index 2ea1a69657a..b3bbced134c 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java @@ -893,11 +893,15 @@ class JarFile extends ZipFile { } private JarEntry verifiableEntry(ZipEntry ze) { - if (!(ze instanceof JarFileEntry)) { - ze = getJarEntry(ze.getName()); + if (ze instanceof JarFileEntry) { + // assure the name and entry match for verification + return ((JarFileEntry)ze).reifiedEntry(); } - // assure the name and entry match for verification - return ze == null ? null : ((JarFileEntry)ze).reifiedEntry(); + ze = getJarEntry(ze.getName()); + if (ze instanceof JarFileEntry) { + return ((JarFileEntry)ze).reifiedEntry(); + } + return (JarEntry)ze; } // Statics for hand-coded Boyer-Moore search diff --git a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java index a500eb2e25c..aeca6c6b50d 100644 --- a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java +++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java @@ -42,27 +42,40 @@ import java.util.jar.JarFile; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class MultiReleaseJarURLConnection { String userdir = System.getProperty("user.dir","."); - String urlFile = "jar:file:" + userdir + "/multi-release.jar!/"; - String urlEntry = urlFile + "version/Version.java"; + String file = userdir + "/signed-multi-release.jar"; @BeforeClass public void initialize() throws Exception { CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); creator.compileEntries(); creator.buildMultiReleaseJar(); + creator.buildSignedMultiReleaseJar(); } @AfterClass public void close() throws IOException { Files.delete(Paths.get(userdir, "multi-release.jar")); + Files.delete(Paths.get(userdir, "signed-multi-release.jar")); } - @Test - public void testRuntimeVersioning() throws Exception { + @DataProvider(name = "data") + public Object[][] createData() { + return new Object[][]{ + {"unsigned file", userdir + "/multi-release.jar"}, + {"signed file", userdir + "/signed-multi-release.jar"}, + }; + } + + @Test(dataProvider = "data") + public void testRuntimeVersioning(String ignore, String file) throws Exception { + String urlFile = "jar:file:" + file + "!/"; + String urlEntry = urlFile + "version/Version.java"; + Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); // #runtime is "magic" Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9")); @@ -72,8 +85,10 @@ public class MultiReleaseJarURLConnection { Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); } - @Test - public void testCachedJars() throws Exception { + @Test(dataProvider = "data") + public void testCachedJars(String ignore, String file) throws Exception { + String urlFile = "jar:file:" + file + "!/"; + URL rootUrl = new URL(urlFile); JarURLConnection juc = (JarURLConnection)rootUrl.openConnection(); JarFile rootJar = juc.getJarFile(); From 519a8843613a2acb8ef141dc4f5cc3fde53dc718 Mon Sep 17 00:00:00 2001 From: Alexandre Iline Date: Thu, 3 Mar 2016 15:13:55 -0800 Subject: [PATCH 207/311] 8150998: Fix module dependences in java/lang tests Reviewed-by: mchung --- jdk/test/java/lang/ProcessHandle/Basic.java | 3 ++- jdk/test/java/lang/ProcessHandle/InfoTest.java | 1 + jdk/test/java/lang/ProcessHandle/OnExitTest.java | 3 ++- jdk/test/java/lang/ProcessHandle/TreeTest.java | 3 ++- jdk/test/java/lang/StackWalker/StackStreamTest.java | 3 ++- jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java | 3 ++- .../java/lang/System/Logger/default/DefaultLoggerTest.java | 4 ++-- .../DefaultLoggerFinderTest/DefaultLoggerFinderTest.java | 3 ++- .../internal/BootstrapLogger/BootstrapLoggerTest.java | 3 ++- .../internal/LoggerBridgeTest/LoggerBridgeTest.java | 6 ++++-- .../PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java | 3 ++- .../LoggerFinder/internal/api/LoggerFinderAPITest.java | 3 ++- jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java | 3 ++- .../java/lang/instrument/ManyMethodsBenchmarkAgent.java | 5 ++--- jdk/test/java/lang/instrument/RetransformAgent.java | 3 ++- .../invoke/lambda/LambdaAccessControlDoPrivilegedTest.java | 3 ++- jdk/test/java/lang/invoke/lambda/LambdaAsm.java | 3 ++- .../java/lang/invoke/lambda/LogGeneratedClassesTest.java | 2 ++ jdk/test/java/lang/ref/CleanerTest.java | 5 ++++- 19 files changed, 41 insertions(+), 21 deletions(-) diff --git a/jdk/test/java/lang/ProcessHandle/Basic.java b/jdk/test/java/lang/ProcessHandle/Basic.java index 005fd538f60..2d7258f3ccc 100644 --- a/jdk/test/java/lang/ProcessHandle/Basic.java +++ b/jdk/test/java/lang/ProcessHandle/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -37,6 +37,7 @@ import org.testng.annotations.Test; /* * @test * @library /test/lib/share/classes + * @modules jdk.management * @run testng Basic * @summary Basic tests for ProcessHandler * @author Roger Riggs diff --git a/jdk/test/java/lang/ProcessHandle/InfoTest.java b/jdk/test/java/lang/ProcessHandle/InfoTest.java index 1688c369343..e269d3e33c8 100644 --- a/jdk/test/java/lang/ProcessHandle/InfoTest.java +++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java @@ -49,6 +49,7 @@ import org.testng.annotations.Test; * @test * @bug 8077350 8081566 8081567 8098852 8136597 * @library /test/lib/share/classes + * @modules jdk.management * @build jdk.test.lib.Platform jdk.test.lib.Utils * @run testng InfoTest * @summary Functions of ProcessHandle.Info diff --git a/jdk/test/java/lang/ProcessHandle/OnExitTest.java b/jdk/test/java/lang/ProcessHandle/OnExitTest.java index 3ec997db342..77cc19d86dd 100644 --- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java +++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -39,6 +39,7 @@ import org.testng.TestNG; /* * @test * @library /test/lib/share/classes + * @modules jdk.management * @build jdk.test.lib.Platform jdk.test.lib.Utils * @run testng OnExitTest * @summary Functions of Process.onExit and ProcessHandle.onExit diff --git a/jdk/test/java/lang/ProcessHandle/TreeTest.java b/jdk/test/java/lang/ProcessHandle/TreeTest.java index 85b752a6602..9840718d881 100644 --- a/jdk/test/java/lang/ProcessHandle/TreeTest.java +++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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,7 @@ import org.testng.annotations.Test; /* * @test * @library /test/lib/share/classes + * @modules jdk.management * @build jdk.test.lib.Utils * @run testng/othervm TreeTest * @summary Test counting and JavaChild.spawning and counting of Processes. diff --git a/jdk/test/java/lang/StackWalker/StackStreamTest.java b/jdk/test/java/lang/StackWalker/StackStreamTest.java index af9c9706d43..a7b7e43dca6 100644 --- a/jdk/test/java/lang/StackWalker/StackStreamTest.java +++ b/jdk/test/java/lang/StackWalker/StackStreamTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -33,6 +33,7 @@ import java.util.stream.Collectors; * @test * @bug 8140450 * @summary Stack Stream Test + * @modules java.logging * @run main/othervm StackStreamTest */ public class StackStreamTest { diff --git a/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java b/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java index d93d2ee94e0..044d87145b7 100644 --- a/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java +++ b/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -30,6 +30,7 @@ import java.util.Set; * @bug 8140364 * @summary Tests System.Logger.Level names and severity. * @author danielfuchs + * @modules java.logging */ public class LoggerLevelTest { public static void main(String[] args) { diff --git a/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java b/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java index 450ba9a2fee..63ab20e2777 100644 --- a/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java +++ b/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -56,7 +56,7 @@ import java.util.stream.Stream; * @summary Tests default loggers returned by System.getLogger, and in * particular the implementation of the the System.Logger method * performed by the default binding. - * + * @modules java.logging * @build DefaultLoggerTest AccessSystemLogger * @run driver AccessSystemLogger * @run main/othervm -Xbootclasspath/a:boot DefaultLoggerTest NOSECURITY diff --git a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java index 0f7524ec242..50c789b5d60 100644 --- a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -52,6 +52,7 @@ import java.util.stream.Stream; * @bug 8140364 * @summary Tests the default implementation of System.Logger, when * JUL is the default backend. + * @modules java.logging * @build AccessSystemLogger DefaultLoggerFinderTest * @run driver AccessSystemLogger * @run main/othervm -Xbootclasspath/a:boot DefaultLoggerFinderTest NOSECURITY diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java index eca65eec03d..033a7d97315 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -52,6 +52,7 @@ import jdk.internal.logger.LazyLoggers; Tests the behavior of bootstrap loggers (and SimpleConsoleLoggers * too). * @modules java.base/jdk.internal.logger + * java.logging * @build BootstrapLoggerUtils LogStream * @run main/othervm BootstrapLoggerTest NO_SECURITY * @run main/othervm BootstrapLoggerTest SECURE diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java index 10e480fc363..c3f5e98d39c 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -58,7 +58,9 @@ import sun.util.logging.PlatformLogger; * @summary JDK implementation specific unit test for JDK internal artifacts. * Tests all bridge methods with the a custom backend whose * loggers implement PlatformLogger.Bridge. - * @modules java.base/sun.util.logging java.base/jdk.internal.logger + * @modules java.base/sun.util.logging + * java.base/jdk.internal.logger + * java.logging * @build CustomSystemClassLoader LoggerBridgeTest * @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader LoggerBridgeTest NOSECURITY * @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader LoggerBridgeTest NOPERMISSIONS diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java index f9b8eabba40..1300c9b2ecd 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -57,6 +57,7 @@ import sun.util.logging.PlatformLogger; * Tests all bridge methods from PlatformLogger with the a custom * backend whose loggers implement PlatformLogger.Bridge. * @modules java.base/sun.util.logging + * java.logging * @build CustomSystemClassLoader PlatformLoggerBridgeTest * @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader PlatformLoggerBridgeTest NOSECURITY * @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader PlatformLoggerBridgeTest NOPERMISSIONS diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java index b616ec81944..e3752b5721c 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -29,6 +29,7 @@ * Tests the consistency of the LoggerFinder and JDK extensions. * @modules java.base/sun.util.logging * java.base/jdk.internal.logger + * java.logging * @run main LoggerFinderAPITest */ diff --git a/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java b/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java index f911d5b8653..a3b9b8dddcf 100644 --- a/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java +++ b/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -28,6 +28,7 @@ import java.util.*; * @bug 8011194 * @summary Test value of file.encoding for corresponding value of LANG, etc * @library ../../../../tools/launcher/ ../ + * @modules jdk.compiler * @build TestHelper TestFileEncoding ExpectedEncoding * @run main TestFileEncoding UTF-8 * @run main/othervm -Dfile.encoding=MyEncoding -DuserEncoding=MyEncoding TestFileEncoding MyEncoding diff --git a/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java b/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java index 1973be456fd..89b958eff3e 100644 --- a/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java +++ b/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -27,9 +27,8 @@ * @summary Tests and benchmarks the JVMTI RedefineClasses when a * single class (and its parent) contains many methods. * - * @modules java.compiler + * @modules jdk.compiler * java.instrument - * jdk.compiler * @run build ManyMethodsBenchmarkApp ManyMethodsBenchmarkAgent * @run shell MakeJAR3.sh ManyMethodsBenchmarkAgent 'Can-Retransform-Classes: true' * @run main/othervm -javaagent:ManyMethodsBenchmarkAgent.jar ManyMethodsBenchmarkApp diff --git a/jdk/test/java/lang/instrument/RetransformAgent.java b/jdk/test/java/lang/instrument/RetransformAgent.java index 4e1bdac4519..920fffbb0b1 100644 --- a/jdk/test/java/lang/instrument/RetransformAgent.java +++ b/jdk/test/java/lang/instrument/RetransformAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, 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 @@ -28,6 +28,7 @@ * @author Robert Field, Sun Microsystems * * @modules java.base/jdk.internal.org.objectweb.asm + * java.instrument * @run shell/timeout=240 MakeJAR2.sh RetransformAgent RetransformApp 'Can-Retransform-Classes: true' * @run main/othervm -javaagent:RetransformAgent.jar RetransformApp */ diff --git a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java index 70dd15c6da8..a5917e589a1 100644 --- a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java +++ b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -27,6 +27,7 @@ * @summary tests DoPrivileged action (implemented as lambda expressions) by * inserting them into the BootClassPath. * @modules jdk.compiler + * jdk.zipfs * @compile -XDignore.symbol.file LambdaAccessControlDoPrivilegedTest.java LUtils.java * @run main/othervm LambdaAccessControlDoPrivilegedTest */ diff --git a/jdk/test/java/lang/invoke/lambda/LambdaAsm.java b/jdk/test/java/lang/invoke/lambda/LambdaAsm.java index 8148733923c..04faad125b6 100644 --- a/jdk/test/java/lang/invoke/lambda/LambdaAsm.java +++ b/jdk/test/java/lang/invoke/lambda/LambdaAsm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -28,6 +28,7 @@ * generate bytecodes with correct constant pool references * @modules java.base/jdk.internal.org.objectweb.asm * jdk.jdeps/com.sun.tools.classfile + * jdk.zipfs * @compile -XDignore.symbol.file LambdaAsm.java LUtils.java * @run main/othervm LambdaAsm */ diff --git a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java index 1030d27f7fe..430591a8ddc 100644 --- a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java +++ b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java @@ -26,6 +26,8 @@ * @bug 8023524 * @summary tests logging generated classes for lambda * @library /java/nio/file + * @modules jdk.compiler + * jdk.zipfs * @run testng LogGeneratedClassesTest */ import java.io.File; diff --git a/jdk/test/java/lang/ref/CleanerTest.java b/jdk/test/java/lang/ref/CleanerTest.java index 396fbed88bd..25c50dc24c1 100644 --- a/jdk/test/java/lang/ref/CleanerTest.java +++ b/jdk/test/java/lang/ref/CleanerTest.java @@ -52,7 +52,10 @@ import org.testng.annotations.Test; * @library /test/lib/share/classes /lib/testlibrary /test/lib * @build sun.hotspot.WhiteBox * @build jdk.test.lib.Utils - * @modules java.base/jdk.internal.misc java.base/jdk.internal.ref + * @modules java.base/jdk.internal + * java.base/jdk.internal.misc + * java.base/jdk.internal.ref + * java.management * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run testng/othervm * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. From 66965df3dcae7307001522385767f6f9de1f1544 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 3 Mar 2016 15:47:08 -0800 Subject: [PATCH 208/311] 8151226: Mark UdpTest.java as intermittently failing Reviewed-by: lancea --- jdk/test/java/net/ipv6tests/UdpTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/net/ipv6tests/UdpTest.java b/jdk/test/java/net/ipv6tests/UdpTest.java index 33fe7e702dd..c5272157c85 100644 --- a/jdk/test/java/net/ipv6tests/UdpTest.java +++ b/jdk/test/java/net/ipv6tests/UdpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 4868820 + * @key intermittent * @summary IPv6 support for Windows XP and 2003 server */ From 8a433e443ea78c3b7b8b755fe370f69867e4ce63 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Fri, 4 Mar 2016 13:59:43 +0800 Subject: [PATCH 209/311] 8038330: tools/jar/JarEntryTime.java fails intermittently on checking extracted file last modified values are the current times Reviewed-by: sherman, plevart --- jdk/test/tools/jar/JarEntryTime.java | 52 +++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/jdk/test/tools/jar/JarEntryTime.java b/jdk/test/tools/jar/JarEntryTime.java index 701779c2828..1985bb1ab66 100644 --- a/jdk/test/tools/jar/JarEntryTime.java +++ b/jdk/test/tools/jar/JarEntryTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, 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,8 @@ import java.io.File; import java.io.PrintWriter; import java.nio.file.attribute.FileTime; +import java.util.Date; +import java.util.TimeZone; import sun.tools.jar.Main; public class JarEntryTime { @@ -39,6 +41,9 @@ public class JarEntryTime { // allow for e.g. rounding/truncation and networked/samba drives. static final long PRECISION = 10000L; + static final TimeZone TZ = TimeZone.getDefault(); + static final boolean DST = TZ.inDaylightTime(new Date()); + static boolean cleanup(File dir) throws Throwable { boolean rc = true; File[] x = dir.listFiles(); @@ -75,11 +80,13 @@ public class JarEntryTime { File dirOuter = new File("outer"); File dirInner = new File(dirOuter, "inner"); File jarFile = new File("JarEntryTime.jar"); + File testFile = new File("JarEntryTimeTest.txt"); // Remove any leftovers from prior run cleanup(dirInner); cleanup(dirOuter); jarFile.delete(); + testFile.delete(); /* Create a directory structure * outer/ @@ -129,23 +136,39 @@ public class JarEntryTime { check(cleanup(dirInner)); check(cleanup(dirOuter)); + try (PrintWriter pw = new PrintWriter(testFile)) { + pw.println("hello, world"); + } + final long start = testFile.lastModified(); + // Extract and check the last modified values are the current times. // See sun.tools.jar.Main extractJar(jarFile, true); + + try (PrintWriter pw = new PrintWriter(testFile)) { + pw.println("hello, world"); + } + final long end = testFile.lastModified(); + check(dirOuter.exists()); check(dirInner.exists()); check(fileInner.exists()); - checkFileTime(dirOuter.lastModified(), now); - checkFileTime(dirInner.lastModified(), now); - checkFileTime(fileInner.lastModified(), now); + checkFileTime(start, dirOuter.lastModified(), end); + checkFileTime(start, dirInner.lastModified(), end); + checkFileTime(start, fileInner.lastModified(), end); check(cleanup(dirInner)); check(cleanup(dirOuter)); check(jarFile.delete()); + check(testFile.delete()); } static void checkFileTime(long now, long original) { + if (isTimeSettingChanged()) { + return; + } + if (Math.abs(now - original) > PRECISION) { System.out.format("Extracted to %s, expected to be close to %s%n", FileTime.fromMillis(now), FileTime.fromMillis(original)); @@ -153,6 +176,27 @@ public class JarEntryTime { } } + static void checkFileTime(long start, long now, long end) { + if (isTimeSettingChanged()) { + return; + } + + if (now < start || now > end) { + System.out.format("Extracted to %s, " + + "expected to be after %s and before %s%n", + FileTime.fromMillis(now), + FileTime.fromMillis(start), + FileTime.fromMillis(end)); + fail(); + } + } + + private static boolean isTimeSettingChanged() { + TimeZone currentTZ = TimeZone.getDefault(); + boolean currentDST = currentTZ.inDaylightTime(new Date()); + return (!currentTZ.equals(TZ) || currentDST != DST); + } + //--------------------- Infrastructure --------------------------- static volatile int passed = 0, failed = 0; static void pass() {passed++;} From 0708e4c089903b6833b98dc06ecc868f2191d6b3 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 3 Mar 2016 22:55:41 -0800 Subject: [PATCH 210/311] 8151228: Mark TestDSAGenParameterSpec.java as intermittently failing Reviewed-by: xuelei --- .../security/provider/NSASuiteB/TestDSAGenParameterSpec.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java index 43a857f0c26..bd2fcdadc31 100644 --- a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java +++ b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -37,6 +37,7 @@ import java.util.List; /* * @test * @bug 8075286 + * @key intermittent * @summary Verify that DSAGenParameterSpec can and can only be used to generate * DSA within some certain range of key sizes as described in the class * specification (L, N) as (1024, 160), (2048, 224), (2048, 256) and From dae73946beff2a9234112932d16c3c0edefd2c28 Mon Sep 17 00:00:00 2001 From: Ramanand Patil Date: Wed, 2 Mar 2016 23:28:59 +0530 Subject: [PATCH 211/311] 8087104: DateFormatSymbols triggers this.clone() in the constructor Instead of using its own instance for caching and calling clone in DateFormatSymbols, a nested class SymbolsCacheEntry is introduced. Reviewed-by: okutsu, peytoia --- .../classes/java/text/DateFormatSymbols.java | 65 +++++++++++++---- .../DateFormat/DFSConstructorCloneTest.java | 70 +++++++++++++++++++ 2 files changed, 122 insertions(+), 13 deletions(-) create mode 100644 jdk/test/java/text/Format/DateFormat/DFSConstructorCloneTest.java diff --git a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java index 955415af8b6..28c3fc7ba00 100644 --- a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java +++ b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -606,7 +606,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { try { DateFormatSymbols other = (DateFormatSymbols)super.clone(); - copyMembers(this, other); + copyMembers(new SymbolsCacheEntry(locale), other); return other; } catch (CloneNotSupportedException e) { throw new InternalError(e); @@ -669,7 +669,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { /** * Cache to hold DateFormatSymbols instances per Locale. */ - private static final ConcurrentMap> cachedInstances + private static final ConcurrentMap> cachedInstances = new ConcurrentHashMap<>(3); private transient int lastZoneIndex; @@ -683,10 +683,10 @@ public class DateFormatSymbols implements Serializable, Cloneable { locale = desiredLocale; // Copy values of a cached instance if any. - SoftReference ref = cachedInstances.get(locale); - DateFormatSymbols dfs; - if (ref != null && (dfs = ref.get()) != null) { - copyMembers(dfs, this); + SoftReference ref = cachedInstances.get(locale); + SymbolsCacheEntry sce; + if (ref != null && (sce = ref.get()) != null) { + copyMembers(sce, this); return; } @@ -717,11 +717,11 @@ public class DateFormatSymbols implements Serializable, Cloneable { weekdays = toOneBasedArray(resource.getStringArray("DayNames")); shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations")); - // Put a clone in the cache - ref = new SoftReference<>((DateFormatSymbols)this.clone()); - SoftReference x = cachedInstances.putIfAbsent(locale, ref); + sce = new SymbolsCacheEntry(locale); + ref = new SoftReference<>(sce); + SoftReference x = cachedInstances.putIfAbsent(locale, ref); if (x != null) { - DateFormatSymbols y = x.get(); + SymbolsCacheEntry y = x.get(); if (y == null) { // Replace the empty SoftReference with ref. cachedInstances.put(locale, ref); @@ -812,7 +812,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { * @param src the source DateFormatSymbols. * @param dst the target DateFormatSymbols. */ - private void copyMembers(DateFormatSymbols src, DateFormatSymbols dst) + private void copyMembers(SymbolsCacheEntry src, DateFormatSymbols dst) { dst.eras = Arrays.copyOf(src.eras, src.eras.length); dst.months = Arrays.copyOf(src.months, src.months.length); @@ -821,7 +821,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { dst.shortWeekdays = Arrays.copyOf(src.shortWeekdays, src.shortWeekdays.length); dst.ampms = Arrays.copyOf(src.ampms, src.ampms.length); if (src.zoneStrings != null) { - dst.zoneStrings = src.getZoneStringsImpl(true); + dst.zoneStrings = getZoneStringsImpl(true); } else { dst.zoneStrings = null; } @@ -842,4 +842,43 @@ public class DateFormatSymbols implements Serializable, Cloneable { } stream.defaultWriteObject(); } + + private static class SymbolsCacheEntry { + + final String eras[]; + final String months[]; + final String shortMonths[]; + final String weekdays[]; + final String shortWeekdays[]; + final String ampms[]; + final String zoneStrings[][]; + final String localPatternChars; + + SymbolsCacheEntry(Locale locale) { + // Initialize the fields from the ResourceBundle for locale. + LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale); + // Avoid any potential recursions + if (!(adapter instanceof ResourceBundleBasedAdapter)) { + adapter = LocaleProviderAdapter.getResourceBundleBased(); + } + ResourceBundle resource = ((ResourceBundleBasedAdapter) adapter).getLocaleData().getDateFormatData(locale); + if (resource.containsKey("Eras")) { + this.eras = resource.getStringArray("Eras"); + } else if (resource.containsKey("long.Eras")) { + this.eras = resource.getStringArray("long.Eras"); + } else if (resource.containsKey("short.Eras")) { + this.eras = resource.getStringArray("short.Eras"); + } else { + this.eras = null; + } + this.months = resource.getStringArray("MonthNames"); + this.shortMonths = resource.getStringArray("MonthAbbreviations"); + this.weekdays = toOneBasedArray(resource.getStringArray("DayNames")); + this.shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations")); + this.ampms = resource.getStringArray("AmPmMarkers"); + this.zoneStrings = TimeZoneNameUtility.getZoneStrings(locale); + this.localPatternChars = resource.getString("DateTimePatternChars"); + + } + } } diff --git a/jdk/test/java/text/Format/DateFormat/DFSConstructorCloneTest.java b/jdk/test/java/text/Format/DateFormat/DFSConstructorCloneTest.java new file mode 100644 index 00000000000..8632f0932cc --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/DFSConstructorCloneTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016, 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 8087104 + * @summary Make sure that clone() method is not called from DateFormatSymbols constructor. + */ +import java.text.DateFormatSymbols; + +public class DFSymbolsCloneTest extends DateFormatSymbols { + + private Foo foo; + + public DFSymbolsCloneTest(Foo fooObj) { + if (fooObj == null) { + this.foo = new Foo(); + } else { + this.foo = fooObj; + } + } + + @Override + public Object clone() { + DFSymbolsCloneTest dfsclone = (DFSymbolsCloneTest) super.clone(); + if (this.foo == null) { + throw new RuntimeException("Clone method should not be called from " + + " Superclass(DateFormatSymbols) Constructor..."); + } else { + dfsclone.foo = (Foo) this.foo.clone(); + } + return dfsclone; + } + + public static void main(String[] args) { + DFSymbolsCloneTest dfsctest = new DFSymbolsCloneTest(new Foo()); + } +} + +class Foo { + + public Foo() { + } + + @Override + protected Object clone() { + return new Foo(); + } + +} From 29383473b186a5afe2144e6944e86b85dea4cb7e Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Wed, 2 Mar 2016 14:52:35 -0500 Subject: [PATCH 212/311] 8145098: JNI GetVersion should return JNI_VERSION_9 Updated JNI_VERSION for current version to be JNI_VERSION_9 Reviewed-by: hseigel, gtriantafill, dholmes, alanb --- jdk/src/java.base/share/native/include/jni.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/native/include/jni.h b/jdk/src/java.base/share/native/include/jni.h index 2e83cb7e06e..c09658a1fa7 100644 --- a/jdk/src/java.base/share/native/include/jni.h +++ b/jdk/src/java.base/share/native/include/jni.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -1952,6 +1952,7 @@ JNI_OnUnload(JavaVM *vm, void *reserved); #define JNI_VERSION_1_4 0x00010004 #define JNI_VERSION_1_6 0x00010006 #define JNI_VERSION_1_8 0x00010008 +#define JNI_VERSION_9 0x00090000 #ifdef __cplusplus } /* extern "C" */ From b7658ef0b7f0af83426ec4164b6747bb466db070 Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Wed, 2 Mar 2016 15:10:38 -0500 Subject: [PATCH 213/311] 8145098: JNI GetVersion should return JNI_VERSION_9 Updated JNI_VERSION for current version to be JNI_VERSION_9 Reviewed-by: hseigel, gtriantafill, dholmes, alanb --- hotspot/src/share/vm/prims/jni.cpp | 2 +- hotspot/src/share/vm/prims/jni.h | 3 ++- hotspot/src/share/vm/runtime/thread.cpp | 1 + hotspot/test/native_sanity/JniVersion.java | 6 +++--- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index ffca3342ebd..40e3c92668a 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -89,7 +89,7 @@ #include "jvmci/jvmciRuntime.hpp" #endif -static jint CurrentVersion = JNI_VERSION_1_8; +static jint CurrentVersion = JNI_VERSION_9; #ifdef _WIN32 extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* ); diff --git a/hotspot/src/share/vm/prims/jni.h b/hotspot/src/share/vm/prims/jni.h index 582f2c97024..564499f83da 100644 --- a/hotspot/src/share/vm/prims/jni.h +++ b/hotspot/src/share/vm/prims/jni.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -1952,6 +1952,7 @@ JNI_OnUnload(JavaVM *vm, void *reserved); #define JNI_VERSION_1_4 0x00010004 #define JNI_VERSION_1_6 0x00010006 #define JNI_VERSION_1_8 0x00010008 +#define JNI_VERSION_9 0x00090000 #ifdef __cplusplus } /* extern "C" */ diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index a411b6868dc..fb5e56e8bdc 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -4133,6 +4133,7 @@ jboolean Threads::is_supported_jni_version(jint version) { if (version == JNI_VERSION_1_4) return JNI_TRUE; if (version == JNI_VERSION_1_6) return JNI_TRUE; if (version == JNI_VERSION_1_8) return JNI_TRUE; + if (version == JNI_VERSION_9) return JNI_TRUE; return JNI_FALSE; } diff --git a/hotspot/test/native_sanity/JniVersion.java b/hotspot/test/native_sanity/JniVersion.java index a85a184c241..e1451d2e9a5 100644 --- a/hotspot/test/native_sanity/JniVersion.java +++ b/hotspot/test/native_sanity/JniVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -27,12 +27,12 @@ */ public class JniVersion { - public static final int JNI_VERSION_1_8 = 0x00010008; + public static final int JNI_VERSION_9 = 0x00090000; public static void main(String... args) throws Exception { System.loadLibrary("JniVersion"); int res = getJniVersion(); - if (res < JNI_VERSION_1_8) { + if (res != JNI_VERSION_9) { throw new Exception("Unexpected value returned from getJniVersion(): 0x" + Integer.toHexString(res)); } } From 311e77373d270bf6b2328677562ff402b55ab6f9 Mon Sep 17 00:00:00 2001 From: Gerard Ziemski Date: Wed, 2 Mar 2016 14:36:55 -0600 Subject: [PATCH 214/311] 8146849: Remove TraceJNIHandleAllocation rather than converting to UL Removed TraceJNIHandleAllocation Reviewed-by: coleenp, dholmes --- hotspot/src/share/vm/runtime/globals.hpp | 3 --- hotspot/src/share/vm/runtime/jniHandles.cpp | 10 +--------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 672b3c340ab..28ecd890b5e 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1433,9 +1433,6 @@ public: product(bool, VerifyMergedCPBytecodes, true, \ "Verify bytecodes after RedefineClasses constant pool merging") \ \ - develop(bool, TraceJNIHandleAllocation, false, \ - "Trace allocation/deallocation of JNI handle blocks") \ - \ develop(bool, TraceBytecodes, false, \ "Trace bytecode execution") \ \ diff --git a/hotspot/src/share/vm/runtime/jniHandles.cpp b/hotspot/src/share/vm/runtime/jniHandles.cpp index 3c4baed8e0e..8e4636bf640 100644 --- a/hotspot/src/share/vm/runtime/jniHandles.cpp +++ b/hotspot/src/share/vm/runtime/jniHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -278,10 +278,6 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread) { // Allocate new block block = new JNIHandleBlock(); _blocks_allocated++; - if (TraceJNIHandleAllocation) { - tty->print_cr("JNIHandleBlock " INTPTR_FORMAT " allocated (%d total blocks)", - p2i(block), _blocks_allocated); - } if (ZapJNIHandleArea) block->zap(); #ifndef PRODUCT // Link new block to list of all allocated blocks @@ -499,10 +495,6 @@ void JNIHandleBlock::rebuild_free_list() { // Not as many free handles as we would like - compute number of new blocks to append _allocate_before_rebuild = (extra + block_size_in_oops - 1) / block_size_in_oops; } - if (TraceJNIHandleAllocation) { - tty->print_cr("Rebuild free list JNIHandleBlock " INTPTR_FORMAT " blocks=%d used=%d free=%d add=%d", - p2i(this), blocks, total-free, free, _allocate_before_rebuild); - } } From 41988936d3f33e2526cc00fa6f97bfd86de7c915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Wed, 2 Mar 2016 21:39:03 +0100 Subject: [PATCH 215/311] 8151053: com/sun/jdi/StepTest.java fails in 2016-03-01 JDK9-hs-rt nightly Reviewed-by: dcubed, egahlin --- jdk/test/com/sun/jdi/TestScaffold.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/com/sun/jdi/TestScaffold.java b/jdk/test/com/sun/jdi/TestScaffold.java index 079733509e0..f221221a1de 100644 --- a/jdk/test/com/sun/jdi/TestScaffold.java +++ b/jdk/test/com/sun/jdi/TestScaffold.java @@ -752,6 +752,7 @@ abstract public class TestScaffold extends TargetAdapter { sr.addClassExclusionFilter("com.oracle.*"); sr.addClassExclusionFilter("oracle.*"); sr.addClassExclusionFilter("jdk.internal.*"); + sr.addClassExclusionFilter("jdk.jfr.*"); sr.addCountFilter(1); sr.enable(); StepEvent retEvent = (StepEvent)waitForRequestedEvent(sr); From 5b14d73a6321004804b8ca97e82b9e5c81dc8cf6 Mon Sep 17 00:00:00 2001 From: Bhavesh Patel Date: Wed, 2 Mar 2016 21:27:01 +0000 Subject: [PATCH 216/311] 8148985: javadoc "FRAMES" and "NO FRAMES" links not working correctly Reviewed-by: jjg, ksrini --- .../tools/doclets/formats/html/FrameOutputWriter.java | 3 ++- .../tools/doclets/formats/html/markup/HtmlWriter.java | 6 +++++- .../doclets/formats/html/FrameOutputWriter.java | 2 ++ .../doclets/formats/html/markup/HtmlWriter.java | 4 ++++ .../sun/javadoc/testHtmlVersion/TestHtmlVersion.java | 8 ++++---- .../sun/javadoc/testJavascript/TestJavascript.java | 9 ++++++++- .../doclet/testHtmlVersion/TestHtmlVersion.java | 8 ++++---- .../javadoc/doclet/testJavascript/TestJavascript.java | 11 +++++++++-- 8 files changed, 38 insertions(+), 13 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java index 037d7fa77eb..66408158a9b 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -96,6 +96,7 @@ public class FrameOutputWriter extends HtmlDocletWriter { protected void generateFrameFile() throws IOException { Content frame = getFrameDetails(); HtmlTree body = new HtmlTree(HtmlTag.BODY); + body.addAttr(HtmlAttr.ONLOAD, "loadFrames()"); if (configuration.allowTag(HtmlTag.MAIN)) { HtmlTree main = HtmlTree.MAIN(frame); body.addContent(main); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java index 5c5d65b3585..2107273913f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -423,6 +423,10 @@ public class HtmlWriter { " }" + DocletConstants.NL + " }" + DocletConstants.NL + " return true;" + DocletConstants.NL + + " }" + DocletConstants.NL + + " function loadFrames() {" + DocletConstants.NL + + " if (targetPage != \"\" && targetPage != \"undefined\")" + DocletConstants.NL + + " top.classFrame.location = top.targetPage;" + DocletConstants.NL + " }" + DocletConstants.NL; RawHtml scriptContent = new RawHtml(scriptCode); script.addContent(scriptContent); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java index 69be1be292e..fa8e8ee3d92 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java @@ -27,6 +27,7 @@ package jdk.javadoc.internal.doclets.formats.html; import java.io.*; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -102,6 +103,7 @@ public class FrameOutputWriter extends HtmlDocletWriter { protected void generateFrameFile() throws IOException { Content frame = getFrameDetails(); HtmlTree body = new HtmlTree(HtmlTag.BODY); + body.addAttr(HtmlAttr.ONLOAD, "loadFrames()"); if (configuration.allowTag(HtmlTag.MAIN)) { HtmlTree main = HtmlTree.MAIN(frame); body.addContent(main); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java index 589f342ef79..88c93108672 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java @@ -401,6 +401,10 @@ public class HtmlWriter { " }" + DocletConstants.NL + " }" + DocletConstants.NL + " return true;" + DocletConstants.NL + + " }" + DocletConstants.NL + + " function loadFrames() {" + DocletConstants.NL + + " if (targetPage != \"\" && targetPage != \"undefined\")" + DocletConstants.NL + + " top.classFrame.location = top.targetPage;" + DocletConstants.NL + " }" + DocletConstants.NL; RawHtml scriptContent = new RawHtml(scriptCode); script.addContent(scriptContent); diff --git a/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java b/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java index 617677363b9..9d1f63cd927 100644 --- a/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java +++ b/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 8072945 8081854 8141492 + * @bug 8072945 8081854 8141492 8148985 * @summary Test the version of HTML generated by the javadoc tool. * @author bpatel * @library ../lib @@ -688,7 +688,7 @@ public class TestHtmlVersion extends JavadocTester { checkOutput("index.html", true, "", "", - "\n" + "\n" + "
          \n" + "
          \n" + "
          \n" @@ -1599,7 +1599,7 @@ public class TestHtmlVersion extends JavadocTester { checkOutput("index.html", true, "", "", - "\n" + "\n" + "
          \n" + "
          \n" + "
          \n" diff --git a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java index 866e238fbef..652ef6690fe 100644 --- a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java +++ b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, 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 @@ -100,8 +100,15 @@ public class TestJavascript extends JavadocTester { + " }\n" + " return true;\n" + " }\n" + + " function loadFrames() {\n" + + " if (targetPage != \"\" && targetPage != \"undefined\")\n" + + " top.classFrame.location = top.targetPage;\n" + + " }\n" + ""); + checkOutput("index.html", true, + "", "", - "\n" + "\n" + "
          \n" + "
          \n" + "
          \n" @@ -1391,7 +1391,7 @@ public class TestHtmlVersion extends JavadocTester { checkOutput("index.html", true, "", "", - "\n" + "\n" + "
          \n" + "
          \n" + "
          \n" diff --git a/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java b/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java index 866e238fbef..21eb3ab69b9 100644 --- a/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java +++ b/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, 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 4665566 4855876 7025314 8012375 8015997 8016328 8024756 + * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756 8148985 * @summary Verify that the output has the right javascript. * @author jamieh * @library ../lib @@ -100,8 +100,15 @@ public class TestJavascript extends JavadocTester { + " }\n" + " return true;\n" + " }\n" + + " function loadFrames() {\n" + + " if (targetPage != \"\" && targetPage != \"undefined\")\n" + + " top.classFrame.location = top.targetPage;\n" + + " }\n" + ""); + checkOutput("index.html", true, + " Date: Wed, 2 Mar 2016 15:00:22 -0800 Subject: [PATCH 217/311] 8150895: Fix bug id in test for JDK-8149842 Reviewed-by: bpatel --- .../test/jdk/javadoc/doclet/testIncluded/TestIncluded.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java b/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java index 2abe9f05a29..3b16b9085d3 100644 --- a/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java +++ b/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8149468 + * @bug 8149842 * @summary Verify that non included classes are not inspected. * @library ../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool From 433d2a7dbb147a96b2b8f5bbe8f79f3ba270d0f5 Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Thu, 3 Mar 2016 06:10:58 +0530 Subject: [PATCH 218/311] 8151018: javac should emit a clearer diagnostic when a <> inferred anonymous type's non-private methods don't override super's Reviewed-by: mcimadamore --- .../com/sun/tools/javac/comp/Check.java | 7 +++- .../tools/javac/resources/compiler.properties | 8 ++++ .../DiamondMethodDoesNotOverride.java | 37 +++++++++++++++++++ .../javac/generics/diamond/neg/Neg15.out | 6 +-- 4 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 langtools/test/tools/javac/diags/examples/DiamondMethodDoesNotOverride.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index 357e44b1913..4b0b3a1a42c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -2001,10 +2001,11 @@ public class Check { } } + final boolean explicitOverride = m.attribute(syms.overrideType.tsym) != null; // Check if this method must override a super method due to being annotated with @Override // or by virtue of being a member of a diamond inferred anonymous class. Latter case is to // be treated "as if as they were annotated" with @Override. - boolean mustOverride = m.attribute(syms.overrideType.tsym) != null || + boolean mustOverride = explicitOverride || (env.info.isAnonymousDiamond && !m.isConstructor() && !m.isPrivate()); if (mustOverride && !isOverrider(m)) { DiagnosticPosition pos = tree.pos(); @@ -2014,7 +2015,9 @@ public class Check { break; } } - log.error(pos, "method.does.not.override.superclass"); + log.error(pos, + explicitOverride ? Errors.MethodDoesNotOverrideSuperclass : + Errors.AnonymousDiamondMethodDoesNotOverrideSuperclass(Fragments.DiamondAnonymousMethodsImplicitlyOverride)); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 281d8e82656..21945462c6f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -214,6 +214,11 @@ compiler.err.bad.functional.intf.anno.1=\ Unexpected @FunctionalInterface annotation\n\ {0} +# 0: message segment +compiler.err.anonymous.diamond.method.does.not.override.superclass=\ + method does not override or implement a method from a supertype\n\ + {0} + # 0: symbol compiler.misc.not.a.functional.intf=\ {0} is not a functional interface @@ -1196,6 +1201,9 @@ compiler.misc.fatal.err.cant.close=\ ## miscellaneous strings ## +compiler.misc.diamond.anonymous.methods.implicitly.override=\ + (due to <>, every non-private method declared in this anonymous class must override or implement a method from a supertype) + compiler.misc.source.unavailable=\ (source unavailable) diff --git a/langtools/test/tools/javac/diags/examples/DiamondMethodDoesNotOverride.java b/langtools/test/tools/javac/diags/examples/DiamondMethodDoesNotOverride.java new file mode 100644 index 00000000000..6f84ae482d2 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DiamondMethodDoesNotOverride.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 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. + */ + +// key: compiler.err.anonymous.diamond.method.does.not.override.superclass +// key: compiler.misc.diamond.anonymous.methods.implicitly.override + +class X { + interface Foo { + void g(T t); + } + void m() { + Foo fs = new Foo<>() { + public void g(String s) { } + void someMethod() { } + }; + } +} diff --git a/langtools/test/tools/javac/generics/diamond/neg/Neg15.out b/langtools/test/tools/javac/generics/diamond/neg/Neg15.out index 1e6f1efa8ac..9d2d1b3a378 100644 --- a/langtools/test/tools/javac/generics/diamond/neg/Neg15.out +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg15.out @@ -1,4 +1,4 @@ -Neg15.java:48:28: compiler.err.method.does.not.override.superclass -Neg15.java:52:21: compiler.err.method.does.not.override.superclass -Neg15.java:56:31: compiler.err.method.does.not.override.superclass +Neg15.java:48:28: compiler.err.anonymous.diamond.method.does.not.override.superclass: (compiler.misc.diamond.anonymous.methods.implicitly.override) +Neg15.java:52:21: compiler.err.anonymous.diamond.method.does.not.override.superclass: (compiler.misc.diamond.anonymous.methods.implicitly.override) +Neg15.java:56:31: compiler.err.anonymous.diamond.method.does.not.override.superclass: (compiler.misc.diamond.anonymous.methods.implicitly.override) 3 errors From c29b38613a99385ef0abce86121b17acb038fca9 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Thu, 3 Mar 2016 12:20:11 +0530 Subject: [PATCH 219/311] 8044788: [D3D] clip is ignored during surface->sw blit Co-authored-by: Prahalad Narayanan Reviewed-by: serb, prr --- .../classes/sun/java2d/d3d/D3DBlitLoops.java | 87 +++++++++++++++++++ .../DrawImage/IncorrectClipSurface2SW.java | 4 +- 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java index 93dc53d4f27..8f4da91eef2 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java @@ -500,6 +500,7 @@ class D3DRTTSurfaceToSurfaceTransform extends TransformBlit { class D3DSurfaceToSwBlit extends Blit { private int typeval; + private WeakReference srcTmp; // REMIND: destination will actually be opaque/premultiplied... D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) { @@ -509,11 +510,97 @@ class D3DSurfaceToSwBlit extends Blit { this.typeval = typeval; } + /* + * Clip value is ignored in D3D SurfaceToSw blit. + * Root Cause: The native interfaces to D3D use StretchRect API followed + * by custom copy of pixels from Surface to Sysmem. As a result, clipping + * in D3DSurfaceToSw works 'only' for Rect clips, provided, proper srcX, + * srcY, dstX, dstY, width and height are passed to native interfaces. + * Non rect clips (For example: Shape clips) are ignored completely. + * + * Solution: There are three solutions possible to fix this issue. + * 1. Convert the entire Surface to Sysmem and perform regular Blit. + * An optimized version of this is to take up the conversion only + * when Shape clips are needed. Existing native interface will suffice + * for supporting Rect clips. + * 2. With help of existing classes we could perform SwToSurface, + * SurfaceToSurface (implements clip) and SurfaceToSw (complete copy) + * in order. + * 3. Modify the native D3D interface to accept clip and perform same logic + * as the second approach but at native side. + * + * Upon multiple experiments, the first approach has been found to be + * faster than the others as it deploys 1-draw/copy operation for rect clip + * and 2-draw/copy operations for shape clip compared to 3-draws/copy + * operations deployed by the remaining approaches. + * + * complexClipBlit method helps to convert or copy the contents from + * D3DSurface onto Sysmem and perform a regular Blit with the clip + * information as required. This method is used when non-rectangular + * clip is needed. + */ + private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst, + Composite comp, Region clip, + int sx, int sy, int dx, int dy, + int w, int h) { + SurfaceData cachedSrc = null; + if (srcTmp != null) { + // use cached intermediate surface, if available + cachedSrc = srcTmp.get(); + } + + // Type- indicates the pixel format of Sysmem based BufferedImage. + // Native d3d interfaces support on the fly conversion of pixels from + // d3d surface to destination sysmem memory of type IntARGB only. + final int type = BufferedImage.TYPE_INT_ARGB; + src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type); + + // copy intermediate SW to destination SW using complex clip + final Blit performop = Blit.getFromCache(src.getSurfaceType(), + CompositeType.SrcNoEa, + dst.getSurfaceType()); + performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h); + + if (src != cachedSrc) { + // cache the intermediate surface + srcTmp = new WeakReference<>(src); + } + } + public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) { + if (clip != null) { + clip = clip.getIntersectionXYWH(dx, dy, w, h); + // At the end this method will flush the RenderQueue, we should exit + // from it as soon as possible. + if (clip.isEmpty()) { + return; + } + + // Adjust final dst(x,y) and src(x,y) based on the clip. The + // logic is that, when clip limits drawing on the destination, + // corresponding pixels from the src should be skipped. + sx += clip.getLoX() - dx; + sy += clip.getLoY() - dy; + dx = clip.getLoX(); + dy = clip.getLoY(); + w = clip.getWidth(); + h = clip.getHeight(); + + // Check if the clip is Rectangular. For non-rectangular clips + // complexClipBlit will convert Surface To Sysmem and perform + // regular Blit. + if (!clip.isRectangular()) { + complexClipBlit(src, dst, comp, clip, + sx, sy, dx, dy, + w, h); + return; + } + } + D3DRenderQueue rq = D3DRenderQueue.getInstance(); rq.lock(); try { diff --git a/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java b/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java index 3c972b661ea..7e493506be1 100644 --- a/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java +++ b/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java @@ -42,11 +42,11 @@ import static java.awt.geom.Rectangle2D.Double; /** * @test - * @bug 8041644 + * @bug 8041644 8044788 * @summary Tests drawing volatile image to BI using different clip. * Results of the blit compatibleImage to BI used for comparison. * @author Sergey Bylokhov - * @run main/othervm -Dsun.java2d.d3d=false IncorrectClipSurface2SW + * @run main/othervm IncorrectClipSurface2SW */ public final class IncorrectClipSurface2SW { From e243f516e75d285a69b38888537a31cfa5fa4456 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Thu, 3 Mar 2016 12:34:41 +0530 Subject: [PATCH 220/311] 8138749: Revisited: PrinterJob.printDialog() does not support multi-mon, always displayed on primary Reviewed-by: prr, jdv --- .../share/classes/javax/print/ServiceUI.java | 40 ++++-- .../classes/sun/print/RasterPrinterJob.java | 64 +++++++-- .../PrinterJob/MultiMonPrintDlgTest.java | 125 ++++++++++++++++++ 3 files changed, 203 insertions(+), 26 deletions(-) create mode 100644 jdk/test/java/awt/print/PrinterJob/MultiMonPrintDlgTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java b/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java index 520d508c3b5..fede6e1b85c 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java +++ b/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java @@ -193,36 +193,48 @@ public class ServiceUI { getLocalGraphicsEnvironment().getDefaultScreenDevice(). getDefaultConfiguration().getBounds() : gc.getBounds(); + x += gcBounds.x; + y += gcBounds.y; ServiceDialog dialog; if (owner instanceof Frame) { dialog = new ServiceDialog(gc, - x + gcBounds.x, - y + gcBounds.y, + x, + y, services, defaultIndex, flavor, attributes, (Frame)owner); } else { dialog = new ServiceDialog(gc, - x + gcBounds.x, - y + gcBounds.y, + x, + y, services, defaultIndex, flavor, attributes, (Dialog)owner); } Rectangle dlgBounds = dialog.getBounds(); - // get union of all GC bounds - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] gs = ge.getScreenDevices(); - for (int j=0; j gcBounds.x + gcBounds.width) { + if ((gcBounds.x + gcBounds.width - dlgBounds.width) > gcBounds.x) { + x = (gcBounds.x + gcBounds.width) - dlgBounds.width; + } else { + x = gcBounds.x; + } + } + if (dlgBounds.y + dlgBounds.height > gcBounds.y + gcBounds.height) { + if ((gcBounds.y + gcBounds.height - dlgBounds.height) > gcBounds.y) { + y = (gcBounds.y + gcBounds.height) - dlgBounds.height; + } else { + y = gcBounds.y; + } + } + dialog.setBounds(x, y, dlgBounds.width, dlgBounds.height); } dialog.show(); diff --git a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index 1ffb6a18e1d..7ba84ab1630 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -791,12 +791,15 @@ public abstract class RasterPrinterJob extends PrinterJob { return page; } - final GraphicsConfiguration gc = - GraphicsEnvironment.getLocalGraphicsEnvironment(). - getDefaultScreenDevice().getDefaultConfiguration(); - Rectangle bounds = gc.getBounds(); - int x = bounds.x+bounds.width/3; - int y = bounds.y+bounds.height/3; + GraphicsConfiguration grCfg = null; + Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + if (w != null) { + grCfg = w.getGraphicsConfiguration(); + } else { + grCfg = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + } + final GraphicsConfiguration gc = grCfg; PrintService service = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -814,9 +817,39 @@ public abstract class RasterPrinterJob extends PrinterJob { return null; } + // we position the dialog a little beyond the upper-left corner of the window + // which is consistent with the NATIVE page dialog + Rectangle gcBounds = gc.getBounds(); + int x = gcBounds.x+50; + int y = gcBounds.y+50; ServiceDialog pageDialog = new ServiceDialog(gc, x, y, service, DocFlavor.SERVICE_FORMATTED.PAGEABLE, attributes, (Frame)null); + Rectangle dlgBounds = pageDialog.getBounds(); + + // if portion of dialog is not within the gc boundary + if (!gcBounds.contains(dlgBounds)) { + // check if dialog exceed window bounds at left or bottom + // Then position the dialog by moving it by the amount it exceeds + // the window bounds + // If it results in dialog moving beyond the window bounds at top/left + // then position it at window top/left + if (dlgBounds.x + dlgBounds.width > gcBounds.x + gcBounds.width) { + if ((gcBounds.x + gcBounds.width - dlgBounds.width) > gcBounds.x) { + x = (gcBounds.x + gcBounds.width) - dlgBounds.width; + } else { + x = gcBounds.x; + } + } + if (dlgBounds.y + dlgBounds.height > gcBounds.y + gcBounds.height) { + if ((gcBounds.y + gcBounds.height - dlgBounds.height) > gcBounds.y) { + y = (gcBounds.y + gcBounds.height) - dlgBounds.height; + } else { + y = gcBounds.y; + } + } + pageDialog.setBounds(x, y, dlgBounds.width, dlgBounds.height); + } pageDialog.show(); if (pageDialog.getStatus() == ServiceDialog.APPROVE) { @@ -893,9 +926,15 @@ public abstract class RasterPrinterJob extends PrinterJob { * We raise privilege when we put up the dialog, to avoid * the "warning applet window" banner. */ - final GraphicsConfiguration gc = - GraphicsEnvironment.getLocalGraphicsEnvironment(). - getDefaultScreenDevice().getDefaultConfiguration(); + GraphicsConfiguration grCfg = null; + Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + if (w != null) { + grCfg = w.getGraphicsConfiguration(); + } else { + grCfg = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + } + final GraphicsConfiguration gc = grCfg; PrintService service = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -940,9 +979,10 @@ public abstract class RasterPrinterJob extends PrinterJob { } } - Rectangle bounds = gc.getBounds(); - int x = bounds.x+bounds.width/3; - int y = bounds.y+bounds.height/3; + // we position the dialog a little beyond the upper-left corner of the window + // which is consistent with the NATIVE print dialog + int x = 50; + int y = 50; PrintService newService; // temporarily add an attribute pointing back to this job. PrinterJobWrapper jobWrapper = new PrinterJobWrapper(this); diff --git a/jdk/test/java/awt/print/PrinterJob/MultiMonPrintDlgTest.java b/jdk/test/java/awt/print/PrinterJob/MultiMonPrintDlgTest.java new file mode 100644 index 00000000000..013de39b8a1 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/MultiMonPrintDlgTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2015, 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.awt.Button; +import java.awt.Component; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.KeyboardFocusManager; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +/** + * @test + * @bug 8138749 + * @summary PrinterJob.printDialog() does not support multi-mon, + * always displayed on primary + * @run main/manual MultiMonPrintDlgTest + */ +public class MultiMonPrintDlgTest implements ActionListener { + + Frame primaryFrame = null; + Frame secFrame = null; + GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getScreenDevices(); + + public MultiMonPrintDlgTest() throws Exception { + if (gd.length <= 1) { + System.out.println("This test should be run only on dual-monitor systems. Aborted!!"); + return; + } + + String[] instructions = + { + " This test should be running on a dual-monitor setup.", + "A frame will be created on each of the 2 monitor. ", + "Click the Print button on the frame displayed in the non-default monitor.", + "Please verify that page dialog followed by print dialog ", + " is displayed in the same screen", + "where the frame is located ie, in the non-default monitor.", + }; + + SwingUtilities.invokeAndWait(() -> { + JOptionPane.showMessageDialog( + (Component) null, + instructions, + "information", JOptionPane.INFORMATION_MESSAGE); + }); + GraphicsDevice defDev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); + int x = 0; + Frame f = null; + for (x = 0; x < gd.length; x ++) { + if (gd[x] != defDev) { + secFrame = new Frame("Screen " + x + " - secondary", gd[x].getDefaultConfiguration()); + f = secFrame; + } else { + primaryFrame = new Frame("Screen " + x + " - primary", gd[x].getDefaultConfiguration()); + f = primaryFrame; + } + Button b = new Button("Print"); + b.addActionListener(this); + f.add("South", b); + f.addWindowListener (new WindowAdapter() { + public void windowClosing(WindowEvent we) { + ((Window) we.getSource()).dispose(); + } + }); + f.setSize(200, 200); + f.setVisible(true); + } + } + + public void actionPerformed (ActionEvent ae) { + try { + javax.print.attribute.PrintRequestAttributeSet prSet = + new javax.print.attribute.HashPrintRequestAttributeSet(); + java.awt.print.PrinterJob.getPrinterJob().pageDialog(prSet); + Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + int dialogButton = JOptionPane.showConfirmDialog (w, + "Did the pageDialog shown in non-default monitor?", + null, JOptionPane.YES_NO_OPTION); + if(dialogButton == JOptionPane.NO_OPTION) { + throw new RuntimeException("PageDialog is shown in wrong monitor"); + } + java.awt.print.PrinterJob.getPrinterJob().printDialog(prSet); + dialogButton = JOptionPane.showConfirmDialog (w, + "Did the printDialog shown in non-default monitor?", + null, JOptionPane.YES_NO_OPTION); + if(dialogButton == JOptionPane.NO_OPTION) { + throw new RuntimeException("PrintDialog is shown in wrong monitor"); + } + } finally { + primaryFrame.dispose(); + secFrame.dispose(); + } + } + + public static void main (String args[]) throws Exception { + MultiMonPrintDlgTest test = new MultiMonPrintDlgTest(); + } +} From 20ebb13fb50590c35fee37e72c6543b9ecfe9914 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Thu, 3 Mar 2016 08:58:00 +0100 Subject: [PATCH 221/311] 8151024: Remove TCKJapaneseChronology.java from the problem list Remove TCKJapaneseChronology.java from the problem list after JDK-8134979 was fixed. Reviewed-by: vlivanov --- jdk/test/ProblemList.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 8e1c6a6a1e1..5296f830828 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -334,9 +334,6 @@ javax/imageio/plugins/tiff/WriteToSequenceAfterAbort.java generic-all # jdk_time -# 8134979 -java/time/tck/java/time/chrono/TCKJapaneseChronology.java generic-all - ############################################################################ # jdk_tools From 2cfacfc3a461b48e024155f10eb6e63ad3125ee3 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Thu, 3 Mar 2016 11:28:48 +0300 Subject: [PATCH 222/311] 8150723: HSDB toolbar icons are missing Reviewed-by: erikj, dsamersoff --- .../toolbarButtonGraphics/development/Server16.gif | Bin .../toolbarButtonGraphics/development/Server24.gif | Bin .../toolbarButtonGraphics/general/About16.gif | Bin .../toolbarButtonGraphics/general/About24.gif | Bin .../toolbarButtonGraphics/general/Delete16.gif | Bin .../toolbarButtonGraphics/general/Delete24.gif | Bin .../toolbarButtonGraphics/general/Find16.gif | Bin .../toolbarButtonGraphics/general/Help16.gif | Bin .../toolbarButtonGraphics/general/Help24.gif | Bin .../toolbarButtonGraphics/general/History16.gif | Bin .../toolbarButtonGraphics/general/History24.gif | Bin .../toolbarButtonGraphics/general/Information16.gif | Bin .../toolbarButtonGraphics/general/Information24.gif | Bin .../toolbarButtonGraphics/general/New16.gif | Bin .../toolbarButtonGraphics/general/New24.gif | Bin .../toolbarButtonGraphics/general/Open16.gif | Bin .../toolbarButtonGraphics/general/Open24.gif | Bin .../toolbarButtonGraphics/general/Save24.gif | Bin .../toolbarButtonGraphics/general/SaveAs16.gif | Bin .../toolbarButtonGraphics/general/SaveAs24.gif | Bin .../toolbarButtonGraphics/general/Zoom16.gif | Bin .../toolbarButtonGraphics/general/ZoomIn16.gif | Bin .../toolbarButtonGraphics/general/ZoomIn24.gif | Bin .../toolbarButtonGraphics/navigation/Down16.gif | Bin .../toolbarButtonGraphics/navigation/Up16.gif | Bin .../toolbarButtonGraphics/text/AlignCenter16.gif | Bin .../toolbarButtonGraphics/text/AlignCenter24.gif | Bin .../toolbarButtonGraphics/text/AlignLeft16.gif | Bin .../toolbarButtonGraphics/text/AlignLeft24.gif | Bin .../toolbarButtonGraphics/text/AlignRight16.gif | Bin .../toolbarButtonGraphics/text/AlignRight24.gif | Bin 31 files changed, 0 insertions(+), 0 deletions(-) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/development/Server16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/development/Server24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/About16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/About24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Delete16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Delete24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Find16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Help16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Help24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/History16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/History24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Information16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Information24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/New16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/New24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Open16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Open24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Save24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/SaveAs16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/SaveAs24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/Zoom16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/ZoomIn16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/general/ZoomIn24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/navigation/Down16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/navigation/Up16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/text/AlignCenter16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/text/AlignCenter24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/text/AlignLeft16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/text/AlignLeft24.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/text/AlignRight16.gif (100%) rename hotspot/src/jdk.hotspot.agent/share/classes/{images => }/toolbarButtonGraphics/text/AlignRight24.gif (100%) diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Find16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Find16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Find16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Find16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Save24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Save24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Save24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Save24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Zoom16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Zoom16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Zoom16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Zoom16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Down16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Down16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Down16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Down16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Up16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Up16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Up16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Up16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight24.gif From 460020d183a15f582f749d65bfee0ecfdbec4a8f Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Thu, 3 Mar 2016 15:07:29 +0530 Subject: [PATCH 223/311] 8151134: Fix bug id in test for JDK-8151018 Reviewed-by: jlahoda --- langtools/test/tools/javac/generics/diamond/neg/Neg15.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/test/tools/javac/generics/diamond/neg/Neg15.java b/langtools/test/tools/javac/generics/diamond/neg/Neg15.java index 2c0d28607fa..573a5a1be3c 100644 --- a/langtools/test/tools/javac/generics/diamond/neg/Neg15.java +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg15.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8062373 + * @bug 8062373 8151018 * * @summary Test that javac complains when a <> inferred class contains a public method that does override a supertype method. * @author sadayapalam From b9210004c4679729da0c166c24024c5baec0339d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 3 Mar 2016 12:34:55 +0100 Subject: [PATCH 224/311] 8151100: Test java/lang/instrument/NativeMethodPrefixAgent.java can't attempt to do CheckIntrinsics Reviewed-by: sspitsyn, ddmitriev, egahlin --- jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java b/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java index 8c209c1b87e..4522d8b1055 100644 --- a/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java +++ b/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java @@ -31,7 +31,7 @@ * java.management * java.instrument * @run shell/timeout=240 MakeJAR2.sh NativeMethodPrefixAgent NativeMethodPrefixApp 'Can-Retransform-Classes: true' 'Can-Set-Native-Method-Prefix: true' - * @run main/othervm -javaagent:NativeMethodPrefixAgent.jar NativeMethodPrefixApp + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-CheckIntrinsics -javaagent:NativeMethodPrefixAgent.jar NativeMethodPrefixApp */ import java.lang.instrument.*; From 041e265d0d9c5999ca22cdcbb2a5f147b0b7e219 Mon Sep 17 00:00:00 2001 From: Andreas Eriksson Date: Thu, 3 Mar 2016 12:36:54 +0100 Subject: [PATCH 225/311] 8150986: serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java failing because expects HPROF JAVA PROFILE 1.0.1 file format Reviewed-by: dcubed, dsamersoff --- .../sa/jmap-hprof/JMapHProfLargeHeapTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java index 3ef260a5dfd..33b59c9af07 100644 --- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java +++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -54,7 +54,6 @@ import jdk.test.lib.ProcessTools; public class JMapHProfLargeHeapTest { private static final String HEAP_DUMP_FILE_NAME = "heap.hprof"; - private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1"; private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; private static final long M = 1024L; private static final long G = 1024L * M; @@ -79,8 +78,8 @@ public class JMapHProfLargeHeapTest { } } - // Small heap 22 megabytes, should create 1.0.1 file format - testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_1); + // All heap dumps should create 1.0.2 file format + testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_2); /** * This test was deliberately commented out since the test system lacks From 2c4627b3991788949d47a921c6a82442b4d12ef8 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Thu, 3 Mar 2016 13:18:53 +0100 Subject: [PATCH 226/311] 8151130: [BACKOUT] Remove Method::_method_data for C1 Backing out the fix for JDK-8147978 because it fails and blocks integration. Reviewed-by: vlivanov, zmajo --- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 26 ++++++++++------------ hotspot/src/share/vm/oops/method.cpp | 5 ++--- hotspot/src/share/vm/oops/method.hpp | 18 --------------- hotspot/src/share/vm/runtime/arguments.cpp | 6 ----- hotspot/src/share/vm/runtime/vmStructs.cpp | 2 +- hotspot/src/share/vm/utilities/macros.hpp | 11 +-------- 6 files changed, 16 insertions(+), 52 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 01e639258c8..92c721575d0 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -1502,23 +1502,21 @@ JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* thread)) nm->make_not_entrant(); methodHandle m(nm->method()); - if (ProfileInterpreter) { - MethodData* mdo = m->method_data(); + MethodData* mdo = m->method_data(); - if (mdo == NULL && !HAS_PENDING_EXCEPTION) { - // Build an MDO. Ignore errors like OutOfMemory; - // that simply means we won't have an MDO to update. - Method::build_interpreter_method_data(m, THREAD); - if (HAS_PENDING_EXCEPTION) { - assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here"); - CLEAR_PENDING_EXCEPTION; - } - mdo = m->method_data(); + if (mdo == NULL && !HAS_PENDING_EXCEPTION) { + // Build an MDO. Ignore errors like OutOfMemory; + // that simply means we won't have an MDO to update. + Method::build_interpreter_method_data(m, THREAD); + if (HAS_PENDING_EXCEPTION) { + assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here"); + CLEAR_PENDING_EXCEPTION; } + mdo = m->method_data(); + } - if (mdo != NULL) { - mdo->inc_trap_count(Deoptimization::Reason_none); - } + if (mdo != NULL) { + mdo->inc_trap_count(Deoptimization::Reason_none); } if (TracePredicateFailedTraps) { diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 1f3eb751413..7620ea9f985 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -383,15 +383,14 @@ void Method::build_interpreter_method_data(const methodHandle& method, TRAPS) { MutexLocker ml(MethodData_lock, THREAD); if (method->method_data() == NULL) { ClassLoaderData* loader_data = method->method_holder()->class_loader_data(); -#if defined(COMPILER2) || INCLUDE_JVMCI MethodData* method_data = MethodData::allocate(loader_data, method, THREAD); if (HAS_PENDING_EXCEPTION) { CompileBroker::log_metaspace_failure(); ClassLoaderDataGraph::set_metaspace_oom(true); return; // return the exception (which is cleared) } + method->set_method_data(method_data); -#endif if (PrintMethodData && (Verbose || WizardMode)) { ResourceMark rm(THREAD); tty->print("build_interpreter_method_data for "); @@ -921,7 +920,7 @@ void Method::unlink_method() { // shared class that failed to load, this->link_method() may // have already been called (before an exception happened), so // this->_method_data may not be NULL. - assert(!DumpSharedSpaces || method_data() == NULL, "unexpected method data?"); + assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?"); set_method_data(NULL); clear_method_counters(); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index fdf7d1f9fb0..8fc7b133a16 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -64,9 +64,7 @@ class Method : public Metadata { friend class JVMCIVMStructs; private: ConstMethod* _constMethod; // Method read-only data. -#if defined(COMPILER2) || INCLUDE_JVMCI MethodData* _method_data; -#endif MethodCounters* _method_counters; AccessFlags _access_flags; // Access flags int _vtable_index; // vtable index of this method (see VtableIndexFlag) @@ -321,7 +319,6 @@ class Method : public Metadata { // InterpreterRuntime::exception_handler_for_exception. static int fast_exception_handler_bci_for(methodHandle mh, KlassHandle ex_klass, int throw_bci, TRAPS); -#if defined(COMPILER2) || INCLUDE_JVMCI // method data access MethodData* method_data() const { return _method_data; @@ -333,10 +330,6 @@ class Method : public Metadata { // the initialization of data otherwise. OrderAccess::release_store_ptr((volatile void *)&_method_data, data); } -#else - MethodData* method_data() const { return NULL; } - void set_method_data(MethodData* data) { } -#endif MethodCounters* method_counters() const { return _method_counters; @@ -646,16 +639,9 @@ class Method : public Metadata { #endif /* CC_INTERP */ static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); } static ByteSize code_offset() { return byte_offset_of(Method, _code); } -#if defined(COMPILER2) || INCLUDE_JVMCI static ByteSize method_data_offset() { return byte_offset_of(Method, _method_data); } -#else - static ByteSize method_data_offset() { - ShouldNotReachHere(); - return in_ByteSize(0); - } -#endif static ByteSize method_counters_offset() { return byte_offset_of(Method, _method_counters); } @@ -668,11 +654,7 @@ class Method : public Metadata { static ByteSize signature_handler_offset() { return in_ByteSize(sizeof(Method) + wordSize); } // for code generation -#if defined(COMPILER2) || INCLUDE_JVMCI static int method_data_offset_in_bytes() { return offset_of(Method, _method_data); } -#else - static int method_data_offset_in_bytes() { ShouldNotReachHere(); return 0; } -#endif static int intrinsic_id_offset_in_bytes() { return offset_of(Method, _intrinsic_id); } static int intrinsic_id_size_in_bytes() { return sizeof(u2); } diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index ca25748543e..006e3c94739 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -3464,12 +3464,6 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req } #endif -#if !defined(COMPILER2) && !INCLUDE_JVMCI - UNSUPPORTED_OPTION(ProfileInterpreter, "ProfileInterpreter"); - NOT_PRODUCT(UNSUPPORTED_OPTION(TraceProfileInterpreter, "TraceProfileInterpreter")); - UNSUPPORTED_OPTION(PrintMethodData, "PrintMethodData"); -#endif - #ifndef TIERED // Tiered compilation is undefined. UNSUPPORTED_OPTION(TieredCompilation, "TieredCompilation"); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 6630da1633c..84d2c6ebd3b 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -390,7 +390,7 @@ typedef CompactHashtable SymbolCompactHashTable; nonstatic_field(MethodCounters, _invocation_counter, InvocationCounter) \ nonstatic_field(MethodCounters, _backedge_counter, InvocationCounter) \ nonstatic_field(Method, _constMethod, ConstMethod*) \ - COMPILER2_OR_JVMCI_PRESENT(nonstatic_field(Method, _method_data, MethodData*)) \ + nonstatic_field(Method, _method_data, MethodData*) \ nonstatic_field(Method, _method_counters, MethodCounters*) \ nonstatic_field(Method, _access_flags, AccessFlags) \ nonstatic_field(Method, _vtable_index, int) \ diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp index 11b4fe4f3aa..ccdb90813b7 100644 --- a/hotspot/src/share/vm/utilities/macros.hpp +++ b/hotspot/src/share/vm/utilities/macros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -206,15 +206,6 @@ #define NOT_COMPILER2(code) code #endif // COMPILER2 -// COMPILER2 or JVMCI -#if defined(COMPILER2) || INCLUDE_JVMCI -#define COMPILER2_OR_JVMCI_PRESENT(code) code -#define NOT_COMPILER2_OR_JVMCI(code) -#else -#define COMPILER2_OR_JVMCI_PRESENT(code) -#define NOT_COMPILER2_OR_JVMCI(code) code -#endif - #ifdef TIERED #define TIERED_ONLY(code) code #define NOT_TIERED(code) From 932077c03b66fab75a737929147a430f11e7f75f Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 3 Mar 2016 12:59:21 +0000 Subject: [PATCH 227/311] 8150162: Move sun.misc.Version to a truly internal package Reviewed-by: alanb, dholmes, iris, mchung, rriggs --- hotspot/src/share/vm/classfile/vmSymbols.hpp | 2 +- hotspot/src/share/vm/runtime/thread.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 626009f4c2f..ecbd0ab776d 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -123,7 +123,7 @@ template(sun_misc_Launcher_ExtClassLoader, "sun/misc/Launcher$ExtClassLoader") \ \ /* Java runtime version access */ \ - template(sun_misc_Version, "sun/misc/Version") \ + template(java_lang_VersionProps, "java/lang/VersionProps") \ template(java_runtime_name_name, "java_runtime_name") \ template(java_runtime_version_name, "java_runtime_version") \ \ diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 267c6584c37..5e1c4a31445 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -1005,9 +1005,9 @@ static void call_initializeSystemClass(TRAPS) { char java_runtime_name[128] = ""; char java_runtime_version[128] = ""; -// extract the JRE name from sun.misc.Version.java_runtime_name +// extract the JRE name from java.lang.VersionProps.java_runtime_name static const char* get_java_runtime_name(TRAPS) { - Klass* k = SystemDictionary::find(vmSymbols::sun_misc_Version(), + Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(), Handle(), Handle(), CHECK_AND_CLEAR_NULL); fieldDescriptor fd; bool found = k != NULL && @@ -1027,9 +1027,9 @@ static const char* get_java_runtime_name(TRAPS) { } } -// extract the JRE version from sun.misc.Version.java_runtime_version +// extract the JRE version from java.lang.VersionProps.java_runtime_version static const char* get_java_runtime_version(TRAPS) { - Klass* k = SystemDictionary::find(vmSymbols::sun_misc_Version(), + Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(), Handle(), Handle(), CHECK_AND_CLEAR_NULL); fieldDescriptor fd; bool found = k != NULL && From c69ad2078e19a4d7e0cbfd992fffd44d9cea2ea8 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Thu, 3 Mar 2016 16:46:58 +0300 Subject: [PATCH 228/311] 8151157: Quarantine test/compiler/unsafe/UnsafeGetStableArrayElement.java Reviewed-by: zmajo, thartmann --- hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java index e103d46454e..1ec5dc5ba17 100644 --- a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java +++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java @@ -27,6 +27,7 @@ * @test * @summary tests on constant folding of unsafe get operations from stable arrays * @library /testlibrary /test/lib + * @ignore 8151137 * * @requires vm.flavor != "client" * From ea360f901ff1822003500643123466dea4e98a47 Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Thu, 3 Mar 2016 15:53:51 +0100 Subject: [PATCH 229/311] 8151141: Sjavac fails to fork server on Windows Reverted changeset 3269:80c06d9873bd. Reviewed-by: jlahoda --- .../classes/com/sun/tools/sjavac/client/SjavacClient.java | 2 +- .../share/classes/com/sun/tools/sjavac/server/PortFile.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java index 4e309210d1f..b9b039354d4 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java @@ -257,7 +257,7 @@ public class SjavacClient implements Sjavac { // serverProcess != null at this point. try { // Throws an IOException if no valid values materialize - portFile.waitForValidValues(serverProcess); + portFile.waitForValidValues(); } catch (IOException ex) { // Process was started, but server failed to initialize. This could // for instance be due to the JVM not finding the server class, diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java index a4cda8383d5..3bbdca22c4e 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java @@ -232,7 +232,7 @@ public class PortFile { /** * Wait for the port file to contain values that look valid. */ - public void waitForValidValues(Process serverProcess) throws IOException, InterruptedException { + public void waitForValidValues() throws IOException, InterruptedException { final int MS_BETWEEN_ATTEMPTS = 500; long startTime = System.currentTimeMillis(); long timeout = startTime + getServerStartupTimeoutSeconds() * 1000; @@ -250,9 +250,6 @@ public class PortFile { if (System.currentTimeMillis() > timeout) { break; } - if (!serverProcess.isAlive()) { - throw new IOException("Server process terminated."); - } Thread.sleep(MS_BETWEEN_ATTEMPTS); } throw new IOException("No port file values materialized. Giving up after " + From 173a62a8d6114bf791fc60bfe96b42bbff85c83d Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Thu, 3 Mar 2016 16:21:16 +0100 Subject: [PATCH 230/311] 8150646: Add support for blocking compiles though whitebox API Co-authored-by: Nils Eliasson Reviewed-by: kvn, ppunegov, simonis, neliasso --- .../src/share/vm/compiler/compileBroker.cpp | 54 +++---- .../src/share/vm/compiler/compileBroker.hpp | 15 +- .../share/vm/compiler/compilerDirectives.cpp | 9 +- .../share/vm/compiler/compilerDirectives.hpp | 5 +- .../share/vm/compiler/directivesParser.cpp | 16 +- .../share/vm/compiler/directivesParser.hpp | 6 +- hotspot/src/share/vm/prims/whitebox.cpp | 29 ++++ .../vm/runtime/advancedThresholdPolicy.cpp | 33 ++--- .../share/vm/services/diagnosticCommand.cpp | 4 +- .../whitebox/BlockingCompilation.java | 137 ++++++++++++++++++ 10 files changed, 238 insertions(+), 70 deletions(-) create mode 100644 hotspot/test/compiler/whitebox/BlockingCompilation.java diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 8689088455c..672fed6f7f4 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -838,12 +838,8 @@ void CompileBroker::compile_method_base(const methodHandle& method, const methodHandle& hot_method, int hot_count, const char* comment, + bool blocking, Thread* thread) { - // do nothing if compiler thread(s) is not available - if (!_initialized) { - return; - } - guarantee(!method->is_abstract(), "cannot compile abstract methods"); assert(method->method_holder()->is_instance_klass(), "sanity check"); @@ -916,7 +912,6 @@ void CompileBroker::compile_method_base(const methodHandle& method, // Outputs from the following MutexLocker block: CompileTask* task = NULL; - bool blocking = false; CompileQueue* queue = compile_queue(comp_level); // Acquire our lock. @@ -946,9 +941,6 @@ void CompileBroker::compile_method_base(const methodHandle& method, return; } - // Should this thread wait for completion of the compile? - blocking = is_compile_blocking(); - #if INCLUDE_JVMCI if (UseJVMCICompiler) { if (blocking) { @@ -1034,11 +1026,28 @@ void CompileBroker::compile_method_base(const methodHandle& method, } } - nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, int comp_level, const methodHandle& hot_method, int hot_count, const char* comment, Thread* THREAD) { + // do nothing if compilebroker is not available + if (!_initialized) { + return NULL; + } + AbstractCompiler *comp = CompileBroker::compiler(comp_level); + assert(comp != NULL, "Ensure we don't compile before compilebroker init"); + DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp); + nmethod* nm = CompileBroker::compile_method(method, osr_bci, comp_level, hot_method, hot_count, comment, directive, THREAD); + DirectivesStack::release(directive); + return nm; +} + +nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, + int comp_level, + const methodHandle& hot_method, int hot_count, + const char* comment, DirectiveSet* directive, + Thread* THREAD) { + // make sure arguments make sense assert(method->method_holder()->is_instance_klass(), "not an instance method"); assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); @@ -1051,8 +1060,8 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, // lock, make sure that the compilation // isn't prohibited in a straightforward way. AbstractCompiler *comp = CompileBroker::compiler(comp_level); - if (comp == NULL || !comp->can_compile_method(method) || - compilation_is_prohibited(method, osr_bci, comp_level)) { + if (!comp->can_compile_method(method) || + compilation_is_prohibited(method, osr_bci, comp_level, directive->ExcludeOption)) { return NULL; } @@ -1160,7 +1169,7 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, CompilationPolicy::policy()->delay_compilation(method()); return NULL; } - compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, THREAD); + compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, !directive->BackgroundCompilationOption, THREAD); } // return requested nmethod @@ -1217,7 +1226,7 @@ bool CompileBroker::compilation_is_in_queue(const methodHandle& method) { // CompileBroker::compilation_is_prohibited // // See if this compilation is not allowed. -bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level) { +bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded) { bool is_native = method->is_native(); // Some compilers may not support the compilation of natives. AbstractCompiler *comp = compiler(comp_level); @@ -1235,11 +1244,6 @@ bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int os return true; } - // Breaking the abstraction - directives are only used inside a compilation otherwise. - DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp); - bool excluded = directive->ExcludeOption; - DirectivesStack::release(directive); - // The method may be explicitly excluded by the user. double scale; if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) { @@ -1304,16 +1308,6 @@ uint CompileBroker::assign_compile_id_unlocked(Thread* thread, const methodHandl return assign_compile_id(method, osr_bci); } -/** - * Should the current thread block until this compilation request - * has been fulfilled? - */ -bool CompileBroker::is_compile_blocking() { - assert(!InstanceRefKlass::owns_pending_list_lock(JavaThread::current()), "possible deadlock"); - return !BackgroundCompilation; -} - - // ------------------------------------------------------------------ // CompileBroker::preload_classes void CompileBroker::preload_classes(const methodHandle& method, TRAPS) { diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index ba4db7d0cdd..01a85b59dd0 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -222,8 +222,7 @@ class CompileBroker: AllStatic { static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS); static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count); static bool compilation_is_complete (const methodHandle& method, int osr_bci, int comp_level); - static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level); - static bool is_compile_blocking(); + static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded); static void preload_classes (const methodHandle& method, TRAPS); static CompileTask* create_compile_task(CompileQueue* queue, @@ -253,6 +252,7 @@ class CompileBroker: AllStatic { const methodHandle& hot_method, int hot_count, const char* comment, + bool blocking, Thread* thread); static CompileQueue* compile_queue(int comp_level); @@ -291,6 +291,15 @@ public: int hot_count, const char* comment, Thread* thread); + static nmethod* compile_method(const methodHandle& method, + int osr_bci, + int comp_level, + const methodHandle& hot_method, + int hot_count, + const char* comment, + DirectiveSet* directive, + Thread* thread); + // Acquire any needed locks and assign a compile id static uint assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci); diff --git a/hotspot/src/share/vm/compiler/compilerDirectives.cpp b/hotspot/src/share/vm/compiler/compilerDirectives.cpp index 28b09f6cb61..22ba721e7f2 100644 --- a/hotspot/src/share/vm/compiler/compilerDirectives.cpp +++ b/hotspot/src/share/vm/compiler/compilerDirectives.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -472,9 +472,12 @@ void DirectivesStack::push(CompilerDirectives* directive) { _depth++; } -void DirectivesStack::pop() { +void DirectivesStack::pop(int count) { MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); - pop_inner(); + assert(count > -1, "No negative values"); + for (int i = 0; i < count; i++) { + pop_inner(); + } } void DirectivesStack::pop_inner() { diff --git a/hotspot/src/share/vm/compiler/compilerDirectives.hpp b/hotspot/src/share/vm/compiler/compilerDirectives.hpp index a754c8bad83..0432d87068f 100644 --- a/hotspot/src/share/vm/compiler/compilerDirectives.hpp +++ b/hotspot/src/share/vm/compiler/compilerDirectives.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -42,6 +42,7 @@ cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \ cflags(PrintInlining, bool, PrintInlining, PrintInlining) \ cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \ + cflags(BackgroundCompilation, bool, BackgroundCompilation, BackgroundCompilation) \ cflags(ReplayInline, bool, false, ReplayInline) \ cflags(DumpReplay, bool, false, DumpReplay) \ cflags(DumpInline, bool, false, DumpInline) \ @@ -87,7 +88,7 @@ public: static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp); static DirectiveSet* getDefaultDirective(AbstractCompiler* comp); static void push(CompilerDirectives* directive); - static void pop(); + static void pop(int count); static bool check_capacity(int request_size, outputStream* st); static void clear(); static void print(outputStream* st); diff --git a/hotspot/src/share/vm/compiler/directivesParser.cpp b/hotspot/src/share/vm/compiler/directivesParser.cpp index 4847e228160..05f44bfe909 100644 --- a/hotspot/src/share/vm/compiler/directivesParser.cpp +++ b/hotspot/src/share/vm/compiler/directivesParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -55,7 +55,7 @@ void DirectivesParser::clean_tmp() { assert(_tmp_depth == 0, "Consistency"); } -bool DirectivesParser::parse_string(const char* text, outputStream* st) { +int DirectivesParser::parse_string(const char* text, outputStream* st) { DirectivesParser cd(text, st); if (cd.valid()) { return cd.install_directives(); @@ -63,7 +63,7 @@ bool DirectivesParser::parse_string(const char* text, outputStream* st) { cd.clean_tmp(); st->flush(); st->print_cr("Parsing of compiler directives failed"); - return false; + return -1; } } @@ -97,17 +97,17 @@ bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* buffer[num_read] = '\0'; // close file os::close(file_handle); - return parse_string(buffer, stream); + return parse_string(buffer, stream) != -1; } } return false; } -bool DirectivesParser::install_directives() { +int DirectivesParser::install_directives() { // Check limit if (!DirectivesStack::check_capacity(_tmp_depth, _st)) { clean_tmp(); - return false; + return 0; } // Pop from internal temporary stack and push to compileBroker. @@ -120,14 +120,14 @@ bool DirectivesParser::install_directives() { } if (i == 0) { _st->print_cr("No directives in file"); - return false; + return 0; } else { _st->print_cr("%i compiler directives added", i); if (CompilerDirectivesPrint) { // Print entire directives stack after new has been pushed. DirectivesStack::print(_st); } - return true; + return i; } } diff --git a/hotspot/src/share/vm/compiler/directivesParser.hpp b/hotspot/src/share/vm/compiler/directivesParser.hpp index f62630f7d56..e7c404b5b3d 100644 --- a/hotspot/src/share/vm/compiler/directivesParser.hpp +++ b/hotspot/src/share/vm/compiler/directivesParser.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -51,8 +51,8 @@ public: static bool has_file(); static bool parse_from_flag(); static bool parse_from_file(const char* filename, outputStream* st); - static bool parse_string(const char* string, outputStream* st); - bool install_directives(); + static int parse_string(const char* string, outputStream* st); + int install_directives(); private: DirectivesParser(const char* text, outputStream* st); diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 776df026f7d..3ba23806271 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -30,6 +30,7 @@ #include "classfile/stringTable.hpp" #include "code/codeCache.hpp" #include "compiler/methodMatcher.hpp" +#include "compiler/directivesParser.hpp" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" @@ -636,6 +637,10 @@ WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject m WB_END WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci)) + // Screen for unavailable/bad comp level + if (CompileBroker::compiler(comp_level) == NULL) { + return false; + } jmethodID jmid = reflected_method_to_jmid(thread, env, method); CHECK_JNI_EXCEPTION_(env, JNI_FALSE); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); @@ -1502,6 +1507,27 @@ void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, } } +WB_ENTRY(jint, WB_AddCompilerDirective(JNIEnv* env, jobject o, jstring compDirect)) + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + const char* dir = env->GetStringUTFChars(compDirect, NULL); + int ret; + { + ThreadInVMfromNative ttvfn(thread); // back to VM + ret = DirectivesParser::parse_string(dir, tty); + } + env->ReleaseStringUTFChars(compDirect, dir); + // -1 for error parsing directive. Return 0 as number of directives added. + if (ret == -1) { + ret = 0; + } + return (jint) ret; +WB_END + +WB_ENTRY(void, WB_RemoveCompilerDirective(JNIEnv* env, jobject o, jint count)) + DirectivesStack::pop(count); +WB_END + #define CC (char*) static JNINativeMethod methods[] = { @@ -1677,6 +1703,9 @@ static JNINativeMethod methods[] = { {CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared }, {CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored }, {CC"clearInlineCaches", CC"()V", (void*)&WB_ClearInlineCaches }, + {CC"addCompilerDirective", CC"(Ljava/lang/String;)I", + (void*)&WB_AddCompilerDirective }, + {CC"removeCompilerDirective", CC"(I)V", (void*)&WB_RemoveCompilerDirective }, }; #undef CC diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp index 4ecfa0e913c..ad739cf05d6 100644 --- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -177,9 +177,7 @@ bool AdvancedThresholdPolicy::is_method_profiled(Method* method) { // Called with the queue locked and with at least one element CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { -#if INCLUDE_JVMCI CompileTask *max_blocking_task = NULL; -#endif CompileTask *max_task = NULL; Method* max_method = NULL; jlong t = os::javaTimeMillis(); @@ -193,7 +191,8 @@ CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { max_method = method; } else { // If a method has been stale for some time, remove it from the queue. - if (is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { + // Blocking tasks don't become stale + if (!task->is_blocking() && is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { if (PrintTieredEvents) { print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level()); } @@ -210,29 +209,25 @@ CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { max_method = method; } } -#if INCLUDE_JVMCI - if (UseJVMCICompiler && task->is_blocking()) { + + if (task->is_blocking()) { if (max_blocking_task == NULL || compare_methods(method, max_blocking_task->method())) { max_blocking_task = task; } } -#endif + task = next_task; } -#if INCLUDE_JVMCI - if (UseJVMCICompiler) { - if (max_blocking_task != NULL) { - // In blocking compilation mode, the CompileBroker will make - // compilations submitted by a JVMCI compiler thread non-blocking. These - // compilations should be scheduled after all blocking compilations - // to service non-compiler related compilations sooner and reduce the - // chance of such compilations timing out. - max_task = max_blocking_task; - max_method = max_task->method(); - } + if (max_blocking_task != NULL) { + // In blocking compilation mode, the CompileBroker will make + // compilations submitted by a JVMCI compiler thread non-blocking. These + // compilations should be scheduled after all blocking compilations + // to service non-compiler related compilations sooner and reduce the + // chance of such compilations timing out. + max_task = max_blocking_task; + max_method = max_task->method(); } -#endif if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile && is_method_profiled(max_method)) { diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 1b745b091c0..3beb7786c16 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 @@ -931,7 +931,7 @@ int CompilerDirectivesAddDCmd::num_arguments() { } void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) { - DirectivesStack::pop(); + DirectivesStack::pop(1); } void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) { diff --git a/hotspot/test/compiler/whitebox/BlockingCompilation.java b/hotspot/test/compiler/whitebox/BlockingCompilation.java new file mode 100644 index 00000000000..793f733ee9c --- /dev/null +++ b/hotspot/test/compiler/whitebox/BlockingCompilation.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016 SAP SE. 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 8150646 + * @summary Add support for blocking compiles through whitebox API + * @library /testlibrary /test/lib / + * @build sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * + * @run main/othervm + * -Xbootclasspath/a:. + * -Xmixed + * -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * -XX:+PrintCompilation + * -XX:CompileCommand=option,BlockingCompilation::foo,PrintInlining + * BlockingCompilation + */ + +import java.lang.reflect.Method; +import java.util.Random; + +import sun.hotspot.WhiteBox; +import compiler.testlibrary.CompilerUtils; + +public class BlockingCompilation { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + private static final Random RANDOM = new Random(); + + public static int foo() { + return RANDOM.nextInt(); + } + + public static void main(String[] args) throws Exception { + long sum = 0; + int level = 0; + boolean enqued = false; + Method m = BlockingCompilation.class.getMethod("foo"); + int[] levels = CompilerUtils.getAvailableCompilationLevels(); + + // If there are no compilers available these tests don't make any sense. + if (levels.length == 0) return; + int max_level = levels[levels.length - 1]; + + // Normal, non-blocking compilation + for (int i = 0; i < 500_000; i++) { + sum += foo(); + if (!enqued && WB.isMethodQueuedForCompilation(m)) { + System.out.println("==> " + m + " enqued for compilation in iteration " + i); + enqued = true; + } + if (WB.isMethodCompiled(m)) { + if (WB.getMethodCompilationLevel(m) != level) { + level = WB.getMethodCompilationLevel(m); + System.out.println("==> " + m + " compiled at level " + level + " in iteration " + i); + enqued = false; + if (level == max_level) break; + } + } + } + + // This is necessarry because WB.deoptimizeMethod doesn't clear the methods + // MDO and therefore level 3 compilations will be downgraded to level 2. + WB.clearMethodState(m); + + // Blocking compilations on all levels, using the default versions of + // WB.enqueueMethodForCompilation() and manually setting compiler directives. + String directive = "[{ match: \"BlockingCompilation.foo\", BackgroundCompilation: false }]"; + WB.addCompilerDirective(directive); + + for (int l : levels) { + WB.deoptimizeMethod(m); + WB.enqueueMethodForCompilation(m, l); + + if (!WB.isMethodCompiled(m) || WB.getMethodCompilationLevel(m) != l) { + String msg = m + " should be compiled at level " + l + + "(but is actually compiled at level " + + WB.getMethodCompilationLevel(m) + ")"; + System.out.println("==> " + msg); + throw new Exception(msg); + } + } + + WB.removeCompilerDirective(1); + + WB.deoptimizeMethod(m); + WB.clearMethodState(m); + level = 0; + enqued = false; + int iteration = 0; + + // Normal, non-blocking compilation + for (int i = 0; i < 500_000; i++) { + sum += foo(); + if (!enqued && WB.isMethodQueuedForCompilation(m)) { + System.out.println("==> " + m + " enqued for compilation in iteration " + i); + iteration = i; + enqued = true; + } + if (WB.isMethodCompiled(m)) { + if (WB.getMethodCompilationLevel(m) != level) { + level = WB.getMethodCompilationLevel(m); + System.out.println("==> " + m + " compiled at level " + level + " in iteration " + i); + if (level == 4 && iteration == i) { + throw new Exception("This seems to be a blocking compilation although it shouldn't."); + } + enqued = false; + if (level == max_level) break; + } + } + } + } +} From 832b46f2fa45890f2d079a7b91d2ffb08125beff Mon Sep 17 00:00:00 2001 From: Andreas Eriksson Date: Thu, 3 Mar 2016 18:05:48 +0100 Subject: [PATCH 231/311] 8151064: com/sun/jdi/RedefineAddPrivateMethod.sh fails intermittently Reviewed-by: dsamersoff, sspitsyn --- jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh b/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh index bb9eefd8968..d91f74ab85c 100644 --- a/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh +++ b/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh @@ -35,7 +35,8 @@ createJavaFile() cat < $1.java.1 public class $1 { static public void main(String[] args) { - // @1 breakpoint @2 breakpoint + System.out.println("@1 breakpoint"); + System.out.println("@2 breakpoint"); } // @1 uncomment private static void test() {} @@ -50,7 +51,8 @@ dojdbCmds() runToBkpt @1 redefineClass @1 setBkpts @2 - cmd allowExit cont + runToBkpt @2 + cmd exitJdb } From 7c23a31489d82eb71f15f623fbf9ab628a871ada Mon Sep 17 00:00:00 2001 From: Joseph Provino Date: Thu, 3 Mar 2016 12:20:22 -0500 Subject: [PATCH 232/311] 8150984: Invalid VM argument causes crash -XX:G1ConcRefinementServiceIntervalMillis=2147483648 Change maximum range so it can't be negative Reviewed-by: kbarrett, sangheki --- hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp | 2 +- .../src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp | 2 +- hotspot/src/share/vm/gc/g1/g1_globals.hpp | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index 1e8081e53e0..778b37f058e 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -68,7 +68,7 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex void ConcurrentG1RefineThread::initialize() { // Current thread activation threshold _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), - cg1r()->yellow_zone()); + cg1r()->yellow_zone()); // A thread deactivates once the number of buffer reached a deactivation threshold _deactivation_threshold = MAX2(_threshold - MIN2(_threshold, cg1r()->thread_threshold_step()), diff --git a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp index 060b7feb3ad..8df01b58511 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp @@ -70,7 +70,7 @@ G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : void G1YoungRemSetSamplingThread::sleep_before_next_cycle() { MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); if (!_should_terminate) { - intx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? + uintx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? _monitor.wait(Mutex::_no_safepoint_check_flag, waitms); } } diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index fa210295098..7bc980e0fee 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -107,25 +107,25 @@ "Number of enqueued update buffers that will " \ "trigger concurrent processing. Will be selected ergonomically " \ "by default.") \ - range(0, SIZE_MAX) \ + range(0, max_intx) \ \ product(size_t, G1ConcRefinementRedZone, 0, \ "Maximum number of enqueued update buffers before mutator " \ "threads start processing new ones instead of enqueueing them. " \ "Will be selected ergonomically by default. Zero will disable " \ "concurrent processing.") \ - range(0, SIZE_MAX) \ + range(0, max_intx) \ \ product(size_t, G1ConcRefinementGreenZone, 0, \ "The number of update buffers that are left in the queue by the " \ "concurrent processing threads. Will be selected ergonomically " \ "by default.") \ - range(0, SIZE_MAX) \ + range(0, max_intx) \ \ product(uintx, G1ConcRefinementServiceIntervalMillis, 300, \ "The last concurrent refinement thread wakes up every " \ "specified number of milliseconds to do miscellaneous work.") \ - range(0, max_uintx) \ + range(0, max_jint) \ \ product(size_t, G1ConcRefinementThresholdStep, 0, \ "Each time the rset update queue increases by this amount " \ From 426cd547198481832c20ed655e9848e0a7130f6c Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 3 Mar 2016 12:25:50 -0800 Subject: [PATCH 233/311] Added tag jdk-9+108 for changeset b14d8a6ad77e --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 87f89fa25a5..528a64a3e8c 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -350,3 +350,4 @@ c4d72a1620835b5d657b7b6792c2879367d0154f jdk-9+101 be58b02c11f90b88c67e4d0e2cb5e4cf2d9b3c57 jdk-9+105 54575d8783b3a39a2d710c28cda675d44261f9d9 jdk-9+106 4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107 +c7be2a78c31b3b6132f2f5e9e4b3d3bb1c20245c jdk-9+108 From 98ef3f6b27678bde950e058c111166101049fa6f Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 3 Mar 2016 12:25:51 -0800 Subject: [PATCH 234/311] Added tag jdk-9+108 for changeset 86c7eda39fe0 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 25cb1c388d2..43b212133c8 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -350,3 +350,4 @@ e385e95e6101711d5c63e7b1a827e99b6ec7a1cc jdk-9+104 64006ae915b3aa85ac7e6fac679024d2da7fe526 jdk-9+105 8ec4f97943fe56f93e4621f622b56b7144c0181a jdk-9+106 49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107 +84f2862a25eb3232ff36c376b4e2bf2a83dfced3 jdk-9+108 From d1ed0e7785b12e37cc6815796d5d4ec2d4584883 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 3 Mar 2016 12:25:52 -0800 Subject: [PATCH 235/311] Added tag jdk-9+108 for changeset 41753e6731a1 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 0e5ef59edfc..c77700ff598 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -510,3 +510,4 @@ c5f55130b1b69510d9a6f4a3105b58e21cd7ffe1 jdk-9+103 266fa9bb5297bf02cb2a7b038b10a109817d2b48 jdk-9+105 7232de4c17c37f60aecec4f3191090bd3d41d334 jdk-9+106 c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107 +934f6793f5f7dca44f69b4559d525fa64b31840d jdk-9+108 From 8342a45da984d9a41a3ef66251317c694d2040d3 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 3 Mar 2016 12:25:55 -0800 Subject: [PATCH 236/311] Added tag jdk-9+108 for changeset 89f39e5bc737 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 2aa2e1a0723..b070406ac71 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -350,3 +350,4 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 5acf6071d4d610068a19c79e004ba8e59cf1b087 jdk-9+105 65d615f71e81bae46dcb4d053e590582e5705879 jdk-9+106 781b83dadcae89b8ae7545bb4044ddc62c6fa006 jdk-9+107 +3b9fa8b1491479f7ae18131a34036b58b647493e jdk-9+108 From 14440af6b35e49195ec253730615eaafc8fdb215 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 3 Mar 2016 12:25:56 -0800 Subject: [PATCH 237/311] Added tag jdk-9+108 for changeset c4f635dcca66 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 08e4cc59c68..64b08144ae1 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -353,3 +353,4 @@ eb5e005a17e50d7d8340daaf21a5c3c5ae358d68 jdk-9+103 45a666c58e4c7d07638878684ad09decb3229dc9 jdk-9+105 c072c572d14948563ef5d86e1921699b3a2396ab jdk-9+106 fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107 +513eb2e432f64f85992442da9acdfcfbb36555d9 jdk-9+108 From 49b10f60c221bfdd427ba98c03a6c132cb884c00 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 3 Mar 2016 12:26:01 -0800 Subject: [PATCH 238/311] Added tag jdk-9+108 for changeset 8ced04acb5e0 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 2021df477ff..08776ccc375 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -350,3 +350,4 @@ cb73b474703e2de266542b505cffd658bcc052da jdk-9+99 81bd82222f8a1f2b291a44a49e063973caa4e73b jdk-9+105 dd05d3761a341143ef4a6b1a245e0960cc125b76 jdk-9+106 7a0c343551497bd0e38ad69a77cc57d9f396615a jdk-9+107 +fd18a155ad22f62e06a9b74850ab8609d415c752 jdk-9+108 From b90601cb8f0f5568e4ecb674a808dcd62a1a31e6 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 3 Mar 2016 12:26:03 -0800 Subject: [PATCH 239/311] Added tag jdk-9+108 for changeset 9f4e085a9160 --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 8c38f51d90e..265117bfdc0 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -341,3 +341,4 @@ a618d3e89fdea5361895ef142a59074fe7ae3d98 jdk-9+104 4e9749cc32f15251d9b2d0eab4373529952902a3 jdk-9+105 cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106 8042e81b530e480dfdad41fd53a7a26f69ebba26 jdk-9+107 +58409eff7e3e0c07f12f543341769964619c0acf jdk-9+108 From 30bbb5ee4b602152d331f95cbc244b624d9321fc Mon Sep 17 00:00:00 2001 From: Christian Tornqvist Date: Thu, 3 Mar 2016 12:44:34 -0800 Subject: [PATCH 240/311] 8151156: [TESTBUG] Integrate trivial Hotspot test changes from Jake before Jigsaw M3 Reviewed-by: hseigel, gtriantafill --- .../CompiledInvokeDynamic2CompiledTest.java | 5 +++-- .../CompiledInvokeDynamic2InterpretedTest.java | 5 +++-- .../CompiledInvokeDynamic2NativeTest.java | 5 +++-- .../InterpretedInvokeDynamic2CompiledTest.java | 5 +++-- .../InterpretedInvokeDynamic2InterpretedTest.java | 5 +++-- .../InterpretedInvokeDynamic2NativeTest.java | 5 +++-- .../unsafe/TestUnsafeUnalignedMismatchedAccesses.java | 3 ++- .../test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java | 3 ++- .../compiler/jvmci/code/InterpreterFrameSizeTest.java | 8 ++++++++ .../jvmci/compilerToVM/JVM_RegisterJVMCINatives.java | 4 +++- .../jvmci/errors/TestInvalidCompilationResult.java | 7 +++++++ .../compiler/jvmci/errors/TestInvalidDebugInfo.java | 6 ++++++ .../test/compiler/jvmci/errors/TestInvalidOopMap.java | 6 ++++++ .../compiler/jvmci/events/JvmciShutdownEventTest.java | 11 ++++++++--- .../ResolvedJavaTypeResolveConcreteMethodTest.java | 4 +++- .../test/ResolvedJavaTypeResolveMethodTest.java | 4 +++- .../RedefineRunningMethodsWithResolutionErrors.java | 7 ++++--- .../test/runtime/ReservedStack/ReservedStackTest.java | 3 ++- .../runtime/SharedArchiveFile/LimitSharedSizes.java | 3 ++- hotspot/test/runtime/contended/Basic.java | 4 ++-- hotspot/test/runtime/contended/DefaultValue.java | 4 ++-- hotspot/test/runtime/contended/HasNonStatic.java | 4 ++-- hotspot/test/runtime/contended/Inheritance1.java | 4 ++-- hotspot/test/runtime/contended/OopMaps.java | 4 ++-- hotspot/test/runtime/contended/OopMapsSameGroup.java | 4 ++-- .../lambda-features/TestStaticandInstance.java | 3 ++- .../test/serviceability/attach/AttachSetGetFlag.java | 4 ++-- .../serviceability/attach/AttachWithStalePidFile.java | 3 ++- .../test/serviceability/dcmd/gc/HeapDumpAllTest.java | 2 +- hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java | 2 +- .../test/testlibrary_tests/ctw/ClassesDirTest.java | 4 ++-- .../test/testlibrary_tests/ctw/ClassesListTest.java | 4 ++-- hotspot/test/testlibrary_tests/ctw/JarDirTest.java | 4 ++-- hotspot/test/testlibrary_tests/ctw/JarsTest.java | 4 ++-- 34 files changed, 102 insertions(+), 51 deletions(-) diff --git a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java index dd4daef9849..12c14cb2ee5 100644 --- a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java +++ b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java index 3074acbc1a8..097cf9d9349 100644 --- a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java +++ b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java index b06cbf5c89c..98baacb6c86 100644 --- a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java +++ b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java index 28b38025db6..ffc4fa94e0e 100644 --- a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java +++ b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java index 3359e8104be..9579fc2e1ce 100644 --- a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java +++ b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java index 03fbfdda2a4..78f2f556fa4 100644 --- a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java +++ b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java b/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java index b6a64e13a67..d1ca58c35bb 100644 --- a/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java +++ b/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -26,6 +26,7 @@ * @test * @bug 8136473 * @summary Mismatched stores on same slice possible with Unsafe.Put*Unaligned methods + * @modules java.base/jdk.internal.misc * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestUnsafeUnalignedMismatchedAccesses * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UnlockDiagnosticVMOptions -XX:-UseUnalignedAccesses TestUnsafeUnalignedMismatchedAccesses * diff --git a/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java b/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java index 30bcd1e63b4..0504798c50a 100644 --- a/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java +++ b/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -27,6 +27,7 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") * @library /testlibrary / + * @modules jdk.vm.ci/jdk.vm.ci.runtime * @run main/othervm -XX:+UnlockExperimentalVMOptions * -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=true * -XX:+EnableJVMCI diff --git a/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java b/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java index 9f5e9cfe106..59c3e228c7a 100644 --- a/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java +++ b/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java @@ -24,6 +24,14 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.code.site + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime + * jdk.vm.ci/jdk.vm.ci.common + * jdk.vm.ci/jdk.vm.ci.amd64 + * jdk.vm.ci/jdk.vm.ci.sparc * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.InterpreterFrameSizeTest */ diff --git a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java index 5a18a6ad29a..ac42d62f543 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -27,6 +27,8 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") * @library /testlibrary / + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.runtime * @run main/othervm -XX:+UnlockExperimentalVMOptions * -Dcompiler.jvmci.compilerToVM.JVM_RegisterJVMCINatives.positive=true * -XX:+EnableJVMCI diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java b/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java index 90284c115de..75d70e7baa7 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java @@ -24,7 +24,14 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.code.site + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime + * jdk.vm.ci/jdk.vm.ci.common * @compile CodeInstallerTest.java + * @build compiler.jvmci.errors.TestInvalidCompilationResult * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidCompilationResult */ diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java b/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java index 6ca22fa9cab..53db53e7d1d 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java @@ -24,6 +24,12 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.code.site + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime + * jdk.vm.ci/jdk.vm.ci.common * @compile CodeInstallerTest.java * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidDebugInfo */ diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java b/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java index 0f1fe6e873c..7fe01e55470 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java @@ -24,6 +24,12 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.code.site + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime + * jdk.vm.ci/jdk.vm.ci.common * @compile CodeInstallerTest.java * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidOopMap */ diff --git a/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java b/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java index 7dae44ee86c..7dbbf8e35fa 100644 --- a/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java +++ b/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -26,6 +26,10 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") * @library /testlibrary / + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime * @build compiler.jvmci.common.JVMCIHelpers * compiler.jvmci.events.JvmciShutdownEventListener * compiler.jvmci.events.JvmciShutdownEventTest @@ -36,10 +40,11 @@ * compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler * compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory * compiler.jvmci.events.JvmciShutdownEventListener - * @run driver - * compiler.jvmci.events.JvmciShutdownEventTest + * @run main/othervm compiler.jvmci.events.JvmciShutdownEventTest */ + // as soon as CODETOOLS-7901589 fixed, '@run main/othervm' at L43 should be replaced w/ '@run driver' + package compiler.jvmci.events; import jdk.test.lib.ExitCode; diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java index 37b54a14796..6f1f1759e8e 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -24,6 +24,8 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveConcreteMethodTest */ diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java index 043aba3d9bb..ba62291d47c 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -24,6 +24,8 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveMethodTest */ diff --git a/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java b/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java index e4cff831d69..29247220f69 100644 --- a/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java +++ b/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -26,8 +26,9 @@ * @bug 8076110 * @summary Redefine running methods that have cached resolution errors * @library /testlibrary - * @modules java.instrument - * java.base/jdk.internal.org.objectweb.asm + * @modules java.base/jdk.internal.org.objectweb.asm + * java.instrument + * jdk.jartool/sun.tools.jar * @build RedefineClassHelper * @run main RedefineClassHelper * @run main/othervm -javaagent:redefineagent.jar -XX:TraceRedefineClasses=0x600 RedefineRunningMethodsWithResolutionErrors diff --git a/hotspot/test/runtime/ReservedStack/ReservedStackTest.java b/hotspot/test/runtime/ReservedStack/ReservedStackTest.java index b8d93be3eb7..43177dda31e 100644 --- a/hotspot/test/runtime/ReservedStack/ReservedStackTest.java +++ b/hotspot/test/runtime/ReservedStack/ReservedStackTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -24,6 +24,7 @@ /* * @test ReservedStackTest * @library /testlibrary + * @modules java.base/jdk.internal.vm.annotation * @build jdk.test.lib.* * @run main/othervm -XX:-Inline -XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread ReservedStackTest */ diff --git a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java index 824fd94f41f..c774111f210 100644 --- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java +++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /runtime/CommandLine/OptionsValidation/common * @modules java.base/sun.misc * java.management + * jdk.attach/sun.tools.attach * @run main LimitSharedSizes */ diff --git a/hotspot/test/runtime/contended/Basic.java b/hotspot/test/runtime/contended/Basic.java index 3ce7eb20e82..bf64e946f29 100644 --- a/hotspot/test/runtime/contended/Basic.java +++ b/hotspot/test/runtime/contended/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -42,7 +42,7 @@ import jdk.internal.vm.annotation.Contended; * @test * @bug 8003985 * @summary Support Contended Annotation - JEP 142 - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended Basic */ public class Basic { diff --git a/hotspot/test/runtime/contended/DefaultValue.java b/hotspot/test/runtime/contended/DefaultValue.java index a121c7a63e9..8ed4f064088 100644 --- a/hotspot/test/runtime/contended/DefaultValue.java +++ b/hotspot/test/runtime/contended/DefaultValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -43,7 +43,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8014509 * @summary \@Contended: explicit default value behaves differently from the implicit value * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended DefaultValue */ public class DefaultValue { diff --git a/hotspot/test/runtime/contended/HasNonStatic.java b/hotspot/test/runtime/contended/HasNonStatic.java index 33878fa6115..3e07c09fcfe 100644 --- a/hotspot/test/runtime/contended/HasNonStatic.java +++ b/hotspot/test/runtime/contended/HasNonStatic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -43,7 +43,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8015270 * @summary \@Contended: fix multiple issues in the layout code * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended HasNonStatic */ public class HasNonStatic { diff --git a/hotspot/test/runtime/contended/Inheritance1.java b/hotspot/test/runtime/contended/Inheritance1.java index 3ea318c40dc..f3333610cf3 100644 --- a/hotspot/test/runtime/contended/Inheritance1.java +++ b/hotspot/test/runtime/contended/Inheritance1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -43,7 +43,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8012939 * @summary \@Contended doesn't work correctly with inheritance * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended Inheritance1 */ public class Inheritance1 { diff --git a/hotspot/test/runtime/contended/OopMaps.java b/hotspot/test/runtime/contended/OopMaps.java index 5e1b39c8271..27d5ba8ddf8 100644 --- a/hotspot/test/runtime/contended/OopMaps.java +++ b/hotspot/test/runtime/contended/OopMaps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -44,7 +44,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8015493 * @summary \@Contended: fix multiple issues in the layout code * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended -XX:ContendedPaddingWidth=128 -Xmx128m OopMaps */ public class OopMaps { diff --git a/hotspot/test/runtime/contended/OopMapsSameGroup.java b/hotspot/test/runtime/contended/OopMapsSameGroup.java index af441a576b9..6975fd3dc68 100644 --- a/hotspot/test/runtime/contended/OopMapsSameGroup.java +++ b/hotspot/test/runtime/contended/OopMapsSameGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -43,7 +43,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8015272 * @summary \@Contended within the same group to use the same oop map * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended -XX:ContendedPaddingWidth=128 -Xmx128m OopMapsSameGroup */ public class OopMapsSameGroup { diff --git a/hotspot/test/runtime/lambda-features/TestStaticandInstance.java b/hotspot/test/runtime/lambda-features/TestStaticandInstance.java index 021ac48bf8a..328f252e771 100644 --- a/hotspot/test/runtime/lambda-features/TestStaticandInstance.java +++ b/hotspot/test/runtime/lambda-features/TestStaticandInstance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -26,6 +26,7 @@ * @test * @bug 8087342 * @summary Test linkresolver search static, instance and overpass duplicates + * @modules java.base/jdk.internal.org.objectweb.asm * @run main/othervm -Xverify:none TestStaticandInstance */ diff --git a/hotspot/test/serviceability/attach/AttachSetGetFlag.java b/hotspot/test/serviceability/attach/AttachSetGetFlag.java index 64adb3984bb..a78edaafff1 100644 --- a/hotspot/test/serviceability/attach/AttachSetGetFlag.java +++ b/hotspot/test/serviceability/attach/AttachSetGetFlag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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,7 +32,7 @@ * jdk.attach/sun.tools.attach * jdk.jvmstat/sun.jvmstat.monitor * @build jdk.test.lib.* AttachSetGetFlag - * @run driver AttachSetGetFlag + * @run main AttachSetGetFlag */ import java.io.BufferedReader; diff --git a/hotspot/test/serviceability/attach/AttachWithStalePidFile.java b/hotspot/test/serviceability/attach/AttachWithStalePidFile.java index 1986ebd4beb..8ed9b479f63 100644 --- a/hotspot/test/serviceability/attach/AttachWithStalePidFile.java +++ b/hotspot/test/serviceability/attach/AttachWithStalePidFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -26,6 +26,7 @@ * @bug 7162400 * @key regression * @summary Regression test for attach issue where stale pid files in /tmp lead to connection issues + * @modules jdk.attach/sun.tools.attach * @library /testlibrary * @build jdk.test.lib.* AttachWithStalePidFileTarget * @run main AttachWithStalePidFile diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java index 63e80ab05bd..6b7cc7608e1 100644 --- a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java +++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java @@ -35,7 +35,7 @@ * @build jdk.test.lib.hprof.* * @build jdk.test.lib.hprof.model.* * @build jdk.test.lib.hprof.parser.* - * @build jdk.test.lib.hprof.utils.* + * @build jdk.test.lib.hprof.util.* * @build HeapDumpTest * @run testng HeapDumpAllTest */ diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java index aefd604c25c..16dfdee007a 100644 --- a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java +++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java @@ -51,7 +51,7 @@ import jdk.test.lib.dcmd.PidJcmdExecutor; * @build jdk.test.lib.hprof.* * @build jdk.test.lib.hprof.model.* * @build jdk.test.lib.hprof.parser.* - * @build jdk.test.lib.hprof.utils.* + * @build jdk.test.lib.hprof.util.* * @run testng HeapDumpTest */ public class HeapDumpTest { diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java index 8560fa6c5b3..f507fb068c5 100644 --- a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java +++ b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -25,7 +25,7 @@ * @test * @bug 8012447 * @library /testlibrary /test/lib /testlibrary/ctw/src - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.misc * java.base/sun.reflect * java.management * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java index cb91c22bfe7..5a792a0c413 100644 --- a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java +++ b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -25,7 +25,7 @@ * @test * @bug 8012447 * @library /testlibrary /test/lib /testlibrary/ctw/src - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.misc * java.base/sun.reflect * java.management * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar diff --git a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java index c8ab89ca846..1bfdc45db93 100644 --- a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java +++ b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -25,7 +25,7 @@ * @test * @bug 8012447 * @library /testlibrary /test/lib /testlibrary/ctw/src - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.misc * java.base/sun.reflect * java.compiler * java.management diff --git a/hotspot/test/testlibrary_tests/ctw/JarsTest.java b/hotspot/test/testlibrary_tests/ctw/JarsTest.java index f9ec895df38..1050e512583 100644 --- a/hotspot/test/testlibrary_tests/ctw/JarsTest.java +++ b/hotspot/test/testlibrary_tests/ctw/JarsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -25,7 +25,7 @@ * @test * @bug 8012447 * @library /testlibrary /test/lib /testlibrary/ctw/src - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.misc * java.base/sun.reflect * java.compiler * java.management From daa39fa665382b61a06f2f7bf28f59dfb01d6f1f Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Thu, 3 Mar 2016 14:54:44 -0800 Subject: [PATCH 241/311] 8150130: NPE building javafx docs with new doclet Reviewed-by: jjg --- .../sun/tools/javac/tree/DocTreeMaker.java | 27 ++++++++++- .../javadoc/doclet/testJavaFX/TestJavaFX.java | 23 +++++++++- .../jdk/javadoc/doclet/testJavaFX/pkg4/C.java | 45 +++++++++++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 langtools/test/jdk/javadoc/doclet/testJavaFX/pkg4/C.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java index 3b5e0832372..56298136002 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java @@ -50,6 +50,7 @@ import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.parser.ParserFactory; import com.sun.tools.javac.parser.ReferenceParser; import com.sun.tools.javac.parser.Tokens.Comment; +import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; import com.sun.tools.javac.tree.DCTree.DCAttribute; import com.sun.tools.javac.tree.DCTree.DCAuthor; import com.sun.tools.javac.tree.DCTree.DCComment; @@ -206,7 +207,31 @@ public class DocTreeMaker implements DocTreeFactory { lb.addAll(cast(firstSentence)); lb.addAll(cast(body)); List fullBody = lb.toList(); - DCDocComment tree = new DCDocComment(null, fullBody, cast(firstSentence), cast(body), cast(tags)); + + // A dummy comment to keep the diagnostics logic happy. + Comment c = new Comment() { + @Override + public String getText() { + return null; + } + + @Override + public int getSourcePos(int index) { + return Position.NOPOS; + } + + @Override + public CommentStyle getStyle() { + return CommentStyle.JAVADOC; + } + + @Override + public boolean isDeprecated() { + return false; + } + }; + + DCDocComment tree = new DCDocComment(c, fullBody, cast(firstSentence), cast(body), cast(tags)); return tree; } diff --git a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java index ca03dcff89f..9e17061778c 100644 --- a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java +++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 7112427 8012295 8025633 8026567 8061305 8081854 + * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 * @summary Test of the JavaFX doclet features. * @author jvalenta * @library ../lib @@ -137,6 +137,7 @@ public class TestJavaFX extends JavadocTester { + "\n" + ""); } + /* * Test without -javafx option, to ensure property getters and setters * are treated just like any other java method. @@ -181,4 +182,22 @@ public class TestJavaFX extends JavadocTester { + "() " ); } + + /* + * Force the doclet to emit a warning when processing a synthesized, + * DocComment, and ensure that the run succeeds. + */ + @Test + void test4() { + javadoc("-d", "out4", + "-javafx", + "-Xdoclint:none", + "-sourcepath", testSrc, + "-package", + "pkg4"); + checkExit(Exit.OK); + + // make sure the doclet indeed emits the warning + checkOutput(Output.OUT, true, "C.java:0: warning - invalid usage of tag >"); + } } diff --git a/langtools/test/jdk/javadoc/doclet/testJavaFX/pkg4/C.java b/langtools/test/jdk/javadoc/doclet/testJavaFX/pkg4/C.java new file mode 100644 index 00000000000..43f4a961876 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/pkg4/C.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, 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 pkg4; + +public class C { + + /** + * Defines the number of cycles in this animation. The {@code cycleCount} + * may be {@code INDEFINITE} for animations that repeat indefinitely. + * Now we add a > to deliberately cause an Html error. + * @defaultValue 11 + * @since JavaFX 8.0 + */ + public DoubleProperty rate; + + public final void setRate(double value) {} + + public final double getRate() {return 2.0d;} + + public final DoubleProperty rateProperty() {return new DoubleProperty();} + + class DoubleProperty {} + +} From 3c244740c608d9239e78795967351d513a096750 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Fri, 4 Mar 2016 14:04:01 +0000 Subject: [PATCH 242/311] 8148108: Disable Diffie-Hellman keys less than 1024 bits Reviewed-by: vinnie, mullan --- .../share/conf/security/java.security | 2 +- .../DHKeyExchange/LegacyDHEKeyExchange.java | 325 ++++++++++++++++++ 2 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 jdk/test/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index 157fa3c7fc7..fdcfe2be25c 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -578,7 +578,7 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768 +jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. diff --git a/jdk/test/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java b/jdk/test/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java new file mode 100644 index 00000000000..76f6a7b949a --- /dev/null +++ b/jdk/test/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2016, 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8148108 + * @summary Disable Diffie-Hellman keys less than 1024 bits + * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy LegacyDHEKeyExchange + */ + +import java.io.*; +import javax.net.ssl.*; + +public class LegacyDHEKeyExchange { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + static boolean separateServerThread = false; + + /* + * Where do we find the keystores? + */ + static String pathToStores = "../../../../javax/net/ssl/etc"; + static String keyStoreFile = "keystore"; + static String trustStoreFile = "truststore"; + static String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + SSLServerSocket sslServerSocket = + (SSLServerSocket) sslssf.createServerSocket(serverPort); + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + + throw new Exception( + "Leagcy DH keys (< 1024) should be restricted"); + } catch (SSLHandshakeException she) { + // ignore, client should terminate the connection + } finally { + sslServerSocket.close(); + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLSocketFactory sslsf = + (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) + sslsf.createSocket("localhost", serverPort); + + String[] suites = new String [] {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"}; + sslSocket.setEnabledCipherSuites(suites); + + try { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + + throw new Exception("Leagcy DH keys (< 1024) should be restricted"); + } catch (SSLHandshakeException she) { + // ignore, should be caused by algorithm constraints + } finally { + sslSocket.close(); + } + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + volatile int serverPort = 0; + + volatile Exception serverException = null; + volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + /* + * Start the tests. + */ + new LegacyDHEKeyExchange(); + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + LegacyDHEKeyExchange() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); + } + } else { + if (clientThread != null) { + clientThread.join(); + } + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + @Override + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + @Override + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} From bbb9ee08eef3ee4bc4ae0a09e43b35f01c6f49d1 Mon Sep 17 00:00:00 2001 From: Alexander Stepanov Date: Fri, 4 Mar 2016 18:42:16 +0300 Subject: [PATCH 243/311] 8150258: [TEST] HiDPI: create a test for multiresolution menu items icons Reviewed-by: serb, yan --- .../MenuMultiresolutionIconTest.java | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 jdk/test/java/awt/image/multiresolution/MenuMultiresolutionIconTest.java diff --git a/jdk/test/java/awt/image/multiresolution/MenuMultiresolutionIconTest.java b/jdk/test/java/awt/image/multiresolution/MenuMultiresolutionIconTest.java new file mode 100644 index 00000000000..332162be952 --- /dev/null +++ b/jdk/test/java/awt/image/multiresolution/MenuMultiresolutionIconTest.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2016, 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 8150258 + * @author a.stepanov + * @summary Check that correct resolution variants are chosen for menu icons + * when multiresolution image is used for their construction. + * + * @library ../../../../lib/testlibrary/ + * @build ExtendedRobot + * @run main/othervm -Dsun.java2d.uiScale=1 MenuMultiresolutionIconTest + * @run main/othervm -Dsun.java2d.uiScale=2 MenuMultiresolutionIconTest + */ + + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import javax.swing.*; + +public class MenuMultiresolutionIconTest extends JPanel { + + private final static int DELAY = 1000; + private final static int SZ = 50; + private final static String SCALE = "sun.java2d.uiScale"; + private final static Color C1X = Color.RED, C2X = Color.BLUE; + private final ExtendedRobot r; + + private static BufferedImage generateImage(int scale, Color c) { + + int x = SZ * scale; + BufferedImage img = new BufferedImage(x, x, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(c); + g.fillRect(0, 0, x, x); + return img; + } + + private static BaseMultiResolutionImage createIcon() { + + return new BaseMultiResolutionImage(new BufferedImage[] { + generateImage(1, C1X), generateImage(2, C2X)}); + } + + private JFrame frame; + private JPopupMenu popup; + private JMenuItem popupItem; + private JMenu menu; + + public MenuMultiresolutionIconTest() throws Exception { + + r = new ExtendedRobot(); + SwingUtilities.invokeAndWait(this::createUI); + } + + private void createUI() { + + ImageIcon ii = new ImageIcon(createIcon()); + + popup = new JPopupMenu(); + popupItem = new JMenuItem("test", ii); + popup.add(popupItem); + popupItem.setHorizontalTextPosition(JMenuItem.RIGHT); + addMouseListener(new MousePopupListener()); + + frame = new JFrame(); + JMenuBar menuBar = new JMenuBar(); + menu = new JMenu("test"); + menuBar.add(menu); + menu.add(new JMenuItem("test", ii)); + menu.add(new JRadioButtonMenuItem("test", ii, true)); + menu.add(new JCheckBoxMenuItem("test", ii, true)); + + frame.setJMenuBar(menuBar); + frame.setContentPane(this); + frame.setSize(300, 300); + frame.setVisible(true); + } + + private class MousePopupListener extends MouseAdapter { + + @Override + public void mousePressed(MouseEvent e) { showPopup(e); } + @Override + public void mouseClicked(MouseEvent e) { showPopup(e); } + @Override + public void mouseReleased(MouseEvent e) { showPopup(e); } + + private void showPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(MenuMultiresolutionIconTest.this, e.getX(), e.getY()); + } + } + } + + private static boolean is2x() { + + return GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(). + getDefaultTransform().getScaleX() > 1.001; + } + + private boolean eqColors(Color c1, Color c2) { + + int tol = 15; + return ( + Math.abs(c2.getRed() - c1.getRed() ) < tol && + Math.abs(c2.getGreen() - c1.getGreen()) < tol && + Math.abs(c2.getBlue() - c1.getBlue() ) < tol); + } + + private void checkIconColor(Point p, String what) { + + Color expected = is2x() ? C2X : C1X; + Color c = r.getPixelColor(p.x + SZ / 2, p.y + SZ / 2); + if (!eqColors(c, expected)) { + frame.dispose(); + throw new RuntimeException("invalid " + what + "menu item icon " + + "color, expected: " + expected + ", got: " + c); + } + System.out.println(what + "item icon check passed"); + } + + private void doTest() { + + r.waitForIdle(2 * DELAY); + + Point p = getLocationOnScreen(); + r.mouseMove(p.x + getWidth() / 4, p.y + getHeight() / 4); + r.waitForIdle(DELAY); + r.click(InputEvent.BUTTON3_DOWN_MASK); + r.waitForIdle(DELAY); + p = popupItem.getLocationOnScreen(); + checkIconColor(p, "popup "); + r.waitForIdle(DELAY); + + p = menu.getLocationOnScreen(); + r.mouseMove(p.x + menu.getWidth() / 2, p.y + menu.getHeight() / 2); + r.waitForIdle(DELAY); + r.click(); + p = menu.getItem(0).getLocationOnScreen(); + checkIconColor(p, ""); + r.waitForIdle(DELAY); + + p = menu.getItem(1).getLocationOnScreen(); + checkIconColor(p, "radiobutton "); + r.waitForIdle(DELAY); + + p = menu.getItem(2).getLocationOnScreen(); + checkIconColor(p, "checkbox "); + r.waitForIdle(DELAY); + + frame.dispose(); + } + + public static void main(String s[]) throws Exception { + + // TODO: remove is2x() after JDK-8150844 fix + if (is2x() == "2".equals(System.getProperty(SCALE))) { + (new MenuMultiresolutionIconTest()).doTest(); + } + } +} From d91d8b251c31870d4c40e508837496b7f4c1f4e0 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 4 Mar 2016 17:05:52 +0100 Subject: [PATCH 244/311] 8151297: Class name change for CLDRLocaleDataMetaInfo_jdk_localedata needs updating in makefile Reviewed-by: alanb --- jdk/make/gensrc/GensrcCLDR.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/make/gensrc/GensrcCLDR.gmk b/jdk/make/gensrc/GensrcCLDR.gmk index 45ccc349878..230dc3eb709 100644 --- a/jdk/make/gensrc/GensrcCLDR.gmk +++ b/jdk/make/gensrc/GensrcCLDR.gmk @@ -30,7 +30,7 @@ GENSRC_BASEDIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.localedata CLDR_BASEMETAINFO_FILE := $(GENSRC_BASEDIR)/sun/util/cldr/CLDRBaseLocaleDataMetaInfo.java -CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo_jdk_localedata.java +CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.java CLDR_BASE_LOCALES := "en-US" From 510bcb3a35a70c6a0f84abbd5d1129aeca59b78e Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 4 Mar 2016 18:36:27 +0100 Subject: [PATCH 245/311] 8151302: Attempt at silencing build log broke html32.bdtd Reviewed-by: mchung --- jdk/make/gendata/GendataHtml32dtd.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/make/gendata/GendataHtml32dtd.gmk b/jdk/make/gendata/GendataHtml32dtd.gmk index 2bc0e708673..0c18d2a280c 100644 --- a/jdk/make/gendata/GendataHtml32dtd.gmk +++ b/jdk/make/gendata/GendataHtml32dtd.gmk @@ -30,6 +30,6 @@ $(HTML32DTD): $(BUILD_TOOLS_JDK) $(call LogInfo, Generating HTML DTD file) $(MKDIR) -p $(@D) $(RM) $@ - ($(TOOL_DTDBUILDER) $(LOG_INFO) html32 > $@) || exit 1 + ($(TOOL_DTDBUILDER) html32 > $@) || exit 1 TARGETS += $(HTML32DTD) From 23734438ce0ecefa1aa960656deb03f5b726dc3a Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 4 Mar 2016 10:09:54 -0800 Subject: [PATCH 246/311] 8151225: Mark SpecTest.java as intermittently failing Reviewed-by: mullan --- jdk/test/sun/security/rsa/SpecTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/test/sun/security/rsa/SpecTest.java b/jdk/test/sun/security/rsa/SpecTest.java index d2ab0a8e79f..c13f1d91989 100644 --- a/jdk/test/sun/security/rsa/SpecTest.java +++ b/jdk/test/sun/security/rsa/SpecTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -34,6 +34,7 @@ import java.security.spec.RSAKeyGenParameterSpec; /** * @test * @bug 8044199 + * @key intermittent * @summary Check same KeyPair's private key and public key have same modulus. * also check public key's public exponent equals to given spec's public * exponent. From 6c3caacddc17b1b31e0a66ca05cde1a43d421aa8 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Sat, 5 Mar 2016 10:30:23 +0800 Subject: [PATCH 247/311] 8151286: Remove intermittent key from TestLocalTime.java and move back to tier1 Reviewed-by: darcy --- jdk/test/TEST.groups | 2 -- jdk/test/java/util/zip/TestLocalTime.java | 1 - 2 files changed, 3 deletions(-) diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index 7d56e8afd61..ea9a6d6fa7e 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -28,7 +28,6 @@ tier1 = \ :jdk_lang \ -java/lang/ProcessHandle/TreeTest.java \ - -java/util/zip/TestLocalTime.java \ :jdk_util \ -java/util/WeakHashMap/GCDuringIteration.java \ -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ @@ -40,7 +39,6 @@ tier1 = \ tier2 = \ java/lang/ProcessHandle/TreeTest.java \ - java/util/zip/TestLocalTime.java \ java/util/WeakHashMap/GCDuringIteration.java \ java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ diff --git a/jdk/test/java/util/zip/TestLocalTime.java b/jdk/test/java/util/zip/TestLocalTime.java index 93770ef2f3b..d4b669a1033 100644 --- a/jdk/test/java/util/zip/TestLocalTime.java +++ b/jdk/test/java/util/zip/TestLocalTime.java @@ -24,7 +24,6 @@ /* * @test * @bug 8075526 8135108 - * @key intermittent * @summary Test timestamp via ZipEntry.get/setTimeLocal() */ From 911e6e48a75d694357abf1044d07ddddc5fcd479 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Sat, 5 Mar 2016 10:34:06 +0800 Subject: [PATCH 248/311] 8151263: Mark java/rmi test LeaseCheckInterval.java as intermittently failing Reviewed-by: darcy --- .../Unreferenced/leaseCheckInterval/LeaseCheckInterval.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java index 61121578c1e..889a55e9879 100644 --- a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java +++ b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -43,6 +43,7 @@ * java.rmi/sun.rmi.transport.tcp * @build TestLibrary JavaVM LeaseCheckInterval_Stub SelfTerminator * @run main/othervm LeaseCheckInterval + * @key intermittent */ import java.rmi.Remote; From 7181a2dcb1e8e186009be7a96993c8e0469db4d7 Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Sat, 5 Mar 2016 22:22:37 +0800 Subject: [PATCH 249/311] 8151340: aarch64: prefetch the destination word for write prior to ldxr/stxr loops Aarch64: add prefetch for write prior to ldxr/stxr loops. Reviewed-by: aph --- hotspot/src/cpu/aarch64/vm/aarch64.ad | 3 +++ hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp | 4 ++++ hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp | 8 ++++++-- .../aarch64/vm/templateInterpreterGenerator_aarch64.cpp | 1 + 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index 7689614b710..3288fbedfb8 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -4683,6 +4683,7 @@ encode %{ __ br(Assembler::EQ, cont); } else { Label retry_load; + __ prfm(Address(oop), PSTL1STRM); __ bind(retry_load); __ ldaxr(tmp, oop); __ cmp(tmp, disp_hdr); @@ -4737,6 +4738,7 @@ encode %{ __ cmp(rscratch1, disp_hdr); } else { Label retry_load, fail; + __ prfm(Address(tmp), PSTL1STRM); __ bind(retry_load); __ ldaxr(rscratch1, tmp); __ cmp(disp_hdr, rscratch1); @@ -4830,6 +4832,7 @@ encode %{ __ cmp(tmp, box); } else { Label retry_load; + __ prfm(Address(oop), PSTL1STRM); __ bind(retry_load); __ ldxr(tmp, oop); __ cmp(box, tmp); diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp index a42f0a127b0..082c1505466 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp @@ -1565,6 +1565,7 @@ void LIR_Assembler::casw(Register addr, Register newval, Register cmpval) { Label retry_load, nope; // flush and load exclusive from the memory location // and fail if it is not what we expect + __ prfm(Address(addr), PSTL1STRM); __ bind(retry_load); __ ldaxrw(rscratch1, addr); __ cmpw(rscratch1, cmpval); @@ -1590,6 +1591,7 @@ void LIR_Assembler::casl(Register addr, Register newval, Register cmpval) { Label retry_load, nope; // flush and load exclusive from the memory location // and fail if it is not what we expect + __ prfm(Address(addr), PSTL1STRM); __ bind(retry_load); __ ldaxr(rscratch1, addr); __ cmp(rscratch1, cmpval); @@ -3170,6 +3172,7 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr } Label again; __ lea(tmp, addr); + __ prfm(Address(tmp), PSTL1STRM); __ bind(again); (_masm->*lda)(dst, tmp); (_masm->*add)(rscratch1, dst, inc); @@ -3189,6 +3192,7 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr assert_different_registers(obj, addr.base(), tmp, rscratch2, dst); Label again; __ lea(tmp, addr); + __ prfm(Address(tmp), PSTL1STRM); __ bind(again); (_masm->*lda)(dst, tmp); (_masm->*stl)(rscratch2, obj, tmp); diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index bfa9c8fba5b..691e6bb29c2 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -1638,6 +1638,7 @@ Address MacroAssembler::form_address(Register Rd, Register base, long byte_offse void MacroAssembler::atomic_incw(Register counter_addr, Register tmp, Register tmp2) { Label retry_load; + prfm(Address(counter_addr), PSTL1STRM); bind(retry_load); // flush and load exclusive from the memory location ldxrw(tmp, counter_addr); @@ -2078,7 +2079,7 @@ void MacroAssembler::cmpxchgptr(Register oldv, Register newv, Register addr, Reg membar(AnyAny); } else { Label retry_load, nope; - + prfm(Address(addr), PSTL1STRM); bind(retry_load); // flush and load exclusive from the memory location // and fail if it is not what we expect @@ -2114,7 +2115,7 @@ void MacroAssembler::cmpxchgw(Register oldv, Register newv, Register addr, Regis membar(AnyAny); } else { Label retry_load, nope; - + prfm(Address(addr), PSTL1STRM); bind(retry_load); // flush and load exclusive from the memory location // and fail if it is not what we expect @@ -2149,6 +2150,7 @@ void MacroAssembler::cmpxchg(Register addr, Register expected, } else { BLOCK_COMMENT("cmpxchg {"); Label retry_load, done; + prfm(Address(addr), PSTL1STRM); bind(retry_load); load_exclusive(tmp, addr, size, acquire); if (size == xword) @@ -2177,6 +2179,7 @@ void MacroAssembler::atomic_##OP(Register prev, RegisterOrConstant incr, Registe result = different(prev, incr, addr) ? prev : rscratch2; \ \ Label retry_load; \ + prfm(Address(addr), PSTL1STRM); \ bind(retry_load); \ LDXR(result, addr); \ OP(rscratch1, result, incr); \ @@ -2199,6 +2202,7 @@ void MacroAssembler::atomic_##OP(Register prev, Register newv, Register addr) { result = different(prev, newv, addr) ? prev : rscratch2; \ \ Label retry_load; \ + prfm(Address(addr), PSTL1STRM); \ bind(retry_load); \ LDXR(result, addr); \ STXR(rscratch1, newv, addr); \ diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp index e37c0881d5c..59bdeeeb044 100644 --- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp @@ -1984,6 +1984,7 @@ void TemplateInterpreterGenerator::count_bytecode() { __ push(rscratch3); Label L; __ mov(rscratch2, (address) &BytecodeCounter::_counter_value); + __ prfm(Address(rscratch2), PSTL1STRM); __ bind(L); __ ldxr(rscratch1, rscratch2); __ add(rscratch1, rscratch1, 1); From c57335f3958ec85ab3e910cf55cd8c6e91fea4cf Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Sat, 5 Mar 2016 07:53:12 -0800 Subject: [PATCH 250/311] 8150000: Javadoc omits package listing for type Reviewed-by: jjg --- .../internal/doclets/formats/html/ClassWriterImpl.java | 8 ++++++-- .../internal/doclets/formats/html/markup/HtmlStyle.java | 3 ++- .../internal/doclets/toolkit/resources/stylesheet.css | 5 +++-- .../jdk/javadoc/doclet/testSubTitle/TestSubTitle.java | 7 ++++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java index 37bc63c57e6..9356fb7f3c2 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java @@ -196,8 +196,12 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite div.addStyle(HtmlStyle.header); PackageElement pkg = utils.containingPackage(typeElement); if (!pkg.isUnnamed()) { - Content pkgNameContent = new StringContent(utils.getPackageName(pkg)); - Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, pkgNameContent); + Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, packageLabel); + Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel); + pkgNameDiv.addContent(getSpace()); + Content pkgNameContent = getPackageLink(pkg, + new StringContent(pkg.getQualifiedName().toString())); + pkgNameDiv.addContent(pkgNameContent); div.addContent(pkgNameDiv); } LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java index ccaf4769276..f55de090491 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -84,6 +84,7 @@ public enum HtmlStyle { overrideSpecifyLabel, overviewSummary, packageHierarchyLabel, + packageLabelInClass, paramLabel, returnLabel, rightContainer, diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css index 076087c92f4..4a0e575f59b 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css @@ -610,8 +610,9 @@ h1.hidden { color:#474747; } .deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { +.overrideSpecifyLabel, .packageLabelInClass, .packageHierarchyLabel, +.paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, .throwsLabel, +.typeNameLabel, .typeNameLink, .searchTagLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { diff --git a/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java b/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java index 374e48fee90..3a93d64fb66 100644 --- a/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java +++ b/langtools/test/jdk/javadoc/doclet/testSubTitle/TestSubTitle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, 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 7010342 + * @bug 7010342 8150000 * @summary Test for correct sub title generation. * @author Bhavesh Patel * @library ../lib @@ -50,7 +50,8 @@ public class TestSubTitle extends JavadocTester { "
          This is the description of package pkg.
          "); checkOutput("pkg/C.html", true, - "
          pkg
          "); + "
          " + + "Package pkg
          "); checkOutput("pkg/package-summary.html", false, "

          \n" + From 3a33180c0155ee9921a92da2eec7692e3464af10 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Sat, 5 Mar 2016 19:22:57 -0800 Subject: [PATCH 251/311] 8151348: quarantine compiler/codecache/jmx/PeakUsageTest.java in JDK9-dev Reviewed-by: ctornqvi, amurillo --- hotspot/test/compiler/codecache/jmx/PeakUsageTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java index 3bb001802ae..dced25799d7 100644 --- a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java +++ b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -27,6 +27,7 @@ import sun.hotspot.code.BlobType; /* * @test PeakUsageTest + * @ignore 8151345 * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management From e9a63602725405441d7ca387eb1e53ae89b5143e Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 7 Mar 2016 11:54:42 +0530 Subject: [PATCH 252/311] 8058316: lookupDefaultPrintService returns null on Solaris 11 Reviewed-by: prr, jdv --- jdk/make/mapfiles/libawt/mapfile-mawt-vers | 1 + .../mapfiles/libawt_headless/mapfile-vers | 1 + jdk/make/mapfiles/libawt_xawt/mapfile-vers | 1 + .../unix/classes/sun/print/CUPSPrinter.java | 12 ++++- .../unix/native/common/awt/CUPSfuncs.c | 49 +++++++++++++++++++ 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/jdk/make/mapfiles/libawt/mapfile-mawt-vers b/jdk/make/mapfiles/libawt/mapfile-mawt-vers index 8f9ee4135a5..247e29698e2 100644 --- a/jdk/make/mapfiles/libawt/mapfile-mawt-vers +++ b/jdk/make/mapfiles/libawt/mapfile-mawt-vers @@ -200,6 +200,7 @@ SUNWprivate_1.1 { Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; + Java_sun_print_CUPSPrinter_getCupsDefaultPrinter; Java_sun_print_CUPSPrinter_canConnect; Java_sun_print_CUPSPrinter_getMedia; Java_sun_print_CUPSPrinter_getPageSizes; diff --git a/jdk/make/mapfiles/libawt_headless/mapfile-vers b/jdk/make/mapfiles/libawt_headless/mapfile-vers index 5ea1745e296..ac5101042a2 100644 --- a/jdk/make/mapfiles/libawt_headless/mapfile-vers +++ b/jdk/make/mapfiles/libawt_headless/mapfile-vers @@ -73,6 +73,7 @@ SUNWprivate_1.1 { Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; + Java_sun_print_CUPSPrinter_getCupsDefaultPrinter; Java_sun_print_CUPSPrinter_canConnect; Java_sun_print_CUPSPrinter_getMedia; Java_sun_print_CUPSPrinter_getPageSizes; diff --git a/jdk/make/mapfiles/libawt_xawt/mapfile-vers b/jdk/make/mapfiles/libawt_xawt/mapfile-vers index 182ed0acfd7..42ef24d90a1 100644 --- a/jdk/make/mapfiles/libawt_xawt/mapfile-vers +++ b/jdk/make/mapfiles/libawt_xawt/mapfile-vers @@ -439,6 +439,7 @@ SUNWprivate_1.1 { Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; + Java_sun_print_CUPSPrinter_getCupsDefaultPrinter; Java_sun_print_CUPSPrinter_canConnect; Java_sun_print_CUPSPrinter_getMedia; Java_sun_print_CUPSPrinter_getPageSizes; diff --git a/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java b/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java index f84f855cce3..d602b3c712a 100644 --- a/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java +++ b/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java @@ -52,6 +52,7 @@ public class CUPSPrinter { private boolean initialized; private static native String getCupsServer(); private static native int getCupsPort(); + private static native String getCupsDefaultPrinter(); private static native boolean canConnect(String server, int port); private static native boolean initIDs(); // These functions need to be synchronized as @@ -266,6 +267,15 @@ public class CUPSPrinter { * Returns 2 values - index 0 is printer name, index 1 is the uri. */ static String[] getDefaultPrinter() { + // Try to get user/lpoptions-defined printer name from CUPS + // if not user-set, then go for server default destination + String printerInfo[] = new String[2]; + printerInfo[0] = getCupsDefaultPrinter(); + + if (printerInfo[0] != null) { + printerInfo[1] = null; + return printerInfo.clone(); + } try { URL url = new URL("http", getServer(), getPort(), ""); final HttpURLConnection urlConnection = @@ -301,7 +311,7 @@ public class CUPSPrinter { attCl)) { HashMap defaultMap = null; - String[] printerInfo = new String[2]; + InputStream is = urlConnection.getInputStream(); HashMap[] responseMap = IPPPrintService.readIPPResponse( is); diff --git a/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c b/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c index a530a47fb84..7ba8652b478 100644 --- a/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c +++ b/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c @@ -43,6 +43,10 @@ typedef int (*fn_ippPort)(void); typedef http_t* (*fn_httpConnect)(const char *, int); typedef void (*fn_httpClose)(http_t *); typedef char* (*fn_cupsGetPPD)(const char *); +typedef cups_dest_t* (*fn_cupsGetDest)(const char *name, + const char *instance, int num_dests, cups_dest_t *dests); +typedef int (*fn_cupsGetDests)(cups_dest_t **dests); +typedef void (*fn_cupsFreeDests)(int num_dests, cups_dest_t *dests); typedef ppd_file_t* (*fn_ppdOpenFile)(const char *); typedef void (*fn_ppdClose)(ppd_file_t *); typedef ppd_option_t* (*fn_ppdFindOption)(ppd_file_t *, const char *); @@ -53,6 +57,9 @@ fn_ippPort j2d_ippPort; fn_httpConnect j2d_httpConnect; fn_httpClose j2d_httpClose; fn_cupsGetPPD j2d_cupsGetPPD; +fn_cupsGetDest j2d_cupsGetDest; +fn_cupsGetDests j2d_cupsGetDests; +fn_cupsFreeDests j2d_cupsFreeDests; fn_ppdOpenFile j2d_ppdOpenFile; fn_ppdClose j2d_ppdClose; fn_ppdFindOption j2d_ppdFindOption; @@ -106,6 +113,24 @@ Java_sun_print_CUPSPrinter_initIDs(JNIEnv *env, return JNI_FALSE; } + j2d_cupsGetDest = (fn_cupsGetDest)dlsym(handle, "cupsGetDest"); + if (j2d_cupsGetDest == NULL) { + dlclose(handle); + return JNI_FALSE; + } + + j2d_cupsGetDests = (fn_cupsGetDests)dlsym(handle, "cupsGetDests"); + if (j2d_cupsGetDests == NULL) { + dlclose(handle); + return JNI_FALSE; + } + + j2d_cupsFreeDests = (fn_cupsFreeDests)dlsym(handle, "cupsFreeDests"); + if (j2d_cupsFreeDests == NULL) { + dlclose(handle); + return JNI_FALSE; + } + j2d_ppdOpenFile = (fn_ppdOpenFile)dlsym(handle, "ppdOpenFile"); if (j2d_ppdOpenFile == NULL) { dlclose(handle); @@ -169,6 +194,30 @@ Java_sun_print_CUPSPrinter_getCupsPort(JNIEnv *env, } +/* + * Gets CUPS default printer name. + * + */ +JNIEXPORT jstring JNICALL +Java_sun_print_CUPSPrinter_getCupsDefaultPrinter(JNIEnv *env, + jobject printObj) +{ + jstring cDefPrinter = NULL; + cups_dest_t *dests; + char *defaultPrinter = NULL; + int num_dests = j2d_cupsGetDests(&dests); + int i = 0; + cups_dest_t *dest = j2d_cupsGetDest(NULL, NULL, num_dests, dests); + if (dest != NULL) { + defaultPrinter = dest->name; + if (defaultPrinter != NULL) { + cDefPrinter = JNU_NewStringPlatform(env, defaultPrinter); + } + } + j2d_cupsFreeDests(num_dests, dests); + return cDefPrinter; +} + /* * Checks if connection can be made to the server. * From 4dd8addd0510be8f7594bf83195b6ba9d3efe90b Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 7 Mar 2016 09:13:56 +0100 Subject: [PATCH 253/311] 8151300: Build shell trace functionality lost in JDK-8076060 Reviewed-by: tbell --- make/common/MakeBase.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index e068be7dd23..6200851793c 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -282,7 +282,7 @@ define SetupLogging # Default shell seems to always be /bin/sh. Must override with bash to get this to work on Solaris. # Only use time if it's GNU time which supports format and output file. WRAPPER_SHELL := $$(BASH) $$(SRC_ROOT)/common/bin/shell-tracer.sh $$(if $$(findstring yes,$$(IS_GNU_TIME)),$$(TIME),-) $$(OUTPUT_ROOT)/build-trace-time.log $$(SHELL) - SHELL := $$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(WRAPPER_SHELL) + SHELL = $$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(WRAPPER_SHELL) endif # The warn level can never be turned off LogWarn = $$(info $$(strip $$1)) From c4bd0e51132fdd5e9f0da69a7d249fa3d6726516 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 7 Mar 2016 09:14:17 +0100 Subject: [PATCH 254/311] 8150504: JIB profiles for reference implementation builds Reviewed-by: ihse --- common/conf/jib-profiles.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index 926fb9d5424..48519cfbe74 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -311,6 +311,16 @@ var getJibProfilesProfiles = function (input, common) { labels: [ "open" ] }, + "linux-x86-open": { + target_os: mainProfiles["linux-x86"].target_os, + target_cpu: mainProfiles["linux-x86"].target_cpu, + dependencies: mainProfiles["linux-x86"].dependencies, + configure_args: concat(mainProfiles["linux-x86"].configure_args, + "--enable-openjdk-only"), + make_args: mainProfiles["linux-x86"].make_args, + labels: [ "open" ] + }, + "solaris-x64-open": { target_os: mainProfiles["solaris-x64"].target_os, target_cpu: mainProfiles["solaris-x64"].target_cpu, @@ -319,6 +329,16 @@ var getJibProfilesProfiles = function (input, common) { "--enable-openjdk-only"), make_args: mainProfiles["solaris-x64"].make_args, labels: [ "open" ] + }, + + "windows-x86-open": { + target_os: mainProfiles["windows-x86"].target_os, + target_cpu: mainProfiles["windows-x86"].target_cpu, + dependencies: mainProfiles["windows-x86"].dependencies, + configure_args: concat(mainProfiles["windows-x86"].configure_args, + "--enable-openjdk-only"), + make_args: mainProfiles["windows-x86"].make_args, + labels: [ "open" ] } }; profiles = concatObjects(profiles, jprtOpenProfiles); From eee630daaaa7c6709f4de162f3a5248b281bc7bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Mon, 7 Mar 2016 13:28:51 +0100 Subject: [PATCH 255/311] 8148148: Remove pluggable CodeStore API Reviewed-by: attila, mhaupt --- .../nashorn/internal/runtime/CodeStore.java | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java index b7194c649a3..a0abdbd7d7b 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -34,13 +34,10 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.security.AccessControlException; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.util.Iterator; import java.util.Map; -import java.util.ServiceLoader; import jdk.nashorn.internal.codegen.OptimisticTypesPersistence; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.logging.DebugLogger; @@ -54,11 +51,6 @@ import jdk.nashorn.internal.runtime.options.Options; @Logger(name="codestore") public abstract class CodeStore implements Loggable { - /** - * Permission needed to provide a CodeStore instance via ServiceLoader. - */ - public final static String NASHORN_PROVIDE_CODE_STORE = "nashorn.provideCodeStore"; - private DebugLogger log; /** @@ -85,23 +77,6 @@ public abstract class CodeStore implements Loggable { * @return The instance, or null if code store could not be created */ public static CodeStore newCodeStore(final Context context) { - final Class baseClass = CodeStore.class; - try { - // security check first - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission(NASHORN_PROVIDE_CODE_STORE)); - } - final ServiceLoader services = ServiceLoader.load(baseClass); - final Iterator iterator = services.iterator(); - if (iterator.hasNext()) { - final CodeStore store = iterator.next(); - store.initLogger(context).info("using code store provider ", store.getClass().getCanonicalName()); - return store; - } - } catch (final AccessControlException e) { - context.getLogger(CodeStore.class).warning("failed to load code store provider ", e); - } try { final CodeStore store = new DirectoryCodeStore(context); store.initLogger(context); From 3a3ef100336b6e41ad6134d7dcbcdb888769448f Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Mon, 7 Mar 2016 18:49:02 +0530 Subject: [PATCH 256/311] 8148930: Incorrect erasure of exceptions in override-equivalent dual interface impl Before computing intersection of thrown types, javac must make sure type variables come from the same set. Reviewed-by: mcimadamore --- .../com/sun/tools/javac/comp/Resolve.java | 7 ++- .../inference/CheckNoTimeoutException.java | 60 +++++++++++++++++++ .../inference/IntersectThrownTypesTest.java | 28 +++++++++ .../inference/IntersectThrownTypesTest.out | 3 + 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/generics/inference/CheckNoTimeoutException.java create mode 100644 langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.java create mode 100644 langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.out diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 00783594e26..38a941b6312 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -4043,7 +4043,12 @@ public class Resolve { found = false; break; } - allThrown = chk.intersect(allThrown, mt2.getThrownTypes()); + List thrownTypes2 = mt2.getThrownTypes(); + if (mt.hasTag(FORALL) && mt2.hasTag(FORALL)) { + // if both are generic methods, adjust thrown types ahead of intersection computation + thrownTypes2 = types.subst(thrownTypes2, mt2.getTypeArguments(), mt.getTypeArguments()); + } + allThrown = chk.intersect(allThrown, thrownTypes2); } if (found) { //all ambiguous methods were abstract and one method had diff --git a/langtools/test/tools/javac/generics/inference/CheckNoTimeoutException.java b/langtools/test/tools/javac/generics/inference/CheckNoTimeoutException.java new file mode 100644 index 00000000000..4e37114d27e --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/CheckNoTimeoutException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016, 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 8148930 + * @summary Verify that there is no spurious unreported exception error. + * @modules java.sql + * @compile CheckNoTimeoutException.java + */ + +import java.util.Collection; +import java.util.List; +import java.util.ArrayList; +import java.util.concurrent.TimeoutException; +import java.io.*; +import java.sql.SQLException; +import java.sql.SQLTransientException; + +class CheckNoTimeoutException { + + interface V {List foo(List arg) throws EOFException, SQLException, TimeoutException;} + interface U {Collection foo(List arg) throws IOException, SQLTransientException;} + + //SAM type ([List], List/List, {EOFException, SQLTransientException}) + interface UV extends U, V {} + + + private static List strs = new ArrayList(); + void methodUV(UV uv) { + System.out.println("methodUV(): SAM type interface UV object instantiated: " + uv); + try{ + System.out.println("result returned: " + uv.foo(strs)); + }catch(EOFException e){ + System.out.println(e.getMessage()); + }catch(SQLTransientException ex){ + System.out.println(ex.getMessage()); + } + } +} \ No newline at end of file diff --git a/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.java b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.java new file mode 100644 index 00000000000..4a37c4ef4d9 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.java @@ -0,0 +1,28 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8148930 + * @summary Incorrect erasure of exceptions in override-equivalent dual interface impl + * @compile/fail/ref=IntersectThrownTypesTest.out -XDrawDiagnostics IntersectThrownTypesTest.java + */ + +public class IntersectThrownTypesTest { + + interface S1 { + void run(Class clazz) throws K; + } + + interface S2 { + void run(Class clazz) throws K; + } + + interface S extends S1, S2 {} + + public void foo(S1 s) { + s.run(java.io.IOException.class); + } + + public void foo(S s) { + s.run(java.io.IOException.class); + } + +} diff --git a/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.out b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.out new file mode 100644 index 00000000000..c42a1c9d6b5 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.out @@ -0,0 +1,3 @@ +IntersectThrownTypesTest.java:21:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.io.IOException +IntersectThrownTypesTest.java:25:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.io.IOException +2 errors From 9ec6fa880011bbbd050e1e6cffb0409a81376acf Mon Sep 17 00:00:00 2001 From: David Dehaven Date: Mon, 7 Mar 2016 09:08:59 -0800 Subject: [PATCH 257/311] 8132743: Move netscape.javascript package from jdk.plugin to new module Reviewed-by: kcr, mchung, alanb --- make/Images.gmk | 2 +- modules.xml | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/make/Images.gmk b/make/Images.gmk index ca6a4e2d8bf..094f9429920 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -42,7 +42,7 @@ MAIN_MODULES += java.se java.smartcardio jdk.httpserver jdk.sctp \ jdk.security.auth jdk.security.jgss jdk.pack200 jdk.xml.dom \ jdk.accessibility jdk.internal.le jdk.dynalink \ jdk.scripting.nashorn jdk.scripting.nashorn.shell \ - jdk.vm.ci jdk.management + jdk.vm.ci jdk.management jdk.jsobject # providers PROVIDER_MODULES += jdk.charsets jdk.crypto.ec jdk.crypto.pkcs11 jdk.jvmstat jdk.jvmstat.rmi \ diff --git a/modules.xml b/modules.xml index 75a523a8cc8..d1b092aaff3 100644 --- a/modules.xml +++ b/modules.xml @@ -843,6 +843,18 @@ jdk.jshell + + jdk.jsobject + java.base + java.desktop + + netscape.javascript + + + jdk.internal.netscape.javascript.spi + jdk.plugin + + java.httpclient java.base @@ -1802,10 +1814,10 @@ com.sun.tools.javadoc - jdk.javadoc.doclet + jdk.javadoc.doclet - jdk.javadoc.doclet.taglet + jdk.javadoc.doclet.taglet From 3fb108bd73901ba4d8a78ae42022086ba7728808 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 7 Mar 2016 12:10:55 -0800 Subject: [PATCH 258/311] 8151393: Revert changes for JDK-8087104 Reviewed-by: alanb --- .../classes/java/text/DateFormatSymbols.java | 65 ++++------------- .../DateFormat/DFSConstructorCloneTest.java | 70 ------------------- 2 files changed, 13 insertions(+), 122 deletions(-) delete mode 100644 jdk/test/java/text/Format/DateFormat/DFSConstructorCloneTest.java diff --git a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java index 28c3fc7ba00..955415af8b6 100644 --- a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java +++ b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -606,7 +606,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { try { DateFormatSymbols other = (DateFormatSymbols)super.clone(); - copyMembers(new SymbolsCacheEntry(locale), other); + copyMembers(this, other); return other; } catch (CloneNotSupportedException e) { throw new InternalError(e); @@ -669,7 +669,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { /** * Cache to hold DateFormatSymbols instances per Locale. */ - private static final ConcurrentMap> cachedInstances + private static final ConcurrentMap> cachedInstances = new ConcurrentHashMap<>(3); private transient int lastZoneIndex; @@ -683,10 +683,10 @@ public class DateFormatSymbols implements Serializable, Cloneable { locale = desiredLocale; // Copy values of a cached instance if any. - SoftReference ref = cachedInstances.get(locale); - SymbolsCacheEntry sce; - if (ref != null && (sce = ref.get()) != null) { - copyMembers(sce, this); + SoftReference ref = cachedInstances.get(locale); + DateFormatSymbols dfs; + if (ref != null && (dfs = ref.get()) != null) { + copyMembers(dfs, this); return; } @@ -717,11 +717,11 @@ public class DateFormatSymbols implements Serializable, Cloneable { weekdays = toOneBasedArray(resource.getStringArray("DayNames")); shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations")); - sce = new SymbolsCacheEntry(locale); - ref = new SoftReference<>(sce); - SoftReference x = cachedInstances.putIfAbsent(locale, ref); + // Put a clone in the cache + ref = new SoftReference<>((DateFormatSymbols)this.clone()); + SoftReference x = cachedInstances.putIfAbsent(locale, ref); if (x != null) { - SymbolsCacheEntry y = x.get(); + DateFormatSymbols y = x.get(); if (y == null) { // Replace the empty SoftReference with ref. cachedInstances.put(locale, ref); @@ -812,7 +812,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { * @param src the source DateFormatSymbols. * @param dst the target DateFormatSymbols. */ - private void copyMembers(SymbolsCacheEntry src, DateFormatSymbols dst) + private void copyMembers(DateFormatSymbols src, DateFormatSymbols dst) { dst.eras = Arrays.copyOf(src.eras, src.eras.length); dst.months = Arrays.copyOf(src.months, src.months.length); @@ -821,7 +821,7 @@ public class DateFormatSymbols implements Serializable, Cloneable { dst.shortWeekdays = Arrays.copyOf(src.shortWeekdays, src.shortWeekdays.length); dst.ampms = Arrays.copyOf(src.ampms, src.ampms.length); if (src.zoneStrings != null) { - dst.zoneStrings = getZoneStringsImpl(true); + dst.zoneStrings = src.getZoneStringsImpl(true); } else { dst.zoneStrings = null; } @@ -842,43 +842,4 @@ public class DateFormatSymbols implements Serializable, Cloneable { } stream.defaultWriteObject(); } - - private static class SymbolsCacheEntry { - - final String eras[]; - final String months[]; - final String shortMonths[]; - final String weekdays[]; - final String shortWeekdays[]; - final String ampms[]; - final String zoneStrings[][]; - final String localPatternChars; - - SymbolsCacheEntry(Locale locale) { - // Initialize the fields from the ResourceBundle for locale. - LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale); - // Avoid any potential recursions - if (!(adapter instanceof ResourceBundleBasedAdapter)) { - adapter = LocaleProviderAdapter.getResourceBundleBased(); - } - ResourceBundle resource = ((ResourceBundleBasedAdapter) adapter).getLocaleData().getDateFormatData(locale); - if (resource.containsKey("Eras")) { - this.eras = resource.getStringArray("Eras"); - } else if (resource.containsKey("long.Eras")) { - this.eras = resource.getStringArray("long.Eras"); - } else if (resource.containsKey("short.Eras")) { - this.eras = resource.getStringArray("short.Eras"); - } else { - this.eras = null; - } - this.months = resource.getStringArray("MonthNames"); - this.shortMonths = resource.getStringArray("MonthAbbreviations"); - this.weekdays = toOneBasedArray(resource.getStringArray("DayNames")); - this.shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations")); - this.ampms = resource.getStringArray("AmPmMarkers"); - this.zoneStrings = TimeZoneNameUtility.getZoneStrings(locale); - this.localPatternChars = resource.getString("DateTimePatternChars"); - - } - } } diff --git a/jdk/test/java/text/Format/DateFormat/DFSConstructorCloneTest.java b/jdk/test/java/text/Format/DateFormat/DFSConstructorCloneTest.java deleted file mode 100644 index 8632f0932cc..00000000000 --- a/jdk/test/java/text/Format/DateFormat/DFSConstructorCloneTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2016, 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 8087104 - * @summary Make sure that clone() method is not called from DateFormatSymbols constructor. - */ -import java.text.DateFormatSymbols; - -public class DFSymbolsCloneTest extends DateFormatSymbols { - - private Foo foo; - - public DFSymbolsCloneTest(Foo fooObj) { - if (fooObj == null) { - this.foo = new Foo(); - } else { - this.foo = fooObj; - } - } - - @Override - public Object clone() { - DFSymbolsCloneTest dfsclone = (DFSymbolsCloneTest) super.clone(); - if (this.foo == null) { - throw new RuntimeException("Clone method should not be called from " - + " Superclass(DateFormatSymbols) Constructor..."); - } else { - dfsclone.foo = (Foo) this.foo.clone(); - } - return dfsclone; - } - - public static void main(String[] args) { - DFSymbolsCloneTest dfsctest = new DFSymbolsCloneTest(new Foo()); - } -} - -class Foo { - - public Foo() { - } - - @Override - protected Object clone() { - return new Foo(); - } - -} From 8041d8453e9f8f707e239cf485a8fb677df24b5f Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Tue, 8 Mar 2016 09:33:31 +0800 Subject: [PATCH 259/311] 8151352: jdk/test/sample fails with "effective library path is outside the test suite" Reviewed-by: darcy --- jdk/test/sample/TEST.properties | 1 + jdk/test/sample/chatserver/ChatTest.java | 9 ++++++--- jdk/test/sample/mergesort/MergeSortTest.java | 9 ++++++--- 3 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 jdk/test/sample/TEST.properties diff --git a/jdk/test/sample/TEST.properties b/jdk/test/sample/TEST.properties new file mode 100644 index 00000000000..8e5f78afde3 --- /dev/null +++ b/jdk/test/sample/TEST.properties @@ -0,0 +1 @@ +external.lib.roots = ../../ diff --git a/jdk/test/sample/chatserver/ChatTest.java b/jdk/test/sample/chatserver/ChatTest.java index 654819b9fa5..dcfe4d3dd6c 100644 --- a/jdk/test/sample/chatserver/ChatTest.java +++ b/jdk/test/sample/chatserver/ChatTest.java @@ -25,9 +25,9 @@ /* @test * @summary Test chat server chatserver test * - * @library ../../../src/sample/share/nio/chatserver + * @library /src/sample/share/nio/chatserver * @build ChatTest ChatServer Client ClientReader DataReader MessageReader NameReader - * @run main ChatTest + * @run testng ChatTest */ import java.io.*; @@ -38,10 +38,13 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.CyclicBarrier; +import org.testng.annotations.Test; + public class ChatTest { public static int listeningPort = 0; - public static void main(String[] args) throws Throwable { + @Test + public static void doTest() throws Throwable { testStartStop(); testPortOpen(); testAsksForName(); diff --git a/jdk/test/sample/mergesort/MergeSortTest.java b/jdk/test/sample/mergesort/MergeSortTest.java index e38a0e03413..fb082c21a56 100644 --- a/jdk/test/sample/mergesort/MergeSortTest.java +++ b/jdk/test/sample/mergesort/MergeSortTest.java @@ -25,14 +25,16 @@ /* @test * @summary Test MergeSort * - * @library ../../../src/sample/share/forkjoin/mergesort + * @library /src/sample/share/forkjoin/mergesort * @build MergeSortTest MergeDemo MergeSort - * @run main MergeSortTest + * @run testng MergeSortTest */ import java.util.Arrays; import java.util.Random; +import org.testng.annotations.Test; + public class MergeSortTest { private Random random; private MergeSort target; @@ -42,7 +44,8 @@ public class MergeSortTest { this.target = target; } - public static void main(String[] args) { + @Test + public static void doTest() { MergeSortTest test = new MergeSortTest(new Random(), new MergeSort(Runtime.getRuntime().availableProcessors() * 4)); test.run(); } From 34313c01e33f7825b3fc6db450ced4b9fd66f0f8 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Tue, 8 Mar 2016 11:01:38 +0000 Subject: [PATCH 260/311] 8143610: (dc) java/nio/channels/DatagramChannel/AdaptDatagramSocket.java failed intermittently due to SocketTimeoutException Reviewed-by: alanb --- .../nio/channels/DatagramChannel/AdaptDatagramSocket.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java index b8ec1c1060b..8b23f14f960 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java +++ b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313882 4981129 + * @bug 4313882 4981129 8143610 * @summary Unit test for datagram-socket-channel adaptors * @library .. * @key randomness @@ -137,7 +137,7 @@ public class AdaptDatagramSocket { echoServer.getPort()); test(address, 0, false, false); test(address, 0, false, true); - test(address, 15000, false, false); + test(address, Integer.MAX_VALUE, false, false); } try (TestServers.UdpDiscardServer discardServer = TestServers.UdpDiscardServer.startNewServer()) { From bd69ca08d2ec1b6c77a8389f986d05458cc8672a Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 8 Mar 2016 12:11:07 +0000 Subject: [PATCH 261/311] 8151384: Improve String.CASE_INSENSITIVE_ORDER and remove sun.misc.ASCIICaseInsensitiveComparator Reviewed-by: shade, sherman --- .../share/classes/java/lang/String.java | 28 +----- .../share/classes/java/lang/StringLatin1.java | 42 ++++++++ .../share/classes/java/lang/StringUTF16.java | 44 +++++++++ .../classes/java/nio/charset/Charset.java | 3 +- .../classes/java/util/jar/Attributes.java | 6 +- .../misc/ASCIICaseInsensitiveComparator.java | 99 ------------------- .../nio/cs/ext/AbstractCharsetProvider.java | 9 +- 7 files changed, 99 insertions(+), 132 deletions(-) delete mode 100644 jdk/src/java.base/share/classes/sun/misc/ASCIICaseInsensitiveComparator.java diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java index 86ec043d5b1..85916e672d9 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -1222,30 +1222,12 @@ public final class String public int compare(String s1, String s2) { byte v1[] = s1.value; byte v2[] = s2.value; - int n1 = s1.length(); - int n2 = s2.length(); - boolean s1IsLatin1 = s1.isLatin1(); - boolean s2IsLatin1 = s2.isLatin1(); - int min = Math.min(n1, n2); - for (int i = 0; i < min; i++) { - char c1 = s1IsLatin1 ? StringLatin1.getChar(v1, i) - : StringUTF16.getChar(v1, i); - char c2 = s2IsLatin1 ? StringLatin1.getChar(v2, i) - : StringUTF16.getChar(v2, i); - if (c1 != c2) { - c1 = Character.toUpperCase(c1); - c2 = Character.toUpperCase(c2); - if (c1 != c2) { - c1 = Character.toLowerCase(c1); - c2 = Character.toLowerCase(c2); - if (c1 != c2) { - // No overflow because of numeric promotion - return c1 - c2; - } - } - } + if (s1.coder() == s2.coder()) { + return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2) + : StringUTF16.compareToCI(v1, v2); } - return n1 - n2; + return s1.isLatin1() ? StringLatin1.compareToCI_UTF16(v1, v2) + : StringUTF16.compareToCI_Latin1(v1, v2); } /** Replaces the de-serialized object. */ diff --git a/jdk/src/java.base/share/classes/java/lang/StringLatin1.java b/jdk/src/java.base/share/classes/java/lang/StringLatin1.java index 8e8016d833e..c491f4833e1 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringLatin1.java +++ b/jdk/src/java.base/share/classes/java/lang/StringLatin1.java @@ -128,6 +128,48 @@ final class StringLatin1 { return len1 - len2; } + public static int compareToCI(byte[] value, byte[] other) { + int len1 = value.length; + int len2 = other.length; + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + if (value[k] != other[k]) { + char c1 = (char) CharacterDataLatin1.instance.toUpperCase(getChar(value, k)); + char c2 = (char) CharacterDataLatin1.instance.toUpperCase(getChar(other, k)); + if (c1 != c2) { + c1 = (char) CharacterDataLatin1.instance.toLowerCase(c1); + c2 = (char) CharacterDataLatin1.instance.toLowerCase(c2); + if (c1 != c2) { + return c1 - c2; + } + } + } + } + return len1 - len2; + } + + public static int compareToCI_UTF16(byte[] value, byte[] other) { + int len1 = length(value); + int len2 = StringUTF16.length(other); + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + char c1 = getChar(value, k); + char c2 = StringUTF16.getChar(other, k); + if (c1 != c2) { + c1 = Character.toUpperCase(c1); + c2 = Character.toUpperCase(c2); + if (c1 != c2) { + c1 = Character.toLowerCase(c1); + c2 = Character.toLowerCase(c2); + if (c1 != c2) { + return c1 - c2; + } + } + } + } + return len1 - len2; + } + public static int hashCode(byte[] value) { int h = 0; for (byte v : value) { diff --git a/jdk/src/java.base/share/classes/java/lang/StringUTF16.java b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java index 937f642ce8d..fe0c964b290 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringUTF16.java +++ b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java @@ -270,6 +270,50 @@ final class StringUTF16 { return len1 - len2; } + public static int compareToCI(byte[] value, byte[] other) { + int len1 = length(value); + int len2 = length(other); + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + char c1 = getChar(value, k); + char c2 = getChar(other, k); + if (c1 != c2) { + c1 = Character.toUpperCase(c1); + c2 = Character.toUpperCase(c2); + if (c1 != c2) { + c1 = Character.toLowerCase(c1); + c2 = Character.toLowerCase(c2); + if (c1 != c2) { + return c1 - c2; + } + } + } + } + return len1 - len2; + } + + public static int compareToCI_Latin1(byte[] value, byte[] other) { + int len1 = length(value); + int len2 = StringLatin1.length(other); + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + char c1 = getChar(value, k); + char c2 = StringLatin1.getChar(other, k); + if (c1 != c2) { + c1 = Character.toUpperCase(c1); + c2 = Character.toUpperCase(c2); + if (c1 != c2) { + c1 = Character.toLowerCase(c1); + c2 = Character.toLowerCase(c2); + if (c1 != c2) { + return c1 - c2; + } + } + } + } + return len1 - len2; + } + public static int hashCode(byte[] value) { int h = 0; int length = value.length >> 1; diff --git a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java index de85b2f525c..78ee33e764a 100644 --- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java @@ -44,7 +44,6 @@ import java.util.ServiceConfigurationError; import java.util.SortedMap; import java.util.TreeMap; import jdk.internal.misc.VM; -import sun.misc.ASCIICaseInsensitiveComparator; import sun.nio.cs.StandardCharsets; import sun.nio.cs.ThreadLocalCoders; import sun.security.action.GetPropertyAction; @@ -579,7 +578,7 @@ public abstract class Charset public SortedMap run() { TreeMap m = new TreeMap<>( - ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + String.CASE_INSENSITIVE_ORDER); put(standardProvider.charsets(), m); CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders; for (CharsetProvider ecp :ecps) { diff --git a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java index b99755b4bb6..342c85ea2fd 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java +++ b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java @@ -34,9 +34,9 @@ import java.util.Set; import java.util.Collection; import java.util.AbstractSet; import java.util.Iterator; +import java.util.Locale; import sun.util.logging.PlatformLogger; import java.util.Comparator; -import sun.misc.ASCIICaseInsensitiveComparator; /** * The Attributes class maps Manifest attribute names to associated string @@ -501,7 +501,7 @@ public class Attributes implements Map, Cloneable { */ public boolean equals(Object o) { if (o instanceof Name) { - Comparator c = ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER; + Comparator c = String.CASE_INSENSITIVE_ORDER; return c.compare(name, ((Name)o).name) == 0; } else { return false; @@ -513,7 +513,7 @@ public class Attributes implements Map, Cloneable { */ public int hashCode() { if (hashCode == -1) { - hashCode = ASCIICaseInsensitiveComparator.lowerCaseHashCode(name); + hashCode = name.toLowerCase(Locale.ROOT).hashCode(); } return hashCode; } diff --git a/jdk/src/java.base/share/classes/sun/misc/ASCIICaseInsensitiveComparator.java b/jdk/src/java.base/share/classes/sun/misc/ASCIICaseInsensitiveComparator.java deleted file mode 100644 index 9fdc6b53b54..00000000000 --- a/jdk/src/java.base/share/classes/sun/misc/ASCIICaseInsensitiveComparator.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2002, 2004, 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. - */ - -package sun.misc; - -import java.util.Comparator; - -/** Implements a locale and case insensitive comparator suitable for - strings that are known to only contain ASCII characters. Some - tables internal to the JDK contain only ASCII data and are using - the "generalized" java.lang.String case-insensitive comparator - which converts each character to both upper and lower case. */ - -public class ASCIICaseInsensitiveComparator implements Comparator { - public static final Comparator CASE_INSENSITIVE_ORDER = - new ASCIICaseInsensitiveComparator(); - - public int compare(String s1, String s2) { - int n1=s1.length(), n2=s2.length(); - int minLen = n1 < n2 ? n1 : n2; - for (int i=0; i < minLen; i++) { - char c1 = s1.charAt(i); - char c2 = s2.charAt(i); - assert c1 <= '\u007F' && c2 <= '\u007F'; - if (c1 != c2) { - c1 = (char)toLower(c1); - c2 = (char)toLower(c2); - if (c1 != c2) { - return c1 - c2; - } - } - } - return n1 - n2; - } - - /** - * A case insensitive hash code method to go with the case insensitive - * compare() method. - * - * Returns a hash code for this ASCII string as if it were lower case. - * - * returns same answer as:

          - * s.toLowerCase(Locale.US).hashCode();

          - * but does not allocate memory (it does NOT have the special - * case Turkish rules). - * - * @param s a String to compute the hashcode on. - * @return a hash code value for this object. - */ - public static int lowerCaseHashCode(String s) { - int h = 0; - int len = s.length(); - - for (int i = 0; i < len; i++) { - h = 31*h + toLower(s.charAt(i)); - } - - return h; - } - - /* If java.util.regex.ASCII ever becomes public or sun.*, use its code instead:*/ - static boolean isLower(int ch) { - return ((ch-'a')|('z'-ch)) >= 0; - } - - static boolean isUpper(int ch) { - return ((ch-'A')|('Z'-ch)) >= 0; - } - - static int toLower(int ch) { - return isUpper(ch) ? (ch + 0x20) : ch; - } - - static int toUpper(int ch) { - return isLower(ch) ? (ch - 0x20) : ch; - } -} diff --git a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java index 972d6593573..1c60443415b 100644 --- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java +++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java @@ -33,7 +33,6 @@ import java.util.TreeMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; -import sun.misc.ASCIICaseInsensitiveComparator; /** @@ -49,22 +48,22 @@ public class AbstractCharsetProvider /* Maps canonical names to class names */ private Map classMap - = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); /* Maps alias names to canonical names */ private Map aliasMap - = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); /* Maps canonical names to alias-name arrays */ private Map aliasNameMap - = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); /* Maps canonical names to soft references that hold cached instances */ private Map> cache - = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private String packagePrefix; From 11def8caf10630801d75d22813c02f20557231ea Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Tue, 8 Mar 2016 15:51:49 +0100 Subject: [PATCH 262/311] 8151435: Windows devkit missing 32bit msvcdis120.dll Reviewed-by: tbell --- make/devkit/createWindowsDevkit.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/make/devkit/createWindowsDevkit.sh b/make/devkit/createWindowsDevkit.sh index 187a4c7c154..fd007a01a9b 100644 --- a/make/devkit/createWindowsDevkit.sh +++ b/make/devkit/createWindowsDevkit.sh @@ -74,6 +74,10 @@ if [ ! -d $DEVKIT_ROOT/VC ]; then cp $DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/ cp $DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/amd64/ cp $DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/amd64/ + # The msvcdis dll is needed to run some of the tools in VC/bin but is not + # shipped in that directory. Copy it from the common dir. + cp "$VS_INSTALL_DIR/Common7/IDE/msvcdis${VS_VERSION_NUM_NODOT}.dll" \ + $DEVKIT_ROOT/VC/bin/ fi ################################################################################ From 685358ed9331fc2afad346611ddeb6275b4e29d4 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Tue, 8 Mar 2016 11:36:30 -0800 Subject: [PATCH 263/311] 8148187: Remove OS X-specific com.apple.concurrent package Removed jdk.deploy.osx module (including com.apple.concurrent) Reviewed-by: alanb, erikj, mchung --- common/bin/unshuffle_list.txt | 8 ++------ make/Images.gmk | 4 ---- make/Main.gmk | 3 --- make/common/NON_CORE_PKGS.gmk | 3 +-- modules.xml | 9 --------- 5 files changed, 3 insertions(+), 24 deletions(-) diff --git a/common/bin/unshuffle_list.txt b/common/bin/unshuffle_list.txt index a419fe43a57..daa919b9444 100644 --- a/common/bin/unshuffle_list.txt +++ b/common/bin/unshuffle_list.txt @@ -1293,12 +1293,8 @@ jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.c : jdk/src/win jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.h : jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.h jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.c : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.c jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.h : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.h -jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html : jdk/src/macosx/classes/com/apple/concurrent/package.html -jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent : jdk/src/macosx/classes/com/apple/concurrent -jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m : jdk/src/macosx/native/com/apple/eio/CFileManager.m -jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m : jdk/src/macosx/native/com/apple/concurrent/Dispatch.m -jdk/src/jdk.deploy.osx/macosx/native/libosx/JavaAppLauncher.m : jdk/src/macosx/native/apple/launcher/JavaAppLauncher.m -jdk/src/jdk.deploy.osx/macosx/native/libosx/KeystoreImpl.m : jdk/src/macosx/native/apple/security/KeystoreImpl.m +jdk/src/java.desktop/macosx/native/libosx/CFileManager.m : jdk/src/macosx/native/com/apple/eio/CFileManager.m +jdk/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m : jdk/src/macosx/native/apple/security/KeystoreImpl.m jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof : jdk/src/share/classes/com/sun/demo/jvmti/hprof jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver : jdk/src/share/classes/com/sun/net/httpserver jdk/src/jdk.httpserver/share/classes/sun/net/httpserver : jdk/src/share/classes/sun/net/httpserver diff --git a/make/Images.gmk b/make/Images.gmk index 094f9429920..7fc063773d6 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -62,10 +62,6 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) PROVIDER_MODULES += jdk.crypto.ucrypto endif -ifeq ($(OPENJDK_TARGET_OS), macosx) - MAIN_MODULES += jdk.deploy.osx -endif - JRE_MODULES := $(filter-out $(MODULES_FILTER), $(MAIN_MODULES) $(PROVIDER_MODULES)) JDK_MODULES := $(filter-out $(MODULES_FILTER), $(JRE_MODULES) $(TOOLS_MODULES)) diff --git a/make/Main.gmk b/make/Main.gmk index b354d9de9ab..66509ddfdcb 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -413,9 +413,6 @@ else # Declare dependencies from all other -lib to java.base-lib $(foreach t, $(filter-out java.base-libs, $(LIBS_TARGETS)), \ $(eval $t: java.base-libs)) - # Declare the special case dependency for jdk.deploy.osx where libosx - # links against libosxapp. - jdk.deploy.osx-libs: java.desktop-libs # jdk.accessibility depends on java.desktop jdk.accessibility-libs: java.desktop-libs diff --git a/make/common/NON_CORE_PKGS.gmk b/make/common/NON_CORE_PKGS.gmk index bf02064cf63..7e63750d28f 100644 --- a/make/common/NON_CORE_PKGS.gmk +++ b/make/common/NON_CORE_PKGS.gmk @@ -98,8 +98,7 @@ SMARTCARDIO_PKGS = javax.smartcardio SCTPAPI_PKGS = com.sun.nio.sctp ifeq ($(PLATFORM), macosx) - APPLE_EXT_PKGS = com.apple.concurrent \ - com.apple.eawt \ + APPLE_EXT_PKGS = com.apple.eawt \ com.apple.eawt.event \ com.apple.eio endif diff --git a/modules.xml b/modules.xml index d1b092aaff3..29133b98552 100644 --- a/modules.xml +++ b/modules.xml @@ -300,7 +300,6 @@ java.xml jdk.charsets jdk.crypto.pkcs11 - jdk.deploy.osx jdk.httpserver jdk.jartool jdk.jconsole @@ -421,7 +420,6 @@ sun.security.pkcs jdk.crypto.ec - jdk.deploy.osx jdk.jartool @@ -462,7 +460,6 @@ jdk.crypto.mscapi jdk.crypto.pkcs11 jdk.crypto.ucrypto - jdk.deploy.osx jdk.jartool jdk.policytool jdk.security.auth @@ -473,7 +470,6 @@ java.naming jdk.crypto.ec jdk.crypto.pkcs11 - jdk.deploy.osx jdk.jartool jdk.security.auth @@ -1706,11 +1702,6 @@ jdk.crypto.ucrypto java.base - - jdk.deploy.osx - java.base - java.desktop - jdk.dev java.base From 7d85e0638fba8325daee77bc5e70793bfa82930d Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Tue, 8 Mar 2016 11:36:42 -0800 Subject: [PATCH 264/311] 8148187: Remove OS X-specific com.apple.concurrent package Removed jdk.deploy.osx module (including com.apple.concurrent) Reviewed-by: alanb, erikj, mchung --- jdk/make/lib/Lib-java.desktop.gmk | 1 + ...jdk.deploy.osx.gmk => LibosxLibraries.gmk} | 5 +- .../classes/build/tools/module/boot.modules | 1 - .../macosx/native/libosx/CFileManager.m | 0 .../com/apple/concurrent/Dispatch.java | 141 -------------- .../LibDispatchConcurrentQueue.java | 44 ----- .../concurrent/LibDispatchMainQueue.java | 53 ------ .../apple/concurrent/LibDispatchNative.java | 48 ----- .../apple/concurrent/LibDispatchQueue.java | 32 ---- .../LibDispatchRetainedResource.java | 43 ----- .../concurrent/LibDispatchSerialQueue.java | 100 ---------- .../classes/com/apple/concurrent/package.html | 7 - .../macosx/native/libosx/Dispatch.m | 174 ------------------ 13 files changed, 2 insertions(+), 647 deletions(-) rename jdk/make/lib/{Lib-jdk.deploy.osx.gmk => LibosxLibraries.gmk} (94%) rename jdk/src/{jdk.deploy.osx => java.desktop}/macosx/native/libosx/CFileManager.m (100%) delete mode 100644 jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/Dispatch.java delete mode 100644 jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchConcurrentQueue.java delete mode 100644 jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchMainQueue.java delete mode 100644 jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchNative.java delete mode 100644 jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchQueue.java delete mode 100644 jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchRetainedResource.java delete mode 100644 jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchSerialQueue.java delete mode 100644 jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html delete mode 100644 jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m diff --git a/jdk/make/lib/Lib-java.desktop.gmk b/jdk/make/lib/Lib-java.desktop.gmk index c8bc8195854..5433fe96acb 100644 --- a/jdk/make/lib/Lib-java.desktop.gmk +++ b/jdk/make/lib/Lib-java.desktop.gmk @@ -29,6 +29,7 @@ include LibCommon.gmk $(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/java.desktop/*/native \ $(JDK_TOPDIR)/src/*/java.desktop/*/native))) +include LibosxLibraries.gmk include PlatformLibraries.gmk include Awt2dLibraries.gmk include SoundLibraries.gmk diff --git a/jdk/make/lib/Lib-jdk.deploy.osx.gmk b/jdk/make/lib/LibosxLibraries.gmk similarity index 94% rename from jdk/make/lib/Lib-jdk.deploy.osx.gmk rename to jdk/make/lib/LibosxLibraries.gmk index 881a387e14d..91ab6457cb4 100644 --- a/jdk/make/lib/Lib-jdk.deploy.osx.gmk +++ b/jdk/make/lib/LibosxLibraries.gmk @@ -23,18 +23,15 @@ # questions. # -include LibCommon.gmk - ifeq ($(OPENJDK_TARGET_OS), macosx) ################################################################################ - LIBOSX_DIRS := $(JDK_TOPDIR)/src/jdk.deploy.osx/macosx/native/libosx + LIBOSX_DIRS := $(JDK_TOPDIR)/src/java.desktop/macosx/native/libosx LIBOSX_CFLAGS := -I$(LIBOSX_DIRS) \ -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libosxapp \ $(LIBJAVA_HEADER_FLAGS) \ -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.deploy.osx \ # $(eval $(call SetupNativeCompilation,BUILD_LIBOSX, \ diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index c774b5a0300..948362f0a51 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -19,7 +19,6 @@ java.xml java.xml.crypto jdk.charsets jdk.deploy -jdk.deploy.osx jdk.httpserver jdk.jfr jdk.jsobject diff --git a/jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m b/jdk/src/java.desktop/macosx/native/libosx/CFileManager.m similarity index 100% rename from jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m rename to jdk/src/java.desktop/macosx/native/libosx/CFileManager.m diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/Dispatch.java b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/Dispatch.java deleted file mode 100644 index e983504a626..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/Dispatch.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package com.apple.concurrent; - -import java.util.concurrent.*; - -/** - * Factory for {@link Executor}s and {@link ExecutorService}s backed by - * libdispatch. - * - * Access is controlled through the Dispatch.getInstance() method, because - * performed tasks occur on threads owned by libdispatch. These threads are - * not owned by any particular AppContext or have any specific context - * classloader installed. - * - * @since Java for Mac OS X 10.6 Update 2 - */ -public final class Dispatch { - /** - * The priorities of the three default asynchronous queues. - */ - public enum Priority { - LOW(-2), NORMAL(0), HIGH(2); // values from - - final int nativePriority; - Priority(final int nativePriority) { this.nativePriority = nativePriority; } - }; - - final static Dispatch instance = new Dispatch(); - - /** - * Factory method returns an instnace of Dispatch if supported by the - * underlying operating system, and if the caller's security manager - * permits "canInvokeInSystemThreadGroup". - * - * @return a factory instance of Dispatch, or null if not available - */ - public static Dispatch getInstance() { - checkSecurity(); - if (!LibDispatchNative.nativeIsDispatchSupported()) return null; - - return instance; - } - - private static void checkSecurity() { - final SecurityManager security = System.getSecurityManager(); - if (security != null) security.checkPermission(new RuntimePermission("canInvokeInSystemThreadGroup")); - } - - private Dispatch() { } - - /** - * Creates an {@link Executor} that performs tasks asynchronously. The {@link Executor} - * cannot be shutdown, and enqueued {@link Runnable}s cannot be canceled. Passing null - * returns the {@link Priority.NORMAL} {@link Executor}. - * - * @param priority - the priority of the returned {@link Executor} - * @return an asynchronous {@link Executor} - */ - public Executor getAsyncExecutor(Priority priority) { - if (priority == null) priority = Priority.NORMAL; - final long nativeQueue = LibDispatchNative.nativeCreateConcurrentQueue(priority.nativePriority); - if (nativeQueue == 0L) return null; - return new LibDispatchConcurrentQueue(nativeQueue); - } - - int queueIndex = 0; - /** - * Creates an {@link ExecutorService} that performs tasks synchronously in FIFO order. - * Useful to protect a resource against concurrent modification, in lieu of a lock. - * Passing null returns an {@link ExecutorService} with a uniquely labeled queue. - * - * @param label - a label to name the queue, shown in several debugging tools - * @return a synchronous {@link ExecutorService} - */ - public ExecutorService createSerialExecutor(String label) { - if (label == null) label = ""; - if (label.length() > 256) label = label.substring(0, 256); - String queueName = "com.apple.java.concurrent."; - if ("".equals(label)) { - synchronized (this) { - queueName += queueIndex++; - } - } else { - queueName += label; - } - - final long nativeQueue = LibDispatchNative.nativeCreateSerialQueue(queueName); - if (nativeQueue == 0) return null; - return new LibDispatchSerialQueue(nativeQueue); - } - - Executor nonBlockingMainQueue = null; - /** - * Returns an {@link Executor} that performs the provided Runnables on the main queue of the process. - * Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread. - * - * Submitting a Runnable to this {@link Executor} does not wait for the Runnable to complete. - * @return an asynchronous {@link Executor} that is backed by the main queue - */ - public synchronized Executor getNonBlockingMainQueueExecutor() { - if (nonBlockingMainQueue != null) return nonBlockingMainQueue; - return nonBlockingMainQueue = new LibDispatchMainQueue.ASync(); - } - - Executor blockingMainQueue = null; - /** - * Returns an {@link Executor} that performs the provided Runnables on the main queue of the process. - * Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread. - * - * Submitting a Runnable to this {@link Executor} will block until the Runnable has completed. - * @return an {@link Executor} that is backed by the main queue - */ - public synchronized Executor getBlockingMainQueueExecutor() { - if (blockingMainQueue != null) return blockingMainQueue; - return blockingMainQueue = new LibDispatchMainQueue.Sync(); - } -} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchConcurrentQueue.java b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchConcurrentQueue.java deleted file mode 100644 index af055aedb57..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchConcurrentQueue.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package com.apple.concurrent; - -import java.util.concurrent.Executor; - -class LibDispatchConcurrentQueue extends LibDispatchQueue implements Executor { - LibDispatchConcurrentQueue(final long queuePtr) { - super(queuePtr); - } - - @Override - public void execute(final Runnable task) { - LibDispatchNative.nativeExecuteAsync(ptr, task); - } - - @Override - protected synchronized void dispose() { - // should not dispose the default concurrent queues - } -} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchMainQueue.java b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchMainQueue.java deleted file mode 100644 index 1e05192986c..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchMainQueue.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package com.apple.concurrent; - -import java.util.concurrent.Executor; - -abstract class LibDispatchMainQueue extends LibDispatchQueue implements Executor { - public LibDispatchMainQueue() { - super(LibDispatchNative.nativeGetMainQueue()); - } - - @Override - protected synchronized void dispose() { - // should not dispose the main queue - } - - static class Sync extends LibDispatchMainQueue { - @Override - public void execute(final Runnable task) { - LibDispatchNative.nativeExecuteSync(ptr, task); - } - } - - static class ASync extends LibDispatchMainQueue { - @Override - public void execute(final Runnable task) { - LibDispatchNative.nativeExecuteAsync(ptr, task); - } - } -} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchNative.java b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchNative.java deleted file mode 100644 index 9b89ac546e3..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchNative.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package com.apple.concurrent; - -final class LibDispatchNative { - static { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("osx"); - return null; - } - }); - } - - static native boolean nativeIsDispatchSupported(); - static native long nativeGetMainQueue(); - static native long nativeCreateConcurrentQueue(int priority); - static native long nativeCreateSerialQueue(String name); - static native void nativeReleaseQueue(long nativeQueue); - static native void nativeExecuteAsync(long nativeQueue, Runnable task); - static native void nativeExecuteSync(long nativeQueue, Runnable task); - - private LibDispatchNative() { } -} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchQueue.java b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchQueue.java deleted file mode 100644 index f464f698541..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchQueue.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package com.apple.concurrent; - -class LibDispatchQueue extends LibDispatchRetainedResource { - LibDispatchQueue(final long queuePtr) { - super(queuePtr); - } -} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchRetainedResource.java b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchRetainedResource.java deleted file mode 100644 index 9d6b59543b0..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchRetainedResource.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package com.apple.concurrent; - -class LibDispatchRetainedResource { - protected long ptr; - - protected LibDispatchRetainedResource(final long ptr) { - this.ptr = ptr; - } - - protected synchronized void dispose() { - if (ptr != 0) LibDispatchNative.nativeReleaseQueue(ptr); - ptr = 0; - } - - protected void finalize() throws Throwable { - dispose(); - } -} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchSerialQueue.java b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchSerialQueue.java deleted file mode 100644 index bb22566aef0..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchSerialQueue.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package com.apple.concurrent; - -import java.util.List; -import java.util.concurrent.*; - -class LibDispatchSerialQueue extends AbstractExecutorService { - static final int RUNNING = 0; - static final int SHUTDOWN = 1; -// static final int STOP = 2; // not supported by GCD - static final int TERMINATED = 3; - - final Object lock = new Object(); - LibDispatchQueue nativeQueueWrapper; - volatile int runState; - - LibDispatchSerialQueue(final long queuePtr) { - nativeQueueWrapper = new LibDispatchQueue(queuePtr); - } - - @Override - public void execute(final Runnable task) { - if (nativeQueueWrapper == null) return; - LibDispatchNative.nativeExecuteAsync(nativeQueueWrapper.ptr, task); - } - - @Override - public boolean isShutdown() { - return runState != RUNNING; - } - - @Override - public boolean isTerminated() { - return runState == TERMINATED; - } - - @Override - public void shutdown() { - synchronized (lock) { - if (runState != RUNNING) return; - - runState = SHUTDOWN; - execute(new Runnable() { - public void run() { - synchronized (lock) { - runState = TERMINATED; - lock.notifyAll(); // for the benefit of awaitTermination() - } - } - }); - nativeQueueWrapper = null; - } - } - - @Override - public List shutdownNow() { - shutdown(); - return null; - } - - @Override - public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException { - if (runState == TERMINATED) return true; - - final long millis = unit.toMillis(timeout); - if (millis <= 0) return false; - - synchronized (lock) { - if (runState == TERMINATED) return true; - lock.wait(timeout); - if (runState == TERMINATED) return true; - } - - return false; - } -} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html deleted file mode 100644 index 003a7a239f3..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - -Apple-specific implementations of the java.util.concurrent.* API based on libdispatch. - - diff --git a/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m b/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m deleted file mode 100644 index cdeac0d435d..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2011, 2015, 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. - */ - -/* - * Must include this before JavaNativeFoundation.h to get jni.h from build - */ -#include "jni.h" -#include "jni_util.h" - -#import "com_apple_concurrent_LibDispatchNative.h" - -#import -#import - -/* - * Declare library specific JNI_Onload entry if static build - */ -DEF_STATIC_JNI_OnLoad - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeIsDispatchSupported - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeIsDispatchSupported -(JNIEnv *env, jclass clazz) -{ - return JNI_TRUE; -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeGetMainQueue - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeGetMainQueue -(JNIEnv *env, jclass clazz) -{ - dispatch_queue_t queue = dispatch_get_main_queue(); - return ptr_to_jlong(queue); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeCreateConcurrentQueue - * Signature: (I)J - */ -JNIEXPORT jlong JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeCreateConcurrentQueue -(JNIEnv *env, jclass clazz, jint priority) -{ - dispatch_queue_t queue = dispatch_get_global_queue((long)priority, 0); - return ptr_to_jlong(queue); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeCreateSerialQueue - * Signature: (Ljava/lang/String;)J - */ -JNIEXPORT jlong JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeCreateSerialQueue -(JNIEnv *env, jclass clazz, jstring name) -{ - if (name == NULL) return 0L; - - jboolean isCopy; - const char *queue_name = (*env)->GetStringUTFChars(env, name, &isCopy); - dispatch_queue_t queue = dispatch_queue_create(queue_name, NULL); - (*env)->ReleaseStringUTFChars(env, name, queue_name); - - return ptr_to_jlong(queue); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeReleaseQueue - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeReleaseQueue -(JNIEnv *env, jclass clazz, jlong nativeQueue) -{ - if (nativeQueue == 0L) return; - dispatch_release((dispatch_queue_t)jlong_to_ptr(nativeQueue)); -} - - -static JNF_CLASS_CACHE(jc_Runnable, "java/lang/Runnable"); -static JNF_MEMBER_CACHE(jm_run, jc_Runnable, "run", "()V"); - -static void perform_dispatch(JNIEnv *env, jlong nativeQueue, jobject runnable, void (*dispatch_fxn)(dispatch_queue_t, dispatch_block_t)) -{ -JNF_COCOA_ENTER(env); - dispatch_queue_t queue = (dispatch_queue_t)jlong_to_ptr(nativeQueue); - if (queue == NULL) return; // shouldn't happen - - // create a global-ref around the Runnable, so it can be safely passed to the dispatch thread - JNFJObjectWrapper *wrappedRunnable = [[JNFJObjectWrapper alloc] initWithJObject:runnable withEnv:env]; - - dispatch_fxn(queue, ^{ - // attach the dispatch thread to the JVM if necessary, and get an env - JNFThreadContext ctx = JNFThreadDetachOnThreadDeath | JNFThreadSetSystemClassLoaderOnAttach | JNFThreadAttachAsDaemon; - JNIEnv *blockEnv = JNFObtainEnv(&ctx); - - JNF_COCOA_ENTER(blockEnv); - - // call the user's runnable - JNFCallObjectMethod(blockEnv, [wrappedRunnable jObject], jm_run); - - // explicitly clear object while we have an env (it's cheaper that way) - [wrappedRunnable setJObject:NULL withEnv:blockEnv]; - - JNF_COCOA_EXIT(blockEnv); - - // let the env go, but leave the thread attached as a daemon - JNFReleaseEnv(blockEnv, &ctx); - }); - - // release this thread's interest in the Runnable, the block - // will have retained the it's own interest above - [wrappedRunnable release]; - -JNF_COCOA_EXIT(env); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeExecuteAsync - * Signature: (JLjava/lang/Runnable;)V - */ -JNIEXPORT void JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeExecuteAsync -(JNIEnv *env, jclass clazz, jlong nativeQueue, jobject runnable) -{ - // enqueues and returns - perform_dispatch(env, nativeQueue, runnable, dispatch_async); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeExecuteSync - * Signature: (JLjava/lang/Runnable;)V - */ -JNIEXPORT void JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeExecuteSync -(JNIEnv *env, jclass clazz, jlong nativeQueue, jobject runnable) -{ - // blocks until the Runnable completes - perform_dispatch(env, nativeQueue, runnable, dispatch_sync); -} From 54ca53c593e61a4983d72a6f26ac4f73f19600ec Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 8 Mar 2016 15:10:02 -0800 Subject: [PATCH 265/311] 8151266: HotSpotResolvedJavaFieldImpl::isStable() does not work as expected Reviewed-by: never, twisti --- .../ci/hotspot/HotSpotMetaAccessProvider.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java index 5bd116cd57b..fd92a15bd96 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java @@ -41,7 +41,6 @@ import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -111,23 +110,26 @@ public class HotSpotMetaAccessProvider implements MetaAccessProvider, HotSpotPro } public ResolvedJavaField lookupJavaField(Field reflectionField) { - String name = reflectionField.getName(); Class fieldHolder = reflectionField.getDeclaringClass(); - Class fieldType = reflectionField.getType(); - // java.lang.reflect.Field's modifiers should be enough here since VM internal modifier bits - // are not used (yet). - final int modifiers = reflectionField.getModifiers(); - final long offset = Modifier.isStatic(modifiers) ? UNSAFE.staticFieldOffset(reflectionField) : UNSAFE.objectFieldOffset(reflectionField); HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder); - JavaType type = runtime.fromClass(fieldType); - - if (offset != -1) { - HotSpotResolvedObjectType resolved = holder; - return resolved.createField(name, type, offset, modifiers); + if (Modifier.isStatic(reflectionField.getModifiers())) { + final long offset = UNSAFE.staticFieldOffset(reflectionField); + for (ResolvedJavaField field : holder.getStaticFields()) { + if (offset == ((HotSpotResolvedJavaField) field).offset()) { + return field; + } + } } else { - throw new JVMCIError("unresolved field %s", reflectionField); + final long offset = UNSAFE.objectFieldOffset(reflectionField); + for (ResolvedJavaField field : holder.getInstanceFields(false)) { + if (offset == ((HotSpotResolvedJavaField) field).offset()) { + return field; + } + } } + + throw new JVMCIError("unresolved field %s", reflectionField); } private static int intMaskRight(int n) { From 025fa588dc68ce37fa09d10f6820ff23beb0e6ae Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Wed, 9 Mar 2016 11:35:21 +0800 Subject: [PATCH 266/311] 8151260: Mark URLPermission/URLTest.java and ipv6tests/TcpTest.java as intermittently failing Reviewed-by: chegar --- jdk/test/java/net/URLPermission/URLTest.java | 3 ++- jdk/test/java/net/ipv6tests/TcpTest.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/net/URLPermission/URLTest.java b/jdk/test/java/net/URLPermission/URLTest.java index 266fdfd0a89..710e8f59cf7 100644 --- a/jdk/test/java/net/URLPermission/URLTest.java +++ b/jdk/test/java/net/URLPermission/URLTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -27,6 +27,7 @@ import java.net.URLPermission; * * @test * @bug 8010464 + * @key intermittent * @library /lib/testlibrary/ * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm/java.security.policy=policy.1 URLTest one diff --git a/jdk/test/java/net/ipv6tests/TcpTest.java b/jdk/test/java/net/ipv6tests/TcpTest.java index 63008acddba..f538831506c 100644 --- a/jdk/test/java/net/ipv6tests/TcpTest.java +++ b/jdk/test/java/net/ipv6tests/TcpTest.java @@ -24,6 +24,7 @@ /* * @test * @bug 4868820 + * @key intermittent * @summary IPv6 support for Windows XP and 2003 server */ From 2610c1da55feb1fbafd49d0033c97d81446301dd Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 9 Mar 2016 11:15:04 +0100 Subject: [PATCH 267/311] 8151497: Set REQUIRED_OS_NAME and REQUIRED_OS_VERSION on AIX Reviewed-by: erikj --- common/autoconf/generated-configure.sh | 6 +++++- common/autoconf/platform.m4 | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 7a9d7900667..35744afa3fe 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4862,7 +4862,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1456136781 +DATE_WHEN_GENERATED=1457518447 ############################################################################### # @@ -15118,6 +15118,10 @@ $as_echo "$COMPILE_TYPE" >&6; } REQUIRED_OS_NAME=Darwin REQUIRED_OS_VERSION=11.2 fi + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + REQUIRED_OS_NAME=AIX + REQUIRED_OS_VERSION=7.1 + fi diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index 3b7e3e33e5d..7553dfe0323 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -406,6 +406,10 @@ AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES], REQUIRED_OS_NAME=Darwin REQUIRED_OS_VERSION=11.2 fi + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + REQUIRED_OS_NAME=AIX + REQUIRED_OS_VERSION=7.1 + fi AC_SUBST(REQUIRED_OS_NAME) AC_SUBST(REQUIRED_OS_VERSION) From a3aa84871979660affad8386f6e09a720699fda3 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Wed, 9 Mar 2016 12:11:31 +0000 Subject: [PATCH 268/311] 8151441: Completion result in httpclient Exchange.java lost Reviewed-by: chegar --- .../share/classes/java/net/http/Exchange.java | 28 ++--- .../java/net/httpclient/ShortRequestBody.java | 103 ++++++++++++++++++ 2 files changed, 117 insertions(+), 14 deletions(-) create mode 100644 jdk/test/java/net/httpclient/ShortRequestBody.java diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java index 597b4c0b6a1..9201d22160a 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java @@ -214,21 +214,21 @@ class Exchange { .sendHeadersAsync() .thenCompose((Void v) -> { // send body and get response at same time - exchImpl.sendBodyAsync(); - return exchImpl.getResponseAsync(null); + return exchImpl.sendBodyAsync() + .thenCompose(exchImpl::getResponseAsync); + }) + .thenCompose((HttpResponseImpl r1) -> { + int rcode = r1.statusCode(); + CompletableFuture cf = + checkForUpgradeAsync(r1, exchImpl); + if (cf != null) { + return cf; + } else { + Exchange.this.response = r1; + logResponse(r1); + return CompletableFuture.completedFuture(r1); + } }) - .thenCompose((HttpResponseImpl r1) -> { - int rcode = r1.statusCode(); - CompletableFuture cf = - checkForUpgradeAsync(r1, exchImpl); - if (cf != null) { - return cf; - } else { - Exchange.this.response = r1; - logResponse(r1); - return CompletableFuture.completedFuture(r1); - } - }) .thenApply((HttpResponseImpl response) -> { this.response = response; logResponse(response); diff --git a/jdk/test/java/net/httpclient/ShortRequestBody.java b/jdk/test/java/net/httpclient/ShortRequestBody.java new file mode 100644 index 00000000000..12a0b6dca51 --- /dev/null +++ b/jdk/test/java/net/httpclient/ShortRequestBody.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, 2016, 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 java.net.http.*; +import java.net.*; +import java.util.concurrent.*; +import java.nio.ByteBuffer; +import java.util.function.LongConsumer; + +/** + * @test + * @bug 8151441 + * @run main/othervm/timeout=10 ShortRequestBody + */ + +/** + * Exception was not being thrown + */ +public class ShortRequestBody { + + static Server server; + static String reqbody = "Hello world"; + + static String response = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n\r\n"; + + static class RequestBody implements HttpRequest.BodyProcessor { + public long onRequestStart(HttpRequest hr, LongConsumer flowController) { + return reqbody.length() + 1; // wrong! + } + + public boolean onRequestBodyChunk(ByteBuffer buf) throws IOException { + byte[] b = reqbody.getBytes(); + buf.put(b); + return true; + } + } + + static void close(Closeable c) { + try { + if (c == null) + return; + c.close(); + } catch (IOException e) {} + } + + public static void main(String[] args) throws Exception { + ServerSocket server = new ServerSocket(0); + int port = server.getLocalPort(); + URI uri = new URI("http://127.0.0.1:" + port + "/"); + + HttpRequest request; + HttpResponse r; + Socket s = null; + CompletableFuture cf1; + try { + cf1 = HttpRequest.create(uri) + .body(new RequestBody()) + .GET() + .responseAsync(); + + s = server.accept(); + s.getInputStream().readAllBytes(); + try (OutputStream os = s.getOutputStream()) { + os.write(response.getBytes()); + } catch (IOException ee) { + } + + try { + r = cf1.get(3, TimeUnit.SECONDS); + throw new RuntimeException("Failed"); + } catch (TimeoutException e0) { + throw new RuntimeException("Failed timeout"); + } catch (ExecutionException e) { + System.err.println("OK"); + } + } finally { + HttpClient.getDefault().executorService().shutdownNow(); + close(s); + close(server); + } + } +} From e53b5a35bec5e9b45d821885c86f15a827c77eb0 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Wed, 9 Mar 2016 13:24:01 +0100 Subject: [PATCH 269/311] 8151291: $EXEC yields "unknown command" on Cygwin Reviewed-by: jlaskey, hannesw, sdama --- nashorn/.hgignore | 1 + .../jdk/nashorn/internal/objects/Global.java | 9 +-- .../internal/runtime/CommandExecutor.java | 54 +++++++++++++-- .../internal/runtime/ScriptingFunctions.java | 2 +- nashorn/test/script/nosecurity/JDK-8151291.js | 68 +++++++++++++++++++ 5 files changed, 120 insertions(+), 14 deletions(-) create mode 100644 nashorn/test/script/nosecurity/JDK-8151291.js diff --git a/nashorn/.hgignore b/nashorn/.hgignore index cba852416c5..92acdd9d019 100644 --- a/nashorn/.hgignore +++ b/nashorn/.hgignore @@ -28,3 +28,4 @@ test/script/external/* .project .externalToolBuilders/* .settings/* +NashornProfile.txt diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java index db042890cd7..adfb15ba20a 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java @@ -2724,12 +2724,9 @@ public final class Global extends Scope { // Retrieve current state of ENV variables. env.putAll(System.getenv(), scriptEnv._strict); - // Some platforms, e.g., Windows, do not define the PWD environment - // variable, so that the $ENV.PWD property needs to be explicitly - // set. - if (!env.containsKey(ScriptingFunctions.PWD_NAME)) { - env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); - } + // Set the PWD variable to a value that is guaranteed to be understood + // by the underlying platform. + env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); } addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java index d8115bc4324..1126e507caf 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java @@ -64,6 +64,9 @@ class CommandExecutor { return System.getProperty("os.name").contains("Windows"); }); + // Cygwin drive alias prefix. + private static final String CYGDRIVE = "/cygdrive/"; + // User's home directory private static final String HOME_DIRECTORY = AccessController.doPrivileged((PrivilegedAction)() -> { @@ -388,7 +391,7 @@ class CommandExecutor { * @return resolved Path to file */ private static Path resolvePath(final String cwd, final String fileName) { - return Paths.get(cwd).resolve(fileName).normalize(); + return Paths.get(sanitizePath(cwd)).resolve(fileName).normalize(); } /** @@ -402,7 +405,8 @@ class CommandExecutor { switch (cmd.get(0)) { // Set current working directory. case "cd": - // If zero args then use home dirrectory as cwd else use first arg. + final boolean cygpath = IS_WINDOWS && cwd.startsWith(CYGDRIVE); + // If zero args then use home directory as cwd else use first arg. final String newCWD = cmd.size() < 2 ? HOME_DIRECTORY : cmd.get(1); // Normalize the cwd final Path cwdPath = resolvePath(cwd, newCWD); @@ -418,7 +422,13 @@ class CommandExecutor { } // Set PWD environment variable to be picked up as cwd. - environment.put("PWD", cwdPath.toString()); + // Make sure Cygwin paths look like Unix paths. + String scwd = cwdPath.toString(); + if (cygpath && scwd.length() >= 2 && + Character.isLetter(scwd.charAt(0)) && scwd.charAt(1) == ':') { + scwd = CYGDRIVE + Character.toLowerCase(scwd.charAt(0)) + "/" + scwd.substring(2); + } + environment.put("PWD", scwd); return true; // Set an environment variable. @@ -445,7 +455,8 @@ class CommandExecutor { } /** - * preprocessCommand - scan the command for redirects + * preprocessCommand - scan the command for redirects, and sanitize the + * executable path * @param tokens command tokens * @param cwd current working directory * @param redirectInfo redirection information @@ -471,9 +482,38 @@ class CommandExecutor { command.add(stripQuotes(token)); } + if (command.size() > 0) { + command.set(0, sanitizePath(command.get(0))); + } + return command; } + /** + * Sanitize a path in case the underlying platform is Cygwin. In that case, + * convert from the {@code /cygdrive/x} drive specification to the usual + * Windows {@code X:} format. + * + * @param d a String representing a path + * @return a String representing the same path in a form that can be + * processed by the underlying platform + */ + private static String sanitizePath(final String d) { + if (!IS_WINDOWS || (IS_WINDOWS && !d.startsWith(CYGDRIVE))) { + return d; + } + final String pd = d.substring(CYGDRIVE.length()); + if (pd.length() >= 2 && pd.charAt(1) == '/') { + // drive letter plus / -> convert /cygdrive/x/... to X:/... + return pd.charAt(0) + ":" + pd.substring(1); + } else if (pd.length() == 1) { + // just drive letter -> convert /cygdrive/x to X: + return pd.charAt(0) + ":"; + } + // remaining case: /cygdrive/ -> can't convert + return d; + } + /** * createProcessBuilder - create a ProcessBuilder for the command. * @param command command tokens @@ -485,7 +525,7 @@ class CommandExecutor { // Create new ProcessBuilder. final ProcessBuilder pb = new ProcessBuilder(command); // Set current working directory. - pb.directory(new File(cwd)); + pb.directory(new File(sanitizePath(cwd))); // Map environment variables. final Map processEnvironment = pb.environment(); @@ -523,7 +563,7 @@ class CommandExecutor { // Create ProcessBuilder with cwd and redirects set. createProcessBuilder(command, cwd, redirectInfo); - // If piped the wait for the next command. + // If piped, wait for the next command. if (isPiped) { return; } @@ -765,7 +805,7 @@ class CommandExecutor { /** * process - process a command array of strings - * @param script command script to be processed + * @param tokens command script to be processed */ void process(final List tokens) { // Prepare to accumulate command tokens. diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java index 5c312cc6040..42f17522656 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java @@ -72,7 +72,7 @@ public final class ScriptingFunctions { public static final String EXIT_NAME = "$EXIT"; /** Names of special properties used by $ENV API. */ - public static final String ENV_NAME = "$ENV"; + public static final String ENV_NAME = "$ENV"; /** Name of the environment variable for the current working directory. */ public static final String PWD_NAME = "PWD"; diff --git a/nashorn/test/script/nosecurity/JDK-8151291.js b/nashorn/test/script/nosecurity/JDK-8151291.js new file mode 100644 index 00000000000..9357b71543c --- /dev/null +++ b/nashorn/test/script/nosecurity/JDK-8151291.js @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, 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 $EXEC and $ENV.PWD handling across platforms. + * There must be a java executable in the PATH. + * + * @test + * @option -scripting + * @run + */ + +$EXEC(["java", "-version"]) +if ($EXIT != 0) { + throw 'java executable problem: ' + $ERR +} + +function eq(p, q, e) { + if (p != q) { + throw e + } +} + +function neq(p, q, e) { + if (p == q) { + throw e + } +} + +var File = Java.type("java.io.File"), + System = Java.type("java.lang.System"), + win = System.getProperty("os.name").startsWith("Windows"), + sep = File.separator, + startwd = $ENV.PWD, + upwd = startwd.substring(0, startwd.lastIndexOf(sep)) + +$EXEC("ls") +var ls_startwd = $OUT +$EXEC("cd ..; ls") +var ls_cdupwd = $OUT +eq($ENV.PWD, startwd, 'PWD changed during $EXEC cd') +neq(ls_startwd, ls_cdupwd, 'same ls result for startwd and upwd') + +$ENV.PWD = upwd +eq($ENV.PWD, upwd, '$ENV.PWD change had no effect') +$EXEC("ls") +var ls_epupwd = $OUT +eq(ls_cdupwd, ls_epupwd, 'different results for upwd') From b9616807fc1b2a8c79d70c9ea6fd96dbc8b89032 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Wed, 9 Mar 2016 13:37:30 +0000 Subject: [PATCH 270/311] 8151299: Http client SelectorManager overwriting read and write events Reviewed-by: chegar --- .../classes/java/net/http/HttpClientImpl.java | 130 +++++++---- .../net/httpclient/whitebox/TEST.properties | 3 + .../whitebox/java/net/http/SelectorTest.java | 208 ++++++++++++++++++ 3 files changed, 300 insertions(+), 41 deletions(-) create mode 100644 jdk/test/java/net/httpclient/whitebox/TEST.properties create mode 100644 jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java index e7e53bd6346..fd1ab0b012d 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java @@ -30,19 +30,17 @@ import java.net.ProxySelector; import java.net.URI; import static java.net.http.Utils.BUFSIZE; import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import static java.nio.channels.SelectionKey.OP_CONNECT; import static java.nio.channels.SelectionKey.OP_READ; import static java.nio.channels.SelectionKey.OP_WRITE; import java.nio.channels.Selector; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.stream.Stream; import java.util.concurrent.ExecutorService; import java.security.NoSuchAlgorithmException; -import java.util.ListIterator; -import java.util.Optional; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import javax.net.ssl.SSLContext; @@ -72,12 +70,6 @@ class HttpClientImpl extends HttpClient implements BufferHandler { private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); private final LinkedList timeouts; - //@Override - void debugPrint() { - selmgr.debugPrint(); - client2.debugPrint(); - } - public static HttpClientImpl create(HttpClientBuilderImpl builder) { HttpClientImpl impl = new HttpClientImpl(builder); impl.start(); @@ -173,19 +165,15 @@ class HttpClientImpl extends HttpClient implements BufferHandler { // Main loop for this client's selector class SelectorManager extends Thread { - final Selector selector; boolean closed; final List readyList; final List registrations; - List debugList; - SelectorManager() throws IOException { readyList = new LinkedList<>(); registrations = new LinkedList<>(); - debugList = new LinkedList<>(); selector = Selector.open(); } @@ -216,13 +204,6 @@ class HttpClientImpl extends HttpClient implements BufferHandler { return c; } - synchronized void debugPrint() { - System.err.println("Selecting on:"); - for (AsyncEvent e : debugList) { - System.err.println(opvals(e.interestOps())); - } - } - String opvals(int i) { StringBuilder sb = new StringBuilder(); if ((i & OP_READ) != 0) @@ -239,14 +220,18 @@ class HttpClientImpl extends HttpClient implements BufferHandler { try { while (true) { synchronized (this) { - debugList = copy(registrations); for (AsyncEvent exchange : registrations) { SelectableChannel c = exchange.channel(); try { c.configureBlocking(false); - c.register(selector, - exchange.interestOps(), - exchange); + SelectionKey key = c.keyFor(selector); + SelectorAttachment sa; + if (key == null) { + sa = new SelectorAttachment(c, selector); + } else { + sa = (SelectorAttachment)key.attachment(); + } + sa.register(exchange); } catch (IOException e) { Log.logError("HttpClientImpl: " + e); c.close(); @@ -266,11 +251,10 @@ class HttpClientImpl extends HttpClient implements BufferHandler { Set keys = selector.selectedKeys(); for (SelectionKey key : keys) { - if (key.isReadable() || key.isConnectable() || key.isWritable()) { - key.cancel(); - AsyncEvent exchange = (AsyncEvent) key.attachment(); - readyList.add(exchange); - } + SelectorAttachment sa = (SelectorAttachment)key.attachment(); + int eventsOccurred = key.readyOps(); + sa.events(eventsOccurred).forEach(readyList::add); + sa.resetInterestOps(eventsOccurred); } selector.selectNow(); // complete cancellation selector.selectedKeys().clear(); @@ -305,6 +289,80 @@ class HttpClientImpl extends HttpClient implements BufferHandler { } } + /** + * Tracks multiple user level registrations associated with one NIO + * registration (SelectionKey). In this implementation, registrations + * are one-off and when an event is posted the registration is cancelled + * until explicitly registered again. + * + *

          No external synchronization required as this class is only used + * by the SelectorManager thread. One of these objects required per + * connection. + */ + private static class SelectorAttachment { + private final SelectableChannel chan; + private final Selector selector; + private final ArrayList pending; + private int interestops; + + SelectorAttachment(SelectableChannel chan, Selector selector) { + this.pending = new ArrayList<>(); + this.chan = chan; + this.selector = selector; + } + + void register(AsyncEvent e) throws ClosedChannelException { + int newops = e.interestOps(); + boolean reRegister = (interestops & newops) != newops; + interestops |= newops; + pending.add(e); + if (reRegister) { + // first time registration happens here also + chan.register(selector, interestops, this); + } + } + + int interestOps() { + return interestops; + } + + /** + * Returns a Stream containing only events that are + * registered with the given {@code interestop}. + */ + Stream events(int interestop) { + return pending.stream() + .filter(ev -> (ev.interestOps() & interestop) != 0); + } + + /** + * Removes any events with the given {@code interestop}, and if no + * events remaining, cancels the associated SelectionKey. + */ + void resetInterestOps(int interestop) { + int newops = 0; + + Iterator itr = pending.iterator(); + while (itr.hasNext()) { + AsyncEvent event = itr.next(); + int evops = event.interestOps(); + if ((evops & interestop) != 0) { + itr.remove(); + } else { + newops |= evops; + } + } + + interestops = newops; + SelectionKey key = chan.keyFor(selector); + if (newops == 0) { + key.cancel(); + } else { + key.interestOps(newops); + } + } + } + /** * Creates a HttpRequest associated with this group. * @@ -425,18 +483,9 @@ class HttpClientImpl extends HttpClient implements BufferHandler { } } iter.add(event); - //debugPrintList("register"); selmgr.wakeupSelector(); } - void debugPrintList(String s) { - System.err.printf("%s: {", s); - for (TimeoutEvent e : timeouts) { - System.err.printf("(%d,%d) ", e.delta, e.timeval); - } - System.err.println("}"); - } - synchronized void signalTimeouts(long then) { if (timeouts.isEmpty()) { return; @@ -462,7 +511,6 @@ class HttpClientImpl extends HttpClient implements BufferHandler { break; } } - //debugPrintList("signalTimeouts"); } synchronized void cancelTimer(TimeoutEvent event) { diff --git a/jdk/test/java/net/httpclient/whitebox/TEST.properties b/jdk/test/java/net/httpclient/whitebox/TEST.properties new file mode 100644 index 00000000000..1d784754199 --- /dev/null +++ b/jdk/test/java/net/httpclient/whitebox/TEST.properties @@ -0,0 +1,3 @@ +TestNG.dirs = . + +bootclasspath.dirs = /java/net/httpclient diff --git a/jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java b/jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java new file mode 100644 index 00000000000..74ef4ff2991 --- /dev/null +++ b/jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2015, 2016, 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 8151299 + * @summary Http client SelectorManager overwriting read and write events + */ +package java.net.http; + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.nio.ByteBuffer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +import static java.lang.System.out; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.util.concurrent.TimeUnit.SECONDS; + +import org.testng.annotations.Test; + +/** + * Whitebox test of selector mechanics. Currently only a simple test + * setting one read and one write event is done. It checks that the + * write event occurs first, followed by the read event and then no + * further events occur despite the conditions actually still existing. + */ +@Test +public class SelectorTest { + + AtomicInteger counter = new AtomicInteger(); + volatile boolean error; + static final CountDownLatch finishingGate = new CountDownLatch(1); + + String readSomeBytes(RawChannel chan) { + try { + ByteBuffer buf = ByteBuffer.allocate(1024); + int t = chan.read(buf); + if (t <= 0) { + out.printf("chan read returned %d\n", t); + return null; + } + byte[] bb = new byte[t]; + buf.get(bb); + return new String(bb, US_ASCII); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + } + + @Test(timeOut = 10000) + public void test() throws Exception { + + try (ServerSocket server = new ServerSocket(0)) { + int port = server.getLocalPort(); + + out.println("Listening on port " + server.getLocalPort()); + + TestServer t = new TestServer(server); + t.start(); + out.println("Started server thread"); + + final RawChannel chan = getARawChannel(port); + + chan.registerEvent(new RawChannel.NonBlockingEvent() { + @Override + public int interestOps() { + return SelectionKey.OP_READ; + } + + @Override + public void handle() { + readSomeBytes(chan); + out.printf("OP_READ\n"); + if (counter.get() != 1) { + out.printf("OP_READ error counter = %d\n", counter); + error = true; + } + } + }); + + chan.registerEvent(new RawChannel.NonBlockingEvent() { + @Override + public int interestOps() { + return SelectionKey.OP_WRITE; + } + + @Override + public void handle() { + out.printf("OP_WRITE\n"); + if (counter.get() != 0) { + out.printf("OP_WRITE error counter = %d\n", counter); + error = true; + } else { + ByteBuffer bb = ByteBuffer.wrap(TestServer.INPUT); + counter.incrementAndGet(); + try { + chan.write(bb); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + } + + }); + out.println("Events registered. Waiting"); + finishingGate.await(30, SECONDS); + if (error) + throw new RuntimeException("Error"); + else + out.println("No error"); + } + } + + static RawChannel getARawChannel(int port) throws Exception { + URI uri = URI.create("http://127.0.0.1:" + port + "/"); + out.println("client connecting to " + uri.toString()); + HttpRequest req = HttpRequest.create(uri).GET(); + HttpResponse r = req.response(); + r.body(HttpResponse.ignoreBody()); + return ((HttpResponseImpl) r).rawChannel(); + } + + static class TestServer extends Thread { + static final byte[] INPUT = "Hello world".getBytes(US_ASCII); + static final byte[] OUTPUT = "Goodbye world".getBytes(US_ASCII); + static final String FIRST_RESPONSE = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n\r\n"; + final ServerSocket server; + + TestServer(ServerSocket server) throws IOException { + this.server = server; + } + + public void run() { + try (Socket s = server.accept(); + InputStream is = s.getInputStream(); + OutputStream os = s.getOutputStream()) { + + out.println("Got connection"); + readRequest(is); + os.write(FIRST_RESPONSE.getBytes()); + read(is); + write(os); + Thread.sleep(1000); + // send some more data, and make sure WRITE op does not get called + write(os); + out.println("TestServer exiting"); + SelectorTest.finishingGate.countDown(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // consumes the HTTP request + static void readRequest(InputStream is) throws IOException { + out.println("starting readRequest"); + byte[] buf = new byte[1024]; + String s = ""; + while (true) { + int n = is.read(buf); + if (n <= 0) + throw new IOException("Error"); + s = s + new String(buf, 0, n); + if (s.indexOf("\r\n\r\n") != -1) + break; + } + out.println("returning from readRequest"); + } + + static void read(InputStream is) throws IOException { + out.println("starting read"); + for (int i = 0; i < INPUT.length; i++) { + int c = is.read(); + if (c == -1) + throw new IOException("closed"); + if (INPUT[i] != (byte) c) + throw new IOException("Error. Expected:" + INPUT[i] + ", got:" + c); + } + out.println("returning from read"); + } + + static void write(OutputStream os) throws IOException { + out.println("doing write"); + os.write(OUTPUT); + } + } +} From 3b675d58d4640eba80098c4ed977ff4ef21a9297 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Wed, 9 Mar 2016 15:15:29 +0100 Subject: [PATCH 271/311] 8151518: relax test requirements to reduce dependency on directory contents Reviewed-by: hannesw, sundar --- nashorn/test/script/nosecurity/JDK-8151291.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nashorn/test/script/nosecurity/JDK-8151291.js b/nashorn/test/script/nosecurity/JDK-8151291.js index 9357b71543c..15ae427913c 100644 --- a/nashorn/test/script/nosecurity/JDK-8151291.js +++ b/nashorn/test/script/nosecurity/JDK-8151291.js @@ -59,10 +59,10 @@ var ls_startwd = $OUT $EXEC("cd ..; ls") var ls_cdupwd = $OUT eq($ENV.PWD, startwd, 'PWD changed during $EXEC cd') -neq(ls_startwd, ls_cdupwd, 'same ls result for startwd and upwd') +neq(ls_startwd, ls_cdupwd, 'same ls result for startwd and upwd with $EXEC cd') $ENV.PWD = upwd eq($ENV.PWD, upwd, '$ENV.PWD change had no effect') $EXEC("ls") var ls_epupwd = $OUT -eq(ls_cdupwd, ls_epupwd, 'different results for upwd') +neq(ls_startwd, ls_epupwd, 'same ls result for startwd and upwd with $ENV.PWD cd') From a8987f1075fc5668dd90b08146ecfc1da7c3af00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Wed, 9 Mar 2016 15:45:44 +0100 Subject: [PATCH 272/311] 8151515: $EXEC output is truncated Reviewed-by: sundar, jlaskey --- .../internal/runtime/CommandExecutor.java | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java index 1126e507caf..dcebbbb3db8 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java @@ -249,18 +249,22 @@ class CommandExecutor { // Stream to copy to. private final OutputStream output; + private final Thread thread; + Piper(final InputStream input, final OutputStream output) { this.input = input; this.output = output; + this.thread = new Thread(this, "$EXEC Piper"); } /** * start - start the Piper in a new daemon thread + * @return this Piper */ - void start() { - Thread thread = new Thread(this, "$EXEC Piper"); + Piper start() { thread.setDaemon(true); thread.start(); + return this; } /** @@ -295,6 +299,10 @@ class CommandExecutor { } } + public void join() throws InterruptedException { + thread.join(); + } + // Exit thread. } @@ -621,15 +629,17 @@ class CommandExecutor { ByteArrayOutputStream byteOutputStream = null; ByteArrayOutputStream byteErrorStream = null; + final List piperThreads = new ArrayList<>(); + // If input is not redirected. if (inputIsPipe) { // If inputStream other than System.in is provided. if (inputStream != null) { // Pipe inputStream to first process output stream. - new Piper(inputStream, firstProcess.getOutputStream()).start(); + piperThreads.add(new Piper(inputStream, firstProcess.getOutputStream()).start()); } else { // Otherwise assume an input string has been provided. - new Piper(new ByteArrayInputStream(inputString.getBytes()), firstProcess.getOutputStream()).start(); + piperThreads.add(new Piper(new ByteArrayInputStream(inputString.getBytes()), firstProcess.getOutputStream()).start()); } } @@ -638,11 +648,11 @@ class CommandExecutor { // If outputStream other than System.out is provided. if (outputStream != null ) { // Pipe outputStream from last process input stream. - new Piper(lastProcess.getInputStream(), outputStream).start(); + piperThreads.add(new Piper(lastProcess.getInputStream(), outputStream).start()); } else { // Otherwise assume an output string needs to be prepared. byteOutputStream = new ByteArrayOutputStream(BUFFER_SIZE); - new Piper(lastProcess.getInputStream(), byteOutputStream).start(); + piperThreads.add(new Piper(lastProcess.getInputStream(), byteOutputStream).start()); } } @@ -650,11 +660,11 @@ class CommandExecutor { if (errorIsPipe) { // If errorStream other than System.err is provided. if (errorStream != null) { - new Piper(lastProcess.getErrorStream(), errorStream).start(); + piperThreads.add(new Piper(lastProcess.getErrorStream(), errorStream).start()); } else { // Otherwise assume an error string needs to be prepared. byteErrorStream = new ByteArrayOutputStream(BUFFER_SIZE); - new Piper(lastProcess.getErrorStream(), byteErrorStream).start(); + piperThreads.add(new Piper(lastProcess.getErrorStream(), byteErrorStream).start()); } } @@ -662,13 +672,13 @@ class CommandExecutor { for (int i = 0, n = processes.size() - 1; i < n; i++) { final Process prev = processes.get(i); final Process next = processes.get(i + 1); - new Piper(prev.getInputStream(), next.getOutputStream()).start(); + piperThreads.add(new Piper(prev.getInputStream(), next.getOutputStream()).start()); } // Wind up processes. try { // Get the user specified timeout. - long timeout = envVarLongValue("JJS_TIMEOUT"); + final long timeout = envVarLongValue("JJS_TIMEOUT"); // If user specified timeout (milliseconds.) if (timeout != 0) { @@ -683,6 +693,10 @@ class CommandExecutor { // Wait for last process and get exit code. exitCode = lastProcess.waitFor(); } + // Wait for all piper threads to terminate + for (final Piper piper : piperThreads) { + piper.join(); + } // Accumulate the output and error streams. outputString += byteOutputStream != null ? byteOutputStream.toString() : ""; From 020a27b202898b2c8ac2addf1149a1faf1657148 Mon Sep 17 00:00:00 2001 From: Peter Levart Date: Wed, 9 Mar 2016 21:17:06 +0100 Subject: [PATCH 273/311] 8149925: We don't need jdk.internal.ref.Cleaner any more - part1 1st part of removing legacy jdk.internal.ref.Cleaner Reviewed-by: chegar, mchung --- .../java/lang/invoke/MethodHandleNatives.java | 12 +++--- .../share/classes/java/lang/ref/Cleaner.java | 12 ++++-- .../jdk/internal/misc/InnocuousThread.java | 8 +++- .../classes/jdk/internal/ref/CleanerImpl.java | 41 ++++++++++++++----- .../classes/sun/nio/ch/IOVecWrapper.java | 4 +- .../share/classes/sun/nio/ch/Util.java | 1 - .../classes/sun/nio/fs/NativeBuffer.java | 12 +++--- .../classes/sun/nio/fs/NativeBuffers.java | 4 +- .../sun/nio/fs/WindowsWatchService.java | 2 +- 9 files changed, 64 insertions(+), 32 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index e9bb8046246..57ad668b903 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -30,7 +30,7 @@ import java.lang.reflect.Field; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; -import jdk.internal.ref.Cleaner; +import jdk.internal.ref.CleanerFactory; /** * The JVM interface for the method handles package is all here. @@ -68,10 +68,12 @@ class MethodHandleNatives { static CallSiteContext make(CallSite cs) { final CallSiteContext newContext = new CallSiteContext(); - // Cleaner is attached to CallSite instance and it clears native structures allocated for CallSite context. - // Though the CallSite can become unreachable, its Context is retained by the Cleaner instance (which is - // referenced from Cleaner class) until cleanup is performed. - Cleaner.create(cs, newContext); + // CallSite instance is tracked by a Cleanable which clears native + // structures allocated for CallSite context. Though the CallSite can + // become unreachable, its Context is retained by the Cleanable instance + // (which is referenced from Cleaner instance which is referenced from + // CleanerFactory class) until cleanup is performed. + CleanerFactory.cleaner().register(cs, newContext); return newContext; } diff --git a/jdk/src/java.base/share/classes/java/lang/ref/Cleaner.java b/jdk/src/java.base/share/classes/java/lang/ref/Cleaner.java index bee049ec8fe..63bd43c53c1 100644 --- a/jdk/src/java.base/share/classes/java/lang/ref/Cleaner.java +++ b/jdk/src/java.base/share/classes/java/lang/ref/Cleaner.java @@ -25,10 +25,11 @@ package java.lang.ref; +import jdk.internal.ref.CleanerImpl; + import java.util.Objects; import java.util.concurrent.ThreadFactory; - -import jdk.internal.ref.CleanerImpl; +import java.util.function.Function; /** * {@code Cleaner} manages a set of object references and corresponding cleaning actions. @@ -135,7 +136,12 @@ public final class Cleaner { final CleanerImpl impl; static { - CleanerImpl.setCleanerImplAccess((Cleaner c) -> c.impl); + CleanerImpl.setCleanerImplAccess(new Function() { + @Override + public CleanerImpl apply(Cleaner cleaner) { + return cleaner.impl; + } + }); } /** diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java b/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java index 8c5b8833834..0891f2a125f 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java @@ -128,8 +128,12 @@ public final class InnocuousThread extends Thread { } final ThreadGroup root = group; INNOCUOUSTHREADGROUP = AccessController.doPrivileged( - (PrivilegedAction) () -> - { return new ThreadGroup(root, "InnocuousThreadGroup"); }); + new PrivilegedAction() { + @Override + public ThreadGroup run() { + return new ThreadGroup(root, "InnocuousThreadGroup"); + } + }); } catch (Exception e) { throw new Error(e); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java b/jdk/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java index 6d99648eac2..787382326f7 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java +++ b/jdk/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java @@ -31,6 +31,7 @@ import java.lang.ref.ReferenceQueue; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import jdk.internal.misc.InnocuousThread; @@ -39,7 +40,7 @@ import jdk.internal.misc.InnocuousThread; * CleanerImpl manages a set of object references and corresponding cleaning actions. * CleanerImpl provides the functionality of {@link java.lang.ref.Cleaner}. */ -public final class CleanerImpl { +public final class CleanerImpl implements Runnable { /** * An object to access the CleanerImpl from a Cleaner; set by Cleaner init. @@ -103,7 +104,7 @@ public final class CleanerImpl { } // schedule a nop cleaning action for the cleaner, so the associated thread // will continue to run at least until the cleaner is reclaimable. - new PhantomCleanableRef(cleaner, cleaner, () -> {}); + new CleanerCleanable(cleaner); if (threadFactory == null) { threadFactory = CleanerImpl.InnocuousThreadFactory.factory(); @@ -112,7 +113,7 @@ public final class CleanerImpl { // now that there's at least one cleaning action, for the cleaner, // we can start the associated thread, which runs until // all cleaning actions have been run. - Thread thread = threadFactory.newThread(this::run); + Thread thread = threadFactory.newThread(this); thread.setDaemon(true); thread.start(); } @@ -128,7 +129,8 @@ public final class CleanerImpl { * If the thread is a ManagedLocalsThread, the threadlocals * are erased before each cleanup */ - private void run() { + @Override + public void run() { Thread t = Thread.currentThread(); InnocuousThread mlThread = (t instanceof InnocuousThread) ? (InnocuousThread) t @@ -147,10 +149,9 @@ public final class CleanerImpl { if (ref != null) { ref.clean(); } - } catch (InterruptedException i) { - continue; // ignore the interruption } catch (Throwable e) { // ignore exceptions from the cleanup action + // (including interruption of cleanup thread) } } } @@ -320,14 +321,32 @@ public final class CleanerImpl { return factory; } + final AtomicInteger cleanerThreadNumber = new AtomicInteger(); + public Thread newThread(Runnable r) { - return AccessController.doPrivileged((PrivilegedAction) () -> { - Thread t = new InnocuousThread(r); - t.setPriority(Thread.MAX_PRIORITY - 2); - t.setName("Cleaner-" + t.getId()); - return t; + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Thread run() { + Thread t = new InnocuousThread(r); + t.setPriority(Thread.MAX_PRIORITY - 2); + t.setName("Cleaner-" + cleanerThreadNumber.getAndIncrement()); + return t; + } }); } } + /** + * A PhantomCleanable implementation for tracking the Cleaner itself. + */ + static final class CleanerCleanable extends PhantomCleanable { + CleanerCleanable(Cleaner cleaner) { + super(cleaner, cleaner); + } + + @Override + protected void performCleanup() { + // no action + } + } } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java b/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java index d2c03a34fea..3c43c5a6777 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java @@ -26,7 +26,7 @@ package sun.nio.ch; import java.nio.ByteBuffer; -import jdk.internal.ref.Cleaner; +import jdk.internal.ref.CleanerFactory; /** @@ -101,7 +101,7 @@ class IOVecWrapper { } if (wrapper == null) { wrapper = new IOVecWrapper(size); - Cleaner.create(wrapper, new Deallocator(wrapper.vecArray)); + CleanerFactory.cleaner().register(wrapper, new Deallocator(wrapper.vecArray)); cached.set(wrapper); } return wrapper; diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java index a580b82c4d0..af89eca4544 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java @@ -33,7 +33,6 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import jdk.internal.misc.Unsafe; -import jdk.internal.ref.Cleaner; import sun.security.action.GetPropertyAction; diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java index 91efac348e8..7daf8ccfe16 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java @@ -26,7 +26,9 @@ package sun.nio.fs; import jdk.internal.misc.Unsafe; -import jdk.internal.ref.Cleaner; +import jdk.internal.ref.CleanerFactory; + +import java.lang.ref.Cleaner; /** * A light-weight buffer in native memory. @@ -37,7 +39,7 @@ class NativeBuffer { private final long address; private final int size; - private final Cleaner cleaner; + private final Cleaner.Cleanable cleanable; // optional "owner" to avoid copying // (only safe for use by thread-local caches) @@ -56,7 +58,7 @@ class NativeBuffer { NativeBuffer(int size) { this.address = unsafe.allocateMemory(size); this.size = size; - this.cleaner = Cleaner.create(this, new Deallocator(address)); + this.cleanable = CleanerFactory.cleaner().register(this, new Deallocator(address)); } void release() { @@ -71,8 +73,8 @@ class NativeBuffer { return size; } - Cleaner cleaner() { - return cleaner; + void free() { + cleanable.clean(); } // not synchronized; only safe for use by thread-local caches diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java index 728d96eb2b3..4f0aa5c9071 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java @@ -107,14 +107,14 @@ class NativeBuffers { for (int i=0; i Date: Wed, 9 Mar 2016 21:19:13 +0100 Subject: [PATCH 274/311] 8073793: serviceability/dcmd/compiler/CodelistTest.java fails with ClassNotFoundException trying to load VM anonymous class Make test less fragile using whitebox API Reviewed-by: kvn --- .../dcmd/compiler/CodelistTest.java | 159 ++++++++++++------ 1 file changed, 108 insertions(+), 51 deletions(-) diff --git a/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java b/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java index 0201e2ceeec..d5360de229d 100644 --- a/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java +++ b/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java @@ -24,26 +24,39 @@ /* * @test CodelistTest * @bug 8054889 - * @library /testlibrary + * @library /testlibrary /test/lib / * @modules java.base/sun.misc * java.compiler * java.management * jdk.jvmstat/sun.jvmstat.monitor * @build jdk.test.lib.* - * @build jdk.test.lib.dcmd.* - * @build MethodIdentifierParser - * @run testng CodelistTest + * jdk.test.lib.dcmd.* + * sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -Xmixed CodelistTest + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -Xint CodelistTest * @summary Test of diagnostic command Compiler.codelist + * + * Flag comment: + * -XX:-UseCodeCacheFlushing - to prevent methods from being removed from the code cache before we have checked the results + * + * This test should never run in the same VM as other tests - the code cache may get huge which will + * create an enormous amount of output to parse. Same for -Xcomp. */ -import org.testng.annotations.Test; -import org.testng.Assert; - +import compiler.testlibrary.CompilerUtils; +import compiler.whitebox.CompilerWhiteBoxTest; import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.dcmd.CommandExecutor; import jdk.test.lib.dcmd.JMXExecutor; +import org.testng.annotations.Test; +import org.testng.Assert; +import sun.hotspot.WhiteBox; import java.lang.reflect.Method; +import java.util.Iterator; public class CodelistTest { @@ -62,58 +75,68 @@ public class CodelistTest { * */ + protected static final WhiteBox WB = WhiteBox.getWhiteBox(); + public void run(CommandExecutor executor) { - int ok = 0; - int fail = 0; + + TestCase[] testcases = { + new TestCase(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE, "testcaseMethod1"), + new TestCase(CompilerWhiteBoxTest.COMP_LEVEL_LIMITED_PROFILE, "testcaseMethod2"), + new TestCase(CompilerWhiteBoxTest.COMP_LEVEL_FULL_PROFILE, "testcaseMethod3"), + new TestCase(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "testcaseMethod4"), + }; + + String directive = "{ match: \"CodelistTest.testcaseMethod*\", " + + "BackgroundCompilation: false }"; + Assert.assertTrue( + WB.addCompilerDirective(directive) == 1, + "Must succeed"); + + try { + // Enqueue one test method for each available level + int[] complevels = CompilerUtils.getAvailableCompilationLevels(); + for (int level : complevels) { + // Only test comp level 1 and 4 - level 1, 2 and 3 may interfere with each other + if (level == 1 || level == 4) { + TestCase testcase = testcases[level - 1]; + WB.enqueueMethodForCompilation(testcase.method, testcase.level); + // Set results to false for those methods we must to find + // We will also assert if we find any test method we don't expect + testcase.check = false; + } + } + } finally { + WB.removeCompilerDirective(1); + } // Get output from dcmd (diagnostic command) OutputAnalyzer output = executor.execute("Compiler.codelist"); + Iterator lines = output.asLines().iterator(); - // Grab a method name from the output - int count = 0; + // Loop over output set result for all found methods + while (lines.hasNext()) { + String line = lines.next(); - for (String line : output.asLines()) { - count++; + // Fast check for common part of method name + if (line.contains("CodelistTest.testcaseMethod")) { + String[] parts = line.split(" "); + int compileID = Integer.parseInt(parts[0]); + int compileLevel = Integer.parseInt(parts[1]); + String str = parts[2]; - String[] parts = line.split(" "); - // int compileID = Integer.parseInt(parts[0]); - // int compileLevel = Integer.parseInt(parts[1]); - String methodPrintedInLogFormat = parts[2]; + for (TestCase testcase : testcases) { + if (str.contains(testcase.methodName)) { + Assert.assertFalse(testcase.check, "Must not be found or already found."); + Assert.assertTrue(testcase.level == compileLevel, "Must have correct level"); + testcase.check = true; + } + } + } + } - // skip inits, clinits, methodHandles and getUnsafe - - // they can not be reflected - if (methodPrintedInLogFormat.contains("")) { - continue; - } - if (methodPrintedInLogFormat.contains("")) { - continue; - } - if (methodPrintedInLogFormat.contains("MethodHandle")) { - continue; - } - if (methodPrintedInLogFormat.contains("sun.misc.Unsafe.getUnsafe")) { - continue; - } - if (methodPrintedInLogFormat.contains("jdk.internal.misc.Unsafe.getUnsafe")) { - continue; - } - - MethodIdentifierParser mf = new MethodIdentifierParser(methodPrintedInLogFormat); - Method m = null; - try { - m = mf.getMethod(); - } catch (NoSuchMethodException e) { - m = null; - } catch (ClassNotFoundException e) { - Assert.fail("Test error: Caught unexpected exception", e); - } - if (m == null) { - Assert.fail("Test failed on: " + methodPrintedInLogFormat); - } - if (count > 10) { - // Testing 10 entries is enough. Lets not waste time. - break; - } + // Check all testcases that was run + for (TestCase testcase : testcases) { + Assert.assertTrue(testcase.check, "Missing testcase " + testcase.methodName); } } @@ -121,4 +144,38 @@ public class CodelistTest { public void jmx() { run(new JMXExecutor()); } + + public void testcaseMethod1() { + } + + public void testcaseMethod2() { + } + + public void testcaseMethod3() { + } + + public void testcaseMethod4() { + } + + public static Method getMethod(Class klass, String name, Class... parameterTypes) { + try { + return klass.getDeclaredMethod(name, parameterTypes); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException("exception on getting method Helper." + name, e); + } + } + + class TestCase { + Method method; + int level; + String methodName; + Boolean check; + + public TestCase(int level, String methodName) { + this.method = getMethod(CodelistTest.class, methodName); + this.level = level; + this.methodName = methodName; + this.check = true; + } + } } From b01a1a42e3c6b690152c89cb12278023fad023e5 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Wed, 9 Mar 2016 21:20:43 +0100 Subject: [PATCH 275/311] 8066770: EnqueueMethodForCompilationTest.java fails to compile method Make compiles blocking and always check queue Reviewed-by: kvn --- .../compiler/whitebox/ClearMethodStateTest.java | 16 ++++++++++++++-- .../compiler/whitebox/CompilerWhiteBoxTest.java | 6 +++--- .../EnqueueMethodForCompilationTest.java | 14 ++++++++++++-- .../compiler/whitebox/LockCompilationTest.java | 7 +++++-- .../whitebox/MakeMethodNotCompilableTest.java | 14 ++++++++++++-- 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/hotspot/test/compiler/whitebox/ClearMethodStateTest.java b/hotspot/test/compiler/whitebox/ClearMethodStateTest.java index 2b93fad4bba..dfc630155fe 100644 --- a/hotspot/test/compiler/whitebox/ClearMethodStateTest.java +++ b/hotspot/test/compiler/whitebox/ClearMethodStateTest.java @@ -22,6 +22,7 @@ */ import java.util.function.Function; + import compiler.whitebox.CompilerWhiteBoxTest; /* @@ -32,14 +33,24 @@ import compiler.whitebox.CompilerWhiteBoxTest; * @build ClearMethodStateTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,compiler.whitebox.SimpleTestCase$Helper::* ClearMethodStateTest + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ClearMethodStateTest * @summary testing of WB::clearMethodState() * @author igor.ignatyev@oracle.com */ public class ClearMethodStateTest extends CompilerWhiteBoxTest { public static void main(String[] args) throws Exception { - CompilerWhiteBoxTest.main(ClearMethodStateTest::new, args); + String directive = + "[{ match:\"*SimpleTestCase$Helper.*\", BackgroundCompilation: false }, " + + " { match:\"*.*\", inline:\"-*SimpleTestCase$Helper.*\"}]"; + if (WHITE_BOX.addCompilerDirective(directive) != 2) { + throw new RuntimeException("Could not add directive"); + } + try { + CompilerWhiteBoxTest.main(ClearMethodStateTest::new, args); + } finally { + WHITE_BOX.removeCompilerDirective(2); + } } private ClearMethodStateTest(TestCase testCase) { @@ -58,6 +69,7 @@ public class ClearMethodStateTest extends CompilerWhiteBoxTest { */ @Override protected void test() throws Exception { + checkNotCompiled(); compile(); WHITE_BOX.clearMethodState(method); diff --git a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java index 269113074e4..5bec2eabd84 100644 --- a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java +++ b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java @@ -213,6 +213,7 @@ public abstract class CompilerWhiteBoxTest { * compilation level. */ protected final void checkNotCompiled() { + waitBackgroundCompilation(); checkNotCompiled(true); checkNotCompiled(false); } @@ -226,7 +227,6 @@ public abstract class CompilerWhiteBoxTest { * compilation level. */ protected final void checkNotCompiled(boolean isOsr) { - waitBackgroundCompilation(); if (WHITE_BOX.isMethodQueuedForCompilation(method)) { throw new RuntimeException(method + " must not be in queue"); } @@ -315,11 +315,11 @@ public abstract class CompilerWhiteBoxTest { return; } final Object obj = new Object(); - for (int i = 0; i < 10 + for (int i = 0; i < 100 && WHITE_BOX.isMethodQueuedForCompilation(executable); ++i) { synchronized (obj) { try { - obj.wait(1000); + obj.wait(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } diff --git a/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java b/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java index cec51a811bc..cde67e20f60 100644 --- a/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java +++ b/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java @@ -31,14 +31,24 @@ import compiler.whitebox.CompilerWhiteBoxTest; * @build EnqueueMethodForCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=600 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,compiler.whitebox.SimpleTestCase$Helper::* EnqueueMethodForCompilationTest + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI EnqueueMethodForCompilationTest * @summary testing of WB::enqueueMethodForCompilation() * @author igor.ignatyev@oracle.com */ public class EnqueueMethodForCompilationTest extends CompilerWhiteBoxTest { public static void main(String[] args) throws Exception { - CompilerWhiteBoxTest.main(EnqueueMethodForCompilationTest::new, args); + String directive = + "[{ match:\"*SimpleTestCase$Helper.*\", BackgroundCompilation: false }, " + + " { match:\"*.*\", inline:\"-*SimpleTestCase$Helper.*\"}]"; + if (WHITE_BOX.addCompilerDirective(directive) != 2) { + throw new RuntimeException("Could not add directive"); + } + try { + CompilerWhiteBoxTest.main(EnqueueMethodForCompilationTest::new, args); + } finally { + WHITE_BOX.removeCompilerDirective(2); + } } private EnqueueMethodForCompilationTest(TestCase testCase) { diff --git a/hotspot/test/compiler/whitebox/LockCompilationTest.java b/hotspot/test/compiler/whitebox/LockCompilationTest.java index 2dd5275dc5e..3efe08edf8f 100644 --- a/hotspot/test/compiler/whitebox/LockCompilationTest.java +++ b/hotspot/test/compiler/whitebox/LockCompilationTest.java @@ -29,7 +29,7 @@ * @build LockCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=600 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,compiler.whitebox.SimpleTestCase$Helper::* LockCompilationTest + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI LockCompilationTest * @summary testing of WB::lock/unlockCompilation() */ @@ -37,12 +37,15 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; + import compiler.whitebox.CompilerWhiteBoxTest; import jdk.test.lib.Asserts; public class LockCompilationTest extends CompilerWhiteBoxTest { public static void main(String[] args) throws Exception { - CompilerWhiteBoxTest.main(LockCompilationTest::new, args); + // This case waits for 10 seconds and verifies that the method hasn't been + // compiled during that time. Only do that for one of the test cases. + CompilerWhiteBoxTest.main(LockCompilationTest::new, new String[] {"METHOD_TEST"}); } private LockCompilationTest(TestCase testCase) { diff --git a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java index 82b568a30c6..1e86bfb5594 100644 --- a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java +++ b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java @@ -31,14 +31,24 @@ import compiler.whitebox.CompilerWhiteBoxTest; * @build MakeMethodNotCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,compiler.whitebox.SimpleTestCase$Helper::* MakeMethodNotCompilableTest + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmixed MakeMethodNotCompilableTest * @summary testing of WB::makeMethodNotCompilable() * @author igor.ignatyev@oracle.com */ public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest { private int bci; public static void main(String[] args) throws Exception { - CompilerWhiteBoxTest.main(MakeMethodNotCompilableTest::new, args); + String directive = + "[{ match:\"*SimpleTestCase$Helper.*\", BackgroundCompilation: false }, " + + " { match:\"*.*\", inline:\"-*SimpleTestCase$Helper.*\"}]"; + if (WHITE_BOX.addCompilerDirective(directive) != 2) { + throw new RuntimeException("Could not add directive"); + } + try { + CompilerWhiteBoxTest.main(MakeMethodNotCompilableTest::new, args); + } finally { + WHITE_BOX.removeCompilerDirective(2); + } } private MakeMethodNotCompilableTest(TestCase testCase) { From 7b2839f9ee66f24f1c4415cc82dcc43a8ad52160 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Wed, 9 Mar 2016 16:09:55 -0800 Subject: [PATCH 276/311] 8150704: XALAN: ERROR: 'No more DTM IDs are available' when transforming with lots of temporary result trees Reviewed-by: joehw --- .../org/apache/xalan/internal/xsltc/DOM.java | 6 +- .../xsltc/compiler/ApplyTemplates.java | 20 +- .../internal/xsltc/compiler/CallTemplate.java | 37 +- .../xalan/internal/xsltc/compiler/Sort.java | 60 +- .../xsltc/compiler/SyntaxTreeNode.java | 9 +- .../internal/xsltc/compiler/Template.java | 9 +- .../internal/xsltc/compiler/VariableBase.java | 53 +- .../internal/xsltc/compiler/WithParam.java | 43 +- .../xsltc/dom/AdaptiveResultTreeImpl.java | 13 +- .../xalan/internal/xsltc/dom/DOMAdapter.java | 15 +- .../xalan/internal/xsltc/dom/MultiDOM.java | 52 +- .../xalan/internal/xsltc/dom/SAXImpl.java | 25 +- .../xsltc/dom/SimpleResultTreeImpl.java | 16 +- .../jaxp/unittest/transform/Bug4693341.out | 19 - .../unittest/transform/Bug4693341Test.java | 26 +- .../unittest/transform/Bug4693341_golden.dtd | 39 - .../unittest/transform/Bug4693341_golden.xml | 20 - .../jaxp/unittest/transform/Bug6505031.java | 94 - .../jaxp/unittest/transform/Bug8150704-1.ref | 1 + .../jaxp/unittest/transform/Bug8150704-1.xml | 5 + .../jaxp/unittest/transform/Bug8150704-1.xsl | 76 + .../jaxp/unittest/transform/Bug8150704-2.ref | 83 + .../jaxp/unittest/transform/Bug8150704-2.xml | 2438 +++++++++++++++++ .../jaxp/unittest/transform/Bug8150704-2.xsl | 1935 +++++++++++++ .../unittest/transform/TransformerTest.java | 218 +- 25 files changed, 4916 insertions(+), 396 deletions(-) delete mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341.out delete mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.dtd delete mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.xml delete mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug6505031.java create mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.ref create mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xml create mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xsl create mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.ref create mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xml create mode 100644 jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xsl diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java index 1e6be9a9d85..47534bc4a8e 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: DOM.java,v 1.2.4.1 2005/08/31 10:18:49 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc; @@ -102,4 +99,5 @@ public interface DOM { public int getDocument(); public String getUnparsedEntityURI(String name); public Map getElementsWithIDs(); + public void release(); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java index 6d6a47c157a..fbbb5c8e986 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: ApplyTemplates.java,v 1.2.4.1 2005/09/12 09:59:21 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -122,12 +119,10 @@ final class ApplyTemplates extends Instruction { final int current = methodGen.getLocalIndex("current"); // check if sorting nodes is required - final Vector sortObjects = new Vector(); - final Iterator children = elements(); - while (children.hasNext()) { - final SyntaxTreeNode child = children.next(); + final Vector sortObjects = new Vector<>(); + for (final SyntaxTreeNode child : getContents()) { if (child instanceof Sort) { - sortObjects.addElement(child); + sortObjects.addElement((Sort)child); } } @@ -193,6 +188,13 @@ final class ApplyTemplates extends Instruction { applyTemplatesSig); il.append(new INVOKEVIRTUAL(applyTemplates)); + // unmap parameters to release temporary result trees + for (final SyntaxTreeNode child : getContents()) { + if (child instanceof WithParam) { + ((WithParam)child).releaseResultTree(classGen, methodGen); + } + } + // Pop parameter frame if (stylesheet.hasLocalParams() || hasContents()) { il.append(classGen.loadTranslet()); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java index caace085213..2e2ca146e84 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2004 The Apache Software Foundation. @@ -17,18 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: CallTemplate.java,v 1.2.4.1 2005/09/12 10:02:41 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; -import com.sun.org.apache.bcel.internal.generic.ALOAD; -import com.sun.org.apache.bcel.internal.generic.ASTORE; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.InstructionList; -import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; @@ -56,7 +49,7 @@ final class CallTemplate extends Instruction { * this array can be either a WithParam or a Param if no WithParam * exists for a particular parameter. */ - private Object[] _parameters = null; + private SyntaxTreeNode[] _parameters = null; /** * The corresponding template which this CallTemplate calls. @@ -147,11 +140,10 @@ final class CallTemplate extends Instruction { // If calling a simply named template, push actual arguments if (_calleeTemplate != null) { - Vector calleeParams = _calleeTemplate.getParameters(); int numParams = _parameters.length; for (int i = 0; i < numParams; i++) { - SyntaxTreeNode node = (SyntaxTreeNode)_parameters[i]; + SyntaxTreeNode node = _parameters[i]; methodSig.append(OBJECT_SIG); // append Object to signature // Push 'null' if Param to indicate no actual parameter specified @@ -170,6 +162,15 @@ final class CallTemplate extends Instruction { methodName, methodSig.toString()))); + // release temporary result trees + if (_parameters != null) { + for (int i = 0; i < _parameters.length; i++) { + if (_parameters[i] instanceof WithParam) { + ((WithParam)_parameters[i]).releaseResultTree(classGen, methodGen); + } + } + } + // Do not need to call Translet.popParamFrame() if we are // calling a simple named template. if (_calleeTemplate == null && (stylesheet.hasLocalParams() || hasContents())) { @@ -203,9 +204,9 @@ final class CallTemplate extends Instruction { private void buildParameterList() { // Put the parameters from the called template into the array first. // This is to ensure the order of the parameters. - Vector defaultParams = _calleeTemplate.getParameters(); + Vector defaultParams = _calleeTemplate.getParameters(); int numParams = defaultParams.size(); - _parameters = new Object[numParams]; + _parameters = new SyntaxTreeNode[numParams]; for (int i = 0; i < numParams; i++) { _parameters[i] = defaultParams.elementAt(i); } @@ -222,15 +223,15 @@ final class CallTemplate extends Instruction { // Search for a Param with the same name for (int k = 0; k < numParams; k++) { - Object object = _parameters[k]; - if (object instanceof Param - && ((Param)object).getName().equals(name)) { + SyntaxTreeNode parm = _parameters[k]; + if (parm instanceof Param + && ((Param)parm).getName().equals(name)) { withParam.setDoParameterOptimization(true); _parameters[k] = withParam; break; } - else if (object instanceof WithParam - && ((WithParam)object).getName().equals(name)) { + else if (parm instanceof WithParam + && ((WithParam)parm).getName().equals(name)) { withParam.setDoParameterOptimization(true); _parameters[k] = withParam; break; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java index d8264a23f93..f7309e50125 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2005 The Apache Software Foundation. @@ -17,32 +16,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: Sort.java,v 1.2.4.1 2005/09/12 11:08:12 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; -import java.text.Collator; import java.util.ArrayList; -import java.util.NoSuchElementException; -import java.util.StringTokenizer; import java.util.Vector; import com.sun.org.apache.bcel.internal.classfile.Field; -import com.sun.org.apache.bcel.internal.classfile.Method; import com.sun.org.apache.bcel.internal.generic.ALOAD; import com.sun.org.apache.bcel.internal.generic.ANEWARRAY; import com.sun.org.apache.bcel.internal.generic.ASTORE; import com.sun.org.apache.bcel.internal.generic.CHECKCAST; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.GETFIELD; -import com.sun.org.apache.bcel.internal.generic.ICONST; import com.sun.org.apache.bcel.internal.generic.ILOAD; import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; -import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; -import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.InstructionHandle; import com.sun.org.apache.bcel.internal.generic.InstructionList; import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; @@ -76,13 +65,10 @@ final class Sort extends Instruction implements Closure { private AttributeValue _order; private AttributeValue _caseOrder; private AttributeValue _dataType; - private String _lang; // bug! see 26869 - - private String _data = null; - + private String _lang; // bug! see 26869 private String _className = null; - private ArrayList _closureVars = null; + private ArrayList _closureVars = null; private boolean _needsSortRecordFactory = false; // -- Begin Closure interface -------------------- @@ -115,7 +101,7 @@ final class Sort extends Instruction implements Closure { */ public void addVariable(VariableRefBase variableRef) { if (_closureVars == null) { - _closureVars = new ArrayList(); + _closureVars = new ArrayList<>(); } // Only one reference per variable @@ -246,7 +232,7 @@ final class Sort extends Instruction implements Closure { public static void translateSortIterator(ClassGenerator classGen, MethodGenerator methodGen, Expression nodeSet, - Vector sortObjects) + Vector sortObjects) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); @@ -312,7 +298,7 @@ final class Sort extends Instruction implements Closure { * Compiles code that instantiates a NodeSortRecordFactory object which * will produce NodeSortRecord objects of a specific type. */ - public static void compileSortRecordFactory(Vector sortObjects, + public static void compileSortRecordFactory(Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen) { String sortRecordClass = @@ -321,7 +307,7 @@ final class Sort extends Instruction implements Closure { boolean needsSortRecordFactory = false; final int nsorts = sortObjects.size(); for (int i = 0; i < nsorts; i++) { - final Sort sort = (Sort) sortObjects.elementAt(i); + final Sort sort = sortObjects.elementAt(i); needsSortRecordFactory |= sort._needsSortRecordFactory; } @@ -429,7 +415,7 @@ final class Sort extends Instruction implements Closure { + "[" + STRING_SIG + ")V"))); // Initialize closure variables in sortRecordFactory - final ArrayList dups = new ArrayList(); + final ArrayList dups = new ArrayList<>(); for (int j = 0; j < nsorts; j++) { final Sort sort = (Sort) sortObjects.get(j); @@ -437,7 +423,7 @@ final class Sort extends Instruction implements Closure { sort._closureVars.size(); for (int i = 0; i < length; i++) { - VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); + VariableRefBase varRef = sort._closureVars.get(i); // Discard duplicate variable references if (dups.contains(varRef)) continue; @@ -455,11 +441,11 @@ final class Sort extends Instruction implements Closure { } } - public static String compileSortRecordFactory(Vector sortObjects, + public static String compileSortRecordFactory(Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen, String sortRecordClass) { - final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC(); + final XSLTC xsltc = (sortObjects.firstElement()).getXSLTC(); final String className = xsltc.getHelperClassName(); final NodeSortRecordFactGenerator sortRecordFactory = @@ -474,15 +460,15 @@ final class Sort extends Instruction implements Closure { // Add a new instance variable for each var in closure final int nsorts = sortObjects.size(); - final ArrayList dups = new ArrayList(); + final ArrayList dups = new ArrayList<>(); for (int j = 0; j < nsorts; j++) { - final Sort sort = (Sort) sortObjects.get(j); + final Sort sort = sortObjects.get(j); final int length = (sort._closureVars == null) ? 0 : sort._closureVars.size(); for (int i = 0; i < length; i++) { - final VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); + final VariableRefBase varRef = sort._closureVars.get(i); // Discard duplicate variable references if (dups.contains(varRef)) continue; @@ -600,10 +586,10 @@ final class Sort extends Instruction implements Closure { /** * Create a new auxillary class extending NodeSortRecord. */ - private static String compileSortRecord(Vector sortObjects, + private static String compileSortRecord(Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen) { - final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC(); + final XSLTC xsltc = sortObjects.firstElement().getXSLTC(); final String className = xsltc.getHelperClassName(); // This generates a new class for handling this specific sort @@ -619,10 +605,10 @@ final class Sort extends Instruction implements Closure { // Add a new instance variable for each var in closure final int nsorts = sortObjects.size(); - final ArrayList dups = new ArrayList(); + final ArrayList dups = new ArrayList<>(); for (int j = 0; j < nsorts; j++) { - final Sort sort = (Sort) sortObjects.get(j); + final Sort sort = sortObjects.get(j); // Set the name of the inner class in this sort object sort.setInnerClassName(className); @@ -644,8 +630,7 @@ final class Sort extends Instruction implements Closure { } } - MethodGenerator init = compileInit(sortObjects, sortRecord, - cpg, className); + MethodGenerator init = compileInit(sortRecord, cpg, className); MethodGenerator extract = compileExtract(sortObjects, sortRecord, cpg, className); sortRecord.addMethod(init); @@ -660,8 +645,7 @@ final class Sort extends Instruction implements Closure { * collator in the super calls only when the stylesheet specifies a new * language in xsl:sort. */ - private static MethodGenerator compileInit(Vector sortObjects, - NodeSortRecordGenerator sortRecord, + private static MethodGenerator compileInit(NodeSortRecordGenerator sortRecord, ConstantPoolGen cpg, String className) { @@ -688,7 +672,7 @@ final class Sort extends Instruction implements Closure { /** * Compiles a method that overloads NodeSortRecord.extractValueFromDOM() */ - private static MethodGenerator compileExtract(Vector sortObjects, + private static MethodGenerator compileExtract(Vector sortObjects, NodeSortRecordGenerator sortRecord, ConstantPoolGen cpg, String className) { @@ -730,7 +714,7 @@ final class Sort extends Instruction implements Closure { // Append all the cases for the switch statment for (int level = 0; level < levels; level++) { match[level] = level; - final Sort sort = (Sort)sortObjects.elementAt(level); + final Sort sort = sortObjects.elementAt(level); target[level] = il.append(NOP); sort.translateSelect(sortRecord, extractMethod); il.append(ARETURN); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java index bfa00213915..3b921a1b815 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: SyntaxTreeNode.java,v 1.6 2006/06/06 22:34:33 spericas Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -519,9 +516,9 @@ public abstract class SyntaxTreeNode implements Constants { // references falling out-of-scope inside the for-each element. // (the cause of which being 'lazy' register allocation for references) for (int i = 0; i < n; i++) { - if( _contents.get(i) instanceof VariableBase) { + if ( _contents.get(i) instanceof VariableBase) { final VariableBase var = (VariableBase)_contents.get(i); - var.unmapRegister(methodGen); + var.unmapRegister(classGen, methodGen); } } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java index 9450702c90c..9284f2a03a3 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: Template.java,v 1.2.4.1 2005/09/12 11:30:11 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -63,7 +60,7 @@ public final class Template extends TopLevelElement { // The list of parameters in this template. This is only used // for simple named templates. - private Vector _parameters = new Vector(); + private Vector _parameters = new Vector<>(); public boolean hasParams() { return _parameters.size() > 0; @@ -85,7 +82,7 @@ public final class Template extends TopLevelElement { _parameters.addElement(param); } - public Vector getParameters() { + public Vector getParameters() { return _parameters; } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java index 7ef4c1cabd6..02e1a5f3ef4 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2004 The Apache Software Foundation. @@ -17,18 +16,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: VariableBase.java,v 1.5 2005/09/28 13:48:18 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; import java.util.Vector; +import com.sun.org.apache.bcel.internal.generic.CHECKCAST; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.Instruction; import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; +import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.bcel.internal.generic.NEW; import com.sun.org.apache.bcel.internal.generic.PUSH; @@ -36,6 +35,7 @@ import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeSetType; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ResultTreeType; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; import com.sun.org.apache.xml.internal.utils.XML11Char; @@ -49,21 +49,18 @@ import com.sun.org.apache.xml.internal.utils.XML11Char; */ class VariableBase extends TopLevelElement { - protected QName _name; // The name of the variable. - protected String _escapedName; // The escaped qname of the variable. - protected Type _type; // The type of this variable. - protected boolean _isLocal; // True if the variable is local. - protected LocalVariableGen _local; // Reference to JVM variable - protected Instruction _loadInstruction; // Instruction to load JVM variable + protected QName _name; // The name of the variable. + protected String _escapedName; // The escaped qname of the variable. + protected Type _type; // The type of this variable. + protected boolean _isLocal; // True if the variable is local. + protected LocalVariableGen _local; // Reference to JVM variable + protected Instruction _loadInstruction; // Instruction to load JVM variable protected Instruction _storeInstruction; // Instruction to load JVM variable - protected Expression _select; // Reference to variable expression - protected String select; // Textual repr. of variable expr. + protected Expression _select; // Reference to variable expression + protected String select; // Textual repr. of variable expr. // References to this variable (when local) - protected Vector _refs = new Vector(2); - - // Dependencies to other variables/parameters (for globals only) - protected Vector _dependencies = null; + protected Vector _refs = new Vector<>(2); // Used to make sure parameter field is not added twice protected boolean _ignore = false; @@ -92,7 +89,7 @@ class VariableBase extends TopLevelElement { public void copyReferences(VariableBase var) { final int size = _refs.size(); for (int i = 0; i < size; i++) { - var.addReference((VariableRefBase) _refs.get(i)); + var.addReference(_refs.get(i)); } } @@ -112,8 +109,24 @@ class VariableBase extends TopLevelElement { * Remove the mapping of this variable to a register. * Called when we leave the AST scope of the variable's declaration */ - public void unmapRegister(MethodGenerator methodGen) { + public void unmapRegister(ClassGenerator classGen, MethodGenerator methodGen) { if (_local != null) { + if (_type instanceof ResultTreeType) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + if (classGen.getStylesheet().callsNodeset() && classGen.getDOMClass().equals(MULTI_DOM_CLASS)) { + final int removeDA = cpg.addMethodref(MULTI_DOM_CLASS, "removeDOMAdapter", "(" + DOM_ADAPTER_SIG + ")V"); + il.append(methodGen.loadDOM()); + il.append(new CHECKCAST(cpg.addClass(MULTI_DOM_CLASS))); + il.append(loadInstruction()); + il.append(new CHECKCAST(cpg.addClass(DOM_ADAPTER_CLASS))); + il.append(new INVOKEVIRTUAL(removeDA)); + } + final int release = cpg.addInterfaceMethodref(DOM_IMPL_CLASS, "release", "()V"); + il.append(loadInstruction()); + il.append(new INVOKEINTERFACE(release, 1)); + } + _local.setEnd(methodGen.getInstructionList().getEnd()); methodGen.removeLocalVariable(_local); _refs = null; @@ -126,7 +139,6 @@ class VariableBase extends TopLevelElement { * the JVM stack. */ public Instruction loadInstruction() { - final Instruction instr = _loadInstruction; if (_loadInstruction == null) { _loadInstruction = _type.LOAD(_local.getIndex()); } @@ -138,7 +150,6 @@ class VariableBase extends TopLevelElement { * into this variable. */ public Instruction storeInstruction() { - final Instruction instr = _storeInstruction; if (_storeInstruction == null) { _storeInstruction = _type.STORE(_local.getIndex()); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java index 3a87d59313c..fc2b202ceea 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2004 The Apache Software Foundation. @@ -17,15 +16,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: WithParam.java,v 1.2.4.1 2005/09/12 11:38:01 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ASTORE; +import com.sun.org.apache.bcel.internal.generic.CHECKCAST; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.bcel.internal.generic.PUSH; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; @@ -59,6 +60,11 @@ final class WithParam extends Instruction { */ private Expression _select; + /** + * Reference to JVM variable holding temporary result tree. + */ + private LocalVariableGen _domAdapter; + /** * %OPT% This is set to true when the WithParam is used in a CallTemplate * for a simple named template. If this is true, the parameters are @@ -164,8 +170,13 @@ final class WithParam extends Instruction { _select.startIterator(classGen, methodGen); } // If not, compile result tree from parameter body if present. + // Store result tree into local variable for releasing it later else if (hasContents()) { + final InstructionList il = methodGen.getInstructionList(); compileResultTree(classGen, methodGen); + _domAdapter = methodGen.addLocalVariable2("@" + _escapedName, Type.ResultTree.toJCType(), il.getEnd()); + il.append(DUP); + il.append(new ASTORE(_domAdapter.getIndex())); } // If neither are present then store empty string in parameter slot else { @@ -208,4 +219,26 @@ final class WithParam extends Instruction { ADD_PARAMETER_SIG))); il.append(POP); // cleanup stack } + + /** + * Release the compiled result tree. + */ + public void releaseResultTree(ClassGenerator classGen, MethodGenerator methodGen) { + if (_domAdapter != null) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + if (classGen.getStylesheet().callsNodeset() && classGen.getDOMClass().equals(MULTI_DOM_CLASS)) { + final int removeDA = cpg.addMethodref(MULTI_DOM_CLASS, "removeDOMAdapter", "(" + DOM_ADAPTER_SIG + ")V"); + il.append(methodGen.loadDOM()); + il.append(new CHECKCAST(cpg.addClass(MULTI_DOM_CLASS))); + il.append(new ALOAD(_domAdapter.getIndex())); + il.append(new CHECKCAST(cpg.addClass(DOM_ADAPTER_CLASS))); + il.append(new INVOKEVIRTUAL(removeDA)); + } + final int release = cpg.addInterfaceMethodref(DOM_IMPL_CLASS, "release", "()V"); + il.append(new ALOAD(_domAdapter.getIndex())); + il.append(new INVOKEINTERFACE(release, 1)); + _domAdapter = null; + } + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java index fc1b1d9412c..cb50cf5d779 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: AdaptiveResultTreeImpl.java,v 1.2.4.1 2005/09/06 05:52:18 pvedula Exp $ - */ + package com.sun.org.apache.xalan.internal.xsltc.dom; import com.sun.org.apache.xalan.internal.xsltc.DOM; @@ -1338,4 +1336,11 @@ public class AdaptiveResultTreeImpl extends SimpleResultTreeImpl } } + public void release() { + if (_dom != null) { + _dom.release(); + _dom = null; + } + super.release(); + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java index a12d9e42c85..4f44ae1baa6 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: DOMAdapter.java,v 1.2.4.1 2005/09/06 06:07:28 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.dom; @@ -56,8 +53,6 @@ public final class DOMAdapter implements DOM { private short[] _NSmapping = null; private short[] _NSreverse = null; - private StripFilter _filter = null; - private int _multiDOMMask; public DOMAdapter(DOM dom, @@ -165,9 +160,7 @@ public final class DOMAdapter implements DOM { } } - public void setFilter(StripFilter filter) { - _filter = filter; - } + public void setFilter(StripFilter filter) {} public DTMAxisIterator getTypedChildren(final int type) { final int[] reverse = getReverse(); @@ -464,4 +457,8 @@ public final class DOMAdapter implements DOM { public Map getElementsWithIDs() { return _dom.getElementsWithIDs(); } + + public void release() { + _dom.release(); + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java index fae254fabc8..cf22c31920f 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ - /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -30,8 +29,8 @@ import com.sun.org.apache.xml.internal.dtm.DTM; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.dtm.DTMManager; import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase; -import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase; import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIterNodeList; +import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase; import com.sun.org.apache.xml.internal.serializer.SerializationHandler; import com.sun.org.apache.xml.internal.utils.SuballocatedIntVector; import java.util.HashMap; @@ -671,4 +670,51 @@ public final class MultiDOM implements DOM { public Map getElementsWithIDs() { return _main.getElementsWithIDs(); } + + public void release() { + _main.release(); + } + + private boolean isMatchingAdapterEntry(DOM entry, DOMAdapter adapter) { + DOM dom = adapter.getDOMImpl(); + + return (entry == adapter) || ( + /* + * Method addDOMAdapter overwrites for AdaptiveResultTreeImpl + * objects the usual entry with an adapter to the nested + * DOM, so we must check this here. See last 'if' statement + * of addDOMAdapter. + */ + (dom instanceof AdaptiveResultTreeImpl) && + (entry instanceof DOMAdapter) && + (((AdaptiveResultTreeImpl)dom).getNestedDOM() == ((DOMAdapter)entry).getDOMImpl()) + ); + } + + public void removeDOMAdapter(DOMAdapter adapter) { + _documents.remove(adapter.getDocumentURI(0)); + DOM dom = adapter.getDOMImpl(); + + if (dom instanceof DTMDefaultBase) { + SuballocatedIntVector ids = ((DTMDefaultBase) dom).getDTMIDs(); + int idsSize = ids.size(); + for (int i = 0; i < idsSize; i++) { + _adapters[ids.elementAt(i) >>> DTMManager.IDENT_DTM_NODE_BITS] = null; + } + } else { + int id = dom.getDocument() >>> DTMManager.IDENT_DTM_NODE_BITS; + if ((id > 0) && (id < _adapters.length) && isMatchingAdapterEntry(_adapters[id], adapter)) { + _adapters[id] = null; + } else { + boolean found = false; + for (int i = 0; i < _adapters.length; i++) { + if (isMatchingAdapterEntry(_adapters[id], adapter)) { + _adapters[i] = null; + found = true; + break; + } + } + } + } + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java index c6b06931702..9a8bc34892a 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: SAXImpl.java,v 1.5 2005/09/28 13:48:37 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.dom; @@ -82,7 +79,7 @@ public final class SAXImpl extends SAX2DTM2 // Namespace prefix-to-uri mapping stuff private int _uriCount = 0; - private int _prefixCount = 0; + // private int _prefixCount = 0; // Stack used to keep track of what whitespace text nodes are protected // by xml:space="preserve" attributes and which nodes that are not. @@ -90,11 +87,11 @@ public final class SAXImpl extends SAX2DTM2 private int _idx = 1; private boolean _preserve = false; - private static final String XML_STRING = "xml:"; + // private static final String XML_STRING = "xml:"; private static final String XML_PREFIX = "xml"; private static final String XMLSPACE_STRING = "xml:space"; private static final String PRESERVE_STRING = "preserve"; - private static final String XMLNS_PREFIX = "xmlns"; + // private static final String XMLNS_PREFIX = "xmlns"; private static final String XML_URI = "http://www.w3.org/XML/1998/namespace"; private boolean _escaping = true; @@ -123,7 +120,7 @@ public final class SAXImpl extends SAX2DTM2 private BitArray _dontEscape = null; // The URI to this document - private String _documentURI = null; + // private String _documentURI = null; static private int _documentURIIndex = 0; // The owner Document when the input source is DOMSource. @@ -143,8 +140,7 @@ public final class SAXImpl extends SAX2DTM2 // Support for access/navigation through org.w3c.dom API private Node[] _nodes; private NodeList[] _nodeLists; - private final static String XML_LANG_ATTRIBUTE = - "http://www.w3.org/XML/1998/namespace:@lang"; + // private final static String XML_LANG_ATTRIBUTE = "http://www.w3.org/XML/1998/namespace:@lang"; /** * Define the origin of the document from which the tree was built @@ -491,6 +487,7 @@ public final class SAXImpl extends SAX2DTM2 /** * Sets up a translet-to-dom type mapping table */ + /* private int[] setupMapping(String[] names, String[] uris, int[] types, int nNames) { // Padding with number of names, because they // may need to be added, i.e for RTFs. See copy03 @@ -502,6 +499,7 @@ public final class SAXImpl extends SAX2DTM2 } return result; } + */ /** * Returns the internal type associated with an expanded QName @@ -1230,9 +1228,6 @@ public final class SAXImpl extends SAX2DTM2 */ public DTMAxisIterator getNamespaceAxisIterator(int axis, int ns) { - - DTMAxisIterator iterator = null; - if (ns == NO_TYPE) { return EMPTYITERATOR; } @@ -1546,7 +1541,6 @@ public final class SAXImpl extends SAX2DTM2 */ public DTMAxisIterator getNthDescendant(int type, int n, boolean includeself) { - DTMAxisIterator source = (DTMAxisIterator) new TypedDescendantIterator(type); return new NthDescendantIterator(n); } @@ -1882,4 +1876,7 @@ public final class SAXImpl extends SAX2DTM2 } } + public void release() { + _dtmManager.release(this, true); + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java index 6739458a94b..812258a8f76 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 1999-2004 The Apache Software Foundation. @@ -17,15 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: SimpleResultTreeImpl.java,v 1.2.4.1 2005/09/06 10:09:25 pvedula Exp $ - */ + package com.sun.org.apache.xalan.internal.xsltc.dom; import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.StripFilter; import com.sun.org.apache.xalan.internal.xsltc.TransletException; - import com.sun.org.apache.xml.internal.dtm.Axis; import com.sun.org.apache.xml.internal.dtm.DTM; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; @@ -1014,4 +1010,12 @@ public class SimpleResultTreeImpl extends EmptySerializer implements DOM, DTM public void migrateTo(DTMManager manager) { } + + public void release() + { + if (_documentID != 0) { + _dtmManager.release(this, true); + _documentID = 0; + } + } } diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341.out b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341.out deleted file mode 100644 index e946a45a944..00000000000 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341.out +++ /dev/null @@ -1,19 +0,0 @@ - - -10016 -Wed May 29 12:45:00 PDT 2002 - -ABC -XYZ -1234 Anywhere Street -Palo Alto -California -USA -94303 -NULL -NULL - - - - - \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java index f0dc71feb5a..8daef2e5cce 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -26,6 +26,7 @@ package transform; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; import java.net.URL; import javax.xml.parsers.SAXParser; @@ -45,16 +46,27 @@ import org.xml.sax.helpers.DefaultHandler; * @summary Test transform with external dtd. */ public class Bug4693341Test { + // save dtd file to current working directory to avoid writing into source repository + public void copyDTDtoWorkDir() throws IOException { + try (FileInputStream dtdres = new FileInputStream(getClass().getResource("Bug4693341.dtd").getPath()); + FileOutputStream dtdwork = new FileOutputStream("Bug4693341.dtd");) { + int n; + byte[] buffer = new byte[1024]; + while((n = dtdres.read(buffer)) > -1) { + dtdwork.write(buffer, 0, n); + } + } + } @Test public void test() { - boolean status = false; - try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); - String out = getClass().getResource("Bug4693341.out").getPath(); - StreamResult result = new StreamResult(new FileOutputStream(out)); + copyDTDtoWorkDir(); + + File outf = new File("Bug4693341.out"); + StreamResult result = new StreamResult(new FileOutputStream(outf)); String in = getClass().getResource("Bug4693341.xml").getPath(); File file = new File(in); @@ -63,7 +75,7 @@ public class Bug4693341Test { transformer.transform(source, result); //URL inputsource = new URL("file", "", golden); - URL output = new URL("file", "", out); + URL output = new URL("file", "", outf.getPath()); // error happens when trying to parse output String systemId = output.toExternalForm(); @@ -71,10 +83,8 @@ public class Bug4693341Test { InputSource is = new InputSource(systemId); SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); parser.parse(is, new DefaultHandler()); - } catch (Exception ex) { Assert.fail(ex.getMessage()); } } - } diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.dtd b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.dtd deleted file mode 100644 index 9e4dd578483..00000000000 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.dtd +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.xml b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.xml deleted file mode 100644 index 5c0928e85ab..00000000000 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - -10016 -Wed May 29 12:45:00 PDT 2002 - -ABC -XYZ -1234 Anywhere Street -Palo Alto -California -USA -94303 -NULL -NULL - - - - - diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug6505031.java b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug6505031.java deleted file mode 100644 index d3fa4fd30f4..00000000000 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug6505031.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2014, 2015, 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 transform; - -import java.io.StringWriter; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.stream.StreamSource; - -import org.testng.Assert; -import org.testng.annotations.Test; - -/* - * @bug 6505031 - * @summary Test transformer parses keys and their values coming from different xml documents. - */ -public class Bug6505031 { - - private String getResource(String s) { - return getClass().getResource(s).toString(); - - } - - @Test - public void test() { - Map params = new HashMap(); - - params.put("config", getResource("config.xml")); - params.put("mapsFile", getResource("maps.xml")); - generate(getResource("template.xml"), getResource("transform.xsl"), params); - } - - private void generate(String in, String xsl, Map params) { - try { - Transformer transformer = getTransformer(xsl); - - for (Iterator i = params.entrySet().iterator(); i.hasNext();) { - Map.Entry entry = (Map.Entry) i.next(); - - transformer.setParameter((String) entry.getKey(), entry.getValue()); - } - transform(in, transformer); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - } - - private Transformer getTransformer(String transform) throws Exception { - TransformerFactory tfactory = TransformerFactory.newInstance(); - - try { - // tfactory.setAttribute("generate-translet", Boolean.TRUE); - } catch (Exception e) { - // Ignore - } - - Transformer transformer = tfactory.newTransformer(new StreamSource(transform)); - return (transformer); - } - - private void transform(String in, Transformer transformer) throws Exception { - StringWriter sw = new StringWriter(); - transformer.transform(new StreamSource(in), new StreamResult(sw)); - String s = sw.toString(); - Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value")); - } - -} diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.ref b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.ref new file mode 100644 index 00000000000..0af2588d894 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.ref @@ -0,0 +1 @@ +................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................ diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xml b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xml new file mode 100644 index 00000000000..382a25f08fb --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xml @@ -0,0 +1,5 @@ + + + + . + diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xsl b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xsl new file mode 100644 index 00000000000..f390323c2f9 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xsl @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.ref b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.ref new file mode 100644 index 00000000000..b012e31307c --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.ref @@ -0,0 +1,83 @@ +0fto-erech 200amos-batch 00000000X/ +1FB01 20150709 EWF 2016021207USD 0000,9302122026623 ////////91284422 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000007366,71//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////D8OOoOOooooOoooooO////15/07 P0480715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40090597 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150630 EWF 2016021206USD 0000,9302122026624 ////////1500006837 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000003844,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////b3oooooooooooooooo////15/07 R1683315 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40127254 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150709 EWF 2016021207CHF 0001,0000022026625 ////////94043801 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000438,50//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0CooOooooooooooOOo////15/07 P0472115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30092874 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150702 EWF 2016021207EUR 0001,0468822026626 ////////TL152062 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000661,30//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////3coooooooooooooooo////15/07 P0431815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40099751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150617 EWF 2016021206EUR 0001,0468822026627 ////////TKL100216 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000699,92//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////55oooooOoOooooOoOo////15/07 L0032815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2014686 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150702 EWF 2016021207EUR 0001,0468822026628 ////////TL152063 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001983,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9boooooooooooooooo////15/07 P0431815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40099751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207EUR 0001,0468822026629 ////////000359084 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000002230,76//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////51oOoOoOoOoooooOOO////15/07 R1735915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40128088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207CHF 0001,0000022026630 ////////90864081 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001893,20//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////acoooooooooooooooo////15/07 P0470615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090668 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207USD 0000,9302122026631 ////////123939 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000007896,34//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////09oooooooooooooooo////15/07 P0400015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40128846 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207USD 0000,9302122026633 ////////000358117 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000006810,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////f5oooooooooooooooo////15/07 P0462815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40128088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207CHF 0001,0000022026635 ////////M90257500 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000016300,50//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////C3oOOOooOoOooOOOoo////15/07 R1488615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207USD 0000,9302122026637 ////////M90257457 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000831,90//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////60ooooOooOOOoOoOoo////15/07 P0463815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000055,22//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0463815 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207USD 0000,9302122026638 ////////M90257509 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000002218,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////60OoooooOOooooOooo////15/07 P0491115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000055,22//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0491115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207CHF 0001,0000022026639 ////////M90257515 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000005833,20//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////A6OOooOoOoOooOoooo////15/07 R1575215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026642 ////////C/5 335835 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////16OooooOooOOoOoooo////15/07 R1612715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026643 ////////C/5 335833 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000835,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////58OOoOOooooOooOOoo////15/07 R1441715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207USD 0000,9302122026644 ////////C/5 336036 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6BooooOOoooOooOooo////15/07 R1659015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026645 ////////C/5 335836 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6DoOoooOooOOoOooOo////15/07 R1613415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207USD 0000,9302122026646 ////////C/5 336201 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////74ooOoOooooooooOoO////15/07 R1728915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207USD 0000,9302122026647 ////////C/5 336035 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////86OoooOOoooOoooOOo////15/07 R1612615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207USD 0000,9302122026648 ////////C/5 336034 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000835,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////99OOooooooOooOoooo////15/07 R1445115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026649 ////////C/5 335834 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000835,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////D8OOoooOOOooooOOoo////15/07 R1445315 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207CHF 0001,0000022026650 ////////351732 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000192,80//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////4BooOooooOOOoOOOOo////15/07 P0448015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207CHF 0001,0000022026651 ////////351730 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000057,25//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////69ooOoOooooooooooO////15/07 P0451715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000007,02//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0451715 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207CHF 0001,0000022026652 ////////351731 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000100,05//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////A9oooooooOoOooOOOo////15/07 P0448015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207EUR 0001,0468822026653 ////////05/91014407 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000225,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////22oooOooooOooOooOO////15/07 R1727915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207EUR 0001,0468822026654 ////////05/91015508 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000225,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////24OooooOOoOooOoOoO////15/07 R1728015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207EUR 0001,0468822026655 ////////05/91015531 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000768,45//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////76oOOOOooOoOooooOO////15/07 W0054415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207USD 0000,9302122026656 ////////SI156008034 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000261,79//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////96OooooOoOoooOOOoo////15/07 P0479215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126601 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150709 EWF 2016021207EUR 0001,0468822026657 ////////05/91015509 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000705,35//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////99ooOoOOoooooOoooo////15/07 R1625015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207EUR 0001,0468822026662 ////////55941607 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000725,60//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////4BOoooOOOoOoooooOo////15/07 P0486115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40091085 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207CHF 0001,0000022026663 ////////100-120606 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000004229,50//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0boooooooooooooooo////15/07 P0474115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30094003 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000430,56//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0474115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000054,38//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0474115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207CHF 0001,0000022026664 ////////13143106 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000318,65//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6eoooooooooooooooo////15/07 P0468115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30092269 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000014,04//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0468115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150709 EWF 2016021207EUR 0001,0468822026665 ////////TL152315 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001983,90//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////74oooooooooooooooo////15/07 P0431815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40099751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150710 EWF 2016021207EUR 0001,0468822026667 ////////11321 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000840,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////caoooooooooooooooo////15/07 P0471915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40129316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150401 EWF 2016021204EUR 0001,0553176278995 ////////76278995 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000007833,33//////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////15/04 S0026415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////566//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VERB05001 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20110209 EWF 2016021202CHF 0001,0000090149059 ////////M90149059 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001077,30//////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////11/03 S0080410 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////566//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20110209 EWF 2016021202USD 0000,9570290149062 ////////90149062 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000002185,78//////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////11/03 S0125011 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////566//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xml b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xml new file mode 100644 index 00000000000..19a8381e919 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xml @@ -0,0 +1,2438 @@ + + + + 22026623 + + + CRX + CHF + + OPEN + I + V0409 + CAGE1 + 40090597 + + 91284422 + 2015-07-09 + + 2015-07-15 + 2015-07-15 + D8OOoOOooooOoooooOOOOooOoooOoOoo + + 7366.71 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0480715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026624 + + + CRX + CHF + + OPEN + I + V0307 + CAGE2 + 40127254 + + 1500006837 + 2015-06-30 + + 2015-07-16 + 2015-07-16 + b3oooooooooooooooooooooooooooooo + + 3844.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1683315 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-30 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026625 + + + CRX + CHF + + CLOSED + I + V0568 + 30092874 + + 94043801 + 2015-07-09 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 0CooOooooooooooOOoooOooOoOOoooOo + + 438.5 + 190.008 + 0.0 + 0.0 + + 4V + 32.48 + + + + P + P0472115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026626 + + + CRX + CHF + + OPEN + I + V0316 + CAGE3 + 40099751 + + TL152062 + 2015-07-02 + + 2015-07-16 + 2015-07-16 + 3coooooooooooooooooooooooooooooo + + 661.3 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0431815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-01 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026627 + + + CRX + CHF + + OPEN + I + V0440 + 2014686 + + TKL100216 + 2015-06-17 + + 2015-07-16 + 2015-07-16 + 55oooooOoOooooOoOoOOOoOOOoooOOoo + + 699.92 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + L + L0032815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-17 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026628 + + + CRX + CHF + + OPEN + I + V0316 + CAGE4 + 40099751 + + TL152063 + 2015-07-02 + + 2015-07-16 + 2015-07-16 + 9boooooooooooooooooooooooooooooo + + 1983.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0431815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-01 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026629 + + + CRX + CHF + + OPEN + I + V0506 + 40128088 + + 000359084 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + 51oOoOoOoOoooooOOOoOooooOOoooOoO + + 2230.76 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1735915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026630 + + + CRX + CHF + + OPEN + I + V0497 + 30090668 + + 90864081 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + acoooooooooooooooooooooooooooooo + + 1893.2 + 0.0 + 0.0 + 0.0 + + 4V + 0.0 + + + + P + P0470615 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026631 + + + CRX + CHF + + OPEN + I + V0512 + 40128846 + + 123939 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + 09oooooooooooooooooooooooooooooo + + 7896.34 + 0.0 + 0.0 + 0.0 + + TAX + 0.0 + + + + P + P0400015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026633 + + + CRX + CHF + + CLOSED + I + V0202 + 40128088 + + 000358117 + 2015-07-07 + 2015-07-16 + 2015-07-16 + 2015-07-16 + f5oooooooooooooooooooooooooooooo + + 6810.0 + 3187.08 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0462815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026635 + + + CRX + CHF + + OPEN + I + V0011 + 30124373 + + M90257500 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + C3oOOOooOoOooOOOoooOOOoOOoooOoOO + + 16300.5 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1488615 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026637 + + + CRX + CHF + + CLOSED + I + V0139 + 30124373 + + M90257457 + 2015-07-13 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 60ooooOooOOOoOoOoooooooOOOOoooOO + + 831.9 + 334.1052 + 118.0 + 0.0 + + V0 + 0.0 + + + + P + P0463815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + H + HANDLING CHARGE + N + N + + 400158 + + 7000 + 7000 + + + 55.224 + 55.224 + + V0 + V0 + 0.0 + + + D + + + + 22026638 + + + CRX + CHF + + CLOSED + I + V0139 + 30124373 + + M90257509 + 2015-07-13 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 60OoooooOOooooOoooooooooOOooOOOO + + 2218.0 + 982.8 + 118.0 + 0.0 + + V0 + 0.0 + + + + P + P0491115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + H + HANDLING CHARGE + N + N + + 400158 + + 7000 + 7000 + + + 55.224 + 55.224 + + V0 + V0 + 0.0 + + + D + + + + 22026639 + + + CRX + CHF + + OPEN + I + V0162 + 30124373 + + M90257515 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + A6OOooOoOoOooOoooooooooOooooOOoo + + 5833.2 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1575215 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026642 + + + CRX + CHF + + OPEN + I + V0400 + CAGE5 + 40126141 + + C/5 335835 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + 16OooooOooOOoOooooOoooooooooooOO + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1612715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026643 + + + CRX + CHF + + OPEN + I + V0400 + CAGE6 + 40126141 + + C/5 335833 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + 58OOoOOooooOooOOooOoooOooooOOoOo + + 835.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1441715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026644 + + + CRX + CHF + + OPEN + I + V0400 + CAGE7 + 40126141 + + C/5 336036 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 6BooooOOoooOooOooooOooooOoOOoooo + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1659015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026645 + + + CRX + CHF + + OPEN + I + V0400 + CAGE8 + 40126141 + + C/5 335836 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + 6DoOoooOooOOoOooOoOoOoOOOoOoOooo + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1613415 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026646 + + + CRX + CHF + + OPEN + I + V0400 + CAGE9 + 40126141 + + C/5 336201 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + 74ooOoOooooooooOoOOOoOoOooOoooOO + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1728915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026647 + + + CRX + CHF + + OPEN + I + V0400 + CAGEA + 40126141 + + C/5 336035 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 86OoooOOoooOoooOOoOooOoooOOoOoOo + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1612615 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026648 + + + CRX + CHF + + OPEN + I + V0400 + CAGEB + 40126141 + + C/5 336034 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 99OOooooooOooOooooOooOooOoOOoOoo + + 835.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1445115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026649 + + + CRX + CHF + + OPEN + I + V0400 + CAGEC + 40126141 + + C/5 335834 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + D8OOoooOOOooooOOoooOOoOoooOoOOOO + + 835.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1445315 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026650 + + + CRX + CHF + + OPEN + I + V0429 + 30090682 + + 351732 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 4BooOooooOOOoOOOOooo + + 192.8 + 0.0 + 0.0 + 0.0 + + 4V + 0.0 + + + + P + P0448015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026651 + + + CRX + CHF + + CLOSED + I + V0429 + 30090682 + + 351730 + 2015-07-06 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 69ooOoOooooooooooOoOooOOOOoooOoO + + 57.25 + 17.784 + 15.0 + 0.0 + + 4V + 4.24 + + + + P + P0451715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + F + FREIGHT + N + N + + 400122 + + 7000 + 7000 + + + 7.02 + 7.02 + + 4V + 4V + 0.5616 + + + D + + + + 22026652 + + + CRX + CHF + + OPEN + I + V0429 + 30090682 + + 351731 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + A9oooooooOoOooOOOoOO + + 100.05 + 0.0 + 0.0 + 0.0 + + 4V + 0.0 + + + + P + P0448015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026653 + + + CRX + CHF + + OPEN + I + V0028 + CAGED + 40096899 + + 05/91014407 + 2015-07-07 + + 2015-07-16 + 2015-07-16 + 22oooOooooOooOooOOoOooOoooooOooO + + 225.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1727915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026654 + + + CRX + CHF + + OPEN + I + V0028 + CAGEE + 40096899 + + 05/91015508 + 2015-07-07 + + 2015-07-16 + 2015-07-16 + 24OooooOOoOooOoOoOoOoooOOoOOooOo + + 225.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1728015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026655 + + + CRX + CHF + + CLOSED + I + V0028 + CAGEF + 40096899 + + 05/91015531 + 2015-07-01 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 76oOOOOooOoOooooOOoOoOOooOooOoOO + + 768.45 + 359.6346 + 0.0 + 0.0 + + V0 + 0.0 + + + + W + W0054415 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026656 + + + CRX + CHF + + OPEN + I + V0651 + 40126601 + + SI156008034 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + 96OooooOoOoooOOOoooOOoooOoOOOOoO + + 261.79 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0479215 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026657 + + + CRX + CHF + + CLOSED + I + V0028 + CAGEG + 40096899 + + 05/91015509 + 2015-07-09 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 99ooOoOOoooooOooooOOOOoooOOoOOoO + + 705.35 + 330.1038 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1625015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026662 + + + CRX + CHF + + OPEN + I + V0495 + CAGEH + 40091085 + + 55941607 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + 4BOoooOOOoOoooooOoOOooOooooOoOoo + + 725.6 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0486115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026663 + + + CRX + CHF + + CLOSED + I + V0604 + 30094003 + + 100-120606 + 2015-07-08 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 0boooooooooooooooooooooooooooooo + + 4229.5 + 1347.84 + 1036.2 + 0.0 + + TAX + 313.3 + + + + P + P0474115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + H + HANDLING CHARGE + N + N + + 400158 + + 7000 + 7000 + + + 430.56 + 430.56 + + 4V + 4V + 34.4448 + + + D + + + + F + FREIGHT + N + N + + 400122 + + 7000 + 7000 + + + 54.3816 + 54.3816 + + 4V + 4V + 4.3524 + + + D + + + + 22026664 + + + CRX + CHF + + CLOSED + I + V0634 + 30092269 + + 13143106 + 2015-07-07 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 6eoooooooooooooooooooooooooooooo + + 318.65 + 124.0434 + 30.0 + 0.0 + + 4V + 23.599999999999998 + + + + P + P0468115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + F + FREIGHT + N + N + + 400122 + + 7000 + 7000 + + + 14.04 + 14.04 + + 4V + 4V + 1.1232 + + + D + + + + 22026665 + + + CRX + CHF + + OPEN + I + V0316 + CAGEI + 40099751 + + TL152315 + 2015-07-09 + + 2015-07-16 + 2015-07-16 + 74oooooooooooooooooooooooooooooo + + 1983.9 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0431815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026667 + + + CRX + CHF + + OPEN + I + V0642 + 40129316 + + 11321 + 2015-07-10 + + 2015-07-16 + 2015-07-16 + caoooooooooooooooooooooooooooooo + + 840.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0471915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-09 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 76278995 + + + CRX + CHF + + CLOSED + I + V0166 + CAGEJ + VERB05001 + + 76278995 + 2015-04-01 + 2015-04-17 + 2015-04-17 + 2015-04-17 + + 7833.33 + 3394.4414 + 0.0 + 0.0 + + V0 + 580.25 + + + + S + S0026415 + + + 2016-02-12 + + Y + + + + + + + + + + 2015-04-01 + 0 + Y + + + 04 + 2015 + + + EUR + CHF + 1.05531 + + + + + 90149059 + + + CRX + CHF + + CLOSED + I + V0016 + 30124373 + + M90149059 + 2011-02-09 + 2011-02-18 + 2011-02-18 + 2011-02-18 + + 1077.3 + 504.1764 + 0.0 + 0.0 + + TAX + 0.0 + + + + S + S0080410 + + + 2016-02-12 + + N + + + + 5 + + + + + + 2011-02-09 + 0 + N + + + 03 + 2011 + + + CHF + CHF + 1.0 + + + + + 90149062 + + + CRX + CHF + + CLOSED + I + V0016 + 30124374 + + 90149062 + 2011-02-09 + 2011-02-21 + 2011-02-21 + 2011-02-21 + + 2185.78 + 1022.945 + 0.0 + 0.0 + + TAX + 0.0 + + + + S + S0125011 + + + 2016-02-12 + + N + + + + 6 + + + + + + 2011-02-09 + 0 + N + + + 03 + 2011 + + + USD + CHF + 0.95702 + + + + + diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xsl b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xsl new file mode 100644 index 00000000000..3fd6282b3de --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xsl @@ -0,0 +1,1935 @@ + + + + + + + + + +0 +fto-erech +200 +amos-batch +00000000 +X + + +FB01 +TP +EWF + + +566 +950 + + +2w + +V0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + + + + + + + + + + + + + + + + + + +KA +EA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/ + + + +/ +/ +/ +/ +/ +X +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + +2 +BBSEG + +31 +21 + +/ +/ +/ + + + + +/ +/ +/ + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + + +/ +/ + + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + +2 +BBSEG + +40 +50 + +/ +/ +/ + + + + +/ +/ +/ + + + +/ +/ +/ +/ + + + + + + + + + + +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + +/ +/ + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + +2 +BBSEG + +40 +50 + +/ +/ +/ + + + +/ +/ +/ + + + +/ +/ +/ +/ + + + + + + + + + + +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + +2 +BBSEG + +40 +50 + +/ +/ +/ + + + + +/ +/ +/ + + + +/ +/ +/ +/ + + + + + + + + + + +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +INVALID ALIGN + + + + \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java index 18229dc28c9..2e01c5dbe59 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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,13 @@ package transform; +import com.sun.org.apache.xml.internal.serialize.OutputFormat; +import com.sun.org.apache.xml.internal.serialize.XMLSerializer; + +import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; @@ -55,56 +61,67 @@ import org.xml.sax.XMLReader; import org.xml.sax.helpers.AttributesImpl; /* - * @summary Test Transformer. + * @summary Transformer Tests + * @bug 6272879 6305029 6505031 8150704 */ public class TransformerTest { - - private static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - private static final String XML_DOCUMENT = "" + ""; - - //Test for JDK-6305029 - @Test - public final void testTransform() throws TransformerException { - - // test SAXSource - SAXSource saxSource = new SAXSource(new MyXMLReader(), new InputSource()); - - StringWriter builder = new StringWriter(); - TransformerFactory.newInstance().newTransformer().transform(saxSource, new StreamResult(builder)); - - AssertJUnit.assertEquals("Identity transform of SAXSource", XML_DOCUMENT, builder.toString()); - - // test StreamSource - StreamSource streamSource = new StreamSource(new StringReader(XML_DOCUMENT)); - - StringWriter streamResult = new StringWriter(); - - TransformerFactory.newInstance().newTransformer().transform(streamSource, new StreamResult(streamResult)); - - AssertJUnit.assertEquals("Identity transform of StreamSource", XML_DOCUMENT, streamResult.toString()); + private Transformer createTransformer() throws TransformerException { + return TransformerFactory.newInstance().newTransformer(); } - private static class MyXMLReader implements XMLReader { + private Transformer createTransformerFromInputstream(InputStream xslStream) throws TransformerException { + return TransformerFactory.newInstance().newTransformer(new StreamSource(xslStream)); + } + private Transformer createTransformerFromResource(String xslResource) throws TransformerException { + return TransformerFactory.newInstance().newTransformer(new StreamSource(getClass().getResource(xslResource).toString())); + } + + private Document transformInputStreamToDocument(Transformer transformer, InputStream sourceStream) throws TransformerException { + DOMResult response = new DOMResult(); + transformer.transform(new StreamSource(sourceStream), response); + return (Document)response.getNode(); + } + + private StringWriter transformResourceToStringWriter(Transformer transformer, String xmlResource) throws TransformerException { + StringWriter sw = new StringWriter(); + transformer.transform(new StreamSource(getClass().getResource(xmlResource).toString()), new StreamResult(sw)); + return sw; + } + + /** + * Reads the contents of the given file into a string. + * WARNING: this method adds a final line feed even if the last line of the file doesn't contain one. + * + * @param f + * The file to read + * @return The content of the file as a string, with line terminators as \"n" + * for all platforms + * @throws IOException + * If there was an error reading + */ + private String getFileContentAsString(File f) throws IOException { + try (BufferedReader reader = new BufferedReader(new FileReader(f))) { + String line; + StringBuilder sb = new StringBuilder(); + while ((line = reader.readLine()) != null) { + sb.append(line).append("\n"); + } + return sb.toString(); + } + } + + private class XMLReaderFor6305029 implements XMLReader { private static final String NAMESPACES = "http://xml.org/sax/features/namespaces"; - private static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes"; - private boolean namespaces = true; - private boolean namespacePrefixes = false; - private EntityResolver resolver; - private DTDHandler dtdHandler; - private ContentHandler contentHandler; - private ErrorHandler errorHandler; public boolean getFeature(final String name) throws SAXNotRecognizedException, SAXNotSupportedException { - if (name.equals(NAMESPACES)) { return namespaces; } else if (name.equals(NAMESPACE_PREFIXES)) { @@ -115,7 +132,6 @@ public class TransformerTest { } public void setFeature(final String name, final boolean value) throws SAXNotRecognizedException, SAXNotSupportedException { - if (name.equals(NAMESPACES)) { namespaces = value; } else if (name.equals(NAMESPACE_PREFIXES)) { @@ -165,12 +181,10 @@ public class TransformerTest { } public void parse(final InputSource input) throws IOException, SAXException { - parse(); } public void parse(final String systemId) throws IOException, SAXException { - parse(); } @@ -190,30 +204,50 @@ public class TransformerTest { } } + /* + * @bug 6272879 + * @summary Test for JDK-6272879 + */ @Test - public final void testCR6272879() { + public final void testBug6272879() throws IOException, TransformerException { + final String LINE_SEPARATOR = System.getProperty("line.separator"); - final String xsl = "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR + "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR + " " + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR + " " - + LINE_SEPARATOR + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR + "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR + ""; + final String xsl = + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + ""; - final String sourceXml = "" - + LINE_SEPARATOR + final String sourceXml = + "" + LINE_SEPARATOR + // "" + LINE_SEPARATOR + // "" + LINE_SEPARATOR + // "" + LINE_SEPARATOR + // "]>" + // LINE_SEPARATOR + - + "" + LINE_SEPARATOR + " " + LINE_SEPARATOR + " Valeur 1" + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR + " Valeur 2" + LINE_SEPARATOR - + " " + LINE_SEPARATOR + ""; + "" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " Valeur 1" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " Valeur 2" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + ""; Document document; Node node; @@ -230,9 +264,12 @@ public class TransformerTest { System.out.println("Source file after transformation:"); System.out.println("================================="); - document = getTransformation(xsl, sourceXml); - - System.out.println(document); + document = transformInputStreamToDocument(createTransformerFromInputstream(new ByteArrayInputStream(xsl.getBytes())), + new ByteArrayInputStream(sourceXml.getBytes())); + OutputFormat format = new OutputFormat(); + format.setIndenting(true); + new XMLSerializer(System.out, format).serialize(document); + System.out.println(); System.out.println("Node content for element valeur2:"); System.out.println("================================="); @@ -248,25 +285,60 @@ public class TransformerTest { } } - private static Document getTransformation(final String xsl, final String sourceXml) { + /* + * @bug 6305029 + * @summary Test for JDK-6305029 + */ + @Test + public final void testBug6305029() throws TransformerException { + final String XML_DOCUMENT = "" + ""; - Transformer transformer; - DOMResult reponse; - Document document = null; + // test SAXSource + SAXSource saxSource = new SAXSource(new XMLReaderFor6305029(), new InputSource()); + StringWriter resultWriter = new StringWriter(); + createTransformer().transform(saxSource, new StreamResult(resultWriter)); + AssertJUnit.assertEquals("Identity transform of SAXSource", XML_DOCUMENT, resultWriter.toString()); - try { - InputStream in = new ByteArrayInputStream(xsl.getBytes()); - transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(in)); + // test StreamSource + StreamSource streamSource = new StreamSource(new StringReader(XML_DOCUMENT)); + resultWriter = new StringWriter(); + createTransformer().transform(streamSource, new StreamResult(resultWriter)); + AssertJUnit.assertEquals("Identity transform of StreamSource", XML_DOCUMENT, resultWriter.toString()); + } - reponse = new DOMResult(); - transformer.transform(new StreamSource(new ByteArrayInputStream(sourceXml.getBytes())), reponse); - document = (Document) reponse.getNode(); - } catch (Exception e) { - String msg = "Exception in getTransformation: " + e; - System.err.println(msg); - Assert.fail(msg); - } + /* + * @bug 6505031 + * @summary Test transformer parses keys and their values coming from different xml documents. + */ + @Test + public final void testBug6505031() throws TransformerException { + Transformer transformer = createTransformerFromResource("transform.xsl"); + transformer.setParameter("config", getClass().getResource("config.xml").toString()); + transformer.setParameter("mapsFile", getClass().getResource("maps.xml").toString()); + String s = transformResourceToStringWriter(transformer, "template.xml").toString(); + Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value")); + } - return (document); + /* + * @bug 8150704 + * @summary Test that XSL transformation with lots of temporary result trees will not run out of DTM IDs. + */ + @Test + public final void testBug8150704() throws TransformerException, IOException { + System.out.println("Testing transformation of Bug8150704-1.xml..."); + Transformer transformer = createTransformerFromResource("Bug8150704-1.xsl"); + StringWriter result = transformResourceToStringWriter(transformer, "Bug8150704-1.xml"); + String resultstring = result.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); + String reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-1.ref").getPath())); + Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-1.xml does not match reference"); + System.out.println("Passed."); + + System.out.println("Testing transformation of Bug8150704-2.xml..."); + transformer = createTransformerFromResource("Bug8150704-2.xsl"); + result = transformResourceToStringWriter(transformer, "Bug8150704-2.xml"); + resultstring = result.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); + reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-2.ref").getPath())); + Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-2.xml does not match reference"); + System.out.println("Passed."); } } From f36012af70c61446189a22c28dd8dadcf5af4363 Mon Sep 17 00:00:00 2001 From: Sergey Ustimenko Date: Thu, 10 Mar 2016 09:35:59 -0500 Subject: [PATCH 277/311] 8043329: Wrong variable used in java.util.Collections javadoc code Reviewed-by: lancea, rriggs --- jdk/src/java.base/share/classes/java/util/Collections.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/util/Collections.java b/jdk/src/java.base/share/classes/java/util/Collections.java index 73047bff5d1..0eb9da0f644 100644 --- a/jdk/src/java.base/share/classes/java/util/Collections.java +++ b/jdk/src/java.base/share/classes/java/util/Collections.java @@ -2728,7 +2728,7 @@ public class Collections { * Set s2 = m2.keySet(); // Needn't be in synchronized block * ... * synchronized (m) { // Synchronizing on m, not m2 or s2! - * Iterator i = s.iterator(); // Must be in synchronized block + * Iterator i = s2.iterator(); // Must be in synchronized block * while (i.hasNext()) * foo(i.next()); * } From 9ecc7cc9283f4e97206990a47a6957fb22ad81c1 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Thu, 10 Mar 2016 13:04:43 -0800 Subject: [PATCH 278/311] 8151470: [JVMCI] remove up-call to HotSpotJVMCICompilerConfig.selectCompiler Reviewed-by: dnsimon, vlivanov --- .../hotspot/HotSpotJVMCICompilerConfig.java | 39 ++--- .../vm/ci/hotspot/HotSpotJVMCIRuntime.java | 1 + hotspot/src/share/vm/jvmci/jvmciRuntime.cpp | 142 ------------------ hotspot/src/share/vm/jvmci/jvmciRuntime.hpp | 20 +-- hotspot/src/share/vm/runtime/arguments.cpp | 2 - hotspot/src/share/vm/runtime/thread.cpp | 9 -- 6 files changed, 27 insertions(+), 186 deletions(-) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java index b1b486721e8..b7b7f9ad347 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -25,6 +25,7 @@ package jdk.vm.ci.hotspot; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequestResult; import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option; import jdk.vm.ci.runtime.JVMCICompiler; import jdk.vm.ci.runtime.JVMCICompilerFactory; import jdk.vm.ci.runtime.JVMCIRuntime; @@ -47,29 +48,33 @@ final class HotSpotJVMCICompilerConfig { } } + /** + * Factory of the selected system compiler. + */ private static JVMCICompilerFactory compilerFactory; /** - * Selects the system compiler. + * Gets the selected system compiler factory. * - * Called from VM. This method has an object return type to allow it to be called with a VM - * utility function used to call other static initialization methods. + * @return the selected system compiler factory */ - static Boolean selectCompiler(String compilerName) { - assert compilerFactory == null; - for (JVMCICompilerFactory factory : Services.load(JVMCICompilerFactory.class)) { - if (factory.getCompilerName().equals(compilerName)) { - compilerFactory = factory; - return Boolean.TRUE; - } - } - - throw new JVMCIError("JVMCI compiler '%s' not found", compilerName); - } - static JVMCICompilerFactory getCompilerFactory() { if (compilerFactory == null) { - compilerFactory = new DummyCompilerFactory(); + JVMCICompilerFactory factory = null; + String compilerName = Option.Compiler.getString(); + if (compilerName != null) { + for (JVMCICompilerFactory f : Services.load(JVMCICompilerFactory.class)) { + if (f.getCompilerName().equals(compilerName)) { + factory = f; + } + } + if (factory == null) { + throw new JVMCIError("JVMCI compiler '%s' not found", compilerName); + } + } else { + factory = new DummyCompilerFactory(); + } + compilerFactory = factory; } return compilerFactory; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index afdc02fe26f..802bc1ccef0 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -91,6 +91,7 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H * A list of all supported JVMCI options. */ public enum Option { + Compiler(String.class, null, "Selects the system compiler."), ImplicitStableValues(boolean.class, true, "Mark well-known stable fields as such."), // Note: The following one is not used (see InitTimer.ENABLED). InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."), diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp index d5a10f4660f..19aff9ed1c9 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp @@ -51,7 +51,6 @@ jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL; bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false; bool JVMCIRuntime::_well_known_classes_initialized = false; -const char* JVMCIRuntime::_compiler = NULL; int JVMCIRuntime::_trivial_prefixes_count = 0; char** JVMCIRuntime::_trivial_prefixes = NULL; bool JVMCIRuntime::_shutdown_called = false; @@ -642,15 +641,6 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) { "HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization"); #endif - if (_compiler != NULL) { - JavaCallArguments args; - oop compiler = java_lang_String::create_oop_from_str(_compiler, CHECK); - args.push_oop(compiler); - callStatic("jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig", - "selectCompiler", - "(Ljava/lang/String;)Ljava/lang/Boolean;", &args, CHECK); - } - Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime", "runtime", "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK); @@ -783,66 +773,6 @@ JVM_ENTRY(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass)) } JVM_END -/** - * Closure for parsing a line from a *.properties file in jre/lib/jvmci/properties. - * The line must match the regular expression "[^=]+=.*". That is one or more - * characters other than '=' followed by '=' followed by zero or more characters. - * Everything before the '=' is the property name and everything after '=' is the value. - * Lines that start with '#' are treated as comments and ignored. - * No special processing of whitespace or any escape characters is performed. - * The last definition of a property "wins" (i.e., it overrides all earlier - * definitions of the property). - */ -class JVMCIPropertiesFileClosure : public ParseClosure { - SystemProperty** _plist; -public: - JVMCIPropertiesFileClosure(SystemProperty** plist) : _plist(plist) {} - void do_line(char* line) { - if (line[0] == '#') { - // skip comment - return; - } - size_t len = strlen(line); - char* sep = strchr(line, '='); - if (sep == NULL) { - warn_and_abort("invalid format: could not find '=' character"); - return; - } - if (sep == line) { - warn_and_abort("invalid format: name cannot be empty"); - return; - } - *sep = '\0'; - const char* name = line; - char* value = sep + 1; - Arguments::PropertyList_unique_add(_plist, name, value); - } -}; - -void JVMCIRuntime::init_system_properties(SystemProperty** plist) { - char jvmciDir[JVM_MAXPATHLEN]; - const char* fileSep = os::file_separator(); - jio_snprintf(jvmciDir, sizeof(jvmciDir), "%s%slib%sjvmci", - Arguments::get_java_home(), fileSep, fileSep, fileSep); - DIR* dir = os::opendir(jvmciDir); - if (dir != NULL) { - struct dirent *entry; - char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(jvmciDir), mtInternal); - JVMCIPropertiesFileClosure closure(plist); - const unsigned suffix_len = (unsigned)strlen(".properties"); - while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL && !closure.is_aborted()) { - const char* name = entry->d_name; - if (strlen(name) > suffix_len && strcmp(name + strlen(name) - suffix_len, ".properties") == 0) { - char propertiesFilePath[JVM_MAXPATHLEN]; - jio_snprintf(propertiesFilePath, sizeof(propertiesFilePath), "%s%s%s",jvmciDir, fileSep, name); - JVMCIRuntime::parse_lines(propertiesFilePath, &closure, false); - } - } - FREE_C_HEAP_ARRAY(char, dbuf); - os::closedir(dir); - } -} - #define CHECK_WARN_ABORT_(message) THREAD); \ if (HAS_PENDING_EXCEPTION) { \ warning(message); \ @@ -853,12 +783,6 @@ void JVMCIRuntime::init_system_properties(SystemProperty** plist) { } \ (void)(0 -void JVMCIRuntime::save_compiler(const char* compiler) { - assert(compiler != NULL, "npe"); - assert(_compiler == NULL, "cannot reassign JVMCI compiler"); - _compiler = compiler; -} - void JVMCIRuntime::shutdown(TRAPS) { if (_HotSpotJVMCIRuntime_instance != NULL) { _shutdown_called = true; @@ -884,69 +808,3 @@ bool JVMCIRuntime::treat_as_trivial(Method* method) { } return false; } - -void JVMCIRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) { - struct stat st; - if (::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file - int file_handle = ::open(path, os::default_file_open_flags(), 0); - if (file_handle != -1) { - char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal); - int num_read; - num_read = (int) ::read(file_handle, (char*) buffer, st.st_size); - if (num_read == -1) { - warning("Error reading file %s due to %s", path, strerror(errno)); - } else if (num_read != st.st_size) { - warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path); - } - ::close(file_handle); - closure->set_filename(path); - if (num_read == st.st_size) { - buffer[num_read] = '\0'; - - char* line = buffer; - while (line - buffer < num_read && !closure->is_aborted()) { - // find line end (\r, \n or \r\n) - char* nextline = NULL; - char* cr = strchr(line, '\r'); - char* lf = strchr(line, '\n'); - if (cr != NULL && lf != NULL) { - char* min = MIN2(cr, lf); - *min = '\0'; - if (lf == cr + 1) { - nextline = lf + 1; - } else { - nextline = min + 1; - } - } else if (cr != NULL) { - *cr = '\0'; - nextline = cr + 1; - } else if (lf != NULL) { - *lf = '\0'; - nextline = lf + 1; - } - // trim left - while (*line == ' ' || *line == '\t') line++; - char* end = line + strlen(line); - // trim right - while (end > line && (*(end -1) == ' ' || *(end -1) == '\t')) end--; - *end = '\0'; - // skip comments and empty lines - if (*line != '#' && strlen(line) > 0) { - closure->parse_line(line); - } - if (nextline != NULL) { - line = nextline; - } else { - // File without newline at the end - break; - } - } - } - FREE_C_HEAP_ARRAY(char, buffer); - } else { - warning("Error opening file %s due to %s", path, strerror(errno)); - } - } else if (warnStatFailure) { - warning("Could not stat file %s due to %s", path, strerror(errno)); - } -} diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp index 17476d65af9..4c37817537d 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -70,7 +70,6 @@ class JVMCIRuntime: public AllStatic { static jobject _HotSpotJVMCIRuntime_instance; static bool _HotSpotJVMCIRuntime_initialized; static bool _well_known_classes_initialized; - static const char* _compiler; static int _trivial_prefixes_count; static char** _trivial_prefixes; @@ -85,19 +84,9 @@ class JVMCIRuntime: public AllStatic { static Handle create_Service(const char* name, TRAPS); public: - - /** - * Parses *.properties files in jre/lib/jvmci/ and adds the properties to plist. - */ - static void init_system_properties(SystemProperty** plist); - - /** - * Saves the value of the "jvmci.compiler" system property for processing - * when JVMCI is initialized. - */ - static void save_compiler(const char* compiler); - - static bool is_HotSpotJVMCIRuntime_initialized() { return _HotSpotJVMCIRuntime_initialized; } + static bool is_HotSpotJVMCIRuntime_initialized() { + return _HotSpotJVMCIRuntime_initialized; + } /** * Gets the singleton HotSpotJVMCIRuntime instance, initializing it if necessary @@ -136,7 +125,6 @@ class JVMCIRuntime: public AllStatic { } static bool treat_as_trivial(Method* method); - static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure); static BasicType kindToBasicType(Handle kind, TRAPS); diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 8033afe70c3..fa307ff891c 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -221,8 +221,6 @@ void Arguments::init_system_properties() { // Set OS specific system properties values os::init_system_properties_values(); - - JVMCI_ONLY(JVMCIRuntime::init_system_properties(&_system_properties);) } // Update/Initialize System properties after JDK version number is known diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 9d6531de9ef..17479b47c6b 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -3696,15 +3696,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { Chunk::start_chunk_pool_cleaner_task(); } -#if INCLUDE_JVMCI - if (EnableJVMCI) { - const char* jvmciCompiler = Arguments::PropertyList_get_value(Arguments::system_properties(), "jvmci.compiler"); - if (jvmciCompiler != NULL) { - JVMCIRuntime::save_compiler(jvmciCompiler); - } - } -#endif // INCLUDE_JVMCI - // initialize compiler(s) #if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI CompileBroker::compilation_init(CHECK_JNI_ERR); From 59193ab336c45e4d1204550dfdb2a63c62c37d28 Mon Sep 17 00:00:00 2001 From: Ed Nevill Date: Thu, 10 Mar 2016 14:53:09 +0000 Subject: [PATCH 279/311] 8151502: optimize pd_disjoint_words and pd_conjoint_words Optimize copy routines using inline assembler Reviewed-by: aph --- .../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 4 +- .../vm/copy_linux_aarch64.inline.hpp | 122 ++++++--- .../linux_aarch64/vm/copy_linux_aarch64.s | 236 ++++++++++++++++++ 3 files changed, 331 insertions(+), 31 deletions(-) create mode 100644 hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index 6ac553302c3..30805fb4150 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -849,8 +849,8 @@ class StubGenerator: public StubCodeGenerator { __ bind(L1); if (direction == copy_forwards) { - __ add(s, s, 2 * wordSize); - __ add(d, d, 2 * wordSize); + __ add(s, s, bias); + __ add(d, d, bias); } __ tbz(count, 1, L2); diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp index 5fc2dfd70d2..96575867dc2 100644 --- a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp +++ b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp @@ -26,44 +26,108 @@ #ifndef OS_CPU_LINUX_AARCH64_VM_COPY_LINUX_AARCH64_INLINE_HPP #define OS_CPU_LINUX_AARCH64_VM_COPY_LINUX_AARCH64_INLINE_HPP +#define COPY_SMALL(from, to, count) \ +{ \ + long tmp0, tmp1, tmp2, tmp3; \ + long tmp4, tmp5, tmp6, tmp7; \ + __asm volatile( \ +" adr %[t0], 0f;" \ +" add %[t0], %[t0], %[cnt], lsl #5;" \ +" br %[t0];" \ +" .align 5;" \ +"0:" \ +" b 1f;" \ +" .align 5;" \ +" ldr %[t0], [%[s], #0];" \ +" str %[t0], [%[d], #0];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldr %[t2], [%[s], #16];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" str %[t2], [%[d], #16];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldp %[t2], %[t3], [%[s], #16];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" stp %[t2], %[t3], [%[d], #16];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldp %[t2], %[t3], [%[s], #16];" \ +" ldr %[t4], [%[s], #32];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" stp %[t2], %[t3], [%[d], #16];" \ +" str %[t4], [%[d], #32];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldp %[t2], %[t3], [%[s], #16];" \ +" ldp %[t4], %[t5], [%[s], #32];" \ +"2:" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" stp %[t2], %[t3], [%[d], #16];" \ +" stp %[t4], %[t5], [%[d], #32];" \ +" b 1f;" \ +" .align 5;" \ +" ldr %[t6], [%[s], #0];" \ +" ldp %[t0], %[t1], [%[s], #8];" \ +" ldp %[t2], %[t3], [%[s], #24];" \ +" ldp %[t4], %[t5], [%[s], #40];" \ +" str %[t6], [%[d]], #8;" \ +" b 2b;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldp %[t2], %[t3], [%[s], #16];" \ +" ldp %[t4], %[t5], [%[s], #32];" \ +" ldp %[t6], %[t7], [%[s], #48];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" stp %[t2], %[t3], [%[d], #16];" \ +" stp %[t4], %[t5], [%[d], #32];" \ +" stp %[t6], %[t7], [%[d], #48];" \ +"1:" \ + \ + : [s]"+r"(from), [d]"+r"(to), [cnt]"+r"(count), \ + [t0]"=&r"(tmp0), [t1]"=&r"(tmp1), [t2]"=&r"(tmp2), [t3]"=&r"(tmp3), \ + [t4]"=&r"(tmp4), [t5]"=&r"(tmp5), [t6]"=&r"(tmp6), [t7]"=&r"(tmp7) \ + : \ + : "memory", "cc"); \ +} + static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { - (void)memmove(to, from, count * HeapWordSize); + __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); + if (__builtin_expect(count <= 8, 1)) { + COPY_SMALL(from, to, count); + return; + } + _Copy_conjoint_words(from, to, count); } static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - (void)memcpy(to, from, count * HeapWordSize); - break; + if (__builtin_constant_p(count)) { + memcpy(to, from, count * sizeof(HeapWord)); + return; } + __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); + if (__builtin_expect(count <= 8, 1)) { + COPY_SMALL(from, to, count); + return; + } + _Copy_disjoint_words(from, to, count); } static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) { - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - while (count-- > 0) { - *to++ = *from++; - } - break; + __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); + if (__builtin_expect(count <= 8, 1)) { + COPY_SMALL(from, to, count); + return; } + _Copy_disjoint_words(from, to, count); } static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s new file mode 100644 index 00000000000..25e3b054f77 --- /dev/null +++ b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2016, Linaro Ltd. 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. + * + */ + .global _Copy_conjoint_words + .global _Copy_disjoint_words + +s .req x0 +d .req x1 +count .req x2 +t0 .req x3 +t1 .req x4 +t2 .req x5 +t3 .req x6 +t4 .req x7 +t5 .req x8 +t6 .req x9 +t7 .req x10 + + .align 6 +_Copy_disjoint_words: + // Ensure 2 word aligned + tbz s, #3, fwd_copy_aligned + ldr t0, [s], #8 + str t0, [d], #8 + sub count, count, #1 + +fwd_copy_aligned: + // Bias s & d so we only pre index on the last copy + sub s, s, #16 + sub d, d, #16 + + ldp t0, t1, [s, #16] + ldp t2, t3, [s, #32] + ldp t4, t5, [s, #48] + ldp t6, t7, [s, #64]! + + subs count, count, #16 + blo fwd_copy_drain + +fwd_copy_again: + prfm pldl1keep, [s, #256] + stp t0, t1, [d, #16] + ldp t0, t1, [s, #16] + stp t2, t3, [d, #32] + ldp t2, t3, [s, #32] + stp t4, t5, [d, #48] + ldp t4, t5, [s, #48] + stp t6, t7, [d, #64]! + ldp t6, t7, [s, #64]! + subs count, count, #8 + bhs fwd_copy_again + +fwd_copy_drain: + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + stp t4, t5, [d, #48] + stp t6, t7, [d, #64]! + + // count is now -8..-1 for 0..7 words to copy + adr t0, 0f + add t0, t0, count, lsl #5 + br t0 + + .align 5 + ret // -8 == 0 words + .align 5 + ldr t0, [s, #16] // -7 == 1 word + str t0, [d, #16] + ret + .align 5 + ldp t0, t1, [s, #16] // -6 = 2 words + stp t0, t1, [d, #16] + ret + .align 5 + ldp t0, t1, [s, #16] // -5 = 3 words + ldr t2, [s, #32] + stp t0, t1, [d, #16] + str t2, [d, #32] + ret + .align 5 + ldp t0, t1, [s, #16] // -4 = 4 words + ldp t2, t3, [s, #32] + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + ret + .align 5 + ldp t0, t1, [s, #16] // -3 = 5 words + ldp t2, t3, [s, #32] + ldr t4, [s, #48] + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + str t4, [d, #48] + ret + .align 5 + ldp t0, t1, [s, #16] // -2 = 6 words + ldp t2, t3, [s, #32] + ldp t4, t5, [s, #48] + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + stp t4, t5, [d, #48] + ret + .align 5 + ldp t0, t1, [s, #16] // -1 = 7 words + ldp t2, t3, [s, #32] + ldp t4, t5, [s, #48] + ldr t6, [s, #64] + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + stp t4, t5, [d, #48] + str t6, [d, #64] + // Is always aligned here, code for 7 words is one instruction + // too large so it just falls through. + .align 5 +0: + ret + + .align 6 +_Copy_conjoint_words: + sub t0, d, s + cmp t0, count, lsl #3 + bhs _Copy_disjoint_words + + add s, s, count, lsl #3 + add d, d, count, lsl #3 + + // Ensure 2 word aligned + tbz s, #3, bwd_copy_aligned + ldr t0, [s, #-8]! + str t0, [d, #-8]! + sub count, count, #1 + +bwd_copy_aligned: + ldp t0, t1, [s, #-16] + ldp t2, t3, [s, #-32] + ldp t4, t5, [s, #-48] + ldp t6, t7, [s, #-64]! + + subs count, count, #16 + blo bwd_copy_drain + +bwd_copy_again: + prfm pldl1keep, [s, #-256] + stp t0, t1, [d, #-16] + ldp t0, t1, [s, #-16] + stp t2, t3, [d, #-32] + ldp t2, t3, [s, #-32] + stp t4, t5, [d, #-48] + ldp t4, t5, [s, #-48] + stp t6, t7, [d, #-64]! + ldp t6, t7, [s, #-64]! + subs count, count, #8 + bhs bwd_copy_again + +bwd_copy_drain: + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + stp t4, t5, [d, #-48] + stp t6, t7, [d, #-64]! + + // count is now -8..-1 for 0..7 words to copy + adr t0, 0f + add t0, t0, count, lsl #5 + br t0 + + .align 5 + ret // -8 == 0 words + .align 5 + ldr t0, [s, #-8] // -7 == 1 word + str t0, [d, #-8] + ret + .align 5 + ldp t0, t1, [s, #-16] // -6 = 2 words + stp t0, t1, [d, #-16] + ret + .align 5 + ldp t0, t1, [s, #-16] // -5 = 3 words + ldr t2, [s, #-24] + stp t0, t1, [d, #-16] + str t2, [d, #-24] + ret + .align 5 + ldp t0, t1, [s, #-16] // -4 = 4 words + ldp t2, t3, [s, #-32] + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + ret + .align 5 + ldp t0, t1, [s, #-16] // -3 = 5 words + ldp t2, t3, [s, #-32] + ldr t4, [s, #-40] + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + str t4, [d, #-40] + ret + .align 5 + ldp t0, t1, [s, #-16] // -2 = 6 words + ldp t2, t3, [s, #-32] + ldp t4, t5, [s, #-48] + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + stp t4, t5, [d, #-48] + ret + .align 5 + ldp t0, t1, [s, #-16] // -1 = 7 words + ldp t2, t3, [s, #-32] + ldp t4, t5, [s, #-48] + ldr t6, [s, #-56] + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + stp t4, t5, [d, #-48] + str t6, [d, #-56] + // Is always aligned here, code for 7 words is one instruction + // too large so it just falls through. + .align 5 +0: + ret From de4fe8115c1332fb132d42a699c3aea4ce57cf6a Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 10 Mar 2016 09:28:08 -0800 Subject: [PATCH 280/311] Added tag jdk-9+109 for changeset 7fe73c768138 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 528a64a3e8c..831d5d6213f 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -351,3 +351,4 @@ be58b02c11f90b88c67e4d0e2cb5e4cf2d9b3c57 jdk-9+105 54575d8783b3a39a2d710c28cda675d44261f9d9 jdk-9+106 4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107 c7be2a78c31b3b6132f2f5e9e4b3d3bb1c20245c jdk-9+108 +1787bdaabb2b6f4193406e25a50cb0419ea8e8f3 jdk-9+109 From 98f09c95ee424b730f287ba48677b1f005efd75d Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 10 Mar 2016 09:28:09 -0800 Subject: [PATCH 281/311] Added tag jdk-9+109 for changeset 896a46cbffee --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 43b212133c8..5c2b765d93d 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -351,3 +351,4 @@ e385e95e6101711d5c63e7b1a827e99b6ec7a1cc jdk-9+104 8ec4f97943fe56f93e4621f622b56b7144c0181a jdk-9+106 49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107 84f2862a25eb3232ff36c376b4e2bf2a83dfced3 jdk-9+108 +b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109 From e9a96608e0413a336cd1bf5a41f0889f40ad6e80 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 10 Mar 2016 09:28:10 -0800 Subject: [PATCH 282/311] Added tag jdk-9+109 for changeset 9ea881b5873b --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index c77700ff598..cbe0b715f78 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -511,3 +511,4 @@ c5f55130b1b69510d9a6f4a3105b58e21cd7ffe1 jdk-9+103 7232de4c17c37f60aecec4f3191090bd3d41d334 jdk-9+106 c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107 934f6793f5f7dca44f69b4559d525fa64b31840d jdk-9+108 +7e7e50ac4faf19899fc811569e32cfa478759ebb jdk-9+109 From 5da9e80b884c1b35dffc1890e0b945f66874b8e2 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 10 Mar 2016 09:28:13 -0800 Subject: [PATCH 283/311] Added tag jdk-9+109 for changeset 94d8adc2f94d --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index b070406ac71..9a01ef541fc 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -351,3 +351,4 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 65d615f71e81bae46dcb4d053e590582e5705879 jdk-9+106 781b83dadcae89b8ae7545bb4044ddc62c6fa006 jdk-9+107 3b9fa8b1491479f7ae18131a34036b58b647493e jdk-9+108 +24e247ee1fffaa625d480b2a4eef2d3a8a59f5cb jdk-9+109 From 9dda52e2c5685753100b47c3b180efdb18fe23c5 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 10 Mar 2016 09:28:14 -0800 Subject: [PATCH 284/311] Added tag jdk-9+109 for changeset 67e5c45fdf9a --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 64b08144ae1..d02e1de4e0c 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -354,3 +354,4 @@ eb5e005a17e50d7d8340daaf21a5c3c5ae358d68 jdk-9+103 c072c572d14948563ef5d86e1921699b3a2396ab jdk-9+106 fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107 513eb2e432f64f85992442da9acdfcfbb36555d9 jdk-9+108 +4b0697e4ce8940b1599af274ff02296d7f59aded jdk-9+109 From 94509dadd14a4f18355d25d0b7f593fa9159475f Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 10 Mar 2016 09:28:15 -0800 Subject: [PATCH 285/311] Added tag jdk-9+109 for changeset 652d06266511 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index ad3f50825db..8d4f94f1f2c 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -351,3 +351,4 @@ eee1ced1d8e78293f2a004af818ca474387dbebf jdk-9+103 6e9ecae50b4e0d37483fb2719202eea5dca026a4 jdk-9+106 8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107 42794e648cfe9fd67461dcbe8b7594241a84bcff jdk-9+108 +1c7bad0798900fe58f4db01ae7ffdc84f5baee8c jdk-9+109 From aef516391e5f61dc76a7b0912451545868e653bf Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 10 Mar 2016 09:28:20 -0800 Subject: [PATCH 286/311] Added tag jdk-9+109 for changeset 2ab100ef7bb0 --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 265117bfdc0..98a913b7fce 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -342,3 +342,4 @@ a618d3e89fdea5361895ef142a59074fe7ae3d98 jdk-9+104 cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106 8042e81b530e480dfdad41fd53a7a26f69ebba26 jdk-9+107 58409eff7e3e0c07f12f543341769964619c0acf jdk-9+108 +70f0c397021116d7dbd79b01c6711c5d2e68dab4 jdk-9+109 From 28ad9686826e55fa5e7418bd220dc666262b615d Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Thu, 10 Mar 2016 11:52:54 -0800 Subject: [PATCH 287/311] 8151660: Revert NativeBuffer.java to use jdk.internal.ref.Cleaner Reviewed-by: rriggs --- .../share/classes/sun/nio/fs/NativeBuffer.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java index 7daf8ccfe16..1a215d11bf1 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java @@ -26,9 +26,7 @@ package sun.nio.fs; import jdk.internal.misc.Unsafe; -import jdk.internal.ref.CleanerFactory; - -import java.lang.ref.Cleaner; +import jdk.internal.ref.Cleaner; /** * A light-weight buffer in native memory. @@ -39,7 +37,7 @@ class NativeBuffer { private final long address; private final int size; - private final Cleaner.Cleanable cleanable; + private final Cleaner cleaner; // optional "owner" to avoid copying // (only safe for use by thread-local caches) @@ -58,7 +56,7 @@ class NativeBuffer { NativeBuffer(int size) { this.address = unsafe.allocateMemory(size); this.size = size; - this.cleanable = CleanerFactory.cleaner().register(this, new Deallocator(address)); + this.cleaner = Cleaner.create(this, new Deallocator(address)); } void release() { @@ -74,7 +72,7 @@ class NativeBuffer { } void free() { - cleanable.clean(); + cleaner.clean(); } // not synchronized; only safe for use by thread-local caches From b87feb324c47437a840421114a8fd60df5f0ccb9 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Thu, 10 Mar 2016 14:06:21 -0800 Subject: [PATCH 288/311] 8151664: [JVMCI] add missing test in 8151266 integration Reviewed-by: never, twisti --- .../compiler/jvmci/meta/StableFieldTest.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 hotspot/test/compiler/jvmci/meta/StableFieldTest.java diff --git a/hotspot/test/compiler/jvmci/meta/StableFieldTest.java b/hotspot/test/compiler/jvmci/meta/StableFieldTest.java new file mode 100644 index 00000000000..80ff0d7dbaa --- /dev/null +++ b/hotspot/test/compiler/jvmci/meta/StableFieldTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 2016, 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 8151664 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library /testlibrary /test/lib / + * @compile StableFieldTest.java + * @run main ClassFileInstaller compiler.jvmci.meta.StableFieldTest + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:. compiler.jvmci.meta.StableFieldTest + */ + +package compiler.jvmci.meta; + +import java.lang.reflect.Field; +import jdk.internal.vm.annotation.Stable; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.runtime.JVMCI; + +public class StableFieldTest { + + @Stable static int myStaticField = 5; + @Stable int myInstanceField = 10; + + public static void main(String[] args) throws Throwable { + MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess(); + for (String name : new String[] {"myStaticField", "myInstanceField"}) { + java.lang.reflect.Field javaField = StableFieldTest.class.getDeclaredField(name); + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) metaAccess.lookupJavaField(javaField); + if (!field.isStable()) { + throw new AssertionError("Expected HotSpotResolvedJavaField.isStable() to return true for " + javaField); + } + } + } +} From bb8ef1b3c61ddf39814dbc8eee214a347fdc567d Mon Sep 17 00:00:00 2001 From: Yuji Kubota Date: Fri, 11 Mar 2016 09:27:56 +0100 Subject: [PATCH 289/311] 8151685: Fix the version of required jdk in configure help text Reviewed-by: erikj --- common/autoconf/generated-configure.sh | 6 +++--- common/autoconf/help.m4 | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 35744afa3fe..58beee04e52 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4005,7 +4005,7 @@ apt_help() { devkit) PKGHANDLER_COMMAND="sudo apt-get install build-essential" ;; openjdk) - PKGHANDLER_COMMAND="sudo apt-get install openjdk-7-jdk" ;; + PKGHANDLER_COMMAND="sudo apt-get install openjdk-8-jdk" ;; alsa) PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; cups) @@ -4026,7 +4026,7 @@ yum_help() { devkit) PKGHANDLER_COMMAND="sudo yum groupinstall \"Development Tools\"" ;; openjdk) - PKGHANDLER_COMMAND="sudo yum install java-1.7.0-openjdk" ;; + PKGHANDLER_COMMAND="sudo yum install java-1.8.0-openjdk-devel" ;; alsa) PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; cups) @@ -4862,7 +4862,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1457518447 +DATE_WHEN_GENERATED=1457684806 ############################################################################### # diff --git a/common/autoconf/help.m4 b/common/autoconf/help.m4 index e266dbf414b..d0892c56256 100644 --- a/common/autoconf/help.m4 +++ b/common/autoconf/help.m4 @@ -106,7 +106,7 @@ apt_help() { devkit) PKGHANDLER_COMMAND="sudo apt-get install build-essential" ;; openjdk) - PKGHANDLER_COMMAND="sudo apt-get install openjdk-7-jdk" ;; + PKGHANDLER_COMMAND="sudo apt-get install openjdk-8-jdk" ;; alsa) PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; cups) @@ -127,7 +127,7 @@ yum_help() { devkit) PKGHANDLER_COMMAND="sudo yum groupinstall \"Development Tools\"" ;; openjdk) - PKGHANDLER_COMMAND="sudo yum install java-1.7.0-openjdk" ;; + PKGHANDLER_COMMAND="sudo yum install java-1.8.0-openjdk-devel" ;; alsa) PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; cups) From a261b38d274a7938eee27abae1f6369f179a77aa Mon Sep 17 00:00:00 2001 From: Srinivas Dama Date: Fri, 11 Mar 2016 11:35:20 +0100 Subject: [PATCH 290/311] 8138906: [TEST_BUG] Test test/script/trusted/JDK-8087292.js intermittently fails Reviewed-by: hannesw, mhaupt --- nashorn/test/script/trusted/JDK-8087292.js | 50 ++++++++++--- nashorn/test/script/trusted/JDK-util.js | 85 ++++++++++++++++++++++ 2 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 nashorn/test/script/trusted/JDK-util.js diff --git a/nashorn/test/script/trusted/JDK-8087292.js b/nashorn/test/script/trusted/JDK-8087292.js index 41869ed68dc..fec9efb37c4 100644 --- a/nashorn/test/script/trusted/JDK-8087292.js +++ b/nashorn/test/script/trusted/JDK-8087292.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -29,26 +29,58 @@ * @run */ +load(__DIR__ + "JDK-util.js") + +var jHomePath = System.getenv("JAVA_HOME") +var jLauncher = "${jHomePath}/bin/java" +var altjLauncher = which('java') + +if (windows) { + if(winCyg) { + jLauncher = "${jHomePath}" + "/bin/java.exe" + jLauncher = cygpath(jLauncher,outPath.windows) + } + else { + jLauncher = "${jHomePath}" + "\\bin\\java.exe" + altjLauncher = which('java.exe') + altjLauncher = cygpath(altjLauncher,outPath.windows) + } +} + +function exists(f) { + return Files.exists(Paths.get(f)) +} + +var javaLauncher = exists(jLauncher) ? jLauncher : altjLauncher + + +if (!exists(javaLauncher)) { + throw "no java launcher found; tried ${jLauncher} and ${altjLauncher}" +} + function tryExec() { try { - `java` + $EXEC("${javaLauncher}") } catch (e) { - print(e); + print(e) } // make sure we got non-zero ("failure") exit code! if ($EXIT == 0) { - print("Error: expected $EXIT code to be non-zero"); + print("Error: expected $EXIT code to be non-zero") } } +//convert windows paths to cygwin +if (windows) + javaLauncher = (winCyg) ? cygpath(javaLauncher,outPath.mixed).trim() : cygpath(javaLauncher,outPath.windows).trim() // no exception now! -tryExec(); +tryExec() // turn on error with non-zero exit code -$ENV.JJS_THROW_ON_EXIT = "1"; -tryExec(); +$ENV.JJS_THROW_ON_EXIT = "1" +tryExec() // no exception after this -$ENV.JJS_THROW_ON_EXIT = "0"; -tryExec(); +$ENV.JJS_THROW_ON_EXIT = "0" +tryExec() diff --git a/nashorn/test/script/trusted/JDK-util.js b/nashorn/test/script/trusted/JDK-util.js new file mode 100644 index 00000000000..f2a118315ce --- /dev/null +++ b/nashorn/test/script/trusted/JDK-util.js @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * This file contains utility functions used by other tests. + * @subtest + */ + +var Files = Java.type('java.nio.file.Files'), + Paths = Java.type('java.nio.file.Paths'), + System = Java.type('java.lang.System') + +var File = java.io.File +var windows = System.getProperty("os.name").startsWith("Windows") +var winCyg = false + +var outPath = { + windows:0, //C:\dir + mixed:1 //C:/dir +} + +if (windows) { + //Is there any better way to diffrentiate between cygwin/command prompt on windows + var term = System.getenv("TERM") + winCyg = term ? true:false +} + +/** + * Returns which command is selected from PATH + * @param cmd name of the command searched from PATH + */ +function which(cmd) { + var path = System.getenv("PATH") + var st = new java.util.StringTokenizer(path, File.pathSeparator) + while (st.hasMoreTokens()) { + var file = new File(st.nextToken(), cmd) + if (file.exists()) { + return (file.getAbsolutePath()) + } + } +} + +/** + * Unix cygpath implementation + * Supports only two outputs,windows(C:\dir\) and mixed(C:/dir/) + */ +function cygpath(path,mode) { + + var newpath = path + if(path.startsWith("/cygdrive/")){ + var str = path.substring(10) + var index = str.indexOf('/',0) + var drv = str.substring(0,index) + var rstr = drv.toUpperCase() + ":" + newpath = str.replaceFirst(drv,rstr) + } + if (mode == outPath.windows) + return Paths.get(newpath).toString() + else { + newpath = newpath.replaceAll('\\\\','/') + return newpath + } + +} + From eee69db96dd84eda04f703719f25db4ccf36aa25 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 11 Mar 2016 13:00:33 +0100 Subject: [PATCH 291/311] 8151570: jtreg tests leave tty in bad state Use unsupported terminal when running tests, to avoid setting tty to a raw mode. Reviewed-by: rfield --- .../classes/jdk/internal/jshell/tool/ConsoleIOContext.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java index 53df5fe0221..d86319f7254 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java @@ -48,6 +48,7 @@ import java.util.function.Supplier; import jdk.internal.jline.NoInterruptUnixTerminal; import jdk.internal.jline.Terminal; import jdk.internal.jline.TerminalFactory; +import jdk.internal.jline.UnsupportedTerminal; import jdk.internal.jline.WindowsTerminal; import jdk.internal.jline.console.ConsoleReader; import jdk.internal.jline.console.KeyMap; @@ -68,7 +69,9 @@ class ConsoleIOContext extends IOContext { this.repl = repl; this.input = new StopDetectingInputStream(() -> repl.state.stop(), ex -> repl.hard("Error on input: %s", ex)); Terminal term; - if (System.getProperty("os.name").toLowerCase(Locale.US).contains(TerminalFactory.WINDOWS)) { + if (System.getProperty("test.jdk") != null) { + term = new UnsupportedTerminal(); + } else if (System.getProperty("os.name").toLowerCase(Locale.US).contains(TerminalFactory.WINDOWS)) { term = new JShellWindowsTerminal(input); } else { term = new JShellUnixTerminal(input); From 9566de29293818419aa29e305132770fe33aa07f Mon Sep 17 00:00:00 2001 From: Abhijit Roy Date: Fri, 11 Mar 2016 18:35:26 +0530 Subject: [PATCH 292/311] 8151065: Typo in javax.naming.CompoundName Reviewed-by: vinnie, prappo --- .../java.naming/share/classes/javax/naming/CompoundName.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java b/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java index a7f43a095e3..aa4b4eb252c 100644 --- a/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java +++ b/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java @@ -82,7 +82,7 @@ import java.util.Properties; * attribute-value-assertions when specifying multiple attribute/value * pairs. (e.g. "," in age=65,gender=male). *

          jndi.syntax.separator.typeval - *
          If present, specifies the string that separators attribute + *
          If present, specifies the string that separates attribute * from value (e.g. "=" in "age=65") * * These properties are interpreted according to the following rules: From 781cae322ee663b62e229f6a837d6db8200aaaa6 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 11 Mar 2016 10:06:12 -0800 Subject: [PATCH 293/311] 8151679: Mark SignatureOffsets.java as intermittently failing Reviewed-by: xuelei --- jdk/test/sun/security/mscapi/SignatureOffsets.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/test/sun/security/mscapi/SignatureOffsets.java b/jdk/test/sun/security/mscapi/SignatureOffsets.java index 4c710396840..128cc00ca04 100644 --- a/jdk/test/sun/security/mscapi/SignatureOffsets.java +++ b/jdk/test/sun/security/mscapi/SignatureOffsets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -28,7 +28,7 @@ import java.security.SignatureException; /* * @test * @bug 8050374 - * @key randomness + * @key randomness intermittent * @summary This test validates signature verification * Signature.verify(byte[], int, int). The test uses RandomFactory to * get random set of clear text data to sign. After the signature From 2fc3f9915c507fa9019bc971d568ebc46b378e6c Mon Sep 17 00:00:00 2001 From: Abhijit Roy Date: Fri, 11 Mar 2016 12:53:10 -0500 Subject: [PATCH 294/311] 8151063: Typo in java.lang.invoke.StringConcatFactory javadoc Reviewed-by: prappo, rriggs --- .../share/classes/java/lang/invoke/StringConcatFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 5fb5277e798..9a4cecdc561 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -91,7 +91,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; * can call with more than 255 slots. This limits the number of static and * dynamic arguments one can pass to bootstrap method. Since there are potential * concatenation strategies that use {@code MethodHandle} combinators, we need - * to reserve a few empty slots on the parameter lists to to capture the + * to reserve a few empty slots on the parameter lists to capture the * temporal results. This is why bootstrap methods in this factory do not accept * more than 200 argument slots. Users requiring more than 200 argument slots in * concatenation are expected to split the large concatenation in smaller From 59eca614db537db2488b79c2eb8613b4fd615a27 Mon Sep 17 00:00:00 2001 From: Jamil Nimeh Date: Fri, 11 Mar 2016 10:54:42 -0800 Subject: [PATCH 295/311] 8132942: ServerHandshaker should not throw SSLHandshakeException when CertificateStatus constructor is called with invalid arguments Performs argument checking on inputs to the CertificateStatus constructor in order to eliminate the need for exception processing. Also pulls stapling processing logic out to its own method. Reviewed-by: xuelei --- .../sun/security/ssl/HandshakeMessage.java | 10 +- .../sun/security/ssl/ServerHandshaker.java | 239 ++++++++++-------- 2 files changed, 141 insertions(+), 108 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java index 86c72bac38a..b49723aa462 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, 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 @@ -700,7 +700,7 @@ static final class CertificateStatus extends HandshakeMessage * OCSP response data is provided. */ CertificateStatus(StatusRequestType type, X509Certificate[] chain, - Map responses) throws SSLException { + Map responses) { statusType = type; encodedResponsesLen = 0; encodedResponses = new ArrayList<>(chain.length); @@ -715,7 +715,7 @@ static final class CertificateStatus extends HandshakeMessage encodedResponses.add(respDER); encodedResponsesLen = 3 + respDER.length; } else { - throw new SSLHandshakeException("Zero-length or null " + + throw new IllegalArgumentException("Zero-length or null " + "OCSP Response"); } } else if (statusType == StatusRequestType.OCSP_MULTI) { @@ -732,8 +732,8 @@ static final class CertificateStatus extends HandshakeMessage } } } else { - throw new SSLHandshakeException("Unsupported StatusResponseType: " + - statusType); + throw new IllegalArgumentException( + "Unsupported StatusResponseType: " + statusType); } } diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java index eb3484c6c4b..a4c119faf25 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java @@ -36,7 +36,6 @@ import java.security.spec.ECParameterSpec; import java.math.BigInteger; import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.*; import sun.security.action.GetLongAction; @@ -67,7 +66,6 @@ final class ServerHandshaker extends Handshaker { // our authentication info private X509Certificate[] certs; - private Map responseMap; private PrivateKey privateKey; private Object serviceCreds; @@ -118,7 +116,6 @@ final class ServerHandshaker extends Handshaker { LegacyAlgorithmConstraints.PROPERTY_TLS_LEGACY_ALGS, new SSLAlgorithmDecomposer()); - private boolean staplingActive = false; private long statusRespTimeout; static { @@ -578,16 +575,6 @@ final class ServerHandshaker extends Handshaker { } } - // Check if the client has asserted the status_request[_v2] extension(s) - CertStatusReqExtension statReqExt = (CertStatusReqExtension) - mesg.extensions.get(ExtensionType.EXT_STATUS_REQUEST); - CertStatusReqListV2Extension statReqExtV2 = - (CertStatusReqListV2Extension)mesg.extensions.get( - ExtensionType.EXT_STATUS_REQUEST_V2); - // Keep stapling active if at least one of the extensions has been set - staplingActive = sslContext.isStaplingEnabled(false) && - (statReqExt != null || statReqExtV2 != null); - /* * FIRST, construct the ServerHello using the options and priorities * from the ClientHello. Update the (pending) cipher spec as we do @@ -883,79 +870,17 @@ final class ServerHandshaker extends Handshaker { m1.extensions.add(maxFragLenExt); } - StatusRequestType statReqType = null; - StatusRequest statReqData = null; - if (staplingActive && !resumingSession) { - ExtensionType statusRespExt = ExtensionType.EXT_STATUS_REQUEST; - - // Determine which type of stapling we are doing and assert the - // proper extension in the server hello. - // Favor status_request_v2 over status_request and ocsp_multi - // over ocsp. - // If multiple ocsp or ocsp_multi types exist, select the first - // instance of a given type - if (statReqExtV2 != null) { // RFC 6961 stapling - statusRespExt = ExtensionType.EXT_STATUS_REQUEST_V2; - List reqItems = - statReqExtV2.getRequestItems(); - int ocspIdx = -1; - int ocspMultiIdx = -1; - for (int pos = 0; pos < reqItems.size(); pos++) { - CertStatusReqItemV2 item = reqItems.get(pos); - if (ocspIdx < 0 && item.getType() == - StatusRequestType.OCSP) { - ocspIdx = pos; - } else if (ocspMultiIdx < 0 && item.getType() == - StatusRequestType.OCSP_MULTI) { - ocspMultiIdx = pos; - } - } - if (ocspMultiIdx >= 0) { - statReqType = reqItems.get(ocspMultiIdx).getType(); - statReqData = reqItems.get(ocspMultiIdx).getRequest(); - } else if (ocspIdx >= 0) { - statReqType = reqItems.get(ocspIdx).getType(); - statReqData = reqItems.get(ocspIdx).getRequest(); - } else { - // Some unknown type. We will not do stapling for - // this connection since we cannot understand the - // requested type. - staplingActive = false; - } - } else { // RFC 6066 stapling - statReqType = StatusRequestType.OCSP; - statReqData = statReqExt.getRequest(); - } - - if (statReqType != null && statReqData != null) { - StatusResponseManager statRespMgr = - sslContext.getStatusResponseManager(); - if (statRespMgr != null) { - responseMap = statRespMgr.get(statReqType, statReqData, - certs, statusRespTimeout, TimeUnit.MILLISECONDS); - if (!responseMap.isEmpty()) { - // We now can safely assert status_request[_v2] in our - // ServerHello, and know for certain that we can provide - // responses back to this client for this connection. - if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST) { - m1.extensions.add(new CertStatusReqExtension()); - } else if (statusRespExt == - ExtensionType.EXT_STATUS_REQUEST_V2) { - m1.extensions.add( - new CertStatusReqListV2Extension()); - } - } - } else { - // This should not happen if stapling is active, but - // if lazy initialization of the StatusResponseManager - // doesn't occur we should turn off stapling. - if (debug != null && Debug.isOn("handshake")) { - System.out.println("Warning: lazy initialization " + - "of the StatusResponseManager failed. " + - "Stapling has been disabled."); - staplingActive = false; - } - } + StaplingParameters staplingParams = processStapling(mesg); + if (staplingParams != null) { + // We now can safely assert status_request[_v2] in our + // ServerHello, and know for certain that we can provide + // responses back to this client for this connection. + if (staplingParams.statusRespExt == + ExtensionType.EXT_STATUS_REQUEST) { + m1.extensions.add(new CertStatusReqExtension()); + } else if (staplingParams.statusRespExt == + ExtensionType.EXT_STATUS_REQUEST_V2) { + m1.extensions.add(new CertStatusReqListV2Extension()); } } @@ -1031,24 +956,15 @@ final class ServerHandshaker extends Handshaker { * supports status stapling and there is at least one response to * return to the client. */ - if (staplingActive && !responseMap.isEmpty()) { - try { - CertificateStatus csMsg = new CertificateStatus(statReqType, - certs, responseMap); - if (debug != null && Debug.isOn("handshake")) { - csMsg.print(System.out); - } - csMsg.write(output); - handshakeState.update(csMsg, resumingSession); - responseMap = null; - } catch (SSLException ssle) { - // We don't want the exception to be fatal, we just won't - // send the message if we fail on construction. - if (debug != null && Debug.isOn("handshake")) { - System.out.println("Failed during CertificateStatus " + - "construction: " + ssle); - } + if (staplingParams != null) { + CertificateStatus csMsg = new CertificateStatus( + staplingParams.statReqType, certs, + staplingParams.responseMap); + if (debug != null && Debug.isOn("handshake")) { + csMsg.print(System.out); } + csMsg.write(output); + handshakeState.update(csMsg, resumingSession); } /* @@ -2078,4 +1994,121 @@ final class ServerHandshaker extends Handshaker { session.setPeerCertificates(peerCerts); } + + private StaplingParameters processStapling(ClientHello mesg) { + StaplingParameters params = null; + ExtensionType ext; + StatusRequestType type = null; + StatusRequest req = null; + Map responses; + + // If this feature has not been enabled, then no more processing + // is necessary. Also we will only staple if we're doing a full + // handshake. + if (!sslContext.isStaplingEnabled(false) || resumingSession) { + return null; + } + + // Check if the client has asserted the status_request[_v2] extension(s) + CertStatusReqExtension statReqExt = (CertStatusReqExtension) + mesg.extensions.get(ExtensionType.EXT_STATUS_REQUEST); + CertStatusReqListV2Extension statReqExtV2 = + (CertStatusReqListV2Extension)mesg.extensions.get( + ExtensionType.EXT_STATUS_REQUEST_V2); + // Keep processing only if either status_request or status_request_v2 + // has been sent in the ClientHello. + if (statReqExt == null && statReqExtV2 == null) { + return null; + } + + // Determine which type of stapling we are doing and assert the + // proper extension in the server hello. + // Favor status_request_v2 over status_request and ocsp_multi + // over ocsp. + // If multiple ocsp or ocsp_multi types exist, select the first + // instance of a given type + ext = ExtensionType.EXT_STATUS_REQUEST; + if (statReqExtV2 != null) { // RFC 6961 stapling + ext = ExtensionType.EXT_STATUS_REQUEST_V2; + List reqItems = + statReqExtV2.getRequestItems(); + int ocspIdx = -1; + int ocspMultiIdx = -1; + for (int pos = 0; pos < reqItems.size(); pos++) { + CertStatusReqItemV2 item = reqItems.get(pos); + if (ocspIdx < 0 && item.getType() == + StatusRequestType.OCSP) { + ocspIdx = pos; + } else if (ocspMultiIdx < 0 && item.getType() == + StatusRequestType.OCSP_MULTI) { + ocspMultiIdx = pos; + } + } + if (ocspMultiIdx >= 0) { + type = reqItems.get(ocspMultiIdx).getType(); + req = reqItems.get(ocspMultiIdx).getRequest(); + } else if (ocspIdx >= 0) { + type = reqItems.get(ocspIdx).getType(); + req = reqItems.get(ocspIdx).getRequest(); + } + } else { // RFC 6066 stapling + type = StatusRequestType.OCSP; + req = statReqExt.getRequest(); + } + + // If, after walking through the extensions we were unable to + // find a suitable StatusRequest, then stapling is disabled. + // Both statReqType and statReqData must have been set to continue. + if (type == null || req == null) { + return null; + } + + // Get the OCSP responses from the StatusResponseManager + StatusResponseManager statRespMgr = + sslContext.getStatusResponseManager(); + if (statRespMgr != null) { + responses = statRespMgr.get(type, req, certs, statusRespTimeout, + TimeUnit.MILLISECONDS); + if (!responses.isEmpty()) { + // If this RFC 6066-style stapling (SSL cert only) then the + // response cannot be zero length + if (type == StatusRequestType.OCSP) { + byte[] respDER = responses.get(certs[0]); + if (respDER == null || respDER.length <= 0) { + return null; + } + } + params = new StaplingParameters(ext, type, req, responses); + } + } else { + // This should not happen, but if lazy initialization of the + // StatusResponseManager doesn't occur we should turn off stapling. + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Warning: lazy initialization " + + "of the StatusResponseManager failed. " + + "Stapling has been disabled."); + } + } + + return params; + } + + /** + * Inner class used to hold stapling parameters needed by the handshaker + * when stapling is active. + */ + private class StaplingParameters { + private final ExtensionType statusRespExt; + private final StatusRequestType statReqType; + private final StatusRequest statReqData; + private final Map responseMap; + + StaplingParameters(ExtensionType ext, StatusRequestType type, + StatusRequest req, Map responses) { + statusRespExt = ext; + statReqType = type; + statReqData = req; + responseMap = responses; + } + } } From f876e4bbd253ebb5658d9c5985caf615d3147206 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 11 Mar 2016 14:07:03 -0800 Subject: [PATCH 296/311] 8151691: [Findbugs]jdk.internal.math.FormattedFloatingDecimal.getExponent() may expose internal rep The reference to the internal array is never leaked via the public API but some internal API clarification is added. Reviewed-by: rriggs --- .../math/FormattedFloatingDecimal.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java b/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java index 0a560dc11e5..88cd1feaf8f 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java +++ b/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java @@ -106,10 +106,28 @@ public class FormattedFloatingDecimal{ return decExponentRounded - 1; } + /** + * Returns the mantissa as a {@code char[]}. Note that the returned value + * is a reference to the internal {@code char[]} containing the mantissa, + * therefore code invoking this method should not pass the return value to + * external code but should in that case make a copy. + * + * @return a reference to the internal {@code char[]} representing the + * mantissa. + */ public char[] getMantissa(){ return mantissa; } + /** + * Returns the exponent as a {@code char[]}. Note that the returned value + * is a reference to the internal {@code char[]} containing the exponent, + * therefore code invoking this method should not pass the return value to + * external code but should in that case make a copy. + * + * @return a reference to the internal {@code char[]} representing the + * exponent. + */ public char[] getExponent(){ return exponent; } From 5c93b2a1544a008bc9d8b5b6747de5536d610b02 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 21:22:48 +0200 Subject: [PATCH 297/311] Added tag jdk-9+107 for changeset 1c076468bf7d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c0b87cffe37..5b33e027053 100644 --- a/.hgtags +++ b/.hgtags @@ -349,3 +349,4 @@ f9bcdce2df26678c3fe468130b535c0342c69b89 jdk-9+99 086c682bd8c5f195c324f61e2c61fbcd0226d63b jdk-9+104 db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105 6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106 +1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107 From 5bad9dfc3755bf6e44b0f606373ba7b5dfb42277 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 21:24:15 +0200 Subject: [PATCH 298/311] Added tag jdk-9+108 for changeset 257b579d8132 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 5b33e027053..989f02b425a 100644 --- a/.hgtags +++ b/.hgtags @@ -350,3 +350,4 @@ f9bcdce2df26678c3fe468130b535c0342c69b89 jdk-9+99 db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105 6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106 1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107 +257b579d813201682931d6b42f0445ffe5b4210d jdk-9+108 From 96678b62c680977b1cbc6932a7702f6d1657b52b Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 21:25:36 +0200 Subject: [PATCH 299/311] Added tag jdk-9+109 for changeset c870cb782aca --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 989f02b425a..96eac58d20e 100644 --- a/.hgtags +++ b/.hgtags @@ -351,3 +351,4 @@ db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105 6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106 1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107 257b579d813201682931d6b42f0445ffe5b4210d jdk-9+108 +c870cb782aca71093d2584376f27f0cfbfec0e3a jdk-9+109 From b4e4244a32fc256ee7841034f904a67127a67473 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 14 Mar 2016 12:35:44 +0300 Subject: [PATCH 300/311] 8139247: Improper locking of MethodData::_extra_data_lock Reviewed-by: dholmes, roland, dcubed --- hotspot/src/share/vm/ci/ciMethodData.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciMethodData.cpp b/hotspot/src/share/vm/ci/ciMethodData.cpp index 7aaf9bdf2c4..0ede3dfc31e 100644 --- a/hotspot/src/share/vm/ci/ciMethodData.cpp +++ b/hotspot/src/share/vm/ci/ciMethodData.cpp @@ -81,7 +81,7 @@ ciMethodData::ciMethodData() : ciMetadata(NULL) { void ciMethodData::load_extra_data() { MethodData* mdo = get_MethodData(); - MutexLocker(mdo->extra_data_lock()); + MutexLocker ml(mdo->extra_data_lock()); // speculative trap entries also hold a pointer to a Method so need to be translated DataLayout* dp_src = mdo->extra_data_base(); @@ -103,16 +103,13 @@ void ciMethodData::load_extra_data() { switch(tag) { case DataLayout::speculative_trap_data_tag: { - ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst); - SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src); - - data_dst->translate_from(data_src); - -#ifdef ASSERT - SpeculativeTrapData* data_src2 = new SpeculativeTrapData(dp_src); - assert(data_src2->method() == data_src->method() && data_src2->bci() == data_src->bci(), "entries changed while translating"); -#endif + ciSpeculativeTrapData data_dst(dp_dst); + SpeculativeTrapData data_src(dp_src); + { // During translation a safepoint can happen or VM lock can be taken (e.g., Compile_lock). + MutexUnlocker ml(mdo->extra_data_lock()); + data_dst.translate_from(&data_src); + } break; } case DataLayout::bit_data_tag: @@ -120,9 +117,11 @@ void ciMethodData::load_extra_data() { case DataLayout::no_tag: case DataLayout::arg_info_data_tag: // An empty slot or ArgInfoData entry marks the end of the trap data - return; + { + return; // Need a block to avoid SS compiler bug + } default: - fatal("bad tag = %d", dp_dst->tag()); + fatal("bad tag = %d", tag); } } } From 28cf824b6056cc66aa7b1d0f86078ae667813ba3 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 14 Mar 2016 12:35:48 +0300 Subject: [PATCH 301/311] 8150320: C1: Illegal bci in debug info for MH::linkTo* methods Reviewed-by: kvn, dlong --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 4 ++-- hotspot/src/share/vm/code/debugInfoRec.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index b2766898d71..d8643aefef7 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -3942,7 +3942,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { - ValueStack* state_before = state()->copy_for_parsing(); + ValueStack* state_before = copy_state_before(); vmIntrinsics::ID iid = callee->intrinsic_id(); switch (iid) { case vmIntrinsics::_invokeBasic: @@ -4032,7 +4032,7 @@ bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)); break; } - set_state(state_before); + set_state(state_before->copy_for_parsing()); return false; } diff --git a/hotspot/src/share/vm/code/debugInfoRec.cpp b/hotspot/src/share/vm/code/debugInfoRec.cpp index 36c35a92f55..b026e5a645b 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.cpp +++ b/hotspot/src/share/vm/code/debugInfoRec.cpp @@ -369,7 +369,6 @@ void DebugInformationRecorder::describe_scope(int pc_offset, assert(method == NULL || (method->is_native() && bci == 0) || (!method->is_native() && 0 <= bci && bci < method->code_size()) || - (method->is_compiled_lambda_form() && bci == -99) || // this might happen in C1 bci == -1, "illegal bci"); // serialize the locals/expressions/monitors From ffdd79f89ca39cf67fbd9506b7fe65a08fbeeac4 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 14 Mar 2016 12:35:48 +0300 Subject: [PATCH 302/311] 8141420: Compiler runtime entries don't hold Klass* from being GCed Reviewed-by: kvn, coleenp --- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 3 +++ hotspot/src/share/vm/jvmci/jvmciRuntime.cpp | 3 +++ hotspot/src/share/vm/opto/runtime.cpp | 23 +++++++++++---------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 92c721575d0..70c4fc3304f 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -335,6 +335,7 @@ JRT_ENTRY(void, Runtime1::new_instance(JavaThread* thread, Klass* klass)) NOT_PRODUCT(_new_instance_slowcase_cnt++;) assert(klass->is_klass(), "not a class"); + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive instanceKlassHandle h(thread, klass); h->check_valid_for_instantiation(true, CHECK); // make sure klass is initialized @@ -370,6 +371,7 @@ JRT_ENTRY(void, Runtime1::new_object_array(JavaThread* thread, Klass* array_klas // anymore after new_objArray() and no GC can happen before. // (This may have to change if this code changes!) assert(array_klass->is_klass(), "not a class"); + Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); objArrayOop obj = oopFactory::new_objArray(elem_klass, length, CHECK); thread->set_vm_result(obj); @@ -386,6 +388,7 @@ JRT_ENTRY(void, Runtime1::new_multi_array(JavaThread* thread, Klass* klass, int assert(klass->is_klass(), "not a class"); assert(rank >= 1, "rank must be nonzero"); + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); thread->set_vm_result(obj); JRT_END diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp index 19aff9ed1c9..367afbf36e1 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp @@ -103,6 +103,7 @@ static void deopt_caller() { JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance(JavaThread* thread, Klass* klass)) JRT_BLOCK; assert(klass->is_klass(), "not a class"); + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive instanceKlassHandle h(thread, klass); h->check_valid_for_instantiation(true, CHECK); // make sure klass is initialized @@ -128,6 +129,7 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array(JavaThread* thread, Klass* array_k BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type(); obj = oopFactory::new_typeArray(elt_type, length, CHECK); } else { + Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); obj = oopFactory::new_objArray(elem_klass, length, CHECK); } @@ -171,6 +173,7 @@ void JVMCIRuntime::new_store_pre_barrier(JavaThread* thread) { JRT_ENTRY(void, JVMCIRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims)) assert(klass->is_klass(), "not a class"); assert(rank >= 1, "rank must be nonzero"); + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); thread->set_vm_result(obj); JRT_END diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index 1d6bdfb6230..dff0da6161b 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -220,22 +220,17 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, JavaThread* thre // These checks are cheap to make and support reflective allocation. int lh = klass->layout_helper(); - if (Klass::layout_helper_needs_slow_path(lh) - || !InstanceKlass::cast(klass)->is_initialized()) { - KlassHandle kh(THREAD, klass); - kh->check_valid_for_instantiation(false, THREAD); + if (Klass::layout_helper_needs_slow_path(lh) || !InstanceKlass::cast(klass)->is_initialized()) { + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive + klass->check_valid_for_instantiation(false, THREAD); if (!HAS_PENDING_EXCEPTION) { - InstanceKlass::cast(kh())->initialize(THREAD); - } - if (!HAS_PENDING_EXCEPTION) { - klass = kh(); - } else { - klass = NULL; + InstanceKlass::cast(klass)->initialize(THREAD); } } - if (klass != NULL) { + if (!HAS_PENDING_EXCEPTION) { // Scavenge and allocate an instance. + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive oop result = InstanceKlass::cast(klass)->allocate_instance(THREAD); thread->set_vm_result(result); @@ -275,6 +270,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, JavaT // Although the oopFactory likes to work with the elem_type, // the compiler prefers the array_type, since it must already have // that latter value in hand for the fast path. + Handle holder(THREAD, array_type->klass_holder()); // keep the array klass alive Klass* elem_type = ObjArrayKlass::cast(array_type)->element_klass(); result = oopFactory::new_objArray(elem_type, len, THREAD); } @@ -353,6 +349,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray2_C(Klass* elem_type, int len1, int l jint dims[2]; dims[0] = len1; dims[1] = len2; + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(2, dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); @@ -369,6 +366,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray3_C(Klass* elem_type, int len1, int l dims[0] = len1; dims[1] = len2; dims[2] = len3; + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(3, dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); @@ -386,6 +384,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray4_C(Klass* elem_type, int len1, int l dims[1] = len2; dims[2] = len3; dims[3] = len4; + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(4, dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); @@ -404,6 +403,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray5_C(Klass* elem_type, int len1, int l dims[2] = len3; dims[3] = len4; dims[4] = len5; + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); @@ -421,6 +421,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(Klass* elem_type, arrayOopDesc* d jint *c_dims = NEW_RESOURCE_ARRAY(jint, len); Copy::conjoint_jints_atomic(j_dims, c_dims, len); + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); From 6ea5772a9b57ea29178fcb8dc321b82e5539de58 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Mon, 14 Mar 2016 12:35:52 +0300 Subject: [PATCH 303/311] 8143407: C1: @Stable array support Reviewed-by: twisti --- hotspot/src/share/vm/c1/c1_Canonicalizer.cpp | 33 ++++++++- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 73 ++++++++++--------- hotspot/src/share/vm/c1/c1_GraphBuilder.hpp | 1 + hotspot/src/share/vm/c1/c1_ValueType.hpp | 16 ++++ .../compiler/stable/StableConfiguration.java | 44 ----------- .../compiler/stable/TestStableBoolean.java | 51 +++++++------ .../test/compiler/stable/TestStableByte.java | 53 +++++++------- .../test/compiler/stable/TestStableChar.java | 53 +++++++------- .../compiler/stable/TestStableDouble.java | 53 +++++++------- .../test/compiler/stable/TestStableFloat.java | 53 +++++++------- .../test/compiler/stable/TestStableInt.java | 53 +++++++------- .../test/compiler/stable/TestStableLong.java | 53 +++++++------- .../compiler/stable/TestStableObject.java | 53 +++++++------- .../test/compiler/stable/TestStableShort.java | 53 +++++++------- 14 files changed, 321 insertions(+), 321 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp index d70a769e93b..c4a084a4518 100644 --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp @@ -257,7 +257,38 @@ void Canonicalizer::do_ArrayLength (ArrayLength* x) { } } -void Canonicalizer::do_LoadIndexed (LoadIndexed* x) {} +void Canonicalizer::do_LoadIndexed (LoadIndexed* x) { + StableArrayConstant* array = x->array()->type()->as_StableArrayConstant(); + IntConstant* index = x->index()->type()->as_IntConstant(); + + assert(array == NULL || FoldStableValues, "not enabled"); + + // Constant fold loads from stable arrays. + if (array != NULL && index != NULL) { + jint idx = index->value(); + if (idx < 0 || idx >= array->value()->length()) { + // Leave the load as is. The range check will handle it. + return; + } + + ciConstant field_val = array->value()->element_value(idx); + if (!field_val.is_null_or_zero()) { + jint dimension = array->dimension(); + assert(dimension <= array->value()->array_type()->dimension(), "inconsistent info"); + ValueType* value = NULL; + if (dimension > 1) { + // Preserve information about the dimension for the element. + assert(field_val.as_object()->is_array(), "not an array"); + value = new StableArrayConstant(field_val.as_object()->as_array(), dimension - 1); + } else { + assert(dimension == 1, "sanity"); + value = as_ValueType(field_val); + } + set_canonical(new Constant(value)); + } + } +} + void Canonicalizer::do_StoreIndexed (StoreIndexed* x) { // If a value is going to be stored into a field or array some of // the conversions emitted by javac are unneeded because the fields diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index d8643aefef7..c3483a5fe00 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1519,6 +1519,29 @@ void GraphBuilder::method_return(Value x) { append(new Return(x)); } +Value GraphBuilder::make_constant(ciConstant field_value, ciField* field) { + BasicType field_type = field_value.basic_type(); + ValueType* value = as_ValueType(field_value); + + // Attach dimension info to stable arrays. + if (FoldStableValues && + field->is_stable() && field_type == T_ARRAY && !field_value.is_null_or_zero()) { + ciArray* array = field_value.as_object()->as_array(); + jint dimension = field->type()->as_array_klass()->dimension(); + value = new StableArrayConstant(array, dimension); + } + + switch (field_type) { + case T_ARRAY: + case T_OBJECT: + if (field_value.as_object()->should_be_constant()) { + return new Constant(value); + } + return NULL; // Not a constant. + default: + return new Constant(value); + } +} void GraphBuilder::access_field(Bytecodes::Code code) { bool will_link; @@ -1563,22 +1586,13 @@ void GraphBuilder::access_field(Bytecodes::Code code) { switch (code) { case Bytecodes::_getstatic: { // check for compile-time constants, i.e., initialized static final fields - Instruction* constant = NULL; + Value constant = NULL; if (field->is_constant() && !PatchALot) { - ciConstant field_val = field->constant_value(); - BasicType field_type = field_val.basic_type(); - switch (field_type) { - case T_ARRAY: - case T_OBJECT: - if (field_val.as_object()->should_be_constant()) { - constant = new Constant(as_ValueType(field_val)); - } - break; - - default: - constant = new Constant(as_ValueType(field_val)); - } + ciConstant field_value = field->constant_value(); // Stable static fields are checked for non-default values in ciField::initialize_from(). + assert(!field->is_stable() || !field_value.is_null_or_zero(), + "stable static w/ default value shouldn't be a constant"); + constant = make_constant(field_value, field); } if (constant != NULL) { push(type, append(constant)); @@ -1591,38 +1605,29 @@ void GraphBuilder::access_field(Bytecodes::Code code) { } break; } - case Bytecodes::_putstatic: - { Value val = pop(type); - if (state_before == NULL) { - state_before = copy_state_for_exception(); - } - append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); + case Bytecodes::_putstatic: { + Value val = pop(type); + if (state_before == NULL) { + state_before = copy_state_for_exception(); } + append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); break; + } case Bytecodes::_getfield: { // Check for compile-time constants, i.e., trusted final non-static fields. - Instruction* constant = NULL; + Value constant = NULL; obj = apop(); ObjectType* obj_type = obj->type()->as_ObjectType(); if (obj_type->is_constant() && !PatchALot) { ciObject* const_oop = obj_type->constant_value(); if (!const_oop->is_null_object() && const_oop->is_loaded()) { if (field->is_constant()) { - ciConstant field_val = field->constant_value_of(const_oop); - BasicType field_type = field_val.basic_type(); - switch (field_type) { - case T_ARRAY: - case T_OBJECT: - if (field_val.as_object()->should_be_constant()) { - constant = new Constant(as_ValueType(field_val)); - } - break; - default: - constant = new Constant(as_ValueType(field_val)); - } - if (FoldStableValues && field->is_stable() && field_val.is_null_or_zero()) { + ciConstant field_value = field->constant_value_of(const_oop); + if (FoldStableValues && field->is_stable() && field_value.is_null_or_zero()) { // Stable field with default value can't be constant. constant = NULL; + } else { + constant = make_constant(field_value, field); } } else { // For CallSite objects treat the target field as a compile time constant. diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp index 4fb1e184d6d..20bed2b164d 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp @@ -276,6 +276,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { void iterate_all_blocks(bool start_in_current_block_for_inlining = false); Dependencies* dependency_recorder() const; // = compilation()->dependencies() bool direct_compare(ciKlass* k); + Value make_constant(ciConstant value, ciField* field); void kill_all(); diff --git a/hotspot/src/share/vm/c1/c1_ValueType.hpp b/hotspot/src/share/vm/c1/c1_ValueType.hpp index 291dd2386d3..a5e901523ef 100644 --- a/hotspot/src/share/vm/c1/c1_ValueType.hpp +++ b/hotspot/src/share/vm/c1/c1_ValueType.hpp @@ -45,6 +45,7 @@ class ObjectType; class ObjectConstant; class ArrayType; class ArrayConstant; +class StableArrayConstant; class InstanceType; class InstanceConstant; class MetadataType; @@ -168,6 +169,7 @@ class ValueType: public CompilationResourceObj { virtual MethodConstant* as_MethodConstant() { return NULL; } virtual MethodDataConstant* as_MethodDataConstant() { return NULL; } virtual ArrayConstant* as_ArrayConstant() { return NULL; } + virtual StableArrayConstant* as_StableArrayConstant() { return NULL; } virtual AddressConstant* as_AddressConstant() { return NULL; } // type operations @@ -355,6 +357,20 @@ class ArrayConstant: public ArrayType { virtual ciType* exact_type() const; }; +class StableArrayConstant: public ArrayConstant { + private: + jint _dimension; + + public: + StableArrayConstant(ciArray* value, jint dimension) : ArrayConstant(value) { + assert(dimension > 0, "not a stable array"); + _dimension = dimension; + } + + jint dimension() const { return _dimension; } + + virtual StableArrayConstant* as_StableArrayConstant() { return this; } +}; class InstanceType: public ObjectType { public: diff --git a/hotspot/test/compiler/stable/StableConfiguration.java b/hotspot/test/compiler/stable/StableConfiguration.java index be69081640c..c224b6db151 100644 --- a/hotspot/test/compiler/stable/StableConfiguration.java +++ b/hotspot/test/compiler/stable/StableConfiguration.java @@ -31,54 +31,10 @@ import sun.hotspot.WhiteBox; public class StableConfiguration { static final WhiteBox WB = WhiteBox.getWhiteBox(); static final boolean isStableEnabled; - static final boolean isServerWithStable; static { Boolean value = WB.getBooleanVMFlag("FoldStableValues"); isStableEnabled = (value == null ? false : value); - isServerWithStable = isStableEnabled && get(); System.out.println("@Stable: " + (isStableEnabled ? "enabled" : "disabled")); - System.out.println("Server Compiler: " + get()); } - - // The method 'get' below returns true if the method is server compiled - // and is used by the Stable tests to determine whether methods in - // general are being server compiled or not as the -XX:+FoldStableValues - // option is only applicable to -server. - // - // On aarch64 we DeOptimize when patching. This means that when the - // method is compiled as a result of -Xcomp it DeOptimizes immediately. - // The result is that getMethodCompilationLevel returns 0. This means - // the method returns true based on java.vm.name. - // - // However when the tests are run with -XX:+TieredCompilation and - // -XX:TieredStopAtLevel=1 this fails because methods will always - // be client compiled. - // - // Solution is to add a simple method 'get1' which should never be - // DeOpted and use that to determine the compilation level instead. - static void get1() { - } - - - - // ::get() is among immediately compiled methods. - static boolean get() { - try { - get1(); - Method m = StableConfiguration.class.getDeclaredMethod("get1"); - int level = WB.getMethodCompilationLevel(m); - if (level > 0) { - return (level == 4); - } else { - String javaVM = System.getProperty("java.vm.name", ""); - if (javaVM.contains("Server")) return true; - if (javaVM.contains("Client")) return false; - throw new Error("Unknown VM type: "+javaVM); - } - } catch (NoSuchMethodException e) { - throw new Error(e); - } - } - } diff --git a/hotspot/test/compiler/stable/TestStableBoolean.java b/hotspot/test/compiler/stable/TestStableBoolean.java index 168ddf48da7..e9d2e1eb703 100644 --- a/hotspot/test/compiler/stable/TestStableBoolean.java +++ b/hotspot/test/compiler/stable/TestStableBoolean.java @@ -87,8 +87,7 @@ import jdk.internal.vm.annotation.Stable; import java.lang.reflect.InvocationTargetException; public class TestStableBoolean { - static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,14 +208,14 @@ public class TestStableBoolean { c.v = new boolean[1]; c.v[0] = true; boolean val1 = get(); c.v[0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); } { c.v = new boolean[20]; c.v[10] = true; boolean val1 = get1(); c.v[10] = false; boolean val2 = get1(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); } { @@ -241,19 +240,19 @@ public class TestStableBoolean { c.v = new boolean[1][1]; c.v[0][0] = true; boolean val1 = get(); c.v[0][0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); c.v = new boolean[1][1]; c.v[0][0] = false; boolean val3 = get(); - assertEquals(val3, (isServerWithStable ? true : false)); + assertEquals(val3, (isStableEnabled ? true : false)); c.v[0] = new boolean[1]; c.v[0][0] = false; boolean val4 = get(); - assertEquals(val4, (isServerWithStable ? true : false)); + assertEquals(val4, (isStableEnabled ? true : false)); } { c.v = new boolean[1][1]; boolean[] val1 = get1(); c.v[0] = new boolean[1]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -279,28 +278,28 @@ public class TestStableBoolean { c.v = new boolean[1][1][1]; c.v[0][0][0] = true; boolean val1 = get(); c.v[0][0][0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); c.v = new boolean[1][1][1]; c.v[0][0][0] = false; boolean val3 = get(); - assertEquals(val3, (isServerWithStable ? true : false)); + assertEquals(val3, (isStableEnabled ? true : false)); c.v[0] = new boolean[1][1]; c.v[0][0][0] = false; boolean val4 = get(); - assertEquals(val4, (isServerWithStable ? true : false)); + assertEquals(val4, (isStableEnabled ? true : false)); c.v[0][0] = new boolean[1]; c.v[0][0][0] = false; boolean val5 = get(); - assertEquals(val5, (isServerWithStable ? true : false)); + assertEquals(val5, (isStableEnabled ? true : false)); } { c.v = new boolean[1][1][1]; boolean[] val1 = get1(); c.v[0][0] = new boolean[1]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1]; boolean[][] val1 = get2(); c.v[0] = new boolean[1][1]; boolean[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -327,37 +326,37 @@ public class TestStableBoolean { c.v = new boolean[1][1][1][1]; c.v[0][0][0][0] = true; boolean val1 = get(); c.v[0][0][0][0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); c.v = new boolean[1][1][1][1]; c.v[0][0][0][0] = false; boolean val3 = get(); - assertEquals(val3, (isServerWithStable ? true : false)); + assertEquals(val3, (isStableEnabled ? true : false)); c.v[0] = new boolean[1][1][1]; c.v[0][0][0][0] = false; boolean val4 = get(); - assertEquals(val4, (isServerWithStable ? true : false)); + assertEquals(val4, (isStableEnabled ? true : false)); c.v[0][0] = new boolean[1][1]; c.v[0][0][0][0] = false; boolean val5 = get(); - assertEquals(val5, (isServerWithStable ? true : false)); + assertEquals(val5, (isStableEnabled ? true : false)); c.v[0][0][0] = new boolean[1]; c.v[0][0][0][0] = false; boolean val6 = get(); - assertEquals(val6, (isServerWithStable ? true : false)); + assertEquals(val6, (isStableEnabled ? true : false)); } { c.v = new boolean[1][1][1][1]; boolean[] val1 = get1(); c.v[0][0][0] = new boolean[1]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1][1]; boolean[][] val1 = get2(); c.v[0][0] = new boolean[1][1]; boolean[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1][1]; boolean[][][] val1 = get3(); c.v[0] = new boolean[1][1][1]; boolean[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -420,7 +419,7 @@ public class TestStableBoolean { c.v = new boolean[1][1]; c.v[0] = new boolean[0]; boolean[] val1 = get1(); c.v[0] = new boolean[0]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -456,14 +455,14 @@ public class TestStableBoolean { c.v = new boolean[1][1][1]; c.v[0][0] = new boolean[0]; boolean[] val1 = get1(); c.v[0][0] = new boolean[0]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1]; c.v[0] = new boolean[0][0]; boolean[][] val1 = get2(); c.v[0] = new boolean[0][0]; boolean[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -598,7 +597,7 @@ public class TestStableBoolean { elem.a = false; boolean val3 = get(); boolean val4 = get1(); assertEquals(val1, true); - assertEquals(val3, (isServerWithStable ? true : false)); + assertEquals(val3, (isStableEnabled ? true : false)); assertEquals(val2, true); assertEquals(val4, false); diff --git a/hotspot/test/compiler/stable/TestStableByte.java b/hotspot/test/compiler/stable/TestStableByte.java index 694205e8e55..ad3653f78be 100644 --- a/hotspot/test/compiler/stable/TestStableByte.java +++ b/hotspot/test/compiler/stable/TestStableByte.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableByte { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableByte { c.v = new byte[1]; c.v[0] = 1; byte val1 = get(); c.v[0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[1]; c.v[0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -220,10 +219,10 @@ public class TestStableByte { c.v = new byte[20]; c.v[10] = 1; byte val1 = get1(); c.v[10] = 2; byte val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[20]; c.v[10] = 3; byte val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -249,21 +248,21 @@ public class TestStableByte { c.v = new byte[1][1]; c.v[0][0] = 1; byte val1 = get(); c.v[0][0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[1][1]; c.v[0][0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new byte[1]; c.v[0][0] = 4; byte val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); } { c.v = new byte[1][1]; byte[] val1 = get1(); c.v[0] = new byte[1]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableByte { c.v = new byte[1][1][1]; c.v[0][0][0] = 1; byte val1 = get(); c.v[0][0][0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[1][1][1]; c.v[0][0][0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new byte[1][1]; c.v[0][0][0] = 4; byte val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new byte[1]; c.v[0][0][0] = 5; byte val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); } { c.v = new byte[1][1][1]; byte[] val1 = get1(); c.v[0][0] = new byte[1]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1]; byte[][] val1 = get2(); c.v[0] = new byte[1][1]; byte[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableByte { c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 1; byte val1 = get(); c.v[0][0][0][0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new byte[1][1][1]; c.v[0][0][0][0] = 4; byte val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new byte[1][1]; c.v[0][0][0][0] = 5; byte val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); c.v[0][0][0] = new byte[1]; c.v[0][0][0][0] = 6; byte val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 6)); } { c.v = new byte[1][1][1][1]; byte[] val1 = get1(); c.v[0][0][0] = new byte[1]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1][1]; byte[][] val1 = get2(); c.v[0][0] = new byte[1][1]; byte[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1][1]; byte[][][] val1 = get3(); c.v[0] = new byte[1][1][1]; byte[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -436,7 +435,7 @@ public class TestStableByte { c.v = new byte[1][1]; c.v[0] = new byte[0]; byte[] val1 = get1(); c.v[0] = new byte[0]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -472,14 +471,14 @@ public class TestStableByte { c.v = new byte[1][1][1]; c.v[0][0] = new byte[0]; byte[] val1 = get1(); c.v[0][0] = new byte[0]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1]; c.v[0] = new byte[0][0]; byte[][] val1 = get2(); c.v[0] = new byte[0][0]; byte[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -614,7 +613,7 @@ public class TestStableByte { elem.a = 2; byte val3 = get(); byte val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isServerWithStable ? 1 : 2)); + assertEquals(val3, (isStableEnabled ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); diff --git a/hotspot/test/compiler/stable/TestStableChar.java b/hotspot/test/compiler/stable/TestStableChar.java index d92dfb67c73..1fdcca19496 100644 --- a/hotspot/test/compiler/stable/TestStableChar.java +++ b/hotspot/test/compiler/stable/TestStableChar.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableChar { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableChar { c.v = new char[1]; c.v[0] = 'a'; char val1 = get(); c.v[0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[1]; c.v[0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); } @@ -220,10 +219,10 @@ public class TestStableChar { c.v = new char[20]; c.v[10] = 'a'; char val1 = get1(); c.v[10] = 'b'; char val2 = get1(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[20]; c.v[10] = 'c'; char val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); } @@ -249,21 +248,21 @@ public class TestStableChar { c.v = new char[1][1]; c.v[0][0] = 'a'; char val1 = get(); c.v[0][0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[1][1]; c.v[0][0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); c.v[0] = new char[1]; c.v[0][0] = 'd'; char val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'd')); } { c.v = new char[1][1]; char[] val1 = get1(); c.v[0] = new char[1]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableChar { c.v = new char[1][1][1]; c.v[0][0][0] = 'a'; char val1 = get(); c.v[0][0][0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[1][1][1]; c.v[0][0][0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); c.v[0] = new char[1][1]; c.v[0][0][0] = 'd'; char val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'd')); c.v[0][0] = new char[1]; c.v[0][0][0] = 'e'; char val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'e')); } { c.v = new char[1][1][1]; char[] val1 = get1(); c.v[0][0] = new char[1]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1]; char[][] val1 = get2(); c.v[0] = new char[1][1]; char[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableChar { c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'a'; char val1 = get(); c.v[0][0][0][0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); c.v[0] = new char[1][1][1]; c.v[0][0][0][0] = 'd'; char val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'd')); c.v[0][0] = new char[1][1]; c.v[0][0][0][0] = 'e'; char val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'e')); c.v[0][0][0] = new char[1]; c.v[0][0][0][0] = 'f'; char val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'f')); } { c.v = new char[1][1][1][1]; char[] val1 = get1(); c.v[0][0][0] = new char[1]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1][1]; char[][] val1 = get2(); c.v[0][0] = new char[1][1]; char[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1][1]; char[][][] val1 = get3(); c.v[0] = new char[1][1][1]; char[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableChar { c.v = new char[1][1]; c.v[0] = new char[0]; char[] val1 = get1(); c.v[0] = new char[0]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableChar { c.v = new char[1][1][1]; c.v[0][0] = new char[0]; char[] val1 = get1(); c.v[0][0] = new char[0]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1]; c.v[0] = new char[0][0]; char[][] val1 = get2(); c.v[0] = new char[0][0]; char[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableChar { elem.a = 'b'; char val3 = get(); char val4 = get1(); assertEquals(val1, 'a'); - assertEquals(val3, (isServerWithStable ? 'a' : 'b')); + assertEquals(val3, (isStableEnabled ? 'a' : 'b')); assertEquals(val2, 'a'); assertEquals(val4, 'b'); diff --git a/hotspot/test/compiler/stable/TestStableDouble.java b/hotspot/test/compiler/stable/TestStableDouble.java index 5e55a0f8597..770d25df10c 100644 --- a/hotspot/test/compiler/stable/TestStableDouble.java +++ b/hotspot/test/compiler/stable/TestStableDouble.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableDouble { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableDouble { c.v = new double[1]; c.v[0] = 1.0; double val1 = get(); c.v[0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[1]; c.v[0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); } @@ -220,10 +219,10 @@ public class TestStableDouble { c.v = new double[20]; c.v[10] = 1.0; double val1 = get1(); c.v[10] = 2.0; double val2 = get1(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[20]; c.v[10] = 3.0; double val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); } @@ -249,21 +248,21 @@ public class TestStableDouble { c.v = new double[1][1]; c.v[0][0] = 1.0; double val1 = get(); c.v[0][0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[1][1]; c.v[0][0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); c.v[0] = new double[1]; c.v[0][0] = 4.0; double val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 4.0)); } { c.v = new double[1][1]; double[] val1 = get1(); c.v[0] = new double[1]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableDouble { c.v = new double[1][1][1]; c.v[0][0][0] = 1.0; double val1 = get(); c.v[0][0][0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[1][1][1]; c.v[0][0][0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); c.v[0] = new double[1][1]; c.v[0][0][0] = 4.0; double val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 4.0)); c.v[0][0] = new double[1]; c.v[0][0][0] = 5.0; double val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 5.0)); } { c.v = new double[1][1][1]; double[] val1 = get1(); c.v[0][0] = new double[1]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1]; double[][] val1 = get2(); c.v[0] = new double[1][1]; double[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableDouble { c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 1.0; double val1 = get(); c.v[0][0][0][0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); c.v[0] = new double[1][1][1]; c.v[0][0][0][0] = 4.0; double val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 4.0)); c.v[0][0] = new double[1][1]; c.v[0][0][0][0] = 5.0; double val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 5.0)); c.v[0][0][0] = new double[1]; c.v[0][0][0][0] = 6.0; double val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 6.0)); } { c.v = new double[1][1][1][1]; double[] val1 = get1(); c.v[0][0][0] = new double[1]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1][1]; double[][] val1 = get2(); c.v[0][0] = new double[1][1]; double[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1][1]; double[][][] val1 = get3(); c.v[0] = new double[1][1][1]; double[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableDouble { c.v = new double[1][1]; c.v[0] = new double[0]; double[] val1 = get1(); c.v[0] = new double[0]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableDouble { c.v = new double[1][1][1]; c.v[0][0] = new double[0]; double[] val1 = get1(); c.v[0][0] = new double[0]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1]; c.v[0] = new double[0][0]; double[][] val1 = get2(); c.v[0] = new double[0][0]; double[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableDouble { elem.a = 2.0; double val3 = get(); double val4 = get1(); assertEquals(val1, 1.0); - assertEquals(val3, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val3, (isStableEnabled ? 1.0 : 2.0)); assertEquals(val2, 1.0); assertEquals(val4, 2.0); diff --git a/hotspot/test/compiler/stable/TestStableFloat.java b/hotspot/test/compiler/stable/TestStableFloat.java index 04acead22ef..d2f417c8ad3 100644 --- a/hotspot/test/compiler/stable/TestStableFloat.java +++ b/hotspot/test/compiler/stable/TestStableFloat.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableFloat { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableFloat { c.v = new float[1]; c.v[0] = 1.0F; float val1 = get(); c.v[0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[1]; c.v[0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); } @@ -220,10 +219,10 @@ public class TestStableFloat { c.v = new float[20]; c.v[10] = 1.0F; float val1 = get1(); c.v[10] = 2.0F; float val2 = get1(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[20]; c.v[10] = 3.0F; float val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); } @@ -249,21 +248,21 @@ public class TestStableFloat { c.v = new float[1][1]; c.v[0][0] = 1.0F; float val1 = get(); c.v[0][0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[1][1]; c.v[0][0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); c.v[0] = new float[1]; c.v[0][0] = 4.0F; float val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 4.0F)); } { c.v = new float[1][1]; float[] val1 = get1(); c.v[0] = new float[1]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableFloat { c.v = new float[1][1][1]; c.v[0][0][0] = 1.0F; float val1 = get(); c.v[0][0][0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[1][1][1]; c.v[0][0][0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); c.v[0] = new float[1][1]; c.v[0][0][0] = 4.0F; float val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 4.0F)); c.v[0][0] = new float[1]; c.v[0][0][0] = 5.0F; float val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 5.0F)); } { c.v = new float[1][1][1]; float[] val1 = get1(); c.v[0][0] = new float[1]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1]; float[][] val1 = get2(); c.v[0] = new float[1][1]; float[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableFloat { c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 1.0F; float val1 = get(); c.v[0][0][0][0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); c.v[0] = new float[1][1][1]; c.v[0][0][0][0] = 4.0F; float val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 4.0F)); c.v[0][0] = new float[1][1]; c.v[0][0][0][0] = 5.0F; float val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 5.0F)); c.v[0][0][0] = new float[1]; c.v[0][0][0][0] = 6.0F; float val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 6.0F)); } { c.v = new float[1][1][1][1]; float[] val1 = get1(); c.v[0][0][0] = new float[1]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1][1]; float[][] val1 = get2(); c.v[0][0] = new float[1][1]; float[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1][1]; float[][][] val1 = get3(); c.v[0] = new float[1][1][1]; float[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableFloat { c.v = new float[1][1]; c.v[0] = new float[0]; float[] val1 = get1(); c.v[0] = new float[0]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableFloat { c.v = new float[1][1][1]; c.v[0][0] = new float[0]; float[] val1 = get1(); c.v[0][0] = new float[0]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1]; c.v[0] = new float[0][0]; float[][] val1 = get2(); c.v[0] = new float[0][0]; float[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableFloat { elem.a = 2.0F; float val3 = get(); float val4 = get1(); assertEquals(val1, 1.0F); - assertEquals(val3, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val3, (isStableEnabled ? 1.0F : 2.0F)); assertEquals(val2, 1.0F); assertEquals(val4, 2.0F); diff --git a/hotspot/test/compiler/stable/TestStableInt.java b/hotspot/test/compiler/stable/TestStableInt.java index 2837bd3d1a5..4b99f95e2d5 100644 --- a/hotspot/test/compiler/stable/TestStableInt.java +++ b/hotspot/test/compiler/stable/TestStableInt.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableInt { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableInt { c.v = new int[1]; c.v[0] = 1; int val1 = get(); c.v[0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[1]; c.v[0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -220,10 +219,10 @@ public class TestStableInt { c.v = new int[20]; c.v[10] = 1; int val1 = get1(); c.v[10] = 2; int val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[20]; c.v[10] = 3; int val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -249,21 +248,21 @@ public class TestStableInt { c.v = new int[1][1]; c.v[0][0] = 1; int val1 = get(); c.v[0][0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[1][1]; c.v[0][0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new int[1]; c.v[0][0] = 4; int val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); } { c.v = new int[1][1]; int[] val1 = get1(); c.v[0] = new int[1]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableInt { c.v = new int[1][1][1]; c.v[0][0][0] = 1; int val1 = get(); c.v[0][0][0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[1][1][1]; c.v[0][0][0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new int[1][1]; c.v[0][0][0] = 4; int val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new int[1]; c.v[0][0][0] = 5; int val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); } { c.v = new int[1][1][1]; int[] val1 = get1(); c.v[0][0] = new int[1]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1]; int[][] val1 = get2(); c.v[0] = new int[1][1]; int[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableInt { c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 1; int val1 = get(); c.v[0][0][0][0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new int[1][1][1]; c.v[0][0][0][0] = 4; int val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new int[1][1]; c.v[0][0][0][0] = 5; int val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); c.v[0][0][0] = new int[1]; c.v[0][0][0][0] = 6; int val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 6)); } { c.v = new int[1][1][1][1]; int[] val1 = get1(); c.v[0][0][0] = new int[1]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1][1]; int[][] val1 = get2(); c.v[0][0] = new int[1][1]; int[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1][1]; int[][][] val1 = get3(); c.v[0] = new int[1][1][1]; int[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableInt { c.v = new int[1][1]; c.v[0] = new int[0]; int[] val1 = get1(); c.v[0] = new int[0]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableInt { c.v = new int[1][1][1]; c.v[0][0] = new int[0]; int[] val1 = get1(); c.v[0][0] = new int[0]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1]; c.v[0] = new int[0][0]; int[][] val1 = get2(); c.v[0] = new int[0][0]; int[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableInt { elem.a = 2; int val3 = get(); int val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isServerWithStable ? 1 : 2)); + assertEquals(val3, (isStableEnabled ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); diff --git a/hotspot/test/compiler/stable/TestStableLong.java b/hotspot/test/compiler/stable/TestStableLong.java index b6c2fbb0be6..00e9863cca0 100644 --- a/hotspot/test/compiler/stable/TestStableLong.java +++ b/hotspot/test/compiler/stable/TestStableLong.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableLong { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableLong { c.v = new long[1]; c.v[0] = 1; long val1 = get(); c.v[0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[1]; c.v[0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -220,10 +219,10 @@ public class TestStableLong { c.v = new long[20]; c.v[10] = 1; long val1 = get1(); c.v[10] = 2; long val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[20]; c.v[10] = 3; long val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -249,21 +248,21 @@ public class TestStableLong { c.v = new long[1][1]; c.v[0][0] = 1; long val1 = get(); c.v[0][0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[1][1]; c.v[0][0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new long[1]; c.v[0][0] = 4; long val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); } { c.v = new long[1][1]; long[] val1 = get1(); c.v[0] = new long[1]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableLong { c.v = new long[1][1][1]; c.v[0][0][0] = 1; long val1 = get(); c.v[0][0][0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[1][1][1]; c.v[0][0][0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new long[1][1]; c.v[0][0][0] = 4; long val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new long[1]; c.v[0][0][0] = 5; long val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); } { c.v = new long[1][1][1]; long[] val1 = get1(); c.v[0][0] = new long[1]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1]; long[][] val1 = get2(); c.v[0] = new long[1][1]; long[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableLong { c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 1; long val1 = get(); c.v[0][0][0][0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new long[1][1][1]; c.v[0][0][0][0] = 4; long val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new long[1][1]; c.v[0][0][0][0] = 5; long val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); c.v[0][0][0] = new long[1]; c.v[0][0][0][0] = 6; long val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 6)); } { c.v = new long[1][1][1][1]; long[] val1 = get1(); c.v[0][0][0] = new long[1]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1][1]; long[][] val1 = get2(); c.v[0][0] = new long[1][1]; long[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1][1]; long[][][] val1 = get3(); c.v[0] = new long[1][1][1]; long[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableLong { c.v = new long[1][1]; c.v[0] = new long[0]; long[] val1 = get1(); c.v[0] = new long[0]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableLong { c.v = new long[1][1][1]; c.v[0][0] = new long[0]; long[] val1 = get1(); c.v[0][0] = new long[0]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1]; c.v[0] = new long[0][0]; long[][] val1 = get2(); c.v[0] = new long[0][0]; long[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableLong { elem.a = 2; long val3 = get(); long val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isServerWithStable ? 1 : 2)); + assertEquals(val3, (isStableEnabled ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); diff --git a/hotspot/test/compiler/stable/TestStableObject.java b/hotspot/test/compiler/stable/TestStableObject.java index b61736b6e32..4602a064468 100644 --- a/hotspot/test/compiler/stable/TestStableObject.java +++ b/hotspot/test/compiler/stable/TestStableObject.java @@ -89,7 +89,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableObject { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -212,10 +211,10 @@ public class TestStableObject { c.v = new Object[1]; c.v[0] = Values.A; Object val1 = get(); c.v[0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[1]; c.v[0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); } @@ -223,10 +222,10 @@ public class TestStableObject { c.v = new Object[20]; c.v[10] = Values.A; Object val1 = get1(); c.v[10] = Values.B; Object val2 = get1(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[20]; c.v[10] = Values.C; Object val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); } @@ -252,21 +251,21 @@ public class TestStableObject { c.v = new Object[1][1]; c.v[0][0] = Values.A; Object val1 = get(); c.v[0][0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[1][1]; c.v[0][0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); c.v[0] = new Object[1]; c.v[0][0] = Values.D; Object val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.D)); } { c.v = new Object[1][1]; Object[] val1 = get1(); c.v[0] = new Object[1]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -292,31 +291,31 @@ public class TestStableObject { c.v = new Object[1][1][1]; c.v[0][0][0] = Values.A; Object val1 = get(); c.v[0][0][0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[1][1][1]; c.v[0][0][0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); c.v[0] = new Object[1][1]; c.v[0][0][0] = Values.D; Object val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.D)); c.v[0][0] = new Object[1]; c.v[0][0][0] = Values.E; Object val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.E)); } { c.v = new Object[1][1][1]; Object[] val1 = get1(); c.v[0][0] = new Object[1]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1]; Object[][] val1 = get2(); c.v[0] = new Object[1][1]; Object[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -343,41 +342,41 @@ public class TestStableObject { c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.A; Object val1 = get(); c.v[0][0][0][0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); c.v[0] = new Object[1][1][1]; c.v[0][0][0][0] = Values.D; Object val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.D)); c.v[0][0] = new Object[1][1]; c.v[0][0][0][0] = Values.E; Object val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.E)); c.v[0][0][0] = new Object[1]; c.v[0][0][0][0] = Values.F; Object val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.F)); } { c.v = new Object[1][1][1][1]; Object[] val1 = get1(); c.v[0][0][0] = new Object[1]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1][1]; Object[][] val1 = get2(); c.v[0][0] = new Object[1][1]; Object[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1][1]; Object[][][] val1 = get3(); c.v[0] = new Object[1][1][1]; Object[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -437,7 +436,7 @@ public class TestStableObject { c.v = new Object[1][1]; c.v[0] = new Object[0]; Object[] val1 = get1(); c.v[0] = new Object[0]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -473,14 +472,14 @@ public class TestStableObject { c.v = new Object[1][1][1]; c.v[0][0] = new Object[0]; Object[] val1 = get1(); c.v[0][0] = new Object[0]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1]; c.v[0] = new Object[0][0]; Object[][] val1 = get2(); c.v[0] = new Object[0][0]; Object[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -615,7 +614,7 @@ public class TestStableObject { elem.a = Values.B; Object val3 = get(); Object val4 = get1(); assertEquals(val1, Values.A); - assertEquals(val3, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val3, (isStableEnabled ? Values.A : Values.B)); assertEquals(val2, Values.A); assertEquals(val4, Values.B); diff --git a/hotspot/test/compiler/stable/TestStableShort.java b/hotspot/test/compiler/stable/TestStableShort.java index 1b0f127785c..9e9b50d05d6 100644 --- a/hotspot/test/compiler/stable/TestStableShort.java +++ b/hotspot/test/compiler/stable/TestStableShort.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableShort { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableShort { c.v = new short[1]; c.v[0] = 1; short val1 = get(); c.v[0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[1]; c.v[0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -220,10 +219,10 @@ public class TestStableShort { c.v = new short[20]; c.v[10] = 1; short val1 = get1(); c.v[10] = 2; short val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[20]; c.v[10] = 3; short val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -249,21 +248,21 @@ public class TestStableShort { c.v = new short[1][1]; c.v[0][0] = 1; short val1 = get(); c.v[0][0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[1][1]; c.v[0][0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new short[1]; c.v[0][0] = 4; short val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); } { c.v = new short[1][1]; short[] val1 = get1(); c.v[0] = new short[1]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableShort { c.v = new short[1][1][1]; c.v[0][0][0] = 1; short val1 = get(); c.v[0][0][0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[1][1][1]; c.v[0][0][0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new short[1][1]; c.v[0][0][0] = 4; short val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new short[1]; c.v[0][0][0] = 5; short val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); } { c.v = new short[1][1][1]; short[] val1 = get1(); c.v[0][0] = new short[1]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1]; short[][] val1 = get2(); c.v[0] = new short[1][1]; short[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableShort { c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 1; short val1 = get(); c.v[0][0][0][0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new short[1][1][1]; c.v[0][0][0][0] = 4; short val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new short[1][1]; c.v[0][0][0][0] = 5; short val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); c.v[0][0][0] = new short[1]; c.v[0][0][0][0] = 6; short val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 6)); } { c.v = new short[1][1][1][1]; short[] val1 = get1(); c.v[0][0][0] = new short[1]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1][1]; short[][] val1 = get2(); c.v[0][0] = new short[1][1]; short[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1][1]; short[][][] val1 = get3(); c.v[0] = new short[1][1][1]; short[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableShort { c.v = new short[1][1]; c.v[0] = new short[0]; short[] val1 = get1(); c.v[0] = new short[0]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableShort { c.v = new short[1][1][1]; c.v[0][0] = new short[0]; short[] val1 = get1(); c.v[0][0] = new short[0]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1]; c.v[0] = new short[0][0]; short[][] val1 = get2(); c.v[0] = new short[0][0]; short[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableShort { elem.a = 2; short val3 = get(); short val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isServerWithStable ? 1 : 2)); + assertEquals(val3, (isStableEnabled ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); From f2880e341ac9f64e33cee16ba25887dfe41d62cd Mon Sep 17 00:00:00 2001 From: Konstantin Shefov Date: Tue, 15 Mar 2016 13:00:43 +0300 Subject: [PATCH 304/311] 8150850: [JVMCI] NPE when executing HotSpotConstantReflectionProvider.readStableFieldValue Reviewed-by: twisti, dnsimon --- .../jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java index 600ecc84ecc..c957b05e1d5 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java @@ -339,7 +339,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv public JavaConstant readStableFieldValue(ResolvedJavaField field, JavaConstant receiver, boolean isDefaultStable) { JavaConstant fieldValue = readNonStableFieldValue(field, receiver); - if (fieldValue.isNonNull()) { + if (fieldValue != null && fieldValue.isNonNull()) { JavaType declaredType = field.getType(); if (declaredType.getComponentType() != null) { int stableDimension = getArrayDimension(declaredType); From d2078b7e23ed30446d8212703f3588cd919e7393 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Tue, 15 Mar 2016 11:17:06 +0100 Subject: [PATCH 305/311] 8151795: compiler/compilercontrol/parser/DirectiveParserTest.java fails with "assert failed: 0 != 0" Treat zero added directives as fail Reviewed-by: twisti, kvn --- hotspot/src/share/vm/compiler/directivesParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/compiler/directivesParser.cpp b/hotspot/src/share/vm/compiler/directivesParser.cpp index 05f44bfe909..9c6d6a0201f 100644 --- a/hotspot/src/share/vm/compiler/directivesParser.cpp +++ b/hotspot/src/share/vm/compiler/directivesParser.cpp @@ -97,7 +97,7 @@ bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* buffer[num_read] = '\0'; // close file os::close(file_handle); - return parse_string(buffer, stream) != -1; + return parse_string(buffer, stream) > 0; } } return false; From a20ceb80f41eb97c12da90dd31a3d65103b268c6 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Tue, 15 Mar 2016 11:17:22 +0100 Subject: [PATCH 306/311] 8151796: compiler/whitebox/BlockingCompilation.java fails due to method not compiled Make test more robust Reviewed-by: simonis --- .../whitebox/BlockingCompilation.java | 137 ++++++++++-------- 1 file changed, 78 insertions(+), 59 deletions(-) diff --git a/hotspot/test/compiler/whitebox/BlockingCompilation.java b/hotspot/test/compiler/whitebox/BlockingCompilation.java index 793f733ee9c..d960ff4264a 100644 --- a/hotspot/test/compiler/whitebox/BlockingCompilation.java +++ b/hotspot/test/compiler/whitebox/BlockingCompilation.java @@ -31,13 +31,12 @@ * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * - * @run main/othervm + * @run main/othervm/timeout=60 * -Xbootclasspath/a:. * -Xmixed * -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * -XX:+PrintCompilation - * -XX:CompileCommand=option,BlockingCompilation::foo,PrintInlining * BlockingCompilation */ @@ -56,82 +55,102 @@ public class BlockingCompilation { } public static void main(String[] args) throws Exception { - long sum = 0; - int level = 0; - boolean enqued = false; Method m = BlockingCompilation.class.getMethod("foo"); int[] levels = CompilerUtils.getAvailableCompilationLevels(); + int highest_level = levels[levels.length-1]; // If there are no compilers available these tests don't make any sense. if (levels.length == 0) return; - int max_level = levels[levels.length - 1]; - // Normal, non-blocking compilation - for (int i = 0; i < 500_000; i++) { - sum += foo(); - if (!enqued && WB.isMethodQueuedForCompilation(m)) { - System.out.println("==> " + m + " enqued for compilation in iteration " + i); - enqued = true; - } - if (WB.isMethodCompiled(m)) { - if (WB.getMethodCompilationLevel(m) != level) { - level = WB.getMethodCompilationLevel(m); - System.out.println("==> " + m + " compiled at level " + level + " in iteration " + i); - enqued = false; - if (level == max_level) break; - } - } + // Make sure no compilations can progress, blocking compiles will hang + WB.lockCompilation(); + + // Verify method state before test + if (WB.isMethodCompiled(m)) { + throw new Exception("Should not be compiled after deoptimization"); + } + if (WB.isMethodQueuedForCompilation(m)) { + throw new Exception("Should not be enqueued on any level"); } - // This is necessarry because WB.deoptimizeMethod doesn't clear the methods - // MDO and therefore level 3 compilations will be downgraded to level 2. + // Try compiling on highest available comp level. + // If the compiles are blocking, this call will block until the test time out, + // Progress == success + // (Don't run with -Xcomp since that can cause long timeouts due to many compiles) + WB.enqueueMethodForCompilation(m, highest_level); + + // restore state + WB.unlockCompilation(); + while (!WB.isMethodCompiled(m)) { + Thread.sleep(100); + } + WB.deoptimizeMethod(m); WB.clearMethodState(m); // Blocking compilations on all levels, using the default versions of // WB.enqueueMethodForCompilation() and manually setting compiler directives. String directive = "[{ match: \"BlockingCompilation.foo\", BackgroundCompilation: false }]"; - WB.addCompilerDirective(directive); - - for (int l : levels) { - WB.deoptimizeMethod(m); - WB.enqueueMethodForCompilation(m, l); - - if (!WB.isMethodCompiled(m) || WB.getMethodCompilationLevel(m) != l) { - String msg = m + " should be compiled at level " + l + - "(but is actually compiled at level " + - WB.getMethodCompilationLevel(m) + ")"; - System.out.println("==> " + msg); - throw new Exception(msg); - } + if (WB.addCompilerDirective(directive) != 1) { + throw new Exception("Failed to add compiler directive"); } - WB.removeCompilerDirective(1); + try { + for (int l : levels) { + // Make uncompiled + WB.deoptimizeMethod(m); - WB.deoptimizeMethod(m); - WB.clearMethodState(m); - level = 0; - enqued = false; - int iteration = 0; + // Verify that it's not compiled + if (WB.isMethodCompiled(m)) { + throw new Exception("Should not be compiled after deoptimization"); + } + if (WB.isMethodQueuedForCompilation(m)) { + throw new Exception("Should not be enqueued on any level"); + } - // Normal, non-blocking compilation - for (int i = 0; i < 500_000; i++) { - sum += foo(); - if (!enqued && WB.isMethodQueuedForCompilation(m)) { - System.out.println("==> " + m + " enqued for compilation in iteration " + i); - iteration = i; - enqued = true; - } - if (WB.isMethodCompiled(m)) { - if (WB.getMethodCompilationLevel(m) != level) { - level = WB.getMethodCompilationLevel(m); - System.out.println("==> " + m + " compiled at level " + level + " in iteration " + i); - if (level == 4 && iteration == i) { - throw new Exception("This seems to be a blocking compilation although it shouldn't."); - } - enqued = false; - if (level == max_level) break; + // Add to queue and verify that it went well + if (!WB.enqueueMethodForCompilation(m, l)) { + throw new Exception("Could not be enqueued for compilation"); + } + + // Verify that it is compiled + if (!WB.isMethodCompiled(m)) { + throw new Exception("Must be compiled here"); + } + // And verify the level + if (WB.getMethodCompilationLevel(m) != l) { + String msg = m + " should be compiled at level " + l + + "(but is actually compiled at level " + + WB.getMethodCompilationLevel(m) + ")"; + System.out.println("==> " + msg); + throw new Exception(msg); } } + } finally { + WB.removeCompilerDirective(1); } + + // Clean up + WB.deoptimizeMethod(m); + WB.clearMethodState(m); + + // Make sure no compilations can progress, blocking compiles will hang + WB.lockCompilation(); + + // Verify method state before test + if (WB.isMethodCompiled(m)) { + throw new Exception("Should not be compiled after deoptimization"); + } + if (WB.isMethodQueuedForCompilation(m)) { + throw new Exception("Should not be enqueued on any level"); + } + + // Try compiling on highest available comp level. + // If the compiles are blocking, this call will block until the test time out, + // Progress == success + // (Don't run with -Xcomp since that can cause long timeouts due to many compiles) + WB.enqueueMethodForCompilation(m, highest_level); + + // restore state + WB.unlockCompilation(); } } From 616744c4c91b44ea201ad7f79778324b7ea66598 Mon Sep 17 00:00:00 2001 From: Pavel Punegov Date: Tue, 15 Mar 2016 16:23:31 +0300 Subject: [PATCH 307/311] 8150955: RandomValidCommandsTest.java fails with UnsatisfiedLinkError: sun.hotspot.WhiteBox.registerNatives Replace invalid command with a valid one Reviewed-by: kvn --- hotspot/test/compiler/compilercontrol/share/MultiCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/test/compiler/compilercontrol/share/MultiCommand.java b/hotspot/test/compiler/compilercontrol/share/MultiCommand.java index 4eac177223b..8072e5b712b 100644 --- a/hotspot/test/compiler/compilercontrol/share/MultiCommand.java +++ b/hotspot/test/compiler/compilercontrol/share/MultiCommand.java @@ -53,8 +53,8 @@ public class MultiCommand extends AbstractTestBase { List testCases = new ArrayList<>(); for (Command cmd : commands) { if (validOnly && cmd == Command.NONEXISTENT) { - // skip invalid command - continue; + // replace with a valid command + cmd = Command.EXCLUDE; } Executable exec = Utils.getRandomElement(METHODS).first; MethodDescriptor md; From 23a62fdfcae789a209997ca47a9a6262ed1ab837 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Tue, 15 Mar 2016 17:42:28 +0100 Subject: [PATCH 308/311] 8150804: C2 Compilation fails with assert(_base >= OopPtr && _base <= AryPtr) failed: Not a Java pointer Wait with removing casts from inputs in PhiNode::ideal() until after parsing for the type information to propagate. Reviewed-by: kvn --- hotspot/src/share/vm/opto/callnode.cpp | 4 +- hotspot/src/share/vm/opto/cfgnode.cpp | 7 +- .../compiler/types/TestPhiElimination.java | 112 ++++++++++++++++++ 3 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 hotspot/test/compiler/types/TestPhiElimination.java diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index ffe97dc68ab..6a43b33cde4 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -1243,13 +1243,13 @@ void SafePointNode::pop_monitor() { Node *SafePointNode::peek_monitor_box() const { int mon = jvms()->nof_monitors() - 1; - assert(mon >= 0, "most have a monitor"); + assert(mon >= 0, "must have a monitor"); return monitor_box(jvms(), mon); } Node *SafePointNode::peek_monitor_obj() const { int mon = jvms()->nof_monitors() - 1; - assert(mon >= 0, "most have a monitor"); + assert(mon >= 0, "must have a monitor"); return monitor_obj(jvms(), mon); } diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp index 12aa7c7d6b4..c0bad767d0c 100644 --- a/hotspot/src/share/vm/opto/cfgnode.cpp +++ b/hotspot/src/share/vm/opto/cfgnode.cpp @@ -1665,7 +1665,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { bool uncasted = false; Node* uin = unique_input(phase, false); - if (uin == NULL) { + if (uin == NULL && can_reshape) { uncasted = true; uin = unique_input(phase, true); } @@ -1702,6 +1702,8 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { } if (uncasted) { + // Wait until after parsing for the type information to propagate from the casts + assert(can_reshape, "Invalid during parsing"); const Type* phi_type = bottom_type(); assert(phi_type->isa_int() || phi_type->isa_ptr(), "bad phi type"); int opcode; @@ -1720,8 +1722,9 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* cast = ConstraintCastNode::make_cast(opcode, r, uin, phi_type, true); cast = phase->transform(cast); // set all inputs to the new cast so the Phi is removed by Identity + PhaseIterGVN* igvn = phase->is_IterGVN(); for (uint i = 1; i < req(); i++) { - set_req(i, cast); + set_req_X(i, cast, igvn); } uin = cast; } diff --git a/hotspot/test/compiler/types/TestPhiElimination.java b/hotspot/test/compiler/types/TestPhiElimination.java new file mode 100644 index 00000000000..5029b99ee77 --- /dev/null +++ b/hotspot/test/compiler/types/TestPhiElimination.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016, 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 8150804 + * @summary Tests elimination of Phi nodes without losing type information. + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestPhiElimination + */ +public class TestPhiElimination { + /* + A::get() is inlined into test(obj) producing the following graph: + + Parm (obj) + TestPhiElimination + | + CastPP + TestPhiElimination:NotNull + | + CheckCastPP + A:NotNull + / \ + CheckCastPP | + A:NotNull | + \ / + Phi + A + | + Safepoint + + PhiNode::ideal() then replaces the Phi by a CheckCastPP: + + Parm (obj) + TestPhiElimination + | + CheckCastPP + A + | + Safepoint + + losing the :NotNull information. Therefore, we cannot prove that obj != null + when accessing a field and add an uncommon trap. Since obj is used as monitor, we + set it to TOP in the uncommon trap branch and later fail in Process_OopMap_Node + because the monitor object is TOP. + */ + public Object test(TestPhiElimination obj) { + if (obj instanceof A) { + return ((A) obj).get(); + } + return null; + } + + static public void main(String[] args) { + TestPhiElimination t = new TestPhiElimination(); + + // Warmup + B b = new B(); + for (int i = 0; i < 1_000; ++i) { + t.test(b); + } + + // Compile + A a = new A(); + for (int i = 0; i < 20_000; ++i) { + if (i % 2 == 0) { + a.f = null; + } + t.test(a); + } + } + +} + +class A extends TestPhiElimination { + public Object f; + + public A create() { + return new A(); + } + + public synchronized Object get() { + if (f == null) { + f = create(); + } + return f; + } +} + +class B extends A { + +} From 3e246411ae02e8c0a32457087d088ddf0de17d2d Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 15 Mar 2016 14:19:24 -0700 Subject: [PATCH 309/311] 8151871: [JVMCI] missing HAS_PENDING_EXCEPTION check Reviewed-by: kvn --- hotspot/src/share/vm/jvmci/jvmciCompiler.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp index 429ccabbe6c..e84d4b319c5 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp @@ -162,6 +162,9 @@ void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JV CLEAR_PENDING_EXCEPTION; java_lang_Throwable::java_printStackTrace(exception, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } env->set_failure("exception throw", false); } else { From a7d116c1f3b2e89510d6ae71033f72add2033b79 Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Wed, 16 Mar 2016 10:45:43 +0100 Subject: [PATCH 310/311] 8150054: Make compilercontrol test ignore xcomp Add -Xmixed and use jtreg driver Reviewed-by: kvn --- .../compiler/compilercontrol/commandfile/CompileOnlyTest.java | 4 ++-- .../compiler/compilercontrol/commandfile/ExcludeTest.java | 4 ++-- .../test/compiler/compilercontrol/commandfile/LogTest.java | 4 ++-- .../test/compiler/compilercontrol/commandfile/PrintTest.java | 4 ++-- .../compiler/compilercontrol/commands/CompileOnlyTest.java | 4 ++-- .../test/compiler/compilercontrol/commands/ExcludeTest.java | 4 ++-- hotspot/test/compiler/compilercontrol/commands/LogTest.java | 4 ++-- hotspot/test/compiler/compilercontrol/commands/PrintTest.java | 4 ++-- .../compiler/compilercontrol/directives/CompileOnlyTest.java | 4 ++-- .../test/compiler/compilercontrol/directives/ExcludeTest.java | 4 ++-- hotspot/test/compiler/compilercontrol/directives/LogTest.java | 4 ++-- .../test/compiler/compilercontrol/directives/PrintTest.java | 4 ++-- .../test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java | 4 ++-- .../compiler/compilercontrol/jcmd/AddCompileOnlyTest.java | 4 ++-- .../test/compiler/compilercontrol/jcmd/AddExcludeTest.java | 4 ++-- hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java | 4 ++-- .../compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java | 4 ++-- .../compilercontrol/jcmd/ClearDirectivesFileStackTest.java | 4 ++-- .../compilercontrol/jcmd/ClearDirectivesStackTest.java | 4 ++-- .../compiler/compilercontrol/jcmd/PrintDirectivesTest.java | 4 ++-- .../compilercontrol/jcmd/StressAddMultiThreadedTest.java | 2 +- .../compiler/compilercontrol/matcher/MethodMatcherTest.java | 2 +- .../compiler/compilercontrol/mixed/RandomCommandsTest.java | 4 ++-- .../compilercontrol/mixed/RandomValidCommandsTest.java | 2 +- hotspot/test/compiler/compilercontrol/share/MultiCommand.java | 1 + .../compiler/compilercontrol/share/scenario/Scenario.java | 1 + 26 files changed, 47 insertions(+), 45 deletions(-) diff --git a/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java b/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java index e128f500901..2541d9d0b83 100644 --- a/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java +++ b/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commandfile.CompileOnlyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commandfile.CompileOnlyTest + * @run driver compiler.compilercontrol.commandfile.CompileOnlyTest */ package compiler.compilercontrol.commandfile; diff --git a/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java b/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java index 2b40af6182e..77c2a2e0748 100644 --- a/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java +++ b/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commandfile.ExcludeTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commandfile.ExcludeTest + * @run driver compiler.compilercontrol.commandfile.ExcludeTest */ package compiler.compilercontrol.commandfile; diff --git a/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java b/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java index a35474235e8..ce45d52b11c 100644 --- a/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java +++ b/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commandfile.LogTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commandfile.LogTest + * @run driver compiler.compilercontrol.commandfile.LogTest */ package compiler.compilercontrol.commandfile; diff --git a/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java b/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java index ede2eb65776..5e90521eabf 100644 --- a/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java +++ b/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.commandfile.PrintTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commandfile.PrintTest + * @run driver compiler.compilercontrol.commandfile.PrintTest */ package compiler.compilercontrol.commandfile; diff --git a/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java b/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java index f08fb34e318..7a1b0c1da40 100644 --- a/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java +++ b/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commands.CompileOnlyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commands.CompileOnlyTest + * @run driver compiler.compilercontrol.commands.CompileOnlyTest */ package compiler.compilercontrol.commands; diff --git a/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java b/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java index 0af19c1a35e..b84befca8c2 100644 --- a/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java +++ b/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commands.ExcludeTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commands.ExcludeTest + * @run driver compiler.compilercontrol.commands.ExcludeTest */ package compiler.compilercontrol.commands; diff --git a/hotspot/test/compiler/compilercontrol/commands/LogTest.java b/hotspot/test/compiler/compilercontrol/commands/LogTest.java index 07a437853cc..4ffebe41a32 100644 --- a/hotspot/test/compiler/compilercontrol/commands/LogTest.java +++ b/hotspot/test/compiler/compilercontrol/commands/LogTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commands.LogTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commands.LogTest + * @run driver compiler.compilercontrol.commands.LogTest */ package compiler.compilercontrol.commands; diff --git a/hotspot/test/compiler/compilercontrol/commands/PrintTest.java b/hotspot/test/compiler/compilercontrol/commands/PrintTest.java index eddeadbfbe7..d9ac685ca8f 100644 --- a/hotspot/test/compiler/compilercontrol/commands/PrintTest.java +++ b/hotspot/test/compiler/compilercontrol/commands/PrintTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.commands.PrintTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commands.PrintTest + * @run driver compiler.compilercontrol.commands.PrintTest */ package compiler.compilercontrol.commands; diff --git a/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java b/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java index bdc3a39f32f..439e5e9505d 100644 --- a/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java +++ b/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.directives.CompileOnlyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.directives.CompileOnlyTest + * @run driver compiler.compilercontrol.directives.CompileOnlyTest */ package compiler.compilercontrol.directives; diff --git a/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java b/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java index 44b33dd43c1..0569cdfe323 100644 --- a/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java +++ b/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.directives.ExcludeTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.directives.ExcludeTest + * @run driver compiler.compilercontrol.directives.ExcludeTest */ package compiler.compilercontrol.directives; diff --git a/hotspot/test/compiler/compilercontrol/directives/LogTest.java b/hotspot/test/compiler/compilercontrol/directives/LogTest.java index 634aee5cb01..1f84d4aea5e 100644 --- a/hotspot/test/compiler/compilercontrol/directives/LogTest.java +++ b/hotspot/test/compiler/compilercontrol/directives/LogTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.directives.LogTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.directives.LogTest + * @run driver compiler.compilercontrol.directives.LogTest */ package compiler.compilercontrol.directives; diff --git a/hotspot/test/compiler/compilercontrol/directives/PrintTest.java b/hotspot/test/compiler/compilercontrol/directives/PrintTest.java index 78ac4de4cee..bbd92c1704b 100644 --- a/hotspot/test/compiler/compilercontrol/directives/PrintTest.java +++ b/hotspot/test/compiler/compilercontrol/directives/PrintTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.directives.PrintTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.directives.PrintTest + * @run driver compiler.compilercontrol.directives.PrintTest */ package compiler.compilercontrol.directives; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java index 21d7af2efb7..372b50a72b6 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.AddAndRemoveTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddAndRemoveTest + * @run driver compiler.compilercontrol.jcmd.AddAndRemoveTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java index 5f17ad0cc27..5b2a9e26843 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.AddCompileOnlyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddCompileOnlyTest + * @run driver compiler.compilercontrol.jcmd.AddCompileOnlyTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java index c72b6c06e4e..a06c32616d8 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.AddExcludeTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddExcludeTest + * @run driver compiler.compilercontrol.jcmd.AddExcludeTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java index 900c57978ab..266cf3c5dda 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.AddLogTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddLogTest + * @run driver compiler.compilercontrol.jcmd.AddLogTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java index 8f9c0250138..9697711c294 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.jcmd.AddPrintAssemblyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddPrintAssemblyTest + * @run driver compiler.compilercontrol.jcmd.AddPrintAssemblyTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java index 25966f9f726..da1fef49141 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.jcmd.ClearDirectivesFileStackTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.ClearDirectivesFileStackTest + * @run driver compiler.compilercontrol.jcmd.ClearDirectivesFileStackTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java index f9f382da110..c9d9f8dcfd0 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.ClearDirectivesStackTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.ClearDirectivesStackTest + * @run driver compiler.compilercontrol.jcmd.ClearDirectivesStackTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java b/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java index 5821de76d75..7afd4d6f8b3 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.jcmd.PrintDirectivesTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.PrintDirectivesTest + * @run driver compiler.compilercontrol.jcmd.PrintDirectivesTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java index 5bf1464fd55..26c225380ac 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java @@ -31,7 +31,7 @@ * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils * compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run driver compiler.compilercontrol.jcmd.StressAddMultiThreadedTest */ diff --git a/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java b/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java index 00ca74d108d..87cd26a8958 100644 --- a/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java +++ b/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java @@ -42,7 +42,7 @@ import java.util.regex.Pattern; * @summary Tests CompilerCommand's method matcher * @library /testlibrary /test/lib /compiler/whitebox ../share / * @build compiler.compilercontrol.matcher.MethodMatcherTest - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI compiler.compilercontrol.matcher.MethodMatcherTest diff --git a/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java b/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java index 13df53afdfe..c954dba9011 100644 --- a/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java +++ b/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.mixed.RandomCommandsTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=600 compiler.compilercontrol.mixed.RandomCommandsTest + * @run driver/timeout=600 compiler.compilercontrol.mixed.RandomCommandsTest */ package compiler.compilercontrol.mixed; diff --git a/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java b/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java index 7b837e672c5..e8739e8abde 100644 --- a/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java +++ b/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java @@ -30,7 +30,7 @@ * @build compiler.compilercontrol.mixed.RandomValidCommandsTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=600 compiler.compilercontrol.mixed.RandomValidCommandsTest */ diff --git a/hotspot/test/compiler/compilercontrol/share/MultiCommand.java b/hotspot/test/compiler/compilercontrol/share/MultiCommand.java index 8072e5b712b..f85591da663 100644 --- a/hotspot/test/compiler/compilercontrol/share/MultiCommand.java +++ b/hotspot/test/compiler/compilercontrol/share/MultiCommand.java @@ -72,6 +72,7 @@ public class MultiCommand extends AbstractTestBase { @Override public void test() { Scenario.Builder builder = Scenario.getBuilder(); + builder.addFlag("-Xmixed"); for (CompileCommand cc : testCases) { cc.print(); builder.add(cc); diff --git a/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java b/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java index 49109151d82..a2408da7fbb 100644 --- a/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java +++ b/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java @@ -200,6 +200,7 @@ public final class Scenario { private final List jcmdCommands = new ArrayList<>(); public Builder() { + addFlag("-Xmixed"); builders.put(Type.FILE, new CommandFileBuilder(Type.FILE.fileName)); builders.put(Type.OPTION, new CommandOptionsBuilder()); builders.put(Type.DIRECTIVE, new DirectiveBuilder( From 42ba4188b0e5e230c2c7f59588bee2733d0c5bd7 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Thu, 17 Mar 2016 09:41:46 +0100 Subject: [PATCH 311/311] 8151882: -XX:+Verbose prints messages even if no other flag is set We should only print messages if PrintOpto && WizardMode is set. Reviewed-by: kvn, neliasso --- hotspot/src/share/vm/opto/reg_split.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/reg_split.cpp b/hotspot/src/share/vm/opto/reg_split.cpp index 5e14b9d5abc..781a53cc00b 100644 --- a/hotspot/src/share/vm/opto/reg_split.cpp +++ b/hotspot/src/share/vm/opto/reg_split.cpp @@ -287,7 +287,7 @@ uint PhaseChaitin::split_USE(MachSpillCopyNode::SpillType spill_type, Node *def, Node* clone_node(Node* def, Block *b, Compile* C) { if (def->needs_anti_dependence_check()) { #ifdef ASSERT - if (Verbose) { + if (PrintOpto && WizardMode) { tty->print_cr("RA attempts to clone node with anti_dependence:"); def->dump(-1); tty->cr(); tty->print_cr("into block:");